def _create_bvals_bvecs(multiframe_dicom, bval_file, bvec_file, nifti, nifti_file):
    """
    Write the bvals from the sorted dicom files to a bval file
    Inspired by https://github.com/IBIC/ibicUtils/blob/master/ibicBvalsBvecs.py
    """

    # create the empty arrays
    number_of_stack_slices = common.get_ss_value(multiframe_dicom[Tag(0x2001, 0x105f)][0][Tag(0x2001, 0x102d)])
    number_of_stacks = int(int(multiframe_dicom.NumberOfFrames) / number_of_stack_slices)

    bvals = numpy.zeros([number_of_stacks], dtype=numpy.int32)
    bvecs = numpy.zeros([number_of_stacks, 3])

    # loop over all timepoints and create a list with all bvals and bvecs
    for stack_index in range(0, number_of_stacks):
        stack = multiframe_dicom[Tag(0x5200, 0x9230)][stack_index]
        if str(stack[Tag(0x0018, 0x9117)][0][Tag(0x0018, 0x9075)].value) == 'DIRECTIONAL':
            bvals[stack_index] = common.get_fd_value(stack[Tag(0x0018, 0x9117)][0][Tag(0x0018, 0x9087)])
            bvecs[stack_index, :] = common.get_fd_array_value(stack[Tag(0x0018, 0x9117)][0]
                                                              [Tag(0x0018, 0x9076)][0][Tag(0x0018, 0x9089)], 3)

    # truncate nifti if needed
    nifti, bvals, bvecs = _fix_diffusion_images(bvals, bvecs, nifti, nifti_file)

    # save the found bvecs to the file
    if numpy.count_nonzero(bvals) > 0 or numpy.count_nonzero(bvecs) > 0:
        common.write_bval_file(bvals, bval_file)
        common.write_bvec_file(bvecs, bvec_file)
    else:
        bval_file = None
        bvec_file = None
        bvals = None
        bvecs = None

    return bvals, bvecs, bval_file, bvec_file
def _create_affine_multiframe(multiframe_dicom):
    """
    Function to create the affine matrix for a siemens mosaic dataset
    This will work for siemens dti and 4D if in mosaic format
    """
    first_frame = multiframe_dicom[Tag(0x5200, 0x9230)][0]
    last_frame = multiframe_dicom[Tag(0x5200, 0x9230)][-1]
    # Create affine matrix (http://nipy.sourceforge.net/nibabel/dicom/dicom_orientation.html#dicom-slice-affine)
    image_orient1 = numpy.array(first_frame.PlaneOrientationSequence[0].ImageOrientationPatient)[0:3].astype(float)
    image_orient2 = numpy.array(first_frame.PlaneOrientationSequence[0].ImageOrientationPatient)[3:6].astype(float)

    normal = numpy.cross(image_orient1, image_orient2)

    delta_r = float(first_frame[0x2005, 0x140f][0].PixelSpacing[0])
    delta_c = float(first_frame[0x2005, 0x140f][0].PixelSpacing[1])

    image_pos = numpy.array(first_frame.PlanePositionSequence[0].ImagePositionPatient).astype(float)
    last_image_pos = numpy.array(last_frame.PlanePositionSequence[0].ImagePositionPatient).astype(float)

    number_of_stack_slices = int(common.get_ss_value(multiframe_dicom[Tag(0x2001, 0x105f)][0][Tag(0x2001, 0x102d)]))
    delta_s = abs(numpy.linalg.norm(last_image_pos - image_pos)) / (number_of_stack_slices - 1)

    return numpy.array(
        [[-image_orient1[0] * delta_c, -image_orient2[0] * delta_r, -delta_s * normal[0], -image_pos[0]],
         [-image_orient1[1] * delta_c, -image_orient2[1] * delta_r, -delta_s * normal[1], -image_pos[1]],
         [image_orient1[2] * delta_c, image_orient2[2] * delta_r, delta_s * normal[2], image_pos[2]],
         [0, 0, 0, 1]])
