def main(argv=None): parser = get_parser() arguments = parser.parse_args(argv) verbose = arguments.v set_loglevel(verbose=verbose) GYRO = float(42.576 * 10**6) # gyromagnetic ratio (in Hz.T^-1) gradamp = [] bigdelta = [] smalldelta = [] gradamp = arguments.g bigdelta = arguments.b smalldelta = arguments.d # printv(arguments) printv('\nCheck parameters:') printv(' gradient amplitude ..... ' + str(gradamp) + ' mT/m') printv(' big delta .............. ' + str(bigdelta) + ' ms') printv(' small delta ............ ' + str(smalldelta) + ' ms') printv(' gyromagnetic ratio ..... ' + str(GYRO) + ' Hz/T') printv('') bvalue = (2 * math.pi * GYRO * gradamp * 0.001 * smalldelta * 0.001)**2 * (bigdelta * 0.001 - smalldelta * 0.001 / 3) printv('b-value = ' + str(bvalue / 10**6) + ' mm^2/s\n') return bvalue
def main(argv=None): """ Main function :param argv: :return: """ parser = get_parser() arguments = parser.parse_args(argv) verbose = arguments.v set_loglevel(verbose=verbose) # check number of input args if not len(arguments.i) == len(arguments.order): raise Exception( "Number of items between flags '-i' and '-order' should be the same." ) if not len(arguments.bval) == len(arguments.bvec): raise Exception( "Number of files for bval and bvec should be the same.") # Concatenate NIFTI files im_list = [Image(fname) for fname in arguments.i] im_concat = concat_data(im_list, dim=3, squeeze_data=False) im_concat.save(arguments.o) printv("Generated file: {}".format(arguments.o)) # Concatenate bvals and bvecs bvals_concat = '' bvecs_concat = ['', '', ''] i_dwi = 0 # counter for DWI files, to read in bvec/bval files for i_item in range(len(arguments.order)): if arguments.order[i_item] == 'b0': # count number of b=0 n_b0 = Image(arguments.i[i_item]).dim[3] bval = np.array([0.0] * n_b0) bvec = np.array([[0.0, 0.0, 0.0]] * n_b0) elif arguments.order[i_item] == 'dwi': # read bval/bvec files bval, bvec = read_bvals_bvecs(arguments.bval[i_dwi], arguments.bvec[i_dwi]) i_dwi += 1 # Concatenate bvals bvals_concat += ' '.join(str(v) for v in bval) bvals_concat += ' ' # Concatenate bvecs for i in (0, 1, 2): bvecs_concat[i] += ' '.join( str(v) for v in map(lambda n: '%.16f' % n, bvec[:, i])) bvecs_concat[i] += ' ' bvecs_concat = '\n'.join( str(v) for v in bvecs_concat) # transform list into lines of strings # Write files new_f = open(arguments.obval, 'w') new_f.write(bvals_concat) new_f.close() printv("Generated file: {}".format(arguments.obval)) new_f = open(arguments.obvec, 'w') new_f.write(bvecs_concat) new_f.close() printv("Generated file: {}".format(arguments.obvec))
def main(argv=None): parser = get_parser() arguments = parser.parse_args(argv) verbose = arguments.v set_loglevel(verbose=verbose) fname_in = arguments.bvec fname_out = arguments.o # get bvecs in proper orientation from dipy.io import read_bvals_bvecs bvals, bvecs = read_bvals_bvecs(None, fname_in) # # Transpose bvecs # printv('Transpose bvecs...', verbose) # # from numpy import transpose # bvecs = bvecs.transpose() # Write new file if fname_out == '': path_in, file_in, ext_in = extract_fname(fname_in) fname_out = path_in + file_in + ext_in fid = open(fname_out, 'w') for iLine in range(bvecs.shape[0]): fid.write(' '.join(str(i) for i in bvecs[iLine, :]) + '\n') fid.close() # display message printv('Created file:\n--> ' + fname_out + '\n', verbose, 'info')
def main(argv=None): """ Main function :param fname_anat: :param fname_centerline: :param verbose: :return: """ parser = get_parser() arguments = parser.parse_args(argv) verbose = arguments.v set_loglevel(verbose=verbose) fname_anat = arguments.i fname_centerline = arguments.s # load input images im_anat = Image(fname_anat) im_centerline = Image(fname_centerline) # flatten sagittal im_anat_flattened = flatten_sagittal(im_anat, im_centerline, verbose) # save output fname_out = add_suffix(fname_anat, '_flatten') im_anat_flattened.save(fname_out) display_viewer_syntax([fname_anat, fname_out])
def main(argv=None): parser = get_parser() arguments = parser.parse_args(argv) verbose = arguments.v set_loglevel(verbose=verbose) fname_bval_list = arguments.i # Build fname_out if arguments.o is not None: fname_out = arguments.o else: path_in, file_in, ext_in = extract_fname(fname_bval_list[0]) fname_out = path_in + 'bvals_concat' + ext_in # Open bval files and concatenate bvals_concat = '' # for file_i in fname_bval_list: # f = open(file_i, 'r') # for line in f: # bvals_concat += line # f.close() from dipy.data.fetcher import read_bvals_bvecs for i_fname in fname_bval_list: bval_i, bvec_i = read_bvals_bvecs(i_fname, None) bvals_concat += ' '.join(str(v) for v in bval_i) bvals_concat += ' ' # Write new bval new_f = open(fname_out, 'w') new_f.write(bvals_concat) new_f.close()
def main(argv=None): parser = get_parser() arguments = parser.parse_args(argv) verbose = arguments.v set_loglevel(verbose=verbose) fname_bvecs_list = arguments.i # Build fname_out if arguments.o is not None: fname_out = arguments.o else: path_in, file_in, ext_in = extract_fname(fname_bvecs_list[0]) fname_out = path_in + 'bvecs_concat' + ext_in # # Open bvec files and collect values # nb_files = len(fname_bvecs_list) # bvecs_all = [] # for i_fname in fname_bvecs_list: # bvecs = [] # with open(i_fname) as f: # for line in f: # bvec_line = map(float, line.split()) # bvecs.append(bvec_line) # bvecs_all.append(bvecs) # f.close() # # Concatenate # bvecs_concat = '' # for i in range(0, 3): # for j in range(0, nb_files): # bvecs_concat += ' '.join(str(v) for v in bvecs_all[j][i]) # bvecs_concat += ' ' # bvecs_concat += '\n' # # Open bvec files and collect values bvecs_all = ['', '', ''] for i_fname in fname_bvecs_list: from dipy.data.fetcher import read_bvals_bvecs bval_i, bvec_i = read_bvals_bvecs(None, i_fname) for i in range(0, 3): bvecs_all[i] += ' '.join( str(v) for v in map(lambda n: '%.16f' % n, bvec_i[:, i])) bvecs_all[i] += ' ' # Concatenate bvecs_concat = '\n'.join(str(v) for v in bvecs_all) # Write new bvec new_f = open(fname_out, 'w') new_f.write(bvecs_concat) new_f.close()
def main(argv=None): parser = get_parser() arguments = parser.parse_args(argv) verbose = arguments.v set_loglevel(verbose=verbose) param.fname_data = arguments.i arg = 0 if arguments.f is not None: param.new_size = arguments.f param.new_size_type = 'factor' arg += 1 elif arguments.mm is not None: param.new_size = arguments.mm param.new_size_type = 'mm' arg += 1 elif arguments.vox is not None: param.new_size = arguments.vox param.new_size_type = 'vox' arg += 1 elif arguments.ref is not None: param.ref = arguments.ref arg += 1 else: printv( parser.error( 'ERROR: you need to specify one of those three arguments : -f, -mm or -vox' )) if arg > 1: printv( parser.error( 'ERROR: you need to specify ONLY one of those three arguments : -f, -mm or -vox' )) if arguments.o is not None: param.fname_out = arguments.o if arguments.x is not None: if len(arguments.x) == 1: param.interpolation = int(arguments.x) else: param.interpolation = arguments.x spinalcordtoolbox.resampling.resample_file(param.fname_data, param.fname_out, param.new_size, param.new_size_type, param.interpolation, param.verbose, fname_ref=param.ref)
def main(argv=None): parser = get_parser() arguments = parser.parse_args(argv) verbose = arguments.v set_loglevel(verbose=verbose) # Get parser info di = arguments.di da = arguments.da db = arguments.db # Compute MSCC MSCC = mscc(di, da, db) # Display results printv('\nMSCC = ' + str(MSCC) + '\n', verbose, 'info')
def main(argv=None): parser = get_parser() arguments = parser.parse_args(argv) verbose = arguments.v set_loglevel(verbose=verbose) param = Param() fname_src = arguments.i if arguments.o is not None: fname_dst = arguments.o else: fname_dst = add_suffix(fname_src, "_tsnr") # call main function tsnr = Tsnr(param=param, fmri=fname_src, out=fname_dst) tsnr.compute()
def main(argv=None): parser = get_parser() arguments = parser.parse_args(argv) verbose = arguments.v set_loglevel(verbose=verbose) input_filename = arguments.i if arguments.o is not None: output_filename = arguments.o else: output_filename = add_suffix(input_filename, '_gmseg') use_tta = arguments.t model_name = arguments.m threshold = arguments.thr if threshold > 1.0 or threshold < 0.0: raise RuntimeError("Threshold should be between 0.0 and 1.0.") # Threshold zero means no thresholding if threshold == 0.0: threshold = None from spinalcordtoolbox.deepseg_gm import deepseg_gm deepseg_gm.check_backend() out_fname = deepseg_gm.segment_file(input_filename, output_filename, model_name, threshold, int(verbose), use_tta) path_qc = arguments.qc qc_dataset = arguments.qc_dataset qc_subject = arguments.qc_subject if path_qc is not None: generate_qc(fname_in1=input_filename, fname_seg=out_fname, args=sys.argv[1:], path_qc=os.path.abspath(path_qc), dataset=qc_dataset, subject=qc_subject, process='sct_deepseg_gm') display_viewer_syntax([input_filename, format(out_fname)], colormaps=['gray', 'red'], opacities=['1', '0.7'], verbose=verbose)
def main(argv=None): parser = get_parser() arguments = parser.parse_args(argv) verbose = arguments.v set_loglevel(verbose=verbose) fname_mtr = arguments.o # compute MTR printv('\nCompute MTR...', verbose) nii_mtr = compute_mtr(nii_mt1=Image(arguments.mt1), nii_mt0=Image(arguments.mt0), threshold_mtr=arguments.thr) # save MTR file nii_mtr.save(fname_mtr, dtype='float32') display_viewer_syntax([arguments.mt0, arguments.mt1, fname_mtr])
def main(argv=None): parser = get_parser() arguments = parser.parse_args(argv) verbose = arguments.v set_loglevel(verbose=verbose) printv('Load data...', verbose) nii_mt = Image(arguments.mt) nii_pd = Image(arguments.pd) nii_t1 = Image(arguments.t1) if arguments.b1map is None: nii_b1map = None else: nii_b1map = Image(arguments.b1map) if arguments.trmt is None: arguments.trmt = fetch_metadata(get_json_file_name(arguments.mt, check_exist=True), 'RepetitionTime') if arguments.trpd is None: arguments.trpd = fetch_metadata(get_json_file_name(arguments.pd, check_exist=True), 'RepetitionTime') if arguments.trt1 is None: arguments.trt1 = fetch_metadata(get_json_file_name(arguments.t1, check_exist=True), 'RepetitionTime') if arguments.famt is None: arguments.famt = fetch_metadata(get_json_file_name(arguments.mt, check_exist=True), 'FlipAngle') if arguments.fapd is None: arguments.fapd = fetch_metadata(get_json_file_name(arguments.pd, check_exist=True), 'FlipAngle') if arguments.fat1 is None: arguments.fat1 = fetch_metadata(get_json_file_name(arguments.t1, check_exist=True), 'FlipAngle') # compute MTsat nii_mtsat, nii_t1map = compute_mtsat(nii_mt, nii_pd, nii_t1, arguments.trmt, arguments.trpd, arguments.trt1, arguments.famt, arguments.fapd, arguments.fat1, nii_b1map=nii_b1map) # Output MTsat and T1 maps printv('Generate output files...', verbose) nii_mtsat.save(arguments.omtsat) nii_t1map.save(arguments.ot1map) display_viewer_syntax([arguments.omtsat, arguments.ot1map], colormaps=['gray', 'gray'], minmax=['-10,10', '0, 3'], opacities=['1', '1'], verbose=verbose)
def main(argv=None): """ Main function :param args: :return: """ parser = get_parser() arguments = parser.parse_args(argv) verbose = arguments.v set_loglevel(verbose=verbose) # Building the command, do sanity checks fname_in = arguments.i fname_out = arguments.o squeeze_data = bool(arguments.squeeze) # convert file img = image.Image(fname_in) img = image.convert(img, squeeze_data=squeeze_data) img.save(fname_out, mutable=True, verbose=verbose)
def main(argv=None): parser = get_parser() arguments = parser.parse_args(argv) verbose = arguments.v set_loglevel(verbose=verbose) # initialization file_mask = '' fname_in = arguments.i fname_bvals = arguments.bval fname_bvecs = arguments.bvec prefix = arguments.o method = arguments.method evecs = arguments.evecs if arguments.m is not None: file_mask = arguments.m # compute DTI if not compute_dti(fname_in, fname_bvals, fname_bvecs, prefix, method, evecs, file_mask, verbose): printv('ERROR in compute_dti()', 1, 'error')
def main(argv=None): """ Main function :param argv: :return: """ parser = get_parser() arguments = parser.parse_args(argv) verbose = arguments.v set_loglevel(verbose=verbose) # initialize ImageCropper cropper = ImageCropper(Image(arguments.i)) cropper.verbose = verbose # Switch across cropping methods if arguments.g: cropper.get_bbox_from_gui() elif arguments.m: cropper.get_bbox_from_mask(Image(arguments.m)) elif arguments.ref: cropper.get_bbox_from_ref(Image(arguments.ref)) else: cropper.get_bbox_from_minmax( BoundingBox(arguments.xmin, arguments.xmax, arguments.ymin, arguments.ymax, arguments.zmin, arguments.zmax) ) # Crop image img_crop = cropper.crop(background=arguments.b) # Write cropped image to file if arguments.o is None: fname_out = add_suffix(arguments.i, '_crop') else: fname_out = arguments.o img_crop.save(fname_out) display_viewer_syntax([arguments.i, fname_out])
def main(argv=None): parser = get_parser() arguments = parser.parse_args(argv) verbose = arguments.v set_loglevel(verbose=verbose) from spinalcordtoolbox.reports.qc import generate_qc # Build args list (for display) args_disp = '-i ' + arguments.i if arguments.d: args_disp += ' -d ' + arguments.d if arguments.s: args_disp += ' -s ' + arguments.s generate_qc(fname_in1=arguments.i, fname_in2=arguments.d, fname_seg=arguments.s, args=args_disp, path_qc=arguments.qc, dataset=arguments.qc_dataset, subject=arguments.qc_subject, process=arguments.p, fps=arguments.fps,)
def main(argv=None): parser = get_parser() arguments = parser.parse_args(argv) verbose = arguments.v set_loglevel(verbose=verbose) # Default params param = Param() # Get parser info fname_data = arguments.i fname_mask = arguments.m fname_mask_noise = arguments.m_noise method = arguments.method file_name = arguments.o rayleigh_correction = arguments.rayleigh # Check parameters if method in ['diff', 'single']: if not fname_mask: raise parser.error( f"Argument '-m' must be specified when using '-method {method}'." ) # Load data im_data = Image(fname_data) data = im_data.data dim = len(data.shape) nz = data.shape[2] if fname_mask: mask = Image(fname_mask).data # Check dimensionality if method in ['diff', 'mult']: if dim != 4: raise ValueError( f"Input data dimension: {dim}. Input dimension for this method should be 4." ) if method in ['single']: if dim not in [3, 4]: raise ValueError( f"Input data dimension: {dim}. Input dimension for this method should be 3 or 4." ) # Check dimensionality of mask if fname_mask: if len(mask.shape) != 3: raise ValueError( f"Mask should be a 3D image, but the input mask has shape '{mask.shape}'." ) # Retrieve selected volumes index_vol = parse_num_list(arguments.vol) if not index_vol: if method == 'mult': index_vol = range(data.shape[3]) elif method == 'diff': index_vol = [0, 1] elif method == 'single': index_vol = [0] # Compute SNR # NB: "time" is assumed to be the 4th dimension of the variable "data" if method == 'mult': # Compute mean and STD across time data_mean = np.mean(data[:, :, :, index_vol], axis=3) data_std = np.std(data[:, :, :, index_vol], axis=3, ddof=1) # Generate mask where std is different from 0 mask_std_nonzero = np.where(data_std > param.almost_zero) snr_map = np.zeros_like(data_mean) snr_map[mask_std_nonzero] = data_mean[mask_std_nonzero] / data_std[ mask_std_nonzero] # Output SNR map fname_snr = add_suffix(fname_data, '_SNR-' + method) im_snr = empty_like(im_data) im_snr.data = snr_map im_snr.save(fname_snr, dtype=np.float32) # Output non-zero mask fname_stdnonzero = add_suffix(fname_data, '_mask-STD-nonzero' + method) im_stdnonzero = empty_like(im_data) data_stdnonzero = np.zeros_like(data_mean) data_stdnonzero[mask_std_nonzero] = 1 im_stdnonzero.data = data_stdnonzero im_stdnonzero.save(fname_stdnonzero, dtype=np.float32) # Compute SNR in ROI if fname_mask: snr_roi = np.average(snr_map[mask_std_nonzero], weights=mask[mask_std_nonzero]) elif method == 'diff': # Check user selected exactly 2 volumes for this method. if not len(index_vol) == 2: raise ValueError( f"Number of selected volumes: {len(index_vol)}. The method 'diff' should be used with " f"exactly 2 volumes. You can specify the number of volumes with the flag '-vol'." ) data_2vol = np.take(data, index_vol, axis=3) # Compute mean across the two volumes data_mean = np.mean(data_2vol, axis=3) # Compute mean in ROI for each z-slice, if the slice in the mask is not null mean_in_roi = [ np.average(data_mean[..., iz], weights=mask[..., iz]) for iz in range(nz) if np.any(mask[..., iz]) ] data_sub = np.subtract(data_2vol[:, :, :, 1], data_2vol[:, :, :, 0]) # Compute STD in the ROI for each z-slice. The "np.sqrt(2)" results from the variance of the subtraction of two # distributions: var(A-B) = var(A) + var(B). # More context in: https://github.com/spinalcordtoolbox/spinalcordtoolbox/issues/3481 std_in_roi = [ weighted_std(data_sub[..., iz] / np.sqrt(2), weights=mask[..., iz]) for iz in range(nz) if np.any(mask[..., iz]) ] # Compute SNR snr_roi_slicewise = [m / s for m, s in zip(mean_in_roi, std_in_roi)] snr_roi = sum(snr_roi_slicewise) / len(snr_roi_slicewise) elif method == 'single': # Check that the input volume is 3D, or if it is 4D, that the user selected exactly 1 volume for this method. if dim == 3: data3d = data elif dim == 4: if not len(index_vol) == 1: raise ValueError( f"Selected volumes: {index_vol}. The method 'single' should be used with " f"exactly 1 volume. You can specify the index of the volume with the flag '-vol'." ) data3d = np.squeeze(data[..., index_vol]) # Check that input noise mask is provided if fname_mask_noise: mask_noise = Image(fname_mask_noise).data else: raise parser.error( "A noise mask is mandatory with '-method single'.") # Check dimensionality of the noise mask if len(mask_noise.shape) != 3: raise ValueError( f"Input noise mask dimension: {dim}. Input dimension for the noise mask should be 3." ) # Check that non-null slices are consistent between mask and mask_noise. for iz in range(nz): if not np.any(mask[..., iz]) == np.any(mask_noise[..., iz]): raise ValueError( f"Slice {iz} is empty in either mask or mask_noise. Non-null slices should be " f"consistent between mask and mask_noise.") # Compute mean in ROI for each z-slice, if the slice in the mask is not null mean_in_roi = [ np.average(data3d[..., iz], weights=mask[..., iz]) for iz in range(nz) if np.any(mask[..., iz]) ] std_in_roi = [ weighted_std(data3d[..., iz], weights=mask_noise[..., iz]) for iz in range(nz) if np.any(mask_noise[..., iz]) ] # Compute SNR snr_roi_slicewise = [m / s for m, s in zip(mean_in_roi, std_in_roi)] snr_roi = sum(snr_roi_slicewise) / len(snr_roi_slicewise) if rayleigh_correction: # Correcting for Rayleigh noise (see eq. A12 in Dietrich et al.) snr_roi *= np.sqrt((4 - np.pi) / 2) # Display result if fname_mask: printv('\nSNR_' + method + ' = ' + str(snr_roi) + '\n', type='info') # Added function for text file if file_name is not None: with open(file_name, "w") as f: f.write(str(snr_roi)) printv('\nFile saved to ' + file_name)
def main(argv=None): parser = get_parser() arguments = parser.parse_args(argv) verbose = arguments.v set_loglevel(verbose=verbose) parameter = arguments.p remove_temp_files = arguments.r noise_threshold = arguments.d file_to_denoise = arguments.i output_file_name = arguments.o std_noise = arguments.std param = Param() param.verbose = verbose param.remove_temp_files = remove_temp_files param.parameter = parameter path, file, ext = extract_fname(file_to_denoise) img = nib.load(file_to_denoise) hdr_0 = img.get_header() data = img.get_data() aff = img.get_affine() if min(data.shape) <= 5: printv( 'One of the image dimensions is <= 5 : reducing the size of the block radius.' ) block_radius = min(data.shape) - 1 else: block_radius = 5 # default value # Process for manual detecting of background # mask = data[:, :, :] > noise_threshold # data = data[:, :, :] if arguments.std is not None: sigma = std_noise # Application of NLM filter to the image printv('Applying Non-local mean filter...') if param.parameter == 'Rician': den = nlmeans(data, sigma=sigma, mask=None, rician=True, block_radius=block_radius) else: den = nlmeans(data, sigma=sigma, mask=None, rician=False, block_radius=block_radius) else: # # Process for manual detecting of background mask = data > noise_threshold sigma = np.std(data[~mask]) # Application of NLM filter to the image printv('Applying Non-local mean filter...') if param.parameter == 'Rician': den = nlmeans(data, sigma=sigma, mask=mask, rician=True, block_radius=block_radius) else: den = nlmeans(data, sigma=sigma, mask=mask, rician=False, block_radius=block_radius) t = time() printv("total time: %s" % (time() - t)) printv("vol size", den.shape) axial_middle = int(data.shape[2] / 2) before = data[:, :, axial_middle].T after = den[:, :, axial_middle].T diff_3d = np.absolute(den.astype('f8') - data.astype('f8')) difference = np.absolute(after.astype('f8') - before.astype('f8')) if arguments.std is None: difference[~mask[:, :, axial_middle].T] = 0 if param.verbose == 2: import matplotlib.pyplot as plt fig, ax = plt.subplots(1, 3) ax[0].imshow(before, cmap='gray', origin='lower') ax[0].set_title('before') ax[1].imshow(after, cmap='gray', origin='lower') ax[1].set_title('after') ax[2].imshow(difference, cmap='gray', origin='lower') ax[2].set_title('difference') for i in range(3): ax[i].set_axis_off() plt.show() # Save files img_denoise = nib.Nifti1Image(den, None, hdr_0) img_diff = nib.Nifti1Image(diff_3d, None, hdr_0) if output_file_name is not None: output_file_name = output_file_name else: output_file_name = file + '_denoised' + ext nib.save(img_denoise, output_file_name) nib.save(img_diff, file + '_difference' + ext) printv('\nDone! To view results, type:', param.verbose) printv('fsleyes ' + file_to_denoise + ' ' + output_file_name + ' & \n', param.verbose, 'info')
#!/usr/bin/env python # -*- coding: utf-8 # pytest unit tests for spinalcordtoolbox.qmri import numpy as np import nibabel import pytest from spinalcordtoolbox.qmri import mt from spinalcordtoolbox.image import Image from spinalcordtoolbox.utils import init_sct, set_loglevel # Set logger to "DEBUG" init_sct() set_loglevel(verbose=2) def make_sct_image(data): """ :return: an Image (3D) in RAS+ (aka SCT LPI) space data: scalar """ affine = np.eye(4) nii = nibabel.nifti1.Nifti1Image(np.array([data, data]), affine) img = Image(nii.get_data(), hdr=nii.header, orientation="LPI", dim=nii.header.get_data_shape()) return img
def main(argv=None): parser = get_parser() arguments = parser.parse_args(argv) verbose = arguments.v set_loglevel(verbose=verbose) fname_bvecs = arguments.bvec fname_bvals = arguments.bval # Read bvals and bvecs files (if arguments.bval is not passed, bvals will be None) bvals, bvecs = read_bvals_bvecs(fname_bvals, fname_bvecs) # if first dimension is not equal to 3 (x,y,z), transpose bvecs file if bvecs.shape[0] != 3: bvecs = bvecs.transpose() # if bvals file was not passed, create dummy unit bvals array (necessary fot scatter plots) if bvals is None: bvals = np.repeat(1, bvecs.shape[1]) # multiply unit b-vectors by b-values x, y, z = bvecs[0] * bvals, bvecs[1] * bvals, bvecs[2] * bvals # Set different color for each shell (bval) shell_colors = {} # Create iterator with different colors from brg palette colors = iter(cm.nipy_spectral(np.linspace(0, 1, len(np.unique(bvals))))) for unique_bval in np.unique(bvals): # skip b=0 if unique_bval < BZERO_THRESH: continue shell_colors[unique_bval] = next(colors) # Get total number of directions n_dir = len(x) # Get effective number of directions bvecs_eff = [] n_b0 = 0 for i in range(0, n_dir): add_direction = True # check if b=0 if abs(x[i]) < BZERO_THRESH and abs(x[i]) < BZERO_THRESH and abs( x[i]) < BZERO_THRESH: n_b0 += 1 add_direction = False else: # loop across bvecs_eff for j in range(0, len(bvecs_eff)): # if bvalue already present, then do not add to bvecs_eff if bvecs_eff[j] == [x[i], y[i], z[i]]: add_direction = False if add_direction: bvecs_eff.append([x[i], y[i], z[i]]) n_dir_eff = len(bvecs_eff) # Display scatter plot fig = plt.figure(facecolor='white', figsize=(9, 8)) fig.suptitle('Number of b=0: ' + str(n_b0) + ', Number of b!=0: ' + str(n_dir - n_b0) + ', Number of effective directions (without duplicates): ' + str(n_dir_eff)) # Display three views plot_2dscatter(fig_handle=fig, subplot=221, x=x, y=y, xlabel='X', ylabel='Y', bvals=bvals, colors=shell_colors) plot_2dscatter(fig_handle=fig, subplot=222, x=x, y=z, xlabel='X', ylabel='Z', bvals=bvals, colors=shell_colors) plot_2dscatter(fig_handle=fig, subplot=223, x=y, y=z, xlabel='Y', ylabel='Z', bvals=bvals, colors=shell_colors) # 3D ax = fig.add_subplot(224, projection='3d') # ax.auto_scale_xyz([-1, 1], [-1, 1], [-1, 1]) for i in range(0, n_dir): # x, y, z = bvecs[0], bvecs[1], bvecs[2] # if b=0, do not plot if not (abs(x[i]) < BZERO_THRESH and abs(x[i]) < BZERO_THRESH and abs(x[i]) < BZERO_THRESH): ax.scatter(x[i], y[i], z[i], color=shell_colors[bvals[i]], alpha=0.7) ax.set_xlim3d(-max(bvals), max(bvals)) ax.set_ylim3d(-max(bvals), max(bvals)) ax.set_zlim3d(-max(bvals), max(bvals)) ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') plt.title('3D view (use mouse to rotate)') plt.axis('on') # plt.draw() plt.tight_layout() # add legend with b-values if bvals file was passed if arguments.bval is not None: create_custom_legend(fig, shell_colors, bvals) # Save image printv("Saving figure: bvecs.png\n") plt.savefig('bvecs.png')
def main(argv: Sequence[str]): """ Main function. When this script is run via CLI, the main function is called using main(sys.argv[1:]). :param argv: A list of unparsed arguments, which is passed to ArgumentParser.parse_args() """ for i, arg in enumerate(argv): if arg == '-create-seg' and len(argv) > i + 1 and '-1,' in argv[i + 1]: raise DeprecationWarning( "The use of '-1' for '-create-seg' has been deprecated. Please use " "'-create-seg-mid' instead.") parser = get_parser() arguments = parser.parse_args(argv) verbose = arguments.v set_loglevel(verbose=verbose) input_filename = arguments.i output_fname = arguments.o img = Image(input_filename) dtype = None if arguments.add is not None: value = arguments.add out = sct_labels.add(img, value) elif arguments.create is not None: labels = arguments.create out = sct_labels.create_labels_empty(img, labels) elif arguments.create_add is not None: labels = arguments.create_add out = sct_labels.create_labels(img, labels) elif arguments.create_seg is not None: labels = arguments.create_seg out = sct_labels.create_labels_along_segmentation(img, labels) elif arguments.create_seg_mid is not None: labels = [(-1, arguments.create_seg_mid)] out = sct_labels.create_labels_along_segmentation(img, labels) elif arguments.cubic_to_point: out = sct_labels.cubic_to_point(img) elif arguments.display: display_voxel(img, verbose) return elif arguments.increment: out = sct_labels.increment_z_inverse(img) elif arguments.disc is not None: ref = Image(arguments.disc) out = sct_labels.labelize_from_discs(img, ref) elif arguments.vert_body is not None: levels = arguments.vert_body if len(levels) == 1 and levels[0] == 0: levels = None # all levels out = sct_labels.label_vertebrae(img, levels) elif arguments.vert_continuous: out = sct_labels.continuous_vertebral_levels(img) dtype = 'float32' elif arguments.MSE is not None: ref = Image(arguments.MSE) mse = sct_labels.compute_mean_squared_error(img, ref) printv(f"Computed MSE: {mse}") return elif arguments.remove_reference is not None: ref = Image(arguments.remove_reference) out = sct_labels.remove_missing_labels(img, ref) elif arguments.remove_sym is not None: # first pass use img as source ref = Image(arguments.remove_reference) out = sct_labels.remove_missing_labels(img, ref) # second pass use previous pass result as reference ref_out = sct_labels.remove_missing_labels(ref, out) ref_out.save(path=ref.absolutepath) elif arguments.remove is not None: labels = arguments.remove out = sct_labels.remove_labels_from_image(img, labels) elif arguments.keep is not None: labels = arguments.keep out = sct_labels.remove_other_labels_from_image(img, labels) elif arguments.create_viewer is not None: msg = "" if arguments.msg is None else f"{arguments.msg}\n" if arguments.ilabel is not None: input_labels_img = Image(arguments.ilabel) out = launch_manual_label_gui( img, input_labels_img, parse_num_list(arguments.create_viewer), msg) else: out = launch_sagittal_viewer( img, parse_num_list(arguments.create_viewer), msg) printv("Generating output files...") out.save(path=output_fname, dtype=dtype) display_viewer_syntax([input_filename, output_fname]) if arguments.qc is not None: generate_qc(fname_in1=input_filename, fname_seg=output_fname, args=argv, path_qc=os.path.abspath(arguments.qc), dataset=arguments.qc_dataset, subject=arguments.qc_subject, process='sct_label_utils')
def main(argv=None): parser = get_parser() arguments = parser.parse_args(argv) verbose = arguments.v set_loglevel(verbose=verbose) model = arguments.model if "," in arguments.radius: patch_radius = list_type(",", int)(arguments.radius) else: patch_radius = int(arguments.radius) file_to_denoise = arguments.i bval_file = arguments.b output_file_name = arguments.o path, file, ext = extract_fname(file_to_denoise) img = nib.load(file_to_denoise) bvals = np.loadtxt(bval_file) hdr_0 = img.get_header() data = img.get_data() printv('Applying Patch2Self Denoising...') den = patch2self(data, bvals, patch_radius=patch_radius, model=model, verbose=True) if verbose == 2: import matplotlib.pyplot as plt fig, ax = plt.subplots(1, 3) axial_middle = int(data.shape[2] / 2) middle_vol = int(data.shape[3] / 2) before = data[:, :, axial_middle, middle_vol].T ax[0].imshow(before, cmap='gray', origin='lower') ax[0].set_title('before') after = den[:, :, axial_middle, middle_vol].T ax[1].imshow(after, cmap='gray', origin='lower') ax[1].set_title('after') difference = np.absolute(after.astype('f8') - before.astype('f8')) ax[2].imshow(difference, cmap='gray', origin='lower') ax[2].set_title('difference') for i in range(3): ax[i].set_axis_off() plt.show() # Save files img_denoise = nib.Nifti1Image(den, None, hdr_0) diff_4d = np.absolute(den.astype('f8') - data.astype('f8')) img_diff = nib.Nifti1Image(diff_4d, None, hdr_0) if output_file_name is not None: output_file_name_den = output_file_name output_file_name_diff = add_suffix(output_file_name, "_difference") else: output_file_name_den = file + '_patch2self_denoised' + ext output_file_name_diff = file + '_patch2self_difference' + ext nib.save(img_denoise, output_file_name_den) nib.save(img_diff, output_file_name_diff) printv('\nDone! To view results, type:', verbose) printv('fsleyes ' + file_to_denoise + ' ' + output_file_name + ' & \n', verbose, 'info')