def regAndResample(self, inputFH, i, filesToAvg, nlinFH): """For last generation, override default output names. Note that the defaultDir specified in the mincANTS call is ignored in this instance. """ if i == (self.generations - 1): registerOutput, resampleOutput = finalGenerationFileNames(inputFH) else: registerOutput = None resampleOutput = None ma = mincANTS(inputFH, self.target, output=registerOutput, defaultDir="tmp", blur=self.blurs[i], gradient=self.gradient[i], similarity_metric=self.similarityMetric[i], weight=self.weight[i], iterations=self.iterations[i], radius_or_histo=self.radiusHisto[i], transformation_model=self.transformationModel[i], regularization=self.regularization[i], useMask=self.useMask[i]) self.p.addStage(ma) rs = mincresample(inputFH, self.target, likeFile=self.target, output=resampleOutput, defaultDir="tmp", argArray=["-sinc"]) #Do we need to resample any masks? filesToAvg.append(rs.outputFiles[0]) self.p.addStage(rs) if i == (self.generations - 1): inputFH.setLastBasevol(newBaseVol=rs.outputFiles[0])
def regAndResample(self, inputFH, i, filesToAvg, nlinFH): """For last generation, override default output names. Note that the defaultDir specified in the minctracc call is ignored in this instance. """ if i == (self.generations - 1): if not self.useGradient[i]: firstRegOutput, resampleOutput = finalGenerationFileNames( inputFH) else: firstRegOutput = None registerOutput, resampleOutput = finalGenerationFileNames( inputFH) else: firstRegOutput = None registerOutput = None resampleOutput = None """If self.useGradient is True, then we call minctracc twice: once with a gradient and once without. Otherwise, we call only once without a gradient. """ mta = minctracc(inputFH, self.target, defaultDir="tmp", output=firstRegOutput, blur=self.blurs[i], gradient=False, iterations=self.iterations[i], step=self.stepSize[i], weight=0.8, stiffness=0.98, similarity=0.8, w_translations=self.w_translations[i], simplex=self.simplex[i]) self.p.addStage(mta) if self.useGradient[i]: mtb = minctracc(inputFH, self.target, output=registerOutput, defaultDir="tmp", blur=self.blurs[i], gradient=True, iterations=self.iterations[i], step=self.stepSize[i], weight=0.8, stiffness=0.98, similarity=0.8, simplex=self.simplex[i]) self.p.addStage(mtb) """Need to set last xfm so that next generation will use it as the input transform""" inputFH.setLastXfm(nlinFH, mtb.outputFiles[0]) rs = mincresample(inputFH, self.target, likeFile=self.target, output=resampleOutput, defaultDir="tmp", argArray=["-sinc"]) #Do we need to resample any masks? filesToAvg.append(rs.outputFiles[0]) self.p.addStage(rs) if i == (self.generations - 1): inputFH.setLastBasevol(newBaseVol=rs.outputFiles[0])
def statsAndConcat(self, s, i, count, beforeAvg=True): """Construct array to common space for this timepoint. This builds upon arrays from previous calls.""" if beforeAvg: xfm = s[i].getLastXfm(s[i+1]) else: xfm = s[i].getLastXfm(s[i-1]) """Set this transform as last xfm from input to nlin and calculate nlin to s[i] stats""" if self.nlinFH: self.xfmToCommon.insert(0, xfm) """ Concat transforms to get xfmToCommon and calculate statistics Note that inverted transform, which is what we want, is calculated in the statistics module. """ xtc = createBaseName(s[i].transformsDir, s[i].basename + "_to_" + self.commonName + ".xfm") xc = ma.xfmConcat(self.xfmToCommon, xtc, fh.logFromFile(s[i].logDir, xtc)) self.p.addStage(xc) # here in order to visually inspect the alignment with the common # time point, we should resample this subject: inputResampledToCommon = createBaseName(s[i].resampledDir, s[i].basename + "_to_" + self.commonName + ".mnc") logToCommon = fh.logFromFile(s[i].logDir, inputResampledToCommon) resampleCmd = ma.mincresample(s[i], self.nlinFH, likeFile=self.nlinFH, transform=xtc, output=inputResampledToCommon, logFile=logToCommon, argArray=["-sinc"]) self.p.addStage(resampleCmd) s[i].addAndSetXfmToUse(self.nlinFH, xtc) self.statsCalculation(s[i], self.nlinFH, xfm=None, useChainStats=False) else: xtc=None """Calculate i to i+1 stats for all but final timePoint""" if count - i > 1: self.statsCalculation(s[i], s[i+1], xfm=xtc, useChainStats=True)
def resampleToCommon(xfm, FH, statsGroup, statsKernels, nlinFH): blurs = [] if isinstance(statsKernels, list): blurs = statsKernels elif isinstance(statsKernels, str): for i in statsKernels.split(","): blurs.append(float(i)) else: print("Improper type of blurring kernels specified for stats calculation: " + str(statsKernels)) sys.exit() pipeline = Pipeline() outputDirectory = FH.statsDir filesToResample = [] for b in blurs: filesToResample.append(statsGroup.relativeJacobians[b]) if statsGroup.absoluteJacobians: filesToResample.append(statsGroup.absoluteJacobians[b]) for f in filesToResample: outputBase = removeBaseAndExtension(f).split(".mnc")[0] outputFile = createBaseName(outputDirectory, outputBase + "_common" + ".mnc") logFile = fh.logFromFile(FH.logDir, outputFile) targetAndLike=nlinFH.getLastBasevol() res = ma.mincresample(f, targetAndLike, likeFile=targetAndLike, transform=xfm, output=outputFile, logFile=logFile, argArray=["-sinc"]) pipeline.addStage(res) return pipeline
def resampleToCommon(xfm, FH, statsGroup, statsKernels, nlinFH): blurs = [] if isinstance(statsKernels, list): blurs = statsKernels elif isinstance(statsKernels, str): for i in statsKernels.split(","): blurs.append(float(i)) else: print "Improper type of blurring kernels specified for stats calculation: " + str(statsKernels) sys.exit() pipeline = Pipeline() outputDirectory = FH.statsDir filesToResample = [] for b in blurs: filesToResample.append(statsGroup.relativeJacobians[b]) if statsGroup.absoluteJacobians: filesToResample.append(statsGroup.absoluteJacobians[b]) for f in filesToResample: outputBase = fh.removeBaseAndExtension(f).split(".mnc")[0] outputFile = fh.createBaseName(outputDirectory, outputBase + "_common" + ".mnc") logFile = fh.logFromFile(FH.logDir, outputFile) targetAndLike=nlinFH.getLastBasevol() res = ma.mincresample(f, targetAndLike, likeFile=targetAndLike, transform=xfm, output=outputFile, logFile=logFile, argArray=["-sinc"]) pipeline.addStage(res) return pipeline
def regAndResample(self, inputFH, i, filesToAvg, nlinFH): """For last generation, override default output names. Note that the defaultDir specified in the mincANTS call is ignored in this instance. """ if i == (self.generations -1): registerOutput, resampleOutput = finalGenerationFileNames(inputFH) else: registerOutput = None resampleOutput = None ma = mincANTS(inputFH, self.target, output=registerOutput, defaultDir="tmp", blur=self.blurs[i], gradient=self.gradient[i], similarity_metric=self.similarityMetric[i], weight=self.weight[i], iterations=self.iterations[i], radius_or_histo=self.radiusHisto[i], transformation_model = self.transformationModel[i], regularization=self.regularization[i], useMask=self.useMask[i]) self.p.addStage(ma) rs = mincresample(inputFH, self.target, likeFile=self.target, output=resampleOutput, defaultDir="tmp", argArray=["-sinc"]) #Do we need to resample any masks? filesToAvg.append(rs.outputFiles[0]) self.p.addStage(rs) if i == (self.generations -1): inputFH.setLastBasevol(newBaseVol=rs.outputFiles[0])
def __init__(self, inputPipeFH, templatePipeFH, name="initial", createMask=False): self.p = Pipeline() self.name = name if createMask: resampleDefault = "tmp" labelsDefault = "tmp" else: resampleDefault = "resampled" labelsDefault = "labels" # Resample all inputLabels inputLabelArray = templatePipeFH.returnLabels(True) if len(inputLabelArray) > 0: """ for the initial registration, resulting labels should be added to inputLabels array for subsequent pairwise registration otherwise labels should be added to labels array for voting """ if self.name == "initial": addOutputToInputLabels = True else: addOutputToInputLabels = False for i in range(len(inputLabelArray)): """Note: templatePipeFH and inputPipeFH have the reverse order from how they are passed into this function. This is intentional because the mincresample classes use the first argument as the one from which to get the file to be resampled. Here, either the mask or labels to be resampled come from the template.""" if createMask: resampleStage = ma.mincresampleMask( templatePipeFH, inputPipeFH, defaultDir=labelsDefault, likeFile=inputPipeFH, argArray=["-invert"], outputLocation=inputPipeFH, labelIndex=i, setInputLabels=addOutputToInputLabels) else: resampleStage = ma.mincresampleLabels( templatePipeFH, inputPipeFH, defaultDir=labelsDefault, likeFile=inputPipeFH, argArray=["-invert"], outputLocation=inputPipeFH, labelIndex=i, setInputLabels=addOutputToInputLabels) self.p.addStage(resampleStage) # resample files resampleStage = ma.mincresample(templatePipeFH, inputPipeFH, defaultDir=resampleDefault, likeFile=inputPipeFH, argArray=["-invert"], outputLocation=inputPipeFH) self.p.addStage(resampleStage)
def buildPipeline(self): # Run lsq12 registration prior to non-linear self.lsq12Params = mp.setLSQ12MinctraccParams( self.fileRes, subject_matter=self.subject_matter, reg_protocol=self.lsq12_protocol) lsq12reg = lsq12.LSQ12(self.inputFH, self.targetFH, blurs=self.lsq12Params.blurs, step=self.lsq12Params.stepSize, gradient=self.lsq12Params.useGradient, simplex=self.lsq12Params.simplex, w_translations=self.lsq12Params.w_translations, defaultDir=self.defaultDir) self.p.addPipeline(lsq12reg.p) #Resample using final LSQ12 transform and reset last base volume. res = ma.mincresample(self.inputFH, self.targetFH, likeFile=self.targetFH, argArray=["-sinc"]) self.p.addStage(res) self.inputFH.setLastBasevol(res.outputFiles[0]) lsq12xfm = self.inputFH.getLastXfm(self.targetFH) #Get registration parameters from nlin protocol, blur and register #Assume a SINGLE generation here. self.nlinParams = mp.setOneGenMincANTSParams( self.fileRes, reg_protocol=self.nlin_protocol) for b in self.nlinParams.blurs: for j in b: #Note that blurs for ANTS params in an array of arrays. if j != -1: self.p.addStage(ma.blur(self.targetFH, j, gradient=True)) self.p.addStage(ma.blur(self.inputFH, j, gradient=True)) sp = ma.mincANTS( self.inputFH, self.targetFH, defaultDir=self.defaultDir, blur=self.nlinParams.blurs[0], gradient=self.nlinParams.gradient[0], similarity_metric=self.nlinParams.similarityMetric[0], weight=self.nlinParams.weight[0], iterations=self.nlinParams.iterations[0], radius_or_histo=self.nlinParams.radiusHisto[0], transformation_model=self.nlinParams.transformationModel[0], regularization=self.nlinParams.regularization[0], useMask=self.nlinParams.useMask[0]) self.p.addStage(sp) nlinXfm = sp.outputFiles[0] #Reset last base volume to original input for future registrations. self.inputFH.setLastBasevol(setToOriginalInput=True) #Concatenate transforms to get final lsq12 + nlin. Register volume handles naming and setting of lastXfm output = self.inputFH.registerVolume(self.targetFH, "transforms") xc = ma.xfmConcat([lsq12xfm, nlinXfm], output, fh.logFromFile(self.inputFH.logDir, output)) self.p.addStage(xc)
def __init__(self, inputPipeFH, templatePipeFH, name="initial", createMask=False): self.p = Pipeline() self.name = name if createMask: resampleDefault = "tmp" labelsDefault = "tmp" else: resampleDefault = "resampled" labelsDefault = "labels" # Resample all inputLabels inputLabelArray = templatePipeFH.returnLabels(True) if len(inputLabelArray) > 0: """ for the initial registration, resulting labels should be added to inputLabels array for subsequent pairwise registration otherwise labels should be added to labels array for voting """ if self.name == "initial": addOutputToInputLabels = True else: addOutputToInputLabels = False for i in range(len(inputLabelArray)): """Note: templatePipeFH and inputPipeFH have the reverse order from how they are passed into this function. This is intentional because the mincresample classes use the first argument as the one from which to get the file to be resampled. Here, either the mask or labels to be resampled come from the template.""" if createMask: resampleStage = ma.mincresampleMask(templatePipeFH, inputPipeFH, defaultDir=labelsDefault, likeFile=inputPipeFH, argArray=["-invert"], outputLocation=inputPipeFH, labelIndex=i, setInputLabels=addOutputToInputLabels) else: resampleStage = ma.mincresampleLabels(templatePipeFH, inputPipeFH, defaultDir=labelsDefault, likeFile=inputPipeFH, argArray=["-invert"], outputLocation=inputPipeFH, labelIndex=i, setInputLabels=addOutputToInputLabels) self.p.addStage(resampleStage) # resample files resampleStage = ma.mincresample(templatePipeFH, inputPipeFH, defaultDir=resampleDefault, likeFile=inputPipeFH, argArray=["-invert"], outputLocation=inputPipeFH) self.p.addStage(resampleStage)
def regAndResample(self, inputFH, i, filesToAvg, nlinFH): """For last generation, override default output names. Note that the defaultDir specified in the minctracc call is ignored in this instance. """ if i == (self.generations -1): if not self.useGradient[i]: firstRegOutput, resampleOutput = finalGenerationFileNames(inputFH) else: firstRegOutput = None registerOutput, resampleOutput = finalGenerationFileNames(inputFH) else: firstRegOutput = None registerOutput = None resampleOutput = None """If self.useGradient is True, then we call minctracc twice: once with a gradient and once without. Otherwise, we call only once without a gradient. """ mta = minctracc(inputFH, self.target, defaultDir="tmp", output=firstRegOutput, blur=self.blurs[i], gradient=False, iterations=self.iterations[i], step=self.stepSize[i], weight=self.weight[i], stiffness=self.stiffness[i], similarity=self.similarity[i], w_translations = self.w_translations[i], simplex=self.simplex[i]) self.p.addStage(mta) if self.useGradient[i]: mtb = minctracc(inputFH, self.target, output=registerOutput, defaultDir="tmp", blur=self.blurs[i], gradient=True, iterations=self.iterations[i], step=self.stepSize[i], weight=self.weight[i], stiffness=self.stiffness[i], similarity=self.similarity[i], simplex=self.simplex[i]) self.p.addStage(mtb) """Need to set last xfm so that next generation will use it as the input transform""" inputFH.setLastXfm(nlinFH, mtb.outputFiles[0]) rs = mincresample(inputFH, self.target, likeFile=self.target, output=resampleOutput, defaultDir="tmp", argArray=["-sinc"]) #Do we need to resample any masks? filesToAvg.append(rs.outputFiles[0]) self.p.addStage(rs) if i == (self.generations -1): inputFH.setLastBasevol(newBaseVol=rs.outputFiles[0])
def iterate(self): if not self.maxPairs: xfmsToAvg = {} lsq12ResampledFiles = {} for inputFH in self.inputs: """Create an array of xfms, to compute an average lsq12 xfm for each input""" xfmsToAvg[inputFH] = [] for targetFH in self.inputs: if inputFH != targetFH: lsq12 = LSQ12(inputFH, targetFH, self.blurs, self.stepSize, self.useGradient, self.simplex) self.p.addPipeline(lsq12.p) xfmsToAvg[inputFH].append(inputFH.getLastXfm(targetFH)) """Create average xfm for inputFH using xfmsToAvg array""" cmd = ["xfmavg"] for i in range(len(xfmsToAvg[inputFH])): cmd.append(InputFile(xfmsToAvg[inputFH][i])) avgXfmOutput = createBaseName(inputFH.transformsDir, inputFH.basename + "-avg-lsq12.xfm") cmd.append(OutputFile(avgXfmOutput)) xfmavg = CmdStage(cmd) xfmavg.setLogFile(LogFile(logFromFile(inputFH.logDir, avgXfmOutput))) self.p.addStage(xfmavg) self.lsq12AvgXfms[inputFH] = avgXfmOutput """ resample brain and add to array for mincAveraging""" if not self.likeFile: likeFile=inputFH else: likeFile=self.likeFile rslOutput = createBaseName(inputFH.resampledDir, inputFH.basename + "-resampled-lsq12.mnc") res = ma.mincresample(inputFH, inputFH, transform=avgXfmOutput, likeFile=likeFile, output=rslOutput, argArray=["-sinc"]) self.p.addStage(res) lsq12ResampledFiles[inputFH] = rslOutput """ After all registrations complete, setLastBasevol for each subject to be resampled file in lsq12 space. We can then call mincAverage on fileHandlers, as it will use the lastBasevol for each by default.""" for inputFH in self.inputs: inputFH.setLastBasevol(lsq12ResampledFiles[inputFH]) """ mincAverage all resampled brains and put in lsq12Directory""" self.lsq12Avg = abspath(self.lsq12Dir) + "/" + basename(self.lsq12Dir) + "-pairs.mnc" self.lsq12AvgFH = RegistrationPipeFH(self.lsq12Avg, basedir=self.lsq12Dir) avg = ma.mincAverage(self.inputs, self.lsq12AvgFH, output=self.lsq12Avg, defaultDir=self.lsq12Dir) self.p.addStage(avg) else: print "Registration using a specified number of max pairs not yet working. Check back soon!" sys.exit()
def buildPipeline(self): # Run lsq12 registration prior to non-linear self.lsq12Params = mp.setLSQ12MinctraccParams(self.fileRes, subject_matter=self.subject_matter, reg_protocol=self.lsq12_protocol) lsq12reg = lsq12.LSQ12(self.inputFH, self.targetFH, blurs=self.lsq12Params.blurs, step=self.lsq12Params.stepSize, gradient=self.lsq12Params.useGradient, simplex=self.lsq12Params.simplex, w_translations=self.lsq12Params.w_translations, defaultDir=self.defaultDir) self.p.addPipeline(lsq12reg.p) #Resample using final LSQ12 transform and reset last base volume. res = ma.mincresample(self.inputFH, self.targetFH, likeFile=self.targetFH, argArray=["-sinc"]) self.p.addStage(res) self.inputFH.setLastBasevol(res.outputFiles[0]) lsq12xfm = self.inputFH.getLastXfm(self.targetFH) #Get registration parameters from nlin protocol, blur and register #Assume a SINGLE generation here. self.nlinParams = mp.setOneGenMincANTSParams(self.fileRes, reg_protocol=self.nlin_protocol) for b in self.nlinParams.blurs: for j in b: #Note that blurs for ANTS params in an array of arrays. if j != -1: self.p.addStage(ma.blur(self.targetFH, j, gradient=True)) self.p.addStage(ma.blur(self.inputFH, j, gradient=True)) sp = ma.mincANTS(self.inputFH, self.targetFH, defaultDir=self.defaultDir, blur=self.nlinParams.blurs[0], gradient=self.nlinParams.gradient[0], similarity_metric=self.nlinParams.similarityMetric[0], weight=self.nlinParams.weight[0], iterations=self.nlinParams.iterations[0], radius_or_histo=self.nlinParams.radiusHisto[0], transformation_model=self.nlinParams.transformationModel[0], regularization=self.nlinParams.regularization[0], useMask=self.nlinParams.useMask[0]) self.p.addStage(sp) nlinXfm = sp.outputFiles[0] #Reset last base volume to original input for future registrations. self.inputFH.setLastBasevol(setToOriginalInput=True) #Concatenate transforms to get final lsq12 + nlin. Register volume handles naming and setting of lastXfm output = self.inputFH.registerVolume(self.targetFH, "transforms") xc = ma.xfmConcat([lsq12xfm, nlinXfm], output, fh.logFromFile(self.inputFH.logDir, output)) self.p.addStage(xc)
def run(self): """Directory handling etc as in MBM""" if not self.options.pipeline_name: pipeName = str(date.today()) + "_pipeline" else: pipeName = self.options.pipeline_name processedDirectory = fh.createSubDir(self.outputDir, pipeName + "_processed") """Check that correct registration method was specified""" if self.options.reg_method != "minctracc" and self.options.reg_method != "mincANTS": logger.error("Incorrect registration method specified: " + self.options.reg_method) sys.exit() """Create file handling classes for each image""" inputs = rf.initializeInputFiles(self.args, processedDirectory, self.options.mask_dir) """Put blurs into array""" blurs = [] for i in self.options.stats_kernels.split(","): blurs.append(float(i)) """Create file handler for nlin average from MBM""" if self.options.nlin_avg: nlinFH = rfh.RegistrationFHBase(abspath(self.options.nlin_avg), processedDirectory) else: nlinFH = None if self.options.mbm_dir and not isdir(abspath(self.options.mbm_dir)): logger.error("The --mbm-directory specified does not exist: " + abspath(self.options.mbm_dir)) sys.exit() """Get transforms from inputs to final nlin average and vice versa as well as lsq6 files""" if self.options.nlin_avg and self.options.mbm_dir: rf.getXfms(nlinFH, inputs, self.options.input_space, abspath(self.options.mbm_dir)) else: logger.info("MBM directory and nlin_average not specified.") logger.info( "Calculating pairwise nlin only without resampling to common space." ) """Create a dictionary of statistics. Each subject gets an array of statistics indexed by inputFile.""" subjectStats = {} """Register each image with every other image.""" for inputFH in inputs: subjectStats[inputFH] = {} for targetFH in inputs: if inputFH != targetFH: # MF TODO: Make generalization of registration parameters easier. if self.options.reg_method == "mincANTS": register = mm.LSQ12ANTSNlin(inputFH, targetFH) self.pipeline.addPipeline(register.p) elif self.options.reg_method == "minctracc": hm = mm.HierarchicalMinctracc(inputFH, targetFH) self.pipeline.addPipeline(hm.p) if nlinFH: resample = ma.mincresample(inputFH, targetFH, likeFile=nlinFH) else: resample = ma.mincresample(inputFH, targetFH, likeFile=inputFH) self.pipeline.addStage(resample) inputFH.setLastBasevol(resample.outputFiles[0]) """Calculate statistics""" stats = st.CalcChainStats(inputFH, targetFH, blurs) stats.calcFullDisplacement() stats.calcDetAndLogDet(useFullDisp=True) self.pipeline.addPipeline(stats.p) subjectStats[inputFH][targetFH] = stats.statsGroup """Resample to nlin space from previous build model run, if specified""" if self.options.nlin_avg and self.options.mbm_dir: xfmToNlin = inputFH.getLastXfm(nlinFH, groupIndex=0) res = mm.resampleToCommon( xfmToNlin, inputFH, subjectStats[inputFH][targetFH], blurs, nlinFH) self.pipeline.addPipeline(res) """Reset last base volume to original input before continuing to next pair in loop.""" inputFH.setLastBasevol(setToOriginalInput=True)
def iterate(self): if not self.maxPairs: xfmsToAvg = {} lsq12ResampledFiles = {} for inputFH in self.inputs: """Create an array of xfms, to compute an average lsq12 xfm for each input""" xfmsToAvg[inputFH] = [] for targetFH in self.inputs: if inputFH != targetFH: lsq12 = LSQ12(inputFH, targetFH, blurs=self.blurs, step=self.stepSize, gradient=self.useGradient, simplex=self.simplex, w_translations=self.w_translations) self.p.addPipeline(lsq12.p) xfmsToAvg[inputFH].append(inputFH.getLastXfm(targetFH)) """Create average xfm for inputFH using xfmsToAvg array""" cmd = ["xfmavg"] for i in range(len(xfmsToAvg[inputFH])): cmd.append(InputFile(xfmsToAvg[inputFH][i])) avgXfmOutput = createBaseName( inputFH.transformsDir, inputFH.basename + "-avg-lsq12.xfm") cmd.append(OutputFile(avgXfmOutput)) xfmavg = CmdStage(cmd) xfmavg.setLogFile( LogFile(logFromFile(inputFH.logDir, avgXfmOutput))) self.p.addStage(xfmavg) self.lsq12AvgXfms[inputFH] = avgXfmOutput """ resample brain and add to array for mincAveraging""" if not self.likeFile: likeFile = inputFH else: likeFile = self.likeFile rslOutput = createBaseName( inputFH.resampledDir, inputFH.basename + "-resampled-lsq12.mnc") res = ma.mincresample(inputFH, inputFH, transform=avgXfmOutput, likeFile=likeFile, output=rslOutput, argArray=["-sinc"]) self.p.addStage(res) lsq12ResampledFiles[inputFH] = rslOutput """ After all registrations complete, setLastBasevol for each subject to be resampled file in lsq12 space. We can then call mincAverage on fileHandlers, as it will use the lastBasevol for each by default.""" for inputFH in self.inputs: inputFH.setLastBasevol(lsq12ResampledFiles[inputFH]) """ mincAverage all resampled brains and put in lsq12Directory""" self.lsq12Avg = abspath(self.lsq12Dir) + "/" + basename( self.lsq12Dir) + "-pairs.mnc" self.lsq12AvgFH = RegistrationPipeFH(self.lsq12Avg, basedir=self.lsq12Dir) avg = ma.mincAverage(self.inputs, self.lsq12AvgFH, output=self.lsq12Avg, defaultDir=self.lsq12Dir) self.p.addStage(avg) else: print "Registration using a specified number of max pairs not yet working. Check back soon!" sys.exit()
def run(self): #Setup output directories for registration chain (_processed only) dirs = rf.setupDirectories(self.outputDir, self.options.pipeline_name, module="ALL") #Check that correct registration method was specified if self.options.reg_method != "minctracc" and self.options.reg_method != "mincANTS": logger.error("Incorrect registration method specified: " + self.options.reg_method) sys.exit() #Take average time point, subtract 1 for proper indexing avgTime = self.options.avg_time_point - 1 #Read in files from csv subjects = rf.setupSubjectHash(self.args[0], dirs, self.options.mask_dir) # If input = native space then do LSQ6 first on all files. if self.options.input_space == "native": initModel, targetPipeFH = rf.setInitialTarget(self.options.init_model, self.options.lsq6_target, dirs.lsq6Dir, self.outputDir) #LSQ6 MODULE, NUC and INORM inputFiles = [] for subj in subjects: for i in range(len(subjects[subj])): inputFiles.append(subjects[subj][i]) runLSQ6NucInorm = lsq6.LSQ6NUCInorm(inputFiles, targetPipeFH, initModel, dirs.lsq6Dir, self.options) self.pipeline.addPipeline(runLSQ6NucInorm.p) elif self.options.input_space == "lsq6": initModel = None else: print """Only native and lsq6 are allowed as input_space options for the registration chain. You specified: """ + str(self.options.input_space) print "Exiting..." sys.exit() #Get current group index for use later, when chain is run. #Value will be different for input_space == native vs LSQ6 currGroupIndex = rf.getCurrIndexForInputs(subjects) #If requested, run iterative groupwise registration for all subjects at the specified #common timepoint, otherwise look to see if files are specified from a previous run. if self.options.run_groupwise: inputs = [] for s in subjects: inputs.append(subjects[s][avgTime]) #Run full LSQ12 and NLIN modules. lsq12Nlin = mm.FullIterativeLSQ12Nlin(inputs, dirs, self.options, avgPrefix=self.options.common_name, initModel=initModel) self.pipeline.addPipeline(lsq12Nlin.p) nlinFH = lsq12Nlin.nlinFH #Set lastBasevol and group to lsq6 space, using currGroupIndex set above. for i in inputs: i.currentGroupIndex = currGroupIndex else: if self.options.mbm_dir and self.options.nlin_avg: if (not isdir(self.options.mbm_dir)) or (not isfile(self.options.nlin_avg)): logger.error("The specified MBM-directory or nlin-average do not exist.") logger.error("Specified MBM-directory: " + abspath(self.options.mbm_dir)) logger.error("Specified nlin average: " + abspath(self.options.nlin_avg)) sys.exit() # create file handler for nlin average nlinFH = rfh.RegistrationPipeFH(abspath(self.options.nlin_avg), basedir=dirs.processedDir) # Get transforms from subjects at avg time point to final nlin average and vice versa rf.getXfms(nlinFH, subjects, "lsq6", abspath(self.options.mbm_dir), time=avgTime) else: logger.info("MBM directory and nlin_average not specified.") logger.info("Calculating registration chain only") nlinFH = None for subj in subjects: s = subjects[subj] count = len(s) for i in range(count - 1): s[i].newGroup(groupName="chain") if self.options.reg_method == "mincANTS": register = mm.LSQ12ANTSNlin(s[i], s[i+1], lsq12_protocol=self.options.lsq12_protocol, nlin_protocol=self.options.nlin_protocol) self.pipeline.addPipeline(register.p) elif self.options.reg_method == "minctracc": hm = mm.HierarchicalMinctracc(s[i], s[i+1], lsq12_protocol=self.options.lsq12_protocol, nlin_protocol=self.options.nlin_protocol) self.pipeline.addPipeline(hm.p) """Resample s[i] into space of s[i+1]""" if nlinFH: resample = ma.mincresample(s[i], s[i+1], likeFile=nlinFH, argArray=["-sinc"]) else: resample = ma.mincresample(s[i], s[i+1], likeFile=s[i], argArray=["-sinc"]) self.pipeline.addStage(resample) """Invert transforms for use later in stats""" lastXfm = s[i].getLastXfm(s[i+1]) inverseXfm = s[i+1].getLastXfm(s[i]) if not inverseXfm: "invert xfm and calculate" xi = ma.xfmInvert(lastXfm, FH=s[i]) self.pipeline.addStage(xi) s[i+1].addAndSetXfmToUse(s[i], xi.outputFiles[0]) """Now that all registration is complete, calculate stats, concat transforms and resample""" car = mm.LongitudinalStatsConcatAndResample(subjects, avgTime, nlinFH, self.options.stats_kernels, self.options.common_name) self.pipeline.addPipeline(car.p)
def run(self): # Setup output directories for registration chain (_processed only). dirs = rf.setupDirectories(self.outputDir, self.options.pipeline_name, module=None) """Check that correct registration method was specified""" if self.options.reg_method != "minctracc" and self.options.reg_method != "mincANTS": logger.error("Incorrect registration method specified: " + self.options.reg_method) sys.exit() """Read in files from csv""" fileList = open(self.args[0], 'rb') subjectList = csv.reader(fileList, delimiter=',', skipinitialspace=True) subjects = {} # One array of images for each subject index = 0 for subj in subjectList: subjects[index] = rf.initializeInputFiles(subj, dirs.processedDir, self.options.mask_dir) index += 1 """Put blurs into array""" blurs = [] for i in self.options.stats_kernels.split(","): blurs.append(float(i)) """Create file handler for nlin average from MBM""" if self.options.nlin_avg: nlinFH = rfh.RegistrationPipeFH(abspath(self.options.nlin_avg), basedir=dirs.processedDir) else: nlinFH = None if self.options.mbm_dir and not isdir(abspath(self.options.mbm_dir)): logger.error("The --mbm-directory specified does not exist: " + abspath(self.options.mbm_dir)) sys.exit() """Take average time point, subtract 1 for proper indexing""" avgTime = self.options.avg_time_point - 1 """Get transforms from inputs to final nlin average and vice versa""" if self.options.nlin_avg and self.options.mbm_dir: xfmsPipe = ombm.getXfms(nlinFH, subjects, self.options.input_space, abspath(self.options.mbm_dir), time=avgTime) if len(xfmsPipe.stages) > 0: self.pipeline.addPipeline(xfmsPipe) """ Possible TODO: Align everything to lsq6 space, with ordering depending on time point. This functionality was previously partially implemented (ChainAlignLSQ6), but was removed, as it was never fully working or tested. Leaving this comment as a place holder in case we want to re-implement. """ else: logger.info("MBM directory and nlin_average not specified.") logger.info("Calculating registration chain only") for subj in subjects: s = subjects[subj] count = len(s) for i in range(count - 1): # Create new groups # MF TODO: Make generalization of registration parameters easier. if self.options.reg_method == "mincANTS": register = mm.LSQ12ANTSNlin(s[i], s[i+1]) self.pipeline.addPipeline(register.p) elif self.options.reg_method == "minctracc": hm = hmt.HierarchicalMinctracc(s[i], s[i+1]) self.pipeline.addPipeline(hm.p) """Resample s[i] into space of s[i+1]""" if nlinFH: resample = ma.mincresample(s[i], s[i+1], likeFile=nlinFH, argArray=["-sinc"]) else: resample = ma.mincresample(s[i], s[i+1], likeFile=s[i], argArray=["-sinc"]) self.pipeline.addStage(resample) """Invert transforms for use later in stats""" lastXfm = s[i].getLastXfm(s[i+1]) inverseXfm = s[i+1].getLastXfm(s[i]) if not inverseXfm: "invert xfm and calculate" xi = ma.xfmInvert(lastXfm, FH=s[i]) self.pipeline.addStage(xi) s[i+1].addAndSetXfmToUse(s[i], xi.outputFiles[0]) """Now that all registration is complete, calculate stats, concat transforms and resample""" car = mm.LongitudinalStatsConcatAndResample(subjects, avgTime, nlinFH, blurs, self.options.common_name) self.pipeline.addPipeline(car.p)
def run(self): #Setup output directories for registration chain (_processed only) dirs = rf.setupDirectories(self.outputDir, self.options.pipeline_name, module="ALL") #Check that correct registration method was specified if self.options.reg_method != "minctracc" and self.options.reg_method != "mincANTS": logger.error("Incorrect registration method specified: " + self.options.reg_method) sys.exit() #Take average time point, subtract 1 for proper indexing avgTime = self.options.avg_time_point - 1 #Read in files from csv subjects = rf.setupSubjectHash(self.args[0], dirs, self.options.mask_dir) # If input = native space then do LSQ6 first on all files. if self.options.input_space == "native": initModel, targetPipeFH = rf.setInitialTarget( self.options.init_model, self.options.lsq6_target, dirs.lsq6Dir, self.outputDir) #LSQ6 MODULE, NUC and INORM inputFiles = [] for subj in subjects: for i in range(len(subjects[subj])): inputFiles.append(subjects[subj][i]) runLSQ6NucInorm = lsq6.LSQ6NUCInorm(inputFiles, targetPipeFH, initModel, dirs.lsq6Dir, self.options) self.pipeline.addPipeline(runLSQ6NucInorm.p) elif self.options.input_space == "lsq6": initModel = None else: print """Only native and lsq6 are allowed as input_space options for the registration chain. You specified: """ + str( self.options.input_space) print "Exiting..." sys.exit() #Get current group index for use later, when chain is run. #Value will be different for input_space == native vs LSQ6 currGroupIndex = rf.getCurrIndexForInputs(subjects) #If requested, run iterative groupwise registration for all subjects at the specified #common timepoint, otherwise look to see if files are specified from a previous run. if self.options.run_groupwise: inputs = [] for s in subjects: inputs.append(subjects[s][avgTime]) #Run full LSQ12 and NLIN modules. lsq12Nlin = mm.FullIterativeLSQ12Nlin( inputs, dirs, self.options, avgPrefix=self.options.common_name, initModel=initModel) self.pipeline.addPipeline(lsq12Nlin.p) nlinFH = lsq12Nlin.nlinFH #Set lastBasevol and group to lsq6 space, using currGroupIndex set above. for i in inputs: i.currentGroupIndex = currGroupIndex else: if self.options.mbm_dir and self.options.nlin_avg: if (not isdir(self.options.mbm_dir)) or (not isfile( self.options.nlin_avg)): logger.error( "The specified MBM-directory or nlin-average do not exist." ) logger.error("Specified MBM-directory: " + abspath(self.options.mbm_dir)) logger.error("Specified nlin average: " + abspath(self.options.nlin_avg)) sys.exit() # create file handler for nlin average nlinFH = rfh.RegistrationPipeFH(abspath(self.options.nlin_avg), basedir=dirs.processedDir) # Get transforms from subjects at avg time point to final nlin average and vice versa rf.getXfms(nlinFH, subjects, "lsq6", abspath(self.options.mbm_dir), time=avgTime) else: logger.info("MBM directory and nlin_average not specified.") logger.info("Calculating registration chain only") nlinFH = None for subj in subjects: s = subjects[subj] count = len(s) for i in range(count - 1): s[i].newGroup(groupName="chain") if self.options.reg_method == "mincANTS": register = mm.LSQ12ANTSNlin( s[i], s[i + 1], lsq12_protocol=self.options.lsq12_protocol, nlin_protocol=self.options.nlin_protocol) self.pipeline.addPipeline(register.p) elif self.options.reg_method == "minctracc": hm = mm.HierarchicalMinctracc( s[i], s[i + 1], lsq12_protocol=self.options.lsq12_protocol, nlin_protocol=self.options.nlin_protocol) self.pipeline.addPipeline(hm.p) """Resample s[i] into space of s[i+1]""" if nlinFH: resample = ma.mincresample(s[i], s[i + 1], likeFile=nlinFH, argArray=["-sinc"]) else: resample = ma.mincresample(s[i], s[i + 1], likeFile=s[i], argArray=["-sinc"]) self.pipeline.addStage(resample) """Invert transforms for use later in stats""" lastXfm = s[i].getLastXfm(s[i + 1]) inverseXfm = s[i + 1].getLastXfm(s[i]) if not inverseXfm: "invert xfm and calculate" xi = ma.xfmInvert(lastXfm, FH=s[i]) self.pipeline.addStage(xi) s[i + 1].addAndSetXfmToUse(s[i], xi.outputFiles[0]) """Now that all registration is complete, calculate stats, concat transforms and resample""" car = mm.LongitudinalStatsConcatAndResample(subjects, avgTime, nlinFH, self.options.stats_kernels, self.options.common_name) self.pipeline.addPipeline(car.p)
def iterate(self): xfmsToAvg = {} lsq12ResampledFiles = {} for inputFH in self.inputs: """Create an array of xfms, to compute an average lsq12 xfm for each input""" xfmsToAvg[inputFH] = [] if self.maxPairs is not None: if self.maxPairs >= len(self.inputs) - 1: # -1 prevents unnecessary sampling in the case self.maxPairs = len(self.inputs) - 1 inputs = self.inputs else: random.seed( tuple(map(lambda fh: fh.inputFileName, self.inputs))) # if inputFH is included in the sample, we will register against one fewer target inputs = random.sample( filter(lambda fh: fh != inputFH, self.inputs), self.maxPairs) else: inputs = self.inputs for targetFH in inputs: if inputFH != targetFH: lsq12 = LSQ12(inputFH, targetFH, blurs=self.blurs, step=self.stepSize, gradient=self.useGradient, simplex=self.simplex, w_translations=self.w_translations) self.p.addPipeline(lsq12.p) xfmsToAvg[inputFH].append(inputFH.getLastXfm(targetFH)) """Create average xfm for inputFH using xfmsToAvg array""" avgXfmOutput = createBaseName(inputFH.transformsDir, inputFH.basename + "-avg-lsq12.xfm") cmd = ["xfmavg", "-verbose", "-clobber"] \ + map(InputFile, xfmsToAvg[inputFH]) + [OutputFile(avgXfmOutput)] #for i in range(len(xfmsToAvg[inputFH])): # cmd.append(InputFile(xfmsToAvg[inputFH][i])) # '-clobber' works around #157, but is probably better in general #cmd.append(OutputFile(avgXfmOutput)) xfmavg = CmdStage(cmd) xfmavg.setLogFile( LogFile(logFromFile(inputFH.logDir, avgXfmOutput))) self.p.addStage(xfmavg) self.lsq12AvgXfms[inputFH] = avgXfmOutput """ resample brain and add to array for mincAveraging""" if not self.likeFile: likeFile = inputFH else: likeFile = self.likeFile rslOutput = createBaseName( inputFH.resampledDir, inputFH.basename + "-resampled-lsq12.mnc") res = ma.mincresample(inputFH, inputFH, transform=avgXfmOutput, likeFile=likeFile, output=rslOutput, argArray=["-sinc"]) self.p.addStage(res) lsq12ResampledFiles[inputFH] = rslOutput """ After all registrations complete, setLastBasevol for each subject to be resampled file in lsq12 space. We can then call mincAverage on fileHandlers, as it will use the lastBasevol for each by default.""" for inputFH in self.inputs: inputFH.setLastBasevol(lsq12ResampledFiles[inputFH]) """ mincAverage all resampled brains and put in lsq12Directory""" self.lsq12Avg = abspath(self.lsq12Dir) + "/" + basename( self.lsq12Dir) + "-pairs.mnc" self.lsq12AvgFH = RegistrationPipeFH(self.lsq12Avg, basedir=self.lsq12Dir) avg = ma.mincAverage(inputs, self.lsq12AvgFH, output=self.lsq12Avg, defaultDir=self.lsq12Dir) self.p.addStage(avg)
def regAndResample(self, inputFH, i, filesToAvg, nlinFH): """For last generation, override default output names. Note that the defaultDir specified in the minctracc call is ignored in this instance. """ if i == (self.generations -1): if not self.useGradient[i]: firstRegOutput, resampleOutput = finalGenerationFileNames(inputFH) else: firstRegOutput = None registerOutput, resampleOutput = finalGenerationFileNames(inputFH) else: firstRegOutput = None #registerOutput = None resampleOutput = None """ In order to make the behavior of different modules / registration methods work in the same manner, the self.useGradient variable will determine what the blurring kernel needs to be applied on: either the image intensities (if self.useGradient = False), or the image gradients (if self.useGradient = True). """ useGradients = self.useGradient[i] mta = minctracc(inputFH, self.target, defaultDir="tmp", output=firstRegOutput, blur=self.blurs[i], gradient=useGradients, iterations=self.iterations[i], step=self.stepSize[i], weight=self.weight[i], stiffness=self.stiffness[i], similarity=self.similarity[i], w_translations = self.w_translations[i], simplex=self.simplex[i], memory=self.memory[i]) self.p.addStage(mta) # after each registration stage, we have to update # the last transformation between the nlinFH and the input file # TODO: we should definitely do something about this. This # assignment below is very cryptic (what is this nlinFH??), but # I assume that with the new file handler classes coming up, this # will all become more clear. inputFH.setLastXfm(nlinFH, mta.outputFiles[0]) #if self.useGradient[i]: # mtb = minctracc(inputFH, # self.target, # output=registerOutput, # defaultDir="tmp", # blur=self.blurs[i], # gradient=True, # iterations=self.iterations[i], # step=self.stepSize[i], # weight=self.weight[i], # stiffness=self.stiffness[i], # similarity=self.similarity[i], # simplex=self.simplex[i]) # self.p.addStage(mtb) # """Need to set last xfm so that next generation will use it as the input transform""" # inputFH.setLastXfm(nlinFH, mtb.outputFiles[0]) rs = mincresample(inputFH, self.target, likeFile=self.target, output=resampleOutput, defaultDir="tmp", argArray=["-sinc"]) #Do we need to resample any masks? filesToAvg.append(rs.outputFiles[0]) self.p.addStage(rs) if i == (self.generations -1): inputFH.setLastBasevol(newBaseVol=rs.outputFiles[0])
def run(self): """Directory handling etc as in MBM""" if not self.options.pipeline_name: pipeName = str(date.today()) + "_pipeline" else: pipeName = self.options.pipeline_name processedDirectory = fh.createSubDir(self.outputDir, pipeName + "_processed") """Check that correct registration method was specified""" if self.options.reg_method != "minctracc" and self.options.reg_method != "mincANTS": logger.error("Incorrect registration method specified: " + self.options.reg_method) sys.exit() """Create file handling classes for each image""" inputs = rf.initializeInputFiles(self.args, processedDirectory, self.options.mask_dir) """Put blurs into array""" blurs = [] for i in self.options.stats_kernels.split(","): blurs.append(float(i)) """Create file handler for nlin average from MBM""" if self.options.nlin_avg: nlinFH = rfh.RegistrationFHBase(abspath(self.options.nlin_avg), processedDirectory) else: nlinFH = None if self.options.mbm_dir and not isdir(abspath(self.options.mbm_dir)): logger.error("The --mbm-directory specified does not exist: " + abspath(self.options.mbm_dir)) sys.exit() """Get transforms from inputs to final nlin average and vice versa as well as lsq6 files""" if self.options.nlin_avg and self.options.mbm_dir: xfmsPipe = ombm.getXfms(nlinFH, inputs, self.options.input_space, abspath(self.options.mbm_dir)) if len(xfmsPipe.stages) > 0: self.pipeline.addPipeline(xfmsPipe) else: logger.info("MBM directory and nlin_average not specified.") logger.info("Calculating pairwise nlin only without resampling to common space.") """Create a dictionary of statistics. Each subject gets an array of statistics indexed by inputFile.""" subjectStats = {} """Register each image with every other image.""" for inputFH in inputs: subjectStats[inputFH] = {} for targetFH in inputs: if inputFH != targetFH: # MF TODO: Make generalization of registration parameters easier. if self.options.reg_method == "mincANTS": register = mm.LSQ12ANTSNlin(inputFH, targetFH) self.pipeline.addPipeline(register.p) elif self.options.reg_method == "minctracc": hm = hmt.HierarchicalMinctracc(inputFH, targetFH) self.pipeline.addPipeline(hm.p) if nlinFH: resample = ma.mincresample(inputFH, targetFH, likeFile=nlinFH) else: resample = ma.mincresample(inputFH, targetFH, likeFile=inputFH) self.pipeline.addStage(resample) inputFH.setLastBasevol(resample.outputFiles[0]) """Calculate statistics""" stats = st.CalcChainStats(inputFH, targetFH, blurs) stats.calcFullDisplacement() stats.calcDetAndLogDet(useFullDisp=True) self.pipeline.addPipeline(stats.p) subjectStats[inputFH][targetFH] = stats.statsGroup """Resample to nlin space from previous build model run, if specified""" if self.options.nlin_avg and self.options.mbm_dir: xfmToNlin = inputFH.getLastXfm(nlinFH, groupIndex=0) res = mm.resampleToCommon(xfmToNlin, inputFH, subjectStats[inputFH][targetFH], blurs, nlinFH) self.pipeline.addPipeline(res) """Reset last base volume to original input before continuing to next pair in loop.""" inputFH.setLastBasevol(setToOriginalInput=True)