Example #1
0
def Matching(cf):

    if cf.compute.useCUDA and cf.compute.gpuID is not None:
        ca.SetCUDADevice(cf.compute.gpuID)

    # prepare output directory
    common.Mkdir_p(os.path.dirname(cf.io.outputPrefix))

    # Output loaded config
    if cf.io.outputPrefix is not None:
        cfstr = Config.ConfigToYAML(MatchingConfigSpec, cf)
        with open(cf.io.outputPrefix + "parsedconfig.yaml", "w") as f:
            f.write(cfstr)

    mType = ca.MEM_DEVICE if cf.compute.useCUDA else ca.MEM_HOST


    I0 = common.LoadITKImage(cf.study.I0, mType)
    I1 = common.LoadITKImage(cf.study.I1, mType)
    #ca.DivC_I(I0,255.0)
    #ca.DivC_I(I1,255.0)
    grid = I0.grid()

    ca.ThreadMemoryManager.init(grid, mType, 1)
    
    #common.DebugHere()
    # TODO: need to work on these
    t = [x*1./cf.optim.nTimeSteps for x in range(cf.optim.nTimeSteps+1)]
    checkpointinds = range(1,len(t))
    checkpointstates =  [(ca.Field3D(grid,mType),ca.Field3D(grid,mType)) for idx in checkpointinds]

    p = MatchingVariables(I0,I1, cf.vectormomentum.sigma, t,checkpointinds, checkpointstates, cf.vectormomentum.diffOpParams[0], cf.vectormomentum.diffOpParams[1], cf.vectormomentum.diffOpParams[2], cf.optim.Niter, cf.optim.stepSize, cf.optim.maxPert, cf.optim.nTimeSteps, integMethod = cf.optim.integMethod, optMethod=cf.optim.method, nInv=cf.optim.NIterForInverse,plotEvery=cf.io.plotEvery, plotSlice = cf.io.plotSlice, quiverEvery = cf.io.quiverEvery, outputPrefix = cf.io.outputPrefix)

    RunMatching(p)

    # write output
    if cf.io.outputPrefix is not None: 
        # reset all variables by shooting once, may have been overwritten
        CAvmCommon.IntegrateGeodesic(p.m0,p.t,p.diffOp,\
                          p.m, p.g, p.ginv,\
                          p.scratchV1, p.scratchV2,p. scratchV3,\
                          p.checkpointstates, p.checkpointinds,\
                          Ninv=p.nInv, integMethod = p.integMethod)
        common.SaveITKField(p.m0, cf.io.outputPrefix+"m0.mhd")
        common.SaveITKField(p.ginv, cf.io.outputPrefix+"phiinv.mhd")
        common.SaveITKField(p.g, cf.io.outputPrefix+"phi.mhd")
def BuildAtlas(cf):
    """Worker for running Atlas construction on a subset of individuals.
    Runs Atlas on this subset sequentially. The variations retuned are
    summed up to get update for all individuals
    """

    localRank = Compute.GetMPIInfo()['local_rank']
    rank = Compute.GetMPIInfo()['rank']

    # prepare output directory
    common.Mkdir_p(os.path.dirname(cf.io.outputPrefix))

    # just one reporter process on each node
    isReporter = rank == 0
    cf.study.numSubjects = len(cf.study.subjectImages)

    if isReporter:
        # Output loaded config
        if cf.io.outputPrefix is not None:
            cfstr = Config.ConfigToYAML(AtlasConfigSpec, cf)
            with open(cf.io.outputPrefix + "parsedconfig.yaml", "w") as f:
                f.write(cfstr)
    #common.DebugHere()

    # if MPI check if processes are greater than number of subjects. it is okay if there are more subjects than processes

    if cf.compute.useMPI and (cf.study.numSubjects < cf.compute.numProcesses):
        raise Exception("Please don't use more processes " +
                        "than total number of individuals")

    # subdivide data, create subsets for this thread to work on
    nodeSubjectIds = cf.study.subjectIds[rank::cf.compute.numProcesses]
    nodeImages = cf.study.subjectImages[rank::cf.compute.numProcesses]
    nodeWeights = cf.study.subjectWeights[rank::cf.compute.numProcesses]

    numLocalSubjects = len(nodeImages)
    print 'rank:', rank, ', localRank:', localRank, ', nodeImages:', nodeImages, ', nodeWeights:', nodeWeights

    # mem type is determined by whether or not we're using CUDA
    mType = ca.MEM_DEVICE if cf.compute.useCUDA else ca.MEM_HOST

    # load data in memory
    # load intercepts
    J_array = [
        common.LoadITKImage(f, mType) if isinstance(f, str) else f
        for f in nodeImages
    ]

    # get imGrid from data
    imGrid = J_array[0].grid()

    # atlas image
    atlas = ca.Image3D(imGrid, mType)

    # allocate memory to store only the initial momenta for each individual in this thread
    m_array = [ca.Field3D(imGrid, mType) for i in range(numLocalSubjects)]

    # allocate only one copy of scratch memory to be reused for each local individual in this thread in loop
    p = WarpVariables(imGrid,
                      mType,
                      cf.vectormomentum.diffOpParams[0],
                      cf.vectormomentum.diffOpParams[1],
                      cf.vectormomentum.diffOpParams[2],
                      cf.optim.NIterForInverse,
                      cf.vectormomentum.sigma,
                      cf.optim.stepSize,
                      integMethod=cf.optim.integMethod)

    # memory to accumulate numerators and denominators for atlas from
    # local individuals which will be summed across MPI threads
    sumSplatI = ca.Image3D(imGrid, mType)
    sumJac = ca.Image3D(imGrid, mType)

    # start up the memory manager for scratch variables
    ca.ThreadMemoryManager.init(imGrid, mType, 0)

    # need some host memory in np array format for MPI reductions
    if cf.compute.useMPI:
        mpiImageBuff = None if mType == ca.MEM_HOST else ca.Image3D(
            imGrid, ca.MEM_HOST)

    t = [
        x * 1. / (cf.optim.nTimeSteps) for x in range(cf.optim.nTimeSteps + 1)
    ]
    cpinds = range(1, len(t))
    msmtinds = [
        len(t) - 2
    ]  # since t=0 is not in cpinds, thats just identity deformation so not checkpointed
    cpstates = [(ca.Field3D(imGrid, mType), ca.Field3D(imGrid, mType))
                for idx in cpinds]
    gradAtMsmts = [ca.Image3D(imGrid, mType) for idx in msmtinds]

    EnergyHistory = []

    # TODO: better initializations
    # initialize atlas image with zeros.
    ca.SetMem(atlas, 0.0)
    # initialize momenta with zeros

    for m0_individual in m_array:
        ca.SetMem(m0_individual, 0.0)
    '''
    # initial template image
    ca.SetMem(groupState.I0, 0.0)
    tmp = ca.ManagedImage3D(imGrid, mType)

    for tdisc in tdiscGroup:
        if tdisc.J is not None:
            ca.Copy(tmp, tdisc.J)
            groupState.I0 += tmp
    del tmp
    if cf.compute.useMPI:
        Compute.Reduce(groupState.I0, mpiImageBuff)
    
    # divide by total num subjects
    groupState.I0 /= cf.study.numSubjects
    '''

    # preprocessinput

    # assign atlas reference to p.I0. This reference will not change.
    p.I0 = atlas

    # run the loop
    for it in range(cf.optim.Niter):
        # run one iteration of warp for each individual and update
        # their own initial momenta and also accumulate SplatI and Jac
        ca.SetMem(sumSplatI, 0.0)
        ca.SetMem(sumJac, 0.0)
        TotalVEnergy = np.array([0.0])
        TotalIEnergy = np.array([0.0])

        for itsub in range(numLocalSubjects):
            # initializations for this subject, this only assigns
            # reference to image variables
            p.m0 = m_array[itsub]
            Imsmts = [J_array[itsub]]

            # run warp iteration
            VEnergy, IEnergy = RunWarpIteration(nodeSubjectIds[itsub], cf, p,
                                                t, Imsmts, cpinds, cpstates,
                                                msmtinds, gradAtMsmts, it)

            # gather relevant results
            ca.Add_I(sumSplatI, p.sumSplatI)
            ca.Add_I(sumJac, p.sumJac)
            TotalVEnergy[0] += VEnergy
            TotalIEnergy[0] += IEnergy

        # if there are multiple nodes we'll need to sum across processes now
        if cf.compute.useMPI:
            # do an MPI sum
            Compute.Reduce(sumSplatI, mpiImageBuff)
            Compute.Reduce(sumJac, mpiImageBuff)

            # also sum up energies of other nodes
            mpi4py.MPI.COMM_WORLD.Allreduce(mpi4py.MPI.IN_PLACE,
                                            TotalVEnergy,
                                            op=mpi4py.MPI.SUM)
            mpi4py.MPI.COMM_WORLD.Allreduce(mpi4py.MPI.IN_PLACE,
                                            TotalIEnergy,
                                            op=mpi4py.MPI.SUM)

        EnergyHistory.append([TotalVEnergy[0], TotalIEnergy[0]])

        # now divide to get the new atlas image
        ca.Div(atlas, sumSplatI, sumJac)

        # keep track of energy in this iteration
        if isReporter and cf.io.plotEvery > 0 and ((
            (it + 1) % cf.io.plotEvery == 0) or (it == cf.optim.Niter - 1)):
            # plots
            AtlasPlots(cf, p, atlas, m_array, EnergyHistory)

        if isReporter:
            # print out energy
            (VEnergy, IEnergy) = EnergyHistory[-1]
            print "Iter", it, "of", cf.optim.Niter, ":", VEnergy + IEnergy, '(Total) = ', VEnergy, '(Vector) + ', IEnergy, '(Image)'

    # write output images and fields
    AtlasWriteOutput(cf, atlas, m_array, nodeSubjectIds, isReporter)
