Exemplo n.º 1
0
def Save_Directory_Statistics(input_directory, ROI_directory, output_csv, mask=False, mask_suffix='_mask', r2_thresholds=[.9]):

    """ Save ROI statistics into a giant csv file.
    """

    # exclude_patients = ['CED_19', ]

    file_database = glob.glob(os.path.join(input_directory, '*blur*r2_' + str(r2_thresholds[0]) + '.nii*'))

    output_headers = ['filename','mean','median','min','max','std', 'total_voxels','removed_values', 'removed_percent', 'low_values', 'low_percent']

    ROI_dict = {}

    for ROI in glob.glob(os.path.join(ROI_directory, '*.nii*')):
        ROI_dict[os.path.basename(os.path.normpath(ROI))[0:15]] = convert_input_2_numpy(ROI)

    for r2 in r2_thresholds:

        output_data = np.zeros((1+len(file_database), len(output_headers)),dtype=object)
        output_data[0,:] = output_headers

        with open(replace_suffix(output_csv, '', '_' + str(r2)), 'wb') as writefile:
            csvfile = csv.writer(writefile, delimiter=',')
            csvfile.writerow(output_data[0,:])

            for row_idx, filename in enumerate(file_database):

                data_array = convert_input_2_numpy(filename)
                patient_visit_code = os.path.basename(os.path.normpath(filename))[0:15]
                roi_array = ROI_dict[patient_visit_code]

                r2_filename = str.split(filename, '_')
                r2_filename[-3] = 'r2'
                r2_filename = '_'.join(r2_filename)

                r2_array = convert_input_2_numpy(r2_filename)

                data_array[data_array<0] = -.01
                data_array[r2_array<=r2] = -.01
                data_array[roi_array<=0] = -.01
                masked_data_array_ROI = np.ma.masked_where(data_array < 0, data_array)

                ROI_values = [np.ma.mean(masked_data_array_ROI), 
                                np.ma.median(masked_data_array_ROI), 
                                np.ma.min(masked_data_array_ROI), 
                                np.ma.max(masked_data_array_ROI), 
                                np.ma.std(masked_data_array_ROI),
                                (roi_array > 0).sum(), 
                                ((data_array <= 0) & (roi_array > 0)).sum(),
                                float(((data_array <= 0) & (roi_array > 0)).sum()) / float((roi_array > 0).sum()), 
                                ((r2_array >= r2) & (roi_array > 0)).sum(), 
                                float(((r2_array >= r2) & (roi_array > 0)).sum()) / float((roi_array > 0).sum())]

                print ROI_values

                output_data[row_idx+1] = [filename] + ROI_values

                csvfile.writerow(output_data[row_idx+1])

    return
Exemplo n.º 2
0
def split_image(input_volume,
                input_label_volume=None,
                label_indices=None,
                mask_value=0):
    """ This function takes in an image, optionally a label image, and optionally a set of indices,
        and returns one duplicate masked image for each given label. Useful for analyzing,
        say, multiple tumors, although expensive in memory. Useful when paired with the
        truncate_image function to reduce array memory.
    """

    image_numpy = convert_input_2_numpy(input_volume)
    label_numpy = convert_input_2_numpy(input_label_volume)

    masked_images = []

    if label_indices is None:
        if label_numpy is None:
            label_indices = np.unique(image_numpy)
        else:
            label_indices = np.unique(label_numpy)

    if mask_value in label_indices:
        label_indices = np.delete(np.array(label_indices),
                                  np.argwhere(label_indices == mask_value))

    for idx in label_indices:
        masked_image = np.copy(image_numpy)
        masked_image[label_numpy != idx] = mask_value
        masked_images += [masked_image]

    return masked_images
Exemplo n.º 3
0
    def __init__(self,
                 dce_data,
                 ktrans_data,
                 ve_data,
                 n_samples=1000,
                 gaussian_noise=[0, 0]):

        self.completed = False

        dce_raw, ve_raw, ktrans_raw = convert_input_2_numpy(
            dce_data), convert_input_2_numpy(ve_data), convert_input_2_numpy(
                ktrans_data)

        # Minit Test
        # dce_raw, ve_raw, ktrans_raw = dce_raw[0:30,0:30,0:30,:], ve_raw[0:30,0:30,0:30], ktrans_raw[0:30,0:30,0:30]

        dce_numpy = dce_raw.reshape(-1, dce_raw.shape[-1])
        ve_numpy, ktrans_numpy = ve_raw.reshape(
            ve_raw.shape[0] * ve_raw.shape[1] *
            ve_raw.shape[2]), ktrans_raw.reshape(ktrans_raw.shape[0] *
                                                 ktrans_raw.shape[1] *
                                                 ktrans_raw.shape[2])

        self.dce_data = [dce_numpy, ktrans_numpy, ve_numpy]
        self.data_shape = ktrans_raw.shape
        self.voxel_count = ktrans_numpy.size

        self.batch_id = 0
Exemplo n.º 4
0
def Determine_R2_Cutoff_Point(input_directory, ROI_directory):
    """ Save ROI statistics into a giant csv file.
    """

    file_database = glob.glob(os.path.join(input_directory, '*.nii*'))

    output_headers = [
        'filename', 'mean', 'median', 'std', 'min', 'max', 'total_voxels',
        'removed_values', 'removed_percent', 'low_values', 'low_percent'
    ]

    output_data = np.zeros((1 + len(file_database), len(output_headers)),
                           dtype=object)
    output_data[0, :] = output_headers

    ROI_dict = {}

    for ROI in glob.glob(os.path.join(ROI_directory, '*.nii*')):
        ROI_dict[os.path.basename(
            os.path.normpath(ROI))[0:15]] = convert_input_2_numpy(ROI)

    r2_masked_num, r2_total_num = [0] * 100, [0] * 100

    np.set_printoptions(precision=2)
    np.set_printoptions(suppress=True)

    for row_idx, filename in enumerate(file_database):

        if 'ktrans' not in filename or '0.2' in filename:
            continue

        data_array = convert_input_2_numpy(filename)
        r2_array = convert_input_2_numpy(
            replace_suffix(filename,
                           input_suffix=None,
                           output_suffix='r2',
                           suffix_delimiter='_'))
        # print replace_suffix(filename, input_suffix=None, output_suffix='r2', suffix_delimiter='_')

        patient_visit_code = os.path.basename(os.path.normpath(filename))[0:15]
        roi_array = ROI_dict[patient_visit_code]

        for r2_idx, r2_threshold in enumerate(np.arange(0, 1, .01)):
            r2_masked_num[r2_idx] += ((r2_array <= r2_threshold) &
                                      (roi_array > 0)).sum()
            r2_total_num[r2_idx] += (roi_array > 0).sum()

        print(
            np.array(r2_masked_num, dtype=float) /
            np.array(r2_total_num, dtype=float))

    r2_percent_num = np.array(r2_masked_num, dtype=float) / np.array(
        r2_total_num, dtype=float)

    for r2_idx, r2_threshold in enumerate(range(0, 1, .01)):
        print(r2_threshold)
        print(r2_percent_num[r2_idx])

    return
