ashs.py 3.2 KB

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