ashs.py 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. """
  2. Read hippocampal subfield volumes computed by ASHS
  3. https://sites.google.com/site/hipposubfields/home
  4. >>> from freesurfer_volume_reader.ashs import HippocampalSubfieldsVolumeFile
  5. >>>
  6. >>> for volume_file in HippocampalSubfieldsVolumeFile('/my/ashs/subjects'):
  7. >>> print(volume_file.subject, volume_file.hemisphere, volume_file.correction)
  8. >>> print(volume_file.read_volumes_mm3())
  9. >>> print(volume_file.read_volumes_dataframe())
  10. >>> from freesurfer_volume_reader.ashs import IntracranialVolumeFile
  11. >>>
  12. >>> for volume_file in IntracranialVolumeFile('/my/ashs/subjects'):
  13. >>> print(volume_file.subject)
  14. >>> print(volume_file.read_volume_mm3())
  15. >>> print(volume_file.read_volume_series())
  16. """
  17. import re
  18. import typing
  19. import pandas
  20. import freesurfer_volume_reader
  21. class IntracranialVolumeFile(freesurfer_volume_reader.VolumeFile):
  22. FILENAME_REGEX = re.compile(r"^(?P<s>\w+)_icv.txt$")
  23. def __init__(self, path: str):
  24. super().__init__(path=path)
  25. filename_match = self.FILENAME_REGEX.match(self._absolute_path.name)
  26. assert filename_match, self._absolute_path
  27. self.subject = filename_match.groupdict()["s"]
  28. def read_volume_mm3(self) -> float:
  29. subject, icv = (
  30. self._absolute_path.read_text(encoding="ascii").rstrip().split(" ")
  31. )
  32. assert subject == self.subject, (subject, self.subject)
  33. return float(icv)
  34. def read_volume_series(self) -> pandas.Series:
  35. return pandas.Series(
  36. data=[self.read_volume_mm3()],
  37. name="intercranial_volume_mm^3",
  38. index=pandas.Index(data=[self.subject], name="subject"),
  39. )
  40. class HippocampalSubfieldsVolumeFile(freesurfer_volume_reader.SubfieldVolumeFile):
  41. # https://sites.google.com/site/hipposubfields/tutorial#TOC-Viewing-ASHS-Segmentation-Results
  42. FILENAME_PATTERN = (
  43. r"^(?P<s>\w+)_(?P<h>left|right)"
  44. r"_(heur|corr_(?P<c>nogray|usegray))_volumes.txt$"
  45. )
  46. FILENAME_REGEX = re.compile(FILENAME_PATTERN)
  47. def __init__(self, path: str):
  48. super().__init__(path=path)
  49. filename_match = self.FILENAME_REGEX.match(self._absolute_path.name)
  50. assert filename_match, self._absolute_path
  51. filename_groups = filename_match.groupdict()
  52. self.subject = filename_groups["s"]
  53. self.hemisphere = filename_groups["h"]
  54. self.correction = filename_groups["c"]
  55. def read_volumes_mm3(self) -> typing.Dict[str, float]:
  56. subfield_volumes = {}
  57. for line in (
  58. self._absolute_path.read_text(encoding="ascii").rstrip().split("\n")
  59. ):
  60. # > echo $ASHS_SUBJID $side $SUB $NBODY $VSUB >> $FNBODYVOL
  61. # https://github.com/pyushkevich/ashs/blob/515ff7c2f50928adabc4e64bded9a7e76fc750b1/bin/ashs_extractstats_qsub.sh#L94
  62. (
  63. subject,
  64. hemisphere,
  65. subfield_name,
  66. slices_number_str,
  67. volume_mm3_str,
  68. ) = line.split(" ")
  69. assert self.subject == subject
  70. assert self.hemisphere == hemisphere
  71. assert int(slices_number_str) >= 0
  72. subfield_volumes[subfield_name] = float(volume_mm3_str)
  73. return subfield_volumes
  74. def read_volumes_dataframe(self) -> pandas.DataFrame:
  75. volumes_frame = self._read_volume_series().reset_index()
  76. # pylint: disable=duplicate-code; software-specific
  77. volumes_frame["subject"] = self.subject
  78. volumes_frame["hemisphere"] = self.hemisphere
  79. volumes_frame["correction"] = self.correction
  80. return volumes_frame