def MatchingImageMomenta(cf):
    """Runs matching for image momenta pair."""
    if cf.compute.useCUDA and cf.compute.gpuID is not None:
        ca.SetCUDADevice(cf.compute.gpuID)

    common.DebugHere()
    # prepare output directory
    common.Mkdir_p(os.path.dirname(cf.io.outputPrefix))

    # Output loaded config
    if cf.io.outputPrefix is not None:
        cfstr = Config.ConfigToYAML(MatchingImageMomentaConfigSpec, cf)
        with open(cf.io.outputPrefix + "parsedconfig.yaml", "w") as f:
            f.write(cfstr)

    # mem type is determined by whether or not we're using CUDA
    mType = ca.MEM_DEVICE if cf.compute.useCUDA else ca.MEM_HOST

    # load data in memory
    I0 = common.LoadITKImage(cf.study.I, mType)
    m0 = common.LoadITKField(cf.study.m, mType)
    J1 = common.LoadITKImage(cf.study.J, mType)
    n1 = common.LoadITKField(cf.study.n, mType)

    # get imGrid from data
    imGrid = I0.grid()

    # create time array with checkpointing info for this geodesic to be estimated
    (s, scratchInd,
     rCpinds) = CAvmHGM.HGMSetUpTimeArray(cf.optim.nTimeSteps, [1.0], 0.001)
    tDiscGeodesic = CAvmHGMCommon.HGMSetupTimeDiscretizationResidual(
        s, rCpinds, imGrid, mType)

    # create the state variable for geodesic that is going to hold all info
    p0 = ca.Field3D(imGrid, mType)
    geodesicState = CAvmHGMCommon.HGMResidualState(
        I0,
        p0,
        imGrid,
        mType,
        cf.vectormomentum.diffOpParams[0],
        cf.vectormomentum.diffOpParams[1],
        cf.vectormomentum.diffOpParams[2],
        s,
        cf.optim.NIterForInverse,
        1.0,
        cf.vectormomentum.sigmaM,
        cf.vectormomentum.sigmaI,
        cf.optim.stepSize,
        integMethod=cf.optim.integMethod)
    # initialize with zero
    ca.SetMem(geodesicState.p0, 0.0)
    # start up the memory manager for scratch variables
    ca.ThreadMemoryManager.init(imGrid, mType, 0)
    EnergyHistory = []
    # run the loop
    for it in range(cf.optim.Niter):
        # shoot the geodesic forward
        CAvmHGMCommon.HGMIntegrateGeodesic(geodesicState.p0, geodesicState.s,
                                           geodesicState.diffOp,
                                           geodesicState.p, geodesicState.rho,
                                           geodesicState.rhoinv, tDiscGeodesic,
                                           geodesicState.Ninv,
                                           geodesicState.integMethod)
        # integrate the geodesic backward
        CAvmHGMCommon.HGMIntegrateAdjointsResidual(geodesicState,
                                                   tDiscGeodesic, m0, J1, n1)

        # TODO: verify it should just be log map/simple image matching when sigmaM=\infty
        # gradient descent step for geodesic.p0
        CAvmHGMCommon.HGMTakeGradientStepResidual(geodesicState)

        # compute and print energy
        (VEnergy, IEnergy,
         MEnergy) = MatchingImageMomentaComputeEnergy(geodesicState, m0, J1,
                                                      n1)
        EnergyHistory.append(
            [VEnergy + IEnergy + MEnergy, VEnergy, IEnergy, MEnergy])
        print "Iter", it, "of", cf.optim.Niter, ":", VEnergy + IEnergy + MEnergy, '(Total) = ', VEnergy, '(Vector) + ', IEnergy, '(Image Match) + ', MEnergy, '(Momenta Match)'

        # plots
        if cf.io.plotEvery > 0 and (((it + 1) % cf.io.plotEvery == 0) or
                                    (it == cf.optim.Niter - 1)):
            MatchingImageMomentaPlots(cf,
                                      geodesicState,
                                      tDiscGeodesic,
                                      EnergyHistory,
                                      m0,
                                      J1,
                                      n1,
                                      writeOutput=True)

    # write output
    MatchingImageMomentaWriteOuput(cf, geodesicState)
