예제 #1
0
def get_dti_features(image, mask, meta_data):
    i_mask_array = sitkh.GetArrayFromImage(mask)
    i_mask_array = i_mask_array.astype(np.bool)
    i_mask_array = i_mask_array.flatten()

    array_list = list()

    for i_dti in image:
        i_dti = sitkh.GetArrayFromImage(i_dti).flatten()
        i_dti = i_dti[i_mask_array]
        array_list.append(i_dti)

    i_image_array = np.vstack(array_list)

    # Adjust such that everything is positive, needed for log
    i_image_array = i_image_array + np.min(i_image_array) + 1

    b_values = meta_data['b_values']
    A = np.vstack([b_values, np.ones(len(b_values))]).T
    # Do least squares fit and get the slope, which is the ADC
    # This will give us the ADC in mm^2/s
    ADC_tumor_voxels = -np.linalg.lstsq(A, np.log(i_image_array))[0][0, :]

    ADC_mean = np.mean(ADC_tumor_voxels)
    ADC_std = np.std(ADC_tumor_voxels)
    ADC_min = np.min(ADC_tumor_voxels)
    ADC_max = np.max(ADC_tumor_voxels)

    dti_features = [ADC_mean, ADC_std, ADC_min, ADC_max]
    dti_labels = ['ADC_mean', 'ADC_std', 'ADC_min', 'ADC_max']

    return dti_features, dti_labels
예제 #2
0
def getfeatureimages(image,
                     segmentation,
                     gabor_settings=None,
                     image_type=None,
                     parameters=None,
                     types=['LBP'],
                     slicenum=None,
                     save=False):

    if parameters is not None:
        # Load variables from the confilg file
        config = config_io.load_config(parameters)

        # Calculate the image features
        gabor_settings = config['ImageFeatures']['gabor_settings']
        image_type = config['ImageFeatures']['image_type']

    print('Calculating image features!')
    image_data = load_images(image, image_type, None, None)

    if type(segmentation) is list:
        segmentation = ''.join(segmentation)
    contours = [sitk.ReadImage(segmentation)]

    # FIXME: Bug in some of our own segmentations
    szi = image_data['images'][0].GetSize()
    szs = contours[0].GetSize()
    if szi != szs:
        message = ('Shapes of image({}) and mask ({}) do not match!').format(
            str(szi), str(szs))
        print message
        # FIXME: Now excluding last slice
        c = contours[0]
        c = sitk.GetArrayFromImage(c)
        c = c[0:-1, :, :]
        contours = [sitk.GetImageFromArray(c)]

        szs = contours[0].GetSize()
        if szi != szs:
            message = (
                'Shapes of image({}) and mask ({}) do not match!').format(
                    str(szi), str(szs))
            raise IndexError(message)
        else:
            print("['FIXED'] Excluded last slice.")

    # Convert to arrays and get only masked slices
    i_image = image_data['images'][0]
    i_mask = contours[0]
    i_image_array = sitkh.GetArrayFromImage(i_image)
    i_mask_array = sitkh.GetArrayFromImage(i_mask)
    i_image_array, i_mask_array = ih.get_masked_slices_image(
        i_image_array, i_mask_array)

    if slicenum is None:
        slicenum = int(i_image_array.shape[2] / 2)

    i_image_array = np.squeeze(i_image_array[:, :, slicenum])
    i_mask_array = np.squeeze(i_mask_array[:, :, slicenum])

    if save:
        filename, file_extension = os.path.splitext('/path/to/somefile.ext')
    else:
        filename = None

    im = list()
    if 'LBP' in types:
        LBP_im = save_LBP_features(i_image_array, i_mask_array, filename)
        im.append(LBP_im)
    if 'Gabor' in types:
        Gabor_im = save_gabor_features(i_image_array, i_mask_array,
                                       gabor_settings, filename)
        im.append(Gabor_im)
    if 'Shape' in types:
        im.append(i_mask_array)
    if 'Histogram' in types:
        im.append(i_image_array)

    return im
