コード例 #1
0
    def _extrapolate_scheme(self, scheme_name, runtime, fit_obj, mask_array, mask_img):
        if scheme_name not in ("ABCD", "HCP"):
            return
        output_dwi_file = fname_presuffix(self.inputs.dwi_file,
                                          suffix=scheme_name,
                                          newpath=runtime.cwd, use_ext=True)
        output_bval_file = fname_presuffix(self.inputs.dwi_file,
                                           suffix='{}.bval'.format(scheme_name),
                                           newpath=runtime.cwd, use_ext=False)
        output_bvec_file = fname_presuffix(self.inputs.dwi_file,
                                           suffix='{}.bvec'.format(scheme_name),
                                           newpath=runtime.cwd, use_ext=False)
        output_b_file = fname_presuffix(self.inputs.dwi_file,
                                        suffix='{}.b'.format(scheme_name),
                                        newpath=runtime.cwd, use_ext=False)
        # Copy in the bval and bvecs
        bval_file = pkgr('qsiprep', 'data/schemes/{}.bval'.format(scheme_name))
        bvec_file = pkgr('qsiprep', 'data/schemes/{}.bvec'.format(scheme_name))
        shutil.copyfile(bval_file, output_bval_file)
        shutil.copyfile(bvec_file, output_bvec_file)
        self._results['extrapolated_bvecs'] = bvec_file
        self._results['extrapolated_bvals'] = bval_file
        _convert_fsl_to_mrtrix(bval_file, bvec_file, output_b_file)
        self._results['extrapolated_b'] = output_b_file

        prediction_gtab = self._get_gtab(external_bvals=bval_file, external_bvecs=bvec_file)
        prediction_shore = brainsuite_shore_basis(fit_obj.model.radial_order, fit_obj.model.zeta,
                                                  prediction_gtab, fit_obj.model.tau)

        shore_array = fit_obj._shore_coef[mask_array]
        output_data = np.zeros(mask_array.shape + (len(prediction_gtab.bvals),))
        output_data[mask_array] = np.dot(shore_array, prediction_shore.T)

        nb.Nifti1Image(output_data, mask_img.affine, mask_img.header).to_filename(output_dwi_file)
        self._results['extrapolated_dwi'] = output_dwi_file
コード例 #2
0
    def _extrapolate_scheme(self, scheme_name, runtime, fit_obj, mask_img):
        if scheme_name not in ("ABCD", "HCP"):
            return
        output_dwi_file = fname_presuffix(self.inputs.dwi_file,
                                          suffix=scheme_name,
                                          newpath=runtime.cwd, use_ext=True)
        output_bval_file = fname_presuffix(self.inputs.dwi_file,
                                           suffix='{}.bval'.format(scheme_name),
                                           newpath=runtime.cwd, use_ext=False)
        output_bvec_file = fname_presuffix(self.inputs.dwi_file,
                                           suffix='{}.bvec'.format(scheme_name),
                                           newpath=runtime.cwd, use_ext=False)
        output_b_file = fname_presuffix(self.inputs.dwi_file,
                                        suffix='{}.b'.format(scheme_name),
                                        newpath=runtime.cwd, use_ext=False)
        # Copy in the bval and bvecs
        bval_file = pkgr('qsiprep', 'data/schemes/{}.bval'.format(scheme_name))
        bvec_file = pkgr('qsiprep', 'data/schemes/{}.bvec'.format(scheme_name))
        shutil.copyfile(bval_file, output_bval_file)
        shutil.copyfile(bvec_file, output_bvec_file)
        self._results['extrapolated_bvecs'] = bvec_file
        self._results['extrapolated_bvals'] = bval_file
        _convert_fsl_to_mrtrix(bval_file, bvec_file, output_b_file)
        self._results['extrapolated_b'] = output_b_file

        gtab_to_predict = self._get_gtab(external_bvals=bval_file, external_bvecs=bvec_file)
        new_data = fit_obj.predict(gtab_to_predict, S0=1)
        nb.Nifti1Image(new_data, mask_img.affine, mask_img.header).to_filename(output_dwi_file)
        self._results['extrapolated_dwi'] = output_dwi_file
