Пример #1
0
    def test_validate_sliceincrement(self):
        validate_slice_increment(
            sort_dicoms(read_dicom_directory(test_data.GE_ANATOMICAL)))

        self.assertRaises(
            ConversionValidationError, validate_slice_increment,
            sort_dicoms(read_dicom_directory(
                test_data.FAILING_SLICEINCREMENT)))
Пример #2
0
 def test_is_slice_increment_inconsistent(self):
     self.assertFalse(
         is_slice_increment_inconsistent(
             sort_dicoms(read_dicom_directory(test_data.GE_ANATOMICAL))))
     self.assertTrue(
         is_slice_increment_inconsistent(
             sort_dicoms(
                 read_dicom_directory(test_data.FAILING_SLICEINCREMENT))))
Пример #3
0
def _classic_get_grouped_dicoms(dicom_input):
    """
    Search all dicoms in the dicom directory, sort and validate them

    fast_read = True will only read the headers not the data
    """
    # Loop overall files and build dict
    # Order all dicom files by InstanceNumber
    if [d for d in dicom_input if 'InstanceNumber' in d]:
        dicoms = sorted(dicom_input, key=lambda x: x.InstanceNumber)
    else:
        dicoms = common.sort_dicoms(dicom_input)

    # now group per stack
    grouped_dicoms = []

    # loop over all sorted dicoms
    stack_position_tag = Tag(
        0x0020, 0x0012)  # in this case it is the acquisition number
    for index in range(0, len(dicoms)):
        dicom_ = dicoms[index]
        if stack_position_tag not in dicom_:
            stack_index = 0
        else:
            stack_index = dicom_[stack_position_tag].value - 1
        while len(grouped_dicoms) <= stack_index:
            grouped_dicoms.append([])
        grouped_dicoms[stack_index].append(dicom_)

    return grouped_dicoms
Пример #4
0
def _get_grouped_dicoms(dicom_input):
    """
    Search all dicoms in the dicom directory, sort and validate them

    fast_read = True will only read the headers not the data
    """
    # if all dicoms have an instance number try sorting by instance number else by position
    if [d for d in dicom_input if 'InstanceNumber' in d]:
        dicoms = sorted(dicom_input, key=lambda x: x.InstanceNumber)
    else:
        dicoms = common.sort_dicoms(dicom_input)
    # now group per stack
    grouped_dicoms = [[]]  # list with first element a list
    timepoint_index = 0
    previous_stack_position = -1

    # loop over all sorted dicoms
    stack_position_tag = Tag(0x2001, 0x100a)  # put this there as this is a slow step and used a lot
    for index in range(0, len(dicoms)):
        dicom_ = dicoms[index]
        stack_position = 0
        if stack_position_tag in dicom_:
            stack_position = common.get_is_value(dicom_[stack_position_tag])
        if previous_stack_position == stack_position:
            # if the stack number is the same we move to the next timepoint
            timepoint_index += 1
            if len(grouped_dicoms) <= timepoint_index:
                grouped_dicoms.append([])
        else:
            # if it changes move back to the first timepoint
            timepoint_index = 0
        grouped_dicoms[timepoint_index].append(dicom_)
        previous_stack_position = stack_position

    return grouped_dicoms
Пример #5
0
def _get_grouped_dicoms(dicom_input):
    """
    Search all dicoms in the dicom directory, sort and validate them

    fast_read = True will only read the headers not the data
    """
    # if all dicoms have an instance number try sorting by instance number else by position
    if [d for d in dicom_input if 'InstanceNumber' in d]:
        dicoms = sorted(dicom_input, key=lambda x: x.InstanceNumber)
    else:
        dicoms = common.sort_dicoms(dicom_input)
    # now group per stack
    grouped_dicoms = [[]]  # list with first element a list
    timepoint_index = 0
    previous_stack_position = -1

    # loop over all sorted dicoms
    stack_position_tag = Tag(0x2001, 0x100a)  # put this there as this is a slow step and used a lot
    for index in range(0, len(dicoms)):
        dicom_ = dicoms[index]
        stack_position = 0
        if stack_position_tag in dicom_:
            stack_position = common.get_is_value(dicom_[stack_position_tag])
        if previous_stack_position == stack_position:
            # if the stack number is the same we move to the next timepoint
            timepoint_index += 1
            if len(grouped_dicoms) <= timepoint_index:
                grouped_dicoms.append([])
        else:
            # if it changes move back to the first timepoint
            timepoint_index = 0
        grouped_dicoms[timepoint_index].append(dicom_)
        previous_stack_position = stack_position

    return grouped_dicoms
