Пример #1
0
def test_BRAINSROIAuto_outputs():
    output_map = dict(
        outputROIMaskVolume=dict(),
        outputVolume=dict(),
    )
    outputs = BRAINSROIAuto.output_spec()

    for key, metadata in output_map.items():
        for metakey, value in metadata.items():
            yield assert_equal, getattr(outputs.traits()[key], metakey), value
Пример #2
0
def test_BRAINSROIAuto_inputs():
    input_map = dict(
        ROIAutoDilateSize=dict(argstr='--ROIAutoDilateSize %f', ),
        args=dict(argstr='%s', ),
        closingSize=dict(argstr='--closingSize %f', ),
        cropOutput=dict(argstr='--cropOutput ', ),
        environ=dict(
            nohash=True,
            usedefault=True,
        ),
        ignore_exception=dict(
            nohash=True,
            usedefault=True,
        ),
        inputVolume=dict(argstr='--inputVolume %s', ),
        maskOutput=dict(argstr='--maskOutput ', ),
        numberOfThreads=dict(argstr='--numberOfThreads %d', ),
        otsuPercentileThreshold=dict(argstr='--otsuPercentileThreshold %f', ),
        outputROIMaskVolume=dict(
            argstr='--outputROIMaskVolume %s',
            hash_files=False,
        ),
        outputVolume=dict(
            argstr='--outputVolume %s',
            hash_files=False,
        ),
        outputVolumePixelType=dict(argstr='--outputVolumePixelType %s', ),
        terminal_output=dict(nohash=True, ),
        thresholdCorrectionFactor=dict(
            argstr='--thresholdCorrectionFactor %f', ),
    )
    inputs = BRAINSROIAuto.input_spec()

    for key, metadata in input_map.items():
        for metakey, value in metadata.items():
            yield assert_equal, getattr(inputs.traits()[key], metakey), value
def CreateLandmarkInitializeWorkflow(WFname, master_config, InterpolationMode, PostACPCAlignToAtlas, DoReverseInit, useEMSP=False, Debug=False):
    CLUSTER_QUEUE=master_config['queue']
    CLUSTER_QUEUE_LONG=master_config['long_q']
    landmarkInitializeWF = pe.Workflow(name=WFname)

    #############
    inputsSpec = pe.Node(interface=IdentityInterface(fields=['inputVolume',
                                                             'atlasLandmarkFilename',
                                                             'atlasWeightFilename',
                                                             'LLSModel',
                                                             'inputTemplateModel',
                                                             'atlasVolume',
                                                             'EMSP']),
                         run_without_submitting=True,
                         name='inputspec')

    #############
    outputsSpec = pe.Node(interface=IdentityInterface(fields=['outputLandmarksInACPCAlignedSpace',
                                                              'outputResampledVolume', 'outputResampledCroppedVolume',
                                                              'outputLandmarksInInputSpace',
                                                              'writeBranded2DImage',
                                                              'outputTransform', 'outputMRML', 'atlasToSubjectTransform'
                                                              ]),
                          run_without_submitting=True,
                          name='outputspec')

    ########################################################/
    # Run ACPC Detect on first T1 Image - Base Image
    ########################################################
    BCD = pe.Node(interface=BRAINSConstellationDetector(), name="BCD")
    many_cpu_BCD_options_dictionary = {'qsub_args': modify_qsub_args(CLUSTER_QUEUE_LONG,4,2,4), 'overwrite': True}
    BCD.plugin_args = many_cpu_BCD_options_dictionary
    ##  Use program default BCD.inputs.inputTemplateModel = T1ACPCModelFile
    # BCD.inputs.outputVolume =   "BCD_OUT" + "_ACPC_InPlace.nii.gz"                #$# T1AcpcImageList
    BCD.inputs.outputTransform = "BCD" + "_Original2ACPC_transform.h5"
    BCD.inputs.outputResampledVolume = "BCD" + "_ACPC.nii.gz"
    BCD.inputs.outputLandmarksInInputSpace = "BCD" + "_Original.fcsv"
    BCD.inputs.outputLandmarksInACPCAlignedSpace = "BCD" + "_ACPC_Landmarks.fcsv"
    BCD.inputs.writeBranded2DImage = "BCD"+"_Branded2DQCimage.png"
    # BCD.inputs.outputMRML = "BCD" + "_Scene.mrml"
    BCD.inputs.interpolationMode = InterpolationMode
    BCD.inputs.houghEyeDetectorMode = 1  # Look for dark eyes like on a T1 image, 0=Look for bright eyes like in a T2 image
    BCD.inputs.acLowerBound = 80.0  # Chop the data set 80mm below the AC PC point.

    # Entries below are of the form:
    landmarkInitializeWF.connect(inputsSpec, 'inputVolume', BCD, 'inputVolume')
    landmarkInitializeWF.connect(inputsSpec, 'atlasWeightFilename',  BCD, 'atlasLandmarkWeights')
    landmarkInitializeWF.connect(inputsSpec, 'atlasLandmarkFilename',BCD, 'atlasLandmarks')

    landmarkInitializeWF.connect(inputsSpec, 'LLSModel',             BCD, 'LLSModel')
    landmarkInitializeWF.connect(inputsSpec, 'inputTemplateModel',   BCD, 'inputTemplateModel')

    # If EMSP, pre-selected landmarks are given, force to use.
    if useEMSP:
        print("*** Use pre-selected landmark file for Landmark Detection")
        landmarkInitializeWF.connect(inputsSpec, 'EMSP', BCD, 'inputLandmarksEMSP')


    # If the atlas volume is from this subject (i.e. after template building for the longitudinal phase) then set this to True
    # Otherwise, it is probably best to let the ACPC alignment be fully defined by the landmark points themselves.
    if PostACPCAlignToAtlas:
        landmarkInitializeWF.connect(inputsSpec, 'atlasVolume',          BCD, 'atlasVolume')

    ########################################################
    # Run BLI atlas_to_subject
    ########################################################
    BLI = pe.Node(interface=BRAINSLandmarkInitializer(), name="BLI")
    BLI.inputs.outputTransformFilename = "landmarkInitializer_atlas_to_subject_transform.h5"

    landmarkInitializeWF.connect(inputsSpec, 'atlasWeightFilename', BLI, 'inputWeightFilename')
    landmarkInitializeWF.connect(inputsSpec, 'atlasLandmarkFilename', BLI, 'inputMovingLandmarkFilename')
    landmarkInitializeWF.connect(BCD, 'outputLandmarksInACPCAlignedSpace', BLI, 'inputFixedLandmarkFilename')

    ## This is for debugging purposes, and it is not intended for general use.
    if DoReverseInit == True:
        ########################################################
        # Run BLI subject_to_atlas
        ########################################################
        BLI2Atlas = pe.Node(interface=BRAINSLandmarkInitializer(), name="BLI2Atlas")
        BLI2Atlas.inputs.outputTransformFilename = "landmarkInitializer_subject_to_atlas_transform.h5"

        landmarkInitializeWF.connect(inputsSpec, 'atlasWeightFilename', BLI2Atlas, 'inputWeightFilename')
        landmarkInitializeWF.connect(inputsSpec, 'atlasLandmarkFilename', BLI2Atlas, 'inputFixedLandmarkFilename')
        landmarkInitializeWF.connect(BCD, 'outputLandmarksInInputSpace', BLI2Atlas, 'inputMovingLandmarkFilename')

        Resample2Atlas = pe.Node(interface=BRAINSResample(), name="Resample2Atlas")
        Resample2Atlas.inputs.interpolationMode = "Linear"
        Resample2Atlas.inputs.outputVolume = "subject2atlas.nii.gz"

        landmarkInitializeWF.connect(inputsSpec, 'inputVolume', Resample2Atlas, 'inputVolume')
        landmarkInitializeWF.connect(BLI2Atlas, 'outputTransformFilename', Resample2Atlas, 'warpTransform')

    if (DoReverseInit == True) and (Debug == True):
        ResampleFromAtlas = pe.Node(interface=BRAINSResample(), name="ResampleFromAtlas")
        ResampleFromAtlas.inputs.interpolationMode = "Linear"
        ResampleFromAtlas.inputs.outputVolume = "atlas2subject.nii.gz"

        landmarkInitializeWF.connect(inputsSpec, 'atlasVolume', ResampleFromAtlas, 'inputVolume')
        landmarkInitializeWF.connect(BLI, 'outputTransformFilename', ResampleFromAtlas, 'warpTransform')
        landmarkInitializeWF.connect(BCD, 'outputResampledVolume', ResampleFromAtlas, 'referenceVolume')

    BROIAUTO = pe.Node(interface=BRAINSROIAuto(), name="BROIAuto_cropped")
    many_cpu_BROIAUTO_options_dictionary = {'qsub_args': modify_qsub_args(CLUSTER_QUEUE_LONG,4,2,4), 'overwrite': True}
    BROIAUTO.plugin_args = many_cpu_BROIAUTO_options_dictionary
    BROIAUTO.inputs.outputVolume = "Cropped_BCD_ACPC_Aligned.nii.gz"
    BROIAUTO.inputs.ROIAutoDilateSize = 10
    BROIAUTO.inputs.cropOutput = True
    landmarkInitializeWF.connect(BCD, 'outputResampledVolume', BROIAUTO, 'inputVolume')

    landmarkInitializeWF.connect(BROIAUTO, 'outputVolume', outputsSpec, 'outputResampledCroppedVolume')
    landmarkInitializeWF.connect(BCD, 'outputLandmarksInACPCAlignedSpace', outputsSpec, 'outputLandmarksInACPCAlignedSpace')
    landmarkInitializeWF.connect(BCD, 'outputResampledVolume', outputsSpec, 'outputResampledVolume')
    landmarkInitializeWF.connect(BCD, 'outputLandmarksInInputSpace', outputsSpec, 'outputLandmarksInInputSpace')
    landmarkInitializeWF.connect(BCD, 'outputTransform', outputsSpec, 'outputTransform')
    landmarkInitializeWF.connect(BCD, 'outputMRML', outputsSpec, 'outputMRML')
    landmarkInitializeWF.connect(BCD, 'writeBranded2DImage', outputsSpec, 'writeBranded2DImage')
    landmarkInitializeWF.connect(BLI, 'outputTransformFilename', outputsSpec, 'atlasToSubjectTransform')

    return landmarkInitializeWF