Example #4
0
def predict_image(args, moving_images, target_images, output_prefixes):
    if (args.use_CPU_for_shooting):
        mType = ca.MEM_HOST
    else:
        mType = ca.MEM_DEVICE

    # load the prediction network
    predict_network_config = torch.load(args.prediction_parameter)
    prediction_net = create_net(args, predict_network_config);

    batch_size = args.batch_size
    patch_size = predict_network_config['patch_size']
    input_batch = torch.zeros(batch_size, 2, patch_size, patch_size, patch_size).cuda()

    # use correction network if required
    if args.use_correction:
        correction_network_config = torch.load(args.correction_parameter);
        correction_net = create_net(args, correction_network_config);
    else:
        correction_net = None;

    # start prediction
    for i in range(0, len(moving_images)):

        common.Mkdir_p(os.path.dirname(output_prefixes[i]))
        if (args.affine_align):
            # Perform affine registration to both moving and target image to the ICBM152 atlas space.
            # Registration is done using Niftireg.
            call(["reg_aladin",
                  "-noSym", "-speeeeed", "-ref", args.atlas ,
                  "-flo", moving_images[i],
                  "-res", output_prefixes[i]+"moving_affine.nii",
                  "-aff", output_prefixes[i]+'moving_affine_transform.txt'])

            call(["reg_aladin",
                  "-noSym", "-speeeeed" ,"-ref", args.atlas ,
                  "-flo", target_images[i],
                  "-res", output_prefixes[i]+"target_affine.nii",
                  "-aff", output_prefixes[i]+'target_affine_transform.txt'])

            moving_image = common.LoadITKImage(output_prefixes[i]+"moving_affine.nii", mType)
            target_image = common.LoadITKImage(output_prefixes[i]+"target_affine.nii", mType)
        else:
            moving_image = common.LoadITKImage(moving_images[i], mType)
            target_image = common.LoadITKImage(target_images[i], mType)

        #preprocessing of the image
        moving_image_np = preprocess_image(moving_image, args.histeq);
        target_image_np = preprocess_image(target_image, args.histeq);

        grid = moving_image.grid()
        #moving_image = ca.Image3D(grid, mType)
        #target_image = ca.Image3D(grid, mType)
        moving_image_processed = common.ImFromNPArr(moving_image_np, mType)
        target_image_processed = common.ImFromNPArr(target_image_np, mType)
        moving_image.setGrid(grid)
        target_image.setGrid(grid)

        # Indicating whether we are using the old parameter files for the Neuroimage experiments (use .t7 files from matlab .h5 format)
        predict_transform_space = False
        if 'matlab_t7' in predict_network_config:
            predict_transform_space = True
        # run actual prediction
        prediction_result = util.predict_momentum(moving_image_np, target_image_np, input_batch, batch_size, patch_size, prediction_net, predict_transform_space);
        m0 = prediction_result['image_space']
        #convert to registration space and perform registration
        m0_reg = common.FieldFromNPArr(m0, mType);

        #perform correction
        if (args.use_correction):
            registration_result = registration_methods.geodesic_shooting(moving_image_processed, target_image_processed, m0_reg, args.shoot_steps, mType, predict_network_config)
            target_inv_np = common.AsNPCopy(registration_result['I1_inv'])

            correct_transform_space = False
            if 'matlab_t7' in correction_network_config:
                correct_transform_space = True
            correction_result = util.predict_momentum(moving_image_np, target_inv_np, input_batch, batch_size, patch_size, correction_net, correct_transform_space);
            m0_correct = correction_result['image_space']
            m0 += m0_correct;
            m0_reg = common.FieldFromNPArr(m0, mType);

        registration_result = registration_methods.geodesic_shooting(moving_image, target_image, m0_reg, args.shoot_steps, mType, predict_network_config)

        #endif

        write_result(registration_result, output_prefixes[i]);
def GeodesicShooting(cf):

    # prepare output directory
    common.Mkdir_p(os.path.dirname(cf.io.outputPrefix))

    # Output loaded config
    if cf.io.outputPrefix is not None:
        cfstr = Config.ConfigToYAML(GeodesicShootingConfigSpec, cf)
        with open(cf.io.outputPrefix + "parsedconfig.yaml", "w") as f:
            f.write(cfstr)

    mType = ca.MEM_DEVICE if cf.useCUDA else ca.MEM_HOST
    #common.DebugHere()
    I0 = common.LoadITKImage(cf.study.I0, mType)
    m0 = common.LoadITKField(cf.study.m0, mType)
    grid = I0.grid()

    ca.ThreadMemoryManager.init(grid, mType, 1)
    # set up diffOp
    if mType == ca.MEM_HOST:
        diffOp = ca.FluidKernelFFTCPU()
    else:
        diffOp = ca.FluidKernelFFTGPU()
    diffOp.setAlpha(cf.diffOpParams[0])
    diffOp.setBeta(cf.diffOpParams[1])
    diffOp.setGamma(cf.diffOpParams[2])
    diffOp.setGrid(grid)

    g = ca.Field3D(grid, mType)
    ginv = ca.Field3D(grid, mType)
    mt = ca.Field3D(grid, mType)
    It = ca.Image3D(grid, mType)
    t = [
        x * 1. / cf.integration.nTimeSteps
        for x in range(cf.integration.nTimeSteps + 1)
    ]
    checkpointinds = range(1, len(t))
    checkpointstates = [(ca.Field3D(grid, mType), ca.Field3D(grid, mType))
                        for idx in checkpointinds]

    scratchV1 = ca.Field3D(grid, mType)
    scratchV2 = ca.Field3D(grid, mType)
    scratchV3 = ca.Field3D(grid, mType)
    # scale momenta to shoot
    cf.study.scaleMomenta = float(cf.study.scaleMomenta)
    if abs(cf.study.scaleMomenta) > 0.000000:
        ca.MulC_I(m0, float(cf.study.scaleMomenta))
        CAvmCommon.IntegrateGeodesic(m0,t,diffOp, mt, g, ginv,\
                                     scratchV1,scratchV2,scratchV3,\
                                     keepstates=checkpointstates,keepinds=checkpointinds,
                                     Ninv=cf.integration.NIterForInverse, integMethod = cf.integration.integMethod)
    else:
        ca.Copy(It, I0)
        ca.Copy(mt, m0)
        ca.SetToIdentity(ginv)
        ca.SetToIdentity(g)

    # write output
    if cf.io.outputPrefix is not None:
        # scale back shotmomenta before writing
        if abs(cf.study.scaleMomenta) > 0.000000:
            ca.ApplyH(It, I0, ginv)
            ca.CoAd(mt, ginv, m0)
            ca.DivC_I(mt, float(cf.study.scaleMomenta))

        common.SaveITKImage(It, cf.io.outputPrefix + "I1.mhd")
        common.SaveITKField(mt, cf.io.outputPrefix + "m1.mhd")
        common.SaveITKField(ginv, cf.io.outputPrefix + "phiinv.mhd")
        common.SaveITKField(g, cf.io.outputPrefix + "phi.mhd")
        GeodesicShootingPlots(g, ginv, I0, It, cf)
        if cf.io.saveFrames:
            SaveFrames(checkpointstates, checkpointinds, I0, It, m0, mt, cf)