Пример #6
0
def _classic_get_grouped_dicoms(dicom_input):
    """
    Search all dicoms in the dicom directory, sort and validate them

    fast_read = True will only read the headers not the data
    """
    # Loop overall files and build dict
    # Order all dicom files by InstanceNumber
    if [d for d in dicom_input if 'InstanceNumber' in d]:
        dicoms = sorted(dicom_input, key=lambda x: x.InstanceNumber)
    else:
        dicoms = common.sort_dicoms(dicom_input)

    # now group per stack
    grouped_dicoms = []

    # loop over all sorted dicoms
    stack_position_tag = Tag(0x0020, 0x0012)  # in this case it is the acquisition number
    for index in range(0, len(dicoms)):
        dicom_ = dicoms[index]
        if stack_position_tag not in dicom_:
            stack_index = 0
        else:
            stack_index = dicom_[stack_position_tag].value - 1
        while len(grouped_dicoms) <= stack_index:
            grouped_dicoms.append([])
        grouped_dicoms[stack_index].append(dicom_)

    return grouped_dicoms
Пример #7
0
def dicom_to_nifti(dicom_input, output_file):
    """
    This function will convert an anatomical dicom series to a nifti

    Examples: See unit test

    :param output_file: filepath to the output nifti
    :param dicom_input: directory with the dicom files for a single scan, or list of read in dicoms
    """
    if len(dicom_input) <= 0:
        raise ConversionError('NO_DICOM_FILES_FOUND')

    # remove duplicate slices based on position and data
    dicom_input = _remove_duplicate_slices(dicom_input)

    # remove localizers based on image type
    dicom_input = _remove_localizers_by_imagetype(dicom_input)
    if settings.validate_slicecount:
        # remove_localizers based on image orientation (only valid if slicecount is validated)
        dicom_input = _remove_localizers_by_orientation(dicom_input)

        # validate all the dicom files for correct orientations
        common.validate_slicecount(dicom_input)
    if settings.validate_orientation:
        # validate that all slices have the same orientation
        common.validate_orientation(dicom_input)
    if settings.validate_orthogonal:
        # validate that we have an orthogonal image (to detect gantry tilting etc)
        common.validate_orthogonal(dicom_input)

    # sort the dicoms
    dicom_input = common.sort_dicoms(dicom_input)

    if settings.validate_sliceincrement:
        # validate that all slices have a consistent slice increment
        common.validate_sliceincrement(dicom_input)

    # Get data; originally z,y,x, transposed to x,y,z
    data = common.get_volume_pixeldata(dicom_input)

    affine = common.create_affine(dicom_input)

    # Convert to nifti
    nii_image = nibabel.Nifti1Image(data, affine)

    # Set TR and TE if available
    if Tag(0x0018, 0x0081) in dicom_input[0] and Tag(0x0018,
                                                     0x0081) in dicom_input[0]:
        common.set_tr_te(nii_image, float(dicom_input[0].RepetitionTime),
                         float(dicom_input[0].EchoTime))

    # Save to disk
    if output_file is not None:
        logger.info('Saving nifti to disk %s' % output_file)
        nii_image.to_filename(output_file)

    return {'NII_FILE': output_file, 'NII': nii_image}