コード例 #3
0
def init_anat_average_wf(
    *,
    bspline_fitting_distance=200,
    longitudinal=False,
    name="anat_average_wf",
    num_maps=1,
    omp_nthreads=None,
    sloppy=False,
):
    """
    Create an average from several images of the same modality.

    Each image undergoes a clipping step, removing background noise and
    high-intensity outliers, which is required by INU correction with the
    N4 algorithm.
    Then INU correction is performed for each of the inputs and the range
    of the image clipped again to fit within uint8.
    Finally, each image is reoriented to have RAS+ data matrix and, if
    more than one inputs, aligned and averaged with FreeSurfer's
    ``mri_robust_template``.

    Parameters
    ----------
    bspline_fitting_distance : :obj:`float`
        Distance in mm between B-Spline control points for N4 INU estimation.
    longitudinal : :obj:`bool`
        Whether an unbiased middle point should be calculated.
    name : :obj:`str`
        This particular workflow's unique name (Nipype requirement).
    num_maps : :obj:`int`
        Then number of input 3D volumes to be averaged.
    omp_nthreads : :obj:`int`
        The number of threads for individual processes in this workflow.
    sloppy : :obj:`bool`
        Run in *sloppy* mode.

    Inputs
    ------
    in_files : :obj:`list`
        A list of one or more input files. They can be 3D or 4D.

    Outputs
    -------
    out_file : :obj:`str`
        The output averaged reference file.
    valid_list : :obj:`list`
        A list of accepted/discarded volumes from the input list.
    realign_xfms : :obj:`list`
        List of rigid-body transformation matrices that bring every volume
        into alignment with the average reference.
    out_report : :obj:`str`
        Path to a reportlet summarizing what happened in this workflow.

    """
    from pkg_resources import resource_filename as pkgr
    from nipype.interfaces.ants import N4BiasFieldCorrection
    from nipype.interfaces.image import Reorient

    from niworkflows.engine.workflows import LiterateWorkflow as Workflow
    from niworkflows.interfaces.header import ValidateImage
    from niworkflows.interfaces.nibabel import IntensityClip, SplitSeries
    from niworkflows.interfaces.freesurfer import (
        StructuralReference,
        PatchedLTAConvert as LTAConvert,
    )
    from niworkflows.interfaces.images import TemplateDimensions, Conform
    from niworkflows.interfaces.nitransforms import ConcatenateXFMs
    from niworkflows.utils.misc import add_suffix

    wf = Workflow(name=name)

    inputnode = pe.Node(niu.IdentityInterface(fields=["in_files"]),
                        name="inputnode")
    outputnode = pe.Node(
        niu.IdentityInterface(
            fields=["out_file", "valid_list", "realign_xfms", "out_report"]),
        name="outputnode",
    )

    # 1. Validate each of the input images
    validate = pe.MapNode(
        ValidateImage(),
        iterfield="in_file",
        name="validate",
        run_without_submitting=True,
    )

    # 2. Ensure we don't have two timepoints and implicitly squeeze image
    split = pe.MapNode(SplitSeries(), iterfield="in_file", name="split")

    # 3. INU correction of all independent volumes
    clip_preinu = pe.MapNode(IntensityClip(p_min=50),
                             iterfield="in_file",
                             name="clip_preinu")
    correct_inu = pe.MapNode(
        N4BiasFieldCorrection(
            dimension=3,
            save_bias=False,
            copy_header=True,
            n_iterations=[50] * (5 - 2 * sloppy),
            convergence_threshold=1e-7,
            shrink_factor=4,
            bspline_fitting_distance=bspline_fitting_distance,
        ),
        iterfield="input_image",
        n_procs=omp_nthreads,
        name="correct_inu",
    )
    clip_postinu = pe.MapNode(IntensityClip(p_min=10.0, p_max=99.5),
                              iterfield="in_file",
                              name="clip_postinu")

    # 4. Reorient T2w image(s) to RAS and resample to common voxel space
    ref_dimensions = pe.Node(TemplateDimensions(), name="ref_dimensions")
    conform = pe.MapNode(Conform(), iterfield="in_file", name="conform")
    # fmt:off
    wf.connect([
        (inputnode, ref_dimensions, [("in_files", "t1w_list")]),
        (inputnode, validate, [("in_files", "in_file")]),
        (validate, split, [("out_file", "in_file")]),
        (split, clip_preinu, [(("out_files", _flatten), "in_file")]),
        (clip_preinu, correct_inu, [("out_file", "input_image")]),
        (correct_inu, clip_postinu, [("output_image", "in_file")]),
        (ref_dimensions, conform, [("t1w_valid_list", "in_file"),
                                   ("target_zooms", "target_zooms"),
                                   ("target_shape", "target_shape")]),
        (ref_dimensions, outputnode, [("out_report", "out_report"),
                                      ("t1w_valid_list", "valid_list")]),
    ])
    # fmt:on

    # 5. Reorient template to RAS, if needed (mri_robust_template may set to LIA)
    ensure_ras = pe.Node(Reorient(), name="ensure_ras")

    if num_maps == 1:
        get1st = pe.Node(niu.Select(index=[0]), name="get1st")
        outputnode.inputs.realign_xfms = [
            pkgr("smriprep", "data/itkIdentityTransform.txt")
        ]
        # fmt:off
        wf.connect([
            (conform, get1st, [("out_file", "inlist")]),
            (get1st, ensure_ras, [("out", "in_file")]),
            (ensure_ras, outputnode, [("out_file", "out_file")]),
        ])
        # fmt:on
        return wf

    from nipype.interfaces import freesurfer as fs

    wf.__desc__ = f"""\
An anatomical reference-map was computed after registration of
{num_maps} images (after INU-correction) using
`mri_robust_template` [FreeSurfer {fs.Info().looseversion() or "<ver>"}, @fs_template].
"""

    conform_xfm = pe.MapNode(
        LTAConvert(in_lta="identity.nofile", out_lta=True),
        iterfield=["source_file", "target_file"],
        name="conform_xfm",
    )

    # 6. StructuralReference is fs.RobustTemplate if > 1 volume, copying otherwise
    merge = pe.Node(
        StructuralReference(
            auto_detect_sensitivity=True,
            initial_timepoint=1,  # For deterministic behavior
            intensity_scaling=True,  # 7-DOF (rigid + intensity)
            subsample_threshold=200,
            fixed_timepoint=not longitudinal,
            no_iteration=not longitudinal,
            transform_outputs=True,
        ),
        mem_gb=2 * num_maps - 1,
        name="merge",
    )

    # 7. Final intensity equalization/conformation
    clip_final = pe.Node(IntensityClip(p_min=2.0, p_max=99.9),
                         name="clip_final")

    merge_xfm = pe.MapNode(
        niu.Merge(2),
        name="merge_xfm",
        iterfield=["in1", "in2"],
        run_without_submitting=True,
    )
    concat_xfms = pe.MapNode(
        ConcatenateXFMs(inverse=True),
        name="concat_xfms",
        iterfield=["in_xfms"],
        run_without_submitting=True,
    )

    def _set_threads(in_list, maximum):
        return min(len(in_list), maximum)

    # fmt:off
    wf.connect([
        (ref_dimensions, conform_xfm, [("t1w_valid_list", "source_file")]),
        (conform, conform_xfm, [("out_file", "target_file")]),
        (conform, merge,
         [("out_file", "in_files"),
          (("out_file", _set_threads, omp_nthreads), "num_threads"),
          (("out_file", add_suffix, "_template"), "out_file")]),
        (merge, ensure_ras, [("out_file", "in_file")]),
        # Combine orientation and template transforms
        (conform_xfm, merge_xfm, [("out_lta", "in1")]),
        (merge, merge_xfm, [("transform_outputs", "in2")]),
        (merge_xfm, concat_xfms, [("out", "in_xfms")]),
        # Output
        (ensure_ras, clip_final, [("out_file", "in_file")]),
        (clip_final, outputnode, [("out_file", "out_file")]),
        (concat_xfms, outputnode, [("out_xfm", "realign_xfms")]),
    ])
    # fmt:on

    return wf