Пример #4
0
def CreateJointFusionWorkflow(WFname, onlyT1, master_config, runFixFusionLabelMap=True):
    """
    This function...
    :param WFname:
    :param onlyT1:
    :param master_config:
    :param runFixFusionLabelMap: True
    :return: JointFusionWF
    """
    from nipype.interfaces import ants

    if onlyT1:
        n_modality = 1
    else:
        n_modality = 2
    CLUSTER_QUEUE = master_config['queue']
    CLUSTER_QUEUE_LONG = master_config['long_q']

    JointFusionWF = pe.Workflow(name=WFname)

    inputsSpec = pe.Node(interface=IdentityInterface(fields=['subj_t1_image',  # Desired image to create label map for
                                                             'subj_t2_image',  # Desired image to create label map for
                                                             'subj_lmks',  # The landmarks corresponding to t1_image
                                                             'subj_fixed_head_labels',
                                                             # The fixed head labels from BABC
                                                             'subj_posteriors',  # The BABC posteriors
                                                             'subj_left_hemisphere',  # The warped left hemisphere mask
                                                             'atlasWeightFilename',  # The static weights file name
                                                             'labelBaseFilename'
                                                             # Atlas label base name ex) neuro_lbls.nii.gz
                                                             ]),
                         run_without_submitting=True,
                         name='inputspec')
    outputsSpec = pe.Node(interface=IdentityInterface(fields=['JointFusion_HDAtlas20_2015_label',
                                                              'JointFusion_HDAtlas20_2015_CSFVBInjected_label',
                                                              'JointFusion_HDAtlas20_2015_fs_standard_label',
                                                              'JointFusion_HDAtlas20_2015_lobe_label',
                                                              'JointFusion_extended_snapshot',
                                                              'JointFusion_HDAtlas20_2015_dustCleaned_label',
                                                              'JointFusion_volumes_csv',
                                                              'JointFusion_volumes_json',
                                                              'JointFusion_lobe_volumes_csv',
                                                              'JointFusion_lobe_volumes_json']),
                          run_without_submitting=True,
                          name='outputspec')

    from collections import OrderedDict  # Need OrderedDict internally to ensure consistent ordering
    BLICreator = OrderedDict()
    A2SantsRegistrationPreJointFusion_SyN = OrderedDict()
    movingROIAuto = OrderedDict()
    labelMapResample = OrderedDict()
    NewlabelMapResample = OrderedDict()

    jointFusion_atlas_mergeindex = 0
    merge_input_offset = 1  # Merge nodes are indexed from 1, not zero!
    """
    multimodal ants registration if t2 exists
    """
    sessionMakeMultimodalInput = pe.Node(Function(function=MakeVector,
                                                  input_names=['inFN1', 'inFN2', 'jointFusion'],
                                                  output_names=['outFNs']),
                                         run_without_submitting=True, name="sessionMakeMultimodalInput")
    sessionMakeMultimodalInput.inputs.jointFusion = False
    JointFusionWF.connect(inputsSpec, 'subj_t1_image', sessionMakeMultimodalInput, 'inFN1')
    """
    T2 resample to T1 average image
    :: BRAINSABC changed its behavior to retain image's original spacing & origin
    :: Since antsJointFusion only works for the identical origin images for targets,
    :: Resampling is placed at this stage
    """
    subjectT2Resample = pe.Node(interface=BRAINSResample(), name="BRAINSResample_T2_forAntsJointFusion")
    if not onlyT1:
        subjectT2Resample.plugin_args = {'qsub_args': modify_qsub_args(master_config['queue'], 1, 1, 1),
                                         'overwrite': True}
        subjectT2Resample.inputs.pixelType = 'short'
        subjectT2Resample.inputs.interpolationMode = 'Linear'
        subjectT2Resample.inputs.outputVolume = "t2_resampled_in_t1.nii.gz"
        # subjectT2Resample.inputs.warpTransform= "Identity" # Default is "Identity"

        JointFusionWF.connect(inputsSpec, 'subj_t1_image', subjectT2Resample, 'referenceVolume')
        JointFusionWF.connect(inputsSpec, 'subj_t2_image', subjectT2Resample, 'inputVolume')

        JointFusionWF.connect(subjectT2Resample, 'outputVolume', sessionMakeMultimodalInput, 'inFN2')
    else:
        pass

    # print('jointFusion_atlas_db_base')
    print("master_config")
    print(master_config)
    print("master_config['jointfusion_atlas_db_base']")
    print((master_config['jointfusion_atlas_db_base']))
    jointFusionAtlasDict = readMalfAtlasDbBase(master_config['jointfusion_atlas_db_base'])
    number_of_atlas_sources = len(jointFusionAtlasDict)
    jointFusionAtlases = OrderedDict()
    atlasMakeMultimodalInput = OrderedDict()
    t2Resample = OrderedDict()
    warpedAtlasLblMergeNode = pe.Node(interface=Merge(number_of_atlas_sources), name="LblMergeAtlas")
    NewwarpedAtlasLblMergeNode = pe.Node(interface=Merge(number_of_atlas_sources), name="fswmLblMergeAtlas")
    # "HACK NOT to use T2 for JointFusion only"
    # warpedAtlasesMergeNode = pe.Node(interface=Merge(number_of_atlas_sources*n_modality),name="MergeAtlases")
    warpedAtlasesMergeNode = pe.Node(interface=Merge(number_of_atlas_sources * 1), name="MergeAtlases")

    ## if using Registration masking, then do ROIAuto on fixed and moving images and connect to registraitons
    UseRegistrationMasking = True
    if UseRegistrationMasking == True:
        from nipype.interfaces.semtools.segmentation.specialized import BRAINSROIAuto

        fixedROIAuto = pe.Node(interface=BRAINSROIAuto(), name="fixedROIAUTOMask")
        fixedROIAuto.inputs.ROIAutoDilateSize = 10
        fixedROIAuto.inputs.outputROIMaskVolume = "fixedImageROIAutoMask.nii.gz"
        JointFusionWF.connect(inputsSpec, 'subj_t1_image', fixedROIAuto, 'inputVolume')

    for jointFusion_atlas_subject in list(jointFusionAtlasDict.keys()):
        ## Need DataGrabber Here For the Atlas
        jointFusionAtlases[jointFusion_atlas_subject] = pe.Node(interface=IdentityInterface(
            fields=['t1', 't2', 'label', 'lmks', 'registration_mask']),
            name='jointFusionAtlasInput' + jointFusion_atlas_subject)
        jointFusionAtlases[jointFusion_atlas_subject].inputs.t1 = jointFusionAtlasDict[jointFusion_atlas_subject]['t1']
        jointFusionAtlases[jointFusion_atlas_subject].inputs.t2 = jointFusionAtlasDict[jointFusion_atlas_subject]['t2']
        jointFusionAtlases[jointFusion_atlas_subject].inputs.label = jointFusionAtlasDict[jointFusion_atlas_subject][
            'label']
        jointFusionAtlases[jointFusion_atlas_subject].inputs.lmks = jointFusionAtlasDict[jointFusion_atlas_subject][
            'lmks']
        jointFusionAtlases[jointFusion_atlas_subject].inputs.registration_mask = \
        jointFusionAtlasDict[jointFusion_atlas_subject]['registration_mask']
        ## Create BLI first
        ########################################################
        # Run BLI atlas_to_subject
        ########################################################
        BLICreator[jointFusion_atlas_subject] = pe.Node(interface=BRAINSLandmarkInitializer(),
                                                        name="BLI_" + jointFusion_atlas_subject)
        BLICreator[
            jointFusion_atlas_subject].inputs.outputTransformFilename = "landmarkInitializer_{0}_to_subject_transform.h5".format(
            jointFusion_atlas_subject)

        JointFusionWF.connect(inputsSpec, 'atlasWeightFilename', BLICreator[jointFusion_atlas_subject],
                              'inputWeightFilename')
        JointFusionWF.connect(jointFusionAtlases[jointFusion_atlas_subject], 'lmks',
                              BLICreator[jointFusion_atlas_subject], 'inputMovingLandmarkFilename')
        JointFusionWF.connect(inputsSpec, 'subj_lmks', BLICreator[jointFusion_atlas_subject],
                              'inputFixedLandmarkFilename')

        ##### Initialize with ANTS Transform For SyN
        currentAtlasToSubjectantsRegistration = 'SyN_AtlasToSubjectANTsPreJointFusion_' + jointFusion_atlas_subject
        A2SantsRegistrationPreJointFusion_SyN[jointFusion_atlas_subject] = pe.Node(interface=ants.Registration(),
                                                                                   name=currentAtlasToSubjectantsRegistration)
        many_cpu_ANTsSyN_options_dictionary = {'qsub_args': modify_qsub_args(CLUSTER_QUEUE_LONG, 4, 2, 16),
                                               'overwrite': True}
        A2SantsRegistrationPreJointFusion_SyN[
            jointFusion_atlas_subject].plugin_args = many_cpu_ANTsSyN_options_dictionary
        if onlyT1:
            JFregistrationTypeDescription = "FiveStageAntsRegistrationT1Only"
        else:
            JFregistrationTypeDescription = "FiveStageAntsRegistrationMultiModal"
        CommonANTsRegistrationSettings(
            antsRegistrationNode=A2SantsRegistrationPreJointFusion_SyN[jointFusion_atlas_subject],
            registrationTypeDescription=JFregistrationTypeDescription,
            output_transform_prefix=jointFusion_atlas_subject + '_ToSubjectPreJointFusion_SyN',
            output_warped_image=jointFusion_atlas_subject + '_2subject.nii.gz',
            output_inverse_warped_image=None,  # NO NEED FOR THIS
            save_state=None,  # NO NEED FOR THIS
            invert_initial_moving_transform=False,
        initial_moving_transform=None)

        ## if using Registration masking, then do ROIAuto on fixed and moving images and connect to registraitons
        if UseRegistrationMasking == True:
            from nipype.interfaces.semtools.segmentation.specialized import BRAINSROIAuto
            JointFusionWF.connect(fixedROIAuto, 'outputROIMaskVolume',
                                  A2SantsRegistrationPreJointFusion_SyN[jointFusion_atlas_subject], 'fixed_image_masks')
            # JointFusionWF.connect(inputsSpec, 'subj_fixed_head_labels',
            #                       A2SantsRegistrationPreJointFusion_SyN[jointFusion_atlas_subject],'fixed_image_masks')

            # NOTE: Moving image mask can be taken from Atlas directly so that it does not need to be read in
            # movingROIAuto[jointFusion_atlas_subject] = pe.Node(interface=BRAINSROIAuto(), name="movingROIAUTOMask_"+jointFusion_atlas_subject)
            # movingROIAuto.inputs.ROIAutoDilateSize=10
            # movingROIAuto[jointFusion_atlas_subject].inputs.outputROIMaskVolume = "movingImageROIAutoMask.nii.gz"
            # JointFusionWF.connect(jointFusionAtlases[jointFusion_atlas_subject], 't1', movingROIAuto[jointFusion_atlas_subject],'inputVolume')
            # JointFusionWF.connect(movingROIAuto[jointFusion_atlas_subject], 'outputROIMaskVolume',A2SantsRegistrationPreJointFusion_SyN[jointFusion_atlas_subject],'moving_image_masks')
            JointFusionWF.connect(jointFusionAtlases[jointFusion_atlas_subject], 'registration_mask',
                                  A2SantsRegistrationPreJointFusion_SyN[jointFusion_atlas_subject], 'moving_image_masks')

        JointFusionWF.connect(BLICreator[jointFusion_atlas_subject], 'outputTransformFilename',
                              A2SantsRegistrationPreJointFusion_SyN[jointFusion_atlas_subject],
                              'initial_moving_transform')

        """
        make multimodal input for atlases
        """
        atlasMakeMultimodalInput[jointFusion_atlas_subject] = pe.Node(Function(function=MakeVector,
                                                                               input_names=['inFN1', 'inFN2',
                                                                                            'jointFusion'],
                                                                               output_names=['outFNs']),
                                                                      run_without_submitting=True,
                                                                      name="atlasMakeMultimodalInput" + jointFusion_atlas_subject)
        atlasMakeMultimodalInput[jointFusion_atlas_subject].inputs.jointFusion = False
        JointFusionWF.connect(jointFusionAtlases[jointFusion_atlas_subject], 't1',
                              atlasMakeMultimodalInput[jointFusion_atlas_subject], 'inFN1')

        if not onlyT1:
            JointFusionWF.connect(jointFusionAtlases[jointFusion_atlas_subject], 't2',
                                  atlasMakeMultimodalInput[jointFusion_atlas_subject], 'inFN2')
        else:
            pass

        JointFusionWF.connect(sessionMakeMultimodalInput, 'outFNs',
                              A2SantsRegistrationPreJointFusion_SyN[jointFusion_atlas_subject], 'fixed_image')
        JointFusionWF.connect(atlasMakeMultimodalInput[jointFusion_atlas_subject], 'outFNs',
                              A2SantsRegistrationPreJointFusion_SyN[jointFusion_atlas_subject], 'moving_image')
        "HACK NOT to use T2 for JointFusion"
        # JointFusionWF.connect(A2SantsRegistrationPreJointFusion_SyN[jointFusion_atlas_subject],'warped_image',
        #               warpedAtlasesMergeNode,'in'+str(merge_input_offset + jointFusion_atlas_mergeindex*n_modality) )
        JointFusionWF.connect(A2SantsRegistrationPreJointFusion_SyN[jointFusion_atlas_subject], 'warped_image',
                              warpedAtlasesMergeNode, 'in' + str(merge_input_offset + jointFusion_atlas_mergeindex * 1))

        """
        Original t2 resampling
        """
        for modality_index in range(1, n_modality):
            t2Resample[jointFusion_atlas_subject] = pe.Node(interface=ants.ApplyTransforms(),
                                                            name="resampledT2" + jointFusion_atlas_subject)
            many_cpu_t2Resample_options_dictionary = {'qsub_args': modify_qsub_args(CLUSTER_QUEUE, 1, 1, 1),
                                                      'overwrite': True}
            t2Resample[jointFusion_atlas_subject].plugin_args = many_cpu_t2Resample_options_dictionary
            t2Resample[jointFusion_atlas_subject].inputs.num_threads = -1
            t2Resample[jointFusion_atlas_subject].inputs.dimension = 3
            t2Resample[jointFusion_atlas_subject].inputs.output_image = jointFusion_atlas_subject + '_t2.nii.gz'
            t2Resample[jointFusion_atlas_subject].inputs.interpolation = 'BSpline'
            t2Resample[jointFusion_atlas_subject].inputs.default_value = 0
            t2Resample[jointFusion_atlas_subject].inputs.invert_transform_flags = [False]

            JointFusionWF.connect(A2SantsRegistrationPreJointFusion_SyN[jointFusion_atlas_subject],
                                  'composite_transform',
                                  t2Resample[jointFusion_atlas_subject], 'transforms')
            JointFusionWF.connect(inputsSpec, 'subj_t1_image',
                                  t2Resample[jointFusion_atlas_subject], 'reference_image')
            JointFusionWF.connect(jointFusionAtlases[jointFusion_atlas_subject], 't2',
                                  t2Resample[jointFusion_atlas_subject], 'input_image')
            "HACK NOT to use T2 for JointFusion only"
            # JointFusionWF.connect(t2Resample[jointFusion_atlas_subject],'output_image',
            #               warpedAtlasesMergeNode,'in'+str(merge_input_offset + jointFusion_atlas_mergeindex*n_modality+modality_index) )

        """
        Original labelmap resampling
        """
        labelMapResample[jointFusion_atlas_subject] = pe.Node(interface=ants.ApplyTransforms(),
                                                              name="resampledLabel" + jointFusion_atlas_subject)
        many_cpu_labelMapResample_options_dictionary = {'qsub_args': modify_qsub_args(CLUSTER_QUEUE, 1, 1, 1),
                                                        'overwrite': True}
        labelMapResample[jointFusion_atlas_subject].plugin_args = many_cpu_labelMapResample_options_dictionary
        labelMapResample[jointFusion_atlas_subject].inputs.num_threads = -1
        labelMapResample[jointFusion_atlas_subject].inputs.dimension = 3
        labelMapResample[
            jointFusion_atlas_subject].inputs.output_image = jointFusion_atlas_subject + '_2_subj_lbl.nii.gz'
        labelMapResample[jointFusion_atlas_subject].inputs.interpolation = 'MultiLabel'
        labelMapResample[jointFusion_atlas_subject].inputs.default_value = 0
        labelMapResample[jointFusion_atlas_subject].inputs.invert_transform_flags = [False]

        JointFusionWF.connect(A2SantsRegistrationPreJointFusion_SyN[jointFusion_atlas_subject], 'composite_transform',
                              labelMapResample[jointFusion_atlas_subject], 'transforms')
        JointFusionWF.connect(inputsSpec, 'subj_t1_image',
                              labelMapResample[jointFusion_atlas_subject], 'reference_image')
        JointFusionWF.connect(jointFusionAtlases[jointFusion_atlas_subject], 'label',
                              labelMapResample[jointFusion_atlas_subject], 'input_image')

        JointFusionWF.connect(labelMapResample[jointFusion_atlas_subject], 'output_image', warpedAtlasLblMergeNode,
                              'in' + str(merge_input_offset + jointFusion_atlas_mergeindex))

        ### New labelmap resampling
        NewlabelMapResample[jointFusion_atlas_subject] = pe.Node(interface=ants.ApplyTransforms(),
                                                                 name="FSWM_WLABEL_" + jointFusion_atlas_subject)
        many_cpu_NewlabelMapResample_options_dictionary = {'qsub_args': modify_qsub_args(CLUSTER_QUEUE, 1, 1, 1),
                                                           'overwrite': True}
        NewlabelMapResample[jointFusion_atlas_subject].plugin_args = many_cpu_NewlabelMapResample_options_dictionary
        NewlabelMapResample[jointFusion_atlas_subject].inputs.num_threads = -1
        NewlabelMapResample[jointFusion_atlas_subject].inputs.dimension = 3
        NewlabelMapResample[
            jointFusion_atlas_subject].inputs.output_image = jointFusion_atlas_subject + 'fswm_2_subj_lbl.nii.gz'
        NewlabelMapResample[jointFusion_atlas_subject].inputs.interpolation = 'MultiLabel'
        NewlabelMapResample[jointFusion_atlas_subject].inputs.default_value = 0
        NewlabelMapResample[jointFusion_atlas_subject].inputs.invert_transform_flags = [False]

        JointFusionWF.connect(A2SantsRegistrationPreJointFusion_SyN[jointFusion_atlas_subject], 'composite_transform',
                              NewlabelMapResample[jointFusion_atlas_subject], 'transforms')
        JointFusionWF.connect(inputsSpec, 'subj_t1_image',
                              NewlabelMapResample[jointFusion_atlas_subject], 'reference_image')
        JointFusionWF.connect(jointFusionAtlases[jointFusion_atlas_subject], 'label',
                              NewlabelMapResample[jointFusion_atlas_subject], 'input_image')

        JointFusionWF.connect(NewlabelMapResample[jointFusion_atlas_subject], 'output_image',
                              NewwarpedAtlasLblMergeNode, 'in' + str(merge_input_offset + jointFusion_atlas_mergeindex))

        jointFusion_atlas_mergeindex += 1

    ## Now work on cleaning up the label maps
    from .FixLabelMapsTools import FixLabelMapFromNeuromorphemetrics2012
    from .FixLabelMapsTools import RecodeLabelMap

    ### Original NeuroMorphometrica merged fusion
    jointFusion = pe.Node(interface=ants.AntsJointFusion(), name="AntsJointFusion")
    many_cpu_JointFusion_options_dictionary = {'qsub_args': modify_qsub_args(CLUSTER_QUEUE, 10, 8, 16),
                                               'overwrite': True}
    jointFusion.plugin_args = many_cpu_JointFusion_options_dictionary
    jointFusion.inputs.num_threads = -1
    jointFusion.inputs.dimension = 3
    jointFusion.inputs.search_radius = [3]
    # jointFusion.inputs.method='Joint[0.1,2]'
    jointFusion.inputs.out_label_fusion = 'JointFusion_HDAtlas20_2015_label.nii.gz'
    # JointFusionWF.connect(inputsSpec, 'subj_fixed_head_labels', jointFusion, 'mask_image')
    JointFusionWF.connect(fixedROIAuto, 'outputROIMaskVolume', jointFusion, 'mask_image')

    JointFusionWF.connect(warpedAtlasLblMergeNode, 'out',
                          jointFusion, 'atlas_segmentation_image')

    AdjustMergeListNode = pe.Node(Function(function=adjustMergeList,
                                           input_names=['allList', 'n_modality'],
                                           output_names=['out']),
                                  name="AdjustMergeListNode")
    "*** HACK JointFusion only uses T1"
    # AdjustMergeListNode.inputs.n_modality = n_modality
    AdjustMergeListNode.inputs.n_modality = 1

    JointFusionWF.connect(warpedAtlasesMergeNode, 'out', AdjustMergeListNode, 'allList')
    JointFusionWF.connect(AdjustMergeListNode, 'out', jointFusion, 'atlas_image')

    AdjustTargetImageListNode = pe.Node(Function(function=adjustMergeList,
                                                 input_names=['allList', 'n_modality'],
                                                 output_names=['out']),
                                        name="AdjustTargetImageListNode")
    AdjustTargetImageListNode.inputs.n_modality = n_modality

    "*** HACK JointFusion only uses T1"
    """ Once JointFusion works with T2 properly,
        delete sessionMakeListSingleModalInput and use sessionMakeMultimodalInput instead
    """
    sessionMakeListSingleModalInput = pe.Node(Function(function=MakeVector,
                                                       input_names=['inFN1', 'inFN2', 'jointFusion'],
                                                       output_names=['outFNs']),
                                              run_without_submitting=True, name="sessionMakeListSingleModalInput")
    sessionMakeListSingleModalInput.inputs.jointFusion = False
    JointFusionWF.connect(inputsSpec, 'subj_t1_image', sessionMakeListSingleModalInput, 'inFN1')
    JointFusionWF.connect(sessionMakeListSingleModalInput, 'outFNs', jointFusion, 'target_image')

    JointFusionWF.connect(jointFusion, 'out_label_fusion', outputsSpec, 'JointFusion_HDAtlas20_2015_label')

    ## We need to recode values to ensure that the labels match FreeSurer as close as possible by merging
    ## some labels together to standard FreeSurfer confenventions (i.e. for WMQL)
    RECODE_LABELS_2_Standard_FSWM = [
        (15071, 47), (15072, 47), (15073, 47), (15145, 1011), (15157, 1011), (15161, 1011),
        (15179, 1012), (15141, 1014), (15151, 1017), (15163, 1018), (15165, 1019), (15143, 1027),
        (15191, 1028), (15193, 1028), (15185, 1030), (15201, 1030), (15175, 1031), (15195, 1031),
        (15173, 1035), (15144, 2011), (15156, 2011), (15160, 2011), (15178, 2012), (15140, 2014),
        (15150, 2017), (15162, 2018), (15164, 2019), (15142, 2027), (15190, 2028), (15192, 2028),
        (15184, 2030), (15174, 2031), (15194, 2031), (15172, 2035), (15200, 2030)]
    ## def RecodeLabelMap(InputFileName,OutputFileName,RECODE_TABLE):
    RecodeToStandardFSWM = pe.Node(Function(function=RecodeLabelMap,
                                            input_names=['InputFileName', 'OutputFileName', 'RECODE_TABLE'],
                                            output_names=['OutputFileName']),
                                   name="RecodeToStandardFSWM")
    RecodeToStandardFSWM.inputs.RECODE_TABLE = RECODE_LABELS_2_Standard_FSWM
    RecodeToStandardFSWM.inputs.OutputFileName = 'JointFusion_HDAtlas20_2015_fs_standard_label.nii.gz'

    JointFusionWF.connect(RecodeToStandardFSWM, 'OutputFileName', outputsSpec,
                          'JointFusion_HDAtlas20_2015_fs_standard_label')

    ## JointFusion_SNAPSHOT_WRITER for Segmented result checking:
    #    JointFusion_SNAPSHOT_WRITERNodeName = "JointFusion_ExtendedJointFusion_SNAPSHOT_WRITER"
    #    JointFusion_SNAPSHOT_WRITER = pe.Node(interface=BRAINSSnapShotWriter(), name=JointFusion_SNAPSHOT_WRITERNodeName)

    #    JointFusion_SNAPSHOT_WRITER.inputs.outputFilename = 'JointFusion_HDAtlas20_2015_CSFVBInjected_label.png'  # output specification
    #    JointFusion_SNAPSHOT_WRITER.inputs.inputPlaneDirection = [2, 1, 1, 1, 1, 0, 0]
    #    JointFusion_SNAPSHOT_WRITER.inputs.inputSliceToExtractInPhysicalPoint = [-3, -7, -3, 5, 7, 22, -22]

    #    JointFusionWF.connect(JointFusion_SNAPSHOT_WRITER,'outputFilename',outputsSpec,'JointFusion_extended_snapshot')

    myLocalDustCleanup = CreateDustCleanupWorkflow("DUST_CLEANUP", onlyT1, master_config)
    JointFusionWF.connect(inputsSpec, 'subj_t1_image', myLocalDustCleanup, 'inputspec.subj_t1_image')
    if not onlyT1:
        JointFusionWF.connect(subjectT2Resample, 'outputVolume', myLocalDustCleanup, 'inputspec.subj_t2_image')
    if runFixFusionLabelMap:
        ## post processing of jointfusion
        injectSurfaceCSFandVBIntoLabelMap = pe.Node(Function(function=FixLabelMapFromNeuromorphemetrics2012,
                                                             input_names=['fusionFN',
                                                                          'FixedHeadFN',
                                                                          'posteriorListOfTuples',
                                                                          'LeftHemisphereFN',
                                                                          'outFN',
                                                                          'OUT_DICT'],
                                                             output_names=['fixedFusionLabelFN']),
                                                    name="injectSurfaceCSFandVBIntoLabelMap")
        injectSurfaceCSFandVBIntoLabelMap.inputs.outFN = 'JointFusion_HDAtlas20_2015_CSFVBInjected_label.nii.gz'
        from collections import OrderedDict  # Need OrderedDict internally to ensure consistent ordering
        FREESURFER_DICT = OrderedDict({'BRAINSTEM': 16, 'RH_CSF': 24, 'LH_CSF': 24, 'BLOOD': 15000, 'UNKNOWN': 999,
                           'CONNECTED': [11, 12, 13, 9, 17, 26, 50, 51, 52, 48, 53, 58]
                           })
        injectSurfaceCSFandVBIntoLabelMap.inputs.OUT_DICT = FREESURFER_DICT
        JointFusionWF.connect(jointFusion, 'out_label_fusion', injectSurfaceCSFandVBIntoLabelMap, 'fusionFN')
        JointFusionWF.connect(inputsSpec, 'subj_fixed_head_labels', injectSurfaceCSFandVBIntoLabelMap, 'FixedHeadFN')
        JointFusionWF.connect(inputsSpec, 'subj_posteriors', injectSurfaceCSFandVBIntoLabelMap, 'posteriorListOfTuples')
        JointFusionWF.connect(inputsSpec, 'subj_left_hemisphere', injectSurfaceCSFandVBIntoLabelMap, 'LeftHemisphereFN')

        JointFusionWF.connect(injectSurfaceCSFandVBIntoLabelMap, 'fixedFusionLabelFN',
                              myLocalDustCleanup, 'inputspec.subj_label_atlas')

        JointFusionWF.connect(injectSurfaceCSFandVBIntoLabelMap, 'fixedFusionLabelFN',
                              outputsSpec, 'JointFusion_HDAtlas20_2015_CSFVBInjected_label')

        JointFusionWF.connect(myLocalDustCleanup, 'outputspec.JointFusion_HDAtlas20_2015_dustCleaned_label',
                              RecodeToStandardFSWM, 'InputFileName')

        JointFusionWF.connect(myLocalDustCleanup, 'outputspec.JointFusion_HDAtlas20_2015_dustCleaned_label',
                              outputsSpec, 'JointFusion_HDAtlas20_2015_dustCleaned_label')

    #        JointFusionWF.connect([(inputsSpec, JointFusion_SNAPSHOT_WRITER, [( 'subj_t1_image','inputVolumes')]),
    #                    (injectSurfaceCSFandVBIntoLabelMap, JointFusion_SNAPSHOT_WRITER,
    #                      [('fixedFusionLabelFN', 'inputBinaryVolumes')])
    #                   ])
    else:
        JointFusionWF.connect(jointFusion, 'output_label_image',
                              myLocalDustCleanup, 'inputspec.subj_label_atlas')

        JointFusionWF.connect(jointFusion, 'output_label_image',
                              outputsSpec, 'JointFusion_HDAtlas20_2015_CSFVBInjected_label')

        JointFusionWF.connect(myLocalDustCleanup, 'outputspec.JointFusion_HDAtlas20_2015_dustCleaned_label',
                              RecodeToStandardFSWM, 'InputFileName')

        JointFusionWF.connect(myLocalDustCleanup, 'outputspec.JointFusion_HDAtlas20_2015_dustCleaned_label',
                              outputsSpec, 'JointFusion_HDAtlas20_2015_dustCleaned_label')

    #        JointFusionWF.connect([(inputsSpec, JointFusion_SNAPSHOT_WRITER, [( 'subj_t1_image','inputVolumes')]),
    #                    (jointFusion, JointFusion_SNAPSHOT_WRITER,
    #                      [('output_label_image', 'inputBinaryVolumes')])
    #                   ])

    """
    Compute label volumes
    """
    computeLabelVolumes = CreateVolumeMeasureWorkflow("LabelVolume", master_config)
    JointFusionWF.connect(inputsSpec, 'subj_t1_image',
                          computeLabelVolumes, 'inputspec.subj_t1_image')
    JointFusionWF.connect(myLocalDustCleanup, 'outputspec.JointFusion_HDAtlas20_2015_dustCleaned_label',
                          computeLabelVolumes, 'inputspec.subj_label_image')
    JointFusionWF.connect(computeLabelVolumes, 'outputspec.csvFilename',
                          outputsSpec, 'JointFusion_volumes_csv')
    JointFusionWF.connect(computeLabelVolumes, 'outputspec.jsonFilename',
                          outputsSpec, 'JointFusion_volumes_json')

    ## Lobe Pacellation by recoding
    if master_config['relabel2lobes_filename'] != None:
        # print("Generate relabeled version based on {0}".format(master_config['relabel2lobes_filename']))

        RECODE_LABELS_2_LobePacellation = readRecodingList(master_config['relabel2lobes_filename'])
        RecordToFSLobes = pe.Node(Function(function=RecodeLabelMap,
                                           input_names=['InputFileName', 'OutputFileName', 'RECODE_TABLE'],
                                           output_names=['OutputFileName']),
                                  name="RecordToFSLobes")
        RecordToFSLobes.inputs.RECODE_TABLE = RECODE_LABELS_2_LobePacellation
        RecordToFSLobes.inputs.OutputFileName = 'JointFusion_HDAtlas20_2015_lobe_label.nii.gz'
        JointFusionWF.connect(RecodeToStandardFSWM, 'OutputFileName', RecordToFSLobes, 'InputFileName')
        JointFusionWF.connect(RecordToFSLobes, 'OutputFileName', outputsSpec, 'JointFusion_HDAtlas20_2015_lobe_label')

        """
        Compute lobe volumes
        """
        computeLobeVolumes = CreateVolumeMeasureWorkflow("LobeVolume", master_config)
        JointFusionWF.connect(inputsSpec, 'subj_t1_image',
                              computeLobeVolumes, 'inputspec.subj_t1_image')
        JointFusionWF.connect(RecordToFSLobes, 'OutputFileName',
                              computeLobeVolumes, 'inputspec.subj_label_image')
        JointFusionWF.connect(computeLobeVolumes, 'outputspec.csvFilename',
                              outputsSpec, 'JointFusion_lobe_volumes_csv')
        JointFusionWF.connect(computeLobeVolumes, 'outputspec.jsonFilename',
                              outputsSpec, 'JointFusion_lobe_volumes_json')

    return JointFusionWF
