123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- """
- Python Library to Read FreeSurfer's cortical parcellation anatomical statistics
- ([lh]h.aparc(.*)?.stats)
- Freesurfer
- https://surfer.nmr.mgh.harvard.edu/
- >>> stats = CorticalParcellationStats.read('tests/subjects/fabian/stats/lh.aparc.DKTatlas.stats')
- >>> stats.creation_time.isoformat()
- '2019-05-09T21:05:54+00:00'
- >>> stats.cvs_version
- 'Id: mris_anatomical_stats.c,v 1.79 2016/03/14 15:15:34 greve Exp'
- >>> stats.cmdline[:64]
- 'mris_anatomical_stats -th3 -mgz -cortex ../label/lh.cortex.label'
- """
- import datetime
- import re
- import typing
- import pandas
- from freesurfer_stats.version import __version__
- class CorticalParcellationStats:
- _HEMISPHERE_PREFIX_TO_SIDE = {'lh': 'left', 'rh': 'right'}
- def __init__(self):
- self.creation_time = None # type: typing.Optional[datetime.datetime]
- self.generating_program = None # type: typing.Optional[str]
- self.cvs_version = None # type: typing.Optional[str]
- self.mrisurf_ccvs_version = None # type: typing.Optional[str]
- self.cmdline = None # type: typing.Optional[str]
- self.sysname = None # type: typing.Optional[str]
- self.hostname = None # type: typing.Optional[str]
- self.machine = None # type: typing.Optional[str]
- self.user = None # type: typing.Optional[str]
- self.subjects_dir = None # type: typing.Optional[str]
- self.anatomy_type = None # type: typing.Optional[str]
- self.subject_name = None # type: typing.Optional[str]
- self.hemisphere = None # type: typing.Optional[str]
- self.annotation_file = None # type: typing.Optional[str]
- self.annotation_file_timestamp \
- = None # type: typing.Optional[datetime.datetime]
- def _read_headers(self, stream: typing.TextIO) -> None:
- creation_time_str = stream.readline()[len('# CreationTime '):].rstrip()
- self.creation_time = datetime.datetime.strptime(
- creation_time_str, '%Y/%m/%d-%H:%M:%S-%Z')
- if self.creation_time.tzinfo is None:
- assert creation_time_str.endswith('-GMT')
- self.creation_time = self.creation_time.replace(
- tzinfo=datetime.timezone.utc)
- while True:
- line = stream.readline().rstrip()
- if line == '#':
- continue
- elif line.startswith('# Measure'):
- break
- prefix, attr_name, attr_value = line.split(' ', maxsplit=2)
- assert prefix == '#'
- attr_value = attr_value.lstrip()
- if attr_name == 'generating_program':
- self.generating_program = attr_value
- elif attr_name == 'cvs_version':
- self.cvs_version = attr_value.strip('$').rstrip()
- elif attr_name == 'mrisurf.c-cvs_version':
- self.mrisurf_ccvs_version = attr_value.strip('$').rstrip()
- elif attr_name == 'cmdline':
- self.cmdline = attr_value
- elif attr_name == 'sysname':
- self.sysname = attr_value
- elif attr_name == 'hostname':
- self.hostname = attr_value
- elif attr_name == 'machine':
- self.machine = attr_value
- elif attr_name == 'user':
- self.user = attr_value
- elif attr_name == 'SUBJECTS_DIR':
- self.subjects_dir = attr_value
- elif attr_name == 'anatomy_type':
- self.anatomy_type = attr_value
- elif attr_name == 'subjectname':
- self.subject_name = attr_value
- elif attr_name == 'hemi':
- self.hemisphere = self._HEMISPHERE_PREFIX_TO_SIDE[attr_value]
- elif attr_name == 'AnnotationFile':
- self.annotation_file = attr_value
- elif attr_name == 'AnnotationFileTimeStamp':
- self.annotation_file_timestamp = datetime.datetime.strptime(
- attr_value, '%Y/%m/%d %H:%M:%S')
- else:
- raise ValueError(attr_name)
- def _read(self, stream: typing.TextIO) -> None:
- assert stream.readline().rstrip() \
- == '# Table of FreeSurfer cortical parcellation anatomical statistics'
- assert stream.readline().rstrip() == '#'
- self._read_headers(stream)
- @classmethod
- def read(cls, path: str) -> 'CorticalParcellationStats':
- stats = cls()
- with open(path, 'r') as stream:
- # pylint: disable=protected-access
- stats._read(stream)
- return stats
|