def _shrink_file(dicom_file_in, subsample_factor):
    """
    Anonimize a single dicomfile
    :param dicom_file_in: filepath for input file
    :param dicom_file_out: filepath for output file
    :param fields_to_keep: dicom tags to keep
    """
    # Default meta_fields
    # Required fields according to reference

    dicom_file_out = dicom_file_in

    # Load dicom_file_in
    dicom_in = compressed_dicom.read_file(dicom_file_in)

    # Create new dicom file
    # Set new file meta information
    file_meta = pydicom.dataset.Dataset()
    for key, value in dicom_in.file_meta.items():
        file_meta.add(value)

        # Create the FileDataset instance (initially no data elements, but file_meta supplied)
    dicom_out = pydicom.dataset.FileDataset(dicom_file_out, {}, file_meta=file_meta, preamble=b'\0' * 128)

    # Copy transfer syntax
    dicom_out.is_little_endian = dicom_in.is_little_endian
    dicom_out.is_implicit_VR = dicom_in.is_implicit_VR

    rows = 0
    columns = 0

    # Add the data elements
    for field_key, field_value in dicom_in.items():
        logging.info(field_key)
        if field_key == (0x7fe0, 0x0010):
            pixel_array = dicom_in.pixel_array[::subsample_factor, ::subsample_factor]

            dicom_out.PixelData = pixel_array.tostring()  # = byte array (see pydicom docs)
            rows = pixel_array.shape[1]
            columns = pixel_array.shape[0]
            # noinspection PyPep8Naming
            dicom_out[0x7fe0, 0x0010].VR = 'OB'
        else:
            dicom_out.add(field_value)

    dicom_out.PixelSpacing[0] *= subsample_factor
    dicom_out.PixelSpacing[1] *= subsample_factor
    dicom_out.Rows = rows
    dicom_out.Columns = columns

    # Save dicom_file_out
    # Make sure we have a directory
    if not os.path.exists(os.path.dirname(dicom_file_out)):
        logging.info('Decompressing files')

    # Save the file
    dicom_out.save_as(dicom_file_out, write_like_original=False)
def _shrink_file(dicom_file_in, subsample_factor):
    """
    Anonimize a single dicomfile
    :param dicom_file_in: filepath for input file
    :param dicom_file_out: filepath for output file
    :param fields_to_keep: dicom tags to keep
    """
    # Default meta_fields
    # Required fields according to reference

    dicom_file_out = dicom_file_in

    # Load dicom_file_in
    dicom_in = compressed_dicom.read_file(dicom_file_in)

    # Create new dicom file
    # Set new file meta information
    file_meta = dicom.dataset.Dataset()
    for key, value in dicom_in.file_meta.items():
        file_meta.add(value)

        # Create the FileDataset instance (initially no data elements, but file_meta supplied)
    dicom_out = dicom.dataset.FileDataset(dicom_file_out, {}, file_meta=file_meta, preamble=b'\0' * 128)

    # Copy transfer syntax
    dicom_out.is_little_endian = dicom_in.is_little_endian
    dicom_out.is_implicit_VR = dicom_in.is_implicit_VR

    rows = 0
    columns = 0

    # Add the data elements
    for field_key, field_value in dicom_in.items():
        logging.info(field_key)
        if field_key == (0x7fe0, 0x0010):
            pixel_array = dicom_in.pixel_array[::subsample_factor, ::subsample_factor]

            dicom_out.PixelData = pixel_array.tostring()  # = byte array (see pydicom docs)
            rows = pixel_array.shape[1]
            columns = pixel_array.shape[0]
            # noinspection PyPep8Naming
            dicom_out[0x7fe0, 0x0010].VR = 'OB'
        else:
            dicom_out.add(field_value)

    dicom_out.PixelSpacing[0] *= subsample_factor
    dicom_out.PixelSpacing[1] *= subsample_factor
    dicom_out.Rows = rows
    dicom_out.Columns = columns

    # Save dicom_file_out
    # Make sure we have a directory
    if not os.path.exists(os.path.dirname(dicom_file_out)):
        logging.info('Decompressing files')

    # Save the file
    dicom_out.save_as(dicom_file_out)