コード例 #4
0
ファイル: anatomical.py プロジェクト: ostanley/smriprep
def init_anat_template_wf(longitudinal,
                          omp_nthreads,
                          num_t1w,
                          name='anat_template_wf'):
    """
    Generate a canonically-oriented, structural average from all input T1w images.

    Workflow Graph
        .. workflow::
            :graph2use: orig
            :simple_form: yes

            from smriprep.workflows.anatomical import init_anat_template_wf
            wf = init_anat_template_wf(
                longitudinal=False, omp_nthreads=1, num_t1w=1)

    Parameters
    ----------
    longitudinal : bool
        Create unbiased structural average, regardless of number of inputs
        (may increase runtime)
    omp_nthreads : int
        Maximum number of threads an individual process may use
    num_t1w : int
        Number of T1w images
    name : str, optional
        Workflow name (default: anat_template_wf)

    Inputs
    ------
    t1w
        List of T1-weighted structural images

    Outputs
    -------
    t1w_ref
        Structural reference averaging input T1w images, defining the T1w space.
    t1w_realign_xfm
        List of affine transforms to realign input T1w images
    out_report
        Conformation report

    """
    workflow = Workflow(name=name)

    if num_t1w > 1:
        workflow.__desc__ = """\
A T1w-reference map was computed after registration of
{num_t1w} T1w images (after INU-correction) using
`mri_robust_template` [FreeSurfer {fs_ver}, @fs_template].
""".format(num_t1w=num_t1w, fs_ver=fs.Info().looseversion() or '<ver>')

    inputnode = pe.Node(niu.IdentityInterface(fields=['t1w']),
                        name='inputnode')
    outputnode = pe.Node(niu.IdentityInterface(
        fields=['t1w_ref', 't1w_valid_list', 't1w_realign_xfm', 'out_report']),
                         name='outputnode')

    # 0. Reorient T1w image(s) to RAS and resample to common voxel space
    t1w_ref_dimensions = pe.Node(TemplateDimensions(),
                                 name='t1w_ref_dimensions')
    t1w_conform = pe.MapNode(Conform(),
                             iterfield='in_file',
                             name='t1w_conform')

    workflow.connect([
        (inputnode, t1w_ref_dimensions, [('t1w', 't1w_list')]),
        (t1w_ref_dimensions, t1w_conform, [('t1w_valid_list', 'in_file'),
                                           ('target_zooms', 'target_zooms'),
                                           ('target_shape', 'target_shape')]),
        (t1w_ref_dimensions, outputnode, [('out_report', 'out_report'),
                                          ('t1w_valid_list', 't1w_valid_list')
                                          ]),
    ])

    if num_t1w == 1:
        get1st = pe.Node(niu.Select(index=[0]), name='get1st')
        outputnode.inputs.t1w_realign_xfm = [
            pkgr('smriprep', 'data/itkIdentityTransform.txt')
        ]

        workflow.connect([
            (t1w_conform, get1st, [('out_file', 'inlist')]),
            (get1st, outputnode, [('out', 't1w_ref')]),
        ])

        return workflow

    t1w_conform_xfm = pe.MapNode(LTAConvert(in_lta='identity.nofile',
                                            out_lta=True),
                                 iterfield=['source_file', 'target_file'],
                                 name='t1w_conform_xfm')

    # 1. Template (only if several T1w images)
    # 1a. Correct for bias field: the bias field is an additive factor
    #     in log-transformed intensity units. Therefore, it is not a linear
    #     combination of fields and N4 fails with merged images.
    # 1b. Align and merge if several T1w images are provided
    n4_correct = pe.MapNode(N4BiasFieldCorrection(dimension=3,
                                                  copy_header=True),
                            iterfield='input_image',
                            name='n4_correct',
                            n_procs=1)  # n_procs=1 for reproducibility
    # StructuralReference is fs.RobustTemplate if > 1 volume, copying otherwise
    t1w_merge = pe.Node(
        StructuralReference(
            auto_detect_sensitivity=True,
            initial_timepoint=1,  # For deterministic behavior
            intensity_scaling=True,  # 7-DOF (rigid + intensity)
            subsample_threshold=200,
            fixed_timepoint=not longitudinal,
            no_iteration=not longitudinal,
            transform_outputs=True,
        ),
        mem_gb=2 * num_t1w - 1,
        name='t1w_merge')

    # 2. Reorient template to RAS, if needed (mri_robust_template may set to LIA)
    t1w_reorient = pe.Node(image.Reorient(), name='t1w_reorient')

    concat_affines = pe.MapNode(ConcatenateLTA(out_type='RAS2RAS',
                                               invert_out=True),
                                iterfield=['in_lta1', 'in_lta2'],
                                name='concat_affines')

    lta_to_itk = pe.MapNode(LTAConvert(out_itk=True),
                            iterfield=['in_lta'],
                            name='lta_to_itk')

    def _set_threads(in_list, maximum):
        return min(len(in_list), maximum)

    workflow.connect([
        (t1w_ref_dimensions, t1w_conform_xfm, [('t1w_valid_list',
                                                'source_file')]),
        (t1w_conform, t1w_conform_xfm, [('out_file', 'target_file')]),
        (t1w_conform, n4_correct, [('out_file', 'input_image')]),
        (t1w_conform, t1w_merge,
         [(('out_file', _set_threads, omp_nthreads), 'num_threads'),
          (('out_file', add_suffix, '_template'), 'out_file')]),
        (n4_correct, t1w_merge, [('output_image', 'in_files')]),
        (t1w_merge, t1w_reorient, [('out_file', 'in_file')]),
        # Combine orientation and template transforms
        (t1w_conform_xfm, concat_affines, [('out_lta', 'in_lta1')]),
        (t1w_merge, concat_affines, [('transform_outputs', 'in_lta2')]),
        (concat_affines, lta_to_itk, [('out_file', 'in_lta')]),
        # Output
        (t1w_reorient, outputnode, [('out_file', 't1w_ref')]),
        (lta_to_itk, outputnode, [('out_itk', 't1w_realign_xfm')]),
    ])

    return workflow
