def _run_interface(self, runtime): # Get a list of settings files. settings_files = self._get_settings() ants_args = self._get_ants_args() if not isdefined(self.inputs.initial_moving_transform): NIWORKFLOWS_LOG.info( "Estimating initial transform using AffineInitializer") init = AffineInitializer( fixed_image=ants_args["fixed_image"], moving_image=ants_args["moving_image"], num_threads=self.inputs.num_threads, ) init.resource_monitor = False init.terminal_output = "allatonce" init_result = init.run() # Save outputs (if available) init_out = _write_outputs(init_result.runtime, ".nipype-init") if init_out: NIWORKFLOWS_LOG.info( "Terminal outputs of initialization saved (%s).", ", ".join(init_out), ) ants_args[ "initial_moving_transform"] = init_result.outputs.out_file # For each settings file... for ants_settings in settings_files: NIWORKFLOWS_LOG.info("Loading settings from file %s.", ants_settings) # Configure an ANTs run based on these settings. self.norm = Registration(from_file=ants_settings, **ants_args) self.norm.resource_monitor = False self.norm.terminal_output = self.terminal_output cmd = self.norm.cmdline # Print the retry number and command line call to the log. NIWORKFLOWS_LOG.info("Retry #%d, commandline: \n%s", self.retry, cmd) self.norm.ignore_exception = True with open("command.txt", "w") as cmdfile: print(cmd + "\n", file=cmdfile) # Try running registration. interface_result = self.norm.run() if interface_result.runtime.returncode != 0: NIWORKFLOWS_LOG.warning("Retry #%d failed.", self.retry) # Save outputs (if available) term_out = _write_outputs(interface_result.runtime, ".nipype-%04d" % self.retry) if term_out: NIWORKFLOWS_LOG.warning("Log of failed retry saved (%s).", ", ".join(term_out)) else: runtime.returncode = 0 # Note this in the log. NIWORKFLOWS_LOG.info( "Successful spatial normalization (retry #%d).", self.retry) # Break out of the retry loop. return runtime self.retry += 1 # If all tries fail, raise an error. raise RuntimeError( "Robust spatial normalization failed after %d retries." % (self.retry - 1))
def _run_interface(self, runtime): # Get a list of settings files. settings_files = self._get_settings() ants_args = self._get_ants_args() if not isdefined(self.inputs.initial_moving_transform): NIWORKFLOWS_LOG.info('Estimating initial transform using AffineInitializer') init = AffineInitializer( fixed_image=ants_args['fixed_image'], moving_image=ants_args['moving_image'], num_threads=self.inputs.num_threads) init.resource_monitor = False init.terminal_output = 'allatonce' init_result = init.run() # Save outputs (if available) init_out = _write_outputs(init_result.runtime, '.nipype-init') if init_out: NIWORKFLOWS_LOG.info( 'Terminal outputs of initialization saved (%s).', ', '.join(init_out)) ants_args['initial_moving_transform'] = init_result.outputs.out_file # For each settings file... for ants_settings in settings_files: NIWORKFLOWS_LOG.info('Loading settings from file %s.', ants_settings) # Configure an ANTs run based on these settings. self.norm = Registration(from_file=ants_settings, **ants_args) self.norm.resource_monitor = False self.norm.terminal_output = self.terminal_output # Print the retry number and command line call to the log. NIWORKFLOWS_LOG.info( 'Retry #%d, commandline: \n%s', self.retry, self.norm.cmdline) self.norm.ignore_exception = True # Try running registration. interface_result = self.norm.run() if interface_result.runtime.returncode != 0: NIWORKFLOWS_LOG.warning('Retry #%d failed.', self.retry) # Save outputs (if available) term_out = _write_outputs(interface_result.runtime, '.nipype-%04d' % self.retry) if term_out: NIWORKFLOWS_LOG.warning( 'Log of failed retry saved (%s).', ', '.join(term_out)) else: runtime.returncode = 0 # Grab the outputs. self._results.update(interface_result.outputs.get()) if isdefined(self.inputs.moving_mask): self._validate_results() # Note this in the log. NIWORKFLOWS_LOG.info( 'Successful spatial normalization (retry #%d).', self.retry) # Break out of the retry loop. return runtime self.retry += 1 # If all tries fail, raise an error. raise RuntimeError( 'Robust spatial normalization failed after %d retries.' % (self.retry - 1))
def _run_interface(self, runtime): # Get a list of settings files. settings_files = self._get_settings() ants_args = self._get_ants_args() if not isdefined(self.inputs.initial_moving_transform): NIWORKFLOWS_LOG.info( 'Estimating initial transform using AffineInitializer') init = AffineInitializer(fixed_image=ants_args['fixed_image'], moving_image=ants_args['moving_image'], num_threads=self.inputs.num_threads) init.resource_monitor = False init.terminal_output = 'allatonce' init_result = init.run() # Save outputs (if available) init_out = _write_outputs(init_result.runtime, '.nipype-init') if init_out: NIWORKFLOWS_LOG.info( 'Terminal outputs of initialization saved (%s).', ', '.join(init_out)) ants_args[ 'initial_moving_transform'] = init_result.outputs.out_file # For each settings file... for ants_settings in settings_files: NIWORKFLOWS_LOG.info('Loading settings from file %s.', ants_settings) # Configure an ANTs run based on these settings. self.norm = Registration(from_file=ants_settings, **ants_args) self.norm.resource_monitor = False self.norm.terminal_output = self.terminal_output # Print the retry number and command line call to the log. NIWORKFLOWS_LOG.info('Retry #%d, commandline: \n%s', self.retry, self.norm.cmdline) self.norm.ignore_exception = True # Try running registration. interface_result = self.norm.run() if interface_result.runtime.returncode != 0: NIWORKFLOWS_LOG.warning('Retry #%d failed.', self.retry) # Save outputs (if available) term_out = _write_outputs(interface_result.runtime, '.nipype-%04d' % self.retry) if term_out: NIWORKFLOWS_LOG.warning('Log of failed retry saved (%s).', ', '.join(term_out)) else: runtime.returncode = 0 # Grab the outputs. self._results.update(interface_result.outputs.get()) if isdefined(self.inputs.moving_mask): self._validate_results() # Note this in the log. NIWORKFLOWS_LOG.info( 'Successful spatial normalization (retry #%d).', self.retry) # Break out of the retry loop. return runtime self.retry += 1 # If all tries fail, raise an error. raise RuntimeError( 'Robust spatial normalization failed after %d retries.' % (self.retry - 1))
def jip_align(source_file, target_file, outdir, jipdir, prefix="w", auto=False, non_linear=False, fslconfig=DEFAULT_FSL_PATH): """ Register a source image to a taget image using the 'jip_align' command. Parameters ---------- source_file: str (mandatory) the source Nifti image. target_file: str (mandatory) the target Nifti masked image. outdir: str (mandatory) the destination folder. jipdir: str (mandatory) the jip binary path. prefix: str (optional, default 'w') prefix the generated file with this character. auto: bool (optional, default False) if set control the JIP window with the script. non_linear: bool (optional, default False) in the automatic mode, decide or not to compute the non-linear deformation field. fslconfig: str (optional) the FSL .sh configuration file. Returns ------- register_file: str the registered image. register_mask_file: str the registered and masked image. native_masked_file: str the masked image in the native space. """ # Check input image orientation: must be the same same_orient, orients = check_orientation([source_file, target_file]) if not same_orient: print( "[WARNING] Source file '{0}' ({2}) and taget file '{1}' ({3}) " "must have the same orientation for JIP to work properly.".format( source_file, target_file, orients[0], orients[1])) # Try to init the affine deformation # ToDo: find a way to init the JIP deformation if False: nb_cpus = multiprocessing.cpu_count() init_file = os.path.join(outdir, "init_affine.mat") init = AffineInitializer() init.inputs.fixed_image = target_file init.inputs.moving_image = source_file init.inputs.num_threads = nb_cpus init.inputs.out_file = init_file init.run() init_source_file = os.path.join(outdir, "init_source.nii.gz") at = ApplyTransforms() at.inputs.dimension = 3 at.inputs.input_image = source_file at.inputs.reference_image = target_file at.inputs.output_image = init_source_file at.inputs.transforms = init_file at.inputs.interpolation = "BSpline" at.inputs.num_threads = nb_cpus at.run() # From https://github.com/ANTsX/ANTs/wiki/ITK-affine-transform-conversion # From https://github.com/netstim/leaddbs/blob/master/helpers/ea_antsmat2mat.m init_mat = loadmat(init_file) afftransform = init_mat["AffineTransform_double_3_3"] m_center = init_mat["fixed"] mat = numpy.eye(4) mat[:3, :3] = afftransform[:9].reshape(3, 3).T m_translation = afftransform[9:] m_offset = m_translation + m_center - numpy.dot(mat[:3, :3], m_center) mat[:3, 3] = m_offset.squeeze() mat = numpy.linalg.inv(mat) #rotation = swap_affine(axes="LPS") #mat = numpy.dot(rotation, mat) ras_to_lps = numpy.ones((4, 4)) ras_to_lps[2, :2] = -1 ras_to_lps[:2, 2:] = -1 mat = mat * ras_to_lps print(mat) trans, rot, zoom, shear = decompose44(mat) euler = numpy.asarray(mat2euler(rot, axes='sxyz')) * 180. / numpy.pi print(trans, euler, zoom, shear) align_file = os.path.join(outdir, "align.com") im = nibabel.load(source_file) orig = im.affine[:3, 3] print(orig) shift = orig - trans with open(align_file, "wt") as of: of.write("set registration-translations {0} \n".format( " ".join([str(elem) for elem in shift]))) # Change current working directory cwd = os.getcwd() os.chdir(outdir) # Only support uncompressed Nifti source_file = ungzip_file(source_file, prefix="", outdir=outdir) target_file = ungzip_file(target_file, prefix="", outdir=outdir) # Create jip environment jip_envriron = os.environ jip_envriron["JIP_HOME"] = os.path.dirname(jipdir) if "PATH" in jip_envriron: jip_envriron["PATH"] = jip_envriron["PATH"] + ":" + jipdir else: jip_envriron["PATH"] = jipdir # Copy source file align_file = os.path.join(outdir, "align.com") cmd = ["align", source_file, "-t", target_file] if auto: if non_linear: auto_cmd = cmd + ["-L", "111111111111", "-W", "111", "-a"] else: auto_cmd = cmd + ["-L", "111111000000", "-W", "000", "-A"] if os.path.isfile(align_file): auto_cmd += ["-I"] subprocess.call(auto_cmd, env=jip_envriron) else: print(" ".join(cmd)) subprocess.call(cmd, env=jip_envriron) if not os.path.isfile(align_file): raise ValueError( "No 'align.com' file in '{0}' folder. JIP has probably failed: " "'{1}'".format(outdir, " ".join(cmd))) # Get the apply nonlinear deformation jip batches aplly_nonlin_batch = os.path.join( os.path.dirname(preproc.__file__), "resources", "apply_nonlin.com") aplly_inv_nonlin_batch = os.path.join( os.path.dirname(preproc.__file__), "resources", "apply_inv_nonlin.com") # Resample the source image register_file = os.path.join(outdir, prefix + os.path.basename(source_file)) cmd = ["jip", aplly_nonlin_batch, source_file, register_file] subprocess.call(cmd, env=jip_envriron) # Apply mask if os.path.isfile(register_file + ".gz"): os.remove(register_file + ".gz") register_mask_fileroot = os.path.join( outdir, "m" + prefix + os.path.basename(source_file).split(".")[0]) register_mask_file = apply_mask( input_file=register_file, output_fileroot=register_mask_fileroot, mask_file=target_file, fslconfig=fslconfig) # Send back masked image to original space register_mask_file = ungzip_file(register_mask_file, prefix="", outdir=outdir) native_masked_file = os.path.join( outdir, "n" + prefix + os.path.basename(register_mask_file)) cmd = ["jip", aplly_inv_nonlin_batch, register_mask_file, native_masked_file] subprocess.call(cmd, env=jip_envriron) # Restore current working directory and gzip output os.chdir(cwd) register_file = gzip_file( register_file, prefix="", outdir=outdir, remove_original_file=True) register_mask_file = gzip_file( register_mask_file, prefix="", outdir=outdir, remove_original_file=True) native_masked_file = gzip_file( native_masked_file, prefix="", outdir=outdir, remove_original_file=True) return register_file, register_mask_file, native_masked_file, align_file
def spatial_normalization(settings, mod='T1w', name='SpatialNormalization', resolution=2.0): """ A simple workflow to perform spatial normalization """ from mriqc.interfaces.common import EnsureSize from nipype.interfaces.ants import AffineInitializer from niworkflows.data import getters as niwgetters # Have some settings handy tpl_id = settings.get('template_id', 'mni_icbm152_nlin_asym_09c') mni_template = getattr(niwgetters, 'get_{}'.format(tpl_id))() # Define workflow interface workflow = pe.Workflow(name=name) inputnode = pe.Node( niu.IdentityInterface(fields=['moving_image', 'moving_mask']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface( fields=['inverse_composite_transform', 'out_report']), name='outputnode') # Mask inputs for initialization mmask = pe.Node(fsl.ApplyMask(), name='MovingApplyMask') fmask = pe.Node(fsl.ApplyMask(), name='FixedApplyMask') fmask.inputs.in_file = op.join( mni_template, '%dmm_%s.nii.gz' % (int(resolution), mod[:2])) fmask.inputs.mask_file = op.join(mni_template, '%dmm_brainmask.nii.gz' % int(resolution)) # Ensure resolution resample = pe.Node(EnsureSize(pixel_size=resolution), 'EnsureSize') # Initializer init = pe.Node( AffineInitializer(num_threads=settings.get('ants_nthreads')), name='NormalizationInit') # Spatial normalization norm = pe.Node( RobustMNINormalization( flavor='testing' if settings.get('testing', False) else 'fast', num_threads=settings.get('ants_nthreads'), template=tpl_id, template_resolution=2, reference=mod[:2], generate_report=True, ), name='SpatialNormalization', # Request all MultiProc processes when ants_nthreads > n_procs num_threads=min( settings.get('ants_nthreads', DEFAULTS['ants_nthreads']), settings.get('n_procs', 1)), estimated_memory_gb=3) workflow.connect([ (inputnode, resample, [('moving_image', 'in_file'), ('moving_mask', 'in_mask')]), (resample, mmask, [('out_file', 'in_file'), ('out_mask', 'mask_file')]), (mmask, init, [('out_file', 'moving_image')]), (fmask, init, [('out_file', 'fixed_image')]), (init, norm, [('out_file', 'initial_moving_transform')]), (resample, norm, [('out_file', 'moving_image'), ('out_mask', 'moving_mask')]), (norm, outputnode, [('inverse_composite_transform', 'inverse_composite_transform'), ('out_report', 'out_report')]), ]) return workflow