Beispiel #3
0
def dicom_diff(file1, file2):
    """ Shows the fields that differ between two DICOM images.

    Inspired by https://code.google.com/p/pydicom/source/browse/source/dicom/examples/DicomDiff.py
    """

    datasets = compressed_dicom.read_file(file1), compressed_dicom.read_file(file2)

    rep = []

    for dataset in datasets:
        lines = (str(dataset.file_meta)+"\n"+str(dataset)).split('\n')
        lines = [line + '\n' for line in lines]  # add the newline to the end
        rep.append(lines)

    diff = difflib.Differ()
    for line in diff.compare(rep[0], rep[1]):
        if (line[0] == '+') or (line[0] == '-'):
            sys.stdout.write(line)
Beispiel #4
0
def dicom_diff(file1, file2):
    """ Shows the fields that differ between two DICOM images.

    Inspired by https://code.google.com/p/pydicom/source/browse/source/dicom/examples/DicomDiff.py
    """

    datasets = compressed_dicom.read_file(file1), compressed_dicom.read_file(
        file2)

    rep = []

    for dataset in datasets:
        lines = (str(dataset.file_meta) + "\n" + str(dataset)).split('\n')
        lines = [line + '\n' for line in lines]  # add the newline to the end
        rep.append(lines)

    diff = difflib.Differ()
    for line in diff.compare(rep[0], rep[1]):
        if (line[0] == '+') or (line[0] == '-'):
            sys.stdout.write(line)
    def test_read_file(self):
        temporary_directory = tempfile.mkdtemp()
        try:
            dicom_file = os.path.join(temporary_directory, 'IM-0001-0001-0001.dcm')
            input_file = os.path.join(test_data.GENERIC_COMPRESSED, 'IM-0001-0001-0001.dcm')
            shutil.copy(input_file, dicom_file)
            dicom_headers = compressed_dicom.read_file(dicom_file)
            pixel_data = dicom_headers.pixel_array
            self.assertIsNotNone(pixel_data)

        finally:
            shutil.rmtree(temporary_directory)
    def test_read_file(self):
        temporary_directory = tempfile.mkdtemp()
        try:
            dicom_file = os.path.join(temporary_directory,
                                      'IM-0001-0001-0001.dcm')
            input_file = os.path.join(test_data.GENERIC_COMPRESSED,
                                      'IM-0001-0001-0001.dcm')
            shutil.copy(input_file, dicom_file)
            dicom_headers = compressed_dicom.read_file(dicom_file)
            pixel_data = dicom_headers.pixel_array
            self.assertIsNotNone(pixel_data)

        finally:
            shutil.rmtree(temporary_directory)
def shrink_multiframe(input_file, output_file=None, slice_count=8, timepoint_count=4):
    if output_file is None:
        output_file = input_file

    # Load dicom_file_in
    dicom_in = compressed_dicom.read_file(input_file)

    if _is_multiframe_diffusion_imaging([dicom_in]) or _is_multiframe_4d([dicom_in]):

        number_of_stack_slices = int(common.get_ss_value(dicom_in[(0x2001, 0x105f)][0][(0x2001, 0x102d)]))
        number_of_stacks = int(int(dicom_in.NumberOfFrames) / number_of_stack_slices)

        # We create a numpy array
        size_x = dicom_in.pixel_array.shape[2]
        size_y = dicom_in.pixel_array.shape[1]
        size_t = number_of_stacks
        frame_info = dicom_in.PerFrameFunctionalGroupsSequence
        data_4d = numpy.zeros((slice_count * timepoint_count, size_x, size_y), dtype=common.get_numpy_type(dicom_in))
        new_frame_info = [None] * slice_count * timepoint_count
        for index_z in range(0, slice_count):
            for index_t in range(0, timepoint_count):
                slice_index = int(size_t * index_z + index_t)
                new_slice_index = int(timepoint_count * index_z + index_t)

                z_location = frame_info[slice_index].FrameContentSequence[0].InStackPositionNumber - 1
                new_frame_info[new_slice_index] = frame_info[slice_index]

                logging.info('Importing slice on position %s %s %s' % (slice_index, z_location, index_t))
                data_4d[new_slice_index, :, :] = dicom_in.pixel_array[slice_index, :, :]

        dicom_in.PixelData = data_4d.tostring()
        common.set_ss_value(dicom_in[(0x2001, 0x105f)][0][(0x2001, 0x102d)], slice_count)
        setattr(dicom_in, 'NumberOfFrames', slice_count * timepoint_count)
        setattr(dicom_in, 'PerFrameFunctionalGroupsSequence', new_frame_info)

    else:
        # truncate the data
        dicom_in.PixelData = dicom_in.pixel_array[:slice_count, :, :].tostring()
        # set number of frames
        common.set_ss_value(dicom_in[(0x2001, 0x105f)][0][(0x2001, 0x102d)], slice_count)

        setattr(dicom_in, 'NumberOfFrames', slice_count)
        # truncate the pre frame groups sequence
        setattr(dicom_in, 'PerFrameFunctionalGroupsSequence', dicom_in.PerFrameFunctionalGroupsSequence[:slice_count])

    # Save the file
    dicom_in.save_as(output_file)