Exemplo n.º 5
0
def Slicer_PkModeling(input_folder,
                      Slicer_path="/opt/Slicer-4.5.0-1-linux-amd64/Slicer"):

    # os.chdir('C:/Users/azb22/Documents/Scripting/DCE_Motion_Phantom')
    # input_folder = '.'
    # Slicer_path = 'C:/Users/azb22/Documents/Software/SlicerNightly/Slicer_4.6.0/Slicer.exe'

    Slicer_Command = Slicer_path + ' --launch'

    T1Blood = '--T1Blood 1440'
    T1Tissue = '--T1Tissue 1000'
    relaxivity = '--relaxivity .0045'
    hematocrit = '--hematocrit .45'
    BAT_mode = '--BATCalculationMode UseConstantBAT'
    BAT_arrival = '--constantBAT 8'
    aif_mask_command = '--aifMask '
    roi_mask_command = '--roiMask '
    t1_map_command = '--T1Map '

    # image_list = glob.glob(input_folder + '/*.nrrd')
    image_list = os.listdir(input_folder)

    for nrrd_image in image_list:

        if '.nrrd' in nrrd_image:

            move(nrrd_image, nrrd_image.replace(' ', ''))
            nrrd_image = nrrd_image.replace(' ', '')

            output_ktrans_image = str.split(nrrd_image,
                                            '.')[0] + '_ktrans.nii.gz'
            output_ve_image = str.split(nrrd_image, '.')[0] + '_ve.nii.gz'

            output_ktrans_command = '--outputKtrans ' + output_ktrans_image
            output_ve_command = '--outputVe ' + output_ve_image

            PkModeling_command = ' '.join([
                Slicer_Command, 'PkModeling', nrrd_image, T1Blood, T1Tissue,
                relaxivity, hematocrit, BAT_mode, BAT_arrival, '--usePopAif',
                output_ve_command, output_ktrans_command
            ])

            # call(PkModeling_command, shell=True)

            ktrans_array = convert_input_2_numpy(output_ktrans_image)
            ve_array = convert_input_2_numpy(output_ve_image)

            for z in range(ktrans_array.shape[-1]):
                ktrans_array[..., z] = medfilt(ktrans_array[..., z], [3, 3])
                ve_array[..., z] = medfilt(ve_array[..., z], [3, 3])

            ktrans_array[ve_array == 0] = .001
            ve_array[ve_array == 0] = .001

            save_numpy_2_nifti(ktrans_array, output_ktrans_image,
                               output_ktrans_image)
            save_numpy_2_nifti(ve_array, output_ve_image, output_ve_image)

    return
Exemplo n.º 6
0
def Preprocess_Volumes(input_directory, output_directory, r2_threshold=.9):

    if not os.path.exists(output_directory):
        os.mkdir(output_directory)

    file_database = glob.glob(os.path.join(input_directory, '*r2*.nii*'))
    print(os.path.join(input_directory, '*r2*.nii*'))

    for file in file_database:

        print(file)

        input_ktrans = replace_suffix(file, 'r2', 'ktrans')
        input_ve = replace_suffix(file, 'r2', 've')

        output_ktrans = os.path.join(
            output_directory,
            replace_suffix(os.path.basename(file), 'r2',
                           'ktrans_r2_' + str(r2_threshold)))
        output_ve = os.path.join(
            output_directory,
            replace_suffix(os.path.basename(file), 'r2',
                           've_r2_' + str(r2_threshold)))
        output_kep = os.path.join(
            output_directory,
            replace_suffix(os.path.basename(file), 'r2',
                           'kep_r2_' + str(r2_threshold)))
        output_r2 = os.path.join(
            output_directory,
            replace_suffix(os.path.basename(file), 'r2',
                           'r2_r2_' + str(r2_threshold)))

        print(input_ktrans)

        r2_map = np.nan_to_num(convert_input_2_numpy(file))
        ktrans_map = convert_input_2_numpy(input_ktrans)
        ve_map = convert_input_2_numpy(input_ve)

        print((r2_map < r2_threshold).sum())

        ve_map[ktrans_map > 10] = 0
        ktrans_map[ktrans_map > 10] = 0
        ktrans_map[ve_map > 1] = 0
        ve_map[ve_map > 1] = 0

        ktrans_map[r2_map < r2_threshold] = -.01
        ve_map[r2_map < r2_threshold] = -.01
        kep_map = np.nan_to_num(ktrans_map / ve_map)
        kep_map[r2_map < r2_threshold] = -.01

        save_numpy_2_nifti(ktrans_map, input_ktrans, output_ktrans)
        save_numpy_2_nifti(ve_map, input_ktrans, output_ve)
        save_numpy_2_nifti(kep_map, input_ktrans, output_kep)
        save_numpy_2_nifti(r2_map, input_ktrans, output_r2)
Exemplo n.º 7
0
def qtim_statistic(input_data, statistics, label_data='', mask_value=0, return_label=[], additional_parameters=''):

    """ TODO: Documentation. This should replace the existing statistics function for the feature extractor.
    """

    outputs = []
    if isinstance(statistics, str):
        statistics = [statistics,]

    input_numpy = convert_input_2_numpy(input_data)

    if label_data != '':
        input_numpy = crop_with_mask(input_numpy, label_data, mask_value=mask_value, return_labels=return_label)
    
    stats_numpy = np.ravel(input_numpy[input_numpy > mask_value])    

    for statistic in statistics:

        if statistics_dict[statistic] == []:
            print('No statistics by that keyword. Returning blank...')
            outputs += ['']

        try:
            outputs += [statistics_dict[statistic](stats_numpy)]
        except:
            outputs += ['NA']

    return outputs
Exemplo n.º 8
0
def intensity_range(input_volume, percentiles=[.25, .75]):
    """Retrieves a min and max of intensities at two specified percentiles on the intensity histogram.
    This could be useful for thresholding, normalizing, or other tasks. Likely redundant with existing
    numpy feature, TODO: remove
    
    Parameters
    ----------
    input_volume : filename or numpy array
        Input data. If not in an array, will attempt to convert to array.
    percentiles : list, optional
        Histogram percentiles to return. Default is [.25, .75]
    
    Returns
    -------
    list
        A two-item list of intensities at the given percentiles.
    """

    image_numpy = convert_input_2_numpy(input_volume)

    intensity_range = [
        np.percentile(image_numpy, percentiles[0], interpolation="nearest"),
        np.percentile(image_numpy, percentiles[1], interpolation="nearest")
    ]

    return intensity_range