def SaveFrames(checkpointstates, checkpointinds, I0, It, m0, mt, cf):
    momentathresh = 0.00002
    common.Mkdir_p(os.path.dirname(cf.io.outputPrefix) + '/frames/')
    image_idx = 0
    fig = plt.figure(1, frameon=False)
    plt.clf()
    display.DispImage(I0,
                      '',
                      newFig=False,
                      cmap='gray',
                      dim=cf.io.plotSliceDim,
                      sliceIdx=cf.io.plotSlice)
    plt.draw()
    outfilename = cf.io.outputPrefix + '/frames/I' + str(image_idx).zfill(
        5) + '.png'
    fig.set_size_inches(4, 4)
    plt.savefig(outfilename, bbox_inches='tight', pad_inches=0, dpi=100)

    fig = plt.figure(2, frameon=False)
    plt.clf()
    temp = ca.Field3D(I0.grid(), I0.memType())
    ca.SetToIdentity(temp)
    common.DebugHere()
    CAvmCommon.MyGridPlot(temp,
                          every=cf.io.gridEvery,
                          color='k',
                          dim=cf.io.plotSliceDim,
                          sliceIdx=cf.io.plotSlice,
                          isVF=False,
                          plotBase=False)
    #fig.patch.set_alpha(0)
    #fig.patch.set_visible(False)
    a = fig.gca()
    #a.set_frame_on(False)
    a.set_xticks([])
    a.set_yticks([])
    plt.axis('tight')
    plt.axis('image')
    plt.axis('off')
    plt.draw()
    fig.set_size_inches(4, 4)
    outfilename = cf.io.outputPrefix + '/frames/invdef' + str(image_idx).zfill(
        5) + '.png'
    plt.savefig(outfilename, bbox_inches='tight', pad_inches=0, dpi=100)

    fig = plt.figure(3, frameon=False)
    plt.clf()
    CAvmCommon.MyGridPlot(temp,
                          every=cf.io.gridEvery,
                          color='k',
                          dim=cf.io.plotSliceDim,
                          sliceIdx=cf.io.plotSlice,
                          isVF=False,
                          plotBase=False)
    #fig.patch.set_alpha(0)
    #fig.patch.set_visible(False)
    a = fig.gca()
    #a.set_frame_on(False)
    a.set_xticks([])
    a.set_yticks([])
    plt.axis('tight')
    plt.axis('image')
    plt.axis('off')
    plt.draw()
    fig.set_size_inches(4, 4)
    outfilename = cf.io.outputPrefix + '/frames/def' + str(image_idx).zfill(
        5) + '.png'
    plt.savefig(outfilename, bbox_inches='tight', pad_inches=0, dpi=100)

    fig = plt.figure(4, frameon=False)
    plt.clf()
    display.DispImage(I0,
                      '',
                      newFig=False,
                      cmap='gray',
                      dim=cf.io.plotSliceDim,
                      sliceIdx=cf.io.plotSlice)
    plt.hold('True')
    CAvmCommon.MyQuiver(m0,
                        dim=cf.io.plotSliceDim,
                        sliceIdx=cf.io.plotSlice,
                        every=cf.io.quiverEvery,
                        thresh=momentathresh,
                        scaleArrows=0.25,
                        arrowCol='r',
                        lineWidth=0.5,
                        width=0.005)
    plt.draw()

    plt.hold('False')

    outfilename = cf.io.outputPrefix + '/frames/m' + str(image_idx).zfill(
        5) + '.png'
    fig.set_size_inches(4, 4)
    plt.savefig(outfilename, bbox_inches='tight', pad_inches=0, dpi=100)

    for i in range(len(checkpointinds)):
        image_idx = image_idx + 1
        ca.ApplyH(It, I0, checkpointstates[i][1])
        fig = plt.figure(1, frameon=False)
        plt.clf()
        display.DispImage(It,
                          '',
                          newFig=False,
                          cmap='gray',
                          dim=cf.io.plotSliceDim,
                          sliceIdx=cf.io.plotSlice)
        plt.draw()
        outfilename = cf.io.outputPrefix + '/frames/I' + str(image_idx).zfill(
            5) + '.png'
        fig.set_size_inches(4, 4)
        plt.savefig(outfilename, bbox_inches='tight', pad_inches=0, dpi=100)

        fig = plt.figure(2, frameon=False)
        plt.clf()
        CAvmCommon.MyGridPlot(checkpointstates[i][1],
                              every=cf.io.gridEvery,
                              color='k',
                              dim=cf.io.plotSliceDim,
                              sliceIdx=cf.io.plotSlice,
                              isVF=False,
                              plotBase=False)
        #fig.patch.set_alpha(0)
        #fig.patch.set_visible(False)
        a = fig.gca()
        #a.set_frame_on(False)
        a.set_xticks([])
        a.set_yticks([])
        plt.axis('tight')
        plt.axis('image')
        plt.axis('off')
        plt.draw()
        outfilename = cf.io.outputPrefix + '/frames/invdef' + str(
            image_idx).zfill(5) + '.png'
        fig.set_size_inches(4, 4)
        plt.savefig(outfilename, bbox_inches='tight', pad_inches=0, dpi=100)

        fig = plt.figure(3, frameon=False)
        plt.clf()
        CAvmCommon.MyGridPlot(checkpointstates[i][0],
                              every=cf.io.gridEvery,
                              color='k',
                              dim=cf.io.plotSliceDim,
                              sliceIdx=cf.io.plotSlice,
                              isVF=False,
                              plotBase=False)
        #fig.patch.set_alpha(0)
        #fig.patch.set_visible(False)
        a = fig.gca()
        #a.set_frame_on(False)
        a.set_xticks([])
        a.set_yticks([])
        plt.axis('tight')
        plt.axis('image')
        plt.axis('off')
        plt.draw()
        outfilename = cf.io.outputPrefix + '/frames/def' + str(
            image_idx).zfill(5) + '.png'
        fig.set_size_inches(4, 4)
        plt.savefig(outfilename, bbox_inches='tight', pad_inches=0, dpi=100)

        ca.CoAd(mt, checkpointstates[i][1], m0)
        fig = plt.figure(4, frameon=False)
        plt.clf()
        display.DispImage(It,
                          '',
                          newFig=False,
                          cmap='gray',
                          dim=cf.io.plotSliceDim,
                          sliceIdx=cf.io.plotSlice)
        plt.hold('True')
        CAvmCommon.MyQuiver(mt,
                            dim=cf.io.plotSliceDim,
                            sliceIdx=cf.io.plotSlice,
                            every=cf.io.quiverEvery,
                            thresh=momentathresh,
                            scaleArrows=0.40,
                            arrowCol='r',
                            lineWidth=0.5,
                            width=0.005)
        plt.draw()
        plt.hold('False')
        outfilename = cf.io.outputPrefix + '/frames/m' + str(image_idx).zfill(
            5) + '.png'
        fig.set_size_inches(4, 4)
        plt.savefig(outfilename, bbox_inches='tight', pad_inches=0, dpi=100)