예제 #3
0
def get_dti_post_features(image, mask, meta_data):
    i_mask_array = sitkh.GetArrayFromImage(mask)
    i_mask_array = i_mask_array.astype(np.bool)
    i_mask_array = i_mask_array.flatten()

    L1_image = sitkh.GetArrayFromImage(image[0]).flatten()
    L2_image = sitkh.GetArrayFromImage(image[1]).flatten()
    L3_image = sitkh.GetArrayFromImage(image[2]).flatten()

    L1_image = L1_image[i_mask_array]
    L2_image = L2_image[i_mask_array]
    L3_image = L3_image[i_mask_array]

    # A small fix because sometimes the eigenvalues are just below/around 0
    # And will give error in division.

    if np.amin(L1_image) <= 0:
        L1_image = L1_image + np.abs(np.amin(L1_image)) + 0.00001
    if np.amin(L2_image) <= 0:
        L2_image = L2_image + np.abs(np.amin(L2_image)) + 0.00001
    if np.amin(L3_image) <= 0:
        L3_image = L3_image + np.abs(np.amin(L3_image)) + 0.00001

    ADC_map = (L1_image + L2_image + L3_image) / 3.0

    # ADC map is also mean diffusivity
    FA_numerator = 3.0 * ((L1_image - ADC_map)**2.0 +
                          (L2_image - ADC_map)**2.0 +
                          (L3_image - ADC_map)**2.0)
    FA_denominator = 2.0 * (L1_image**2.0 + L2_image**2.0 + L3_image**2.0)
    FA_map = np.sqrt(FA_numerator / FA_denominator)

    # print(min(L2_image))
    # print(min(L3_image))

    # Also volume ratio
    VR_map = 1.0 - L1_image * L2_image * L3_image / ADC_map**3.0

    # Now get inside tumor

    # ADC_tumor = ADC_map[i_mask_array]
    # FA_tumor = FA_map[i_mask_array]
    # VR_tumor = VR_map[i_mask_array]

    ADC_min, ADC_max, ADC_mean, ADC_std, ADC_median, ADC_skew, ADC_kurtosis, ADC_range =\
        get_statistical_moments(ADC_map)

    FA_min, FA_max, FA_mean, FA_std, FA_median, FA_skew, FA_kurtosis, FA_range =\
        get_statistical_moments(FA_map)

    VR_min, VR_max, VR_mean, VR_std, VR_median, VR_skew, VR_kurtosis, VR_range =\
        get_statistical_moments(VR_map)

    # dti_features = [ADC_min, ADC_max, ADC_mean, ADC_std, ADC_median, ADC_skew, ADC_kurtosis, ADC_range,
    #                 FA_min, FA_max, FA_mean, FA_std, FA_median, FA_skew, FA_kurtosis, FA_range,
    #                 VR_min, VR_max, VR_mean, VR_std, VR_median, VR_skew, VR_kurtosis, VR_range]
    #
    # panda_labels = ['ADC_min', 'ADC_max', 'ADC_mean', 'ADC_std', 'ADC_median', 'ADC_skew', 'ADC_kurtosis', 'ADC_range',
    #                 'FA_min', 'FA_max', 'FA_mean', 'FA_std', 'FA_median', 'FA_skew', 'FA_kurtosis', 'FA_range',
    #                 'VR_min', 'VR_max', 'VR_mean', 'VR_std', 'VR_median', 'VR_skew', 'VR_kurtosis', 'VR_range']

    dti_features = [
        ADC_min, ADC_max, ADC_mean, ADC_std, ADC_median, ADC_skew,
        ADC_kurtosis, ADC_range
    ]

    dti_labels = [
        'ADC_min', 'ADC_max', 'ADC_mean', 'ADC_std', 'ADC_median', 'ADC_skew',
        'ADC_kurtosis', 'ADC_range'
    ]

    return dti_features, dti_labels