def CreateTissueClassifyWorkflow(WFname, master_config, InterpolationMode,
                                 UseRegistrationMasking):
    from nipype.interfaces import ants

    CLUSTER_QUEUE = master_config['queue']
    CLUSTER_QUEUE_LONG = master_config['long_q']

    tissueClassifyWF = pe.Workflow(name=WFname)

    inputsSpec = pe.Node(interface=IdentityInterface(fields=[
        'T1List', 'T2List', 'PDList', 'FLList', 'OTHERList', 'T1_count',
        'PrimaryT1', 'atlasDefinition', 'atlasToSubjectInitialTransform',
        'atlasVolume', 'atlasheadregion'
    ]),
                         run_without_submitting=True,
                         name='inputspec')
    outputsSpec = pe.Node(
        interface=IdentityInterface(fields=[
            'atlasToSubjectTransform',
            'atlasToSubjectInverseTransform',
            'atlasToSubjectRegistrationState',
            'outputLabels',
            'outputHeadLabels',  # ???
            #'t1_corrected', 't2_corrected',
            't1_average',
            't2_average',
            'pd_average',
            'fl_average',
            'posteriorImages',
        ]),
        run_without_submitting=True,
        name='outputspec')

    ########################################################
    # Run BABCext on Multi-modal images
    ########################################################
    makeOutImageList = pe.Node(Function(function=MakeOutFileList,
                                        input_names=[
                                            'T1List', 'T2List', 'PDList',
                                            'FLList', 'OTHERList', 'postfix',
                                            'postfixBFC', 'postfixUnwrapped',
                                            'PrimaryT1', 'ListOutType'
                                        ],
                                        output_names=[
                                            'inImageList', 'outImageList',
                                            'outBFCImageList',
                                            'outUnwrappedImageList',
                                            'imageTypeList'
                                        ]),
                               run_without_submitting=True,
                               name="99_makeOutImageList")
    tissueClassifyWF.connect(inputsSpec, 'T1List', makeOutImageList, 'T1List')
    tissueClassifyWF.connect(inputsSpec, 'T2List', makeOutImageList, 'T2List')
    tissueClassifyWF.connect(inputsSpec, 'PDList', makeOutImageList, 'PDList')
    tissueClassifyWF.connect(inputsSpec, 'FLList', makeOutImageList, 'FLList')
    tissueClassifyWF.connect(inputsSpec, 'OTHERList', makeOutImageList,
                             'OTHERList')
    tissueClassifyWF.connect(inputsSpec, 'PrimaryT1', makeOutImageList,
                             'PrimaryT1')
    makeOutImageList.inputs.ListOutType = False
    makeOutImageList.inputs.postfix = "_corrected.nii.gz"
    makeOutImageList.inputs.postfixBFC = "_NOT_USED"
    makeOutImageList.inputs.postfixUnwrapped = "_NOT_USED"

    ##### Initialize with ANTS Transform For AffineComponentBABC
    currentAtlasToSubjectantsRigidRegistration = 'AtlasToSubjectANTsPreABC_Affine'
    A2SantsRegistrationPreABCAffine = pe.Node(
        interface=ants.Registration(),
        name=currentAtlasToSubjectantsRigidRegistration)
    many_cpu_ANTsRigid_options_dictionary = {
        'qsub_args': modify_qsub_args(CLUSTER_QUEUE, 4, 2, 8),
        'overwrite': True
    }
    A2SantsRegistrationPreABCAffine.plugin_args = many_cpu_ANTsRigid_options_dictionary

    CommonANTsRegistrationSettings(
        antsRegistrationNode=A2SantsRegistrationPreABCAffine,
        registrationTypeDescription='AtlasToSubjectANTsPreABC_Affine',
        output_transform_prefix='AtlasToSubjectPreBABC_Rigid',
        output_warped_image='atlas2subjectRigid.nii.gz',
        output_inverse_warped_image='subject2atlasRigid.nii.gz',
        save_state=None,
        invert_initial_moving_transform=False)

    tissueClassifyWF.connect(inputsSpec, 'atlasToSubjectInitialTransform',
                             A2SantsRegistrationPreABCAffine,
                             'initial_moving_transform')
    tissueClassifyWF.connect(inputsSpec, 'PrimaryT1',
                             A2SantsRegistrationPreABCAffine, 'fixed_image')
    tissueClassifyWF.connect(inputsSpec, 'atlasVolume',
                             A2SantsRegistrationPreABCAffine, 'moving_image')

    ##### Initialize with ANTS Transform For SyN component BABC
    currentAtlasToSubjectantsRegistration = 'AtlasToSubjectANTsPreABC_SyN'
    A2SantsRegistrationPreABCSyN = pe.Node(
        interface=ants.Registration(),
        name=currentAtlasToSubjectantsRegistration)
    many_cpu_ANTsSyN_options_dictionary = {
        'qsub_args': modify_qsub_args(CLUSTER_QUEUE_LONG, 8, 8, 16),
        'overwrite': True
    }
    A2SantsRegistrationPreABCSyN.plugin_args = many_cpu_ANTsSyN_options_dictionary
    CommonANTsRegistrationSettings(
        antsRegistrationNode=A2SantsRegistrationPreABCSyN,
        registrationTypeDescription='AtlasToSubjectANTsPreABC_SyN',
        output_transform_prefix='AtlasToSubjectPreBABC_SyN',
        output_warped_image='atlas2subject.nii.gz',
        output_inverse_warped_image='subject2atlas.nii.gz',
        save_state='SavedInternalSyNState.h5',
        invert_initial_moving_transform=False)

    ## if using Registration masking, then do ROIAuto on fixed and moving images and connect to registraitons
    if UseRegistrationMasking == True:
        from nipype.interfaces.semtools.segmentation.specialized import BRAINSROIAuto

        fixedROIAuto = pe.Node(interface=BRAINSROIAuto(),
                               name="fixedImageROIAUTOMask")
        fixedROIAuto.inputs.ROIAutoDilateSize = 15  ## NOTE Very large to include some skull in bad cases of bias where back of head is very dark
        fixedROIAuto.inputs.outputROIMaskVolume = "fixedImageROIAutoMask.nii.gz"

        tissueClassifyWF.connect(inputsSpec, 'PrimaryT1', fixedROIAuto,
                                 'inputVolume')
        tissueClassifyWF.connect(fixedROIAuto, 'outputROIMaskVolume',
                                 A2SantsRegistrationPreABCAffine,
                                 'fixed_image_mask')
        tissueClassifyWF.connect(fixedROIAuto, 'outputROIMaskVolume',
                                 A2SantsRegistrationPreABCSyN,
                                 'fixed_image_mask')

    ## NOTE: Always use atlas head region to avoid computing this every time.
    tissueClassifyWF.connect(inputsSpec, 'atlasheadregion',
                             A2SantsRegistrationPreABCAffine,
                             'moving_image_mask')
    tissueClassifyWF.connect(inputsSpec, 'atlasheadregion',
                             A2SantsRegistrationPreABCSyN, 'moving_image_mask')

    tissueClassifyWF.connect(A2SantsRegistrationPreABCAffine,
                             'composite_transform',
                             A2SantsRegistrationPreABCSyN,
                             'initial_moving_transform')
    tissueClassifyWF.connect(inputsSpec, 'PrimaryT1',
                             A2SantsRegistrationPreABCSyN, 'fixed_image')
    tissueClassifyWF.connect(inputsSpec, 'atlasVolume',
                             A2SantsRegistrationPreABCSyN, 'moving_image')

    BABCext = pe.Node(interface=BRAINSABCext(), name="BABC")
    many_cpu_BABC_options_dictionary = {
        'qsub_args': modify_qsub_args(CLUSTER_QUEUE, 13, 8, 16),
        'overwrite': True
    }
    BABCext.plugin_args = many_cpu_BABC_options_dictionary
    tissueClassifyWF.connect(makeOutImageList, 'inImageList', BABCext,
                             'inputVolumes')
    tissueClassifyWF.connect(makeOutImageList, 'imageTypeList', BABCext,
                             'inputVolumeTypes')
    tissueClassifyWF.connect(makeOutImageList, 'outImageList', BABCext,
                             'outputVolumes')
    BABCext.inputs.debuglevel = 0
    BABCext.inputs.useKNN = True
    BABCext.inputs.purePlugsThreshold = 0.1  #New feature to allow for pure plug processing and improvements.
    BABCext.inputs.maxIterations = 2
    BABCext.inputs.maxBiasDegree = 0
    BABCext.inputs.filterIteration = 3
    #BABCext.inputs.filterMethod = 'GradientAnisotropicDiffusion' ## If inputs are denoised, we don't need this
    BABCext.inputs.filterMethod = 'None'
    BABCext.inputs.atlasToSubjectTransformType = 'SyN'
    # Using SyN, so no bsplines here BABCext.inputs.gridSize = [10, 10, 10]
    BABCext.inputs.outputFormat = "NIFTI"
    BABCext.inputs.outputLabels = "brain_label_seg.nii.gz"
    BABCext.inputs.outputDirtyLabels = "volume_label_seg.nii.gz"
    BABCext.inputs.posteriorTemplate = "POSTERIOR_%s.nii.gz"
    BABCext.inputs.atlasToSubjectTransform = "atlas_to_subject.h5"
    # BABCext.inputs.implicitOutputs = ['t1_average_BRAINSABC.nii.gz', 't2_average_BRAINSABC.nii.gz']
    BABCext.inputs.interpolationMode = InterpolationMode
    BABCext.inputs.outputDir = './'
    BABCext.inputs.saveState = 'SavedBABCInternalSyNState.h5'

    tissueClassifyWF.connect(inputsSpec, 'atlasDefinition', BABCext,
                             'atlasDefinition')
    # NOTE: MUTUALLY EXCLUSIVE with restoreState
    #tissueClassifyWF.connect(A2SantsRegistrationPreABCSyN,
    #                         'composite_transform',
    #                         BABCext, 'atlasToSubjectInitialTransform')
    tissueClassifyWF.connect(A2SantsRegistrationPreABCSyN, 'save_state',
                             BABCext, 'restoreState')
    """
    Get the first T1 and T2 corrected images from BABCext
    """
    """ HACK:  THIS IS NOT NEEDED!  We should use the averged t1 and averaged t2 images instead!
    def get_first_T1_and_T2(in_files,T1_count):
        '''
        Returns the first T1 and T2 file in in_files, based on offset in T1_count.
        '''
        return in_files[0],in_files[T1_count]
    bfc_files = pe.Node(Function(input_names=['in_files','T1_count'],
                               output_names=['t1_corrected','t2_corrected'],
                               function=get_first_T1_and_T2), run_without_submitting=True, name='99_bfc_files' )
    tissueClassifyWF.connect( inputsSpec, 'T1_count', bfc_files, 'T1_count')
    tissueClassifyWF.connect(BABCext,'outputVolumes',bfc_files, 'in_files')


    tissueClassifyWF.connect(bfc_files,'t1_corrected',outputsSpec,'t1_corrected')
    tissueClassifyWF.connect(bfc_files,'t2_corrected',outputsSpec,'t2_corrected')
    #tissueClassifyWF.connect(bfc_files,'pd_corrected',outputsSpec,'pd_corrected')
    #tissueClassifyWF.connect(bfc_files,'fl_corrected',outputsSpec,'fl_corrected')

    """

    #############
    tissueClassifyWF.connect(BABCext, 'saveState', outputsSpec,
                             'atlasToSubjectRegistrationState')

    tissueClassifyWF.connect(BABCext, 'atlasToSubjectTransform', outputsSpec,
                             'atlasToSubjectTransform')

    def MakeInverseTransformFileName(TransformFileName):
        """### HACK:  This function is to work around a deficiency in BRAINSABCext where the inverse transform name is not being computed properly
          in the list outputs"""
        fixed_inverse_name = TransformFileName.replace(".h5", "_Inverse.h5")
        return [fixed_inverse_name]

    tissueClassifyWF.connect([
        (BABCext, outputsSpec, [(('atlasToSubjectTransform',
                                  MakeInverseTransformFileName),
                                 "atlasToSubjectInverseTransform")]),
    ])
    tissueClassifyWF.connect(BABCext, 'outputLabels', outputsSpec,
                             'outputLabels')
    tissueClassifyWF.connect(BABCext, 'outputDirtyLabels', outputsSpec,
                             'outputHeadLabels')

    tissueClassifyWF.connect(BABCext, 'outputT1AverageImage', outputsSpec,
                             't1_average')
    tissueClassifyWF.connect(BABCext, 'outputT2AverageImage', outputsSpec,
                             't2_average')
    tissueClassifyWF.connect(BABCext, 'outputPDAverageImage', outputsSpec,
                             'pd_average')
    tissueClassifyWF.connect(BABCext, 'outputFLAverageImage', outputsSpec,
                             'fl_average')
    ##  remove tissueClassifyWF.connect( [ ( BABCext, outputsSpec, [ (( 'outputAverageImages', getListIndexOrNoneIfOutOfRange, 0 ), "t1_average")] ), ] )
    ##  remove tissueClassifyWF.connect( [ ( BABCext, outputsSpec, [ (( 'outputAverageImages', getListIndexOrNoneIfOutOfRange, 1 ), "t2_average")] ), ] )
    ##  remove tissueClassifyWF.connect( [ ( BABCext, outputsSpec, [ (( 'outputAverageImages', getListIndexOrNoneIfOutOfRange, 2 ), "pd_average")] ), ] )

    MakePosteriorDictionaryNode = pe.Node(Function(
        function=MakePosteriorDictionaryFunc,
        input_names=['posteriorImages'],
        output_names=['posteriorDictionary']),
                                          run_without_submitting=True,
                                          name="99_makePosteriorDictionary")
    tissueClassifyWF.connect(BABCext, 'posteriorImages',
                             MakePosteriorDictionaryNode, 'posteriorImages')

    tissueClassifyWF.connect(MakePosteriorDictionaryNode,
                             'posteriorDictionary', outputsSpec,
                             'posteriorImages')

    return tissueClassifyWF
