freesurfer.py 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. """
  2. Read hippocampal subfield volumes computed by Freesurfer
  3. https://surfer.nmr.mgh.harvard.edu/fswiki/HippocampalSubfields
  4. https://github.com/freesurfer/freesurfer/tree/release_6_0_0/HippoSF
  5. >>> from freesurfer_volume_reader.freesurfer import HippocampalSubfieldsVolumeFile
  6. >>>
  7. >>> for volume_file in HippocampalSubfieldsVolumeFile.find('/my/freesurfer/subjects'):
  8. >>> print(volume_file.read_volumes_mm3())
  9. >>> print(volume_file.read_volumes_dataframe())
  10. """
  11. import pathlib
  12. import re
  13. import typing
  14. import pandas
  15. import freesurfer_volume_reader
  16. class HippocampalSubfieldsVolumeFile(freesurfer_volume_reader.SubfieldVolumeFile):
  17. # https://surfer.nmr.mgh.harvard.edu/fswiki/HippocampalSubfields
  18. FILENAME_PATTERN = (
  19. r"^(?P<h>[lr])h\.hippoSfVolumes"
  20. r"(?P<T1>-T1)?(-(?P<analysis_id>.+?))?\.v10.txt$"
  21. )
  22. FILENAME_REGEX = re.compile(FILENAME_PATTERN)
  23. FILENAME_HEMISPHERE_PREFIX_MAP = {"l": "left", "r": "right"}
  24. def __init__(self, path: str):
  25. self._absolute_path = pathlib.Path(path).absolute()
  26. subject_dir_path = self._absolute_path.parent.parent
  27. self.subject = subject_dir_path.name
  28. filename_match = self.FILENAME_REGEX.match(self._absolute_path.name)
  29. assert filename_match, self._absolute_path
  30. filename_groups = filename_match.groupdict()
  31. assert (
  32. filename_groups["T1"] or filename_groups["analysis_id"]
  33. ), self._absolute_path
  34. self.hemisphere = self.FILENAME_HEMISPHERE_PREFIX_MAP[filename_groups["h"]]
  35. self.t1_input = filename_groups["T1"] is not None
  36. self.analysis_id = filename_groups["analysis_id"]
  37. super().__init__(path=path)
  38. @property
  39. def absolute_path(self):
  40. return str(self._absolute_path)
  41. def read_volumes_mm3(self) -> typing.Dict[str, float]:
  42. subfield_volumes = {}
  43. for line in (
  44. self._absolute_path.read_text(encoding="ascii").rstrip().split("\n")
  45. ):
  46. # https://github.com/freesurfer/freesurfer/blob/release_6_0_0/HippoSF/src/segmentSubjectT1T2_autoEstimateAlveusML.m#L8
  47. # https://github.com/freesurfer/freesurfer/blob/release_6_0_0/HippoSF/src/segmentSubjectT1T2_autoEstimateAlveusML.m#L1946
  48. subfield_name, subfield_volume_mm3_str = line.split(" ")
  49. subfield_volumes[subfield_name] = float(subfield_volume_mm3_str)
  50. return subfield_volumes
  51. def read_volumes_dataframe(self) -> pandas.DataFrame:
  52. volumes_frame = self._read_volume_series().reset_index()
  53. volumes_frame["subject"] = self.subject
  54. volumes_frame["hemisphere"] = self.hemisphere
  55. # volumes_frame['hemisphere'] = volumes_frame['hemisphere'].astype('category')
  56. volumes_frame["T1_input"] = self.t1_input
  57. volumes_frame["analysis_id"] = self.analysis_id
  58. return volumes_frame