예제 #4
0
def get_shape_features_2D(mask, metadata=None):
    # Pre-allocation
    perimeter = list()
    convexity = list()
    area = list()
    rad_dist_avg = list()
    rad_dist_std = list()
    roughness_avg = list()
    roughness_std = list()
    cvar = list()
    prax = list()
    evar = list()
    solidity = list()
    compactness = list()
    rad_dist = list()
    rad_dist_norm = list()
    roughness = list()

    # Now calculate some of the edge shape features
    # NOTE: Due to conversion to array, first and third axis are switched
    mask = sitkh.GetArrayFromImage(mask)
    N_mask_slices = mask.shape[2]
    mask = label(mask, connectivity=3)
    for i_slice in range(0, N_mask_slices):
        # Iterate over all slices
        slicie = mask[:, :, i_slice]

        for nblob in range(0, np.max(slicie)):
            blobimage = np.zeros(slicie.shape)
            blobimage[slicie == nblob] = 1

            if np.sum(blobimage) == 0:
                # No points in volume, therefore we ignore it.
                continue

            blobimage = blobimage.astype(np.uint8)
            blobimage = sitk.GetImageFromArray(blobimage)

            # Iterate over all blobs in a slice
            boundary_points = cf.get_smooth_contour(blobimage,
                                                    N_min_smooth,
                                                    N_max_smooth)
            if boundary_points.shape[0] <= 3:
                # Only 1 or 2 points in volume, which means it's not really a
                # volume, therefore we ignore it.
                continue

            rad_dist_i, rad_dist_norm_i = compute_radial_distance(
                boundary_points)
            rad_dist.append(rad_dist_i)
            rad_dist_norm.append(rad_dist_norm_i)
            perimeter.append(compute_perimeter(boundary_points))

            area.append(compute_area(boundary_points))
            compactness.append(compute_compactness(boundary_points))
            roughness_i, roughness_avg_temp = compute_roughness(
                boundary_points, rad_dist_i)
            roughness_avg.append(roughness_avg_temp)
            roughness.append(roughness_i)

            cvar.append(compute_cvar(boundary_points))
            prax.append(compute_prax(boundary_points))
            evar.append(compute_evar(boundary_points))

            # TODO: Move computing convexity into esf
            convex_hull = cf.convex_hull(blobimage)
            convexity.append(compute_perimeter(convex_hull)
                / perimeter[-1])

            solidity.append(compute_area(convex_hull)/area[-1])
            rad_dist_avg.append(np.mean(np.asarray(rad_dist_i)))
            rad_dist_std.append(np.std(np.asarray(rad_dist_i)))
            roughness_std.append(np.std(np.asarray(roughness_i)))

    compactness_avg = np.mean(compactness)
    compactness_std = np.std(compactness)
    convexity_avg = np.mean(convexity)
    convexity_std = np.std(convexity)
    rad_dist_avg = np.mean(rad_dist_avg)
    rad_dist_std = np.mean(rad_dist_std)
    roughness_avg = np.mean(roughness_avg)
    roughness_std = np.mean(roughness_std)
    cvar_avg = np.mean(cvar)
    cvar_std = np.std(cvar)
    prax_avg = np.mean(prax)
    prax_std = np.std(prax)
    evar_avg = np.mean(evar)
    evar_std = np.std(evar)
    solidity_avg = np.mean(solidity)
    solidity_std = np.std(solidity)

    shape_labels = ['sf_compactness_avg', 'sf_compactness_std', 'sf_rad_dist_avg',
                    'sf_rad_dist_std', 'sf_roughness_avg', 'sf_roughness_std',
                    'sf_convexity_avg', 'sf_convexity_std', 'sf_cvar_avg', 'sf_cvar_std',
                    'sf_prax_avg', 'sf_prax_std', 'sf_evar_avg', 'sf_evar_std',
                    'sf_solidity_avg', 'sf_solidity_std']

    shape_features = [compactness_avg, compactness_std, rad_dist_avg,
                      rad_dist_std, roughness_avg, roughness_std,
                      convexity_avg, convexity_std, cvar_avg, cvar_std,
                      prax_avg, prax_std, evar_avg, evar_std, solidity_avg,
                      solidity_std]

    if metadata is not None:
        if (0x18, 0x50) in metadata.keys():
            # import dicom as pydicom
            # metadata = pydicom.read_file(metadata)
            pixel_spacing = metadata[0x28, 0x30].value
            slice_thickness = int(metadata[0x18, 0x50].value)
            voxel_volume = pixel_spacing[0] * pixel_spacing[1] * slice_thickness
            volume = np.sum(mask) * voxel_volume
            shape_labels.append('sf_volume')
            shape_features.append(volume)

    return shape_features, shape_labels