Beispiel #8
0
def _get_first_header(dicom_directory):
    """
    Function to get the first dicom file form a directory and return the header
    Useful to determine the type of data to convert

    :param dicom_directory: directory with dicom files
    """
    # looping over all files
    for root, _, file_names in os.walk(dicom_directory):
        # go over all the files and try to read the dicom header
        for file_name in file_names:
            file_path = os.path.join(root, file_name)
            # check wither it is a dicom file
            if not compressed_dicom.is_dicom_file(file_path):
                continue
            # read the headers
            return compressed_dicom.read_file(file_path,
                                              stop_before_pixels=True,
                                              force=dicom2nifti.settings.pydicom_read_force)
    # no dicom files found
    raise ConversionError('NO_DICOM_FILES_FOUND')
Beispiel #9
0
def _get_first_header(dicom_directory):
    """
    Function to get the first dicom file form a directory and return the header
    Useful to determine the type of data to convert

    :param dicom_directory: directory with dicom files
    """
    # looping over all files
    for root, _, file_names in os.walk(dicom_directory):
        # go over all the files and try to read the dicom header
        for file_name in file_names:
            file_path = os.path.join(root, file_name)
            # check wither it is a dicom file
            if not compressed_dicom.is_dicom_file(file_path):
                continue
            # read the headers
            return compressed_dicom.read_file(file_path,
                                              stop_before_pixels=True,
                                              force=dicom2nifti.settings.pydicom_read_force)
    # no dicom files found
    raise ConversionError('NO_DICOM_FILES_FOUND')
def read_dicom_directory(dicom_directory, stop_before_pixels=False):
    """
    Read all dicom files in a given directory (stop before pixels)

    :type stop_before_pixels: bool
    :type dicom_directory: six.string_types
    :param stop_before_pixels: Should we stop reading before the pixeldata (handy if we only want header info)
    :param dicom_directory: Directory with dicom data
    :return: List of dicom objects
    """
    dicom_input = []
    for root, _, files in os.walk(dicom_directory):
        for dicom_file in files:
            file_path = os.path.join(root, dicom_file)
            if compressed_dicom.is_dicom_file(file_path):
                dicom_headers = compressed_dicom.read_file(file_path,
                                                           defer_size=100,
                                                           stop_before_pixels=stop_before_pixels,
                                                           force=dicom2nifti.settings.pydicom_read_force)
                dicom_input.append(dicom_headers)
    return dicom_input
Beispiel #11
0
def read_dicom_directory(dicom_directory, stop_before_pixels=False):
    """
    Read all dicom files in a given directory (stop before pixels)

    :type stop_before_pixels: bool
    :type dicom_directory: six.string_types
    :param stop_before_pixels: Should we stop reading before the pixeldata (handy if we only want header info)
    :param dicom_directory: Directory with dicom data
    :return: List of dicom objects
    """
    dicom_input = []
    for root, _, files in os.walk(dicom_directory):
        for dicom_file in files:
            file_path = os.path.join(root, dicom_file)
            if compressed_dicom.is_dicom_file(file_path):
                dicom_headers = compressed_dicom.read_file(file_path,
                                                           defer_size="1 KB",
                                                           stop_before_pixels=stop_before_pixels,
                                                           force=dicom2nifti.settings.pydicom_read_force)
                if is_valid_imaging_dicom(dicom_headers):
                    dicom_input.append(dicom_headers)
    return dicom_input