Пример #6
0
def CreateTissueClassifyWorkflow(WFname, master_config, InterpolationMode,
                                 UseRegistrationMasking):
    from nipype.interfaces import ants

    CLUSTER_QUEUE = master_config['queue']
    CLUSTER_QUEUE_LONG = master_config['long_q']

    tissueClassifyWF = pe.Workflow(name=WFname)

    inputsSpec = pe.Node(interface=IdentityInterface(fields=[
        'T1List', 'T2List', 'PDList', 'FLList', 'OtherList', 'T1_count',
        'PrimaryT1', 'atlasDefinition', 'atlasToSubjectInitialTransform',
        'atlasVolume'
    ]),
                         run_without_submitting=True,
                         name='inputspec')
    outputsSpec = pe.Node(
        interface=IdentityInterface(fields=[
            'atlasToSubjectTransform',
            'atlasToSubjectInverseTransform',
            'atlasToSubjectRegistrationState',
            'outputLabels',
            'outputHeadLabels',  # ???
            #'t1_corrected', 't2_corrected',
            't1_average',
            't2_average',
            'pd_average',
            'fl_average',
            'posteriorImages',
        ]),
        run_without_submitting=True,
        name='outputspec')

    ########################################################
    # Run BABCext on Multi-modal images
    ########################################################
    makeOutImageList = pe.Node(Function(
        function=MakeOutFileList,
        input_names=[
            'T1List', 'T2List', 'PDList', 'FLList', 'OtherList', 'postfix',
            'PrimaryT1'
        ],
        output_names=['inImageList', 'outImageList', 'imageTypeList']),
                               run_without_submitting=True,
                               name="99_makeOutImageList")
    tissueClassifyWF.connect(inputsSpec, 'T1List', makeOutImageList, 'T1List')
    tissueClassifyWF.connect(inputsSpec, 'T2List', makeOutImageList, 'T2List')
    tissueClassifyWF.connect(inputsSpec, 'PDList', makeOutImageList, 'PDList')
    tissueClassifyWF.connect(inputsSpec, 'PrimaryT1', makeOutImageList,
                             'PrimaryT1')
    makeOutImageList.inputs.FLList = []  # an emptyList HACK
    makeOutImageList.inputs.postfix = "_corrected.nii.gz"
    # HACK tissueClassifyWF.connect( inputsSpec, 'FLList', makeOutImageList, 'FLList' )
    tissueClassifyWF.connect(inputsSpec, 'OtherList', makeOutImageList,
                             'OtherList')

    ##### Initialize with ANTS Transform For AffineComponentBABC
    currentAtlasToSubjectantsRigidRegistration = 'AtlasToSubjectANTsPreABC_Rigid'
    A2SantsRegistrationPreABCRigid = pe.Node(
        interface=ants.Registration(),
        name=currentAtlasToSubjectantsRigidRegistration)
    many_cpu_ANTsRigid_options_dictionary = {
        'qsub_args': modify_qsub_args(CLUSTER_QUEUE, 4, 2, 8),
        'overwrite': True
    }
    A2SantsRegistrationPreABCRigid.plugin_args = many_cpu_ANTsRigid_options_dictionary

    A2SantsRegistrationPreABCRigid.inputs.num_threads = -1
    A2SantsRegistrationPreABCRigid.inputs.dimension = 3
    A2SantsRegistrationPreABCRigid.inputs.transforms = [
        "Affine",
    ]
    A2SantsRegistrationPreABCRigid.inputs.transform_parameters = [[0.1]]
    A2SantsRegistrationPreABCRigid.inputs.metric = ['MI']
    A2SantsRegistrationPreABCRigid.inputs.sampling_strategy = ['Regular']
    A2SantsRegistrationPreABCRigid.inputs.sampling_percentage = [0.5]
    A2SantsRegistrationPreABCRigid.inputs.metric_weight = [1.0]
    A2SantsRegistrationPreABCRigid.inputs.radius_or_number_of_bins = [32]
    A2SantsRegistrationPreABCRigid.inputs.number_of_iterations = [[
        1000, 1000, 500, 100
    ]]

    A2SantsRegistrationPreABCRigid.inputs.convergence_threshold = [1e-8]

    A2SantsRegistrationPreABCRigid.inputs.convergence_window_size = [10]
    A2SantsRegistrationPreABCRigid.inputs.use_histogram_matching = [True]
    A2SantsRegistrationPreABCRigid.inputs.shrink_factors = [[8, 4, 2, 1]]
    A2SantsRegistrationPreABCRigid.inputs.smoothing_sigmas = [[3, 2, 1, 0]]
    A2SantsRegistrationPreABCRigid.inputs.sigma_units = ["vox"]
    A2SantsRegistrationPreABCRigid.inputs.use_estimate_learning_rate_once = [
        False
    ]
    A2SantsRegistrationPreABCRigid.inputs.write_composite_transform = True  # Required for initialize_transforms_per_stage
    A2SantsRegistrationPreABCRigid.inputs.collapse_output_transforms = False  # Mutually Exclusive with initialize_transforms_per_stage
    A2SantsRegistrationPreABCRigid.inputs.initialize_transforms_per_stage = True
    A2SantsRegistrationPreABCRigid.inputs.output_transform_prefix = 'AtlasToSubjectPreBABC_Rigid'
    A2SantsRegistrationPreABCRigid.inputs.winsorize_lower_quantile = 0.01
    A2SantsRegistrationPreABCRigid.inputs.winsorize_upper_quantile = 0.99
    A2SantsRegistrationPreABCRigid.inputs.output_warped_image = 'atlas2subjectRigid.nii.gz'
    A2SantsRegistrationPreABCRigid.inputs.output_inverse_warped_image = 'subject2atlasRigid.nii.gz'
    A2SantsRegistrationPreABCRigid.inputs.float = True

    tissueClassifyWF.connect(inputsSpec, 'atlasToSubjectInitialTransform',
                             A2SantsRegistrationPreABCRigid,
                             'initial_moving_transform')
    tissueClassifyWF.connect(inputsSpec, 'PrimaryT1',
                             A2SantsRegistrationPreABCRigid, 'fixed_image')
    tissueClassifyWF.connect(inputsSpec, 'atlasVolume',
                             A2SantsRegistrationPreABCRigid, 'moving_image')

    ##### Initialize with ANTS Transform For SyN component BABC
    currentAtlasToSubjectantsRegistration = 'AtlasToSubjectANTsPreABC_SyN'
    A2SantsRegistrationPreABCSyN = pe.Node(
        interface=ants.Registration(),
        name=currentAtlasToSubjectantsRegistration)
    many_cpu_ANTsSyN_options_dictionary = {
        'qsub_args': modify_qsub_args(CLUSTER_QUEUE_LONG, 8, 8, 12),
        'overwrite': True
    }
    A2SantsRegistrationPreABCSyN.plugin_args = many_cpu_ANTsSyN_options_dictionary

    A2SantsRegistrationPreABCSyN.inputs.num_threads = -1
    A2SantsRegistrationPreABCSyN.inputs.dimension = 3
    A2SantsRegistrationPreABCSyN.inputs.transforms = ["SyN", "SyN"]
    A2SantsRegistrationPreABCSyN.inputs.transform_parameters = [[0.1, 3, 0],
                                                                [0.1, 3, 0]]
    A2SantsRegistrationPreABCSyN.inputs.metric = ['CC', 'CC']
    A2SantsRegistrationPreABCSyN.inputs.sampling_strategy = [None, None]
    A2SantsRegistrationPreABCSyN.inputs.sampling_percentage = [1.0, 1.0]
    A2SantsRegistrationPreABCSyN.inputs.metric_weight = [1.0, 1.0]
    A2SantsRegistrationPreABCSyN.inputs.radius_or_number_of_bins = [4, 4]
    A2SantsRegistrationPreABCSyN.inputs.number_of_iterations = [[500, 500],
                                                                [500, 70]]

    A2SantsRegistrationPreABCSyN.inputs.convergence_threshold = [1e-8, 1e-6]

    A2SantsRegistrationPreABCSyN.inputs.convergence_window_size = [12]
    A2SantsRegistrationPreABCSyN.inputs.use_histogram_matching = [True, True]
    A2SantsRegistrationPreABCSyN.inputs.shrink_factors = [[8, 4], [2, 1]]
    A2SantsRegistrationPreABCSyN.inputs.smoothing_sigmas = [[3, 2], [1, 0]]
    A2SantsRegistrationPreABCSyN.inputs.sigma_units = ["vox", "vox"]
    A2SantsRegistrationPreABCSyN.inputs.use_estimate_learning_rate_once = [
        False, False
    ]
    A2SantsRegistrationPreABCSyN.inputs.write_composite_transform = True  # Required for initialize_transforms_per_stage
    A2SantsRegistrationPreABCSyN.inputs.collapse_output_transforms = False  # Mutually Exclusive with initialize_transforms_per_stage
    A2SantsRegistrationPreABCSyN.inputs.initialize_transforms_per_stage = True
    A2SantsRegistrationPreABCSyN.inputs.save_state = 'SavedInternalSyNState.h5'
    A2SantsRegistrationPreABCSyN.inputs.output_transform_prefix = 'AtlasToSubjectPreBABC_SyN'
    A2SantsRegistrationPreABCSyN.inputs.winsorize_lower_quantile = 0.01
    A2SantsRegistrationPreABCSyN.inputs.winsorize_upper_quantile = 0.99
    A2SantsRegistrationPreABCSyN.inputs.output_warped_image = 'atlas2subject.nii.gz'
    A2SantsRegistrationPreABCSyN.inputs.output_inverse_warped_image = 'subject2atlas.nii.gz'
    A2SantsRegistrationPreABCSyN.inputs.float = True

    ## if using Registration masking, then do ROIAuto on fixed and moving images and connect to registraitons
    if UseRegistrationMasking == True:
        from nipype.interfaces.semtools.segmentation.specialized import BRAINSROIAuto

        fixedROIAuto = pe.Node(interface=BRAINSROIAuto(),
                               name="fixedImageROIAUTOMask")
        fixedROIAuto.inputs.ROIAutoDilateSize = 10
        fixedROIAuto.inputs.outputROIMaskVolume = "fixedImageROIAutoMask.nii.gz"

        movingROIAuto = pe.Node(interface=BRAINSROIAuto(),
                                name="movingImageROIAUTOMask")
        fixedROIAuto.inputs.ROIAutoDilateSize = 10
        movingROIAuto.inputs.outputROIMaskVolume = "movingImageROIAutoMask.nii.gz"

        tissueClassifyWF.connect(inputsSpec, 'PrimaryT1', fixedROIAuto,
                                 'inputVolume')
        tissueClassifyWF.connect(inputsSpec, 'atlasVolume', movingROIAuto,
                                 'inputVolume')

        tissueClassifyWF.connect(fixedROIAuto, 'outputROIMaskVolume',
                                 A2SantsRegistrationPreABCRigid,
                                 'fixed_image_mask')
        tissueClassifyWF.connect(movingROIAuto, 'outputROIMaskVolume',
                                 A2SantsRegistrationPreABCRigid,
                                 'moving_image_mask')

        tissueClassifyWF.connect(fixedROIAuto, 'outputROIMaskVolume',
                                 A2SantsRegistrationPreABCSyN,
                                 'fixed_image_mask')
        tissueClassifyWF.connect(movingROIAuto, 'outputROIMaskVolume',
                                 A2SantsRegistrationPreABCSyN,
                                 'moving_image_mask')

    tissueClassifyWF.connect(A2SantsRegistrationPreABCRigid,
                             'composite_transform',
                             A2SantsRegistrationPreABCSyN,
                             'initial_moving_transform')
    tissueClassifyWF.connect(inputsSpec, 'PrimaryT1',
                             A2SantsRegistrationPreABCSyN, 'fixed_image')
    tissueClassifyWF.connect(inputsSpec, 'atlasVolume',
                             A2SantsRegistrationPreABCSyN, 'moving_image')

    BABCext = pe.Node(interface=BRAINSABCext(), name="BABC")
    many_cpu_BABC_options_dictionary = {
        'qsub_args': modify_qsub_args(CLUSTER_QUEUE, 8, 2, 4),
        'overwrite': True
    }
    BABCext.plugin_args = many_cpu_BABC_options_dictionary
    tissueClassifyWF.connect(makeOutImageList, 'inImageList', BABCext,
                             'inputVolumes')
    tissueClassifyWF.connect(makeOutImageList, 'imageTypeList', BABCext,
                             'inputVolumeTypes')
    tissueClassifyWF.connect(makeOutImageList, 'outImageList', BABCext,
                             'outputVolumes')
    BABCext.inputs.debuglevel = 0
    BABCext.inputs.useKNN = True
    BABCext.inputs.maxIterations = 3
    BABCext.inputs.maxBiasDegree = 4
    BABCext.inputs.filterIteration = 3
    BABCext.inputs.filterMethod = 'GradientAnisotropicDiffusion'
    BABCext.inputs.atlasToSubjectTransformType = 'SyN'
    BABCext.inputs.gridSize = [10, 10, 10]
    BABCext.inputs.outputFormat = "NIFTI"
    BABCext.inputs.outputLabels = "brain_label_seg.nii.gz"
    BABCext.inputs.outputDirtyLabels = "volume_label_seg.nii.gz"
    BABCext.inputs.posteriorTemplate = "POSTERIOR_%s.nii.gz"
    BABCext.inputs.atlasToSubjectTransform = "atlas_to_subject.h5"
    # BABCext.inputs.implicitOutputs = ['t1_average_BRAINSABC.nii.gz', 't2_average_BRAINSABC.nii.gz']
    BABCext.inputs.interpolationMode = InterpolationMode
    BABCext.inputs.outputDir = './'
    BABCext.inputs.saveState = 'SavedBABCInternalSyNState.h5'

    tissueClassifyWF.connect(inputsSpec, 'atlasDefinition', BABCext,
                             'atlasDefinition')
    # NOTE: MUTUALLY EXCLUSIVE with restoreState
    #tissueClassifyWF.connect(A2SantsRegistrationPreABCSyN,
    #                         'composite_transform',
    #                         BABCext, 'atlasToSubjectInitialTransform')
    tissueClassifyWF.connect(A2SantsRegistrationPreABCSyN, 'save_state',
                             BABCext, 'restoreState')
    """
    Get the first T1 and T2 corrected images from BABCext
    """
    """ HACK:  THIS IS NOT NEEDED!  We should use the averged t1 and averaged t2 images instead!
    def get_first_T1_and_T2(in_files,T1_count):
        '''
        Returns the first T1 and T2 file in in_files, based on offset in T1_count.
        '''
        return in_files[0],in_files[T1_count]
    bfc_files = pe.Node(Function(input_names=['in_files','T1_count'],
                               output_names=['t1_corrected','t2_corrected'],
                               function=get_first_T1_and_T2), run_without_submitting=True, name='99_bfc_files' )
    tissueClassifyWF.connect( inputsSpec, 'T1_count', bfc_files, 'T1_count')
    tissueClassifyWF.connect(BABCext,'outputVolumes',bfc_files, 'in_files')


    tissueClassifyWF.connect(bfc_files,'t1_corrected',outputsSpec,'t1_corrected')
    tissueClassifyWF.connect(bfc_files,'t2_corrected',outputsSpec,'t2_corrected')
    #tissueClassifyWF.connect(bfc_files,'pd_corrected',outputsSpec,'pd_corrected')
    #tissueClassifyWF.connect(bfc_files,'fl_corrected',outputsSpec,'fl_corrected')

    """

    #############
    tissueClassifyWF.connect(BABCext, 'saveState', outputsSpec,
                             'atlasToSubjectRegistrationState')

    tissueClassifyWF.connect(BABCext, 'atlasToSubjectTransform', outputsSpec,
                             'atlasToSubjectTransform')

    def MakeInverseTransformFileName(TransformFileName):
        """### HACK:  This function is to work around a deficiency in BRAINSABCext where the inverse transform name is not being computed properly
          in the list outputs"""
        fixed_inverse_name = TransformFileName.replace(".h5", "_Inverse.h5")
        return [fixed_inverse_name]

    tissueClassifyWF.connect([
        (BABCext, outputsSpec, [(('atlasToSubjectTransform',
                                  MakeInverseTransformFileName),
                                 "atlasToSubjectInverseTransform")]),
    ])
    tissueClassifyWF.connect(BABCext, 'outputLabels', outputsSpec,
                             'outputLabels')
    tissueClassifyWF.connect(BABCext, 'outputDirtyLabels', outputsSpec,
                             'outputHeadLabels')

    tissueClassifyWF.connect(BABCext, 'outputT1AverageImage', outputsSpec,
                             't1_average')
    tissueClassifyWF.connect(BABCext, 'outputT2AverageImage', outputsSpec,
                             't2_average')
    tissueClassifyWF.connect(BABCext, 'outputPDAverageImage', outputsSpec,
                             'pd_average')
    tissueClassifyWF.connect(BABCext, 'outputFLAverageImage', outputsSpec,
                             'fl_average')
    ##  remove tissueClassifyWF.connect( [ ( BABCext, outputsSpec, [ (( 'outputAverageImages', getListIndexOrNoneIfOutOfRange, 0 ), "t1_average")] ), ] )
    ##  remove tissueClassifyWF.connect( [ ( BABCext, outputsSpec, [ (( 'outputAverageImages', getListIndexOrNoneIfOutOfRange, 1 ), "t2_average")] ), ] )
    ##  remove tissueClassifyWF.connect( [ ( BABCext, outputsSpec, [ (( 'outputAverageImages', getListIndexOrNoneIfOutOfRange, 2 ), "pd_average")] ), ] )

    MakePosteriorDictionaryNode = pe.Node(Function(
        function=MakePosteriorDictionaryFunc,
        input_names=['posteriorImages'],
        output_names=['posteriorDictionary']),
                                          run_without_submitting=True,
                                          name="99_makePosteriorDictionary")
    tissueClassifyWF.connect(BABCext, 'posteriorImages',
                             MakePosteriorDictionaryNode, 'posteriorImages')

    tissueClassifyWF.connect(MakePosteriorDictionaryNode,
                             'posteriorDictionary', outputsSpec,
                             'posteriorImages')

    return tissueClassifyWF