Example #7
0
def BuildHGM(cf):
    """Worker for running Hierarchical Geodesic Model (HGM) 
n    for group geodesic estimation on a subset of individuals. 
    Runs HGM on this subset sequentially. The variations retuned
    are summed up to get update for all individuals"""

    size = Compute.GetMPIInfo()['size']
    rank = Compute.GetMPIInfo()['rank']
    name = Compute.GetMPIInfo()['name']
    localRank = Compute.GetMPIInfo()['local_rank']
    nodename = socket.gethostname()

    # prepare output directory
    common.Mkdir_p(os.path.dirname(cf.io.outputPrefix))

    # just one reporter process on each node
    isReporter = rank == 0
    cf.study.numSubjects = len(cf.study.subjectIntercepts)
    if isReporter:
        # Output loaded config
        if cf.io.outputPrefix is not None:
            cfstr = Config.ConfigToYAML(HGMConfigSpec, cf)
            with open(cf.io.outputPrefix + "parsedconfig.yaml", "w") as f:
                f.write(cfstr)
    #common.DebugHere()

    # if MPI check if processes are greater than number of subjects. it is okay if there are more subjects than processes

    if cf.compute.useMPI and (cf.study.numSubjects < cf.compute.numProcesses):
        raise Exception("Please don't use more processes " +
                        "than total number of individuals")

    # subdivide data, create subsets for this thread to work on
    nodeSubjectIds = cf.study.subjectIds[rank::cf.compute.numProcesses]
    nodeIntercepts = cf.study.subjectIntercepts[rank::cf.compute.numProcesses]
    nodeSlopes = cf.study.subjectSlopes[rank::cf.compute.numProcesses]
    nodeBaselineTimes = cf.study.subjectBaselineTimes[rank::cf.compute.
                                                      numProcesses]
    sys.stdout.write(
        "This is process %d of %d with name: %s on machinename: %s and local rank: %d.\nnodeIntercepts: %s\n nodeSlopes: %s\n nodeBaselineTimes: %s\n"
        % (rank, size, name, nodename, localRank, nodeIntercepts, nodeSlopes,
           nodeBaselineTimes))

    # mem type is determined by whether or not we're using CUDA
    mType = ca.MEM_DEVICE if cf.compute.useCUDA else ca.MEM_HOST

    # load data in memory
    # load intercepts
    J = [
        common.LoadITKImage(f, mType) if isinstance(f, str) else f
        for f in nodeIntercepts
    ]

    # load slopes
    n = [
        common.LoadITKField(f, mType) if isinstance(f, str) else f
        for f in nodeSlopes
    ]

    # get imGrid from data
    imGrid = J[0].grid()

    # create time array with checkpointing info for group geodesic
    (t, Jind, gCpinds) = HGMSetUpTimeArray(cf.optim.nTimeStepsGroup,
                                           nodeBaselineTimes, 0.0000001)
    tdiscGroup = CAvmHGMCommon.HGMSetupTimeDiscretizationGroup(
        t, J, n, Jind, gCpinds, mType, nodeSubjectIds)

    # create time array with checkpointing info for residual geodesic
    (s, scratchInd, rCpinds) = HGMSetUpTimeArray(cf.optim.nTimeStepsResidual,
                                                 [1.0], 0.0000001)
    tdiscResidual = CAvmHGMCommon.HGMSetupTimeDiscretizationResidual(
        s, rCpinds, imGrid, mType)

    # create group state and residual state
    groupState = CAvmHGMCommon.HGMGroupState(
        imGrid,
        mType,
        cf.vectormomentum.diffOpParamsGroup[0],
        cf.vectormomentum.diffOpParamsGroup[1],
        cf.vectormomentum.diffOpParamsGroup[2],
        t,
        cf.optim.NIterForInverse,
        cf.vectormomentum.varIntercept,
        cf.vectormomentum.varSlope,
        cf.vectormomentum.varInterceptReg,
        cf.optim.stepSizeGroup,
        integMethod=cf.optim.integMethodGroup)

    #ca.Copy(groupState.I0, common.LoadITKImage('/usr/sci/projects/ADNI/nikhil/software/vectormomentumtest/TestData/FlowerData/Longitudinal/GroupGeodesic/I0.mhd', mType))

    # note that residual state is treated a scratch variable in this algorithm and reused for computing residual geodesics of multiple individual
    residualState = CAvmHGMCommon.HGMResidualState(
        None,
        None,
        imGrid,
        mType,
        cf.vectormomentum.diffOpParamsResidual[0],
        cf.vectormomentum.diffOpParamsResidual[1],
        cf.vectormomentum.diffOpParamsResidual[2],
        s,
        cf.optim.NIterForInverse,
        cf.vectormomentum.varIntercept,
        cf.vectormomentum.varSlope,
        cf.vectormomentum.varInterceptReg,
        cf.optim.stepSizeResidual,
        integMethod=cf.optim.integMethodResidual)

    # start up the memory manager for scratch variables
    ca.ThreadMemoryManager.init(imGrid, mType, 0)

    # need some host memory in np array format for MPI reductions
    if cf.compute.useMPI:
        mpiImageBuff = None if mType == ca.MEM_HOST else ca.Image3D(
            imGrid, ca.MEM_HOST)
        mpiFieldBuff = None if mType == ca.MEM_HOST else ca.Field3D(
            imGrid, ca.MEM_HOST)
    for i in range(len(groupState.t) - 1, -1, -1):
        if tdiscGroup[i].J is not None:
            indx_last_individual = i
            break
    '''
    # initial template image
    ca.SetMem(groupState.I0, 0.0)
    tmp = ca.ManagedImage3D(imGrid, mType)

    for tdisc in tdiscGroup:
        if tdisc.J is not None:
            ca.Copy(tmp, tdisc.J)
            groupState.I0 += tmp
    del tmp
    if cf.compute.useMPI:
        Compute.Reduce(groupState.I0, mpiImageBuff)
    
    # divide by total num subjects
    groupState.I0 /= cf.study.numSubjects
    '''

    # run the loop

    for it in range(cf.optim.Niter):
        # compute HGM variation for group
        HGMGroupVariation(groupState, tdiscGroup, residualState, tdiscResidual,
                          cf.io.outputPrefix, rank, it)
        common.CheckCUDAError("Error after HGM iteration")
        # compute gradient for momenta (m is used as scratch)
        # if there are multiple nodes we'll need to sum across processes now
        if cf.compute.useMPI:
            # do an MPI sum
            Compute.Reduce(groupState.sumSplatI, mpiImageBuff)
            Compute.Reduce(groupState.sumJac, mpiImageBuff)
            Compute.Reduce(groupState.madj, mpiFieldBuff)
            # also sum up energies of other nodes
            # intercept
            Eintercept = np.array([groupState.EnergyHistory[-1][1]])
            mpi4py.MPI.COMM_WORLD.Allreduce(mpi4py.MPI.IN_PLACE,
                                            Eintercept,
                                            op=mpi4py.MPI.SUM)
            groupState.EnergyHistory[-1][1] = Eintercept[0]

            Eslope = np.array([groupState.EnergyHistory[-1][2]])
            mpi4py.MPI.COMM_WORLD.Allreduce(mpi4py.MPI.IN_PLACE,
                                            Eslope,
                                            op=mpi4py.MPI.SUM)
            groupState.EnergyHistory[-1][2] = Eslope[0]

        ca.Copy(groupState.m, groupState.m0)
        groupState.diffOp.applyInverseOperator(groupState.m)
        ca.Sub_I(groupState.m, groupState.madj)
        #groupState.diffOp.applyOperator(groupState.m)
        # now take gradient step in momenta for group
        if cf.optim.method == 'FIXEDGD':
            # take fixed stepsize gradient step
            ca.Add_MulC_I(groupState.m0, groupState.m, -cf.optim.stepSizeGroup)
        else:
            raise Exception("Unknown optimization scheme: " + cf.optim.method)
        # end if

        # now divide to get the new base image for group
        ca.Div(groupState.I0, groupState.sumSplatI, groupState.sumJac)

        # keep track of energy in this iteration
        if isReporter and cf.io.plotEvery > 0 and ((
            (it + 1) % cf.io.plotEvery == 0) or (it == cf.optim.Niter - 1)):
            HGMPlots(cf,
                     groupState,
                     tdiscGroup,
                     residualState,
                     tdiscResidual,
                     indx_last_individual,
                     writeOutput=True)

        if isReporter:
            (VEnergy, IEnergy, SEnergy) = groupState.EnergyHistory[-1]
            print datetime.datetime.now().time(
            ), " Iter", it, "of", cf.optim.Niter, ":", VEnergy + IEnergy + SEnergy, '(Total) = ', VEnergy, '(Vector) + ', IEnergy, '(Intercept) + ', SEnergy, '(Slope)'

    # write output images and fields
    HGMWriteOutput(cf, groupState, tdiscGroup, isReporter)
