Beispiel #1
0
def parse_one(self):
    """
    Composer function, parses all metadata that can be parsed from a single dicom.

    Called by NIMSDicom init, if dicom manufacturer is Siemens.

    """
    mr.parse_standard_mr_tags(self)

    self.psd_name = self.getelem(
        self._hdr, 'CsaSeries.MrPhoenixProtocol.tSequenceFileName', str,
        '').lower().replace('%', '', 1)
    self.psd_iname = self.getelem(self._hdr, 'SeriesDescription')
    self.fov_x = self.getelem(
        self._hdr,
        'CsaSeries.MrPhoenixProtocol.sSliceArray.asSlice[0].dPhaseFOV',
        float)  # XXX fov-x = PhaseFOV?
    self.fov_y = self.getelem(
        self._hdr,
        'CsaSeries.MrPhoenixProtocol.sSliceArray.asSlice[0].dReadoutFOV',
        float)  # XXX fov-y = ReadoutFOV?
    self.receive_coil_name = self.getelem(self._hdr, 'CsaImage.ImaCoilString')
    slice_duration = self.getelem(self._hdr,
                                  'CsaImage.SliceMeasurementDuration', float,
                                  0.)
    self.slice_duration = slice_duration / 1e6 if slice_duration else None
    self.prescribed_duration = self.getelem(
        self._hdr, 'CsaSeries.MrPhoenixProtocol.lScanTimeSec')  # FIXME
    self.duration = self.getelem(
        self._hdr, 'CsaSeries.MrPhoenixProtocol.lTotalScanTimeSec'
    )  # FIXME: not guaranteed
    self.acq_no = None  # siemens acq # indicates the brain volume instance. varies within one scan.

    # this is not an ideal solution, as it assumes that EPI timeserise are always stored in mosaic
    # for mosaics, lReps = prescribed timepoints.  non-mosaics and non-timeseries will not have this tag
    lRep = self.getelem(self._hdr, 'CsaSeries.MrPhoenixProtocol.lRepetitions',
                        int)
    self.num_timepoints = (lRep + 1) if lRep else None

    self.dwi_dirs = self.getelem(
        self._hdr, 'CsaSeries.MrPhoenixProtocol.sDiffusion.lDiffDirections',
        int, None)
    if (self.dwi_dirs or 0) > 1:
        self.is_dwi = True
        self.num_timepoints = 1

    # some siemens MR dicoms are not reconstructable
    if 'CSAPARALLEL' in self.image_type:
        self.is_non_image = True
    if 'POSDISP' in self.image_type:
        self.is_non_image = True
    if self.image_type == SIEMENS_TYPE_DIS2D:
        # had 2 image orientations, and other metdata that varied between dicoms, and is not a localizer. AFNI cannot reconstsruct.
        # this is a specific hack fix. A more general fix is to check each dicom to see if the orientation matches the first dicom
        # but checking EVERY dicom isn't very ideal solution (some datasets might have an ENORMOUS number of dicoms)
        self.is_non_image = True

    infer_psd_type(self)
    mr.adjust_fov_acqmat(self)
    mr.infer_scan_type(self)