Exemple #3
0
def _create_bvals_bvecs(multiframe_dicom, bval_file, bvec_file, nifti, nifti_file):
    """
    Write the bvals from the sorted dicom files to a bval file
    Inspired by https://github.com/IBIC/ibicUtils/blob/master/ibicBvalsBvecs.py
    """

    # create the empty arrays
    number_of_stack_slices = common.get_ss_value(multiframe_dicom[Tag(0x2001, 0x105f)][0][Tag(0x2001, 0x102d)])
    number_of_stacks = int(int(multiframe_dicom.NumberOfFrames) / number_of_stack_slices)

    bvals = numpy.zeros([number_of_stacks], dtype=numpy.int32)
    bvecs = numpy.zeros([number_of_stacks, 3])

    # loop over all timepoints and create a list with all bvals and bvecs
    for stack_index in range(0, number_of_stacks):
        stack = multiframe_dicom[Tag(0x5200, 0x9230)][stack_index]
        if str(stack[Tag(0x0018, 0x9117)][0][Tag(0x0018, 0x9075)].value) == 'DIRECTIONAL':
            bvals[stack_index] = common.get_fd_value(stack[Tag(0x0018, 0x9117)][0][Tag(0x0018, 0x9087)])
            bvecs[stack_index, :] = common.get_fd_array_value(stack[Tag(0x0018, 0x9117)][0]
                                                              [Tag(0x0018, 0x9076)][0][Tag(0x0018, 0x9089)], 3)

    # truncate nifti if needed
    nifti, bvals, bvecs = _fix_diffusion_images(bvals, bvecs, nifti, nifti_file)

    # save the found bvecs to the file
    if numpy.count_nonzero(bvals) > 0 or numpy.count_nonzero(bvecs) > 0:
        common.write_bval_file(bvals, bval_file)
        common.write_bvec_file(bvecs, bvec_file)
    else:
        bval_file = None
        bvec_file = None
        bvals = None
        bvecs = None

    return bvals, bvecs, bval_file, bvec_file
Exemple #4
0
def _create_affine_multiframe(multiframe_dicom):
    """
    Function to create the affine matrix for a siemens mosaic dataset
    This will work for siemens dti and 4D if in mosaic format
    """
    first_frame = multiframe_dicom[Tag(0x5200, 0x9230)][0]
    last_frame = multiframe_dicom[Tag(0x5200, 0x9230)][-1]
    # Create affine matrix (http://nipy.sourceforge.net/nibabel/dicom/dicom_orientation.html#dicom-slice-affine)
    image_orient1 = numpy.array(first_frame.PlaneOrientationSequence[0].ImageOrientationPatient)[0:3].astype(float)
    image_orient2 = numpy.array(first_frame.PlaneOrientationSequence[0].ImageOrientationPatient)[3:6].astype(float)

    normal = numpy.cross(image_orient1, image_orient2)

    delta_r = float(first_frame[0x2005, 0x140f][0].PixelSpacing[0])
    delta_c = float(first_frame[0x2005, 0x140f][0].PixelSpacing[1])

    image_pos = numpy.array(first_frame.PlanePositionSequence[0].ImagePositionPatient).astype(float)
    last_image_pos = numpy.array(last_frame.PlanePositionSequence[0].ImagePositionPatient).astype(float)

    number_of_stack_slices = int(common.get_ss_value(multiframe_dicom[Tag(0x2001, 0x105f)][0][Tag(0x2001, 0x102d)]))
    delta_s = abs(numpy.linalg.norm(last_image_pos - image_pos)) / (number_of_stack_slices - 1)

    return numpy.array(
        [[-image_orient1[0] * delta_c, -image_orient2[0] * delta_r, -delta_s * normal[0], -image_pos[0]],
         [-image_orient1[1] * delta_c, -image_orient2[1] * delta_r, -delta_s * normal[1], -image_pos[1]],
         [image_orient1[2] * delta_c, image_orient2[2] * delta_r, delta_s * normal[2], image_pos[2]],
         [0, 0, 0, 1]])
