ashs.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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 os
  18. import re
  19. import typing
  20. import pandas
  21. import freesurfer_volume_reader
  22. class IntracranialVolumeFile(freesurfer_volume_reader.VolumeFile):
  23. FILENAME_REGEX = re.compile(r'^(?P<s>\w+)_icv.txt$')
  24. def __init__(self, path: str):
  25. self._absolute_path = os.path.abspath(path)
  26. filename_match = self.FILENAME_REGEX.match(os.path.basename(path))
  27. assert filename_match, self._absolute_path
  28. self.subject = filename_match.groupdict()['s']
  29. @property
  30. def absolute_path(self):
  31. return self._absolute_path
  32. def read_volume_mm3(self) -> float:
  33. with open(self.absolute_path, 'r') as volume_file:
  34. subject, icv = volume_file.read().rstrip().split(' ')
  35. assert subject == self.subject, (subject, self.subject)
  36. return float(icv)
  37. def read_volume_series(self) -> pandas.Series:
  38. return pandas.Series(
  39. data=[self.read_volume_mm3()],
  40. name='intercranial_volume_mm^3',
  41. index=pandas.Index(
  42. data=[self.subject],
  43. name='subject',
  44. ),
  45. )
  46. class HippocampalSubfieldsVolumeFile(freesurfer_volume_reader.SubfieldVolumeFile):
  47. # https://sites.google.com/site/hipposubfields/tutorial#TOC-Viewing-ASHS-Segmentation-Results
  48. FILENAME_PATTERN = r'^(?P<s>\w+)_(?P<h>left|right)' \
  49. r'_(heur|corr_(?P<c>nogray|usegray))_volumes.txt$'
  50. FILENAME_REGEX = re.compile(FILENAME_PATTERN)
  51. def __init__(self, path: str):
  52. self._absolute_path = os.path.abspath(path)
  53. filename_match = self.FILENAME_REGEX.match(os.path.basename(path))
  54. assert filename_match, self._absolute_path
  55. filename_groups = filename_match.groupdict()
  56. self.subject = filename_groups['s']
  57. self.hemisphere = filename_groups['h']
  58. self.correction = filename_groups['c']
  59. @property
  60. def absolute_path(self):
  61. return self._absolute_path
  62. def read_volumes_mm3(self) -> typing.Dict[str, float]:
  63. subfield_volumes = {}
  64. with open(self.absolute_path, 'r') as volume_file:
  65. for line in volume_file.read().rstrip().split('\n'):
  66. # > echo $ASHS_SUBJID $side $SUB $NBODY $VSUB >> $FNBODYVOL
  67. # https://github.com/pyushkevich/ashs/blob/515ff7c2f50928adabc4e64bded9a7e76fc750b1/bin/ashs_extractstats_qsub.sh#L94
  68. subject, hemisphere, subfield_name, slices_number_str, volume_mm3_str \
  69. = line.split(' ')
  70. assert self.subject == subject
  71. assert self.hemisphere == hemisphere
  72. assert int(slices_number_str) >= 0
  73. subfield_volumes[subfield_name] = float(volume_mm3_str)
  74. return subfield_volumes
  75. def read_volumes_dataframe(self) -> pandas.DataFrame:
  76. volumes_frame = self._read_volume_series().reset_index()
  77. volumes_frame['subject'] = self.subject
  78. volumes_frame['hemisphere'] = self.hemisphere
  79. volumes_frame['correction'] = self.correction
  80. return volumes_frame