Beispiel #2
0
def parse_one(self):
    """
    Composer function, parses all metadata that can be parsed from a single dicom.

    Called by NIMSDicom init, if dicom manufacturer is Siemens.

    """
    mr.parse_standard_mr_tags(self)

    self.psd_name = self.getelem(self._hdr, 'CsaSeries.MrPhoenixProtocol.tSequenceFileName', str, '').lower().replace('%', '', 1)
    self.psd_iname = self.getelem(self._hdr, 'SeriesDescription')
    self.fov_x = self.getelem(self._hdr, 'CsaSeries.MrPhoenixProtocol.sSliceArray.asSlice[0].dPhaseFOV', float)    # XXX fov-x = PhaseFOV?
    self.fov_y = self.getelem(self._hdr, 'CsaSeries.MrPhoenixProtocol.sSliceArray.asSlice[0].dReadoutFOV', float)  # XXX fov-y = ReadoutFOV?
    self.receive_coil_name = self.getelem(self._hdr, 'CsaImage.ImaCoilString')
    slice_duration = self.getelem(self._hdr, 'CsaImage.SliceMeasurementDuration', float, 0.)
    self.slice_duration = slice_duration / 1e6 if slice_duration else None
    self.prescribed_duration = self.getelem(self._hdr, 'CsaSeries.MrPhoenixProtocol.lScanTimeSec')   # FIXME
    self.duration = self.getelem(self._hdr, 'CsaSeries.MrPhoenixProtocol.lTotalScanTimeSec')         # FIXME: not guaranteed
    self.acq_no = None      # siemens acq # indicates the brain volume instance. varies within one scan.

    # this is not an ideal solution, as it assumes that EPI timeserise are always stored in mosaic
    # for mosaics, lReps = prescribed timepoints.  non-mosaics and non-timeseries will not have this tag
    lRep = self.getelem(self._hdr, 'CsaSeries.MrPhoenixProtocol.lRepetitions', int)
    self.num_timepoints = (lRep + 1) if lRep else None

    self.dwi_dirs = self.getelem(self._hdr, 'CsaSeries.MrPhoenixProtocol.sDiffusion.lDiffDirections', int, None)
    if (self.dwi_dirs or 0) > 1:
        self.is_dwi = True
        self.num_timepoints = 1

    # some siemens MR dicoms are not reconstructable
    if 'CSAPARALLEL' in self.image_type:
        self.is_non_image = True
    if 'POSDISP' in self.image_type:
        self.is_non_image = True
    if self.image_type == SIEMENS_TYPE_DIS2D:
        # had 2 image orientations, and other metdata that varied between dicoms, and is not a localizer. AFNI cannot reconstsruct.
        # this is a specific hack fix. A more general fix is to check each dicom to see if the orientation matches the first dicom
        # but checking EVERY dicom isn't very ideal solution (some datasets might have an ENORMOUS number of dicoms)
        self.is_non_image = True

    infer_psd_type(self)
    mr.adjust_fov_acqmat(self)
    mr.infer_scan_type(self)
Beispiel #3
0
def parse_one(self):
    """
    Composer function, parses all metadata that can be parsed from a single dicom.

    Called by NIMSData init, if dicom manufacturer is GE Medical Sytems.

    """

    mr.parse_standard_mr_tags(self)
    self.psd_name = self.getelem(self._hdr, 'PulseSequenceName', str,
                                 '').lower()
    self.psd_iname = self.getelem(self._hdr, 'InternalPulseSequenceName')
    self.fov_x, self.fov_y = 2 * [
        self.getelem(self._hdr, 'ReconstructionDiameter', float)
    ]
    self.receive_coil_name = self.getelem(self._hdr, 'ReceiveCoilName')
    self.mt_offset_hz = self.getelem(self._hdr, 'OffsetFrequency', float)
    effective_echo_spacing = self.getelem(self._hdr, 'EffectiveEchoSpacing',
                                          float)
    self.effective_echo_spacing = effective_echo_spacing / 1e6 if effective_echo_spacing else None
    asset_r = self.getelem(self._hdr, 'AssetRFactors', None, [None, None])
    if isinstance(
            asset_r, unicode
    ) and '\\' in asset_r:  # GE Signa HDxt stores asset as string '1\1'
        asset_r = map(
            int, asset_r.split('\\'))  # reformat to [1, 1] for consistency
    elif isinstance(asset_r, float):  # asset_r can be single item float
        asset_r = [None, None]
    self.phase_encode_undersample, self.slice_encode_undersample = asset_r
    # some very old Ge systems will output dicoms that don't define Locations in Acquition, or define it in a way
    # that is weird.  It may incorrectly label the value type as OB, but not be able to translate the value, resulting
    # in the MetaExtractor excluding it from the it's output metadata.
    self.num_slices = self.getelem(self._hdr, 'LocationsInAcquisition', int)
    self.total_num_slices = self.getelem(self._hdr, 'ImagesInAcquisition', int)
    self.num_timepoints = self.getelem(self._hdr, 'NumberOfTemporalPositions',
                                       int)

    # slice check could end up wrong, if both total_num_slices and num_slices are None
    # could force num_slices and total_num_slices into different ORs, to prevent matching if both are None
    # thus only when they are both defined, AND not equal, can this test pass
    if (self.total_num_slices or 1) == (self.num_slices or 0):
        self.total_num_slices = (self.num_slices or 1) * (self.num_timepoints
                                                          or 1)
        log.debug('adjusted total_num_slices from %3d to %3d' %
                  (self.num_slices,
                   self.total_num_slices))  # num_slices == 'old' total_num

    # some localizer don't have header field to indicate the number of slices
    # per acquisition.  If the total_number of slices is set, and the num_timepoints is 1
    # then the number of slices should be equal to total number of slices
    if not self.num_slices and (self.num_timepoints or 1) == 1:
        self.num_slices = self.total_num_slices

    prescribed_duration = (self.tr or 0) * (self.num_timepoints or 0) * (
        self.num_averages or 1)  # FIXME: only works for fMRI, not anatomical
    if prescribed_duration != 0:
        self.prescribed_duration = prescribed_duration
        self.duration = prescribed_duration
    else:
        self.prescribed_duration = None
        self.duration = None

    dwi_dirs = self.getelem(self._hdr,
                            'UserData24{#DTIDiffusionDir.,Release10.0&Above}',
                            float)
    self.dwi_dirs = int(dwi_dirs) if dwi_dirs else None
    if self.image_type == GEMS_TYPE_ORIG and (self.dwi_dirs or 0) >= 6:
        self.is_dwi = True
        self.num_timepoints = 1

    if self.image_type == GEMS_TYPE_DERIVED_RFMT:
        self.is_non_image = True

    infer_psd_type(self)
    mr.adjust_fov_acqmat(self)
    mr.infer_scan_type(self)
