Ejemplo n.º 1
0
    def nifti2dcm_conversion_pipeline(self, **name_maps):

        pipeline = self.new_pipeline(
            name='conversion_to_dicom',
            desc=("Conversing aligned umap from nifti to dicom format - "
                  "parallel implementation"),
            citations=(),
            name_maps=name_maps)

        list_niftis = pipeline.add(
            'list_niftis',
            ListDir(),
            inputs={'directory': ('umaps_align2ref', directory_format)})

        reorient_niftis = pipeline.add('reorient_niftis',
                                       ReorientUmap(),
                                       inputs={
                                           'niftis': (list_niftis, 'files'),
                                           'umap': ('umap', dicom_format)
                                       },
                                       requirements=[mrtrix_req.v('3.0rc3')])

        list_dicoms = pipeline.add(
            'list_dicoms',
            ListDir(sort_key=dicom_fname_sort_key),
            inputs={'directory': ('umap', dicom_format)})

        nii2dicom = pipeline.add(
            'nii2dicom',
            Nii2Dicom(
                # extension='Frame',  #  nii2dicom parameter
            ),
            inputs={'reference_dicom': (list_dicoms, 'files')},
            outputs={'in_file': (reorient_niftis, 'reoriented_umaps')},
            iterfield=['in_file'],
            wall_time=20)

        pipeline.add(
            'copy2dir',
            CopyToDir(extension='Frame'),
            inputs={'in_files': (nii2dicom, 'out_file')},
            outputs={'umap_aligned_dicoms': ('out_dir', directory_format)})

        return pipeline
Ejemplo n.º 2
0
    def qsm_pipeline(self, **name_maps):
        """
        Process dual echo data for QSM (TE=[7.38, 22.14])

        NB: Default values come from the STI-Suite
        """
        pipeline = self.new_pipeline(
            name='qsm_pipeline',
            name_maps=name_maps,
            desc="Resolve QSM from t2star coils",
            citations=[sti_cites, fsl_cite, matlab_cite])

        erosion = pipeline.add(
            'mask_erosion',
            fsl.ErodeImage(kernel_shape='sphere',
                           kernel_size=self.parameter('qsm_erosion_size'),
                           output_type='NIFTI'),
            inputs={'in_file': ('brain_mask', nifti_gz_format)},
            requirements=[fsl_req.v('5.0.8')],
            wall_time=15,
            mem_gb=12)

        # If we have multiple echoes we can combine the phase images from
        # each channel into a single image. Otherwise for single echo sequences
        # we need to perform QSM on each coil separately and then combine
        # afterwards.
        if self.branch('qsm_dual_echo'):
            # Combine channels to produce phase and magnitude images
            channel_combine = pipeline.add(
                'channel_combine',
                HIPCombineChannels(),
                inputs={
                    'magnitudes_dir': ('mag_channels', multi_nifti_gz_format),
                    'phases_dir': ('phase_channels', multi_nifti_gz_format)
                })

            # Unwrap phase using Laplacian unwrapping
            unwrap = pipeline.add(
                'unwrap',
                UnwrapPhase(padsize=self.parameter('qsm_padding')),
                inputs={
                    'voxelsize': ('voxel_sizes', float),
                    'in_file': (channel_combine, 'phase')
                },
                requirements=[matlab_req.v('r2017a'),
                              sti_req.v(2.2)])

            # Remove background noise
            vsharp = pipeline.add(
                "vsharp",
                VSharp(mask_manip="imerode({}>0, ball(5))"),
                inputs={
                    'voxelsize': ('voxel_sizes', float),
                    'in_file': (unwrap, 'out_file'),
                    'mask': (erosion, 'out_file')
                },
                requirements=[matlab_req.v('r2017a'),
                              sti_req.v(2.2)])

            # Run QSM iLSQR
            pipeline.add('qsmrecon',
                         QSMiLSQR(mask_manip="{}>0",
                                  padsize=self.parameter('qsm_padding')),
                         inputs={
                             'voxelsize': ('voxel_sizes', float),
                             'te': ('echo_times', float),
                             'B0': ('main_field_strength', float),
                             'H': ('main_field_orient', float),
                             'in_file': (vsharp, 'out_file'),
                             'mask': (vsharp, 'new_mask')
                         },
                         outputs={'qsm': ('qsm', nifti_format)},
                         requirements=[matlab_req.v('r2017a'),
                                       sti_req.v(2.2)])

        else:
            # Dialate eroded mask
            dialate = pipeline.add(
                'dialate',
                DialateMask(dialation=self.parameter('qsm_mask_dialation')),
                inputs={'in_file': (erosion, 'out_file')},
                requirements=[matlab_req.v('r2017a')])

            # List files for the phases of separate channel
            list_phases = pipeline.add(
                'list_phases',
                ListDir(sort_key=coil_sort_key,
                        filter=CoilEchoFilter(self.parameter('qsm_echo'))),
                inputs={
                    'directory': ('phase_channels', multi_nifti_gz_format)
                })

            # List files for the phases of separate channel
            list_mags = pipeline.add(
                'list_mags',
                ListDir(sort_key=coil_sort_key,
                        filter=CoilEchoFilter(self.parameter('qsm_echo'))),
                inputs={'directory': ('mag_channels', multi_nifti_gz_format)})

            # Generate coil specific masks
            mask_coils = pipeline.add(
                'mask_coils',
                MaskCoils(dialation=self.parameter('qsm_mask_dialation')),
                inputs={
                    'masks': (list_mags, 'files'),
                    'whole_brain_mask': (dialate, 'out_file')
                },
                requirements=[matlab_req.v('r2017a')])

            # Unwrap phase
            unwrap = pipeline.add(
                'unwrap',
                BatchUnwrapPhase(padsize=self.parameter('qsm_padding')),
                inputs={
                    'voxelsize': ('voxel_sizes', float),
                    'in_file': (list_phases, 'files')
                },
                requirements=[matlab_req.v('r2017a'),
                              sti_req.v(2.2)])

            # Background phase removal
            vsharp = pipeline.add(
                "vsharp",
                BatchVSharp(mask_manip='{}>0'),
                inputs={
                    'voxelsize': ('voxel_sizes', float),
                    'mask': (mask_coils, 'out_files'),
                    'in_file': (unwrap, 'out_file')
                },
                requirements=[matlab_req.v('r2017a'),
                              sti_req.v(2.2)])

            first_echo_time = pipeline.add(
                'first_echo',
                Select(index=0),
                inputs={'inlist': ('echo_times', float)})

            # Perform channel-wise QSM
            coil_qsm = pipeline.add(
                'coil_qsmrecon',
                BatchQSMiLSQR(mask_manip="{}>0",
                              padsize=self.parameter('qsm_padding')),
                inputs={
                    'voxelsize': ('voxel_sizes', float),
                    'B0': ('main_field_strength', float),
                    'H': ('main_field_orient', float),
                    'in_file': (vsharp, 'out_file'),
                    'mask': (vsharp, 'new_mask'),
                    'te': (first_echo_time, 'out')
                },
                requirements=[matlab_req.v('r2017a'),
                              sti_req.v(2.2)],
                wall_time=45)  # FIXME: Should be dependent on number of coils

            # Combine channel QSM by taking the median coil value
            pipeline.add('combine_qsm',
                         MedianInMasks(),
                         inputs={
                             'channels': (coil_qsm, 'out_file'),
                             'channel_masks': (vsharp, 'new_mask'),
                             'whole_brain_mask': (dialate, 'out_file')
                         },
                         outputs={'qsm': ('out_file', nifti_format)},
                         requirements=[matlab_req.v('r2017a')])
        return pipeline