Exemplo n.º 9
0
def minimum_bounding_box(data_directories,
                         modalities=['FLAIR_pp.nii.gz', 'T1post_pp.nii.gz']):

    max_dims = [0, 0, 0]

    patient_vols = []
    for directory in data_directories:
        patients = glob.glob(os.path.join(directory, '*/'))
        for patient in patients:
            single_patient_vols = []
            for modality in modalities:
                single_patient_vols += [
                    glob.glob(os.path.join(patient, modality))[0]
                ]
            patient_vols += [single_patient_vols]

    for p_idx, single_patient_vols in enumerate(patient_vols):

        for modality in single_patient_vols:

            array = convert_input_2_numpy(modality)
            # print array.shape
            cropped_array = crop2(array)
            # print cropped_array.shape

            for idx, dim in enumerate(max_dims):
                if cropped_array.shape[idx] > 200:
                    print idx, cropped_array.shape[idx]
                    print modality
                if cropped_array.shape[idx] > dim:
                    max_dims[idx] = cropped_array.shape[idx]

            # print max_dims

    print max_dims
Exemplo n.º 10
0
def Convert_NRRD_to_Nifti(input_4d_nrrd, reference_nifti):

    input_4d_numpy = convert_input_2_numpy(input_4d_nrrd)
    reference_nifti = reference_nifti

    create_4d_nifti_from_3d(input_4d_numpy, reference_nifti, os.path.splitext(input_4d_nrrd)[0] + '.nii.gz')

    return os.path.splitext(input_4d_nrrd)[0] + '.nii.gz'
Exemplo n.º 11
0
def Slicer_Rotate(input_numpy, reference_nifti, affine_matrix, Slicer_path="/opt/Slicer-4.5.0-1-linux-amd64/Slicer"):

    save_numpy_2_nifti(input_numpy, reference_nifti, 'temp.nii.gz')
    save_affine(affine_matrix, 'temp.txt')

    Slicer_Command = [Slicer_path, '--launch', 'ResampleScalarVectorDWIVolume', 'temp.nii.gz', 'temp_out.nii.gz', '-f', 'temp.txt', '-i', 'bs']

    call(' '.join(Slicer_Command), shell=True)

    return convert_input_2_numpy('temp_out.nii.gz')
Exemplo n.º 12
0
    def __init__(self, phantom_data_files, n_samples=1000, max_seq_len=65):

        self.data = []
        self.labels = []
        self.seqlen = []

        self.completed = False

        dce_phantoms = [
            convert_input_2_numpy(data) for data in phantom_data_files
        ]

        sample_per_phantom = n_samples / len(dce_phantoms)

        ktrans_values = np.array([.01, .02, .05, .1, .2, .5])
        ktrans_values = np.repeat(np.repeat(ktrans_values, 10)[:, np.newaxis],
                                  50,
                                  axis=1).T

        ve_values = np.array([.01, .05, .1, .2, .5])
        ve_values = np.repeat(np.repeat(ve_values, 10)[:, np.newaxis],
                              60,
                              axis=1)

        concentration_sample = list(np.ndindex(50, 60))
        aif_sample = list(np.ndindex(50, 10))

        indices = [(x, y) for x in concentration_sample for y in aif_sample]
        print ktrans_values.shape

        for phantom in dce_phantoms:

            seq_len = phantom.shape[-1]

            for i in range(sample_per_phantom):

                self.seqlen.append(seq_len)

                x, y = random.choice(indices)

                Intensity = phantom[x[0], x[1] + 10, :]
                AIF = phantom[y[0], y[1] + 70, :]

                ktrans = ktrans_values[x]
                ve = ve_values[x]

                s = []
                for idx in xrange(len(Intensity)):
                    s += [[Intensity[idx], AIF[idx]]]
                s += [[0., 0] for i in range(max_seq_len - seq_len)]

                self.data.append(s)
                self.labels.append([ktrans, ve])

        self.batch_id = 0
Exemplo n.º 13
0
def fill_in_convex_outline(input_data,
                           output_file=None,
                           reference_nifti=None,
                           threshold_limit=[0, 100],
                           color_threshold_limits=[[100, 300], [0, 100],
                                                   [0, 100]],
                           output_label_num=1):
    """ Thresholds a jpg according to certain color parameters. Uses a hole-filling algorithm to color in
        regions of interest.

        TODO: Reorganize into two separate tracks, instead of two winding tracks.
    """

    image_nifti, image_type = convert_input_2_numpy(input_data,
                                                    return_type=True)

    label_nifti = np.zeros_like(image_nifti)

    if image_type == 'image':

        red_range = np.logical_and(
            color_threshold_limits[0][0] < image_nifti[:, :, 0],
            image_nifti[:, :, 0] < color_threshold_limits[0][1])
        green_range = np.logical_and(
            color_threshold_limits[1][0] < image_nifti[:, :, 1],
            image_nifti[:, :, 1] < color_threshold_limits[1][1])
        blue_range = np.logical_and(
            color_threshold_limits[2][0] < image_nifti[:, :, 2],
            image_nifti[:, :, 2] < color_threshold_limits[2][1])
        valid_range = np.logical_and(red_range, green_range, blue_range)

        label_nifti[valid_range] = 1

        label_nifti = ndimage.morphology.binary_fill_holes(
            label_nifti[:, :, 0]).astype(label_nifti.dtype)

        if output_file is not None:
            misc.imsave(output_file, label_nifti * 255)

    else:
        image_nifti[image_nifti != 0] = output_label_num
        if image_nifti.ndim == 3:
            for z in range(image_nifti.shape[2]):
                label_nifti[..., z] = ndimage.morphology.binary_fill_holes(
                    image_nifti[..., z]).astype(image_nifti.dtype)
        else:
            label_nifti = ndimage.morphology.binary_fill_holes(
                image_nifti).astype(image_nifti.dtype)

        print(np.sum(label_nifti), 'HOLE FILLED SUM')

        if output_file is not None:
            save_numpy_2_nifti(label_nifti, reference_nifti, output_file)

    return label_nifti
Exemplo n.º 14
0
def calculate_prediction_dice(label_volume_1, label_volume_2):

    label_volume_1, label_volume_2, = convert_input_2_numpy(
        label_volume_1), convert_input_2_numpy(label_volume_2)

    im1 = np.asarray(label_volume_1).astype(np.bool)
    im2 = np.asarray(label_volume_2).astype(np.bool)

    if im1.shape != im2.shape:
        raise ValueError(
            "Shape mismatch: im1 and im2 must have the same shape.")

    im_sum = im1.sum() + im2.sum()
    if im_sum == 0:
        return empty_score

    # Compute Dice coefficient
    intersection = np.logical_and(im1, im2)

    return 2. * intersection.sum() / im_sum