Пример #7
0
def CreateLandmarkInitializeWorkflow(WFname,
                                     InterpolationMode,
                                     DoReverseInit=False,
                                     debug=False):
    landmarkInitializeWF = pe.Workflow(name=WFname)

    #############
    inputsSpec = pe.Node(interface=IdentityInterface(fields=[
        'inputVolume', 'atlasLandmarkFilename', 'atlasWeightFilename',
        'LLSModel', 'inputTemplateModel', 'atlasVolume'
    ]),
                         run_without_submitting=True,
                         name='inputspec')

    #############
    outputsSpec = pe.Node(interface=IdentityInterface(fields=[
        'outputLandmarksInACPCAlignedSpace', 'outputResampledVolume',
        'outputResampledCroppedVolume', 'outputLandmarksInInputSpace',
        'writeBranded2DImage', 'outputTransform', 'outputMRML',
        'atlasToSubjectTransform'
    ]),
                          run_without_submitting=True,
                          name='outputspec')

    ########################################################/
    # Run ACPC Detect on first T1 Image - Base Image
    ########################################################
    BCD = pe.Node(interface=BRAINSConstellationDetector(), name="BCD")
    ##  Use program default BCD.inputs.inputTemplateModel = T1ACPCModelFile
    # BCD.inputs.outputVolume =   "BCD_OUT" + "_ACPC_InPlace.nii.gz"                #$# T1AcpcImageList
    BCD.inputs.outputTransform = "BCD" + "_Original2ACPC_transform.h5"
    BCD.inputs.outputResampledVolume = "BCD" + "_ACPC.nii.gz"
    BCD.inputs.outputLandmarksInInputSpace = "BCD" + "_Original.fcsv"
    BCD.inputs.outputLandmarksInACPCAlignedSpace = "BCD" + "_ACPC_Landmarks.fcsv"
    BCD.inputs.writeBranded2DImage = "BCD" + "_Branded2DQCimage.png"
    # BCD.inputs.outputMRML = "BCD" + "_Scene.mrml"
    BCD.inputs.interpolationMode = InterpolationMode
    BCD.inputs.houghEyeDetectorMode = 1  # Look for dark eyes like on a T1 image, 0=Look for bright eyes like in a T2 image
    BCD.inputs.acLowerBound = 80.0  # Chop the data set 80mm below the AC PC point.

    # Entries below are of the form:
    landmarkInitializeWF.connect(inputsSpec, 'inputVolume', BCD, 'inputVolume')
    landmarkInitializeWF.connect(inputsSpec, 'atlasWeightFilename', BCD,
                                 'atlasLandmarkWeights')
    landmarkInitializeWF.connect(inputsSpec, 'atlasLandmarkFilename', BCD,
                                 'atlasLandmarks')

    landmarkInitializeWF.connect(inputsSpec, 'LLSModel', BCD, 'LLSModel')
    landmarkInitializeWF.connect(inputsSpec, 'inputTemplateModel', BCD,
                                 'inputTemplateModel')

    landmarkInitializeWF.connect(inputsSpec, 'atlasVolume', BCD, 'atlasVolume')

    ########################################################
    # Run BLI atlas_to_subject
    ########################################################
    BLI = pe.Node(interface=BRAINSLandmarkInitializer(), name="BLI")
    BLI.inputs.outputTransformFilename = "landmarkInitializer_atlas_to_subject_transform.h5"

    landmarkInitializeWF.connect(inputsSpec, 'atlasWeightFilename', BLI,
                                 'inputWeightFilename')
    landmarkInitializeWF.connect(inputsSpec, 'atlasLandmarkFilename', BLI,
                                 'inputMovingLandmarkFilename')
    landmarkInitializeWF.connect(BCD, 'outputLandmarksInACPCAlignedSpace', BLI,
                                 'inputFixedLandmarkFilename')

    ## This is for debugging purposes, and it is not intended for general use.
    if DoReverseInit == True:
        ########################################################
        # Run BLI subject_to_atlas
        ########################################################
        BLI2Atlas = pe.Node(interface=BRAINSLandmarkInitializer(),
                            name="BLI2Atlas")
        BLI2Atlas.inputs.outputTransformFilename = "landmarkInitializer_subject_to_atlas_transform.h5"

        landmarkInitializeWF.connect(inputsSpec, 'atlasWeightFilename',
                                     BLI2Atlas, 'inputWeightFilename')
        landmarkInitializeWF.connect(inputsSpec, 'atlasLandmarkFilename',
                                     BLI2Atlas, 'inputFixedLandmarkFilename')
        landmarkInitializeWF.connect(BCD, 'outputLandmarksInInputSpace',
                                     BLI2Atlas, 'inputMovingLandmarkFilename')

        Resample2Atlas = pe.Node(interface=BRAINSResample(),
                                 name="Resample2Atlas")
        Resample2Atlas.inputs.interpolationMode = "Linear"
        Resample2Atlas.inputs.outputVolume = "subject2atlas.nii.gz"

        landmarkInitializeWF.connect(inputsSpec, 'inputVolume', Resample2Atlas,
                                     'inputVolume')
        landmarkInitializeWF.connect(BLI2Atlas, 'outputTransformFilename',
                                     Resample2Atlas, 'warpTransform')
        landmarkInitializeWF.connect(inputsSpec, 'atlasVolume', Resample2Atlas,
                                     'referenceVolume')

    if (DoReverseInit == True) and (debug == True):
        ResampleFromAtlas = pe.Node(interface=BRAINSResample(),
                                    name="ResampleFromAtlas")
        ResampleFromAtlas.inputs.interpolationMode = "Linear"
        ResampleFromAtlas.inputs.outputVolume = "atlas2subject.nii.gz"

        landmarkInitializeWF.connect(inputsSpec, 'atlasVolume',
                                     ResampleFromAtlas, 'inputVolume')
        landmarkInitializeWF.connect(BLI, 'outputTransformFilename',
                                     ResampleFromAtlas, 'warpTransform')
        landmarkInitializeWF.connect(BCD, 'outputResampledVolume',
                                     ResampleFromAtlas, 'referenceVolume')

    BROIAUTO = pe.Node(interface=BRAINSROIAuto(), name="BROIAuto_cropped")
    BROIAUTO.inputs.outputVolume = "Cropped_BCD_ACPC_Aligned.nii.gz"
    BROIAUTO.inputs.ROIAutoDilateSize = 10
    BROIAUTO.inputs.cropOutput = True
    landmarkInitializeWF.connect(BCD, 'outputResampledVolume', BROIAUTO,
                                 'inputVolume')

    landmarkInitializeWF.connect(BROIAUTO, 'outputVolume', outputsSpec,
                                 'outputResampledCroppedVolume')
    landmarkInitializeWF.connect(BCD, 'outputLandmarksInACPCAlignedSpace',
                                 outputsSpec,
                                 'outputLandmarksInACPCAlignedSpace')
    landmarkInitializeWF.connect(BCD, 'outputResampledVolume', outputsSpec,
                                 'outputResampledVolume')
    landmarkInitializeWF.connect(BCD, 'outputLandmarksInInputSpace',
                                 outputsSpec, 'outputLandmarksInInputSpace')
    landmarkInitializeWF.connect(BCD, 'outputTransform', outputsSpec,
                                 'outputTransform')
    landmarkInitializeWF.connect(BCD, 'outputMRML', outputsSpec, 'outputMRML')
    landmarkInitializeWF.connect(BCD, 'writeBranded2DImage', outputsSpec,
                                 'writeBranded2DImage')
    landmarkInitializeWF.connect(BLI, 'outputTransformFilename', outputsSpec,
                                 'atlasToSubjectTransform')

    return landmarkInitializeWF