Ejemplo n.º 3
0
    def preprocess_channels_pipeline(self, **name_maps):
        pipeline = self.new_pipeline(
            'preprocess_channels',
            name_maps=name_maps,
            desc=("Convert channel signals in complex coords to polar coords "
                  "and combine"))

        if (self.provided('header_image') or
                self.branch('reorient_to_std') or
                self.parameter('force_channel_flip') is not None):
            # Read channel files reorient them into standard space and then
            # write back to directory
            list_channels = pipeline.add(
                'list_channels',
                ListDir(),
                inputs={
                    'directory': ('channels', multi_nifti_gz_format)})

            if self.parameter('force_channel_flip') is not None:
                force_flip = pipeline.add(
                    'flip_dims',
                    fsl.SwapDimensions(
                        new_dims=tuple(self.parameter('force_channel_flip'))),
                    inputs={
                        'in_file': (list_channels, 'files')},
                    iterfield=['in_file'])
                geom_dest_file = (force_flip, 'out_file')
            else:
                geom_dest_file = (list_channels, 'files')

            if self.provided('header_image'):
                # If header image is provided stomp its geometry over the
                # acquired channels
                copy_geom = pipeline.add(
                    'qsm_copy_geometry',
                    fsl.CopyGeom(
                        output_type='NIFTI_GZ'),
                    inputs={
                        'in_file': ('header_image', nifti_gz_format),
                        'dest_file': geom_dest_file},
                    iterfield=(['dest_file']),
                    requirements=[fsl_req.v('5.0.8')])
                reorient_in_file = (copy_geom, 'out_file')
            else:
                reorient_in_file = geom_dest_file

            if self.branch('reorient_to_std'):
                reorient = pipeline.add(
                    'reorient_channel',
                    fsl.Reorient2Std(
                        output_type='NIFTI_GZ'),
                    inputs={
                        'in_file': reorient_in_file},
                    iterfield=['in_file'],
                    requirements=[fsl_req.v('5.0.8')])
                copy_to_dir_in_files = (reorient, 'out_file')
            else:
                copy_to_dir_in_files = reorient_in_file

            copy_to_dir = pipeline.add(
                'copy_to_dir',
                CopyToDir(),
                inputs={
                    'in_files': copy_to_dir_in_files,
                    'file_names': (list_channels, 'files')})
            to_polar_in_dir = (copy_to_dir, 'out_dir')
        else:
            to_polar_in_dir = ('channels', multi_nifti_gz_format)

        pipeline.add(
            'to_polar',
            ToPolarCoords(
                in_fname_re=self.parameter('channel_fname_regex'),
                real_label=self.parameter('channel_real_label'),
                imaginary_label=self.parameter('channel_imag_label')),
            inputs={
                'in_dir': to_polar_in_dir},
            outputs={
                'mag_channels': ('magnitudes_dir', multi_nifti_gz_format),
                'phase_channels': ('phases_dir', multi_nifti_gz_format)})

        return pipeline