예제 #5
0
def get_image_features(image_data,
                       masks,
                       parameters,
                       mask_index=-1,
                       multi_mask=False,
                       config=None,
                       output=None):
    if type(image_data) == pd.core.frame.DataFrame:
        images = image_data['images']
        image_types = image_data['images'].keys()
        meta_data = image_data['metadata']
        sem_data = image_data['semantics']
        N_images = len(image_data.images)
    else:
        # Dictionary
        images = image_data['images']
        image_types = image_data['image_type']
        meta_data = image_data['metadata']
        sem_data = image_data['semantics']
        N_images = len(images)

    N_masks = len(masks)
    feature_values = list()
    feature_labels = list()

    if ~multi_mask and mask_index == -1:
        raise ValueError('Multi_mask was set to False, but no mask index was\
                         provided')

    if multi_mask and N_images != N_masks:
        raise ValueError('Multi_contour was set to True, but the number of\
                         contours does not match the number of images')

    if multi_mask:
        pass
    else:
        shape_mask = ih.get_masked_slices_mask(masks[mask_index])

        print("Computing shape features.")
        shape_features, shape_labels = sf.get_shape_features(
            shape_mask, meta_data[0])
        feature_values += shape_features
        feature_labels += shape_labels

        if config["orientation"]:
            print("Computing orientation features.")
            orientation_features, orientation_labels =\
                of.get_orientation_features(shape_mask)
            feature_values += orientation_features
            feature_labels += orientation_labels

    if meta_data[0] is not None:
        print("Extracting patient features.")
        patient_features, patient_labels =\
            pf.get_patient_features(meta_data[0], image_types[0])
        feature_values += patient_features
        feature_labels += patient_labels

    if sem_data[0] is not None and output is not None:
        print("Extracting semantic features.")
        sem_features, sem_labels = semf.get_semantic_features(
            sem_data[0], output)
        feature_values += sem_features
        feature_labels += sem_labels

    for i_image, i_mask, i_image_type, i_meta_data in zip(
            images, masks, image_types, meta_data):
        if 'MR' in i_image_type:
            i_image_array = sitkh.GetArrayFromImage(i_image)
            i_mask_array = sitkh.GetArrayFromImage(i_mask)

            masked_voxels = ih.get_masked_voxels(i_image_array, i_mask_array)

            print("Computing histogram features.")
            histogram_features, histogram_labels =\
                hf.get_histogram_features(masked_voxels,
                                          N_BINS)

            i_image_array, i_mask_array = ih.get_masked_slices_image(
                i_image_array, i_mask_array)

            print("Computing texture features.")
            texture_features, texture_labels =\
                tf.get_texture_features(i_image_array,
                                        i_mask_array,
                                        parameters,
                                        config['texture'])

            feature_values += histogram_features + texture_features
            feature_labels += histogram_labels + texture_labels

            if config["coliage"]:
                print("Computing coliage features.")
                coliage_features, coliage_labels =\
                    cf.get_coliage_features(i_image_array,
                                            i_mask_array)
                feature_values += coliage_features
                feature_labels += coliage_labels

            if config["vessel"]:
                print("Computing vessel features.")
                vessel_features, vessel_labels =\
                    vesf.get_vessel_features(i_image_array,
                                             i_mask_array,
                                             parameters['vessel'])
                feature_values += vessel_features
                feature_labels += vessel_labels

            if config["log"]:
                print("Computing log features.")
                log_features, log_labels =\
                    logf.get_log_features(i_image_array,
                                          i_mask_array,
                                          parameters['log'])
                feature_values += log_features
                feature_labels += log_labels

            if config["phase"]:
                print("Computing phase features.")
                phase_features, phase_labels =\
                    phasef.get_phase_features(i_image_array,
                                              i_mask_array,
                                              parameters['phase'])
                feature_values += phase_features
                feature_labels += phase_labels

        elif 'DTI_post' in i_image_type:
            dti_features, dti_labels = dtif.get_dti_post_features(
                i_image, i_mask, i_meta_data)
            feature_values += dti_features
            feature_labels += dti_labels

        elif 'DTI' in i_image_type:
            dti_features, dti_labels = dtif.get_dti_features(
                i_image, i_mask, i_meta_data)
            feature_values += dti_features
            feature_labels += dti_labels

        elif 'CT' in i_image_type:
            i_image_array = sitkh.GetArrayFromImage(i_image)
            i_mask_array = sitkh.GetArrayFromImage(i_mask)

            masked_voxels = ih.get_masked_voxels(i_image_array, i_mask_array)

            print("Computing histogram features.")
            histogram_features, histogram_labels =\
                hf.get_histogram_features(masked_voxels,
                                          N_BINS)

            i_image_array, i_mask_array = ih.get_masked_slices_image(
                i_image_array, i_mask_array)

            print("Computing texture features.")
            texture_features, texture_labels =\
                tf.get_texture_features(i_image_array,
                                        i_mask_array,
                                        parameters,
                                        config['texture'])

            feature_values += histogram_features + texture_features
            feature_labels += histogram_labels + texture_labels

            if config["coliage"]:
                print("Computing coliage features.")
                coliage_features, coliage_labels =\
                    cf.get_coliage_features(i_image_array,
                                            i_mask_array)
                feature_values += coliage_features
                feature_labels += coliage_labels

            if config["vessel"]:
                print("Computing vessel features.")
                vessel_features, vessel_labels =\
                    vesf.get_vessel_features(i_image_array,
                                             i_mask_array,
                                             parameters['vessel'])
                feature_values += vessel_features
                feature_labels += vessel_labels

            if config["log"]:
                print("Computing log features.")
                log_features, log_labels =\
                    logf.get_log_features(i_image_array,
                                          i_mask_array,
                                          parameters['log'])
                feature_values += log_features
                feature_labels += log_labels

            if config["phase"]:
                print("Computing phase features.")
                phase_features, phase_labels =\
                    phasef.get_phase_features(i_image_array,
                                              i_mask_array,
                                              parameters['phase'])
                feature_values += phase_features
                feature_labels += phase_labels

        else:
            print("Invalid image type: {}").format(i_image_type)
            raise TypeError

    return feature_values, feature_labels