Beispiel #12
0
def shrink_multiframe(input_file,
                      output_file=None,
                      slice_count=8,
                      timepoint_count=4):
    if output_file is None:
        output_file = input_file

    # Load dicom_file_in
    dicom_in = compressed_dicom.read_file(input_file)

    if _is_multiframe_diffusion_imaging([dicom_in]) or _is_multiframe_4d(
        [dicom_in]):

        number_of_stack_slices = int(
            common.get_ss_value(dicom_in[(0x2001, 0x105f)][0][(0x2001,
                                                               0x102d)]))
        number_of_stacks = int(
            int(dicom_in.NumberOfFrames) / number_of_stack_slices)

        # We create a numpy array
        size_x = dicom_in.pixel_array.shape[2]
        size_y = dicom_in.pixel_array.shape[1]
        size_t = number_of_stacks
        frame_info = dicom_in.PerFrameFunctionalGroupsSequence
        data_4d = numpy.zeros((slice_count * timepoint_count, size_x, size_y),
                              dtype=common.get_numpy_type(dicom_in))
        new_frame_info = [None] * slice_count * timepoint_count
        for index_z in range(0, slice_count):
            for index_t in range(0, timepoint_count):
                slice_index = int(size_t * index_z + index_t)
                new_slice_index = int(timepoint_count * index_z + index_t)

                z_location = frame_info[slice_index].FrameContentSequence[
                    0].InStackPositionNumber - 1
                new_frame_info[new_slice_index] = frame_info[slice_index]

                logging.info('Importing slice on position %s %s %s' %
                             (slice_index, z_location, index_t))
                data_4d[new_slice_index, :, :] = dicom_in.pixel_array[
                    slice_index, :, :]

        dicom_in.PixelData = data_4d.tostring()
        common.set_ss_value(dicom_in[(0x2001, 0x105f)][0][(0x2001, 0x102d)],
                            slice_count)
        setattr(dicom_in, 'NumberOfFrames', slice_count * timepoint_count)
        setattr(dicom_in, 'PerFrameFunctionalGroupsSequence', new_frame_info)

    else:
        # truncate the data
        dicom_in.PixelData = dicom_in.pixel_array[:slice_count, :, :].tostring(
        )
        # set number of frames
        common.set_ss_value(dicom_in[(0x2001, 0x105f)][0][(0x2001, 0x102d)],
                            slice_count)

        setattr(dicom_in, 'NumberOfFrames', slice_count)
        # truncate the pre frame groups sequence
        setattr(dicom_in, 'PerFrameFunctionalGroupsSequence',
                dicom_in.PerFrameFunctionalGroupsSequence[:slice_count])

    # Save the file
    dicom_in.save_as(output_file)
Beispiel #13
0
 def test_get_asconv_headers(self):
     mosaic = compressed_dicom.read_file(
         os.path.join(test_data.SIEMENS_FMRI, 'IM-0001-0001.dcm'))
     asconv_headers = convert_siemens._get_asconv_headers(mosaic)
     assert len(asconv_headers) == 64022