Exemplo n.º 15
0
def extract_maximal_slice(input_volume,
                          input_label_volume='',
                          mode='max_intensity',
                          axis=2,
                          mask_value=0,
                          return_index=False):
    """ Extracts one slice from a presumably 3D volume. Either take the slice whose label
        has the greatest area (mode='max_label'), or whos sum of voxels has the greatest 
        intensity (mode='max_intensity'), according to the provided axis variable.
    """

    image_numpy = convert_input_2_numpy(input_volume)

    sum_dimensions = tuple(
        [int(x) for x in range(0, image_numpy.ndim) if x != axis])

    if mode == 'max_intensity':
        flattened_image = np.sum(image_numpy, axis=sum_dimensions)
    elif mode == 'max_label':
        label_numpy = convert_input_2_numpy(input_label_volume)
        flattened_image = np.sum(label_numpy, axis=sum_dimensions)
    elif mode == 'non_mask':
        flattened_image = (image_numpy != mask_value).sum(axis=sum_dimensions)
    else:
        print(
            'Invalid mode entered to extract_maximal_slice_3d. Returning original array..'
        )
        return image_numpy

    # TODO: Put in support for
    highest_slice_index = np.argmax(flattened_image)
    try:
        highest_slice_index = highest_slice_index[0]
    except:
        pass

    if return_index:
        return get_arbitrary_axis_slice(
            image_numpy, axis, highest_slice_index), highest_slice_index

    return get_arbitrary_axis_slice(image_numpy, axis, highest_slice_index)
Exemplo n.º 16
0
def Add_White_Noise(input_folder, noise_scale=1, noise_multiplier=10):

    input_niis = glob.glob(os.path.join(input_folder, '*Signal.nii*'))

    for input_4d_nifti in input_niis:

        input_numpy = convert_input_2_numpy(input_4d_nifti)

        for t in xrange(input_numpy.shape[-1]):
            input_numpy[..., t] = input_numpy[..., t] + np.random.normal(scale=noise_scale, size=input_numpy[..., t].shape).reshape(input_numpy[..., t].shape) * noise_multiplier

        save_numpy_2_nifti(input_numpy, input_4d_nifti, str.split(input_4d_nifti, '.')[0] + '_noise_' + str(noise_multiplier) +'.nii.gz')
Exemplo n.º 17
0
def truncate_image(input_volume,
                   mask_value=0,
                   return_mask=False,
                   padding=0,
                   output_mask_filename=""):
    """ This function takes in an N-dimensional array and truncates all rows/columns/etc
        that contain only mask values. Useful for reducing computation time on functions
        whose running time scales exponentially with dimensions size.

        BUG: Currently seems to fail on axes with length 1.
        TODO: Truncate only on some axes.
        TODO: Add the option to add buffer pixels to meet output_dimensions.

        Parameters
        ----------

        input_volume: N-dimensional array
            The volume to be truncated. Will be truncated in every axis.
        mask_value: int or float
            Vectors in an axis that are composed entirely of mask_value will be truncated.
    """

    image_numpy = convert_input_2_numpy(input_volume)

    dims = image_numpy.shape
    truncate_ranges = [[0, 0] for x in dims]

    for axis, axis_length in enumerate(dims):
        start_flag = True
        for idx in range(axis_length):
            if (get_arbitrary_axis_slice(image_numpy, axis,
                                         idx) == mask_value).all():
                if start_flag:
                    truncate_ranges[axis][0] = idx + 1
            else:
                start_flag = False
                truncate_ranges[axis][1] = idx + 1

    if padding > 0:
        truncate_ranges = [[
            max(0, x[0] - padding),
            min(dims[axis], x[1] + padding)
        ] for axis, x in enumerate(truncate_ranges)]

    truncate_slices = [slice(x[0], x[1]) for x in truncate_ranges]

    truncate_image_numpy = image_numpy[tuple(truncate_slices)]

    if return_mask:
        return truncate_image_numpy, mask_numpy
    else:
        return truncate_image_numpy
Exemplo n.º 18
0
    def get_shape(self):

        # TODO: Add support for non-nifti files.
        # Also this is not good. Perhaps specify shape in input?

        if self.output_shape is None:
            if self.data == []:
                return (0, )
            else:
                return convert_input_2_numpy(self.data[0][0]).shape + (len(
                    self.data[0]), )
        else:
            return self.output_shape
Exemplo n.º 19
0
def Add_Head_Jerks(input_folder, random_rotations=5, random_duration_range=[4,9], random_rotation_peaks=[[-4,4],[-4,4],[-4,4]], durations=7, timepoints=7, rotation_peaks=[4, 4, 0],):

    input_niis = glob.glob(os.path.join(input_folder, '*Signal*noise*'))
    print os.path.join(input_folder, '*Signal*noise*')
    input_niis = [x for x in input_niis if 'jerk' not in x]

    for input_4d_nifti in input_niis:

        print input_4d_nifti
        input_4d_numpy = convert_input_2_numpy(input_4d_nifti)
        print input_4d_numpy.shape
        output_motion_array = generate_identity_affine(input_4d_numpy.shape[-1])

        if random_rotations > 0:

            total_jerk_windows = []

            for random_rotation in xrange(random_rotations):

                # Will hang if more random_rotations are specified than can fit in available timepoints.
                overlapping = True
                while overlapping:
                    random_duration = np.random.randint(*random_duration_range)
                    random_timepoint = np.random.randint(0, input_4d_numpy.shape[-1]-random_duration)
                    random_jerk_window = np.arange(random_timepoint, random_timepoint + random_duration)
                    if not any(x in total_jerk_windows for x in random_jerk_window):
                        overlapping = False
                        total_jerk_windows.extend(random_jerk_window)

                random_motion = generate_motion_jerk(duration=random_duration, timepoint=random_timepoint, rotation_peaks=[np.random.randint(*random_rotation_peaks[0]),np.random.randint(*random_rotation_peaks[1]),np.random.randint(*random_rotation_peaks[2])], total_timepoints=input_4d_numpy.shape[-1])

                print random_motion.shape
                print output_motion_array.shape

                for t in xrange(input_4d_numpy.shape[-1]):
                    print output_motion_array[..., t]

                output_motion_array = compose_affines(output_motion_array, random_motion)

            output_4d_numpy = np.zeros_like(input_4d_numpy)

            for t in xrange(input_4d_numpy.shape[-1]):
                print output_motion_array[..., t]
                output_4d_numpy[..., t] = apply_affine(input_4d_numpy[...,t], output_motion_array[...,t], method='slicer', Slicer_path="C:/Users/azb22/Documents/Software/SlicerNightly/Slicer_4.6.0/Slicer.exe")

        else:
            pass

        save_numpy_2_nifti(output_4d_numpy, input_4d_nifti, str.split(input_4d_nifti, '.')[0] + '_jerk.nii.gz')
Exemplo n.º 20
0
    def __init__(self, phantom_data, gaussian_noise=[0, 0]):

        self.completed = False

        dce_raw = convert_input_2_numpy(phantom_data)

        self.aif = np.mean(dce_raw[:, 70:, :], axis=(0, 1))
        self.data_shape = dce_raw[..., 0].shape

        dce_numpy = dce_raw.reshape(-1, dce_raw.shape[-1])

        self.dce_data = dce_numpy
        self.voxel_count = dce_numpy[..., 0].size

        self.batch_id = 0
Exemplo n.º 21
0
def read_image_files(image_files, return_affine=False):

    # Rename this function to something more descriptive?

    image_list = []
    affine = None
    for image_file in image_files:
        image_list.append(convert_input_2_numpy(image_file))
        # if affine

    # This is a little clunky.
    if return_affine:
        # This assumes all images share an affine matrix.
        # Replace with a better convert function, at some point.
        return np.stack([image for image in image_list], axis=-1), nib.load(image_files[0]).affine
    else:
        return np.stack([image for image in image_list], axis=-1)