예제 #6
0
def get_image_features(image_data,
                       masks,
                       gabor_settings,
                       mask_index=-1,
                       multi_mask=False,
                       config=None,
                       output=None):

    if type(image_data) == pd.core.frame.DataFrame:
        images = image_data['images']
        image_types = image_data['images'].keys()
        meta_data = image_data['metadata']
        sem_data = image_data['semantics']
        N_images = len(image_data.images)
    else:
        # Dictionary
        images = image_data['images']
        image_types = image_data['image_type']
        meta_data = image_data['metadata']
        sem_data = image_data['semantics']
        N_images = len(images)

    N_masks = len(masks)
    image_features = dict()

    if ~multi_mask and mask_index == -1:
        raise ValueError('Multi_mask was set to False, but no mask index was\
                         provided')

    if multi_mask and N_images != N_masks:
        raise ValueError('Multi_contour was set to True, but the number of\
                         contours does not match the number of images')

    if multi_mask:
        pass
    else:
        shape_mask = ih.get_masked_slices_mask(masks[mask_index])

        shape_features = sf.get_shape_features(shape_mask, meta_data[0])

        if config["orientation"]:
            orientation_features = of.get_orientation_features(shape_mask)
            image_features['orientation_features'] = orientation_features

    image_features['shape_features'] = shape_features

    if meta_data[0] is not None:
        patient_features = pf.get_patient_features(meta_data[0],
                                                   image_types[0])
        image_features['patient_features'] = patient_features

    if sem_data[0] is not None and output is not None:
        sem_features = semf.get_semantic_features(sem_data[0], output)
        image_features['semantic_features'] = sem_features

    for i_image, i_mask, i_image_type, i_meta_data in zip(
            images, masks, image_types, meta_data):
        if 'MR' in i_image_type:
            i_image_array = sitkh.GetArrayFromImage(i_image)
            i_mask_array = sitkh.GetArrayFromImage(i_mask)

            masked_voxels = ih.get_masked_voxels(i_image_array, i_mask_array)

            histogram_features = hf.get_histogram_features(
                masked_voxels, N_BINS)

            i_image_array, i_mask_array = ih.get_masked_slices_image(
                i_image_array, i_mask_array)

            texture_features = tf.get_texture_features(i_image_array,
                                                       i_mask_array,
                                                       gabor_settings,
                                                       config['texture'])

            coliage_features = cf.get_coliage_featues(i_image_array,
                                                      i_mask_array)
            # filter_features = ff.get_filter_features(i_image_array,
            #                                          i_mask_array)

            # image_features[i_image_type] =\
            #     pd.concat([histogram_features, texture_features],
            #               keys=['histogram_features', 'texture_features'])
            image_features['histogram_features'] = histogram_features
            image_features['texture_features'] = texture_features
            image_features['coliage_features'] = coliage_features
            # image_features['filter_features'] = filter_features
            # image_features[i_image_type] = histogram_features

        elif 'DTI_post' in i_image_type:
            dti_features = dtif.get_dti_post_features(i_image, i_mask,
                                                      i_meta_data)
            image_features[i_image_type] = dti_features
        elif 'DTI' in i_image_type:
            dti_features = dtif.get_dti_features(i_image, i_mask, i_meta_data)
            image_features[i_image_type] = dti_features
        elif 'CT' in i_image_type:
            i_image_array = sitkh.GetArrayFromImage(i_image)
            i_mask_array = sitkh.GetArrayFromImage(i_mask)

            masked_voxels = ih.get_masked_voxels(i_image_array, i_mask_array)

            histogram_features = hf.get_histogram_features(
                masked_voxels, N_BINS)

            i_image_array, i_mask_array = ih.get_masked_slices_image(
                i_image_array, i_mask_array)

            texture_features = tf.get_texture_features(i_image_array,
                                                       i_mask_array,
                                                       gabor_settings,
                                                       config['texture'])

            coliage_features = cf.get_coliage_featues(i_image_array,
                                                      i_mask_array)

            # filter_features = ff.get_filter_features(i_image_array,
            #                                          i_mask_array)

            # image_features[i_image_type] = histogram_features
            image_features['histogram_features'] = histogram_features
            image_features['texture_features'] = texture_features
            image_features['coliage_features'] = coliage_features
            # image_features['filter_features'] = filter_features
        else:
            print("Invalid image type: {}").format(i_image_type)
            raise TypeError

    # We also return just the arrray
    image_feature_array = list()

    for _, feattype in image_features.iteritems():
        for _, features in feattype.iteritems():
            image_feature_array.extend(features.values)

    print image_feature_array

    image_feature_array = np.asarray(image_feature_array)
    image_feature_array = image_feature_array.ravel()

    return image_features, image_feature_array