Example #8
0
def predict_image(args):
    if (args.use_CPU_for_shooting):
        mType = ca.MEM_HOST
    else:
        mType = ca.MEM_DEVICE

    # load the prediction network
    predict_network_config = torch.load(args.prediction_parameter)
    prediction_net = create_net(args, predict_network_config)

    batch_size = args.batch_size
    patch_size = predict_network_config['patch_size']
    input_batch = torch.zeros(batch_size, 2, patch_size, patch_size,
                              patch_size).cuda()

    # start prediction
    for i in range(0, len(args.moving_image)):
        common.Mkdir_p(os.path.dirname(args.output_prefix[i]))
        if (args.affine_align):
            # Perform affine registration to both moving and target image to the ICBM152 atlas space.
            # Registration is done using Niftireg.
            call([
                "reg_aladin", "-noSym", "-speeeeed", "-ref", args.atlas,
                "-flo", args.moving_image[i], "-res",
                args.output_prefix[i] + "moving_affine.nii", "-aff",
                args.output_prefix[i] + 'moving_affine_transform.txt'
            ])

            call([
                "reg_aladin", "-noSym", "-speeeeed", "-ref", args.atlas,
                "-flo", args.target_image[i], "-res",
                args.output_prefix[i] + "target_affine.nii", "-aff",
                args.output_prefix[i] + 'target_affine_transform.txt'
            ])

            moving_image = common.LoadITKImage(
                args.output_prefix[i] + "moving_affine.nii", mType)
            target_image = common.LoadITKImage(
                args.output_prefix[i] + "target_affine.nii", mType)
        else:
            moving_image = common.LoadITKImage(args.moving_image[i], mType)
            target_image = common.LoadITKImage(args.target_image[i], mType)

        #preprocessing of the image
        moving_image_np = preprocess_image(moving_image, args.histeq)
        target_image_np = preprocess_image(target_image, args.histeq)

        grid = moving_image.grid()
        moving_image_processed = common.ImFromNPArr(moving_image_np, mType)
        target_image_processed = common.ImFromNPArr(target_image_np, mType)
        moving_image.setGrid(grid)
        target_image.setGrid(grid)

        predict_transform_space = False
        if 'matlab_t7' in predict_network_config:
            predict_transform_space = True
        # run actual prediction
        prediction_result = util.predict_momentum(moving_image_np,
                                                  target_image_np, input_batch,
                                                  batch_size, patch_size,
                                                  prediction_net,
                                                  predict_transform_space)

        m0 = prediction_result['image_space']
        m0_reg = common.FieldFromNPArr(prediction_result['image_space'], mType)
        registration_result = registration_methods.geodesic_shooting(
            moving_image_processed, target_image_processed, m0_reg,
            args.shoot_steps, mType, predict_network_config)
        phi = common.AsNPCopy(registration_result['phiinv'])
        phi_square = np.power(phi, 2)

        for sample_iter in range(1, args.samples):
            print(sample_iter)
            prediction_result = util.predict_momentum(
                moving_image_np, target_image_np, input_batch, batch_size,
                patch_size, prediction_net, predict_transform_space)
            m0 += prediction_result['image_space']
            m0_reg = common.FieldFromNPArr(prediction_result['image_space'],
                                           mType)
            registration_result = registration_methods.geodesic_shooting(
                moving_image_processed, target_image_processed, m0_reg,
                args.shoot_steps, mType, predict_network_config)
            phi += common.AsNPCopy(registration_result['phiinv'])
            phi_square += np.power(
                common.AsNPCopy(registration_result['phiinv']), 2)

        m0_mean = np.divide(m0, args.samples)
        m0_reg = common.FieldFromNPArr(m0_mean, mType)
        registration_result = registration_methods.geodesic_shooting(
            moving_image_processed, target_image_processed, m0_reg,
            args.shoot_steps, mType, predict_network_config)
        phi_mean = registration_result['phiinv']
        phi_var = np.divide(phi_square, args.samples) - np.power(
            np.divide(phi, args.samples), 2)

        #save result
        common.SaveITKImage(registration_result['I1'],
                            args.output_prefix[i] + "I1.mhd")
        common.SaveITKField(phi_mean,
                            args.output_prefix[i] + "phiinv_mean.mhd")
        common.SaveITKField(common.FieldFromNPArr(phi_var, mType),
                            args.output_prefix[i] + "phiinv_var.mhd")