コード例 #5
0
ファイル: fake.py プロジェクト: ebohorqu/pipeline
    def _run_interface(self, runtime):
        out_path = _find(self.inputs.source_file, self.images)

        if out_path is None:
            for k in self.images.keys():
                if k in self.inputs.in_file[0]:
                    out_path = k
            if "anat" in self.inputs.in_file[0]:
                out_path = out_path + "/" + "T1w"

        if out_path is None:
            out_path = ""

        _, ext = _splitext(self.inputs.in_file[0])
        compress = ext == '.nii'
        if compress:
            ext = '.nii.gz'

        base_directory = runtime.cwd
        if isdefined(self.inputs.base_directory):
            base_directory = os.path.abspath(self.inputs.base_directory)

        if base_directory == self.fmriprep_output_dir:
            # don't copy file
            return runtime
        elif base_directory == self.fmriprep_reportlets_dir:
            # write to json
            work_dir = os.path.dirname(base_directory)
            json_id = "%s.%s" % (self.node_id, self.inputs.suffix)
            json_id = re.sub(r'func_preproc_[^.]*', "func_preproc_wf", json_id)
            json_data = {"id": json_id}

            out_path = os.path.join(out_path, "qualitycheck")
            os.makedirs(os.path.join(self.output_dir, out_path), exist_ok=True)

            touch_fname = os.path.join(out_path, json_data["id"] + ext)
            touch_path = os.path.join(self.output_dir, touch_fname)

            if not os.path.isfile(touch_path):
                for i, fname in enumerate(self.inputs.in_file):
                    copy(fname, touch_path)
                    # with open(fname, "r") as f:
                    #     json_data["html"] += f.read()
                json_data["fname"] = os.path.join(
                    os.path.basename(self.output_dir), touch_fname)
                with fasteners.InterProcessLock(
                        os.path.join(work_dir, "qc.lock")):
                    json_file = os.path.join(work_dir, "qc.json")
                    with open(json_file, "ab+") as f:
                        f.seek(0, 2)

                        if f.tell() == 0:
                            f.write(json.dumps([json_data]).encode())
                        else:
                            f.seek(-1, 2)
                            f.truncate()
                            f.write(','.encode())
                            f.write(json.dumps(json_data).encode())
                            f.write(']'.encode())
                Path(touch_path).touch()
            html_path = os.path.join(os.path.dirname(self.output_dir),
                                     "index.html")
            if not os.path.isfile(html_path):
                copy(pkgr('pipeline', 'index.html'), html_path)
        else:
            # copy file to out_path
            out_path = os.path.join(base_directory, out_path)

            os.makedirs(out_path, exist_ok=True)

            formatstr = '{suffix}{ext}'
            if len(self.inputs.in_file) > 1 and not isdefined(
                    self.inputs.extra_values):
                formatstr = '{suffix}{i:04d}{ext}'

            for i, fname in enumerate(self.inputs.in_file):
                out_file = formatstr.format(suffix=self.inputs.suffix,
                                            i=i,
                                            ext=ext)

                if isdefined(self.inputs.extra_values):
                    out_file = out_file.format(
                        extra_value=self.inputs.extra_values[i])

                out_file = os.path.join(out_path, out_file)

                self._results['out_file'].append(out_file)

                if compress:
                    with open(fname, 'rb') as f_in:
                        with gzip.open(out_file, 'wb') as f_out:
                            copyfileobj(f_in, f_out)
                else:
                    copy(fname, out_file)

        return runtime