예제 #7
0
def get_image_features(image_data,
                       mask,
                       parameters,
                       config=None,
                       config_general=None,
                       output=None):
    '''
    Calculate features from a ROI of an image.

    Parameters
    ----------
    image_data: Pandas DataFrame or dictionary, mandatory
            Contains the image, image type, metadata and semantics for
            the feature extraction. These have to be indexed by these keys.

            Should either be a Pandas DataFrame, in which the image type is
            he key of the images, or a dictionary, in which image type is a
            a separate field.

            The image should be a SimpleITK Image, the image type a string,
            the metadata a pydicom dicom type and the semantics a dictionary.


    mask: ITK Image, mandatory
            ROI to be used for feature extraction.

    parameters: dictionary, mandatory,
            Parameters for feature calculation. See the Github Wiki for the possible
            fields and their description.

    config: dictionary, mandatory
            Configuration for feature calculation. Mostly configures which
            features are calculated or not. See the Github Wiki for the possible
            fields and their description.

    config_general: dictionary, mandatory
            Configuration for general settings. Currently only configures
            settings for the Joblib Parallel function. See the Github Wiki
            for the possible fields and their description.

    output: string, mandatory
            path referring to the .hdf5 file to which the output should be
            written for the CalcFeatures function. This field is used to match
            the patient ID of the semantic features to this filename.


    Returns
    ----------
    feature_values: list
            Contains the values for all extracted features.

    feature_labels: list
            Contains the labels for all extracted features. Each entry
            corresponds to the element with the same index from the
            feature_values object.

    '''

    # Assign data to correct variables
    if type(image_data) == pd.core.frame.DataFrame:
        image_type = image_data['images'].keys()[0]
        meta_data = image_data['metadata']
        sem_data = image_data['semantics']
        image_data = image_data['images']
    else:
        # Dictionary
        image_type = image_data['image_type']
        meta_data = image_data['metadata']
        sem_data = image_data['semantics']
        image_data = image_data['images']

    # Initialize feature value and label lists.
    feature_values = list()
    feature_labels = list()

    # Extract shape features
    shape_mask = ih.get_masked_slices_mask(mask)

    print("Computing shape features.")
    shape_features, shape_labels = sf.get_shape_features(shape_mask, meta_data)
    feature_values += shape_features
    feature_labels += shape_labels

    if config["orientation"]:
        print("Computing orientation features.")
        orientation_features, orientation_labels =\
            of.get_orientation_features(shape_mask)
        feature_values += orientation_features
        feature_labels += orientation_labels

    if meta_data is not None:
        print("Extracting patient features.")
        patient_features, patient_labels =\
            pf.get_patient_features(meta_data, image_type)
        feature_values += patient_features
        feature_labels += patient_labels

    if sem_data is not None and output is not None:
        print("Extracting semantic features.")
        sem_features, sem_labels = semf.get_semantic_features(sem_data, output)
        feature_values += sem_features
        feature_labels += sem_labels

    if 'DTI_post' in image_type:
        dti_features, dti_labels = dtif.get_dti_post_features(
            image_data, mask, meta_data)
        feature_values += dti_features
        feature_labels += dti_labels

    elif 'DTI' in image_type:
        dti_features, dti_labels = dtif.get_dti_features(
            image_data, mask, meta_data)
        feature_values += dti_features
        feature_labels += dti_labels

    elif any(type in image_type for type in ['MR', 'CT', 'PET', 'MG']):
        image_data_array = sitkh.GetArrayFromImage(image_data)
        mask_array = sitkh.GetArrayFromImage(mask)

        masked_voxels = ih.get_masked_voxels(image_data_array, mask_array)

        print("Computing histogram features.")
        histogram_features, histogram_labels =\
            hf.get_histogram_features(masked_voxels,
                                      N_BINS)

        # NOTE: As a minimum of 4 voxels in each dimension is needed
        # for the SimpleITK log filter, we compute these features
        # on the full image
        if config["log"]:
            print("Computing log features.")
            log_features, log_labels =\
                logf.get_log_features(image_data_array,
                                      mask_array,
                                      parameters['log'])
            feature_values += log_features
            feature_labels += log_labels

        image_data_array, mask_array = ih.get_masked_slices_image(
            image_data_array, mask_array)

        print("Computing texture features.")
        texture_features, texture_labels =\
            tf.get_texture_features(image_data_array,
                                    mask_array,
                                    parameters,
                                    config['texture'],
                                    config_general)

        feature_values += histogram_features + texture_features
        feature_labels += histogram_labels + texture_labels

        if config["coliage"]:
            print("Computing coliage features.")
            coliage_features, coliage_labels =\
                cf.get_coliage_features(image_data_array,
                                        mask_array)
            feature_values += coliage_features
            feature_labels += coliage_labels

        if config["vessel"]:
            print("Computing vessel features.")
            vessel_features, vessel_labels =\
                vesf.get_vessel_features(image_data_array,
                                         mask_array,
                                         parameters['vessel'])
            feature_values += vessel_features
            feature_labels += vessel_labels

        if config["phase"]:
            print("Computing phase features.")
            phase_features, phase_labels =\
                phasef.get_phase_features(image_data_array,
                                          mask_array,
                                          parameters['phase'])
            feature_values += phase_features
            feature_labels += phase_labels

    else:
        raise ae.PREDICTTypeError(
            ("Invalid image type: {}").format(image_type))

    return feature_values, feature_labels