Exemplo n.º 22
0
def correlation_analysis(input_volume):

    image_numpy = convert_input_2_numpy(input_volume)

    displacement_list = np.mgrid[1:17:1, 1:17:1, 1:17:1].reshape(3, -1).T - 8

    output_correlation_matrix = np.zeros((17, 17, 17), dtype=float)

    for displacement in displacement_list:
        print displacement
        x, y, z = displacement
        slice_list = []
        displacement_slice_list = []

        for axis in [x, y, z]:
            if axis < 0:
                slice_list += [slice(-axis, None, 1)]
                displacement_slice_list += [slice(0, axis, 1)]
            elif axis > 0:
                slice_list += [slice(0, -axis, 1)]
                displacement_slice_list += [slice(axis, None, 1)]
            else:
                slice_list += [slice(None)]
                displacement_slice_list += [slice(None)]

        print slice_list
        print displacement_slice_list

        compare_array_1 = image_numpy[slice_list]
        compare_array_2 = image_numpy[displacement_slice_list]

        print compare_array_1.shape
        print compare_array_2.shape

        correlation = np.corrcoef(compare_array_1.reshape(-1),
                                  compare_array_2.reshape(-1))
        print correlation
        print '\n'

        output_correlation_matrix[x + 8, y + 8, z + 8] = correlation[1, 0]

    save_numpy_2_nifti(
        output_correlation_matrix, None,
        nifti_splitext(os.path.basename(input_volume))[0] + '_array' +
        nifti_splitext(os.path.basename(input_volume))[-1])
Exemplo n.º 23
0
def get_arbitrary_axis_slice(input_volume, axis, slice_num):
    """ Returns a slice of numpy array according to an arbitrary axis. This is a
        convencience function mostly because I find Python's slice notation a bit
        cumbersome.
    """

    image_numpy = convert_input_2_numpy(input_volume)

    image_slice = []

    for dim in xrange(image_numpy.ndim):
        if dim == axis:
            if slice_num is list:
                image_slice += [slice(slice_num[0], slice_num[1])]
            else:
                image_slice += [slice(slice_num, slice_num + 1)]
        else:
            image_slice += [slice(None)]

    return image_numpy[tuple(image_slice)]
Exemplo n.º 24
0
    def __init__(self,
                 dce_data,
                 ktrans_data,
                 ve_data,
                 n_samples=1000,
                 gaussian_noise=[0, 0],
                 reconstruct=False,
                 overwrite=False,
                 masked=True):

        self.data = []
        self.labels = []
        self.seqlen = []

        self.completed = False

        dce_raw, ve_raw, ktrans_raw = convert_input_2_numpy(
            dce_data), convert_input_2_numpy(ve_data), convert_input_2_numpy(
                ktrans_data)

        # Minit Test
        # dce_raw, ve_raw, ktrans_raw = dce_raw[0:30,0:30,0:30,:], ve_raw[0:30,0:30,0:30], ktrans_raw[0:30,0:30,0:30]

        dce_numpy = dce_raw.reshape(-1, dce_raw.shape[-1])
        ve_numpy, ktrans_numpy = ve_raw.reshape(
            ve_raw.shape[0] * ve_raw.shape[1] *
            ve_raw.shape[2]), ktrans_raw.reshape(ktrans_raw.shape[0] *
                                                 ktrans_raw.shape[1] *
                                                 ktrans_raw.shape[2])

        self.dce_data = [dce_numpy, ktrans_numpy, ve_numpy]
        self.data_shape = ktrans_raw.shape
        self.voxel_count = ktrans_numpy.size

        dce_seq_len = dce_numpy.shape[-1]
        dce_idx = np.arange(self.voxel_count)

        if masked:
            ktrans_high_mask = ktrans_numpy > .06
            ktrans_low_mask = ktrans_numpy <= .06
            dce_idx = dce_idx[ktrans_low_mask][0:int(np.ceil(
                2 * n_samples / 9))].tolist() + dce_idx[ktrans_high_mask][
                    0:int(np.ceil(7 * n_samples / 9)) + 1].tolist()

        # print np.min(ktrans_numpy), np.max(ktrans_numpy)

        for i in range(n_samples):

            # Random sequence length
            seq_len = dce_seq_len

            # Monitor sequence length for TensorFlow dynamic calculation
            self.seqlen.append(seq_len)

            Intensity = dce_numpy[dce_idx[i], :]
            ktrans = ktrans_numpy[dce_idx[i]]
            ve = ve_numpy[dce_idx[i]]

            s = Intensity
            s = [[i] for i in s]

            self.data.append(s)
            self.labels.append([ktrans, ve])

        self.batch_id = 0
Exemplo n.º 25
0
def Create_Ideal_DCE(input_folder, output_filepath = '', input_aif=''):

    input_DCEs = []
    input_niis = glob.glob(os.path.join(input_folder, '*nrrd'))

    for nii in input_niis:
        if 'ktrans' in nii or 've' in nii:
            continue
        else:
            input_DCEs += [nii]

    for input_4d_nifti in input_DCEs:

        print 'Regenerating... ', input_4d_nifti

        # if output_filepath == '':
        output_filepath = str.split(input_4d_nifti, '.')[0]

        input_ktrans = output_filepath + '_ktrans.nii.gz'
        input_ve = output_filepath + '_ve.nii.gz'

        input_4d_nifti = Convert_NRRD_to_Nifti(input_4d_nifti, input_ktrans)

        input_numpy_4d = convert_input_2_numpy(input_4d_nifti)
        output_numpy_4d = np.zeros_like(input_numpy_4d)
        input_numpy_ktrans = convert_input_2_numpy(input_ktrans)
        input_numpy_ve = convert_input_2_numpy(input_ve)

        baseline_numpy = np.mean(input_numpy_4d[..., 0:7], axis=3)

        scan_time_seconds = 307.2
        time_interval_seconds = float((scan_time_seconds) / input_numpy_4d.shape[-1])
        time_interval_minutes = time_interval_seconds/60
        time_series = np.arange(0, input_numpy_4d.shape[-1]) / (60 / time_interval_seconds)
        injection_start_time_seconds=38.4

        T1_tissue=1000
        T1_blood=1440
        TR=3.8
        flip_angle_degrees=25
        relaxivity=.0045
        hematocrit=.45

        if input_aif == '':
            population_AIF = parker_model_AIF(scan_time_seconds, injection_start_time_seconds, time_interval_seconds, input_numpy_4d)
            concentration_AIF = population_AIF
        else:
            print 'extracting AIF...'
            AIF_label_numpy = convert_input_2_numpy(input_aif)
            AIF = generate_AIF(scan_time_seconds, injection_start_time_seconds, time_interval_seconds, input_numpy_4d, AIF_label_numpy)
            concentration_AIF = convert_intensity_to_concentration(AIF, T1_tissue, TR, flip_angle_degrees, injection_start_time_seconds, relaxivity, time_interval_seconds, hematocrit, T1_blood=T1_blood)

        for index in np.ndindex(input_numpy_ktrans.shape):

            output_numpy_4d[index] = np.array(estimate_concentration([input_numpy_ktrans[index],input_numpy_ve[index]], concentration_AIF, time_interval_minutes))

        # Or load presaved..
        # output_numpy_4d = nifti_2_numpy('DCE_MRI_Phantom_Regenerated_Concentrations.nii.gz')

        save_numpy_2_nifti(output_numpy_4d, input_4d_nifti, output_filepath + '_Regenerated_Concentrations.nii.gz')

        output_numpy_4d = revert_concentration_to_intensity(data_numpy=output_numpy_4d, reference_data_numpy=input_numpy_4d, T1_tissue=T1_tissue, TR=TR, flip_angle_degrees=flip_angle_degrees, injection_start_time_seconds=injection_start_time_seconds, relaxivity=relaxivity, time_interval_seconds=time_interval_seconds, hematocrit=hematocrit, T1_blood=0, T1_map = [])

        save_numpy_2_nifti(output_numpy_4d, input_4d_nifti, output_filepath + '_Regenerated_Signal.nii.gz')

    return