Beispiel #4
0
def parse_one(self):
    """
    Composer function, parses all metadata that can be parsed from a single dicom.

    Called by NIMSData init, if dicom manufacturer is GE Medical Sytems.

    """

    mr.parse_standard_mr_tags(self)
    self.psd_name = self.getelem(self._hdr, 'PulseSequenceName', str, '').lower()
    self.psd_iname = self.getelem(self._hdr, 'InternalPulseSequenceName')
    self.fov_x, self.fov_y = 2 * [self.getelem(self._hdr, 'ReconstructionDiameter', float)]
    self.receive_coil_name = self.getelem(self._hdr, 'ReceiveCoilName')
    self.mt_offset_hz = self.getelem(self._hdr, 'OffsetFrequency', float)
    effective_echo_spacing = self.getelem(self._hdr, 'EffectiveEchoSpacing', float)
    self.effective_echo_spacing = effective_echo_spacing / 1e6 if effective_echo_spacing else None
    asset_r = self.getelem(self._hdr, 'AssetRFactors', None, [None, None])
    if isinstance(asset_r, unicode) and '\\' in asset_r:    # GE Signa HDxt stores asset as string '1\1'
        asset_r = map(int, asset_r.split('\\'))             # reformat to [1, 1] for consistency
    elif isinstance(asset_r, float):                        # asset_r can be single item float
        asset_r = [None, None]
    self.phase_encode_undersample, self.slice_encode_undersample = asset_r
    # some very old Ge systems will output dicoms that don't define Locations in Acquition, or define it in a way
    # that is weird.  It may incorrectly label the value type as OB, but not be able to translate the value, resulting
    # in the MetaExtractor excluding it from the it's output metadata.
    self.num_slices = self.getelem(self._hdr, 'LocationsInAcquisition', int)
    self.total_num_slices = self.getelem(self._hdr, 'ImagesInAcquisition', int)
    self.num_timepoints = self.getelem(self._hdr, 'NumberOfTemporalPositions', int)

    # slice check could end up wrong, if both total_num_slices and num_slices are None
    # could force num_slices and total_num_slices into different ORs, to prevent matching if both are None
    # thus only when they are both defined, AND not equal, can this test pass
    if (self.total_num_slices or 1) == (self.num_slices or 0):
        self.total_num_slices = (self.num_slices or 1) * (self.num_timepoints or 1)
        log.debug('adjusted total_num_slices from %3d to %3d' % (self.num_slices, self.total_num_slices))  # num_slices == 'old' total_num

    # some localizer don't have header field to indicate the number of slices
    # per acquisition.  If the total_number of slices is set, and the num_timepoints is 1
    # then the number of slices should be equal to total number of slices
    if not self.num_slices and (self.num_timepoints or 1) == 1:
        self.num_slices = self.total_num_slices

    prescribed_duration = (self.tr or 0) * (self.num_timepoints or 0) * (self.num_averages or 1)  # FIXME: only works for fMRI, not anatomical
    if prescribed_duration != 0:
        self.prescribed_duration = prescribed_duration
        self.duration = prescribed_duration
    else:
        self.prescribed_duration = None
        self.duration = None

    dwi_dirs = self.getelem(self._hdr, 'UserData24{#DTIDiffusionDir.,Release10.0&Above}', float)
    self.dwi_dirs = int(dwi_dirs) if dwi_dirs else None
    if self.image_type == GEMS_TYPE_ORIG and (self.dwi_dirs or 0) >= 6:
        self.is_dwi = True
        self.num_timepoints = 1

    if self.image_type == GEMS_TYPE_DERIVED_RFMT:
        self.is_non_image = True

    infer_psd_type(self)
    mr.adjust_fov_acqmat(self)
    mr.infer_scan_type(self)