def _resample_slicewise(self, image, p_resample, type_img, image_ref=None): """ Resample at a fixed resolution to make sure the cord always appears with similar scale, regardless of the native resolution of the image. Assumes SAL orientation. :param image: Image() to resample :param p_resample: float: Resampling resolution in mm :param type_img: {'im', 'seg'}: If im, interpolate using spline. If seg, interpolate using linear then binarize. :param image_ref: Destination Image() to resample image to. :return: """ dict_interp = {'im': 'spline', 'seg': 'linear'} # Create nibabel object nii = Nifti1Image(image.data, image.hdr.get_best_affine()) # If no reference image is provided, resample to specified resolution if image_ref is None: # Resample to px x p_resample x p_resample mm (orientation is SAL by convention in QC module) nii_r = resample_nib(nii, new_size=[image.dim[4], p_resample, p_resample], new_size_type='mm', interpolation=dict_interp[type_img]) # Otherwise, resampling to the space of the reference image else: # Create nibabel object for reference image nii_ref = Nifti1Image(image_ref.data, image_ref.hdr.get_best_affine()) nii_r = resample_nib(nii, image_dest=nii_ref, interpolation=dict_interp[type_img]) # If resampled image is a segmentation, binarize using threshold at 0.5 if type_img == 'seg': img_r_data = (nii_r.get_data() > 0.5) * 1 else: img_r_data = nii_r.get_data() # Create Image objects image_r = Image(img_r_data, hdr=nii_r.header, dim=nii_r.header.get_data_shape()). \ change_orientation(image.orientation) return image_r
def test_affines_save(image_orientation): """Check implementation of exporting affines to formats.""" # Generate test transform img = loadimg(SOMEONES_ANATOMY) imgaff = img.affine if image_orientation == 'LAS': newaff = imgaff.copy() newaff[0, 0] *= -1.0 newaff[0, 3] = imgaff.dot(np.hstack( (np.array(img.shape[:3]) - 1, 1.0)))[0] img = Nifti1Image(np.flip(img.get_fdata(), 0), newaff, img.header) elif image_orientation == 'LPS': newaff = imgaff.copy() newaff[0, 0] *= -1.0 newaff[1, 1] *= -1.0 newaff[:2, 3] = imgaff.dot(np.hstack( (np.array(img.shape[:3]) - 1, 1.0)))[:2] img = Nifti1Image(np.flip(np.flip(img.get_fdata(), 0), 1), newaff, img.header) elif image_orientation == 'oblique': A = shape_zoom_affine(img.shape, img.header.get_zooms(), x_flip=False) R = from_matvec(euler2mat(x=0.09, y=0.001, z=0.001)) newaff = R.dot(A) img = Nifti1Image(img.get_fdata(), newaff, img.header) img.header.set_qform(newaff, 1) img.header.set_sform(newaff, 1) T = from_matvec(euler2mat(x=0.9, y=0.001, z=0.001), [4.0, 2.0, -1.0]) xfm = nbl.Affine(T) xfm.reference = img itk = nbl.load(os.path.join(data_path, 'affine-%s-itk.tfm' % image_orientation), fmt='itk') fsl = np.loadtxt( os.path.join(data_path, 'affine-%s.fsl' % image_orientation)) afni = np.loadtxt( os.path.join(data_path, 'affine-%s.afni' % image_orientation)) with InTemporaryDirectory(): xfm.to_filename('M.tfm', fmt='itk') xfm.to_filename('M.fsl', fmt='fsl') xfm.to_filename('M.afni', fmt='afni') nb_itk = nbl.load('M.tfm', fmt='itk') nb_fsl = np.loadtxt('M.fsl') nb_afni = np.loadtxt('M.afni') assert_equal(itk, nb_itk) assert_almost_equal(fsl, nb_fsl) assert_almost_equal(afni, nb_afni) # Create version not aligned to canonical
def test_smooth_image(caplog): # Test image smoothing data = np.arange(24).reshape((2, 3, 4)) aff = np.diag([-4, 5, 6, 1]) img = Nifti1Image(data, aff) # Zero smoothing is no-op out_img = smooth_image(img, 0) assert_array_equal(out_img.affine, img.affine) assert_array_equal(out_img.shape, img.shape) assert_array_equal(out_img.dataobj, data) # Isotropic smoothing sd = fwhm2sigma(np.true_divide(8, [4, 5, 6])) exp_out = spnd.gaussian_filter(data, sd, mode='nearest') assert_array_equal(smooth_image(img, 8).dataobj, exp_out) assert_array_equal(smooth_image(img, [8, 8, 8]).dataobj, exp_out) with pytest.raises(ValueError): smooth_image(img, [8, 8]) # Not isotropic mixed_sd = fwhm2sigma(np.true_divide([8, 7, 6], [4, 5, 6])) exp_out = spnd.gaussian_filter(data, mixed_sd, mode='nearest') assert_array_equal(smooth_image(img, [8, 7, 6]).dataobj, exp_out) # In 2D img_2d = Nifti1Image(data[0], aff) exp_out = spnd.gaussian_filter(data[0], sd[:2], mode='nearest') assert_array_equal(smooth_image(img_2d, 8).dataobj, exp_out) assert_array_equal(smooth_image(img_2d, [8, 8]).dataobj, exp_out) with pytest.raises(ValueError): smooth_image(img_2d, [8, 8, 8]) # Isotropic in 4D has zero for last dimension in scalar case data_4d = np.arange(24 * 5).reshape((2, 3, 4, 5)) img_4d = Nifti1Image(data_4d, aff) exp_out = spnd.gaussian_filter(data_4d, list(sd) + [0], mode='nearest') assert_array_equal(smooth_image(img_4d, 8).dataobj, exp_out) # But raises error for vector case with pytest.raises(ValueError): smooth_image(img_4d, [8, 8, 8]) # mode, cval exp_out = spnd.gaussian_filter(data, sd, mode='constant') assert_array_equal(smooth_image(img, 8, mode='constant').dataobj, exp_out) exp_out = spnd.gaussian_filter(data, sd, mode='constant', cval=99) assert_array_equal( smooth_image(img, 8, mode='constant', cval=99).dataobj, exp_out) # out_class img_ni1 = Nifti1Image(data, np.eye(4)) img_ni2 = Nifti2Image(data, np.eye(4)) # Default is Nifti1Image with caplog.at_level( logging.CRITICAL ): # Here and below, suppress logs when changing classes assert smooth_image(img_ni2, 0).__class__ == Nifti1Image # Can be overridden with caplog.at_level(logging.CRITICAL): assert smooth_image(img_ni1, 0, out_class=Nifti2Image).__class__ == Nifti2Image # None specifies out_class from input assert smooth_image(img_ni2, 0, out_class=None).__class__ == Nifti2Image
def generate_average_density_map(data_dir, file_path_data, tract, space): '''Loads and averages the tract density maps in the file_paths list. Then saves averaged density map in data/temp folder so it can be sent in a response later. ''' data = np.zeros((len(file_path_data), 91, 109, 91), dtype=np.float32) for i in range(len(file_path_data)): subject_id = file_path_data[i][0] dataset_dir = file_path_data[i][1] method = file_path_data[i][2] data[i] = nib.load( file_path(data_dir, dataset_dir, tract.file_path, method, subject_id, space, tract.code, 'nii.gz')).get_data() data[np.nonzero(data)] = 1 # binarize before averaging mean = np.mean(data, axis=0) # add the template affine and header to the averaged nii to ensure correct alignment in XTK library # maybe cache the template affine and header on startup so we don't need to do this load here? template = nib.load(data_dir + '/' + TEMPLATE_FILE_NAME) new_img = Nifti1Image(mean.astype(np.float32), template.affine, template.header) temp_file_path = temp_file(data_dir, tract.code, '.nii.gz') nib.save(new_img, temp_file_path) return temp_file_path
def _resample(self, image, p_resample, type, image_ref=None): """ Resample at a fixed resolution to make sure the cord always appears with similar scale, regardless of the native resolution of the image. Assumes SAL orientation. :param image: Image() to resample :param p_resample: float: Resampling resolution in mm :param type: {'im', 'seg'}: If im, interpolate using spline. If seg, interpolate using linear then binarize. :param image_ref: Destination Image() to resample image to. :return: """ # If no reference image is provided, create nipy object and resample using resample_nipy() if image_ref is None: dict_interp = {'im': 'spline', 'seg': 'linear'} # Create nibabel object nii = Nifti1Image(image.data, image.hdr.get_best_affine()) img = nifti2nipy(nii) # Resample to px x p_resample x p_resample mm (orientation is SAL by convention in QC module) img_r = resample_nipy(img, new_size=str(image.dim[4]) + 'x' + str(p_resample) + 'x' + str(p_resample), new_size_type='mm', interpolation=dict_interp[type]) # If segmentation, binarize using threshold at 0.5 if type == 'seg': img_r_data = (img_r.get_data() > 0.5) * 1 else: img_r_data = img_r.get_data() nii_r = nipy2nifti(img_r) # Create Image objects image_r = Image(img_r_data, hdr=nii_r.header, dim=nii_r.header.get_data_shape()). \ change_orientation(image.orientation) # If resampling to reference image, use Image() built-in resampling function to ref image else: dict_interp = {'im': 3, 'seg': 0} image_r = image.interpolate_from_image(image_ref, interpolation_mode=dict_interp[type], border='nearest') return image_r
def smooth_image_file(in_file, smooth_file, sigma=0): img = nii_io.readnii(in_file) img_data = img.get_data() smooth_img_data = smooth_image(img_data, sigma) smooth_img = Nifti1Image(smooth_img_data, affine=img.get_affine(), header=img.get_header()) nii_io.writenii(smooth_file, smooth_img)
def subject_averaged_MD(subject_ids_dataset_paths, data_dir): template = nib.load(data_dir + '/' + TEMPLATE_FILE_NAME) new_img = Nifti1Image( subject_averaged_map(subject_ids_dataset_paths, 'MD', data_dir), template.affine, template.header) file_path = temp_file(data_dir, 'MD', '.nii.gz') nib.save(new_img, file_path) return file_path
def process_subject( input_files: str, peaks_file: str, subject_id: str, normalize: bool = False, wm: str = None, gm: str = None, csf: str = None, interface: str = None ) -> Tuple[np.ndarray, List, List, Dict, np.ndarray, np.ndarray]: affine = nib.load(input_files[0]).affine input_volumes = [nib.load(f).get_fdata() for f in input_files] for i, v in enumerate(input_volumes): if len(v.shape) == 3: input_volumes[i] = v[..., None] peaks_image = nib.load(peaks_file) wm_mask_image = None if wm: wm_mask_image = nib.load(wm) gm_mask_image = None if gm: gm_mask_image = nib.load(gm) csf_mask_image = None if csf: csf_mask_image = nib.load(csf) interface_mask_image = None if interface: interface_mask_image = nib.load(interface) if normalize: print('Normalizing signal volume') input_volume = normalize_data_volume(input_volumes[0]) else: input_volume = input_volumes[0] inputs = np.concatenate([input_volume] + input_volumes[1:], axis=-1) # Save processed data input_image = Nifti1Image(inputs, affine) return (input_image, peaks_image, wm_mask_image, gm_mask_image, csf_mask_image, interface_mask_image)
def _reorient_to_ras(img: Nifti1Image) -> Nifti1Image: ''' Re-orient image to RAS Args: img: Image to re-orient to match ref image Returns: img re-oriented to RAS ''' img = nimg.load_img(img) ras_ornt = nib.orientations.axcodes2ornt(('R', 'A', 'S')) img_ornt = nib.orientations.axcodes2ornt( nib.orientations.aff2axcodes(img.affine)) img2ref = nib.orientations.ornt_transform(img_ornt, ras_ornt) return img.as_reoriented(img2ref)
def jacobian_det_image(in_file, out_file, sigma=0): nii = nii_io.readnii(in_file) nii_data = nii.get_data() if len(nii_data.shape) != 4: raise ValueError( ' Expecting a 4D file containing vector fields. The dimensions of ' + in_file + ' are ' + str(nii_data.shape) + '.\n') # TODO: Change this to a custom exception in future v1 = nii_data[:, :, :, 0] v2 = nii_data[:, :, :, 1] v3 = nii_data[:, :, :, 2] detJ, J = jacobian(v1, v2, v3) detJ_smooth = smooth_image(detJ, sigma) detJ_smooth_img = Nifti1Image(detJ_smooth, affine=nii.get_affine(), header=nii.get_header()) nii_io.writenii(out_file, detJ_smooth_img)
def test_resample_to_output(): # Test routine to sample iamges to output space # Image aligned to output axes - no-op data = np.arange(24).reshape((2, 3, 4)) img = Nifti1Image(data, np.eye(4)) # Check default resampling img2 = resample_to_output(img) assert_array_equal(img2.shape, (2, 3, 4)) assert_array_equal(img2.affine, np.eye(4)) assert_array_equal(img2.dataobj, data) # Check resampling with different voxel size specifications for vox_sizes in (None, 1, [1, 1, 1]): img2 = resample_to_output(img, vox_sizes) assert_array_equal(img2.shape, (2, 3, 4)) assert_array_equal(img2.affine, np.eye(4)) assert_array_equal(img2.dataobj, data) img2 = resample_to_output(img, vox_sizes) # Check 2D works img_2d = Nifti1Image(data[0], np.eye(4)) for vox_sizes in (None, 1, (1, 1), (1, 1, 1)): img3 = resample_to_output(img_2d, vox_sizes) assert_array_equal(img3.shape, (3, 4, 1)) assert_array_equal(img3.affine, np.eye(4)) assert_array_equal(img3.dataobj, data[0][..., None]) # Even 1D img_1d = Nifti1Image(data[0, 0], np.eye(4)) img3 = resample_to_output(img_1d) assert_array_equal(img3.shape, (4, 1, 1)) assert_array_equal(img3.affine, np.eye(4)) assert_array_equal(img3.dataobj, data[0, 0][..., None, None]) # But 4D does not img_4d = Nifti1Image(data.reshape(2, 3, 2, 2), np.eye(4)) with pytest.raises(ValueError): resample_to_output(img_4d) # Run vox2vox_out tests, checking output shape, coordinate transform for in_shape, in_aff, vox, out_shape, out_aff in get_outspace_params(): # Allow for expansion of image shape from < 3D in_n_dim = len(in_shape) if in_n_dim < 3: in_shape = in_shape + (1,) * (3 - in_n_dim) if not vox is None: vox = vox + (1,) * (3 - in_n_dim) assert len(out_shape) == in_n_dim out_shape = out_shape + (1,) * (3 - in_n_dim) img = Nifti1Image(np.ones(in_shape), in_aff) out_img = resample_to_output(img, vox) assert_all_in(in_shape, in_aff, out_img.shape, out_img.affine) assert out_img.shape == out_shape assert_almost_equal(out_img.affine, out_aff) # Check data is as expected with some transforms # Flip first axis out_img = resample_to_output(Nifti1Image(data, np.diag([-1, 1, 1, 1]))) assert_array_equal(out_img.dataobj, np.flipud(data)) # Subsample voxels out_img = resample_to_output(Nifti1Image(data, np.diag([4, 5, 6, 1]))) exp_out = spnd.affine_transform(data, [1/4, 1/5, 1/6], output_shape = (5, 11, 19)) assert_array_equal(out_img.dataobj, exp_out) # Unsubsample with voxel sizes out_img = resample_to_output(Nifti1Image(data, np.diag([4, 5, 6, 1])), [4, 5, 6]) assert_array_equal(out_img.dataobj, data) # A rotation to test nearest, order, cval rot_3 = from_matvec(euler2mat(np.pi / 4), [0, 0, 0]) rot_3_img = Nifti1Image(data, rot_3) out_img = resample_to_output(rot_3_img) exp_shape = (4, 4, 4) assert out_img.shape == exp_shape exp_aff = np.array([[1, 0, 0, -2 * np.cos(np.pi / 4)], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) assert_almost_equal(out_img.affine, exp_aff) rzs, trans = to_matvec(np.dot(npl.inv(rot_3), exp_aff)) exp_out = spnd.affine_transform(data, rzs, trans, exp_shape) assert_almost_equal(out_img.dataobj, exp_out) # Order assert_almost_equal( resample_to_output(rot_3_img, order=0).dataobj, spnd.affine_transform(data, rzs, trans, exp_shape, order=0)) # Cval assert_almost_equal( resample_to_output(rot_3_img, cval=99).dataobj, spnd.affine_transform(data, rzs, trans, exp_shape, cval=99)) # Mode assert_almost_equal( resample_to_output(rot_3_img, mode='nearest').dataobj, spnd.affine_transform(data, rzs, trans, exp_shape, mode='nearest')) # out_class img_ni1 = Nifti2Image(data, np.eye(4)) img_ni2 = Nifti2Image(data, np.eye(4)) # Default is Nifti1Image assert resample_to_output(img_ni2).__class__ == Nifti1Image # Can be overriden assert resample_to_output(img_ni1, out_class=Nifti2Image).__class__ == Nifti2Image # None specifies out_class from input assert resample_to_output(img_ni2, out_class=None).__class__ == Nifti2Image
def plotGlassbrainSlices(niftipath, mnipath, ortho='z', nRows=2, nCuts=6, threshpos=0, threshneg=0, figLayout='Both', showLRannot=True, findOptimalCut=True, imageType='svg'): """ Creates nice glassbrain slice figures in the direction x, y and z """ # Initiation of relevant parameters img = nb.load(niftipath) lineW = 2. / (nRows + int((figLayout == 'Brain' or figLayout == 'Both'))) # Reduce 4D volume to 3D if len(img.shape) == 4: data4D = img.get_data() data4D = data4D.reshape(data4D.shape[:-1]) img = Nifti1Image(data4D, img.get_affine()) # Get voxel extend in all directions dirMin = np.dot(img.get_affine(), [0, 0, 0, 1])[:3] dirMax = np.dot(img.get_affine(), np.array(img.shape).tolist() + [1])[:3] if findOptimalCut: # Find cuts automatically cut_coords = find_cut_slices(img, direction=ortho, n_cuts=nCuts) else: # Split orientation in x-equal parts cut_coords = getEqualSpacing(dirMin, dirMax, ortho, nCuts) # Split cuts according nRows cut_coords = [cut_coords[int(i * len(cut_coords) / np.float(nRows)): int((i + 1) * len(cut_coords) / np.float(nRows))] for i in range(nRows)] # Create Slices for i in range(nRows): # Create axes for plotting ax = plt.subplot(nRows + int((figLayout == 'Brain' or figLayout == 'Both')), 1, i + 1) # Plot the white background for all slices as a zeros value brain # (without it, the view focuses around the first area plotted) zerobrain = Nifti1Image(img.get_data() * 0, img.get_affine()) brain = plot_roi( zerobrain, zerobrain, colorbar=False, cut_coords=cut_coords[i], display_mode=ortho, alpha=1, draw_cross=False, cmap=plt.cm.gray, black_bg=False, axes=ax, annotate=False) # Plot positive values posdata = np.copy(img.get_data()) posdata[posdata <= threshpos] = 0.001 # = 0 crashes contour function posbrain = Nifti1Image(posdata, img.get_affine()) brain.add_contours( posbrain, filled=False, cmap=plt.cm.hot, alpha=1, linewidths=lineW) # Plot negative values negdata = np.copy(img.get_data()) negdata[negdata >= -threshneg] = 0.001 # = 0 crashes contour function negbrain = Nifti1Image(negdata, img.get_affine()) brain.add_contours( negbrain, filled=False, cmap=plt.cm.winter, alpha=1, linewidths=lineW) # Plot outer MNI contours brain.add_contours( smooth_img(mnipath, 4), alpha=1, filled=False, levels=[100], linewidths=lineW, cmap=plt.cm.gray) # Plot inner MNI contours brain.add_contours( nb.load(mnipath), alpha=0.8, levels=[5000], linewidths=lineW, cmap=plt.cm.gray) # Add annotation if requested if figLayout == 'Both' or figLayout == 'Number': brain.annotate(left_right=showLRannot, size=int(12 * lineW)) # Plot overview Brain at the bottom if figLayout == 'Brain' or figLayout == 'Both': # Create axes for overview brain ax = plt.subplot(nRows + 1, 1, nRows + 1) # Find overview view direction if ortho == 'z': direction = 'x' elif ortho == 'x': direction = 'z' elif ortho == 'y': direction = 'z' # Plot the white backgroundas a zeros value brain brain = plot_roi( zerobrain, zerobrain, colorbar=False, cut_coords=[0], display_mode=direction, alpha=1, draw_cross=False, cmap=plt.cm.gray, black_bg=False, axes=ax, annotate=False) # Plot positive values brain.add_contours( posbrain, filled=False, cmap=plt.cm.hot, alpha=1, linewidths=lineW) # Plot negative values brain.add_contours( negbrain, filled=False, cmap=plt.cm.winter, alpha=1, linewidths=lineW) # Plot outer MNI contours brain.add_contours( smooth_img(mnipath, 4), alpha=1, filled=False, levels=[100], linewidths=lineW, cmap=plt.cm.gray) # Plot inner MNI contours brain.add_contours( nb.load(mnipath), alpha=0.8, levels=[5000], linewidths=lineW, cmap=plt.cm.gray) # Plot the line indicating the cut for i in np.array(cut_coords).flatten(): if ortho == 'z' or ortho == 'y': ax.plot([-100, 100], [i, i], 'k-', lw=lineW) elif ortho == 'x': ax.plot([i, i], [-100, 100], 'k-', lw=lineW) if ortho == 'z': ax.axis((-300.0, 300.0, dirMin[2], dirMax[2])) elif ortho == 'y': ax.axis((-300.0, 300.0, dirMin[1], dirMax[1])) elif ortho == 'x': stretcher = (nRows + 1) / 2. ax.axis((-300.0 * stretcher, 300.0 * stretcher, -100.0, 100.0)) # Add annotation if requested if figLayout == 'Both' or figLayout == 'Number': brain.annotate(left_right=showLRannot, size=int(12 * lineW)) # Get file prefix if niftipath.endswith('.nii'): filename = opb(niftipath)[:-4] elif niftipath.endswith('.nii.gz'): filename = opb(niftipath)[:-7] # Create output folder path2Figure = opj(os.path.split(os.path.realpath(niftipath))[0], 'figures') if not os.path.exists(opj(path2Figure)): os.makedirs(opj(path2Figure)) # Save figure figname = '_'.join([filename, '%s-cut' % ortho]) plt.savefig(opj(path2Figure, '%s.%s' % (figname, imageType))) plt.clf()
import numpy as np import pandas as pd import nibabel as nib from nibabel.nifti1 import Nifti1Image from nilearn.input_data import NiftiLabelsMasker epi = nib.load(snakemake.input.vol) csf = nib.load(snakemake.input.csf) wm = nib.load(snakemake.input.wm) img = Nifti1Image(csf.get_fdata(), epi.affine, csf.header) masker = NiftiLabelsMasker(labels_img=img, standardize=False) time_series1 = masker.fit_transform(epi) img = Nifti1Image(wm.get_fdata(), epi.affine, wm.header) masker = NiftiLabelsMasker(labels_img=img, standardize=False) time_series2 = masker.fit_transform(epi) # Concatenate timeseries df1 = pd.DataFrame({ 'CSF': time_series1[:, 0], 'WhiteMatter': time_series2[:, 0] }) # Load movement parameters (and their derivatives) names = ['X', 'Y', 'Z', 'RotX', 'RotY', 'RotZ'] df2 = pd.read_csv(snakemake.input.movreg, names=names, header=None, delim_whitespace=True)
import numpy as np import pandas as pd import nibabel as nib from nibabel.nifti1 import Nifti1Image t1 = nib.load(snakemake.input.t1) t1_vals = t1.get_fdata() lh_cerebellum = nib.load(snakemake.input.lh_cerebellum).get_fdata() rh_cerebellum = nib.load(snakemake.input.rh_cerebellum).get_fdata() combined = np.zeros((t1.shape)) combined[(lh_cerebellum > 0) & (t1_vals < 2000)] = 8 combined[(rh_cerebellum > 0) & (t1_vals < 2000)] = 47 img = Nifti1Image(combined, t1.affine, t1.header) nib.save(img, snakemake.output[0])
def _get_input_names(data_dict): """Get names from dict Read in the data_dict to return the relevant file names. Will also add the default values if trDuration, isi, or burn_in haven't been set Parameters ---------- data_dict : dict A dictionary to specify the parameters used for making data, specifying the following keys numTRs - int - Specify the number of time points multivariate_patterns - bool - Is the difference between conditions univariate (0) or multivariate (1) different_ROIs - bool - Are there different ROIs for each condition ( 1) or is it in the same ROI (0). If it is the same ROI and you are using univariate differences, the second condition will have a smaller evoked response than the other. event_duration - int - How long, in seconds, is each event scale_percentage - float - What is the percent signal change trDuration - float - How many seconds per volume save_dicom - bool - Save to data as a dicom (1) or numpy (0) save_realtime - bool - Do you want to save the data in real time (1) or as fast as possible (0)? isi - float - What is the time between each event (in seconds) burn_in - int - How long before the first event (in seconds) Returns ---------- ROI_A_file : str Path to ROI for condition A ROI_B_file : str Path to ROI for condition B template_path : str Path to template file for data noise_dict_file : str Path to file containing parameters for noise simulation """ # Load in the ROIs if data_dict.get('ROI_A_file') is None: vol = resource_stream(__name__, "sim_parameters/ROI_A.nii.gz").read() ROI_A_file = Nifti1Image.from_bytes(gzip.decompress(vol)).get_data() else: ROI_A_file = data_dict['ROI_A_file'] if data_dict.get('ROI_B_file') is None: vol = resource_stream(__name__, "sim_parameters/ROI_B.nii.gz").read() ROI_B_file = Nifti1Image.from_bytes(gzip.decompress(vol)).get_data() else: ROI_B_file = data_dict['ROI_B_file'] # Get the path to the template if data_dict.get('template_path') is None: vol = resource_stream(__name__, "sim_parameters/sub_template.nii.gz").read() template_path = Nifti1Image.from_bytes(gzip.decompress(vol)).get_data() else: template_path = data_dict['template_path'] # Load in the noise dict if supplied if data_dict.get('noise_dict_file') is None: file = resource_stream(__name__, 'sim_parameters/sub_noise_dict.txt').read() noise_dict_file = file else: noise_dict_file = data_dict['noise_dict_file'] # Return the paths return ROI_A_file, ROI_B_file, template_path, noise_dict_file
def save(data, filename): _save_nifti1(Nifti1Image(data, None), filename)
import pytest import os import time import glob from pkg_resources import resource_stream from typing import Dict from nibabel.nifti1 import Nifti1Image import gzip # Test that it crashes without inputs with pytest.raises(TypeError): gen.generate_data() # type: ignore data_dict = {} # type: Dict vol = resource_stream(gen.__name__, "sim_parameters/ROI_A.nii.gz").read() data_dict['ROI_A_file'] = Nifti1Image.from_bytes( gzip.decompress(vol)).get_data() vol = resource_stream(gen.__name__, "sim_parameters/ROI_B.nii.gz").read() data_dict['ROI_B_file'] = Nifti1Image.from_bytes( gzip.decompress(vol)).get_data() vol = resource_stream(gen.__name__, "sim_parameters/sub_template.nii.gz").read() data_dict['template_path'] = Nifti1Image.from_bytes( gzip.decompress(vol)).get_data() noise_dict_file = resource_stream(gen.__name__, "sim_parameters/sub_noise_dict.txt").read() data_dict['noise_dict_file'] = noise_dict_file data_dict['numTRs'] = 30 data_dict['event_duration'] = 2 data_dict['scale_percentage'] = 1 data_dict['different_ROIs'] = True data_dict['multivariate_pattern'] = False
def rtss_to_nifti(input_rtstruct_dicom: str, input_structural_dicom: str, output_rtss_nii: str, output_struct_nii: str, exclude_labels: list, write_one_roi_per_file: bool): ''' Convert RTSTRUCT and structural DICOM to a NIFTI mask. ''' #1. read the structural image. dicomFiles = next(os.walk(input_structural_dicom))[2] numberOfDicomImages = len(dicomFiles) dicomsSorted = sort_dcms_by_slice_pos(input_structural_dicom, dicomFiles, stop_before_pixels=False) ds_struct = dicomsSorted[0]['dataset'] struct_voxels = voxel_array_from_sorted_dicoms(dicomsSorted) xPixelSize, yPixelSize = ds_struct.PixelSpacing[0], ds_struct.PixelSpacing[ 1] xyPixelSize = 0.5 * (xPixelSize + yPixelSize) #for now; remember to update with DistanceBetweenSlices zPixelSize = ds_struct.SliceThickness imwidth, imheight, imdepth = ds_struct.Rows, ds_struct.Columns, len( dicomsSorted) voxel_vol_mm3 = xPixelSize * yPixelSize * zPixelSize if not write_one_roi_per_file: rtss_voxels = [np.zeros([imwidth, imheight, imdepth], dtype=np.uint16)] else: rtss_voxels = [] print('Voxel size: {} by {} by {} mm'.format(xPixelSize, yPixelSize, zPixelSize)) # Find position of first slice patientPosition = ds_struct.ImagePositionPatient patientStartingZ = dicomsSorted[0]['z'] mm_vox_size = np.array([1. / xPixelSize, 1. / yPixelSize, 1. / zPixelSize]) origin = np.array( [patientPosition[0], patientPosition[1], patientStartingZ]) print('Patient position is ', patientPosition[:2]) print('First slice at ', patientStartingZ) #2. read the RTSTRUCT. ds_rtss = pydicom.dcmread(input_rtstruct_dicom, stop_before_pixels=False) if [0x3006, 0x0020] not in ds_rtss: raise ValueError( 'Cannot find (0x3006,0020) StructureSetROISequence tag in RTSS file' ) structure_set_roi_sequence = ssrs = ds_rtss[(0x3006, 0x0020)]._value roi_contour_sequence = rcs = ds_rtss[(0x3006, 0x0039)] n = len(ssrs) print('Found {} structures'.format(n)) roi_list = [] current_region_code = 1 roi_file_index = 0 for ind in range(n): ss = ssrs[ind] roi_number = ss[(0x3006, 0x0022)].value roi_name = re.sub(r'\W+', '', ss[(0x3006, 0x0026)].value) print('ROI number {}, name {}'.format(roi_number, roi_name)) if roi_name.lower() in exclude_labels: print('skipping structure', roi_name) continue roi_contour = None #now find the matching ROI contour. for rc in roi_contour_sequence: #print ('comparing',rc[0x3006, 0x0084]._value,'and', roi_number) if rc[0x3006, 0x0084]._value == roi_number: roi_contour = rc break if not roi_contour: print('WARNING: no matching roi contour sequence for this ROI') continue display_color = roi_contour[0x3006, 0x002a] if ( 0x3006, 0x002a) in roi_contour else None print('display color:', display_color) if (0x3006, 0x0040) in roi_contour: contour_sequence = roi_contour[0x3006, 0x0040] else: print('WARNING: no matching contour sequence for this ROI') continue nContours = len(contour_sequence._value) #write rasterized data to image array. nptsAcc = 0 if write_one_roi_per_file: new_roi_voxels = np.zeros([imwidth, imheight, imdepth], dtype=np.uint16) rtss_voxels.append(new_roi_voxels) current_voxels = new_roi_voxels else: current_voxels = rtss_voxels[0] for k in range(nContours): contour = contour_sequence[k] npts = contour.NumberOfContourPoints nptsAcc += npts print('Contour {}, number of points: {}'.format(k + 1, npts)) pts = contour.ContourData poly2d, z = pts2poly(pts, origin, mm_vox_size) imslice = current_region_code * get_rasterized_poly_slice( poly2d, imwidth, imheight) rtss_voxels[roi_file_index][:, :, z] = imslice #get region properties. try: p = measure.regionprops( (current_voxels == current_region_code).astype(int))[0] vol_mm3 = p.area * voxel_vol_mm3 except: vol_mm3 = 0 print('volume:', vol_mm3, 'mm3') v = display_color.value color = '0x{:02X}{:02X}{:02X}'.format(int(v[0]), int(v[1]), int(v[2])) if not write_one_roi_per_file: out_file = output_rtss_nii else: out_file = output_rtss_nii + '_' + roi_name roi_descriptor = dict(roi_number=roi_number, roi_name=roi_name, display_color=color, num_contours=nContours, points_in_all_contours=nptsAcc, intensity_value=current_region_code, out_file_root=out_file, volume_mm3=vol_mm3) roi_list.append(roi_descriptor) #update appropriate counters if not write_one_roi_per_file: current_region_code += 1 else: roi_file_index += 1 #create and save nifti images. #flip axes to orient from DICOM (LPS) to RAS space flips = np.array([-1., -1., 1., 1.]) nifti_affine = np.diag( np.array([xPixelSize, yPixelSize, zPixelSize, 1]) * flips) nifti_affine[:3, 3] = origin * flips[:-1] nifti_image_struct = Nifti1Image(struct_voxels, nifti_affine) if not write_one_roi_per_file: nifti_image_roi = Nifti1Image(rtss_voxels[0], nifti_affine) print('writing', output_rtss_nii) nibabel.nifti1.save(nifti_image_roi, output_rtss_nii) else: for i in range(len(rtss_voxels)): nifti_image_roi = Nifti1Image(rtss_voxels[i], nifti_affine) outfile = roi_list[i]['out_file_root'] print('writing', outfile) nibabel.nifti1.save(nifti_image_roi, outfile) print('writing', output_rtss_nii + '.json') with open(output_rtss_nii + '.json', 'w') as fout: json.dump(roi_list, fout) print('writing', output_struct_nii) nibabel.nifti1.save(nifti_image_struct, output_struct_nii) print('done')
def _mask_img(n): img = np.ones((1, 1, n)) affine = np.eye(4) return Nifti1Image(img, affine=affine)
def test_resample_from_to(): # Test resampling from image to image / image space data = np.arange(24).reshape((2, 3, 4)) affine = np.diag([-4, 5, 6, 1]) img = Nifti1Image(data, affine) img.header['descrip'] = 'red shirt image' out = resample_from_to(img, img) assert_almost_equal(img.dataobj, out.dataobj) assert_array_equal(img.affine, out.affine) # Check resampling reverses effect of flipping axes # This will also test translations flip_ornt = np.array([[0, 1], [1, 1], [2, 1]]) for axis in (0, 1, 2): ax_flip_ornt = flip_ornt.copy() ax_flip_ornt[axis, 1] = -1 aff_flip_i = inv_ornt_aff(ax_flip_ornt, (2, 3, 4)) flipped_img = Nifti1Image(flip_axis(data, axis), np.dot(affine, aff_flip_i)) out = resample_from_to(flipped_img, ((2, 3, 4), affine)) assert_almost_equal(img.dataobj, out.dataobj) assert_array_equal(img.affine, out.affine) # A translation of one voxel on each axis trans_aff = from_matvec(np.diag([-4, 5, 6]), [4, -5, -6]) trans_img = Nifti1Image(data, trans_aff) out = resample_from_to(trans_img, img) exp_out = np.zeros_like(data) exp_out[:-1, :-1, :-1] = data[1:, 1:, 1:] assert_almost_equal(out.dataobj, exp_out) out = resample_from_to(img, trans_img) trans_exp_out = np.zeros_like(data) trans_exp_out[1:, 1:, 1:] = data[:-1, :-1, :-1] assert_almost_equal(out.dataobj, trans_exp_out) # Test mode with translation of first axis only # Default 'constant' mode first trans1_aff = from_matvec(np.diag([-4, 5, 6]), [4, 0, 0]) trans1_img = Nifti1Image(data, trans1_aff) out = resample_from_to(img, trans1_img) exp_out = np.zeros_like(data) exp_out[1:, :, :] = data[:-1, :, :] assert_almost_equal(out.dataobj, exp_out) # Then 'nearest' mode out = resample_from_to(img, trans1_img, mode='nearest') exp_out[0, :, :] = exp_out[1, :, :] assert_almost_equal(out.dataobj, exp_out) # Test order trans_p_25_aff = from_matvec(np.diag([-4, 5, 6]), [1, 0, 0]) trans_p_25_img = Nifti1Image(data, trans_p_25_aff) # Suprising to me, but all points outside are set to 0, even with NN out = resample_from_to(img, trans_p_25_img, order=0) exp_out = np.zeros_like(data) exp_out[1:, :, :] = data[1, :, :] assert_almost_equal(out.dataobj, exp_out) out = resample_from_to(img, trans_p_25_img) exp_out = spnd.affine_transform(data, [1, 1, 1], [-0.25, 0, 0], order=3) assert_almost_equal(out.dataobj, exp_out) # Test cval out = resample_from_to(img, trans_img, cval=99) exp_out = np.zeros_like(data) + 99 exp_out[1:, 1:, 1:] = data[:-1, :-1, :-1] assert_almost_equal(out.dataobj, exp_out) # Out class out = resample_from_to(img, trans_img) assert out.__class__ == Nifti1Image # By default, type of from_img makes no difference n1_img = Nifti2Image(data, affine) out = resample_from_to(n1_img, trans_img) assert out.__class__ == Nifti1Image # Passed as keyword arg out = resample_from_to(img, trans_img, out_class=Nifti2Image) assert out.__class__ == Nifti2Image # If keyword arg is None, use type of from_img out = resample_from_to(n1_img, trans_img, out_class=None) assert out.__class__ == Nifti2Image # to_img type irrelevant in all cases n1_trans_img = Nifti2Image(data, trans_aff) out = resample_from_to(img, n1_trans_img, out_class=None) assert out.__class__ == Nifti1Image # From 2D to 3D, error, the fixed affine is not invertible img_2d = Nifti1Image(data[:, :, 0], affine) with pytest.raises(AffineError): resample_from_to(img_2d, img) # 3D to 2D, we don't need to invert the fixed matrix out = resample_from_to(img, img_2d) assert_array_equal(out.dataobj, data[:, :, 0]) # Same for tuple as to_img imput out = resample_from_to(img, (img_2d.shape, img_2d.affine)) assert_array_equal(out.dataobj, data[:, :, 0]) # 4D input and output also OK data_4d = np.arange(24 * 5).reshape((2, 3, 4, 5)) img_4d = Nifti1Image(data_4d, affine) out = resample_from_to(img_4d, img_4d) assert_almost_equal(data_4d, out.dataobj) assert_array_equal(img_4d.affine, out.affine) # Errors trying to match 3D to 4D with pytest.raises(ValueError): resample_from_to(img_4d, img) with pytest.raises(ValueError): resample_from_to(img, img_4d)
import numpy as np import pandas as pd import nibabel as nib from nibabel.nifti1 import Nifti1Image from nilearn.input_data import NiftiLabelsMasker atlas = nib.load(snakemake.input.rois) labels = atlas.get_fdata() # Relabel and extract timeseries for CSF and WM labels img = np.zeros(labels.shape) img[(labels == 4) | (labels == 43)] = 1 # CSF img[labels > 5000] = 2 # WM tmp = Nifti1Image(img, atlas.affine, atlas.header) masker = NiftiLabelsMasker(labels_img=tmp, standardize=False) time_series1 = masker.fit_transform(snakemake.input.vol) # Then for whole brain (i.e., 'global') brain = np.zeros(labels.shape) brain[labels != 0] = 1 tmp = Nifti1Image(brain, atlas.affine, atlas.header) masker = NiftiLabelsMasker(labels_img=tmp, standardize=False) time_series2 = masker.fit_transform(snakemake.input.vol) # Concatenate timeseries df1 = pd.DataFrame({ 'CSF': time_series1[:, 0], 'WhiteMatter': time_series1[:, 1], 'GlobalSignal': time_series2[:, 0]
# Prepare masker & Correct affine template = load_mni152_template() basc = datasets.fetch_atlas_basc_multiscale_2015(version='sym')['scale444'] orig_filename='F:/sim/template/restbaseline.nii.gz' orig_img= image.load_img(orig_filename) brainmask = load_mni152_brain_mask() mem = Memory('nilearn_cache') masker = NiftiLabelsMasker(labels_img = basc, mask_img = brainmask, memory=mem, memory_level=1, verbose=0, detrend=False, standardize=False, high_pass=0.01,t_r=2, resampling_target='labels') masker.fit() # Prep Classification for s in np.arange(84,89):#range(suj):# for n in range(meas): sim_filename='F:/sim/sim_'+str(s+1)+'_'+ str(n+1)+ '.nii.gz' if os.path.exists(sim_filename): sim_img = image.load_img(sim_filename) sim=sim_img.get_data() data_sim=Nifti1Image(sim,orig_img.affine) roi = masker.transform(data_sim) save_name= 'F:/sim/mni/roi_mni_'+str(s+1)+'_'+str(n+1)+'.npz' np.savez_compressed(save_name,roi=roi) rest=roi[rest_mask] sio.savemat('F:/sim/rest/sim_'+str(s+1)+'_'+ str(n+1)+'_rest.mat', {'rest':rest})
s4_file_path = 'TESTDATASETB004_MNI_' s4_mmse = None #### Subject tract metrics #### #### Neuroimaging data #### affine = np.eye(4) nifti_dim = (91,109,91) template_filepath = 'mgtrk_atlas_template.nii.gz' template_nifti = Nifti1Image(np.ones(nifti_dim, dtype=np.int16), affine) s1_MD = Nifti1Image(0.5*np.ones(nifti_dim, dtype=np.int16), affine) s1_FA = Nifti1Image(0.5*np.ones(nifti_dim, dtype=np.int16), affine) s3_MD = Nifti1Image(1.5*np.ones(nifti_dim, dtype=np.int16), affine) s3_FA = Nifti1Image(1.5*np.ones(nifti_dim, dtype=np.int16), affine) s1_t1 = Nifti1Image(np.ones(nifti_dim, dtype=np.int16), affine) s3_t1 = Nifti1Image(np.ones(nifti_dim, dtype=np.int16), affine) empty_nifti = Nifti1Image(np.zeros(nifti_dim, dtype=np.int16), affine) lesion_filepath = 'lesion.nii.gz' test_lesion = Nifti1Image(np.ones(nifti_dim, dtype=np.int16), affine)