Пример #8
0
def dicom_to_nifti(dicom_input, output_file):
    """
    This function will convert an anatomical dicom series to a nifti

    Examples: See unit test

    :param output_file: filepath to the output nifti
    :param dicom_input: directory with the dicom files for a single scan, or list of read in dicoms
    """
    if len(dicom_input) <= 0:
        raise ConversionError('NO_DICOM_FILES_FOUND')

    # remove duplicate slices based on position and data
    dicom_input = remove_duplicate_slices(dicom_input)

    # remove localizers based on image type
    dicom_input = remove_localizers_by_imagetype(dicom_input)
    # if no dicoms remain we should raise exception
    if len(dicom_input) < 1:
        raise ConversionValidationError('TOO_FEW_SLICES/LOCALIZER')

    if settings.validate_slicecount:
        common.validate_slicecount(dicom_input)
        # remove_localizers based on image orientation (only valid if slicecount is validated)
        dicom_input = remove_localizers_by_orientation(dicom_input)

        # validate all the dicom files for correct orientations
        common.validate_slicecount(dicom_input)
    if settings.validate_orientation:
        # validate that all slices have the same orientation
        common.validate_orientation(dicom_input)
    if settings.validate_orthogonal:
        # validate that we have an orthogonal image (to detect gantry tilting etc)
        common.validate_orthogonal(dicom_input)

    # sort the dicoms
    dicom_input = common.sort_dicoms(dicom_input)

    # validate slice increment inconsistent
    slice_increment_inconsistent = False
    if settings.validate_slice_increment:
        # validate that all slices have a consistent slice increment
        common.validate_slice_increment(dicom_input)
    elif common.is_slice_increment_inconsistent(dicom_input):
        slice_increment_inconsistent = True

    if settings.validate_instance_number:
        # validate that all slices have a consistent instance_number
        common.validate_instance_number(dicom_input)


    # if inconsistent increment and we allow resampling then do the resampling based conversion to maintain the correct geometric shape
    if slice_increment_inconsistent and settings.resample:
        nii_image, max_slice_increment = _convert_slice_incement_inconsistencies(dicom_input)
    # do the normal conversion
    else:
        # Get data; originally z,y,x, transposed to x,y,z
        data = common.get_volume_pixeldata(dicom_input)

        affine, max_slice_increment = common.create_affine(dicom_input)

        # Convert to nifti
        nii_image = nibabel.Nifti1Image(data.squeeze(), affine)

    # Set TR and TE if available
    if Tag(0x0018, 0x0080) in dicom_input[0] and Tag(0x0018, 0x0081) in dicom_input[0]:
        common.set_tr_te(nii_image, float(dicom_input[0].RepetitionTime), float(dicom_input[0].EchoTime))

    # Save to disk
    if output_file is not None:
        logger.info('Saving nifti to disk %s' % output_file)
        nii_image.header.set_slope_inter(1, 0)
        nii_image.header.set_xyzt_units(2)  # set units for xyz (leave t as unknown)
        nii_image.to_filename(output_file)

    return {'NII_FILE': output_file,
            'NII': nii_image,
            'MAX_SLICE_INCREMENT': max_slice_increment}
Пример #9
0
    def test_validate_sliceincrement(self):
        validate_slice_increment(sort_dicoms(read_dicom_directory(test_data.GE_ANATOMICAL)))

        self.assertRaises(ConversionValidationError,
                          validate_slice_increment,
                          sort_dicoms(read_dicom_directory(test_data.FAILING_SLICEINCREMENT)))
Пример #10
0
def dicom_to_nifti(dicom_input, output_file):
    """
    This function will convert an anatomical dicom series to a nifti

    Examples: See unit test

    :param output_file: filepath to the output nifti
    :param dicom_input: directory with the dicom files for a single scan, or list of read in dicoms
    """
    if len(dicom_input) <= 0:
        raise ConversionError('NO_DICOM_FILES_FOUND')

    # remove duplicate slices based on position and data
    dicom_input = _remove_duplicate_slices(dicom_input)

    # remove localizers based on image type
    dicom_input = _remove_localizers_by_imagetype(dicom_input)
    if settings.validate_slicecount:
        # remove_localizers based on image orientation (only valid if slicecount is validated)
        dicom_input = _remove_localizers_by_orientation(dicom_input)

        # validate all the dicom files for correct orientations
        common.validate_slicecount(dicom_input)
    if settings.validate_orientation:
        # validate that all slices have the same orientation
        common.validate_orientation(dicom_input)
    if settings.validate_orthogonal:
        # validate that we have an orthogonal image (to detect gantry tilting etc)
        common.validate_orthogonal(dicom_input)

    # sort the dicoms
    dicom_input = common.sort_dicoms(dicom_input)

    # validate slice increment inconsistent
    slice_increment_inconsistent = False
    if settings.validate_slice_increment:
        # validate that all slices have a consistent slice increment
        common.validate_slice_increment(dicom_input)
    elif common.is_slice_increment_inconsistent(dicom_input):
        slice_increment_inconsistent = True

    # if inconsistent increment and we allow resampling then do the resampling based conversion to maintain the correct geometric shape
    if slice_increment_inconsistent and settings.resample:
        nii_image, max_slice_increment = _convert_slice_incement_inconsistencies(dicom_input)
    # do the normal conversion
    else:
        # Get data; originally z,y,x, transposed to x,y,z
        data = common.get_volume_pixeldata(dicom_input)

        affine, max_slice_increment = common.create_affine(dicom_input)

        # Convert to nifti
        nii_image = nibabel.Nifti1Image(data, affine)

    # Set TR and TE if available
    if Tag(0x0018, 0x0081) in dicom_input[0] and Tag(0x0018, 0x0081) in dicom_input[0]:
        common.set_tr_te(nii_image, float(dicom_input[0].RepetitionTime), float(dicom_input[0].EchoTime))

    # Save to disk
    if output_file is not None:
        logger.info('Saving nifti to disk %s' % output_file)
        nii_image.to_filename(output_file)

    return {'NII_FILE': output_file,
            'NII': nii_image,
            'MAX_SLICE_INCREMENT': max_slice_increment}