def _multiframe_to_block(multiframe_dicom):
    """
    Generate a full datablock containing all stacks
    """
    # Calculate the amount of stacks and slices in the stack
    number_of_stack_slices = int(common.get_ss_value(multiframe_dicom[Tag(0x2001, 0x105f)][0][Tag(0x2001, 0x102d)]))
    number_of_stacks = int(int(multiframe_dicom.NumberOfFrames) / number_of_stack_slices)

    # We create a numpy array
    size_x = multiframe_dicom.pixel_array.shape[2]
    size_y = multiframe_dicom.pixel_array.shape[1]
    size_z = number_of_stack_slices
    size_t = number_of_stacks
    # get the format
    format_string = common.get_numpy_type(multiframe_dicom)

    # get header info needed for ordering
    frame_info = multiframe_dicom[0x5200, 0x9230]

    data_4d = numpy.zeros((size_z, size_y, size_x, size_t), dtype=format_string)

    # loop over each slice and insert in datablock
    t_location_index = _get_t_position_index(multiframe_dicom)
    for slice_index in range(0, size_t * size_z):

        z_location = frame_info[slice_index].FrameContentSequence[0].InStackPositionNumber - 1
        if t_location_index is None:
            t_location = frame_info[slice_index].FrameContentSequence[0].TemporalPositionIndex - 1
        else:
            t_location = frame_info[slice_index].FrameContentSequence[0].DimensionIndexValues[t_location_index] - 1

        block_data = multiframe_dicom.pixel_array[slice_index, :, :]
        # apply scaling
        rescale_intercept = frame_info[slice_index].PixelValueTransformationSequence[0].RescaleIntercept
        rescale_slope = frame_info[slice_index].PixelValueTransformationSequence[0].RescaleSlope
        block_data = common.do_scaling(block_data,
                                       rescale_slope, rescale_intercept)
        # switch to float if needed
        if block_data.dtype != data_4d.dtype:
            data_4d = data_4d.astype(block_data.dtype)
        data_4d[z_location, :, :, t_location] = block_data

    full_block = numpy.zeros((size_x, size_y, size_z, size_t), dtype=data_4d.dtype)

    # loop over each stack and reorganize the data
    for t_index in range(0, size_t):
        # transpose the block so the directions are correct
        data_3d = numpy.transpose(data_4d[:, :, :, t_index], (2, 1, 0))
        # add the block the the full data
        full_block[:, :, :, t_index] = data_3d

    return full_block