Пример #8
0
def create_tissue_classify_workflow(
    WFname, master_config, InterpolationMode, UseRegistrationMasking
):
    """
    This function...

    :param WFname:
    :param master_config:
    :param InterpolationMode:
    :param UseRegistrationMasking:
    :return:
    """
    from nipype.interfaces import ants

    CLUSTER_QUEUE = master_config["queue"]
    CLUSTER_QUEUE_LONG = master_config["long_q"]

    tissueClassifyWF = pe.Workflow(name=WFname)

    inputsSpec = pe.Node(
        interface=IdentityInterface(
            fields=[
                "T1List",
                "T2List",
                "PDList",
                "FLList",
                "OTHERList",
                "T1_count",
                "PrimaryT1",
                "atlasDefinition",
                "atlasToSubjectInitialTransform",
                "atlasVolume",
                "atlasheadregion",
            ]
        ),
        run_without_submitting=True,
        name="inputspec",
    )
    outputsSpec = pe.Node(
        interface=IdentityInterface(
            fields=[
                "atlasToSubjectTransform",
                "atlasToSubjectInverseTransform",
                "atlasToSubjectRegistrationState",
                "outputLabels",
                "outputHeadLabels",  # ???
                # 't1_corrected', 't2_corrected',
                "t1_average",
                "t2_average",
                "pd_average",
                "fl_average",
                "posteriorImages",
            ]
        ),
        run_without_submitting=True,
        name="outputspec",
    )

    ########################################################
    # Run BABCext on Multi-modal images
    ########################################################
    makeOutImageList = pe.Node(
        Function(
            function=make_out_from_file,
            input_names=[
                "T1List",
                "T2List",
                "PDList",
                "FLList",
                "OTHERList",
                "postfix",
                "postfixBFC",
                "postfixUnwrapped",
                "PrimaryT1",
                "ListOutType",
            ],
            output_names=[
                "inImageList",
                "outImageList",
                "outBFCImageList",
                "outUnwrappedImageList",
                "imageTypeList",
            ],
        ),
        run_without_submitting=True,
        name="99_makeOutImageList",
    )
    tissueClassifyWF.connect(inputsSpec, "T1List", makeOutImageList, "T1List")
    tissueClassifyWF.connect(inputsSpec, "T2List", makeOutImageList, "T2List")
    tissueClassifyWF.connect(inputsSpec, "PDList", makeOutImageList, "PDList")
    tissueClassifyWF.connect(inputsSpec, "FLList", makeOutImageList, "FLList")
    tissueClassifyWF.connect(inputsSpec, "OTHERList", makeOutImageList, "OTHERList")
    tissueClassifyWF.connect(inputsSpec, "PrimaryT1", makeOutImageList, "PrimaryT1")
    makeOutImageList.inputs.ListOutType = False
    makeOutImageList.inputs.postfix = "_corrected.nii.gz"
    makeOutImageList.inputs.postfixBFC = "_NOT_USED"
    makeOutImageList.inputs.postfixUnwrapped = "_NOT_USED"

    ##### Initialize with ANTS Transform For AffineComponentBABC
    currentAtlasToSubjectantsRigidRegistration = "AtlasToSubjectANTsPreABC_Affine"
    A2SantsRegistrationPreABCAffine = pe.Node(
        interface=ants.Registration(), name=currentAtlasToSubjectantsRigidRegistration
    )
    many_cpu_ANTsRigid_options_dictionary = {
        "qsub_args": modify_qsub_args(CLUSTER_QUEUE, 4, 2, 8),
        "overwrite": True,
    }
    A2SantsRegistrationPreABCAffine.plugin_args = many_cpu_ANTsRigid_options_dictionary

    common_ants_registration_settings(
        antsRegistrationNode=A2SantsRegistrationPreABCAffine,
        registrationTypeDescription="AtlasToSubjectANTsPreABC_Affine",
        output_transform_prefix="AtlasToSubjectPreBABC_Rigid",
        output_warped_image="atlas2subjectRigid.nii.gz",
        output_inverse_warped_image="subject2atlasRigid.nii.gz",
        save_state=None,
        invert_initial_moving_transform=False,
        initial_moving_transform=None,
    )

    tissueClassifyWF.connect(
        inputsSpec,
        "atlasToSubjectInitialTransform",
        A2SantsRegistrationPreABCAffine,
        "initial_moving_transform",
    )
    tissueClassifyWF.connect(
        inputsSpec, "PrimaryT1", A2SantsRegistrationPreABCAffine, "fixed_image"
    )
    tissueClassifyWF.connect(
        inputsSpec, "atlasVolume", A2SantsRegistrationPreABCAffine, "moving_image"
    )

    ##### Initialize with ANTS Transform For SyN component BABC
    currentAtlasToSubjectantsRegistration = "AtlasToSubjectANTsPreABC_SyN"
    A2SantsRegistrationPreABCSyN = pe.Node(
        interface=ants.Registration(), name=currentAtlasToSubjectantsRegistration
    )
    many_cpu_ANTsSyN_options_dictionary = {
        "qsub_args": modify_qsub_args(CLUSTER_QUEUE_LONG, 8, 8, 16),
        "overwrite": True,
    }
    A2SantsRegistrationPreABCSyN.plugin_args = many_cpu_ANTsSyN_options_dictionary
    common_ants_registration_settings(
        antsRegistrationNode=A2SantsRegistrationPreABCSyN,
        registrationTypeDescription="AtlasToSubjectANTsPreABC_SyN",
        output_transform_prefix="AtlasToSubjectPreBABC_SyN",
        output_warped_image="atlas2subject.nii.gz",
        output_inverse_warped_image="subject2atlas.nii.gz",
        save_state="SavedInternalSyNState.h5",
        invert_initial_moving_transform=False,
        initial_moving_transform=None,
    )

    ## if using Registration masking, then do ROIAuto on fixed and moving images and connect to registraitons
    if UseRegistrationMasking == True:
        from nipype.interfaces.semtools.segmentation.specialized import BRAINSROIAuto

        fixedROIAuto = pe.Node(interface=BRAINSROIAuto(), name="fixedImageROIAUTOMask")
        fixedROIAuto.inputs.ROIAutoDilateSize = (
            15
        )  ## NOTE Very large to include some skull in bad cases of bias where back of head is very dark
        fixedROIAuto.inputs.outputROIMaskVolume = "fixedImageROIAutoMask.nii.gz"

        tissueClassifyWF.connect(inputsSpec, "PrimaryT1", fixedROIAuto, "inputVolume")
        tissueClassifyWF.connect(
            fixedROIAuto,
            "outputROIMaskVolume",
            A2SantsRegistrationPreABCAffine,
            "fixed_image_masks",
        )
        tissueClassifyWF.connect(
            fixedROIAuto,
            "outputROIMaskVolume",
            A2SantsRegistrationPreABCSyN,
            "fixed_image_masks",
        )

    ## NOTE: Always use atlas head region to avoid computing this every time.
    tissueClassifyWF.connect(
        inputsSpec,
        "atlasheadregion",
        A2SantsRegistrationPreABCAffine,
        "moving_image_masks",
    )
    tissueClassifyWF.connect(
        inputsSpec,
        "atlasheadregion",
        A2SantsRegistrationPreABCSyN,
        "moving_image_masks",
    )

    tissueClassifyWF.connect(
        A2SantsRegistrationPreABCAffine,
        "composite_transform",
        A2SantsRegistrationPreABCSyN,
        "initial_moving_transform",
    )
    tissueClassifyWF.connect(
        inputsSpec, "PrimaryT1", A2SantsRegistrationPreABCSyN, "fixed_image"
    )
    tissueClassifyWF.connect(
        inputsSpec, "atlasVolume", A2SantsRegistrationPreABCSyN, "moving_image"
    )

    BABCext = pe.Node(interface=BRAINSABCext(), name="BABC")
    many_cpu_BABC_options_dictionary = {
        "qsub_args": modify_qsub_args(CLUSTER_QUEUE, 13, 8, 16),
        "overwrite": True,
    }
    BABCext.plugin_args = many_cpu_BABC_options_dictionary
    tissueClassifyWF.connect(makeOutImageList, "inImageList", BABCext, "inputVolumes")
    tissueClassifyWF.connect(
        makeOutImageList, "imageTypeList", BABCext, "inputVolumeTypes"
    )
    tissueClassifyWF.connect(makeOutImageList, "outImageList", BABCext, "outputVolumes")
    BABCext.inputs.debuglevel = 0
    BABCext.inputs.useKNN = True
    BABCext.inputs.purePlugsThreshold = (
        0.1
    )  # New feature to allow for pure plug processing and improvements.
    BABCext.inputs.maxIterations = 2
    BABCext.inputs.maxBiasDegree = 0
    BABCext.inputs.filterIteration = 3
    # BABCext.inputs.filterMethod = 'GradientAnisotropicDiffusion' ## If inputs are denoised, we don't need this
    BABCext.inputs.filterMethod = "None"
    BABCext.inputs.atlasToSubjectTransformType = "SyN"
    # Using SyN, so no bsplines here BABCext.inputs.gridSize = [10, 10, 10]
    BABCext.inputs.outputFormat = "NIFTI"
    BABCext.inputs.outputLabels = "brain_label_seg.nii.gz"
    BABCext.inputs.outputDirtyLabels = "volume_label_seg.nii.gz"
    BABCext.inputs.posteriorTemplate = "POSTERIOR_%s.nii.gz"
    BABCext.inputs.atlasToSubjectTransform = "atlas_to_subject.h5"
    # BABCext.inputs.implicitOutputs = ['t1_average_BRAINSABC.nii.gz', 't2_average_BRAINSABC.nii.gz']
    BABCext.inputs.interpolationMode = InterpolationMode
    BABCext.inputs.outputDir = "./"
    BABCext.inputs.saveState = "SavedBABCInternalSyNState.h5"

    tissueClassifyWF.connect(inputsSpec, "atlasDefinition", BABCext, "atlasDefinition")
    # NOTE: MUTUALLY EXCLUSIVE with restoreState
    # tissueClassifyWF.connect(A2SantsRegistrationPreABCSyN,
    #                         'composite_transform',
    #                         BABCext, 'atlasToSubjectInitialTransform')
    tissueClassifyWF.connect(
        A2SantsRegistrationPreABCSyN, "save_state", BABCext, "restoreState"
    )

    """
    Get the first T1 and T2 corrected images from BABCext
    """

    """ HACK:  THIS IS NOT NEEDED!  We should use the averged t1 and averaged t2 images instead!
    def get_first_T1_and_T2(in_files,T1_count):
        '''
        Returns the first T1 and T2 file in in_files, based on offset in T1_count.
        '''
        return in_files[0],in_files[T1_count]
    bfc_files = pe.Node(Function(input_names=['in_files','T1_count'],
                               output_names=['t1_corrected','t2_corrected'],
                               function=get_first_T1_and_T2), run_without_submitting=True, name='99_bfc_files' )
    tissueClassifyWF.connect( inputsSpec, 'T1_count', bfc_files, 'T1_count')
    tissueClassifyWF.connect(BABCext,'outputVolumes',bfc_files, 'in_files')


    tissueClassifyWF.connect(bfc_files,'t1_corrected',outputsSpec,'t1_corrected')
    tissueClassifyWF.connect(bfc_files,'t2_corrected',outputsSpec,'t2_corrected')
    #tissueClassifyWF.connect(bfc_files,'pd_corrected',outputsSpec,'pd_corrected')
    #tissueClassifyWF.connect(bfc_files,'fl_corrected',outputsSpec,'fl_corrected')

    """

    #############
    tissueClassifyWF.connect(
        BABCext, "saveState", outputsSpec, "atlasToSubjectRegistrationState"
    )

    tissueClassifyWF.connect(
        BABCext, "atlasToSubjectTransform", outputsSpec, "atlasToSubjectTransform"
    )

    def make_inverse_transform_filename(TransformFileName):
        """### HACK:  This function is to work around a deficiency in BRAINSABCext where the inverse transform name is not being computed properly
          in the list outputs

          :param Transform:
          :return:
          """
        fixed_inverse_name = TransformFileName.replace(".h5", "_Inverse.h5")
        return [fixed_inverse_name]

    tissueClassifyWF.connect(
        [
            (
                BABCext,
                outputsSpec,
                [
                    (
                        ("atlasToSubjectTransform", make_inverse_transform_filename),
                        "atlasToSubjectInverseTransform",
                    )
                ],
            )
        ]
    )
    tissueClassifyWF.connect(BABCext, "outputLabels", outputsSpec, "outputLabels")
    tissueClassifyWF.connect(
        BABCext, "outputDirtyLabels", outputsSpec, "outputHeadLabels"
    )

    tissueClassifyWF.connect(BABCext, "outputT1AverageImage", outputsSpec, "t1_average")
    tissueClassifyWF.connect(BABCext, "outputT2AverageImage", outputsSpec, "t2_average")
    tissueClassifyWF.connect(BABCext, "outputPDAverageImage", outputsSpec, "pd_average")
    tissueClassifyWF.connect(BABCext, "outputFLAverageImage", outputsSpec, "fl_average")

    ##  remove tissueClassifyWF.connect( [ ( BABCext, outputsSpec, [ (( 'outputAverageImages', get_list_index_or_none_if_out_of_range, 0 ), "t1_average")] ), ] )
    ##  remove tissueClassifyWF.connect( [ ( BABCext, outputsSpec, [ (( 'outputAverageImages', get_list_index_or_none_if_out_of_range, 1 ), "t2_average")] ), ] )
    ##  remove tissueClassifyWF.connect( [ ( BABCext, outputsSpec, [ (( 'outputAverageImages', get_list_index_or_none_if_out_of_range, 2 ), "pd_average")] ), ] )

    MakePosteriorListOfTuplesNode = pe.Node(
        Function(
            function=make_posteriour_list_of_tuplefunc,
            input_names=["posteriorImages"],
            output_names=["posteriorDictionary"],
        ),
        run_without_submitting=True,
        name="99_makePosteriorDictionary",
    )
    tissueClassifyWF.connect(
        BABCext, "posteriorImages", MakePosteriorListOfTuplesNode, "posteriorImages"
    )

    tissueClassifyWF.connect(
        MakePosteriorListOfTuplesNode,
        "posteriorDictionary",
        outputsSpec,
        "posteriorImages",
    )

    return tissueClassifyWF