Exemplo n.º 26
0
def return_connected_components(input_volume,
                                mask_value=0,
                                return_split=True,
                                truncate=False,
                                truncate_padding=0,
                                output_filepath=None):
    """ This function takes in an N-dimensional array and uses scikit-image's measure.label function
        to split it into individual connected components. One can either return a split version of
        the original label, which will be stackd in a new batch dimension (N, ...), or return a renumbered
        version of the original label. One can also choose to truncate the output of the original image,
        instead returning a list of arrays of different sizes.

        Parameters
        ----------

        input_volume: N-dimensional array
            The volume to be queried.
        mask_value: int or float
            Islands composed of "mask_value" will be ignored.
        return_split: bool
            Whether to a return a stacked output of equal-size binary arrays for each island,
            or to return one array with differently-labeled islands for each output.
        truncate: bool
            Whether or not to truncate the output. Irrelevant if return_split is False
        truncate_padding: int
            How many voxels of padding to leave when truncating.
        output_filepath: str
            If return_split is False, output will be saved to this file. If return_split
            is True, output will be save to this file with the suffix "_[#]" for island
            number

        Returns
        -------
        output_array: N+1 or N-dimensional array
            Output array(s) depending on return_split

    """

    image_numpy = convert_input_2_numpy(input_volume)

    connected_components = measure.label(image_numpy,
                                         background=mask_value,
                                         connectivity=2)

    if not return_split:
        if output_filepath is not None:
            save_numpy_2_nifti(connected_components, input_volume,
                               output_filepath)
        return connected_components

    else:
        all_islands = split_image(connected_components)
        for island in all_islands:
            all_islands[island] = truncate_image(
                island, truncate_padding=truncate_padding)

        if output_filepath is not None:
            for island_idx, island in enumerate(all_islands):
                save_numpy_2_nifti(
                    connected_components, input_volume,
                    replace_suffix(output_filepath, '', str(island_idx)))

        return all_islands
Exemplo n.º 27
0
def resample(input_data,
             output_filename='',
             input_transform=None,
             method="slicer",
             command="Slicer",
             temp_dir='./',
             interpolation='linear',
             dimensions=[1, 1, 1],
             reference_volume=None):
    """ A catch-all function for resampling. Will resample a 3D volume to given dimensions according
        to the method provided.

        TODO: Add resampling for 4D volumes.
        TODO: Add dimension, interpolation, reference parameter. Currently set to linear/isotropic.

        Parameters
        ----------
        input_data: str or array
            Can be a 3D volume or a filename.
        output_filename: str
            Location to save output data to. If left as '', will return numpy array.
        input_transform: str
            detatails TBD, unimplemented
        method: str
            Will perform motion correction according to the provided method.
            Currently available: ['fsl']
        command: str
            The literal command-line string to be inputted via Python's subprocess module.
        temp_dir: str
            If temporary files are created, they will be saved here.

        Returns
        -------
        output: array
            Output data, only if output_filename is left as ''.
    """

    skull_strip_methods = ['slicer']
    if method not in skull_strip_methods:
        print(
            'Input \"method\" parameter is not available. Available methods: ',
            skull_strip_methods)
        return

    if method == 'slicer':

        # A good reason to have a Class for qtim methods is to cut through all of this extra code.

        temp_input, temp_output = False, False

        if not isinstance(input_data, str):
            input_filename = os.path.join(temp_dir, 'temp.nii.gz')
            nifti_util.save_numpy_2_nifti(input_data, input_filename)
            temp_input = True
        else:
            input_filename = input_data

        if output_filename == '':
            temp_output = True
            output_filename = os.path.join(temp_dir, 'temp_out.nii.gz')

        dimensions = str(dimensions).strip('[]').replace(' ', '')

        if reference_volume or input_transform is not None:
            resample_command = [
                command, '--launch', 'ResampleScalarVectorDWIVolume',
                input_filename, output_filename, '-R', reference_volume,
                '--interpolation', interpolation
            ]
            if input_transform is not None:
                resample_command += ['-f', input_transform]
            print(' '.join(resample_command))
            subprocess.call(resample_command)
        else:
            resample_command = [
                command, '--launch', 'ResampleScalarVolume', '-i',
                interpolation, '-s', dimensions, input_filename,
                output_filename
            ]
            print(' '.join(resample_command))
            subprocess.call(resample_command)

        if temp_input:
            os.remove(input_filename)
            pass

        if temp_output:
            output = format_util.convert_input_2_numpy(output_filename)
            os.remove(output_filename)
            return output
Exemplo n.º 28
0
def download_slices(
        data_directories,
        output_filepath='mri_slice.hdf5',
        modalities=['FLAIR_pp.nii.gz', 'T1post_pp.nii.gz', 'T2_pp.nii.gz'],
        preload_levels=True,
        levels=[4, 8, 16, 32, 64, 128, 256],
        verbose=True):

    max_dims = [0, 0, 0]

    patient_vols = []
    for directory in data_directories:
        patients = glob.glob(os.path.join(directory, '*/'))
        for patient in patients:
            single_patient_vols = []
            for modality in modalities:
                single_patient_vols += [
                    glob.glob(os.path.join(patient, modality))[0]
                ]
            patient_vols += [single_patient_vols]

    num_cases = 120 * len(patient_vols)

    hdf5_file = tables.open_file(output_filepath, mode='w')
    filters = tables.Filters(complevel=5, complib='blosc')
    hdf5_file.create_earray(hdf5_file.root,
                            'imagenames',
                            tables.StringAtom(256),
                            shape=(0, 1),
                            filters=filters,
                            expectedrows=num_cases)

    # If we want to pre-store different levels...
    if preload_levels:
        for dimension in levels:
            data_shape = (0, dimension, dimension, 3)
            hdf5_file.create_earray(hdf5_file.root,
                                    'data_' + str(dimension),
                                    tables.Float32Atom(),
                                    shape=data_shape,
                                    filters=filters,
                                    expectedrows=num_cases)

    for p_idx, single_patient_vols in enumerate(patient_vols):

        filename = os.path.basename(os.path.dirname(single_patient_vols[0]))
        hdf5_file.root.imagenames.append(
            np.array(filename)[np.newaxis][np.newaxis])

        for dimension in levels:
            try:

                if verbose:
                    print 'Processing...', os.path.basename(
                        filename), 'at', dimension, ', idx', p_idx

                volumes = np.stack([
                    convert_input_2_numpy(vol) for vol in single_patient_vols
                ],
                                   axis=3)

                for z in xrange(volumes.shape[2]):

                    data = volumes[:, :, z, :]
                    data = imresize(data, (dimension, dimension))

                    getattr(hdf5_file.root,
                            'data_' + str(dimension)).append(data[np.newaxis])

            except KeyboardInterrupt:
                raise
            except:
                raise
                # print 'ERROR converting', filename, 'at dimension', dimension

    hdf5_file.close()
