def maskFiles(FH, isAtlas, numAtlases=1): """ Assume that if there is more than one atlas, multiple masks were generated and we need to perform a voxel_vote. Otherwise, assume we are using inputLabels from crossing with only one atlas. """ #MF TODO: Make this more general to handle pairwise option. p = Pipeline() if not isAtlas: if numAtlases > 1: voxel = voxelVote(FH, False, True) p.addStage(voxel) mincMathInput = voxel.outputFiles[0] else: mincMathInput = FH.returnLabels(True)[0] FH.setMask(mincMathInput) else: mincMathInput = FH.getMask() mincMathOutput = fh.createBaseName(FH.resampledDir, FH.basename) mincMathOutput += "_masked.mnc" logFile = fh.logFromFile(FH.logDir, mincMathOutput) cmd = ["mincmath"] + ["-clobber"] + ["-mult"] cmd += [InputFile(mincMathInput)] + [InputFile(FH.getLastBasevol())] cmd += [OutputFile(mincMathOutput)] mincMath = CmdStage(cmd) mincMath.setLogFile(LogFile(logFile)) p.addStage(mincMath) FH.setLastBasevol(mincMathOutput) return(p)
def maskFiles(FH, isAtlas, numAtlases=1): """ Assume that if there is more than one atlas, multiple masks were generated and we need to perform a voxel_vote. Otherwise, assume we are using inputLabels from crossing with only one atlas. """ #MF TODO: Make this more general to handle pairwise option. p = Pipeline() if not isAtlas: if numAtlases > 1: voxel = voxelVote(FH, False, True) p.addStage(voxel) mincMathInput = voxel.outputFiles[0] else: mincMathInput = FH.returnLabels(True)[0] FH.setMask(mincMathInput) else: mincMathInput = FH.getMask() mincMathOutput = fh.createBaseName(FH.resampledDir, FH.basename) mincMathOutput += "_masked.mnc" logFile = fh.logFromFile(FH.logDir, mincMathOutput) cmd = ["mincmath"] + ["-clobber"] + ["-mult"] cmd += [InputFile(mincMathInput)] + [InputFile(FH.getLastBasevol())] cmd += [OutputFile(mincMathOutput)] mincMath = CmdStage(cmd) mincMath.setLogFile(LogFile(logFile)) p.addStage(mincMath) FH.setLastBasevol(mincMathOutput) return (p)
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 __init__( self, inSource, inTarget, output=None, # ability to specify output transform when using strings for input logFile=None, maskFile=None, defaultDir="transforms", blur=0.56, resample_step=4, registration_step=10, w_translations=8, rotational_range=50, rotational_interval=10, mousedata=False): CmdStage.__init__(self, None) #don't do any arg processing in superclass # handling of the input files try: if rf.isFileHandler(inSource, inTarget): self.source = inSource.getBlur(fwhm=blur) self.target = inTarget.getBlur(fwhm=blur) if (output == None): self.output = inSource.registerVolume(inTarget, defaultDir) else: self.output = output if (logFile == None): self.logFile = fh.logFromFile(inSource.logDir, self.output) else: self.logFile = logFile else: # TODO: fix this to work with string input files self.source = inSource self.target = inTarget except: print "Failed in putting together RotationalMinctracc command; unexpected error:" raise # The resolution is used to determine the step size and # blurring kernels for the rotational minctracc call. This # should be based on the target, not the input file (source) highestResolution = rf.returnFinestResolution(inTarget) # TODO: finish the following if clause... hahaha #if(mousedata): self.addDefaults(resample_step * highestResolution, registration_step * highestResolution, w_translations * highestResolution, int(rotational_range), int(rotational_interval)) # potentially add a mask to the command self.finalizeCommand(inTarget, maskFile) self.setName() self.colour = "green"
def __init__(self, inSource, inTarget, output = None, # ability to specify output transform when using strings for input logFile = None, maskFile = None, defaultDir="transforms", blur=0.56, resample_step=4, registration_step=10, w_translations=8, rotational_range=50, rotational_interval=10, mousedata=False): CmdStage.__init__(self, None) #don't do any arg processing in superclass # handling of the input files try: if rf.isFileHandler(inSource, inTarget): self.source = inSource.getBlur(fwhm=blur) self.target = inTarget.getBlur(fwhm=blur) if(output == None): self.output = inSource.registerVolume(inTarget, defaultDir) else: self.output = output if(logFile == None): self.logFile = fh.logFromFile(inSource.logDir, self.output) else: self.logFile = logFile else: # TODO: fix this to work with string input files self.source = inSource self.target = inTarget except: print "Failed in putting together RotationalMinctracc command." print "Unexpected error: ", sys.exc_info() raise highestResolution = rf.getFinestResolution(inSource) # TODO: finish the following if clause... hahaha #if(mousedata): self.addDefaults(resample_step * highestResolution, registration_step * highestResolution, w_translations * highestResolution, int(rotational_range), int(rotational_interval)) # potentially add a mask to the command self.finalizeCommand(inTarget, maskFile) self.setName() self.colour = "green"
def __init__(self, inFile, fwhm, defaultDir="tmp", gradient=False): """calls mincblur with the specified 3D Gaussian kernel The inputs can be in one of two styles. The first argument can be an instance of RegistrationPipeFH, in which case the last volume in that instance (i.e. inFile.lastBasevol) will be blurred and the output will be determined by its blurFile method. Alternately, the inFile can be a string representing a filename, in which case the output and logfile will be set based on the inFile name. If the fwhm specified is -1, we do not construct a command. """ if fwhm == -1: return CmdStage.__init__(self, None) try: if isFileHandler(inFile): blurlist = inFile.blurFile(fwhm, gradient, defaultDir) self.base = blurlist["base"] self.inputFiles = [inFile.getLastBasevol()] self.outputFiles = [blurlist["file"]] self.logFile = blurlist["log"] self.name = "mincblur " + str(fwhm) + " " + inFile.basename if gradient: self.outputFiles.append(blurlist["gradient"]) else: self.base = str(inFile).replace(".mnc", "") self.inputFiles = [inFile] blurBase = "".join([self.base, "_fwhm", str(fwhm), "_blur"]) output = "".join([blurBase, ".mnc"]) self.outputFiles = [output] self.logFile = fh.logFromFile(abspath(curdir), output) self.name = "mincblur " + str(fwhm) + " " + basename(inFile) if gradient: gradientBase = blurBase.replace("blur", "dxyz") self.outputFiles += ["".join([gradientBase, ".mnc"])] except: print "Failed in putting together blur command." print "Unexpected error: ", sys.exc_info() self.cmd = ["mincblur", "-clobber", "-no_apodize", "-fwhm", str(fwhm), self.inputFiles[0], self.base] if gradient: self.cmd += ["-gradient"] self.colour="blue"
def linAndNlinDisplacement(self): """ The function calculates both the linear and nonlinear portions of the displacement, in order to find pure nonlinear. Common space here is the target (usually an average of some sort). We also recentre pure non linear displacement. """ """Calculate linear part of non-linear xfm from input to target""" lpnl = linearPartofNlin(self.inputFH, self.targetFH) self.p.addStage(lpnl) self.linearXfm = lpnl.outputFiles[0] """Calculate full displacement from target to input""" self.calcFullDisplacement() """Calculate pure non-linear displacement from target to input 1. Concatenate linear and inverse target to input transform to get pure_nlin xfm 2. Compute mincDisplacement on this transform. """ nlinXfm = createPureNlinXfmName(self.inputFH, self.invXfm) xc = xfmConcat([self.linearXfm, self.invXfm], nlinXfm, fh.logFromFile(self.inputFH.logDir, nlinXfm)) self.p.addStage(xc) nlinDisp = mincDisplacement(self.targetFH, self.inputFH, transform=nlinXfm) self.p.addStage(nlinDisp) self.nlinDisp = nlinDisp.outputFiles[0] """Calculate average displacement and re-center non-linear displacement if an array of input file handlers was specified on instantiation. """ if self.dispToAvg: """Calculate average inverse displacement""" avgOutput = abspath(self.targetFH.basedir) + "/" + "average_inv_pure_displacement.mnc" logBase = fh.removeBaseAndExtension(avgOutput) avgLog = fh.createLogFile(self.targetFH.basedir, logBase) avg = mincAverageDisp(self.dispToAvg, avgOutput, logFile=avgLog) self.p.addStage(avg) """Centre pure nlin displacement by subtracting average from existing""" centredBase = fh.removeBaseAndExtension(self.nlinDisp).split("_displacement")[0] centredOut = fh.createBaseName(self.inputFH.statsDir, centredBase + "_centred_displacement.mnc") cmd = ["mincmath", "-clobber", "-sub", InputFile(self.nlinDisp), InputFile(avgOutput), OutputFile(centredOut)] centredDisp = CmdStage(cmd) centredDisp.setLogFile(LogFile(fh.logFromFile(self.inputFH.logDir, centredOut))) self.p.addStage(centredDisp) """Reset centred displacement to be self.nlinDisp""" self.nlinDisp = centredOut
def __init__(self, inFile, fwhm, defaultDir="tmp", gradient=False): """calls mincblur with the specified 3D Gaussian kernel The inputs can be in one of two styles. The first argument can be an instance of RegistrationPipeFH, in which case the last volume in that instance (i.e. inFile.lastBasevol) will be blurred and the output will be determined by its blurFile method. Alternately, the inFile can be a string representing a filename, in which case the output and logfile will be set based on the inFile name. If the fwhm specified is -1, we do not construct a command. """ if fwhm == -1: return CmdStage.__init__(self, None) try: if isFileHandler(inFile): blurlist = inFile.blurFile(fwhm, gradient, defaultDir) self.base = blurlist["base"] self.inputFiles = [inFile.getLastBasevol()] self.outputFiles = [blurlist["file"]] self.logFile = blurlist["log"] self.name = "mincblur " + str(fwhm) + " " + inFile.basename if gradient: self.outputFiles.append(blurlist["gradient"]) else: self.base = str(inFile).replace(".mnc", "") self.inputFiles = [inFile] blurBase = "".join([self.base, "_fwhm", str(fwhm), "_blur"]) output = "".join([blurBase, ".mnc"]) self.outputFiles = [output] self.logFile = fh.logFromFile(abspath(curdir), output) self.name = "mincblur " + str(fwhm) + " " + basename(inFile) if gradient: gradientBase = blurBase.replace("blur", "dxyz") self.outputFiles += ["".join([gradientBase, ".mnc"])] except: print "Failed in putting together blur command." print "Unexpected error: ", sys.exc_info() self.cmd = [ "mincblur", "-clobber", "-no_apodize", "-fwhm", str(fwhm), self.inputFiles[0], self.base ] if gradient: self.cmd += ["-gradient"] self.colour = "blue"
def __init__(self, inputFiles, outputFile, logFile=None): CmdStage.__init__(self, None) # in case there is a single input file... (it's actually possible) if (not (type(inputFiles) is list)): inputFiles = [inputFiles] self.inputFiles = inputFiles self.outputFiles = [outputFile] self.logFile = logFile self.cmd = ["xfmconcat", "-clobber"] self.cmd += inputFiles self.cmd += [outputFile] self.name = "xfm-concat" self.colour = "yellow"
def voxelVote(inputFH, pairwise, mask): # if we do pairwise crossing, use output labels for voting (Default) # otherwise, return inputLabels from initial atlas-input crossing useInputLabels = False if not pairwise: useInputLabels = True labels = inputFH.returnLabels(useInputLabels) out = fh.createBaseName(inputFH.labelsDir, inputFH.basename) if mask: out += "_mask.mnc" else: out += "_votedlabels.mnc" logFile = fh.logFromFile(inputFH.logDir, out) cmd = ["voxel_vote"] + [InputFile(l) for l in labels] + [OutputFile(out)] voxel = CmdStage(cmd) voxel.setLogFile(LogFile(logFile)) return (voxel)
def voxelVote(inputFH, pairwise, mask): # if we do pairwise crossing, use output labels for voting (Default) # otherwise, return inputLabels from initial atlas-input crossing useInputLabels = False if not pairwise: useInputLabels = True labels = inputFH.returnLabels(useInputLabels) out = fh.createBaseName(inputFH.labelsDir, inputFH.basename) if mask: out += "_mask.mnc" else: out += "_votedlabels.mnc" logFile = fh.logFromFile(inputFH.logDir, out) cmd = ["voxel_vote.py"] + [InputFile(l) for l in labels] + [OutputFile(out)] voxel = CmdStage(cmd) voxel.setLogFile(LogFile(logFile)) return(voxel)
def __init__(self, inputFiles, outputFile, logFile=None): CmdStage.__init__(self, None) # in case there is a single input file... (it's actually possible) if(not(type(inputFiles) is list)): inputFiles = [inputFiles] self.inputFiles = inputFiles self.outputFiles = [outputFile] self.logFile = logFile self.cmd = ["xfmconcat", "-clobber"] self.cmd += inputFiles self.cmd += [outputFile] self.name = "xfm-concat" self.colour = "yellow"
def __init__(self, inputFH, outputFH, transform, defaultDir="tmp"): CmdStage.__init__(self, None) try: if isFileHandler(inputFH, outputFH): self.inFile = inputFH.getLastBasevol() self.xfm = transform self.outfile = createOutputFileName(outputFH, self.xfm, defaultDir, "_displacement.mnc") self.logFile = fh.logFromFile(outputFH.logDir, self.outfile) else: print ("minc_displacement only works using file handlers. " "Exception being raised.") raise except: print("Failed in putting together minc_displacement command") print("Unexpected error: ", sys.exc_info()) self.addDefaults() self.finalizeCommand() self.setName()
def __init__(self, inputFH, outputFH, transform, defaultDir="tmp"): CmdStage.__init__(self, None) try: if isFileHandler(inputFH, outputFH): self.inFile = inputFH.getLastBasevol() self.xfm = transform self.outfile = createOutputFileName(outputFH, self.xfm, defaultDir, "_displacement.mnc") self.logFile = fh.logFromFile(outputFH.logDir, self.outfile) else: print ("minc_displacement only works using file handlers. " "Exception being raised.") raise except: print "Failed in putting together minc_displacement command" print "Unexpected error: ", sys.exc_info() self.addDefaults() self.finalizeCommand() self.setName()
def __init__(self, inputFH, targetFH, defaultDir="transforms"): CmdStage.__init__(self, None) try: if isFileHandler(inputFH, targetFH): self.inFile = inputFH.getLastBasevol() self.mask = inputFH.getMask() self.xfm = inputFH.getLastXfm(targetFH) self.outfile = self.setOutputFile(inputFH, defaultDir) self.logFile = fh.logFromFile(inputFH.logDir, self.outfile) else: print ("linear part of nlin currently only works using file handlers. " "Exception being raised.") raise except: print "Failed in putting together linearPartofNlin command" print "Unexpected error: ", sys.exc_info() self.addDefaults() self.finalizeCommand() self.setName()
def __init__(self, inputFH, targetFH, defaultDir="transforms"): CmdStage.__init__(self, None) try: if isFileHandler(inputFH, targetFH): self.inFile = inputFH.getLastBasevol() self.mask = inputFH.getMask() self.xfm = inputFH.getLastXfm(targetFH) self.outfile = self.setOutputFile(inputFH, defaultDir) self.logFile = fh.logFromFile(inputFH.logDir, self.outfile) else: print ("linear part of nlin currently only works using file handlers. " "Exception being raised.") raise except: print("Failed in putting together linearPartofNlin command") print("Unexpected error: ", sys.exc_info()) self.addDefaults() self.finalizeCommand() self.setName()
def __init__(self, xfm, FH=None, logFile=None): CmdStage.__init__(self, None) try: self.xfm = xfm if isFileHandler(FH): invXfmBase = fh.removeBaseAndExtension( self.xfm).split(".xfm")[0] self.output = fh.createBaseName(FH.transformsDir, invXfmBase + "_inverted.xfm") self.logFile = fh.logFromFile(FH.logDir, self.output) else: invXfmBase = splitext(self.xfm)[0] self.output = invXfmBase + "_inverted.xfm" if logFile: self.logFile = logFile except: print "Failed in putting together xfminvert command" print "Unexpected error: ", sys.exc_info() self.finalizeCommand() self.setName()
def __init__(self, resolution, inFile, output=None, logFile=None, defaultDir="resampled"): """Resamples the input file to the resolution specified using autocrop. The -resample flag forces the use of mincresample. Resolutions should be specified in mm. e.g. 56 microns should be specified as 0.056 """ CmdStage.__init__(self, None) self.resolution = str(resolution) try: if isFileHandler(inFile): self.inFile = inFile.getLastBasevol() self.outfile = self.setOutputFile(inFile, defaultDir) self.logFile = fh.logFromFile(inFile.logDir, self.outfile) else: self.inFile = inFile self.outfile = output if not logFile: self.logFile = fh.logFromFile(abspath(curdir), output) else: self.logFile = logFile except: print "Failed in putting together autocrop command" print "Unexpected error: ", sys.exc_info() self.addDefaults() self.finalizeCommand() self.setName()
def maskFiles(FH, isAtlas, numAtlases=1): """ Assume that if there is more than one atlas, multiple masks were generated and we need to perform a voxel_vote. Otherwise, assume we are using inputLabels from crossing with only one atlas. """ #MF TODO: Make this more general to handle pairwise option. p = Pipeline() if not isAtlas: if numAtlases > 1: voxel = voxelVote(FH, False, True) p.addStage(voxel) mincMathInput = voxel.outputFiles[0] else: mincMathInput = FH.returnLabels(True)[0] FH.setMask(mincMathInput) else: mincMathInput = FH.getMask() mincMathOutput = fh.createBaseName(FH.resampledDir, FH.basename) mincMathOutput += "_masked.mnc" logFile = fh.logFromFile(FH.logDir, mincMathOutput) cmd = ["mincmath"] + ["-clobber"] + ["-mult"] # In response to issue #135 # the order of the input files to mincmath matters. By default the # first input files is used as a "like file" for the output file. # We should make sure that the mask is not used for that, because # it has an image range from 0 to 1; not something we want to be # set for the masked output file # average mask cmd += [InputFile(FH.getLastBasevol())] + [InputFile(mincMathInput)] cmd += [OutputFile(mincMathOutput)] mincMath = CmdStage(cmd) mincMath.setLogFile(LogFile(logFile)) p.addStage(mincMath) FH.setLastBasevol(mincMathOutput) return(p)
def voxelVote(inputFH, pairwise, mask): # In the main MAGeT.py code, when not only a mask is created for the # input files, the process works as follows: # # 1) the template files (library) are aligned to each input upto max_templates input files # 2) all templates (library + newly created) are aligned to each input # # That second stage contains alignments that have already run in the first stage. # And pydpiper is coded such, that this duplicated stage is not performed. In order # to get all labels for voxel voting, we need to combine atlases from both these # stages, i.e., the "initial" and the "templates". This means that we should always # get the "useInputLabels". (In the special case where there is only 1 input file # and pairwise is set to true, this is particularly important, because of the duplicate # stages, only the inputlabels will exists.) # 1) get the input templates # the True parameter will return "inputLabels" from the groupedFiles for inputFH labels = inputFH.returnLabels(True) # 2) if we do pairwise crossing, also get the output labels for voting if pairwise: # False will return "labels" from the groupedFiles for inputFH outputLabels = inputFH.returnLabels(False) # add these labels to the "initial" or input labels: labels = labels + outputLabels out = fh.createBaseName(inputFH.labelsDir, inputFH.basename) if mask: out += "_mask.mnc" else: out += "_votedlabels.mnc" logFile = fh.logFromFile(inputFH.logDir, out) cmd = ["voxel_vote"] + [InputFile(l) for l in labels] + [OutputFile(out)] voxel = CmdStage(cmd) voxel.setLogFile(LogFile(logFile)) return(voxel)
def voxelVote(inputFH, pairwise, mask): # In the main MAGeT.py code, when not only a mask is created for the # input files, the process works as follows: # # 1) the template files (library) are aligned to each input upto max_templates input files # 2) all templates (library + newly created) are aligned to each input # # That second stage contains alignments that have already run in the first stage. # And pydpiper is coded such, that this duplicated stage is not performed. In order # to get all labels for voxel voting, we need to combine atlases from both these # stages, i.e., the "initial" and the "templates". This means that we should always # get the "useInputLabels". (In the special case where there is only 1 input file # and pairwise is set to true, this is particularly important, because of the duplicate # stages, only the inputlabels will exists.) # 1) get the input templates # the True parameter will return "inputLabels" from the groupedFiles for inputFH labels = inputFH.returnLabels(True) # 2) if we do pairwise crossing, also get the output labels for voting if pairwise: # False will return "labels" from the groupedFiles for inputFH outputLabels = inputFH.returnLabels(False) # add these labels to the "initial" or input labels: labels = labels + outputLabels out = fh.createBaseName(inputFH.labelsDir, inputFH.basename) if mask: out += "_mask.mnc" else: out += "_votedlabels.mnc" logFile = fh.logFromFile(inputFH.logDir, out) cmd = ["voxel_vote"] + [InputFile(l) for l in labels] + [OutputFile(out)] voxel = CmdStage(cmd) voxel.setLogFile(LogFile(logFile)) return (voxel)
def __init__(self, inputArray, outputAvg, output=None, logFile=None, defaultDir="tmp"): CmdStage.__init__(self, None) try: """If output is fileHandler, we assume input array is as well""" if isFileHandler(outputAvg): self.filesToAvg = [] for i in range(len(inputArray)): self.filesToAvg.append(inputArray[i].getLastBasevol()) """If no output file is specified, create default, using file handler otherwise use what is specified.""" if not output: self.output = self.setOutputFile(outputAvg, defaultDir) else: self.output = output self.logFile = fh.logFromFile(outputAvg.logDir, self.output) else: self.filesToAvg = inputArray self.output = outputAvg if not logFile: self.logFile = fh.logFromFile(abspath(curdir), outputAvg) else: self.logFile = logFile except: print "Failed in putting together mincaverage command" print "Unexpected error: ", sys.exc_info() self.addDefaults() self.finalizeCommand() self.setName()
def __init__(self, xfm, FH=None, logFile=None): CmdStage.__init__(self, None) try: self.xfm = xfm if isFileHandler(FH): invXfmBase = fh.removeBaseAndExtension(self.xfm).split(".xfm")[0] self.output = fh.createBaseName(FH.transformsDir, invXfmBase + "_inverted.xfm") self.logFile = fh.logFromFile(FH.logDir, self.output) else: invXfmBase = splitext(self.xfm)[0] self.output = invXfmBase + "_inverted.xfm" if logFile: self.logFile = logFile except: print "Failed in putting together xfminvert command" print "Unexpected error: ", sys.exc_info() self.finalizeCommand() self.setName()
def maskFiles(FH, isAtlas, numAtlases=1): """ Assume that if there is more than one atlas, multiple masks were generated and we need to perform a voxel_vote. Otherwise, assume we are using inputLabels from crossing with only one atlas. """ #MF TODO: Make this more general to handle pairwise option. p = Pipeline() if not isAtlas: if numAtlases > 1: voxel = voxelVote(FH, False, True) p.addStage(voxel) mincMathInput = voxel.outputFiles[0] else: mincMathInput = FH.returnLabels(True)[0] FH.setMask(mincMathInput) else: mincMathInput = FH.getMask() mincMathOutput = fh.createBaseName(FH.resampledDir, FH.basename) mincMathOutput += "_masked.mnc" logFile = fh.logFromFile(FH.logDir, mincMathOutput) cmd = ["mincmath"] + ["-clobber"] + ["-mult"] # In response to issue #135 # the order of the input files to mincmath matters. By default the # first input files is used as a "like file" for the output file. # We should make sure that the mask is not used for that, because # it has an image range from 0 to 1; not something we want to be # set for the masked output file # average mask cmd += [InputFile(FH.getLastBasevol())] + [InputFile(mincMathInput)] cmd += [OutputFile(mincMathOutput)] mincMath = CmdStage(cmd) mincMath.setLogFile(LogFile(logFile)) p.addStage(mincMath) FH.setLastBasevol(mincMathOutput) return (p)
def __init__( self, inSource, inTarget, output=None, logFile=None, defaultDir="transforms", blur=[-1, 0.056], gradient=[False, True], target_mask=None, #ANTS only uses one mask similarity_metric=["CC", "CC"], weight=[1, 1], iterations="100x100x100x150", radius_or_histo=[3, 3], transformation_model="SyN[0.1]", regularization="Gauss[2,1]", useMask=True): CmdStage.__init__(self, None) #don't do any arg processing in superclass try: if isFileHandler(inSource, inTarget): """Same defaults as minctracc class: blur = None --> return lastblur gradient = True --> return gradient instead of blur if blur = -1 --> lastBaseVol returned and gradient ignored""" self.source = [] self.target = [] # Need to check that length of blur, gradient, similarity, weight # and radius_or_histo are the same self.checkArrayLengths(blur, gradient, similarity_metric, weight, radius_or_histo) for i in range(len(blur)): self.source.append(inSource.getBlur(blur[i], gradient[i])) self.target.append(inTarget.getBlur(blur[i], gradient[i])) """If no output transform is specified, use registerVolume to create a default. If an output transform name is specified, use this as the output, and add it as the last xfm between source and target. Note: The output file passed in must be a full path.""" if not output: outputXfm = inSource.registerVolume(inTarget, defaultDir) self.output = outputXfm else: self.output = output inSource.addAndSetXfmToUse(inTarget, self.output) self.logFile = fh.logFromFile(inSource.logDir, self.output) self.useMask = useMask if self.useMask: self.target_mask = inTarget.getMask() else: self.source = inSource self.target = inTarget #MF TODO: Need to find a way to specify multiple source and targets #based on blur and gradient self.output = output if not logFile: self.logFile = fh.logFromFile(abspath(curdir), output) else: self.logFile = logFile self.useMask = useMask if self.useMask: self.target_mask = target_mask except: print "Failed in putting together mincANTS command." print "Unexpected error: ", sys.exc_info() self.similarity_metric = similarity_metric self.weight = weight self.iterations = iterations self.radius_or_histo = radius_or_histo """Single quotes needed on the command line for transformation_model and regularization """ self.transformation_model = "'" + transformation_model + "'" self.regularization = "'" + regularization + "'" self.addDefaults() self.finalizeCommand() self.setName() self.colour = "red"
def calcDetAndLogDet(self, useFullDisp=False): if useFullDisp: dispToUse = self.fullDisp #absolute jacobians else: dispToUse = self.nlinDisp #relative jacobians """Insert -1 at beginning of blurs array to include the calculation of unblurred jacobians.""" self.blurs.insert(0,-1) for b in self.blurs: """Create base name for determinant calculation.""" outputBase = fh.removeBaseAndExtension(dispToUse).split("_displacement")[0] """Calculate smoothed deformation field for all blurs other than -1""" if b != -1: fwhm = "--fwhm=" + str(b) outSmooth = fh.createBaseName(self.inputFH.tmpDir, outputBase + "_smooth_displacement_fwhm" + str(b) + ".mnc") cmd = ["smooth_vector", "--clobber", "--filter", fwhm, InputFile(dispToUse), OutputFile(outSmooth)] smoothVec = CmdStage(cmd) smoothVec.setLogFile(LogFile(fh.logFromFile(self.inputFH.logDir, outSmooth))) self.p.addStage(smoothVec) """Set input for determinant calculation.""" inputDet = outSmooth nameAddendum = "_fwhm" + str(b) else: inputDet = dispToUse nameAddendum = "" outputDet = fh.createBaseName(self.inputFH.tmpDir, outputBase + "_determinant" + nameAddendum + ".mnc") outDetShift = fh.createBaseName(self.inputFH.tmpDir, outputBase + "_det_plus1" + nameAddendum + ".mnc") if useFullDisp: #absolute jacobians outLogDet = fh.createBaseName(self.inputFH.statsDir, outputBase + "_absolute_log_determinant" + nameAddendum + ".mnc") else: #relative jacobians outLogDet = fh.createBaseName(self.inputFH.statsDir, outputBase + "_relative_log_determinant" + nameAddendum + ".mnc") """Calculate the determinant, then add 1 (per mincblob weirdness)""" cmd = ["mincblob", "-clobber", "-determinant", InputFile(inputDet), OutputFile(outputDet)] det = CmdStage(cmd) det.setLogFile(LogFile(fh.logFromFile(self.inputFH.logDir, outputDet))) self.p.addStage(det) cmd = ["mincmath", "-clobber", "-2", "-const", str(1), "-add", InputFile(outputDet), OutputFile(outDetShift)] det = CmdStage(cmd) det.setLogFile(LogFile(fh.logFromFile(self.inputFH.logDir, outDetShift))) self.p.addStage(det) """Calculate log determinant (jacobian) and add to statsGroup.""" cmd = ["mincmath", "-clobber", "-2", "-log", InputFile(outDetShift), OutputFile(outLogDet)] det = CmdStage(cmd) det.setLogFile(LogFile(fh.logFromFile(self.inputFH.logDir, outLogDet))) self.p.addStage(det) if useFullDisp: self.statsGroup.absoluteJacobians[b] = outLogDet else: self.statsGroup.relativeJacobians[b] = outLogDet
def calcDetAndLogDet(self, useFullDisp=False): #Lots of repetition here--let's see if we can't make some functions. """useFullDisp indicates whether or not to use full displacement field or non-linear component only""" if useFullDisp: dispToUse = self.fullDisp else: dispToUse = self.nlinDisp """Insert -1 at beginning of blurs array to include the calculation of unblurred jacobians.""" self.blurs.insert(0,-1) for b in self.blurs: """Calculate default output filenames and set input for determinant calculation.""" outputBase = fh.removeBaseAndExtension(dispToUse).split("_displacement")[0] inputDet = dispToUse outputDet = fh.createBaseName(self.inputFH.tmpDir, outputBase + "_determinant.mnc") outDetShift = fh.createBaseName(self.inputFH.tmpDir, outputBase + "_det_plus1.mnc") outLogDet = fh.createBaseName(self.inputFH.statsDir, outputBase + "_log_determinant.mnc") outLogDetScaled = fh.createBaseName(self.inputFH.statsDir, outputBase + "_log_determinant_scaled.mnc") """Calculate smoothed deformation field for all blurs other than -1""" if b != -1: fwhm = "--fwhm=" + str(b) outSmooth = fh.createBaseName(self.inputFH.tmpDir, outputBase + "_smooth_displacement_fwhm" + str(b) + ".mnc") cmd = ["smooth_vector", "--clobber", "--filter", fwhm, InputFile(dispToUse), OutputFile(outSmooth)] smoothVec = CmdStage(cmd) smoothVec.setLogFile(LogFile(fh.logFromFile(self.inputFH.logDir, outSmooth))) self.p.addStage(smoothVec) """Override file name defaults for each blur and set input for determinant calculation.""" inputDet = outSmooth outputDet = fh.createBaseName(self.inputFH.tmpDir, outputBase + "_determinant_fwhm" + str(b) + ".mnc") outDetShift = fh.createBaseName(self.inputFH.tmpDir, outputBase + "_det_plus1_fwhm" + str(b) + ".mnc") outLogDet = fh.createBaseName(self.inputFH.statsDir, outputBase + "_log_determinant_fwhm" + str(b) + ".mnc") outLogDetScaled = fh.createBaseName(self.inputFH.statsDir, outputBase + "_log_determinant_scaled_fwhm" + str(b) + ".mnc") """Calculate the determinant, then add 1 (per mincblob weirdness)""" cmd = ["mincblob", "-clobber", "-determinant", InputFile(inputDet), OutputFile(outputDet)] det = CmdStage(cmd) det.setLogFile(LogFile(fh.logFromFile(self.inputFH.logDir, outputDet))) self.p.addStage(det) cmd = ["mincmath", "-clobber", "-2", "-const", str(1), "-add", InputFile(outputDet), OutputFile(outDetShift)] det = CmdStage(cmd) det.setLogFile(LogFile(fh.logFromFile(self.inputFH.logDir, outDetShift))) self.p.addStage(det) """Calculate log determinant (jacobian) and add to statsGroup.""" cmd = ["mincmath", "-clobber", "-2", "-log", InputFile(outDetShift), OutputFile(outLogDet)] det = CmdStage(cmd) det.setLogFile(LogFile(fh.logFromFile(self.inputFH.logDir, outLogDet))) self.p.addStage(det) self.statsGroup.jacobians[b] = outLogDet """If self.linearXfm present, calculate scaled log determinant (scaled jacobian) and add to statsGroup""" if not useFullDisp: """ If self.scaleFactor is specified, then concatenate this additional transform with self.linearXfm. Typically, this will come from an LSQ12 registration, but may come from another alignment. """ if self.scalingFactor: toConcat = [self.scalingFactor, self.linearXfm] self.fullLinearXfm = fh.createBaseName(self.inputFH.transformsDir, self.inputFH.basename + "_full_linear.xfm") logFile=fh.logFromFile(self.inputFH.logDir, fh.removeBaseAndExtension(self.fullLinearXfm)) concat = xfmConcat(toConcat, self.fullLinearXfm, logFile=logFile) self.p.addStage(concat) else: self.fullLinearXfm = self.linearXfm cmd = ["scale_voxels", "-clobber", "-invert", "-log", InputFile(self.fullLinearXfm), InputFile(outLogDet), OutputFile(outLogDetScaled)] det = CmdStage(cmd) det.setLogFile(LogFile(fh.logFromFile(self.inputFH.logDir, outLogDetScaled))) self.p.addStage(det) self.statsGroup.scaledJacobians[b] = outLogDetScaled else: self.statsGroup.scaledJacobians = None
def __init__(self, inFile, fwhm, defaultDir="tmp", gradient=False): """calls mincblur with the specified 3D Gaussian kernel The inputs can be in one of two styles. The first argument can be an instance of RegistrationPipeFH, in which case the last volume in that instance (i.e. inFile.lastBasevol) will be blurred and the output will be determined by its blurFile method. Alternately, the inFile can be a string representing a filename, in which case the output and logfile will be set based on the inFile name. If the fwhm specified is -1, we do not construct a command. """ if fwhm == -1: return CmdStage.__init__(self, None) try: if isFileHandler(inFile): blurlist = inFile.blurFile(fwhm, gradient, defaultDir) self.base = blurlist["base"] self.inputFiles = [inFile.getLastBasevol()] self.outputFiles = [blurlist["file"]] self.logFile = blurlist["log"] self.name = "mincblur " + str(fwhm) + " " + inFile.basename if gradient: self.outputFiles.append(blurlist["gradient"]) else: self.base = str(inFile).replace(".mnc", "") self.inputFiles = [inFile] blurBase = "".join([self.base, "_fwhm", str(fwhm), "_blur"]) output = "".join([blurBase, ".mnc"]) self.outputFiles = [output] self.logFile = fh.logFromFile(abspath(curdir), output) self.name = "mincblur " + str(fwhm) + " " + basename(inFile) if gradient: gradientBase = blurBase.replace("blur", "dxyz") self.outputFiles += ["".join([gradientBase, ".mnc"])] except: print "Failed in putting together blur command; unexpected error: " raise self.cmd = [ "mincblur", "-clobber", "-no_apodize", "-fwhm", str(fwhm), self.inputFiles[0], self.base ] if gradient: self.cmd += ["-gradient"] self.colour = "blue" # this is a temporary solution, but it's better to at least catch it # somewhere... In the mincblur code, there is a hardcoded limit for # the length of the output file: full_outfilename[256]; (blur_volume.c) # This is a limit for the basename. Added to that will be: _dxyz.mnc # or _blur.mnc. In total the output file names can not be longer than 264 # characters. Given that we don't know which version of mincblur is installed # (this should and will be fixed at some point in the future), we'll exit here if len(self.outputFiles[0]) > 264: raise Exception( "mincblur (potentially) has a hardcoded limit for the allowed length of the output file. The following command will not be able to run: \n\n%s\n\nPlease rename your input files/paths to make sure the filenames become shorter.\n" % self.cmd)
def __init__(self, inSource, inTarget, output=None, logFile=None, defaultDir="transforms", blur=None, gradient=False, linearparam="nlin", source_mask=None, target_mask=None, iterations=40, step=0.5, transform=None, weight=0.8, stiffness=0.98, similarity=0.8, w_translations=0.4, w_rotations=0.0174533, w_scales=0.02, w_shear=0.02, simplex=1, optimization="-use_simplex", useMask=True): #MF TODO: Specify different w_translations, rotations, scales shear in each direction? # Now assumes same in all directions # Go to more general **kwargs? """an efficient way to add a minctracc call to a pipeline The constructor needs two inputFile arguments, the source and the target for the registration, and multiple optional arguments for specifying parameters. The source and the target can be specified as either RegistrationPipeFH instances or as strings representing filenames. In the latter case an output and a logfile filename are required as well (these are filled in automatically in the case of RegistrationPipeFH instances.) """ CmdStage.__init__(self, None) #don't do any arg processing in superclass try: if isFileHandler(inSource, inTarget): """ if blur = None, getBlur returns lastblur if gradient is true, getBlur returns gradient instead of blur if blur = -1, lastBaseVol is returned and gradient is ignored. self.transform will be None if there is no previous transform between input and target. If this is the case, lsq6 and lsq12 defaults are added in the setTransforms function """ self.source = inSource.getBlur(blur, gradient) self.target = inTarget.getBlur(blur, gradient) self.transform = inSource.getLastXfm(inTarget) """If no output transform is specified, use registerVolume to create a default. If an output transform name is specified, use this as the output, and add it as the last xfm between source and target. Note: The output file passed in must be a full path.""" if not output: outputXfm = inSource.registerVolume(inTarget, defaultDir) self.output = outputXfm else: self.output = output inSource.addAndSetXfmToUse(inTarget, self.output) outputXfm = output self.logFile = fh.logFromFile(inSource.logDir, outputXfm) self.useMask = useMask if self.useMask: self.source_mask = inSource.getMask() self.target_mask = inTarget.getMask() else: self.source = inSource self.target = inTarget self.output = output if not logFile: self.logFile = fh.logFromFile(abspath(curdir), output) else: self.logFile = logFile self.transform = transform self.useMask = useMask if self.useMask: self.source_mask = source_mask self.target_mask = target_mask except: print "Failed in putting together minctracc command." print "Unexpected error: ", sys.exc_info() self.linearparam = linearparam self.iterations = str(iterations) self.lattice_diameter = str(step*3.0) self.step = str(step) self.weight = str(weight) self.stiffness = str(stiffness) self.similarity = str(similarity) self.w_translations = str(w_translations) self.w_rotations = str(w_rotations) self.w_scales = str(w_scales) self.w_shear = str(w_shear) self.simplex = str(simplex) self.optimization = str(optimization) self.addDefaults() self.finalizeCommand() self.setTransform() self.setName() self.colour = "red"
def __init__(self, inFile, targetFile, **kwargs): """calls mincresample with the specified options The inFile and likeFile can be in one of two styles. The first argument can be an instance of RegistrationPipeFH. In this case the last volume in that instance (i.e. inFile.lastBasevol) will be resampled and the output will be determined accordingly. Alternatively, the inFile can be a string representing a filename, in which case the output and logfile will be set based on the inFile name. inFile is required, everything else optional This class assuming use of the most commonly used flags (-2, -clobber, -like, -transform) Any commands above and beyond the standard will be read in from argarray argarray could contain inFile and/or output files """ argArray = kwargs.pop("argArray", None) if not argArray: CmdStage.__init__(self, ["mincresample"]) else: CmdStage.__init__(self, ["mincresample"] + argArray) try: #MF TODO: What if we don't want to use lastBasevol? if isFileHandler(inFile, targetFile): self.inFile = self.getFileToResample(inFile, **kwargs) self.targetFile = targetFile.getLastBasevol() likeFile=kwargs.pop("likeFile", None) if likeFile: if isFileHandler(likeFile): self.likeFile = likeFile.getLastBasevol() else: print "likeFile must be RegistrationPipeFH or RegistrationFHBase." raise invert = False for cmd in self.cmd: if fnmatch.fnmatch(cmd, "*-invert*"): invert = True break xfm = kwargs.pop("transform", None) if xfm: self.cxfm = xfm else: if invert: self.cxfm = targetFile.getLastXfm(inFile) else: self.cxfm = inFile.getLastXfm(targetFile) self.outputLocation=kwargs.pop("outputLocation", None) if not self.outputLocation: self.outputLocation=inFile else: if not isFileHandler(self.outputLocation): print "outputLocation must be RegistrationPipeFH or RegistrationFHBase." raise default = kwargs.pop("defaultDir", None) if not default: defaultDir = "resampled" else: defaultDir = default """If an output file is specified, then use it, else create a default file name. Note: The output file passed in must be a full path.""" output = kwargs.pop("output", None) if not output: self.outfile = self.setOutputFile(self.outputLocation, defaultDir) else: self.outfile = output self.logFile = fh.logFromFile(self.outputLocation.logDir, self.outfile) else: self.inFile = inFile self.targetFile = targetFile self.likeFile = kwargs.pop("likeFile", None) self.cxfm = kwargs.pop("transform", None) self.outfile=kwargs.pop("output", None) logFile=kwargs.pop("logFile", None) if not logFile: self.logFile = fh.logFromFile(abspath(curdir), self.outfile) else: self.logFile = logFile except: print "Failed in putting together resample command" print "Unexpected error: ", sys.exc_info() self.addDefaults() self.finalizeCommand() self.setName() if isFileHandler(inFile, targetFile): self.setLastResampledFile()
def __init__(self, inSource, inTarget, output=None, logFile=None, defaultDir="transforms", blur=None, gradient=False, linearparam="nlin", source_mask=None, target_mask=None, iterations=40, step=0.5, transform=None, weight=0.8, stiffness=0.98, similarity=0.8, w_translations=0.4, w_rotations=0.0174533, w_scales=0.02, w_shear=0.02, simplex=1, optimization="-use_simplex", useMask=True): #MF TODO: Specify different w_translations, rotations, scales shear in each direction? # Now assumes same in all directions # Go to more general **kwargs? """an efficient way to add a minctracc call to a pipeline The constructor needs two inputFile arguments, the source and the target for the registration, and multiple optional arguments for specifying parameters. The source and the target can be specified as either RegistrationPipeFH instances or as strings representing filenames. In the latter case an output and a logfile filename are required as well (these are filled in automatically in the case of RegistrationPipeFH instances.) """ CmdStage.__init__(self, None) #don't do any arg processing in superclass try: if isFileHandler(inSource, inTarget): """ if blur = None, getBlur returns lastblur if gradient is true, getBlur returns gradient instead of blur if blur = -1, lastBaseVol is returned and gradient is ignored. self.transform will be None if there is no previous transform between input and target. If this is the case, lsq6 and lsq12 defaults are added in the setTransforms function """ self.source = inSource.getBlur(blur, gradient) self.target = inTarget.getBlur(blur, gradient) self.transform = inSource.getLastXfm(inTarget) """If no output transform is specified, use registerVolume to create a default. If an output transform name is specified, use this as the output, and add it as the last xfm between source and target. Note: The output file passed in must be a full path.""" if not output: outputXfm = inSource.registerVolume(inTarget, defaultDir) self.output = outputXfm else: self.output = output inSource.addAndSetXfmToUse(inTarget, self.output) outputXfm = output self.logFile = fh.logFromFile(inSource.logDir, outputXfm) self.useMask = useMask if self.useMask: self.source_mask = inSource.getMask() self.target_mask = inTarget.getMask() else: self.source = inSource self.target = inTarget self.output = output if not logFile: self.logFile = fh.logFromFile(abspath(curdir), output) else: self.logFile = logFile self.transform = transform self.useMask = useMask if self.useMask: self.source_mask = source_mask self.target_mask = target_mask except: print "Failed in putting together minctracc command." print "Unexpected error: ", sys.exc_info() self.linearparam = linearparam self.iterations = str(iterations) self.lattice_diameter = str(step * 3.0) self.step = str(step) self.weight = str(weight) self.stiffness = str(stiffness) self.similarity = str(similarity) self.w_translations = str(w_translations) self.w_rotations = str(w_rotations) self.w_scales = str(w_scales) self.w_shear = str(w_shear) self.simplex = str(simplex) self.optimization = str(optimization) self.addDefaults() self.finalizeCommand() self.setTransform() self.setName() self.colour = "red"
def __init__(self, inFile, targetFile, **kwargs): """calls mincresample with the specified options The inFile and likeFile can be in one of two styles. The first argument can be an instance of RegistrationPipeFH. In this case the last volume in that instance (i.e. inFile.lastBasevol) will be resampled and the output will be determined accordingly. Alternatively, the inFile can be a string representing a filename, in which case the output and logfile will be set based on the inFile name. inFile is required, everything else optional This class assuming use of the most commonly used flags (-2, -clobber, -like, -transform) Any commands above and beyond the standard will be read in from argarray argarray could contain inFile and/or output files """ argArray = kwargs.pop("argArray", None) if not argArray: CmdStage.__init__(self, ["mincresample"]) else: CmdStage.__init__(self, ["mincresample"] + argArray) try: #MF TODO: What if we don't want to use lastBasevol? if isFileHandler(inFile, targetFile): self.inFile = self.getFileToResample(inFile, **kwargs) self.targetFile = targetFile.getLastBasevol() likeFile = kwargs.pop("likeFile", None) if likeFile: if isFileHandler(likeFile): self.likeFile = likeFile.getLastBasevol() else: print "likeFile must be RegistrationPipeFH or RegistrationFHBase." raise invert = False for cmd in self.cmd: if fnmatch.fnmatch(cmd, "*-invert*"): invert = True break xfm = kwargs.pop("transform", None) if xfm: self.cxfm = xfm else: if invert: self.cxfm = targetFile.getLastXfm(inFile) else: self.cxfm = inFile.getLastXfm(targetFile) self.outputLocation = kwargs.pop("outputLocation", None) if not self.outputLocation: self.outputLocation = inFile else: if not isFileHandler(self.outputLocation): print "outputLocation must be RegistrationPipeFH or RegistrationFHBase." raise default = kwargs.pop("defaultDir", None) if not default: defaultDir = "resampled" else: defaultDir = default """If an output file is specified, then use it, else create a default file name. Note: The output file passed in must be a full path.""" output = kwargs.pop("output", None) if not output: self.outfile = self.setOutputFile(self.outputLocation, defaultDir) else: self.outfile = output self.logFile = fh.logFromFile(self.outputLocation.logDir, self.outfile) else: self.inFile = inFile self.targetFile = targetFile self.likeFile = kwargs.pop("likeFile", None) self.cxfm = kwargs.pop("transform", None) self.outfile = kwargs.pop("output", None) logFile = kwargs.pop("logFile", None) if not logFile: self.logFile = fh.logFromFile(abspath(curdir), self.outfile) else: self.logFile = logFile except: print "Failed in putting together resample command" print "Unexpected error: ", sys.exc_info() self.addDefaults() self.finalizeCommand() self.setName() if isFileHandler(inFile, targetFile): self.setLastResampledFile()
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 __init__(self, inputFiles, createMontage=True, montageOutPut=None, scalingFactor=20, message="lsq6"): self.p = Pipeline() self.individualImages = [] self.individualImagesLabeled = [] self.message = message if createMontage and montageOutPut == None: print("\nError: createMontage is specified in createQualityControlImages, but no output name for the montage is provided. Exiting...\n") sys.exit() # for each of the input files, run a mincpik call and create # a triplane image. for inFile in inputFiles: if isFileHandler(inFile): # create command using last base vol inputToMincpik = inFile.getLastBasevol() outputMincpik = createBaseName(inFile.tmpDir, removeBaseAndExtension(inputToMincpik) + "_QC_image.png") cmd = ["mincpik", "-clobber", "-scale", scalingFactor, "-triplanar", InputFile(inputToMincpik), OutputFile(outputMincpik)] mincpik = CmdStage(cmd) mincpik.setLogFile(LogFile(logFromFile(inFile.logDir, outputMincpik))) self.p.addStage(mincpik) self.individualImages.append(outputMincpik) # we should add a label to each of the individual images # so it will be easier for the user to identify what # which images potentially fail outputConvert = createBaseName(inFile.tmpDir, removeBaseAndExtension(inputToMincpik) + "_QC_image_labeled.png") cmdConvert = ["convert", "-label", inFile.basename, InputFile(outputMincpik), OutputFile(outputConvert)] convertAddLabel = CmdStage(cmdConvert) convertAddLabel.setLogFile(LogFile(logFromFile(inFile.logDir, outputConvert))) self.p.addStage(convertAddLabel) self.individualImagesLabeled.append(outputConvert) # if montageOutput is specified, create the overview image if createMontage: cmdmontage = ["montage", "-geometry", "+2+2"] \ + map(InputFile, self.individualImagesLabeled) + [OutputFile(montageOutPut)] montage = CmdStage(cmdmontage) montage.setLogFile(splitext(montageOutPut)[0] + ".log") message_to_print = "\n* * * * * * *\nPlease consider the following verification " message_to_print += "image, which shows a slice through all input " message_to_print += "files %s. " % self.message message_to_print += "\n%s\n" % (montageOutPut) message_to_print += "* * * * * * *\n" # the hook needs a return. Given that "print" does not return # anything, we need to encapsulate the print statement in a # function (which in this case will return None, but that's fine) def printMessageForMontage(): print(message_to_print) montage.finished_hooks.append( lambda : printMessageForMontage()) self.p.addStage(montage)
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 __init__(self, inSource, inTarget, output=None, logFile=None, defaultDir="transforms", blur=[-1, 0.056], gradient=[False, True], target_mask=None, #ANTS only uses one mask similarity_metric=["CC", "CC"], weight=[1,1], iterations="100x100x100x150", radius_or_histo=[3,3], transformation_model="SyN[0.1]", regularization="Gauss[2,1]", useMask=True): CmdStage.__init__(self, None) #don't do any arg processing in superclass try: if isFileHandler(inSource, inTarget): """Same defaults as minctracc class: blur = None --> return lastblur gradient = True --> return gradient instead of blur if blur = -1 --> lastBaseVol returned and gradient ignored""" self.source = [] self.target = [] # Need to check that length of blur, gradient, similarity, weight # and radius_or_histo are the same self.checkArrayLengths(blur, gradient, similarity_metric, weight, radius_or_histo) for i in range(len(blur)): self.source.append(inSource.getBlur(blur[i], gradient[i])) self.target.append(inTarget.getBlur(blur[i], gradient[i])) """If no output transform is specified, use registerVolume to create a default. If an output transform name is specified, use this as the output, and add it as the last xfm between source and target. Note: The output file passed in must be a full path.""" if not output: outputXfm = inSource.registerVolume(inTarget, defaultDir) self.output = outputXfm else: self.output = output inSource.addAndSetXfmToUse(inTarget, self.output) self.logFile = fh.logFromFile(inSource.logDir, self.output) self.useMask=useMask if self.useMask: self.target_mask = inTarget.getMask() else: self.source = inSource self.target = inTarget #MF TODO: Need to find a way to specify multiple source and targets #based on blur and gradient self.output = output if not logFile: self.logFile = fh.logFromFile(abspath(curdir), output) else: self.logFile = logFile self.useMask=useMask if self.useMask: self.target_mask = target_mask except: print "Failed in putting together mincANTS command." print "Unexpected error: ", sys.exc_info() self.similarity_metric = similarity_metric self.weight = weight self.iterations = iterations self.radius_or_histo = radius_or_histo """Single quotes needed on the command line for transformation_model and regularization """ self.transformation_model = "'" + transformation_model + "'" self.regularization = "'" + regularization + "'" self.addDefaults() self.finalizeCommand() self.setName() self.colour = "red"