Exemple #6
0
def _multiframe_to_block(multiframe_dicom):
    """
    Generate a full datablock containing all stacks
    """
    # Calculate the amount of stacks and slices in the stack
    number_of_stack_slices = int(common.get_ss_value(multiframe_dicom[Tag(0x2001, 0x105f)][0][Tag(0x2001, 0x102d)]))
    number_of_stacks = int(int(multiframe_dicom.NumberOfFrames) / number_of_stack_slices)

    # We create a numpy array
    size_x = multiframe_dicom.pixel_array.shape[2]
    size_y = multiframe_dicom.pixel_array.shape[1]
    size_z = number_of_stack_slices
    size_t = number_of_stacks
    # get the format
    format_string = common.get_numpy_type(multiframe_dicom)

    # get header info needed for ordering
    frame_info = multiframe_dicom[0x5200, 0x9230]

    data_4d = numpy.zeros((size_z, size_y, size_x, size_t), dtype=format_string)

    # loop over each slice and insert in datablock
    t_location_index = _get_t_position_index(multiframe_dicom)
    for slice_index in range(0, size_t * size_z):

        z_location = frame_info[slice_index].FrameContentSequence[0].InStackPositionNumber - 1
        if t_location_index is None:
            t_location = frame_info[slice_index].FrameContentSequence[0].TemporalPositionIndex - 1
        else:
            t_location = frame_info[slice_index].FrameContentSequence[0].DimensionIndexValues[t_location_index] - 1

        block_data = multiframe_dicom.pixel_array[slice_index, :, :]
        # apply scaling
        rescale_intercept = frame_info[slice_index].PixelValueTransformationSequence[0].RescaleIntercept
        rescale_slope = frame_info[slice_index].PixelValueTransformationSequence[0].RescaleSlope
        block_data = common.do_scaling(block_data,
                                       rescale_slope, rescale_intercept)
        # switch to float if needed
        if block_data.dtype != data_4d.dtype:
            data_4d = data_4d.astype(block_data.dtype)
        data_4d[z_location, :, :, t_location] = block_data

    full_block = numpy.zeros((size_x, size_y, size_z, size_t), dtype=data_4d.dtype)

    # loop over each stack and reorganize the data
    for t_index in range(0, size_t):
        # transpose the block so the directions are correct
        data_3d = numpy.transpose(data_4d[:, :, :, t_index], (2, 1, 0))
        # add the block the the full data
        full_block[:, :, :, t_index] = data_3d

    return full_block
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)
def _is_multiframe_4d(dicom_input):
    """
    Use this function to detect if a dicom series is a philips multiframe 4D dataset
    """
    # check if it is multi frame dicom
    if not common.is_multiframe_dicom(dicom_input):
        return False

    header = dicom_input[0]

    # check if there are multiple stacks
    number_of_stack_slices = common.get_ss_value(header[Tag(0x2001, 0x105f)][0][Tag(0x2001, 0x102d)])
    number_of_stacks = int(int(header.NumberOfFrames) / number_of_stack_slices)
    if number_of_stacks <= 1:
        return False

    return True
Exemple #9
0
def _is_multiframe_4d(dicom_input):
    """
    Use this function to detect if a dicom series is a philips multiframe 4D dataset
    """
    # check if it is multi frame dicom
    if not common.is_multiframe_dicom(dicom_input):
        return False

    header = dicom_input[0]

    # check if there are multiple stacks
    number_of_stack_slices = common.get_ss_value(header[Tag(0x2001, 0x105f)][0][Tag(0x2001, 0x102d)])
    number_of_stacks = int(int(header.NumberOfFrames) / number_of_stack_slices)
    if number_of_stacks <= 1:
        return False

    return True
def _is_multiframe_anatomical(dicom_input):
    """
    Use this function to detect if a dicom series is a philips multiframe anatomical dataset
    NOTE: Only the first slice will be checked so you can only provide an already sorted dicom directory
    (containing one series)
    """
    # check if it is multi frame dicom
    if not common.is_multiframe_dicom(dicom_input):
        return False

    header = dicom_input[0]

    # check if there are multiple stacks
    number_of_stack_slices = common.get_ss_value(header[Tag(0x2001, 0x105f)][0][Tag(0x2001, 0x102d)])
    number_of_stacks = int(int(header.NumberOfFrames) / number_of_stack_slices)

    if number_of_stacks > 1:
        return False

    return True
Exemple #11
0
def _is_multiframe_anatomical(dicom_input):
    """
    Use this function to detect if a dicom series is a philips multiframe anatomical dataset
    NOTE: Only the first slice will be checked so you can only provide an already sorted dicom directory
    (containing one series)
    """
    # check if it is multi frame dicom
    if not common.is_multiframe_dicom(dicom_input):
        return False

    header = dicom_input[0]

    # check if there are multiple stacks
    number_of_stack_slices = common.get_ss_value(header[Tag(0x2001, 0x105f)][0][Tag(0x2001, 0x102d)])
    number_of_stacks = int(int(header.NumberOfFrames) / number_of_stack_slices)

    if number_of_stacks > 1:
        return False

    return True
Exemple #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)