コード例 #6
0
def init_dwi_recon_workflow(dwi_files,
                            workflow_spec,
                            output_dir,
                            reportlets_dir,
                            has_transform,
                            omp_nthreads,
                            name="recon_wf"):
    """Convert a workflow spec into a nipype workflow.

    """
    atlas_names = workflow_spec.get('atlases', [])
    space = workflow_spec['space']
    workflow = Workflow(name=name)
    scans_iter = pe.Node(niu.IdentityInterface(fields=['dwi_file']),
                         name='scans_iter')
    scans_iter.iterables = ("dwi_file", dwi_files)
    inputnode = pe.Node(niu.IdentityInterface(fields=input_fields +
                                              ['dwi_file']),
                        name='inputnode')
    qsiprep_preprocessed_dwi_data = pe.Node(
        QsiReconIngress(), name="qsiprep_preprocessed_dwi_data")

    # For doctests
    if not workflow_spec['name'] == 'fake':
        scans_iter.inputs.dwi_file = dwi_files

    # Connect the collected diffusion data (gradients, etc) to the inputnode
    workflow.connect([(scans_iter, qsiprep_preprocessed_dwi_data,
                       ([('dwi_file', 'dwi_file')])),
                      (qsiprep_preprocessed_dwi_data, inputnode,
                       [(trait, trait) for trait in qsiprep_output_names])])

    # Resample all atlases to dwi_file's resolution
    get_atlases = pe.Node(GetConnectivityAtlases(atlas_names=atlas_names,
                                                 space=space),
                          name='get_atlases',
                          run_without_submitting=True)

    # Resample ROI targets to DWI resolution for ODF plotting
    crossing_rois_file = pkgr('qsiprep', 'data/crossing_rois.nii.gz')
    odf_rois = pe.Node(ants.ApplyTransforms(interpolation="MultiLabel",
                                            dimension=3),
                       name="odf_rois")
    odf_rois.inputs.input_image = crossing_rois_file
    if has_transform and space == "T1w":
        workflow.connect(inputnode, 't1_2_mni_reverse_transform', odf_rois,
                         'transforms')
    elif space == 'template':
        odf_rois.inputs.transforms = ['identity']
    else:
        LOGGER.warning("Unable to transform ODF ROIs to dwi data. "
                       "No ODF reports will be created.")
        odf_rois = pe.Node(niu.IdentityInterface(fields=['output_image']),
                           name='odf_rois')
    workflow.connect(scans_iter, 'dwi_file', odf_rois, 'reference_image')

    # Save the atlases
    if len(atlas_names) > 0:
        if space == "T1w":
            if not has_transform:
                LOGGER.critical(
                    "No reverse transform found, unable to move atlases"
                    " into DWI space")
            workflow.connect([(inputnode, get_atlases, [
                ('t1_2_mni_reverse_transform', 'forward_transform')
            ])])
        for atlas in workflow_spec['atlases']:
            workflow.connect([
                (get_atlases,
                 pe.Node(ReconDerivativesDataSink(space=space,
                                                  desc=atlas,
                                                  suffix="atlas",
                                                  compress=True),
                         name='ds_atlases_' + atlas,
                         run_without_submitting=True),
                 [(('atlas_configs', _get_resampled, atlas,
                    'dwi_resolution_file'), 'in_file')]),
                (get_atlases,
                 pe.Node(ReconDerivativesDataSink(space=space,
                                                  desc=atlas,
                                                  suffix="atlas",
                                                  extension=".mif.gz",
                                                  compress=True),
                         name='ds_atlas_mifs_' + atlas,
                         run_without_submitting=True),
                 [(('atlas_configs', _get_resampled, atlas,
                    'dwi_resolution_mif'), 'in_file')]),
                (get_atlases,
                 pe.Node(ReconDerivativesDataSink(space=space,
                                                  desc=atlas,
                                                  extension=".txt",
                                                  suffix="mrtrixLUT"),
                         name='ds_atlas_mrtrix_lut_' + atlas,
                         run_without_submitting=True),
                 [(('atlas_configs', _get_resampled, atlas, 'mrtrix_lut'),
                   'in_file')]),
                (get_atlases,
                 pe.Node(ReconDerivativesDataSink(space=space,
                                                  desc=atlas,
                                                  extension=".txt",
                                                  suffix="origLUT"),
                         name='ds_atlas_orig_lut_' + atlas,
                         run_without_submitting=True),
                 [(('atlas_configs', _get_resampled, atlas, 'orig_lut'),
                   'in_file')]),
            ])
        workflow.connect(inputnode, "dwi_file", get_atlases, "reference_image")
    # Read nodes from workflow spec, make sure we can implement them
    nodes_to_add = []
    for node_spec in workflow_spec['nodes']:
        if not node_spec['name']:
            raise Exception("Node has no name [{}]".format(node_spec))
        new_node = workflow_from_spec(omp_nthreads, has_transform
                                      or space == 'template', node_spec)
        if new_node is None:
            raise Exception("Unable to create a node for %s" % node_spec)
        nodes_to_add.append(new_node)
    workflow.add_nodes(nodes_to_add)
    _check_repeats(workflow.list_node_names())
    # Now that all nodes are in the workflow, connect them
    for node_spec in workflow_spec['nodes']:

        # get the nipype node object
        node_name = node_spec['name']
        node = workflow.get_node(node_name)

        if node_spec.get('input', 'qsiprep') == 'qsiprep':
            # directly connect all the qsiprep outputs to every node
            workflow.connect([(inputnode, node,
                               _as_connections(input_fields,
                                               dest_prefix='inputnode.'))])
            # for from_conn, to_conn in default_connections:
            #     workflow.connect(inputnode, from_conn, node, 'inputnode.' + to_conn)
            #     _check_repeats(workflow.list_node_names())

        # connect the outputs from the upstream node to this node
        else:
            upstream_node = workflow.get_node(node_spec['input'])
            upstream_outputnode_name = node_spec['input'] + '.outputnode'
            upstream_outputnode = workflow.get_node(upstream_outputnode_name)
            upstream_outputs = set(upstream_outputnode.outputs.get().keys())
            downstream_inputnode_name = node_name + ".inputnode"
            downstream_inputnode = workflow.get_node(downstream_inputnode_name)
            downstream_inputs = set(downstream_inputnode.outputs.get().keys())

            connect_from_upstream = upstream_outputs.intersection(
                downstream_inputs)
            connect_from_qsiprep = default_input_set - connect_from_upstream

            # LOGGER.info("connecting %s from %s to %s", connect_from_qsiprep,
            #             inputnode, node)
            workflow.connect([(inputnode, node,
                               _as_connections(connect_from_qsiprep,
                                               dest_prefix='inputnode.'))])
            # for qp_connection in connect_from_qsiprep:
            #    workflow.connect(inputnode, qp_connection, node, 'inputnode.' + qp_connection)
            _check_repeats(workflow.list_node_names())

            # LOGGER.info("connecting %s from %s to %s", connect_from_upstream,
            #             upstream_outputnode_name, downstream_inputnode_name)
            workflow.connect([(upstream_node, node,
                               _as_connections(connect_from_upstream,
                                               src_prefix='outputnode.',
                                               dest_prefix='inputnode.'))])
            # for upstream_connection in connect_from_upstream:
            #     workflow.connect(upstream_node, "outputnode." + upstream_connection,
            #                      node, 'inputnode.' + upstream_connection)
            _check_repeats(workflow.list_node_names())

        # If it's a connectivity calculation, send it the atlas configs
        if node_spec['action'] == 'connectivity':
            workflow.connect([(get_atlases, node, [
                ('atlas_configs', 'inputnode.atlas_configs')
            ])])
        _check_repeats(workflow.list_node_names())

        # Send the ODF rois to reconstruction nodes
        if node_spec['action'] == 'csd' or 'reconstruction' in node_spec[
                'action']:
            workflow.connect([(odf_rois, node, [('output_image',
                                                 'inputnode.odf_rois')])])
        _check_repeats(workflow.list_node_names())

    # Fill-in datasinks and reportlet datasinks seen so far
    for node in workflow.list_node_names():
        node_suffix = node.split('.')[-1]
        if node_suffix.startswith('ds_'):
            workflow.connect(scans_iter, 'dwi_file', workflow.get_node(node),
                             'source_file')
            workflow.get_node(node).inputs.space = space
            if "report" in node_suffix:
                workflow.get_node(node).inputs.base_directory = reportlets_dir
            else:
                workflow.get_node(node).inputs.base_directory = output_dir

    return workflow
