class SiemensSliceOrder(BaseInterface): input_spec = SingleInFile output_spec = SingleOutFile def _run_interface(self, runtime): fname = self.inputs.in_file # Determine number of slices # Assumes slice selection is on z axis. Usually true -- but always? n_slices = nib.load(fname).shape[2] slices = np.arange(1, n_slices + 1) if n_slices % 2: # Odd slice number starts with odd slices slice_order = np.r_[slices[::2], slices[1::2]] else: # Even slice number starts with even slices slice_order = np.r_[slices[1::2], slices[::2]] np.savetxt("slice_order.txt", slice_order, fmt="%d") return runtime _list_outputs = list_out_file("slice_order.txt")
class ExtractRealignmentTarget(BaseInterface): input_spec = SingleInFile output_spec = SingleOutFile def _run_interface(self, runtime): # Load the input timeseries img = nib.load(self.inputs.in_file) # Extract the target volume targ = self.extract_target(img) # Save a new 3D image targ_img = nib.Nifti1Image(targ, img.get_affine(), img.get_header()) targ_img.to_filename("example_func.nii.gz") return runtime def extract_target(self, img): """Return a 3D array with data from the middle TR.""" middle_vol = img.shape[-1] // 2 targ = np.empty(img.shape[:-1]) targ[:] = img.dataobj[..., middle_vol] return targ _list_outputs = list_out_file("example_func.nii.gz")
class PrepTimeseries(BaseInterface): input_spec = PrepTimeseriesInput output_spec = SingleOutFile def _run_interface(self, runtime): # Load the input timeseries img = nib.load(self.inputs.in_file) data = img.get_data() aff = img.get_affine() hdr = img.get_header() # Trim off the equilibrium TRs data = self.trim_timeseries(data) # Save the output timeseries as float32 hdr.set_data_dtype(np.float32) new_img = nib.Nifti1Image(data, aff, hdr) new_img.to_filename("timeseries.nii.gz") return runtime def trim_timeseries(self, data): """Remove frames from beginning of timeseries.""" return data[..., self.inputs.frames_to_toss:] _list_outputs = list_out_file("timeseries.nii.gz")
class ScaleTimeseries(BaseInterface): input_spec = ScaleTimeseriesInput output_spec = SingleOutFile def _run_interface(self, runtime): ts_img = nib.load(self.inputs.in_file) ts_data = ts_img.get_data() mask = nib.load(self.inputs.mask_file).get_data().astype(bool) # Flexibly get the statistic value. # This has to be stringly-typed because nipype # can't pass around functions stat_func = getattr(np, self.inputs.statistic) # Do the scaling scaled_ts = self.scale_timeseries(stat_func, ts_data, mask, self.inputs.target) # Save the resulting image scaled_img = nib.Nifti1Image(scaled_ts, ts_img.get_affine(), ts_img.get_header()) scaled_img.to_filename("timeseries_scaled.nii.gz") return runtime def scale_timeseries(self, stat_func, data, mask, target): """Make scale timeseries across four dimensions to a target.""" stat_value = stat_func(data[mask]) scale_value = target / stat_value scaled_data = data * scale_value return scaled_data _list_outputs = list_out_file("timeseries_scaled.nii.gz")
class UnwarpReport(BaseInterface): input_spec = UnwarpReportInput output_spec = SingleOutFile def _run_interface(self, runtime): # Make a discrete colormap cmap = mpl.colors.ListedColormap(["black", "#d65f5f", "white"]) # Initialize the figure f, axes = plt.subplots(1, 2, figsize=(9, 2.75), facecolor="black", edgecolor="black") for ax, fname in zip( axes, [self.inputs.orig_file, self.inputs.corrected_file]): # Combine the frames from this image and plot img = nib.load(fname) ax.imshow(self.combine_frames(img), cmap=cmap, vmin=0, vmax=2) ax.set_axis_off() # Save the figure and close f.subplots_adjust(0, 0, 1, 1, 0, 0) f.savefig("unwarping.png", facecolor="black", edgecolor="black") plt.close(f) return runtime def combine_frames(self, img): # Find a value to loosely segment the brain d = img.get_data() counts, bins = np.histogram(d[d > 0], 50) thresh = bins[np.diff(counts) > 0][0] # Show the middle slice middle = d.shape[0] // 2 # Combine a binary mask for each phase direction a = np.rot90(d[middle, ..., 0] > thresh) b = np.rot90(d[middle, ..., 1] > thresh) # Make an image showing overlap and divergence c = np.zeros_like(a, int) c[a ^ b] = 1 c[a & b] = 2 return c _list_outputs = list_out_file("unwarping.png")
class CoregReport(BaseInterface): input_spec = CoregReportInput output_spec = SingleOutFile def _run_interface(self, runtime): subjects_dir = os.environ["SUBJECTS_DIR"] wm_file = op.join(subjects_dir, self.inputs.subject_id, "mri/wm.mgz") wm_data = nib.load(wm_file).get_data().astype(bool).astype(int) m = Mosaic(self.inputs.in_file, wm_data, step=3) m.plot_contours(["#DD2222"]) m.savefig("func2anat.png") m.close() return runtime _list_outputs = list_out_file("func2anat.png")
class ExtractConfounds(BaseInterface): """Extract nuisance variables from anatomical sources.""" input_spec = ExtractConfoundsInput output_spec = SingleOutFile def _run_interface(self, runtime): # Load the brain images ts_data = nib.load(self.inputs.timeseries).get_data() wm_mask = nib.load(self.inputs.wm_mask).get_data() brain_mask = nib.load(self.inputs.brain_mask).get_data() # Set up the output dataframe wm_cols = [ "wm_{:d}".format(i) for i in range(self.inputs.n_components) ] cols = wm_cols + ["brain"] index = np.arange(ts_data.shape[-1]) out_df = pd.DataFrame(index=index, columns=cols, dtype=np.float) # Extract eigenvariates of the white matter timeseries wm_ts = ts_data[wm_mask.astype(bool)].T wm_pca = decomp.PCA(self.inputs.n_components) wm_comp = wm_pca.fit_transform(wm_ts) out_df[wm_cols] = wm_comp # Extract the mean whole-brain timeseries brain_ts = ts_data[brain_mask.astype(bool)].mean(axis=0) out_df["brain"] = brain_ts # Write out the resulting data to disk out_df.to_csv("nuisance_variables.csv", index=False) return runtime _list_outputs = list_out_file("nuisance_variables.csv")