Exemplo n.º 29
0
def create_mosaic(input_volume,
                  outfile=None,
                  label_volume=None,
                  generate_outline=True,
                  mask_value=0,
                  step=1,
                  dim=2,
                  cols=8,
                  label_buffer=5,
                  rotate_90=3,
                  flip=True,
                  dpi=100):
    """This creates a mosaic of 2D images from a 3D Volume.
    
    Parameters
    ----------
    input_volume : TYPE
        Any neuroimaging file with a filetype supported by qtim_tools, or existing numpy array.
    outfile : None, optional
        Where to save your output, in a filetype supported by matplotlib (e.g. .png). If 
    label_volume : None, optional
        Whether to create your mosaic with an attached label filepath / numpy array. Will not perform volume transforms from header (yet)
    generate_outline : bool, optional
        If True, will generate outlines for label_volumes, instead of filled-in areas. Default is True.
    mask_value : int, optional
        Background value for label volumes. Default is 0.
    step : int, optional
        Will generate an image for every [step] slice. Default is 1.
    dim : int, optional
        Mosaic images will be sliced along this dimension. Default is 2, which often corresponds to axial.
    cols : int, optional
        How many columns in your output mosaic. Rows will be determined automatically. Default is 8.
    label_buffer : int, optional
        Images more than [label_buffer] slices away from a slice containing a label pixel will note be included. Default is 5.
    rotate_90 : int, optional
        If the output mosaic is incorrectly rotated, you may rotate clockwise [rotate_90] times. Default is 3.
    flip : bool, optional
        If the output is incorrectly flipped, you may set to True to flip the data. Default is True.
    
    No Longer Returned
    ------------------
    
    Returns
    -------
    output_array: N+1 or N-dimensional array
        The generated mosaic array.
    
    """

    image_numpy = convert_input_2_numpy(input_volume)
    if step is None:
        step = 1

    if label_volume is not None:

        label_numpy = convert_input_2_numpy(label_volume)

        if generate_outline:
            label_numpy = generate_label_outlines(label_numpy, dim, mask_value)

        # This is fun in a wacky way, but could probably be done more concisely and effeciently.
        mosaic_selections = []
        for i in range(label_numpy.shape[dim]):
            label_slice = np.squeeze(label_numpy[[
                slice(None) if k != dim else slice(i, i + 1) for k in range(3)
            ]])
            if np.sum(label_slice) != 0:
                mosaic_selections += list(
                    range(i - label_buffer, i + label_buffer))
        mosaic_selections = np.unique(mosaic_selections)
        mosaic_selections = mosaic_selections[mosaic_selections >= 0]
        mosaic_selections = mosaic_selections[
            mosaic_selections <= image_numpy.shape[dim]]
        mosaic_selections = mosaic_selections[::step]

        color_range_image = [np.min(image_numpy), np.max(image_numpy)]
        color_range_label = [np.min(label_numpy), np.max(label_numpy)]

        # One day, specify rotations by affine matrix.
        # Is test slice necessary? Operate directly on shape if possible.
        test_slice = np.rot90(
            np.squeeze(image_numpy[[
                slice(None) if k != dim else slice(0, 1) for k in range(3)
            ]]), rotate_90)
        slice_width = test_slice.shape[1]
        slice_height = test_slice.shape[0]

        mosaic_image_numpy = np.zeros(
            (int(slice_height *
                 np.ceil(float(len(mosaic_selections)) / float(cols))),
             int(test_slice.shape[1] * cols)),
            dtype=float)
        mosaic_label_numpy = np.zeros_like(mosaic_image_numpy)

        row_index = 0
        col_index = 0

        for i in mosaic_selections:
            image_slice = np.rot90(
                np.squeeze(image_numpy[[
                    slice(None) if k != dim else slice(i, i + 1)
                    for k in range(3)
                ]]), rotate_90)
            label_slice = np.rot90(
                np.squeeze(label_numpy[[
                    slice(None) if k != dim else slice(i, i + 1)
                    for k in range(3)
                ]]), rotate_90)

            # Again, specify from affine matrix if possible.
            if flip:
                image_slice = np.fliplr(image_slice)
                label_slice = np.fliplr(label_slice)

            if image_slice.size > 0:
                mosaic_image_numpy[
                    int(row_index):int(row_index + slice_height),
                    int(col_index):int(col_index + slice_width)] = image_slice
                mosaic_label_numpy[
                    int(row_index):int(row_index + slice_height),
                    int(col_index):int(col_index + slice_width)] = label_slice

            if col_index == mosaic_image_numpy.shape[1] - slice_width:
                col_index = 0
                row_index += slice_height
            else:
                col_index += slice_width

        mosaic_label_numpy = np.ma.masked_where(mosaic_label_numpy == 0,
                                                mosaic_label_numpy)

        if outfile is not None:
            fig = plt.figure(figsize=(mosaic_image_numpy.shape[0] / 100,
                                      mosaic_image_numpy.shape[1] / 100),
                             dpi=100,
                             frameon=False)
            plt.margins(0, 0)
            plt.gca().set_axis_off()
            plt.gca().xaxis.set_major_locator(plt.NullLocator())
            plt.gca().yaxis.set_major_locator(plt.NullLocator())
            plt.imshow(mosaic_image_numpy,
                       'gray',
                       vmin=color_range_image[0],
                       vmax=color_range_image[1],
                       interpolation='none')
            plt.imshow(mosaic_label_numpy,
                       'jet',
                       vmin=color_range_label[0],
                       vmax=color_range_label[1],
                       interpolation='none')

            plt.savefig(outfile, bbox_inches='tight', pad_inches=0.0, dpi=1000)
            plt.clf()
            plt.close()

        return mosaic_image_numpy

    else:

        color_range_image = [np.min(image_numpy), np.max(image_numpy)]

        test_slice = np.rot90(
            np.squeeze(image_numpy[[
                slice(None) if k != dim else slice(0, 1) for k in range(3)
            ]]), rotate_90)
        slice_width = test_slice.shape[1]
        slice_height = test_slice.shape[0]

        mosaic_selections = np.arange(image_numpy.shape[dim])[::step]
        mosaic_image_numpy = np.zeros(
            (int(slice_height *
                 np.ceil(float(len(mosaic_selections)) / float(cols))),
             int(test_slice.shape[1] * cols)),
            dtype=float)

        row_index = 0
        col_index = 0

        for i in mosaic_selections:
            image_slice = np.squeeze(image_numpy[[
                slice(None) if k != dim else slice(i, i + 1) for k in range(3)
            ]])

            image_slice = np.rot90(image_slice, rotate_90)

            if flip:
                image_slice = np.fliplr(image_slice)

            mosaic_image_numpy[int(row_index):int(row_index + slice_height),
                               int(col_index):int(col_index +
                                                  slice_width)] = image_slice

            if col_index == mosaic_image_numpy.shape[1] - slice_width:
                col_index = 0
                row_index += slice_height
            else:
                col_index += slice_width

        if outfile is not None:
            fig = plt.figure(figsize=(mosaic_image_numpy.shape[0] / 100,
                                      mosaic_image_numpy.shape[1] / 100),
                             dpi=100,
                             frameon=False)
            plt.margins(0, 0)
            plt.gca().set_axis_off()
            plt.gca().xaxis.set_major_locator(plt.NullLocator())
            plt.gca().yaxis.set_major_locator(plt.NullLocator())
            plt.imshow(mosaic_image_numpy,
                       'gray',
                       vmin=color_range_image[0],
                       vmax=color_range_image[1],
                       interpolation='none')

            plt.savefig(outfile, bbox_inches='tight', pad_inches=0.0, dpi=dpi)
            plt.clf()
            plt.close()

        return mosaic_image_numpy