コード例 #7
0
ファイル: converters.py プロジェクト: dPys/qsiprep
def get_dsi_studio_ODF_geometry(odf_key):
    mat_path = pkgr('qsiprep', 'data/odfs.mat')
    m = loadmat(mat_path)
    odf_vertices = m[odf_key + "_vertices"].T
    odf_faces = m[odf_key + "_faces"].T
    return odf_vertices, odf_faces
コード例 #8
0
def init_t2w_template_wf(longitudinal,
                         omp_nthreads,
                         num_t2w,
                         name="anat_t2w_template_wf"):
    """
    Adapts :py:func:`~smriprep.workflows.anatomical.init_anat_template_wf` for T2w image reference
    """
    from pkg_resources import resource_filename as pkgr
    from nipype.interfaces import freesurfer as fs, image, ants
    from niworkflows.engine.workflows import LiterateWorkflow as Workflow
    from niworkflows.interfaces.freesurfer import (
        StructuralReference,
        PatchedLTAConvert as LTAConvert,
    )
    from niworkflows.interfaces.images import TemplateDimensions, Conform, ValidateImage
    from niworkflows.interfaces.nitransforms import ConcatenateXFMs
    from niworkflows.utils.misc import add_suffix

    wf = Workflow(name=name)

    inputnode = pe.Node(niu.IdentityInterface(fields=["t2w"]),
                        name="inputnode")
    outputnode = pe.Node(
        niu.IdentityInterface(fields=[
            "t2w_ref", "t2w_valid_list", "t2_realign_xfm", "out_report"
        ]),
        name="outputnode",
    )

    # 0. Reorient T2w image(s) to RAS and resample to common voxel space
    t2w_ref_dimensions = pe.Node(TemplateDimensions(),
                                 name='t2w_ref_dimensions')
    t2w_conform = pe.MapNode(Conform(),
                             iterfield='in_file',
                             name='t2w_conform')

    wf.connect([
        (inputnode, t2w_ref_dimensions, [('t2w', 't1w_list')]),
        (t2w_ref_dimensions, t2w_conform, [('t1w_valid_list', 'in_file'),
                                           ('target_zooms', 'target_zooms'),
                                           ('target_shape', 'target_shape')]),
        (t2w_ref_dimensions, outputnode, [('out_report', 'out_report'),
                                          ('t1w_valid_list', 't2w_valid_list')
                                          ]),
    ])

    if num_t2w == 1:
        get1st = pe.Node(niu.Select(index=[0]), name='get1st')
        outputnode.inputs.t2w_realign_xfm = [
            pkgr('smriprep', 'data/itkIdentityTransform.txt')
        ]

        wf.connect([
            (t2w_conform, get1st, [('out_file', 'inlist')]),
            (get1st, outputnode, [('out', 't2w_ref')]),
        ])

        return wf

    wf.__desc__ = f"""\
A T2w-reference map was computed after registration of
{num_t2w} T2w images (after INU-correction) using
`mri_robust_template` [FreeSurfer {fs.Info().looseversion() or "<ver>"}, @fs_template].
"""

    t2w_conform_xfm = pe.MapNode(LTAConvert(in_lta='identity.nofile',
                                            out_lta=True),
                                 iterfield=['source_file', 'target_file'],
                                 name='t2w_conform_xfm')

    # 1a. Correct for bias field: the bias field is an additive factor
    #     in log-transformed intensity units. Therefore, it is not a linear
    #     combination of fields and N4 fails with merged images.
    # 1b. Align and merge if several T1w images are provided
    n4_correct = pe.MapNode(ants.N4BiasFieldCorrection(dimension=3,
                                                       copy_header=True),
                            iterfield='input_image',
                            name='n4_correct',
                            n_procs=1)  # n_procs=1 for reproducibility

    # StructuralReference is fs.RobustTemplate if > 1 volume, copying otherwise
    t2w_merge = pe.Node(
        StructuralReference(
            auto_detect_sensitivity=True,
            initial_timepoint=1,  # For deterministic behavior
            intensity_scaling=True,  # 7-DOF (rigid + intensity)
            subsample_threshold=200,
            fixed_timepoint=not longitudinal,
            no_iteration=not longitudinal,
            transform_outputs=True,
        ),
        mem_gb=2 * num_t2w - 1,
        name='t2w_merge')

    # 2. Reorient template to RAS, if needed (mri_robust_template may set to LIA)
    t2w_reorient = pe.Node(image.Reorient(), name='t2w_reorient')

    merge_xfm = pe.MapNode(niu.Merge(2),
                           name='merge_xfm',
                           iterfield=['in1', 'in2'],
                           run_without_submitting=True)
    concat_xfms = pe.MapNode(ConcatenateXFMs(inverse=True),
                             name="concat_xfms",
                             iterfield=['in_xfms'],
                             run_without_submitting=True)

    def _set_threads(in_list, maximum):
        return min(len(in_list), maximum)

    wf.connect([
        (t2w_ref_dimensions, t2w_conform_xfm, [('t1w_valid_list',
                                                'source_file')]),
        (t2w_conform, t2w_conform_xfm, [('out_file', 'target_file')]),
        (t2w_conform, n4_correct, [('out_file', 'input_image')]),
        (t2w_conform, t2w_merge,
         [(('out_file', _set_threads, omp_nthreads), 'num_threads'),
          (('out_file', add_suffix, '_template'), 'out_file')]),
        (n4_correct, t2w_merge, [('output_image', 'in_files')]),
        (t2w_merge, t2w_reorient, [('out_file', 'in_file')]),
        # Combine orientation and template transforms
        (t2w_conform_xfm, merge_xfm, [('out_lta', 'in1')]),
        (t2w_merge, merge_xfm, [('transform_outputs', 'in2')]),
        (merge_xfm, concat_xfms, [('out', 'in_xfms')]),
        # Output
        (t2w_reorient, outputnode, [('out_file', 't2w_ref')]),
        (concat_xfms, outputnode, [('out_xfm', 't2w_realign_xfm')]),
    ])

    return wf