Пример #9
0
def CreateMALFWorkflow(WFname, onlyT1, master_config,BASE_DATA_GRABBER_DIR=None, runFixFusionLabelMap=True):
    from nipype.interfaces import ants

    if onlyT1:
      n_modality = 1
    else:
      n_modality = 2
    CLUSTER_QUEUE=master_config['queue']
    CLUSTER_QUEUE_LONG=master_config['long_q']

    MALFWF = pe.Workflow(name=WFname)

    inputsSpec = pe.Node(interface=IdentityInterface(fields=['subj_t1_image', #Desired image to create label map for
                                                             'subj_t2_image', #Desired image to create label map for
                                                             'subj_lmks', #The landmarks corresponding to t1_image
                                                             'subj_fixed_head_labels', #The fixed head labels from BABC
                                                             'subj_left_hemisphere', #The warped left hemisphere mask
                                                             'atlasWeightFilename',  #The static weights file name
                                                             'labelBaseFilename' #Atlas label base name ex) neuro_lbls.nii.gz
                                                            ]),
                         run_without_submitting=True,
                         name='inputspec')
    outputsSpec = pe.Node(interface=IdentityInterface(fields=['MALF_HDAtlas20_2015_label',
                                                       'MALF_HDAtlas20_2015_CSFVBInjected_label',
                                                       'MALF_HDAtlas20_2015_fs_standard_label',
                                                       'MALF_HDAtlas20_2015_lobar_label',
                                                       'MALF_extended_snapshot']),
                          run_without_submitting=True,
                          name='outputspec')

    BLICreator = dict()
    A2SantsRegistrationPreMALF_SyN = dict()
    fixedROIAuto = dict()
    movingROIAuto = dict()
    labelMapResample = dict()
    NewlabelMapResample = dict()

    malf_atlas_mergeindex = 0
    merge_input_offset = 1 #Merge nodes are indexed from 1, not zero!
    """
    multimodal ants registration if t2 exists
    """
    sessionMakeMultimodalInput = pe.Node(Function(function=MakeVector,
                                                                      input_names=['inFN1', 'inFN2'],
                                                                      output_names=['outFNs']),
                                run_without_submitting=True, name="sessionMakeMultimodalInput")
    MALFWF.connect(inputsSpec, 'subj_t1_image', sessionMakeMultimodalInput, 'inFN1')
    if not onlyT1:
        MALFWF.connect(inputsSpec, 'subj_t2_image', sessionMakeMultimodalInput, 'inFN2')
    else:
        pass


    #print('malf_atlas_db_base')
    #print(master_config['malf_atlas_db_base'])
    malfAtlasDict = readMalfAtlasDbBase( master_config['malf_atlas_db_base'] )
    number_of_atlas_sources = len(malfAtlasDict)
    malfAtlases = dict()
    atlasMakeMultimodalInput = dict()
    t2Resample = dict()
    warpedAtlasLblMergeNode = pe.Node(interface=Merge(number_of_atlas_sources),name="LblMergeAtlas")
    NewwarpedAtlasLblMergeNode = pe.Node(interface=Merge(number_of_atlas_sources),name="fswmLblMergeAtlas")
    warpedAtlasesMergeNode = pe.Node(interface=Merge(number_of_atlas_sources*n_modality),name="MergeAtlases")

    for malf_atlas_subject in list(malfAtlasDict.keys()):
        ## Need DataGrabber Here For the Atlas
        malfAtlases[malf_atlas_subject] = pe.Node(interface = IdentityInterface(
                                                                  fields=['t1', 't2', 'label', 'lmks']),
                                                                  name='malfAtlasInput'+malf_atlas_subject)
        malfAtlases[malf_atlas_subject].inputs.t1 = malfAtlasDict[malf_atlas_subject]['t1']
        malfAtlases[malf_atlas_subject].inputs.t2 = malfAtlasDict[malf_atlas_subject]['t2']
        malfAtlases[malf_atlas_subject].inputs.label = malfAtlasDict[malf_atlas_subject]['label']
        malfAtlases[malf_atlas_subject].inputs.lmks = malfAtlasDict[malf_atlas_subject]['lmks']
        ## Create BLI first
        ########################################################
        # Run BLI atlas_to_subject
        ########################################################
        BLICreator[malf_atlas_subject] = pe.Node(interface=BRAINSLandmarkInitializer(), name="BLI_"+malf_atlas_subject)
        BLICreator[malf_atlas_subject].inputs.outputTransformFilename = "landmarkInitializer_{0}_to_subject_transform.h5".format(malf_atlas_subject)

        MALFWF.connect(inputsSpec, 'atlasWeightFilename', BLICreator[malf_atlas_subject], 'inputWeightFilename')
        MALFWF.connect(malfAtlases[malf_atlas_subject], 'lmks', BLICreator[malf_atlas_subject], 'inputMovingLandmarkFilename')
        MALFWF.connect(inputsSpec, 'subj_lmks', BLICreator[malf_atlas_subject], 'inputFixedLandmarkFilename')

        ##### Initialize with ANTS Transform For SyN
        currentAtlasToSubjectantsRegistration = 'SyN_AtlasToSubjectANTsPreMALF_'+malf_atlas_subject
        A2SantsRegistrationPreMALF_SyN[malf_atlas_subject] = pe.Node(interface=ants.Registration(), name=currentAtlasToSubjectantsRegistration)
        many_cpu_ANTsSyN_options_dictionary = {'qsub_args': modify_qsub_args(CLUSTER_QUEUE_LONG,4,2,16), 'overwrite': True}
        A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].plugin_args = many_cpu_ANTsSyN_options_dictionary

        A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.num_threads   = -1
        A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.dimension = 3
        #### DEBUGGIN
        A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.transforms = ["Affine","Affine","SyN","SyN"]
        A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.transform_parameters = [[0.1],[0.1],[0.1, 3, 0],[0.1, 3, 0]]
        if onlyT1:
            A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.metric = ['MI','MI','CC','CC']
            A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.metric_weight = [1.0,1.0,1.0,1.0]
            A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.sampling_percentage = [.5,.5,1.0,1.0]
            A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.radius_or_number_of_bins = [32,32,4,4]
            A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.sampling_strategy = ['Regular','Regular',None,None]
        else:
            A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.metric = ['MI',['MI','MI'],'CC',['CC','CC']]
            A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.metric_weight = [1.0,[1.0,1.0],1.0,[1.0,1.0]]
            A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.sampling_percentage = [.5,[.5,0.5],1.0,[1.0,1.0]]
            A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.radius_or_number_of_bins = [32,[32,32],4,[4,4]]
            A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.sampling_strategy = ['Regular',['Regular','Regular'],None,[None,None]]


        A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.number_of_iterations = [[1000,1000,500],[500,500],[500,500],[500,70]]

        A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.convergence_threshold = [1e-8,1e-6,1e-8,1e-6]

        A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.convergence_window_size = [12]
        A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.use_histogram_matching = [True,True,True,True]
        A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.shrink_factors = [[8, 4, 2],[2, 1],[8, 4],[2, 1]]
        A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.smoothing_sigmas = [[3, 2, 1],[1, 0],[3, 2],[1, 0]]
        A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.sigma_units = ["vox","vox","vox","vox"]
        A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.use_estimate_learning_rate_once = [False,False,False,False]
        A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.write_composite_transform = True # Required for initialize_transforms_per_stage
        A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.collapse_output_transforms = False # Mutually Exclusive with initialize_transforms_per_stage
        A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.initialize_transforms_per_stage = True
        ## NO NEED FOR THIS A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.save_state = 'SavedInternalSyNState.h5'
        A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.output_transform_prefix = malf_atlas_subject+'_ToSubjectPreMALF_SyN'
        A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.winsorize_lower_quantile = 0.01
        A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.winsorize_upper_quantile = 0.99
        A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.output_warped_image = malf_atlas_subject + '_2subject.nii.gz'
        ## NO NEED FOR THIS A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.output_inverse_warped_image = 'subject2atlas.nii.gz'
        A2SantsRegistrationPreMALF_SyN[malf_atlas_subject].inputs.float = True

        ## if using Registration masking, then do ROIAuto on fixed and moving images and connect to registraitons
        UseRegistrationMasking = True
        if UseRegistrationMasking == True:
            from nipype.interfaces.semtools.segmentation.specialized import BRAINSROIAuto

            fixedROIAuto[malf_atlas_subject] = pe.Node(interface=BRAINSROIAuto(), name="fixedROIAUTOMask_"+malf_atlas_subject)
            fixedROIAuto[malf_atlas_subject].inputs.ROIAutoDilateSize=10
            fixedROIAuto[malf_atlas_subject].inputs.outputROIMaskVolume = "fixedImageROIAutoMask.nii.gz"

            movingROIAuto[malf_atlas_subject] = pe.Node(interface=BRAINSROIAuto(), name="movingROIAUTOMask_"+malf_atlas_subject)
            fixedROIAuto[malf_atlas_subject].inputs.ROIAutoDilateSize=10
            movingROIAuto[malf_atlas_subject].inputs.outputROIMaskVolume = "movingImageROIAutoMask.nii.gz"

            MALFWF.connect(inputsSpec, 'subj_t1_image',fixedROIAuto[malf_atlas_subject],'inputVolume')
            MALFWF.connect(malfAtlases[malf_atlas_subject], 't1', movingROIAuto[malf_atlas_subject],'inputVolume')

            MALFWF.connect(fixedROIAuto[malf_atlas_subject], 'outputROIMaskVolume',A2SantsRegistrationPreMALF_SyN[malf_atlas_subject],'fixed_image_mask')
            MALFWF.connect(movingROIAuto[malf_atlas_subject], 'outputROIMaskVolume',A2SantsRegistrationPreMALF_SyN[malf_atlas_subject],'moving_image_mask')

        MALFWF.connect(BLICreator[malf_atlas_subject],'outputTransformFilename',
                       A2SantsRegistrationPreMALF_SyN[malf_atlas_subject],'initial_moving_transform')

        """
        make multimodal input for atlases
        """
        atlasMakeMultimodalInput[malf_atlas_subject] = pe.Node(Function(function=MakeVector, input_names=['inFN1', 'inFN2'], output_names=['outFNs']),
                                  run_without_submitting=True, name="atlasMakeMultimodalInput"+malf_atlas_subject)
        MALFWF.connect(malfAtlases[malf_atlas_subject], 't1', atlasMakeMultimodalInput[malf_atlas_subject], 'inFN1')
        if not onlyT1:
            MALFWF.connect(malfAtlases[malf_atlas_subject], 't2', atlasMakeMultimodalInput[malf_atlas_subject], 'inFN2')
        else:
            pass

        MALFWF.connect(sessionMakeMultimodalInput, 'outFNs',
                       A2SantsRegistrationPreMALF_SyN[malf_atlas_subject],'fixed_image')
        MALFWF.connect(atlasMakeMultimodalInput[malf_atlas_subject], 'outFNs',
                       A2SantsRegistrationPreMALF_SyN[malf_atlas_subject],'moving_image')
        MALFWF.connect(A2SantsRegistrationPreMALF_SyN[malf_atlas_subject],'warped_image',
                       warpedAtlasesMergeNode,'in'+str(merge_input_offset + malf_atlas_mergeindex*n_modality) )

        """
        Original t2 resampling
        """
        for modality_index in range(1,n_modality):
            t2Resample[malf_atlas_subject] = pe.Node(interface=ants.ApplyTransforms(),name="resampledT2"+malf_atlas_subject)
            many_cpu_t2Resample_options_dictionary = {'qsub_args': modify_qsub_args(CLUSTER_QUEUE,1,1,1), 'overwrite': True}
            t2Resample[malf_atlas_subject].plugin_args = many_cpu_t2Resample_options_dictionary
            t2Resample[malf_atlas_subject].inputs.dimension=3
            t2Resample[malf_atlas_subject].inputs.output_image=malf_atlas_subject+'_t2.nii.gz'
            t2Resample[malf_atlas_subject].inputs.interpolation='BSpline'
            t2Resample[malf_atlas_subject].inputs.default_value=0
            t2Resample[malf_atlas_subject].inputs.invert_transform_flags=[False]

            MALFWF.connect( A2SantsRegistrationPreMALF_SyN[malf_atlas_subject],'composite_transform',
                            t2Resample[malf_atlas_subject],'transforms')
            MALFWF.connect( inputsSpec, 'subj_t1_image',
                            t2Resample[malf_atlas_subject],'reference_image')
            MALFWF.connect( malfAtlases[malf_atlas_subject], 't2',
                            t2Resample[malf_atlas_subject],'input_image')
            MALFWF.connect(t2Resample[malf_atlas_subject],'output_image',
                           warpedAtlasesMergeNode,'in'+str(merge_input_offset + malf_atlas_mergeindex*n_modality+modality_index) )

        """
        Original labelmap resampling
        """
        labelMapResample[malf_atlas_subject] = pe.Node(interface=ants.ApplyTransforms(),name="resampledLabel"+malf_atlas_subject)
        many_cpu_labelMapResample_options_dictionary = {'qsub_args': modify_qsub_args(CLUSTER_QUEUE,1,1,1), 'overwrite': True}
        labelMapResample[malf_atlas_subject].plugin_args = many_cpu_labelMapResample_options_dictionary
        labelMapResample[malf_atlas_subject].inputs.dimension=3
        labelMapResample[malf_atlas_subject].inputs.output_image=malf_atlas_subject+'_2_subj_lbl.nii.gz'
        labelMapResample[malf_atlas_subject].inputs.interpolation='MultiLabel'
        labelMapResample[malf_atlas_subject].inputs.default_value=0
        labelMapResample[malf_atlas_subject].inputs.invert_transform_flags=[False]

        MALFWF.connect( A2SantsRegistrationPreMALF_SyN[malf_atlas_subject],'composite_transform',
                        labelMapResample[malf_atlas_subject],'transforms')
        MALFWF.connect( inputsSpec, 'subj_t1_image',
                        labelMapResample[malf_atlas_subject],'reference_image')
        MALFWF.connect( malfAtlases[malf_atlas_subject], 'label',
                        labelMapResample[malf_atlas_subject],'input_image')


        MALFWF.connect(labelMapResample[malf_atlas_subject],'output_image',warpedAtlasLblMergeNode,'in'+str(merge_input_offset + malf_atlas_mergeindex) )

        ### New labelmap resampling
        NewlabelMapResample[malf_atlas_subject] = pe.Node(interface=ants.ApplyTransforms(),name="FSWM_WLABEL_"+malf_atlas_subject)
        many_cpu_NewlabelMapResample_options_dictionary = {'qsub_args': modify_qsub_args(CLUSTER_QUEUE,1,1,1), 'overwrite': True}
        NewlabelMapResample[malf_atlas_subject].plugin_args = many_cpu_NewlabelMapResample_options_dictionary
        NewlabelMapResample[malf_atlas_subject].inputs.dimension=3
        NewlabelMapResample[malf_atlas_subject].inputs.output_image=malf_atlas_subject+'fswm_2_subj_lbl.nii.gz'
        NewlabelMapResample[malf_atlas_subject].inputs.interpolation='MultiLabel'
        NewlabelMapResample[malf_atlas_subject].inputs.default_value=0
        NewlabelMapResample[malf_atlas_subject].inputs.invert_transform_flags=[False]

        MALFWF.connect( A2SantsRegistrationPreMALF_SyN[malf_atlas_subject],'composite_transform',
                        NewlabelMapResample[malf_atlas_subject],'transforms')
        MALFWF.connect( inputsSpec, 'subj_t1_image',
                        NewlabelMapResample[malf_atlas_subject],'reference_image')
        MALFWF.connect( malfAtlases[malf_atlas_subject], 'label',
                        NewlabelMapResample[malf_atlas_subject],'input_image')


        MALFWF.connect(NewlabelMapResample[malf_atlas_subject],'output_image',NewwarpedAtlasLblMergeNode,'in'+str(merge_input_offset + malf_atlas_mergeindex) )

        malf_atlas_mergeindex += 1


    ## Now work on cleaning up the label maps
    from .FixLabelMapsTools import FixLabelMapFromNeuromorphemetrics2012
    from .FixLabelMapsTools import RecodeLabelMap

    ### Original NeuroMorphometrica merged fusion
    jointFusion = pe.Node(interface=ants.JointFusion(),name="JointFusion")
    many_cpu_JointFusion_options_dictionary = {'qsub_args': modify_qsub_args(CLUSTER_QUEUE,8,4,4), 'overwrite': True}
    jointFusion.plugin_args = many_cpu_JointFusion_options_dictionary
    jointFusion.inputs.dimension=3
    jointFusion.inputs.method='Joint[0.1,2]'
    jointFusion.inputs.output_label_image='MALF_HDAtlas20_2015_label.nii.gz'

    MALFWF.connect(warpedAtlasesMergeNode,'out',jointFusion,'warped_intensity_images')
    MALFWF.connect(warpedAtlasLblMergeNode,'out',jointFusion,'warped_label_images')
    #MALFWF.connect(inputsSpec, 'subj_t1_image',jointFusion,'target_image')
    MALFWF.connect(sessionMakeMultimodalInput, 'outFNs',jointFusion,'target_image')
    MALFWF.connect(jointFusion, 'output_label_image', outputsSpec,'MALF_HDAtlas20_2015_label')

    if onlyT1:
        jointFusion.inputs.modalities=1
    else:
        jointFusion.inputs.modalities=2


    ## We need to recode values to ensure that the labels match FreeSurer as close as possible by merging
    ## some labels together to standard FreeSurfer confenventions (i.e. for WMQL)
    RECODE_LABELS_2_Standard_FSWM = [
                                (15071,47),(15072,47),(15073,47),(15145,1011),(15157,1011),(15161,1011),
                                (15179,1012),(15141,1014),(15151,1017),(15163,1018),(15165,1019),(15143,1027),
                                (15191,1028),(15193,1028),(15185,1030),(15201,1030),(15175,1031),(15195,1031),
                                (15173,1035),(15144,2011),(15156,2011),(15160,2011),(15178,2012),(15140,2014),
                                (15150,2017),(15162,2018),(15164,2019),(15142,2027),(15190,2028),(15192,2028),
                                (15184,2030),(15174,2031),(15194,2031),(15172,2035),(15200,2030)]
    ## def RecodeLabelMap(InputFileName,OutputFileName,RECODE_TABLE):
    RecodeToStandardFSWM = pe.Node(Function(function=RecodeLabelMap,
                                                   input_names=['InputFileName','OutputFileName','RECODE_TABLE'],
                                                   output_names=['OutputFileName']),
                                                   name="RecodeToStandardFSWM")
    RecodeToStandardFSWM.inputs.RECODE_TABLE = RECODE_LABELS_2_Standard_FSWM
    RecodeToStandardFSWM.inputs.OutputFileName = 'MALF_HDAtlas20_2015_fs_standard_label.nii.gz'

    MALFWF.connect(RecodeToStandardFSWM,'OutputFileName',outputsSpec,'MALF_HDAtlas20_2015_fs_standard_label')

    ## MALF_SNAPSHOT_WRITER for Segmented result checking:
#    MALF_SNAPSHOT_WRITERNodeName = "MALF_ExtendedMALF_SNAPSHOT_WRITER"
#    MALF_SNAPSHOT_WRITER = pe.Node(interface=BRAINSSnapShotWriter(), name=MALF_SNAPSHOT_WRITERNodeName)

#    MALF_SNAPSHOT_WRITER.inputs.outputFilename = 'MALF_HDAtlas20_2015_CSFVBInjected_label.png'  # output specification
#    MALF_SNAPSHOT_WRITER.inputs.inputPlaneDirection = [2, 1, 1, 1, 1, 0, 0]
#    MALF_SNAPSHOT_WRITER.inputs.inputSliceToExtractInPhysicalPoint = [-3, -7, -3, 5, 7, 22, -22]

#    MALFWF.connect(MALF_SNAPSHOT_WRITER,'outputFilename',outputsSpec,'MALF_extended_snapshot')

    if runFixFusionLabelMap:
        ## post processing of jointfusion
        injectSurfaceCSFandVBIntoLabelMap = pe.Node(Function(function=FixLabelMapFromNeuromorphemetrics2012,
                                                      input_names=['fusionFN',
                                                        'FixedHeadFN',
                                                        'LeftHemisphereFN',
                                                        'outFN',
                                                        'OUT_DICT'],
                                                      output_names=['fixedFusionLabelFN']),
                                               name="injectSurfaceCSFandVBIntoLabelMap")
        injectSurfaceCSFandVBIntoLabelMap.inputs.outFN = 'MALF_HDAtlas20_2015_CSFVBInjected_label.nii.gz'
        FREESURFER_DICT = { 'BRAINSTEM': 16, 'RH_CSF':24, 'LH_CSF':24, 'BLOOD': 15000, 'UNKNOWN': 999,
                            'CONNECTED': [11,12,13,9,17,26,50,51,52,48,53,58]
                          }
        injectSurfaceCSFandVBIntoLabelMap.inputs.OUT_DICT = FREESURFER_DICT
        MALFWF.connect(jointFusion, 'output_label_image', injectSurfaceCSFandVBIntoLabelMap, 'fusionFN')
        MALFWF.connect(inputsSpec, 'subj_fixed_head_labels', injectSurfaceCSFandVBIntoLabelMap, 'FixedHeadFN')
        MALFWF.connect(inputsSpec, 'subj_left_hemisphere', injectSurfaceCSFandVBIntoLabelMap, 'LeftHemisphereFN')

        MALFWF.connect(injectSurfaceCSFandVBIntoLabelMap, 'fixedFusionLabelFN',
                       RecodeToStandardFSWM,'InputFileName')

        MALFWF.connect(injectSurfaceCSFandVBIntoLabelMap,'fixedFusionLabelFN',
                       outputsSpec,'MALF_HDAtlas20_2015_CSFVBInjected_label')
#        MALFWF.connect([(inputsSpec, MALF_SNAPSHOT_WRITER, [( 'subj_t1_image','inputVolumes')]),
#                    (injectSurfaceCSFandVBIntoLabelMap, MALF_SNAPSHOT_WRITER,
#                      [('fixedFusionLabelFN', 'inputBinaryVolumes')])
#                   ])
    else:
        MALFWF.connect(jointFusion, 'output_label_image',
                       RecodeToStandardFSWM,'InputFileName')
        MALFWF.connect(jointFusion, 'output_label_image',
                       outputsSpec,'MALF_HDAtlas20_2015_CSFVBInjected_label')
#        MALFWF.connect([(inputsSpec, MALF_SNAPSHOT_WRITER, [( 'subj_t1_image','inputVolumes')]),
#                    (jointFusion, MALF_SNAPSHOT_WRITER,
#                      [('output_label_image', 'inputBinaryVolumes')])
#                   ])

    ## Lobar Pacellation by recoding
    if master_config['relabel2lobes_filename'] != None:
        #print("Generate relabeled version based on {0}".format(master_config['relabel2lobes_filename']))

        RECODE_LABELS_2_LobarPacellation = readRecodingList( master_config['relabel2lobes_filename'] )
        RecordToFSLobes = pe.Node(Function(function=RecodeLabelMap,
                                                    input_names=['InputFileName','OutputFileName','RECODE_TABLE'],
                                                    output_names=['OutputFileName']),
                                                    name="RecordToFSLobes")
        RecordToFSLobes.inputs.RECODE_TABLE = RECODE_LABELS_2_LobarPacellation
        RecordToFSLobes.inputs.OutputFileName = 'MALF_HDAtlas20_2015_lobar_label.nii.gz'
        MALFWF.connect(RecodeToStandardFSWM, 'OutputFileName',RecordToFSLobes,'InputFileName')
        MALFWF.connect(RecordToFSLobes,'OutputFileName',outputsSpec,'MALF_HDAtlas20_2015_lobar_label')

    return MALFWF