Exemplo n.º 30
0
def store_preloaded_hdf5_file(
        data_directories,
        output_filepath,
        modalities=['FLAIR_pp.nii.gz', 'T1post_pp.nii.gz'],
        label='full_edemamask_pp.nii.gz',
        verbose=True,
        levels=[4, 8, 16, 32, 64, 128],
        boundary_padding=10,
        max_dimension=64,
        samples_per_patient=100,
        preload_levels=False,
        wholevolume=False):

    patient_vols = []
    for directory in data_directories:
        patients = glob.glob(os.path.join(directory, '*/'))
        for patient in patients:
            single_patient_vols = []
            for modality in modalities + [label]:
                if modality is None:
                    continue
                single_patient_vols += [
                    glob.glob(os.path.join(patient, modality))[0]
                ]
            patient_vols += [single_patient_vols]

    if wholevolume:
        num_cases = len(patient_vols)
    else:
        num_cases = len(modalities) * len(patient_vols)

    hdf5_file = tables.open_file(output_filepath, mode='w')
    filters = tables.Filters(complevel=5, complib='blosc')
    hdf5_file.create_earray(hdf5_file.root,
                            'imagenames',
                            tables.StringAtom(256),
                            shape=(0, 1),
                            filters=filters,
                            expectedrows=num_cases)

    # If we want to pre-store different levels...
    if preload_levels:
        for dimension in levels:
            data_shape = (0, dimension + boundary_padding,
                          dimension + boundary_padding,
                          dimension + boundary_padding, 2)
            hdf5_file.create_earray(hdf5_file.root,
                                    'data_' + str(dimension),
                                    tables.Float32Atom(),
                                    shape=data_shape,
                                    filters=filters,
                                    expectedrows=num_cases)
    else:
        # If we don't.
        if wholevolume:
            data_shape = (0, 200, 200, 200, len(modalities))
        else:
            data_shape = (0, max_dimension + boundary_padding,
                          max_dimension + boundary_padding,
                          max_dimension + boundary_padding, len(modalities))
        print data_shape
        hdf5_file.create_earray(hdf5_file.root,
                                'data',
                                tables.Float32Atom(),
                                shape=data_shape,
                                filters=filters,
                                expectedrows=num_cases)

    for p_idx, single_patient_vols in enumerate(patient_vols):

        hdf5_file.root.imagenames.append(
            np.array(os.path.basename(os.path.dirname(
                single_patient_vols[0])))[np.newaxis][np.newaxis])
        print os.path.basename(os.path.dirname(single_patient_vols[0]))

        if label is not None:
            # Find tumor label center of mass
            label = single_patient_vols[-1]
            label_numpy = convert_input_2_numpy(label)
            label_center = [int(x) for x in center_of_mass(label_numpy)]

            # Load volumes,
            volumes = np.stack([
                convert_input_2_numpy(vol) for vol in single_patient_vols[:-1]
            ],
                               axis=3)

            # pad if necessary, using black magic
            pad_dims = []
            radius = (max_dimension + boundary_padding) / 2
            for idx, dim in enumerate(volumes.shape[:-1]):
                padding = (-1 * min(0, label_center[idx] - radius),
                           -1 * min(0, dim - (label_center[idx] + radius)))
                pad_dims += [padding]
            pad_dims += [(0, 0)]
            print pad_dims
            volumes = np.pad(volumes, pad_dims, mode='constant')

            # and subsample, with more black magic ;)
            print label_center
            label_center = [
                x + pad_dims[i][0] for i, x in enumerate(label_center)
            ]
            print label_center
            print volumes.shape
            patch = volumes[label_center[0] - radius:label_center[0] + radius,
                            label_center[1] - radius:label_center[1] + radius,
                            label_center[2] - radius:label_center[2] +
                            radius, :]
            print patch.shape

            # Add to HDF5
            getattr(hdf5_file.root, 'data').append(patch[np.newaxis])

            save_numpy_2_nifti(
                patch[..., 1], single_patient_vols[0],
                os.path.join(os.path.dirname(single_patient_vols[0]),
                             'gan_patch.nii.gz'))

        elif wholevolume:

            # Load volumes,
            volumes = np.stack(
                [convert_input_2_numpy(vol) for vol in single_patient_vols],
                axis=3)

            # Crop volumes
            volumes = crop2(volumes)

            large = False

            # Skip strangely processed volumes
            for dim in volumes.shape:
                if dim > 200:
                    large = True

            if large:
                continue

            same_size_volume = np.zeros((200, 200, 200, len(modalities)))
            same_size_volume[0:volumes.shape[0], 0:volumes.shape[1],
                             0:volumes.shape[2], :] = volumes

            # Add to HDF5
            getattr(hdf5_file.root,
                    'data').append(same_size_volume[np.newaxis])

        else:

            # Generic MRI patching goes on here..

            continue

            if verbose:
                print 'Processed...', os.path.basename(
                    os.path.dirname(single_patient_vols[0])), 'idx', p_idx

        # except KeyboardInterrupt:
        #     raise
        # except:
        #     print 'ERROR converting', filepath, 'at dimension', dimension

    hdf5_file.close()

    return