def main():
    # Extract the Monkey number and section number from the command line
    global frgNum
    global secOb

    mkyNum = sys.argv[1]
    secNum = sys.argv[2]
    frgNum = int(sys.argv[3])
    write = True

    # if not os.path.exists(os.path.expanduser('~/korenbergNAS/3D_database/Working/configuration_files/SidescapeRelateBlockface/M{0}/section_{1}/include_configFile.yaml'.format(mkyNum,secNum))):
    #     cf = initial(secNum, mkyNum)

    try:
        secOb = Config.Load(
            secSpec,
            pth.expanduser(
                '~/korenbergNAS/3D_database/Working/configuration_files/SidescapeRelateBlockface/M{0}/section_{1}/include_configFile.yaml'
                .format(mkyNum, secNum)))
    except IOError as e:
        try:
            temp = Config.LoadYAMLDict(pth.expanduser(
                '~/korenbergNAS/3D_database/Working/configuration_files/SidescapeRelateBlockface/M{0}/section_{1}/include_configFile.yaml'
                .format(mkyNum, secNum)),
                                       include=False)
            secOb = Config.MkConfig(temp, secSpec)
        except IOError:
            print 'It appears there is no configuration file for this section. Please initialize one and restart.'
            sys.exit()
        if frgNum == int(secOb.yamlList[frgNum][-6]):
            Fragmenter()
            try:
                secOb = Config.Load(
                    secSpec,
                    pth.expanduser(
                        '~/korenbergNAS/3D_database/Working/configuration_files/SidescapeRelateBlockface/M{0}/section_{1}/include_configFile.yaml'
                        .format(mkyNum, secNum)))
            except IOError:
                print 'It appeas that the include yaml file list does not match your fragmentation number. Please check them and restart.'
                sys.exit()

    if not pth.exists(
            pth.expanduser(secOb.ssiOutPath + 'frag{0}'.format(frgNum))):
        common.Mkdir_p(
            pth.expanduser(secOb.ssiOutPath + 'frag{0}'.format(frgNum)))
    if not pth.exists(
            pth.expanduser(secOb.bfiOutPath + 'frag{0}'.format(frgNum))):
        common.Mkdir_p(
            pth.expanduser(secOb.bfiOutPath + 'frag{0}'.format(frgNum)))
    if not pth.exists(
            pth.expanduser(secOb.ssiSrcPath + 'frag{0}'.format(frgNum))):
        os.mkdir(pth.expanduser(secOb.ssiSrcPath + 'frag{0}'.format(frgNum)))
    if not pth.exists(
            pth.expanduser(secOb.bfiSrcPath + 'frag{0}'.format(frgNum))):
        os.mkdir(pth.expanduser(secOb.bfiSrcPath + 'frag{0}'.format(frgNum)))

    frgOb = Config.MkConfig(secOb.yamlList[frgNum], frgSpec)
    ssiSrc, bfiSrc, ssiMsk, bfiMsk = Loader(frgOb, ca.MEM_HOST)

    #Extract the saturation Image from the color iamge
    bfiHsv = common.FieldFromNPArr(
        matplotlib.colors.rgb_to_hsv(
            np.rollaxis(np.array(np.squeeze(bfiSrc.asnp())), 0, 3)),
        ca.MEM_HOST)
    bfiHsv.setGrid(bfiSrc.grid())
    bfiSat = ca.Image3D(bfiSrc.grid(), bfiHsv.memType())
    ca.Copy(bfiSat, bfiHsv, 1)
    #Histogram equalize, normalize and mask the blockface saturation image
    bfiSat = cb.HistogramEqualize(bfiSat, 256)
    bfiSat.setGrid(bfiSrc.grid())
    bfiSat *= -1
    bfiSat -= ca.Min(bfiSat)
    bfiSat /= ca.Max(bfiSat)
    bfiSat *= bfiMsk
    bfiSat.setGrid(bfiSrc.grid())

    #Write out the blockface region after adjusting the colors with a format that supports header information
    if write:
        common.SaveITKImage(
            bfiSat,
            pth.expanduser(secOb.bfiSrcPath +
                           'frag{0}/M{1}_01_bfi_section_{2}_frag{0}_sat.nrrd'.
                           format(frgNum, secOb.mkyNum, secOb.secNum)))

    #Set the sidescape grid relative to that of the blockface
    ssiSrc.setGrid(ConvertGrid(ssiSrc.grid(), bfiSat.grid()))
    ssiMsk.setGrid(ConvertGrid(ssiMsk.grid(), bfiSat.grid()))
    ssiSrc *= ssiMsk

    #Write out the sidescape masked image in a format that stores the header information
    if write:
        common.SaveITKImage(
            ssiSrc,
            pth.expanduser(secOb.ssiSrcPath +
                           'frag{0}/M{1}_01_ssi_section_{2}_frag{0}.nrrd'.
                           format(frgNum, secOb.mkyNum, secOb.secNum)))

    #Update the image parameters of the sidescape image for future use
    frgOb.imSize = ssiSrc.size().tolist()
    frgOb.imOrig = ssiSrc.origin().tolist()
    frgOb.imSpac = ssiSrc.spacing().tolist()
    updateFragOb(frgOb)

    #Find the affine transform between the two fragments
    bfiAff, ssiAff, aff = Affine(bfiSat, ssiSrc, frgOb)
    updateFragOb(frgOb)

    #Write out the affine transformed images in a format that stores header information
    if write:
        common.SaveITKImage(
            bfiAff,
            pth.expanduser(
                secOb.bfiOutPath +
                'frag{0}/M{1}_01_bfi_section_{2}_frag{0}_aff_ssi.nrrd'.format(
                    frgNum, secOb.mkyNum, secOb.secNum)))
        common.SaveITKImage(
            ssiAff,
            pth.expanduser(
                secOb.ssiOutPath +
                'frag{0}/M{1}_01_ssi_section_{2}_frag{0}_aff_bfi.nrrd'.format(
                    frgNum, secOb.mkyNum, secOb.secNum)))

    bfiVe = bfiAff.copy()
    ssiVe = ssiSrc.copy()
    cc.VarianceEqualize_I(bfiVe, sigma=frgOb.sigVarBfi, eps=frgOb.epsVar)
    cc.VarianceEqualize_I(ssiVe, sigma=frgOb.sigVarSsi, eps=frgOb.epsVar)

    #As of right now, the largest pre-computed FFT table is 2048, so resample onto that grid for registration
    regGrd = ConvertGrid(
        cc.MakeGrid(ca.Vec3Di(2048, 2048, 1), ca.Vec3Df(1, 1, 1),
                    ca.Vec3Df(0, 0, 0)), ssiSrc.grid())
    ssiReg = ca.Image3D(regGrd, ca.MEM_HOST)
    bfiReg = ca.Image3D(regGrd, ca.MEM_HOST)
    cc.ResampleWorld(ssiReg, ssiVe)
    cc.ResampleWorld(bfiReg, bfiVe)

    #Create the default configuration object for IDiff Matching and then set some parameters
    idCf = Config.SpecToConfig(IDiff.Matching.MatchingConfigSpec)
    idCf.compute.useCUDA = True
    idCf.io.outputPrefix = '/home/sci/blakez/IDtest/'

    #Run the registration
    ssiDef, phi = DefReg(ssiReg, bfiReg, frgOb, ca.MEM_DEVICE, idCf)

    #Turn the deformation into a displacement field so it can be applied to the large tif with C++ code
    affV = phi.copy()
    cc.ApplyAffineReal(affV, phi, np.linalg.inv(frgOb.affine))
    ca.HtoV_I(affV)

    #Apply the found deformation to the input ssi
    ssiSrc.toType(ca.MEM_DEVICE)
    cc.HtoReal(phi)
    affPhi = phi.copy()
    ssiBfi = ssiSrc.copy()
    upPhi = ca.Field3D(ssiSrc.grid(), phi.memType())

    cc.ApplyAffineReal(affPhi, phi, np.linalg.inv(frgOb.affine))
    cc.ResampleWorld(upPhi, affPhi, bg=2)
    cc.ApplyHReal(ssiBfi, ssiSrc, upPhi)

    # ssiPhi = ca.Image3D(ssiSrc.grid(), phi.memType())
    # upPhi = ca.Field3D(ssiSrc.grid(), phi.memType())
    # cc.ResampleWorld(upPhi, phi, bg=2)
    # cc.ApplyHReal(ssiPhi, ssiSrc, upPhi)
    # ssiBfi = ssiSrc.copy()
    # cc.ApplyAffineReal(ssiBfi, ssiPhi, np.linalg.inv(frgOb.affine))

    # #Apply affine to the deformation
    # affPhi = phi.copy()
    # cc.ApplyAffineReal(affPhi, phi, np.linalg.inv(frgOb.affine))

    if write:
        common.SaveITKImage(
            ssiBfi,
            pth.expanduser(
                secOb.ssiOutPath +
                'frag{0}/M{1}_01_ssi_section_{2}_frag{0}_def_bfi.nrrd'.format(
                    frgNum, secOb.mkyNum, secOb.secNum)))
        cc.WriteMHA(
            affPhi,
            pth.expanduser(
                secOb.ssiOutPath +
                'frag{0}/M{1}_01_ssi_section_{2}_frag{0}_to_bfi_real.mha'.
                format(frgNum, secOb.mkyNum, secOb.secNum)))
        cc.WriteMHA(
            affV,
            pth.expanduser(
                secOb.ssiOutPath +
                'frag{0}/M{1}_01_ssi_section_{2}_frag{0}_to_bfi_disp.mha'.
                format(frgNum, secOb.mkyNum, secOb.secNum)))

    #Create the list of names that the deformation should be applied to
    # nameList = ['M15_01_0956_SideLight_DimLED_10x_ORG.tif',
    #             'M15_01_0956_TyrosineHydroxylase_Ben_10x_Stitching_c1_ORG.tif',
    #             'M15_01_0956_TyrosineHydroxylase_Ben_10x_Stitching_c2_ORG.tif',
    #             'M15_01_0956_TyrosineHydroxylase_Ben_10x_Stitching_c3_ORG.tif']

    # appLarge(nameList, affPhi)

    common.DebugHere()
