| | import sys |
| | sys.path.append('../TM2_segmentation') |
| |
|
| | import os |
| | os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE" |
| |
|
| | import logging |
| | import SimpleITK as sitk |
| | from scipy.signal import medfilt |
| | import numpy as np |
| | import nibabel as nib |
| | import scipy |
| | import skimage |
| | import functools |
| | from skimage.transform import resize |
| | import subprocess |
| | import pandas as pd |
| | import shutil |
| | import itk |
| |
|
| | |
| | def iou(component1, component2): |
| | component1 = np.array(component1, dtype=bool) |
| | component2 = np.array(component2, dtype=bool) |
| |
|
| | overlap = component1 * component2 |
| | union = component1 + component2 |
| |
|
| | IOU = overlap.sum()/float(union.sum()) |
| | return IOU |
| |
|
| | |
| | def get_id_and_path(row, image_dir, nested = False, no_tms=True): |
| | patient_id, image_path, ltm_file, rtm_file = "","","","" |
| | if no_tms and row['Ok registered? Y/N'] == "N" : |
| | print("skip - bad registration") |
| | return "","","","" |
| | if "NDAR" in str(row['Filename']) and nested==False and no_tms: |
| | patient_id = str(row['Filename']).split("_")[0] |
| | else: |
| | patient_id = str(row['Filename']).split(".")[0] |
| |
|
| | path = find_file_in_path(patient_id, os.listdir(image_dir)) |
| | |
| | if nested: |
| | patient_id = patient_id.split("/")[-1] |
| | path = patient_id.split("/")[-1] |
| | if no_tms==False: |
| | path="" |
| | |
| | scan_folder = image_dir+path |
| | patient_id=patient_id.split("/")[-1] |
| | |
| | for file in os.listdir(scan_folder): |
| | t = image_dir+path+"/"+file |
| | if "LTM" in file: |
| | ltm_file = t |
| | elif "RTM" in file: |
| | rtm_file = t |
| | elif "TM" in file: |
| | rtm_file = t |
| | ltm_file = t |
| | if patient_id in file: |
| | image_path = t |
| | return patient_id, image_path, ltm_file, rtm_file |
| |
|
| | |
| | def get_id_and_path_not_nested(row, image_dir, masks_dir): |
| | patient_id, image_path, tm_file = 0,0,0 |
| | if row['Ok registered? Y/N'] == "N": |
| | print("skip - bad registration") |
| | return 0,0,0,0 |
| | if "NDAR" in row['Filename']: |
| | patient_id = row['Filename'].split("_")[0] |
| | else: |
| | patient_id = row['Filename'].split(".")[0] |
| |
|
| | path = find_file_in_path(patient_id, os.listdir(masks_dir)) |
| | if len(path)<3: |
| | return 0,0,0,0 |
| | scan_folder_masks = masks_dir+path |
| |
|
| | for file in os.listdir(scan_folder_masks): |
| | if "._" in file: |
| | continue |
| | if "TM" in file: |
| | tm_file = masks_dir+path+"/"+file |
| | elif ".nii" in file and "TM" not in file: |
| | image_path = image_dir+patient_id+".nii" |
| |
|
| | return patient_id, image_path, tm_file |
| |
|
| | |
| | def crop_center(img,cropx,cropy): |
| | y,x = img.shape |
| | startx = x//2-(cropx//2) |
| | starty = y//2-(cropy//2) |
| | return img[starty:starty+cropy,startx:startx+cropx] |
| |
|
| | |
| | def find_file_in_path(name, path): |
| | result = [] |
| | result = list(filter(lambda x:name in x, path)) |
| | if len(result) != 0: |
| | for file in result: |
| | if "._" in file: |
| | continue |
| | else: |
| | return file |
| | else: |
| | return "" |
| |
|
| | |
| | def bias_field_correction(img): |
| | image = sitk.GetImageFromArray(img) |
| | maskImage = sitk.OtsuThreshold(image, 0, 1, 200) |
| | corrector = sitk.N4BiasFieldCorrectionImageFilter() |
| | numberFittingLevels = 4 |
| |
|
| | corrector.SetMaximumNumberOfIterations([100] * numberFittingLevels) |
| | corrected_image = corrector.Execute(image, maskImage) |
| | log_bias_field = corrector.GetLogBiasFieldAsImage(image) |
| | corrected_image_full_resolution = image / sitk.Exp(log_bias_field) |
| | return sitk.GetArrayFromImage(corrected_image_full_resolution) |
| |
|
| | def load_nii(path): |
| | nii = nib.load(path) |
| | return nii.get_fdata(), nii.affine |
| |
|
| | def save_nii(data, path, affine): |
| | nib.save(nib.Nifti1Image(data, affine), path) |
| | return |
| |
|
| | def denoise(volume, kernel_size=3): |
| | return medfilt(volume, kernel_size) |
| | |
| | |
| | def apply_window(image, win_centre= 40, win_width= 400): |
| | range_bottom = 149 |
| | scale = 256 / 256 |
| | image = image - range_bottom |
| |
|
| | image = image * scale |
| | image[image < 0] = 0 |
| | image[image > 255] = 255 |
| | return image |
| |
|
| | |
| | def rescale_intensity(volume, percentils=[0.5, 99.5], bins_num=256): |
| | |
| | t = skimage.filters.threshold_otsu(volume,nbins=6) |
| | volume[volume < t] = 0 |
| | |
| | obj_volume = volume[np.where(volume > 0)] |
| | min_value = np.percentile(obj_volume, percentils[0]) |
| | max_value = np.percentile(obj_volume, percentils[1]) |
| | if bins_num == 0: |
| | obj_volume = (obj_volume - min_value) / (max_value - min_value).astype(np.float32) |
| | else: |
| | obj_volume = np.round((obj_volume - min_value) / (max_value - min_value) * (bins_num - 1)) |
| | obj_volume[np.where(obj_volume < 1)] = 1 |
| | obj_volume[np.where(obj_volume > (bins_num - 1))] = bins_num - 1 |
| |
|
| | volume = volume.astype(obj_volume.dtype) |
| | volume[np.where(volume > 0)] = obj_volume |
| | return volume |
| |
|
| | |
| | def equalize_hist(volume, bins_num=256): |
| | obj_volume = volume[np.where(volume > 0)] |
| | hist, bins = np.histogram(obj_volume, bins_num) |
| | cdf = hist.cumsum() |
| | cdf = (bins_num - 1) * cdf / cdf[-1] |
| |
|
| | obj_volume = np.round(np.interp(obj_volume, bins[:-1], cdf)).astype(obj_volume.dtype) |
| | volume[np.where(volume > 0)] = obj_volume |
| | return volume |
| |
|
| | |
| | def enhance(volume, kernel_size=3, |
| | percentils=[0.5, 99.5], bins_num=256, eh=True): |
| | try: |
| | volume = bias_field_correction(volume) |
| | volume = denoise(volume, kernel_size) |
| | volume = rescale_intensity(volume, percentils, bins_num) |
| | if eh: |
| | volume = equalize_hist(volume, bins_num) |
| | return volume |
| | except RuntimeError: |
| | logging.warning('Failed enchancing') |
| |
|
| | |
| | def enhance_noN4(volume, kernel_size=3, |
| | percentils=[0.5, 99.5], bins_num=256, eh=True): |
| | try: |
| | |
| | volume = denoise(volume, kernel_size) |
| | |
| | volume = rescale_intensity(volume, percentils, bins_num) |
| | |
| | if eh: |
| | volume = equalize_hist(volume, bins_num) |
| | return volume |
| | except RuntimeError: |
| | logging.warning('Failed enchancing') |
| |
|
| | |
| | def get_resampled_sitk(data_sitk,target_spacing): |
| | new_spacing = target_spacing |
| |
|
| | orig_spacing = data_sitk.GetSpacing() |
| | orig_size = data_sitk.GetSize() |
| |
|
| | new_size = [int(orig_size[0] * orig_spacing[0] / new_spacing[0]), |
| | int(orig_size[1] * orig_spacing[1] / new_spacing[1]), |
| | int(orig_size[2] * orig_spacing[2] / new_spacing[2])] |
| |
|
| | res_filter = sitk.ResampleImageFilter() |
| | img_sitk = res_filter.Execute(data_sitk, |
| | new_size, |
| | sitk.Transform(), |
| | sitk.sitkLinear, |
| | data_sitk.GetOrigin(), |
| | new_spacing, |
| | data_sitk.GetDirection(), |
| | 0, |
| | data_sitk.GetPixelIDValue()) |
| |
|
| | return img_sitk |
| |
|
| | |
| | def nrrd_to_nifty(nrrd_file): |
| | _nrrd = nrrd.read(nrrd_file) |
| | data_f = _nrrd[0] |
| | header = _nrrd[1] |
| | return np.asarray(data_f), header |
| |
|
| | |
| | def crop_brain(var_img, mni_img): |
| | |
| | inverted_mask = np.invert(mni_img.astype(bool)).astype(float) |
| | mask_data = inverted_mask * var_img |
| | return mask_data |
| |
|
| | |
| | def brain_norm_masked(mask_data, brain_data, to_save=False): |
| | masked = crop_brain(brain_data, mask_data) |
| | enhanced = enhance(masked) |
| | return enhanced |
| |
|
| | |
| | def enhance_and_debias_all_in_path(image_dir='data/mni_templates_BK/',path_to='data/denoised_mris/',\ |
| | input_annotation_file = 'data/all_metadata.csv'): |
| |
|
| | df = pd.read_csv(input_annotation_file,header=0) |
| | df=df[df['Ok registered? Y/N']=='Y'].reset_index() |
| | |
| | for idx in range(0, 1): |
| | print(idx) |
| | row = df.iloc[idx] |
| | patient_id, image_path, tm_file, _ = get_id_and_path(row, image_dir) |
| | print(patient_id, image_path, tm_file) |
| | image_sitk = sitk.ReadImage(image_path) |
| | image_array = sitk.GetArrayFromImage(image_sitk) |
| | image_array = enhance(image_array) |
| | image3 = sitk.GetImageFromArray(image_array) |
| | sitk.WriteImage(image3,path_to+patient_id+'.nii') |
| | return |
| |
|
| | |
| | def z_enhance_and_debias_all_in_path(image_dir='data/mni_templates_BK/',path_to='data/z_scored_mris/',\ |
| | input_annotation_file = 'data/all_metadata.csv', for_training=True, annotations=True): |
| | df = pd.read_csv(input_annotation_file,header=0) |
| | |
| | if for_training: |
| | df=df[df['Ok registered? Y/N']=='Y'].reset_index() |
| | print(df.shape[0]) |
| | |
| | for idx in range(0, df.shape[0]): |
| | print(idx) |
| | row = df.iloc[idx] |
| | patient_id, image_path, tm_file, _ = get_id_and_path(row, image_dir, nested=False, no_tms=for_training) |
| | print(patient_id, len(image_path), tm_file, path_to) |
| | if not os.path.isdir(path_to+"no_z"): |
| | os.mkdir(path_to+"no_z") |
| | if not os.path.isdir(path_to+"z"): |
| | os.mkdir(path_to+"z") |
| | |
| | if len(image_path)>3: |
| | image_sitk = sitk.ReadImage(image_path) |
| | image_array = sitk.GetArrayFromImage(image_sitk) |
| | print(len(image_array)) |
| | try: |
| | image_array = enhance_noN4(image_array) |
| | image3 = sitk.GetImageFromArray(image_array) |
| | sitk.WriteImage(image3,path_to+"no_z/"+patient_id+'.nii') |
| | os.mkdir(path_to+"z/"+patient_id) |
| | if annotations: |
| | shutil.copyfile(tm_file, path_to+"z/"+patient_id+"/TM.nii.gz") |
| | duck_line = "zscore-normalize "+path_to+"no_z/"+patient_id+".nii -o "+path_to+"z/"+patient_id +"/"+patient_id+'.nii' |
| | subprocess.getoutput(duck_line) |
| | except: |
| | continue |
| |
|
| | |
| | def closest_value(input_list, input_value): |
| | arr = np.asarray(input_list) |
| | i = (np.abs(arr - input_value)).argmin() |
| | return arr[i], i |
| |
|
| | |
| | def find_centile(input_tmt, age, df): |
| | |
| | val,i=closest_value(df['x'],age) |
| | |
| | centile = 'out of range' |
| | if input_tmt<df.iloc[i]['X3']: |
| | centile ='< 3' |
| | if df.iloc[i]['X3']<=input_tmt<df.iloc[i]['X10']: |
| | centile ='3-10' |
| | if df.iloc[i]['X10']<=input_tmt<df.iloc[i]['X25']: |
| | centile ='10-25' |
| | if df.iloc[i]['X25']<=input_tmt<df.iloc[i]['X50']: |
| | centile ='25-50' |
| | if df.iloc[i]['X50']<=input_tmt<df.iloc[i]['X75']: |
| | centile ='50-75' |
| | if df.iloc[i]['X75']<=input_tmt<df.iloc[i]['X90']: |
| | centile ='75-90' |
| | if df.iloc[i]['X90']<=input_tmt<df.iloc[i]['X97']: |
| | centile ='90-97' |
| | if input_tmt>df.iloc[i]['X97']: |
| | centile ='97>' |
| | |
| | return centile |
| |
|
| | |
| | def find_exact_percentile_return_number(input_tmt, age, df): |
| | |
| | val,i=closest_value(df['x'],age) |
| | |
| | mu = df.iloc[i]['mu'] |
| | sigma = df.iloc[i]['sigma'] |
| | nu = df.iloc[i]['nu'] |
| | |
| | |
| | if nu!=0: |
| | z = ((input_tmt/mu)**(nu)-1)/(nu*sigma) |
| | else: |
| | z = 1/sigma * math.log(input_tmt/mu) |
| | percentile = scipy.stats.norm.cdf(z) |
| | return round(percentile*100,2) |
| |
|
| | |
| | def add_median_labels(ax, fmt='.1f'): |
| | lines = ax.get_lines() |
| | boxes = [c for c in ax.get_children() if type(c).__name__ == 'PathPatch'] |
| | lines_per_box = int(len(lines) / len(boxes)) |
| | for median in lines[4:len(lines):lines_per_box]: |
| | x, y = (data.mean() for data in median.get_data()) |
| | |
| | value = x if (median.get_xdata()[1] - median.get_xdata()[0]) == 0 else y |
| | text = ax.text(x, y, f'{value:{fmt}}', ha='center', va='center', |
| | fontweight='ultralight', color='gray') |
| | |
| | text.set_path_effects([ |
| | path_effects.Stroke(linewidth=3, foreground=median.get_color()), |
| | path_effects.Normal(), |
| | ]) |
| |
|
| | |
| | def register_to_template(input_image_path, output_path, fixed_image_path,create_subfolder=True): |
| | fixed_image = itk.imread(fixed_image_path, itk.F) |
| |
|
| | |
| | parameter_object = itk.ParameterObject.New() |
| | parameter_object.AddParameterFile('data/golden_image/mni_templates/Parameters_Rigid.txt') |
| |
|
| | if "nii" in input_image_path and "._" not in input_image_path: |
| | print(input_image_path) |
| |
|
| | |
| | try: |
| | moving_image = itk.imread(input_image_path, itk.F) |
| | result_image, result_transform_parameters = itk.elastix_registration_method( |
| | fixed_image, moving_image, |
| | parameter_object=parameter_object, |
| | log_to_console=False) |
| | image_id = input_image_path.split("/")[-1] |
| | |
| | if create_subfolder: |
| | new_dir = output_path+image_id.split(".")[0] |
| | if not os.path.exists(new_dir): |
| | os.mkdir(new_dir) |
| | itk.imwrite(result_image, new_dir+"/"+image_id) |
| | else: |
| | itk.imwrite(result_image, output_path+"/"+image_id) |
| | |
| | print("Registered ", image_id) |
| | except: |
| | print("Cannot transform", input_image_path.split("/")[-1]) |
| | |
| | if __name__=="__main__": |
| | |
| | ''' |
| | z_enhance_and_debias_all_in_path(image_dir='data/mni_templates_BK/', |
| | path_to='data/z_scored_mris/z_with_pseudo/',\ |
| | input_annotation_file = 'data/all_metadata.csv') |
| | |
| | z_enhance_and_debias_all_in_path(image_dir='data/curated_test/reg_tm_not_corrected/', |
| | path_to='data/curated_test/final_test/', |
| | input_annotation_file = 'data/curated_test/reg_tm_not_corrected/Dataset_test_rescaled.csv', |
| | for_training=True) |
| | # all the datasets |
| | z_enhance_and_debias_all_in_path(image_dir='data/t1_mris/registered_not_ench/', |
| | path_to='data/t1_mris/registered/', |
| | input_annotation_file = 'data/Dataset_t1_healthy_raw.csv', |
| | for_training=False,annotations=False) |
| | |
| | #ping |
| | # z_enhance_and_debias_all_in_path(image_dir='data/t1_mris/pings_registered/', |
| | path_to='data/t1_mris/pings_ench_reg/', |
| | input_annotation_file = 'data/Dataset_ping.csv', |
| | for_training=False, annotations=False) |
| | # pixar |
| | z_enhance_and_debias_all_in_path(image_dir='data/t1_mris/pixar/', |
| | path_to='data/t1_mris/pixar_ench/', |
| | input_annotation_file = 'data/Dataset_pixar.csv', |
| | for_training=False, annotations=False) |
| | #abide |
| | z_enhance_and_debias_all_in_path(image_dir='data/t1_mris/abide_registered/', |
| | path_to='data/t1_mris/abide_ench_reg/', |
| | input_annotation_file = "data/Dataset_abide.csv", |
| | for_training=False, annotations=False) |
| | |
| | # calgary |
| | z_enhance_and_debias_all_in_path(image_dir='data/t1_mris/calgary_reg/', |
| | path_to='data/t1_mris/calgary_reg_ench/', |
| | input_annotation_file = "data/Dataset_calgary.csv", |
| | for_training=False, annotations=False) |
| | |
| | # aomic replace header with ,AGE_M,SEX,SCAN_PATH,Filename,dataset |
| | z_enhance_and_debias_all_in_path(image_dir='data/t1_mris/aomic_reg/', |
| | path_to='data/t1_mris/aomic_reg_ench/', |
| | input_annotation_file = "data/Dataset_aomic.csv", |
| | for_training=False, annotations=False) |
| | |
| | # NIHM replace header with ,AGE_M,SEX,SCAN_PATH,Filename,dataset |
| | z_enhance_and_debias_all_in_path(image_dir='data/t1_mris/nihm_reg/', |
| | path_to='data/t1_mris/nihm_ench_reg/', |
| | input_annotation_file = "data/Dataset_nihm.csv", |
| | for_training=False, annotations=False) |
| | |
| | # ICBM replace header with ,AGE_M,SEX,SCAN_PATH,Filename,dataset |
| | z_enhance_and_debias_all_in_path(image_dir='data/t1_mris/icbm_reg/', |
| | path_to='data/t1_mris/icbm_ench_reg/', |
| | input_annotation_file = "data/Dataset_icbm.csv", |
| | for_training=False, annotations=False) |
| | |
| | # SALD |
| | z_enhance_and_debias_all_in_path(image_dir='data/t1_mris/sald_reg/', |
| | path_to='data/t1_mris/sald_reg_ench/', |
| | input_annotation_file = "data/Dataset_sald.csv", |
| | for_training=False, annotations=False) |
| | |
| | ## NYU |
| | z_enhance_and_debias_all_in_path(image_dir='data/t1_mris/nyu_reg/', |
| | path_to='data/t1_mris/nyu_reg_ench/', |
| | input_annotation_file = "data/Dataset_nyu.csv", |
| | for_training=False, annotations=False) |
| | ## NAH |
| | z_enhance_and_debias_all_in_path(image_dir='data/t1_mris/healthy_adults_nihm/', |
| | path_to='data/t1_mris/healthy_adults_nihm_reg_ench/', |
| | input_annotation_file = "data/Dataset_healthy_adults_nihm.csv", |
| | for_training=False, annotations=False) |
| | ## Petfrog |
| | z_enhance_and_debias_all_in_path(image_dir='data/t1_mris/petfrog_reg/', |
| | path_to='data/t1_mris/petfrog_reg_ench/', |
| | input_annotation_file = "data/Dataset_petfrog.csv", |
| | for_training=False, annotations=False) |
| | ## CBTN |
| | z_enhance_and_debias_all_in_path(image_dir='data/t1_mris/cbtn_reg/', |
| | path_to='data/t1_mris/cbtn_reg_ench/', |
| | input_annotation_file = "data/Dataset_cbtn.csv", |
| | for_training=False, annotations=False) |
| | ## DMG |
| | z_enhance_and_debias_all_in_path(image_dir='data/t1_mris/dmg_reg/', |
| | path_to='data/t1_mris/dmg_reg_ench/', |
| | input_annotation_file = "data/Dataset_dmg.csv", |
| | for_training=False, annotations=False) |
| | ## BCH |
| | z_enhance_and_debias_all_in_path(image_dir='data/t1_mris/bch_reg/', |
| | path_to='data/t1_mris/bch_reg_ench/', |
| | input_annotation_file = "data/Dataset_bch.csv", |
| | for_training=False, annotations=False) |
| | ## BCH long |
| | z_enhance_and_debias_all_in_path(image_dir='data/t1_mris/bch_long_reg/', |
| | path_to='data/t1_mris/bch_long_reg_ench/', |
| | input_annotation_file = "data/Dataset_bch_long.csv", |
| | for_training=False, annotations=False) |
| | ## 28 |
| | z_enhance_and_debias_all_in_path(image_dir='data/t1_mris/uscf_reg/', |
| | path_to='data/t1_mris/uscf_reg_ench/', |
| | input_annotation_file = "data/Dataset_ucsf.csv", |
| | for_training=False, annotations=False)''' |
| | |
| | z_enhance_and_debias_all_in_path(image_dir='data/bch_long_pre_test/reg/', |
| | path_to='data/bch_long_pre_test/reg_ench/', |
| | input_annotation_file = "data/Dataset_bch_long_pre_test.csv", |
| | for_training=False, annotations=False) |
| | |
| | |