def getACE2Path(self): exename = 'ace2correct.exe' ace2exe = subprocess.Popen("which "+exename, shell=True, stdout=subprocess.PIPE).stdout.read().strip() if not os.path.isfile(ace2exe): ace2exe = os.path.join(apParam.getAppionDirectory(), 'bin', exename) if not os.path.isfile(ace2exe): apDisplay.printError(exename+" was not found at: "+apParam.getAppionDirectory()) return ace2exe
def getCtfProgPath(self): exename = "ctffind4" ctfprgmexe = subprocess.Popen("which "+exename, shell=True, stdout=subprocess.PIPE).stdout.read().strip() if not os.path.isfile(ctfprgmexe): ctfprgmexe = os.path.join(apParam.getAppionDirectory(), 'bin', exename) if not os.path.isfile(ctfprgmexe): apDisplay.printError(exename+" was not found at: "+apParam.getAppionDirectory()) apDisplay.printMsg("Running program %s"%(exename)) return ctfprgmexe
def getSignaturePath(): unames = os.uname() if unames[-1].find('64') >= 0: exename = 'signature64.exe' else: exename = 'signature32.exe' signaturepath = os.path.join(apParam.getAppionDirectory(), 'bin', exename) if not os.path.isfile(signaturepath): signaturepath = subprocess.Popen("which "+exename, shell=True, stdout=subprocess.PIPE).stdout.read().strip() if not os.path.isfile(signaturepath): apDisplay.printError(exename+" was not found at: "+apParam.getAppionDirectory()) return signaturepath
def getFindEMPath(): unames = os.uname() if True: #if unames[-1].find('64') >= 0: exename = 'automatch' else: apDisplay.printError(exename+" not implemented for 32 bit computer") findempath = os.path.join(apParam.getAppionDirectory(), 'bin', exename) if not os.path.isfile(findempath): findempath = subprocess.Popen("which "+exename, shell=True, stdout=subprocess.PIPE).stdout.read().strip() if not os.path.isfile(findempath): apDisplay.printError(exename+" was not found at: "+apParam.getAppionDirectory()) return findempath
def getFindEMPath(): unames = os.uname() if unames[-1].find('64') >= 0: # For FindEM2 # exename = '/ami/sw/packages/FindEM2/FindEM2_V1.00.exe' exename = 'findem64.exe' else: exename = 'findem32.exe' findempath = os.path.join(apParam.getAppionDirectory(), 'bin', exename) if not os.path.isfile(findempath): findempath = subprocess.Popen("which "+exename, shell=True, stdout=subprocess.PIPE).stdout.read().strip() if not os.path.isfile(findempath): apDisplay.printError(exename+" was not found at: "+apParam.getAppionDirectory()) return findempath
def _addDefaultParams(self): ### new system, global params self.params['functionname'] = self.functionname self.params['appiondir'] = apParam.getAppionDirectory() ### classic methods self.params['functionLog']=None self.defaultparams = {}
def getPrototypeParamFile(outparamfile): #TODO: expand on this later appiondir=apParam.getAppionDirectory() origparamfile=os.path.join(appiondir,'appionlib','data','protomo.param') newparamfile=os.path.join(os.getcwd(),outparamfile) shutil.copyfile(origparamfile,newparamfile)
def getCtfProgPath(self): unames = os.uname() exename = "ctffind" if self.params['ctftilt'] is True: exename = "ctftilt" if unames[-1].find('64') >= 0: exename += '64.exe' else: exename += "3.exe" ctfprgmexe = subprocess.Popen("which "+exename, shell=True, stdout=subprocess.PIPE).stdout.read().strip() if not os.path.isfile(ctfprgmexe): ctfprgmexe = os.path.join(apParam.getAppionDirectory(), 'bin', exename) if not os.path.isfile(ctfprgmexe): apDisplay.printError(exename+" was not found at: "+apParam.getAppionDirectory()) apDisplay.printMsg("Running program %s"%(exename)) return ctfprgmexe
def runAffinityPropagation(self, alignedstack): ### Get initial correlation values ### this is really, really slow similarfile, simlist = self.fillSimilarityMatrix(alignedstack) ### Preference value stats preffile = self.setPreferences(simlist) ### run apcluster.exe program outfile = "clusters.out" apDisplay.printMsg("Run apcluster.exe program") apclusterexe = os.path.join(apParam.getAppionDirectory(), "bin/apcluster.exe") apFile.removeFile(outfile) clustercmd = apclusterexe+" "+similarfile+" "+preffile+" "+outfile clusttime = time.time() proc = subprocess.Popen(clustercmd, shell=True) proc.wait() apDisplay.printMsg("apCluster time: "+apDisplay.timeString(time.time()-clusttime)) if not os.path.isfile(outfile): apDisplay.printError("apCluster did not run") ### Parse apcluster output file: clusters.out apDisplay.printMsg("Parse apcluster output file: "+outfile) clustf = open(outfile, "r") ### each line is the particle and the number is the class partnum = 0 classes = {} for line in clustf: sline = line.strip() if sline: partnum += 1 classnum = int(sline) if not classnum in classes: classes[classnum] = [partnum,] else: classes[classnum].append(partnum) clustf.close() apDisplay.printMsg("Found %d classes"%(len(classes.keys()))) ### Create class averages classavgdata = [] classnames = classes.keys() classnames.sort() for classnum in classnames: apDisplay.printMsg("Class %d, %d members"%(classnum, len(classes[classnum]))) #clsf = open('subcls%04d.lst'%(classnum), 'w') #for partnum in classes[classnum]: # clsf.write("%d\n"%(partnum)) #clsf.close() classdatalist = apImagicFile.readParticleListFromStack(alignedstack, classes[classnum], msg=False) classdatarray = numpy.asarray(classdatalist) classavgarray = classdatarray.mean(0) #mrc.write(classavgarray, 'subcls%04d.mrc'%(classnum)) classavgdata.append(classavgarray) apFile.removeStack("classaverage-"+self.timestamp+".hed") apImagicFile.writeImagic(classavgdata, "classaverage-"+self.timestamp+".hed") return classes
def getSnapPath(): chimsnappath = os.path.join(apParam.getAppionDirectory(), "appionlib", "apChimSnapshot.py") if not os.path.isfile(chimsnappath): libdir = os.path.dirname(__file__) chimsnappath = os.path.join(libdir, "apChimSnapshot.py") if not os.path.isfile(chimsnappath): apDisplay.printError("Could not find file: apChimSnapshot.py") return chimsnappath
def __init__(self,optargs=sys.argv[1:],quiet=False,useglobalparams=True,maxnproc=None): """ Starts a new function and gets all the parameters """ ### setup some expected values self.successful_run = False self.params = {} sys.stdout.write("\n\n") self.quiet = quiet self.maxnproc = maxnproc self.startmem = mem.active() self.t0 = time.time() self.createDefaultStats() self.timestamp = apParam.makeTimestamp() self.argdict = {} self.optdict = {} apDisplay.printMsg("Time stamp: "+self.timestamp) self.functionname = apParam.getFunctionName(sys.argv[0]) apDisplay.printMsg("Function name: "+self.functionname) self.appiondir = apParam.getAppionDirectory() apDisplay.printMsg("Appion directory: "+self.appiondir) self.parsePythonPath() # loadavg = os.getloadavg()[0] # if loadavg > 2.0: # apDisplay.printMsg("Load average is high "+str(round(loadavg,2))) # loadsquared = loadavg*loadavg # time.sleep(loadavg) # apDisplay.printMsg("New load average "+str(round(os.getloadavg()[0],2))) self.setLockname('lock') ### setup default parser: run directory, etc. self.setParams(optargs,useglobalparams) #if 'outdir' in self.params and self.params['outdir'] is not None: # self.params['rundir'] = self.params['outdir'] self.checkConflicts() if useglobalparams is True: self.checkGlobalConflicts() ### setup run directory self.setProcessingDirName() self.setupRunDirectory() ### Start pool of threads to run subprocesses. ### Later you will use self.process_launcher.launch(...) to ### put commands into the queue. ### There is currently a timeout built into it that will cause ### the threads to die if they have no tasks after 10 seconds. self.process_launcher = apThread.ProcessLauncher(2, self.params['rundir']) ### write function log self.logfile = apParam.writeFunctionLog(sys.argv, msg=(not self.quiet)) ### any custom init functions go here self.onInit()
def getRMeasurePath(): unames = os.uname() if unames[-1].find("64") >= 0: exename = "rmeasure64.exe" else: exename = "rmeasure32.exe" rmeasexe = subprocess.Popen("which " + exename, shell=True, stdout=subprocess.PIPE).stdout.read().strip() if not os.path.isfile(rmeasexe): rmeasexe = os.path.join(apParam.getAppionDirectory(), "bin", exename) if not os.path.isfile(rmeasexe): exename = "rmeasure.exe" rmeasexe = subprocess.Popen("which " + exename, shell=True, stdout=subprocess.PIPE).stdout.read().strip() if not os.path.isfile(rmeasexe): exename = "rmeasure" rmeasexe = subprocess.Popen("which " + exename, shell=True, stdout=subprocess.PIPE).stdout.read().strip() if not os.path.isfile(rmeasexe): apDisplay.printWarning(exename + " was not found at: " + apParam.getAppionDirectory()) return None return rmeasexe
def locateAmpFile(self): ### may be ready to use as is ampabspath = os.path.abspath(self.params['ampfile']) if os.path.isfile(ampabspath): return ampabspath ### try to find it in the appion directory appiondir = apParam.getAppionDirectory() ampabspath = os.path.join(appiondir, "appionlib/data", os.path.basename(self.params['ampfile'])) if os.path.isfile(ampabspath): return ampabspath ### can't find it apDisplay.printError("Could not locate amplitude file: %s" % (self.params['ampfile'],))
def createAmpcorBatchFile(infile,params): localinfile = spyder.fileFilter(infile) appiondir = apParam.getAppionDirectory() scriptfile = os.path.join(appiondir, "appionlib/data/enhance.bat") pwscfile = os.path.join(appiondir, "appionlib/data/pwsc.bat") if not os.path.isfile(scriptfile): apDisplay.printError("could not find spider script: "+scriptfile) if not os.path.isfile(pwscfile): apDisplay.printError("could not find spider script: "+pwscfile) inf = open(scriptfile, "r") tmpfile = "out_"+os.path.basename(infile) tmpfile = os.path.join(params['rundir'], tmpfile) localtmpfile = spyder.fileFilter(tmpfile) outfile = "enhance_edit.bat" if os.path.isfile(outfile): apDisplay.printWarning(outfile+" already exists; removing it") time.sleep(2) os.remove(outfile) if os.path.isfile('pwsc.bat'): apDisplay.printWarning(pwscfile+" already exists; replacing it") time.sleep(2) shutil.copyfile(pwscfile, 'pwsc.bat') outf = open(outfile, "w") notdone = True for line in inf: if notdone is False: outf.write(line) else: thr = line[:3] if thr == "x99": outf.write(spiderline(99,params['box'],"box size in pixels")) elif thr == "x98": outf.write(spiderline(98,params['maxfilt'],"filter limit in angstroms")) elif thr == "x80": outf.write(spiderline(80,params['apix'],"pixel size")) elif re.search("^\[vol\]",line): outf.write(spiderline("vol",localinfile,"input density file")) elif re.search("^\[outvol\]",line): outf.write(spiderline("outvol",localtmpfile,"enhanced output file")) elif re.search("^\[scatter\]",line): outf.write(spiderline("scatter",params['ampfile'],"amplitude curve file")) elif re.search("^\[pwsc\]",line): outf.write(spiderline("pwsc","pwsc","scaling script")) elif re.search("^\[applyfen\]",line): outf.write(spiderline("applyfen",os.path.join(appiondir,"appionlib/data/applyfen"),"apply curve to data script")) else: outf.write(line) return tmpfile
def runSpiderBatch(self, localbatch, spiderstack): ### set SPPROC_DIR environment variable spiprocdir = os.path.join(apParam.getAppionDirectory(), "spiderbatch/") ### strip localbatch extension batchheadname = os.path.splitext(localbatch)[0] ###batchheadname = localbatch.split('.')[0] ### run Iterative Classification and Alignment mySpider = spyder.SpiderSession(logo=True, spiderprocdir=spiprocdir, projext=".spi", term=True, verbose=True) mySpider.toSpider("@%s" % batchheadname) mySpider.close() ###output is class averages, variances, particle lists, and alignment parameters ### write aligned stack if not os.path.isfile("apshdoc.spi"): apDisplay.printError("Output alignment parameters file apshdoc.spi does not exist.") else: mySpider = spyder.SpiderSession(logo=True, spiderprocdir=spiprocdir, projext=".spi", term=True, verbose=True) mySpider.toSpider("@rtmr", #spider script for rotate,shift,mirror "apshdoc", #input transformation doc "%s@******" % spyder.fileFilter(spiderstack), #input particles "alignstack@******") #output aligned particles mySpider.close()
def getPrototypeParamPath(): appiondir=apParam.getAppionDirectory() origparamfile=os.path.join(appiondir,'appionlib','data','protomo.param') return origparamfile
def setupBatchFile(self, spiderstack, templatestack, orientref): """ sets up Ed's batch script to run """ ### write particle selection file partsel = os.path.join(self.params['rundir'], "partlist.spi") f = open(partsel, "w") for i in range(self.params['numpart']): f.write("%06d 1 %06d \n"%(i+1, i+1)) f.close() refsel = os.path.join(self.params['rundir'], "reflist.spi") f = open(refsel, "w") for i in range(self.params['numtemplate']): f.write("%03d 1 %03d \n"%(i+1, i+1)) f.close() ### read / write batch file globalbatch = os.path.join(apParam.getAppionDirectory(), "spiderbatch/IterativeClassifyAlign.spi") localbatch = os.path.join(self.params['rundir'], "IterativeClassifyAlign.spi") gf = open(globalbatch, "r") lf = open(localbatch, "w") modify = True for line in gf: if modify is True: #flag for line is in header ### Input files ### if re.match("\<pcltmpl\>", line): ### template for spider particle names lf.write("<pcltmpl>"+spyder.fileFilter(spiderstack)+"@****** \n") elif re.match("\<pcllist\>", line): ### list of particle numbers lf.write("<pcllist>"+spyder.fileFilter(partsel)+"\n") elif re.match("\<reftmpl\>", line): ### template for reference image names lf.write("<reftmpl>"+spyder.fileFilter(templatestack)+"@*** \n") elif re.match("\<reflist\>", line): ### list of reference numbers lf.write("<reflist>"+spyder.fileFilter(refsel)+"\n") elif re.match("\<ref\>", line): ### orientation reference lf.write("<ref>"+spyder.fileFilter(orientref)+"\n") ### Parameters ### elif re.match("23 ;pixels", line): ### particle radius in pixels pixrad = int(self.params['partrad']/self.stack['apix']/self.params['bin']) lf.write("%d ;pixels\n"%(pixrad)) elif re.match("10 ;iterations", line): ### number of ref-based iterations lf.write("%d ;iterations\n"%(self.params['numiter'])) #elif re.match("1 ;free-align rounds", line): ### number of ref-free alignments per class #lf.write("%d ;free-align rounds\n"%(self.params['freealigns'])) elif re.match("0 ;processors", line): ### number of processors lf.write("%d ;processors\n"%(self.params['nproc'])) elif re.match("\<dir\>", line): ### sub-directory, we use "." lf.write("<dir>.\n") elif re.search("- END BATCH HEADER -", line): ### reached last line of batch header ### modify = False else: lf.write(line) else: lf.write(line) return localbatch
from appionlib import apDog from appionlib import apFile from appionlib import apPeaks from appionlib import apImage from appionlib import apParam from appionlib import apDisplay from appionlib.apTilt import apTiltTransform version = "2.0b13" releasedate = "July 21, 2010" this_file = inspect.currentframe().f_code.co_filename logoimage = os.path.abspath(os.path.join(os.path.dirname(this_file), "../../data/tplogo.png")) if not os.path.isfile(logoimage): logoimage = os.path.abspath(os.path.join(os.path.dirname(this_file), "../data/tplogo.png")) if not os.path.isfile(logoimage): logoimage = os.path.join(apParam.getAppionDirectory(), "appionlib/data/tplogo.png") citation = """ Voss NR, Yoshioka CK, Radermacher M, Potter CS, and Carragher B. "DoG Picker and TiltPicker: software tools to facilitate particle selection in single particle electron microscopy." J Struct Biol. 2009 v166(2): pp. 205-13. http://dx.doi.org/10.1016/j.jsb.2009.01.004 """ citationlogo = """ #### # ### Voss NR, Yoshioka CK, Radermacher M, Potter CS, and Carragher B. # # # "DoG Picker and TiltPicker: software tools to facilitate particle selection ##### in single particle electron microscopy." # J Struct Biol. 2009 v166(2): pp. 205-13. # http://dx.doi.org/10.1016/j.jsb.2009.01.004 """
def __init__(self,optargs=sys.argv[1:],quiet=False,useglobalparams=True,maxnproc=None): """ Starts a new function and gets all the parameters """ ### setup some expected values self.successful_run = False self.clusterjobdata = None self.params = {} sys.stdout.write("\n\n") self.quiet = quiet self.maxnproc = maxnproc self.startmem = mem.active() self.t0 = time.time() self.createDefaultStats() self.timestamp = apParam.makeTimestamp() self.argdict = {} self.optdict = {} apDisplay.printMsg("Time stamp: "+self.timestamp) self.functionname = apParam.getFunctionName(sys.argv[0]) apDisplay.printMsg("Function name: "+self.functionname) self.appiondir = apParam.getAppionDirectory() apDisplay.printMsg("Appion directory: "+self.appiondir) hostname = apParam.getHostname() apDisplay.printMsg("Processing hostname: "+hostname) self.parsePythonPath() # loadavg = os.getloadavg()[0] # if loadavg > 2.0: # apDisplay.printMsg("Load average is high "+str(round(loadavg,2))) # loadsquared = loadavg*loadavg # time.sleep(loadavg) # apDisplay.printMsg("New load average "+str(round(os.getloadavg()[0],2))) self.setLockname('lock') ### setup default parser: run directory, etc. self.setParams(optargs,useglobalparams) #if 'outdir' in self.params and self.params['outdir'] is not None: # self.params['rundir'] = self.params['outdir'] ### setup correct database after we have read the project id if 'projectid' in self.params and self.params['projectid'] is not None: apDisplay.printMsg("Using split database") # use a project database newdbname = apProject.getAppionDBFromProjectId(self.params['projectid']) sinedon.setConfig('appiondata', db=newdbname) apDisplay.printColor("Connected to database: '"+newdbname+"'", "green") ### check if user wants to print help message if 'commit' in self.params and self.params['commit'] is True: apDisplay.printMsg("Committing data to database") else: apDisplay.printWarning("Not committing data to database") self.checkConflicts() if useglobalparams is True: self.checkGlobalConflicts() ### setup run directory self.setProcessingDirName() self.setupRunDirectory() ### Start pool of threads to run subprocesses. ### Later you will use self.process_launcher.launch(...) to ### put commands into the queue. ### There is currently a timeout built into it that will cause ### the threads to die if they have no tasks after 10 seconds. self.process_launcher = apThread.ProcessLauncher(2, self.params['rundir']) ### write function log self.logfile = apParam.writeFunctionLog(sys.argv, msg=(not self.quiet)) ### upload command line parameters to database self.uploadScriptData() ### any custom init functions go here self.onInit()
def checkConflicts(self): self.appiondir = apParam.getAppionDirectory() ### necessary input values if self.params['threedfile'] is None and self.params['modelid'] is None: apDisplay.printError('either threed .mrc file or modelid was not defined') if self.params['threedfile'] is not None and self.params['modelid'] is not None: apDisplay.printError('please specify a single .mrc file (i.e. threedfile or modelid)') if self.params['box'] is None and self.params['modelid'] is None: apDisplay.printError('boxsize of the output stack not specified') if self.params['apix'] is None and self.params['modelid'] is None: apDisplay.printError('angstroms per pixel of the input model not specified') ### radius defaulted to 0.5 if self.params['radius'] is None: self.params['radius'] = self.params['box'] / 2 if self.params['radius'] > self.params['box']/2: apDisplay.printError('radius of particle (in pixels) must be smaller than 1/2*boxsize of model') if self.params['radius'] > 0 and self.params['radius'] < 1: apDisplay.printError('radius must be specified in pixels') ### get session info if self.params['sessionname'] is None: split = self.params['rundir'].split("/") self.params['sessionname'] = split[4] ### make sure that the defoci are positive (underfocus) and in microns self.params['df1'] *= 10**-6 self.params['df2'] *= 10**-6 if self.params['df1'] < 0: apDisplay.printError('defocus value is negative! specify positive (underfocus) values') if self.params['df2'] < 0: apDisplay.printError('defocus value is negative! specify positive (underfocus) values') ### check defocus group values if self.params['defocus_groups'] is not None: self.defmin = float(self.params['defocus_groups'].split(",")[0]) self.defmax = float(self.params['defocus_groups'].split(",")[1]) self.defint = float(self.params['defocus_groups'].split(",")[2]) if self.defmin is None or self.defmax is None or self.defint is None: apDisplay.printError("all defocus group values must be specified, e.g. --defocus_groups=1,3,0.1") ### make sure that only one type of ace2correction is specified if self.params['ace2correct'] is True and self.params['ace2correct_rand'] is True: apDisplay.printError('Please specify only 1 type of ace2 correction') if self.params['ace2correct_std'] >= 0.5 or self.params['ace2correct_std'] <= 0: apDisplay.printError("Ace2correct standard deviation specified too high, please use value between 0 < std < 0.5") if self.params['ace2estimate'] is True and self.params['ace2correct'] is False: apDisplay.printError("ACE2 estimation should only be used if you're doing correction as well, please use both ace2correct and ace2estimate") ### make sure amplitude correction file exists if self.params['envelopefile'] is None: self.params['envelopefile'] = os.path.join(apParam.getAppionDirectory(), "appionlib/data/radial-envelope.spi") ### set cs value & make sure that it's in millimeters if self.params['cs'] is None: self.params['cs'] = apInstrument.getCsValueFromSession(self.getSessionData()) self.params['cs'] = self.params['cs'] if self.params['cs'] > 0: apDisplay.printWarning("non-zero cs value is untested and may not be properly applied. Consider setting to 0") apDisplay.printColor("cs value: %.3f" % self.params['cs'], "cyan") return
def uploadScriptData(self): """ Using tables to track program run parameters in a generic fashion inspired by Roberto Marabini and Carlos Oscar Sanchez Sorzano from the Xmipp team/Carazo lab """ apDisplay.printMsg("Uploading ScriptData....") prognameq = appiondata.ScriptProgramName() prognameq['name'] = self.functionname userq = appiondata.ScriptUserName() userdict = apParam.getUserDict() if userdict: userq['name'] = userdict['username'] userq['uid'] = userdict['uid'] userq['gid'] = userdict['gid'] userq['fullname'] = userdict['fullname'] unixshell = userdict['unixshell'] else: userq['name'] = "unknown" unixshell = None hostq = appiondata.ScriptHostName() hostq['name'] = apParam.getHostname() hostq['ip'] = apParam.getHostIP() hostq['system'] = apParam.getSystemName() hostq['distro'] = apParam.getLinuxDistro() hostq['nproc'] = apParam.getNumProcessors() hostq['memory'] = apParam.getTotalMemory() hostq['cpu_vendor'] = apParam.getCPUVendor() hostq['gpu_vendor'] = apParam.getGPUVendor() hostq['arch'] = apParam.getMachineArch() progrunq = appiondata.ScriptProgramRun() progrunq['runname'] = self.params['runname'] progrunq['progname'] = prognameq progrunq['username'] = userq progrunq['hostname'] = hostq progrunq['unixshell'] = unixshell progrunq['rundir'] = appiondata.ApPathData(path=os.path.abspath(self.params['rundir'])) progrunq['job'] = self.getClusterJobData() appiondir = apParam.getAppionDirectory() ### get appion version/subversion revision progrunq['revision'] = None versionfile = os.path.join(appiondir, "appionlib/version.txt") if os.path.isfile(versionfile): f = open(versionfile, 'r') line = f.readline() f.close() sline = line.strip() progrunq['revision'] = sline if os.path.isdir(os.path.join(appiondir, ".svn")): if progrunq['revision'] is None: progrunq['revision'] = version.getSubversionRevision(appiondir) else: progrunq['revision'] += "-"+version.getSubversionRevision(appiondir) if not progrunq['revision']: progrunq['revision'] = 'unknown' apDisplay.printMsg("Running Appion version '%s'"%(progrunq['revision'])) progrunq['appion_path'] = appiondata.ApPathData(path=os.path.abspath(appiondir)) for paramname in self.params.keys(): paramnameq = appiondata.ScriptParamName() paramnameq['name'] = paramname paramnameq['progname'] = prognameq paramvalueq = appiondata.ScriptParamValue() paramvalueq['value'] = str(self.params[paramname]) usage = self.usageFromParamDest(paramname, self.params[paramname]) #print "usage: ", usage paramvalueq['usage'] = usage paramvalueq['paramname'] = paramnameq paramvalueq['progrun'] = progrunq if usage is not None: paramvalueq.insert()