Beispiel #14
0
def convert_directory(dicom_directory, output_folder, compression=True, reorient=True):
    """
    This function will order all dicom files by series and order them one by one

    :param compression: enable or disable gzip compression
    :param reorient: reorient the dicoms according to LAS orientation
    :param output_folder: folder to write the nifti files to
    :param dicom_directory: directory with dicom files
    """
    # sort dicom files by series uid
    dicom_series = {}
    for root, _, files in os.walk(dicom_directory):
        for dicom_file in files:
            file_path = os.path.join(root, dicom_file)
            # noinspection PyBroadException
            try:
                if compressed_dicom.is_dicom_file(file_path):
                    # read the dicom as fast as possible
                    # (max length for SeriesInstanceUID is 64 so defer_size 100 should be ok)

                    dicom_headers = compressed_dicom.read_file(file_path,
                                                               defer_size="1 KB",
                                                               stop_before_pixels=False,
                                                               force=dicom2nifti.settings.pydicom_read_force)
                    if not _is_valid_imaging_dicom(dicom_headers):
                        logger.info("Skipping: %s" % file_path)
                        continue
                    logger.info("Organizing: %s" % file_path)
                    if dicom_headers.SeriesInstanceUID not in dicom_series:
                        dicom_series[dicom_headers.SeriesInstanceUID] = []
                    dicom_series[dicom_headers.SeriesInstanceUID].append(dicom_headers)
            except:  # Explicitly capturing all errors here to be able to continue processing all the rest
                logger.warning("Unable to read: %s" % file_path)
                traceback.print_exc()

    # start converting one by one
    for series_id, dicom_input in iteritems(dicom_series):
        base_filename = ""
        # noinspection PyBroadException
        try:
            # construct the filename for the nifti
            base_filename = ""
            if 'SeriesNumber' in dicom_input[0]:
                base_filename = _remove_accents('%s' % dicom_input[0].SeriesNumber)
                if 'SeriesDescription' in dicom_input[0]:
                    base_filename = _remove_accents('%s_%s' % (base_filename,
                                                               dicom_input[0].SeriesDescription))
                elif 'SequenceName' in dicom_input[0]:
                    base_filename = _remove_accents('%s_%s' % (base_filename,
                                                               dicom_input[0].SequenceName))
                elif 'ProtocolName' in dicom_input[0]:
                    base_filename = _remove_accents('%s_%s' % (base_filename,
                                                               dicom_input[0].ProtocolName))
            else:
                base_filename = _remove_accents(dicom_input[0].SeriesInstanceUID)
            logger.info('--------------------------------------------')
            logger.info('Start converting %s' % base_filename)
            if compression:
                nifti_file = os.path.join(output_folder, base_filename + '.nii.gz')
            else:
                nifti_file = os.path.join(output_folder, base_filename + '.nii')
            convert_dicom.dicom_array_to_nifti(dicom_input, nifti_file, reorient)
            gc.collect()
        except:  # Explicitly capturing app exceptions here to be able to continue processing
            logger.info("Unable to convert: %s" % base_filename)
            traceback.print_exc()
Beispiel #15
0
def _anonymize_file(dicom_file_in, dicom_file_out, fields_to_keep):
    """
    Anonimize a single dicomfile
    :param dicom_file_in: filepath for input file
    :param dicom_file_out: filepath for output file
    :param fields_to_keep: dicom tags to keep
    """
    # Default meta_fields
    # Required fields according to reference

    meta_fields = [
        'MediaStorageSOPClassUID', 'MediaStorageSOPInstanceUID',
        'ImplementationClassUID'
    ]

    # Load dicom_file_in
    dicom_in = compressed_dicom.read_file(dicom_file_in)

    # Create new dicom file
    # Set new file meta information
    file_meta = pydicom.dataset.Dataset()
    file_meta.TransferSyntaxUID = pydicom.uid.ExplicitVRLittleEndian
    for field_key in meta_fields:
        file_meta.add(dicom_in.file_meta.data_element(field_key))

        # Create the FileDataset instance (initially no data elements, but file_meta supplied)
    dicom_out = pydicom.dataset.FileDataset(dicom_file_out, {},
                                            file_meta=file_meta,
                                            preamble=b'\0' * 128)

    # Copy transfer syntax
    dicom_out.is_little_endian = dicom_in.is_little_endian
    dicom_out.is_implicit_VR = dicom_in.is_implicit_VR

    # Add the data elements
    for (field_key, field_value) in iteritems(fields_to_keep):
        logging.info(field_key)
        if field_key == (0x7fe0, 0x0010):

            # anonimize the dicom pixeldata
            random_data = numpy.random.randint(
                0, 255,
                dicom_in.pixel_array.shape).astype(dicom_in.pixel_array.dtype)
            dicom_out.PixelData = random_data.tostring(
            )  # = byte array (see pydicom docs)

            # dicom_out.PixelData = dicom_in.pixel_array.tostring()  # = byte array (see pydicom docs)

            # noinspection PyPep8Naming
            dicom_out[0x7fe0, 0x0010].VR = 'OB'
        elif field_value is None:
            try:
                if isinstance(field_key, string_types):
                    if field_key in dicom_in:
                        dicom_out.add(dicom_in.data_element(field_key))
                else:
                    if dicom_in.get(field_key) is not None:
                        dicom_out.add(dicom_in[field_key])
            except KeyError:
                logging.info('Warning: %s not found' % field_key)
        else:
            setattr(dicom_out, field_key, field_value)

    # Save dicom_file_out
    # Make sure we have a directory
    if not os.path.exists(os.path.dirname(dicom_file_out)):
        logging.info('Decompressing files')

        # Save the file
        dicom_out.is_little_endian = True
    dicom_out.is_implicit_VR = False

    dicom_out.save_as(dicom_file_out, write_like_original=False)