Example #10
0
def BuildGeoReg(cf):
    """Worker for running geodesic estimation on a subset of individuals
    """
    #common.DebugHere()
    localRank = Compute.GetMPIInfo()['local_rank']
    rank = Compute.GetMPIInfo()['rank']

    # prepare output directory
    common.Mkdir_p(os.path.dirname(cf.io.outputPrefix))

    # just one reporter process on each node
    isReporter = rank == 0

    # load filenames and times for all subjects
    (subjectsIds, subjectsImagePaths,
     subjectsTimes) = GeoRegLoadSubjectsDetails(cf.study.subjectFile)
    cf.study.numSubjects = len(subjectsIds)
    if isReporter:
        # Output loaded config
        if cf.io.outputPrefix is not None:
            cfstr = Config.ConfigToYAML(GeoRegConfigSpec, cf)
            with open(cf.io.outputPrefix + "parsedconfig.yaml", "w") as f:
                f.write(cfstr)

    # if MPI check if processes are greater than number of subjects. it is okay if there are more subjects than processes
    if cf.compute.useMPI and (len(subjectsIds) < cf.compute.numProcesses):
        raise Exception("Please don't use more processes " +
                        "than total number of individuals")

    nodeSubjectsIds = subjectsIds[rank::cf.compute.numProcesses]
    nodeSubjectsImagePaths = subjectsImagePaths[rank::cf.compute.numProcesses]
    nodeSubjectsTimes = subjectsTimes[rank::cf.compute.numProcesses]

    numLocalSubjects = len(nodeSubjectsImagePaths)
    if cf.study.initializationsFile is not None:
        (subjectsInitialImages,
         subjectsInitialMomenta) = GeoRegLoadSubjectsInitializations(
             cf.study.initializationsFile)
        nodeSubjectsInitialImages = subjectsInitialImages[rank::cf.compute.
                                                          numProcesses]
        nodeSubjectsInitialMomenta = subjectsInitialMomenta[rank::cf.compute.
                                                            numProcesses]

    print 'rank:', rank, ', localRank:', localRank, ', numberSubjects/TotalSubjects:', len(
        nodeSubjectsImagePaths
    ), '/', cf.study.numSubjects, ', nodeSubjectsImagePaths:', nodeSubjectsImagePaths, ', nodeSubjectsTimes:', nodeSubjectsTimes

    # mem type is determined by whether or not we're using CUDA
    mType = ca.MEM_DEVICE if cf.compute.useCUDA else ca.MEM_HOST

    # setting gpuid should be handled in gpu
    # if using GPU  set device based on local rank
    #if cf.compute.useCUDA:
    #    ca.SetCUDADevice(localRank)

    # get image size information
    dummyImToGetGridInfo = common.LoadITKImage(nodeSubjectsImagePaths[0][0],
                                               mType)
    imGrid = dummyImToGetGridInfo.grid()
    if cf.study.setUnitSpacing:
        imGrid.setSpacing(ca.Vec3Df(1.0, 1.0, 1.0))
    if cf.study.setZeroOrigin:
        imGrid.setOrigin(ca.Vec3Df(0, 0, 0))
    #del dummyImToGetGridInfo;

    # start up the memory manager for scratch variables
    ca.ThreadMemoryManager.init(imGrid, mType, 0)

    # allocate memory
    p = GeoRegVariables(imGrid,
                        mType,
                        cf.vectormomentum.diffOpParams[0],
                        cf.vectormomentum.diffOpParams[1],
                        cf.vectormomentum.diffOpParams[2],
                        cf.optim.NIterForInverse,
                        cf.vectormomentum.sigma,
                        cf.optim.stepSize,
                        integMethod=cf.optim.integMethod)
    # for each individual run geodesic regression for each subject
    for i in range(numLocalSubjects):

        # initializations for this subject
        if cf.study.initializationsFile is not None:
            # assuming the initializations are already preprocessed, in terms of intensities, origin and voxel scalings.
            p.I0 = common.LoadITKImage(nodeSubjectsInitialImages[i], mType)
            p.m0 = common.LoadITKField(nodeSubjectsInitialMomenta[i], mType)
        else:
            ca.SetMem(p.m0, 0.0)
            ca.SetMem(p.I0, 0.0)

        # allocate memory specific to this subject in steps a, b and c
        # a. create time array with checkpointing info for regression geodesic, allocate checkpoint memory
        (t, msmtinds, cpinds) = GeoRegSetUpTimeArray(cf.optim.nTimeSteps,
                                                     nodeSubjectsTimes[i],
                                                     0.001)
        cpstates = [(ca.Field3D(imGrid, mType), ca.Field3D(imGrid, mType))
                    for idx in cpinds]
        # b. allocate gradAtMeasurements of the length of msmtindex for storing residuals
        gradAtMsmts = [ca.Image3D(imGrid, mType) for idx in msmtinds]

        # c. load timepoint images for this subject
        Imsmts = [
            common.LoadITKImage(f, mType) if isinstance(f, str) else f
            for f in nodeSubjectsImagePaths[i]
        ]
        # reset stepsize if adaptive stepsize changed it inside
        p.stepSize = cf.optim.stepSize
        # preprocessimages
        GeoRegPreprocessInput(nodeSubjectsIds[i], cf, p, t, Imsmts, cpinds,
                              cpstates, msmtinds, gradAtMsmts)

        # run regression for this subject
        # REMEMBER
        # msmtinds index into cpinds
        # gradAtMsmts is parallel to msmtinds
        # cpinds index into t
        EnergyHistory = RunGeoReg(nodeSubjectsIds[i], cf, p, t, Imsmts, cpinds,
                                  cpstates, msmtinds, gradAtMsmts)

        # write output images and fields for this subject
        # TODO: BEWARE There are hardcoded numbers inside preprocessing code specific for ADNI/OASIS brain data.
        GeoRegWriteOuput(nodeSubjectsIds[i], cf, p, t, Imsmts, cpinds,
                         cpstates, msmtinds, gradAtMsmts, EnergyHistory)

        # clean up memory specific to this subject
        del t, Imsmts, cpinds, cpstates, msmtinds, gradAtMsmts