Beispiel #16
0
 def test_get_asconv_headers(self):
     mosaic = compressed_dicom.read_file(os.path.join(test_data.SIEMENS_FMRI, 'IM-0001-0001.dcm'))
     asconv_headers = convert_siemens._get_asconv_headers(mosaic)
     assert len(asconv_headers) == 64022
Beispiel #17
0
def convert_directory(dicom_directory, output_folder, compression=True, reorient=True):
    """
    This function will order all dicom files by series and order them one by one

    :param compression: enable or disable gzip compression
    :param reorient: reorient the dicoms according to LAS orientation
    :param output_folder: folder to write the nifti files to
    :param dicom_directory: directory with dicom files
    """
    # sort dicom files by series uid
    dicom_series = {}
    for root, _, files in os.walk(dicom_directory):
        for dicom_file in files:
            file_path = os.path.join(root, dicom_file)
            # noinspection PyBroadException
            try:
                if compressed_dicom.is_dicom_file(file_path):
                    # read the dicom as fast as possible
                    # (max length for SeriesInstanceUID is 64 so defer_size 100 should be ok)

                    dicom_headers = compressed_dicom.read_file(file_path,
                                                               defer_size="1 KB",
                                                               stop_before_pixels=False,
                                                               force=dicom2nifti.settings.pydicom_read_force)
                    if not _is_valid_imaging_dicom(dicom_headers):
                        logger.info("Skipping: %s" % file_path)
                        continue
                    logger.info("Organizing: %s" % file_path)
                    if dicom_headers.SeriesInstanceUID not in dicom_series:
                        dicom_series[dicom_headers.SeriesInstanceUID] = []
                    dicom_series[dicom_headers.SeriesInstanceUID].append(dicom_headers)
            except:  # Explicitly capturing all errors here to be able to continue processing all the rest
                logger.warning("Unable to read: %s" % file_path)
                traceback.print_exc()

    # start converting one by one
    for series_id, dicom_input in dicom_series.items():
        base_filename = ""
        # noinspection PyBroadException
        try:
            # construct the filename for the nifti
            base_filename = ""
            if 'SeriesNumber' in dicom_input[0]:
                base_filename = _remove_accents('%s' % dicom_input[0].SeriesNumber)
                if 'SeriesDescription' in dicom_input[0]:
                    base_filename = _remove_accents('%s_%s' % (base_filename,
                                                               dicom_input[0].SeriesDescription))
                elif 'SequenceName' in dicom_input[0]:
                    base_filename = _remove_accents('%s_%s' % (base_filename,
                                                               dicom_input[0].SequenceName))
                elif 'ProtocolName' in dicom_input[0]:
                    base_filename = _remove_accents('%s_%s' % (base_filename,
                                                               dicom_input[0].ProtocolName))
            else:
                base_filename = _remove_accents(dicom_input[0].SeriesInstanceUID)
            logger.info('--------------------------------------------')
            logger.info('Start converting %s' % base_filename)
            if compression:
                nifti_file = os.path.join(output_folder, base_filename + '.nii.gz')
            else:
                nifti_file = os.path.join(output_folder, base_filename + '.nii')
            convert_dicom.dicom_array_to_nifti(dicom_input, nifti_file, reorient)
            gc.collect()
        except:  # Explicitly capturing app exceptions here to be able to continue processing
            logger.info("Unable to convert: %s" % base_filename)
            traceback.print_exc()