def parseToReport( self, fileName, keyTag, header = None, unique = True):
        '''
        @var fileName: name of flat (delimited) in text format to be parsed
        @type fileName: String
        @var keyTag: ID of column to be used for report key row
        @type keyTag: String
        @summary: 
        Primary Function
        Parses flat file returns report object.
        '''
    
        if header != None:
            self.setHeader(header)
                  
        result = Report()
        self.startFile(fileName)
        d = self.getTagedLine()
        
        while d != None:
            if d != "":
                keyName = d[keyTag]
                del d[keyTag]
                
                for valueTag in d.keys():
                    v = d[valueTag]
                    result.addElement(keyName,valueTag,v)

            d = self.getTagedLine()
            
        self.closeFile()
        return result
 def analyseRecombindationResults(self,oligoReport,featureList,outputFile="oligo_recomb_analysis.txt"):
     
     result = Report()
     result.extend(oligoReport)
     rowNames = oligoReport.returnRowNames()
     recordAlignment = SeqRecord(Seq(""))
     recordAlignment.features = featureList
     for rName in rowNames:
         output.write(rName + "\n")
         
         start = float(oligoReport["genomic_start"][rName])
         end = float(oligoReport["genomic_end"][rName])
         oligo = oligoReport["best"][rName]
         
         keyString = "\n(%s,%s) %s\n\n" % (start,end,oligo)
         output.write(keyString)
         
         subFeatures = self._selectFeatures(featureList,start,end)
         index = 0
         for feature in subFeatures:
             matchName = "match_" + str(index)
             id = feature.id
             qValue = feature.qualifiers["query"]
             sValue = feature.qualifiers["subject"]
             matchString = feature.qualifiers["alignment"]
             output.write(id + "\n")
             output.write(matchString + "\n\n")
             result.add(rName,matchName,qValue)
             index += 1
     output.close()
     return result
 def controlMapReport(self,controlMap):
     '''
     convert control map to report object
     '''
     
     report = Report()
     
     for (key,coeffMap) in controlMap.items():
         colName = str(key)
         report.addColumnHash(colName, coeffMap)
         
     return report
 def writeSensitivityLibraryReport(self, senseLibrary, fileName, report=None):
     if report == None:
         report = Report()
     for (libraryName,lib) in senseLibrary.items():
         report.addColumnHash(libraryName, lib)
     
     writer = ReportWriter()
     writer.setFile(fileName)
     code = writer.write(report)
     writer.closeFile()
     
     return code
 def geneControlReport(self,model,controlMap,outputName):
     report = Report()
     geneMap = model.controlMap
     for (target,controls) in geneMap.keys():
         for control in controls:
             report.add(target,control,"control")
     
     writer = ReportWriter()
     writer.setFile(outputName)
     
     writer.write(report)
     writer.closeFile()
 
     return None
 def parseGenericReport(self, fileName, keyTag=None, header = None, unique = True):
     '''
     @var fileName: name of flat (delimited) in text format to be parsed
     @type fileName: String
     @var keyTag: ID of column to be used for report key row
     @type keyTag: String
     @summary: 
     Primary Function
     Parses flat file returns report object.
     '''
     
     result = Report()
     kIndex = None
     lines = open( fileName, 'r' )
     index = 0
     
     for line in lines:
         
         if self.isComment( line ):
             pass
         
         elif self.endLine < index < self.startLine:
             index += 1
             continue
         
         elif index == self.headerLine:
             header = self.parseHeader( line, unique )
             if keyTag in header:
                 kIndex = header.index(keyTag)
                 
         elif self.endLine > index > self.startLine:
             line = line.replace('\n','')
             sLine =self._safeSplit(line)
             if kIndex != None:
                 rName = sLine[kIndex]
             else:
                 rName = str(index)
             for i in range(len(sLine)):
                 if i != kIndex:
                     cName = header[i]
                     value = sLine[i]
                     result.add(rName,cName,value)
                 
         index += 1
         
     lines.close()
     return result
Exemple #7
0
 def getReport(self):        
     report = Report()
     fluxModel = self
     
     reactionNames = fluxModel.network.getOrderedReactionNames()
     reactionMap = fluxModel.network.getReactionMap()
     
     for reactionName in reactionNames:
         reaction = reactionMap[reactionName]
         equation = reaction.getEquation()
         pathway = reaction.getAnnotation("Subsystem")
         name = reaction.getName()#Currently sensitivity values can be too large for control factors.
         report.addElement(reactionName,"name",name)
         report.addElement(reactionName,"equation", equation)
         report.addElement(reactionName,"Subsystem", pathway)
     
     return report
def enzymeBoundaryControl(model,targets,bounds,objectiveName,productionName,searchSize):
    targets = bounds.keys()
    controlNames = model.getControlsForNames(targets)
    eControlMap = model.getEnzymeControlMap()
    
    controlSubSets = combinations(controlNames,searchSize)
    xcontrolSubSets = set(controlSubSets)
    
    result = Report()
    iter = 0
    for icontrolNames in xcontrolSubSets:
        ibounds = {}
        controlTag = ''
        ienzymeNames = model.annotateGeneList(list(icontrolNames))
        ienzymeNames.sort()
        for ieName in ienzymeNames:
            controlTag += "(%s)" % (ieName)
        for icontrolName in icontrolNames:
            itargets = eControlMap[icontrolName]
            for itarget in itargets:
                if itarget in bounds.keys():
                    ibound = bounds[itarget]
                    ibounds[itarget] = ibound
            #print ("control %s => [%s]") % (icontrolName,ibounds)
            pass
        if len(ibounds) == 0:
            continue
        (fluxMap,oflux,pflux) = findBoundaryProduction(model, ibounds, None, objectiveName, productionName)
        print "[%s] objective %s => production %s" % (controlTag, oflux, pflux)
        iter += 1
        #iEnzymeNames = model.annotateGeneList(icontrolNames) 
        #for icontrolName in iEnzymeNames:
        #    result.add(iter, icontrolName, "active")
        result.add(controlTag,"natural",oflux)
        result.add(controlTag,"production",pflux)
    
    return result
Exemple #9
0
def main_function():

    parser = OptionParser()
    
    parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False, help="set verbose mode")
    
    parser.add_option("-c","--config", dest="config", default="redirector.config", help="master configuration file", metavar="FILE")
                  
    parser.add_option("--model_config", dest="modelConfig", default="model.config", help="configuration file", metavar="FILE")
    
    parser.add_option("-n","--configNames", type = "string", dest = "configNames", default = "Default", help = "comma separated list of configuration settings to include", metavar="FILE")
    
    parser.add_option("-m","--modelname", type = "string", dest="modelName", default="", help="name of model from configuration file", metavar="String")
    
    parser.add_option("-b","--bioObjective", type = "string", dest="bioObj", default = 'Biomass', help="name of biological objective reaction", metavar="String")
    
    parser.add_option("-s","--synthObjective", type = "string", dest="synthObj", default='', help="name of synthetic objective reaction", metavar="String")
                       
    parser.add_option("--sn", "--searchNeighborhood", dest = "searchNeighborhood", default = 1, type = int, help = "size of search neighborhood", metavar = "int")
    
    parser.add_option("--iter", "--searchIterations", dest = "iterations", default = 1, type = int, help = "maximum number of iterations, if blank no max", metavar = "int")
    
    parser.add_option("--report", action = "store_true", dest = "isReport", default = False, help = "Write report", metavar = "boolean")
    
    parser.add_option("--pl","--preload", dest = "preload", default = 0, type = int, help = "indicate size of pre-made library to load for faster start", metavar="int")
    
    parser.add_option("--ps", "--preStart", dest = "preStart", default = 0, type = int, help = "start from previous iteration state", metavar = "int")
        
    parser.add_option("--gm", "--GeneMap", action="store_true", dest = "useGeneMap", default = False, help = "Use Gene Map")
    
    parser.add_option("--control", dest="control", default = "flat", help = "control library type, flat,binary,sense", metavar="String")
    
    parser.add_option("--simocontrol", dest="simoControl", default = 1.0, help = "number of simultaneously active controls", metavar="int")
    
    parser.add_option("--section", dest="subSections", default = '', help = "Comma separated list of sections of the model files to use", metavar="String")
        
    parser.add_option("-o", dest="resultDirectory", default = './Result', help = "Directory to store analysis results", metavar="String")
    
    
    # Parse options
    (options,args) = parser.parse_args()    
    config = ReflectionConfig()    
    config.readfp(open("Redirector.config"))

    '''
    0. configure analysis
    '''
    
    configNames = options.configNames.split(",")
    configNames.insert(0,"Redirector Model")
    for name in configNames:
        config.merge(name,"Redirector",append=True)
    
    #----------------------------------------
    # reflect options from configuration
    #----------------------------------------

    config.reflect("Redirector",options)
    config.load("Redirector", options.__dict__,override=False)
    
    #-----------------------------------------
    # Check and Build Storage Directories
    #-----------------------------------------
    
    dataDirectory = config.getValue("Redirector","dataDirectory",classType=''.__class__)
    libraryDirectory = config.getValue("Redirector","libraryDirectory",classType=''.__class__)
    resultsDirectory = config.getValue("Redirector","resultDirectory",classType=''.__class__)
    analysisDirectory = config.getValue("Redirector","analysisDirectory",classType=''.__class__)
    
    if not os.path.exists(dataDirectory):
        raise IOError("unable to find required data directory" % dataDirectory)
    if not os.path.exists(resultsDirectory):
        os.makedirs(resultsDirectory)
    if not os.path.exists(libraryDirectory):
        os.makedirs(libraryDirectory)
    if not os.path.exists(analysisDirectory):
        os.makedirs(analysisDirectory)
    
    #----------------------------
    # Parse Inputs
    #----------------------------

    verbose                     = config.get("Redirector","verbose") 
    modelName                   = config.get("Redirector","modelName")
    objectiveName               = config.get("Redirector","bioObj")
    syntheticObjectiveName      = config.get("Redirector","synthObj")
    searchSize                  = config.get("Redirector","searchNeighborhood")
    searchIter                  = config.get("Redirector","iterations")
    objectiveMinPercent         = float(config.get("Redirector","bioTarget"))
    usePrimeBounds              = config.get("Redirector","primeBounds") == "True"
   
    #----------------------------------------------------
    # Initialize and set values for tools and factories
    #----------------------------------------------------
    
    naturalObjective = {objectiveName:-1.0}
    syntheticObjective = {syntheticObjectiveName:-1.0}
    protectedTargets = set(naturalObjective.keys()).union(syntheticObjective.keys())
    
    if verbose: print "Redirector Version 1.0"
    if verbose: print "Model names: [%s]" % (modelName)
    if verbose: print "Synthetic objective: [%s]" % (syntheticObjectiveName)
    if verbose: print "Parsing data files for [%s]" % (modelName)
    if verbose: print "Search Size [%s] Iterations [%s]" % (searchSize,searchIter)
    
    '''
    I. Parse data files and configuration settings
    '''
    
    if verbose: print "----------------Loading Metabolic Models---------------"
    modelNames = modelName.split(",")        
    modelFactory = ModelFactory()
    config.reflect("Redirector",modelFactory)
    modelFactory.protectedTargets = protectedTargets
    (fluxModel,modelMatrix) = modelFactory.loadModel(modelNames)    
    
    if verbose: print "Removing objectives from target set"
    targets = modelMatrix.targets
    targets = set(targets).difference(protectedTargets)
    if verbose: print "Targets List Size [%s]" % len(targets)
    simControl = options.simoControl
    if verbose: print "Simultaneous Control %s" % simControl
           
    #-------------------------------------------------------------------
    # Pre-discovery of flux bound current not used due to instability
    #-------------------------------------------------------------------
        
    primeFluxBoundaries = {}
    
    boundarySearchSize = 1
    boundaryTargets = targets
    boundaryReportFileName = "rd_flux_boundary_M_%s_t_%s_p_%s_s_%s_analysis.csv" % (modelName,len(targets),objectiveMinPercent,boundarySearchSize)
    fluxBoundariesFile = "ControlLibraries/FluxBounds_M_%s_O_%s_T_%s_S_%s" % (modelName,objectiveName,objectiveMinPercent,syntheticObjectiveName)
    
    naturalFluxBounds = None
    if usePrimeBounds:
        
        print "finding natural flux bounds [%s]" % (usePrimeBounds)
        #return False
        naturalFluxBounds = LinearModelVariableBoundarys(modelMatrix, objectiveName=objectiveName, targets=boundaryTargets, pickleFileName = fluxBoundariesFile, minObjectivePercent=objectiveMinPercent,searchSize=boundarySearchSize)
        print "finding production flux bounds"
        #syntheticFluxBounds = LinearModelVariableBoundarys(modelMatrix, objectiveName=syntheticObjectiveName, targets=boundaryTargets, pickleFileName = fluxBoundariesFile, minObjectivePercent=objectiveMinPercent,searchSize=boundarySearchSize)
        if verbose: print "Prime flux boundaries found."
        
        boundaryReport = Report()
        boundaryReport.addColumnHash(objectiveName, naturalFluxBounds)
        #boundaryReport.addColumnHash(syntheticObjectiveName, syntheticFluxBounds)
        
        writer = ReportWriter()       
        writer.setFile(boundaryReportFileName)
        writer.write(boundaryReport) 
        writer.closeFile()
        
    '''
    II. Generate Control Library(ies)
    '''
    
    if verbose:  print "===============Setting up control libraries================="
    processLibrary = OptimizationControlFactory()
    config.reflect("Redirector",processLibrary)
    
    processLibrary.geneMap = modelMatrix.controlMap
    processLibrary.fluxBounds = primeFluxBoundaries
    processLibrary.naturalObjectiveName = objectiveName
    processLibrary.syntheticObjectiveName = syntheticObjectiveName     
    
    controlLibraries = []
    controlMap = {}
    controlTags = options.control.split(",")
    
    if "sense" in controlTags:
        print "====>Using sensitivity control library"
        (icontrolLibraries, controlMap) = processLibrary.generateControl(modelMatrix,targets,targetsOnly = False)
        icontrolLibraries = processLibrary._filterControl(icontrolLibraries, targets)
        controlLibraries.extend(icontrolLibraries)
            
    if "flat" in controlTags:
        print "====>Using flat control library"
        (icontrolLibraries) = processLibrary.seedTestLibrary(targets, randomize=False)
        controlLibraries.extend(icontrolLibraries)
        
    if "random" in controlTags: 
        print "====>Using random control library"
        (icontrolLibraries) = processLibrary.seedTestLibrary(targets, randomize=True, factor = 2.0)
        controlLibraries.extend(icontrolLibraries)
        
    if "binary" in controlTags:
        print "====>Using binary control library"
        binaryRange =[-3,-2,-1,0]
        icontrolLibraries = processLibrary.generateBinaryControl(targets,binaryRange)
        controlLibraries.extend(icontrolLibraries)
    
    controlReportName = "ControlLibraries/ControlReport_%s_%s_%s_%s.csv" % (options.configNames,objectiveName,syntheticObjectiveName,len(targets))
    processLibrary.controlReport(modelMatrix, controlLibraries, controlMap, targets, controlReportName)
    
    
    print "============Control Constructed============="
    
    #--------------------------------------------------
    #configure Redirector model construction object 
    #--------------------------------------------------
    if verbose: print "==Formulating Framework=="    
    con = ConstructRegulationOptimization()
    config.reflect("Redirector",con)
    con.controlMax = options.searchNeighborhood
    con.newObjective = syntheticObjectiveName
    
    #----------------------------------------
    # Initialize redirector analysis object
    #----------------------------------------
    if verbose: print "==Running Optimization=="
    redirector = OptimizationControlRedirector()
    config.reflect("Redirector",redirector)
    
    redirector.modelFactory = modelFactory
    redirector.con = con
    redirector.controlFactory = processLibrary
    redirector.controlLibraries = controlLibraries
    redirector.primeBounds = naturalFluxBounds
    #redirector.targets = targets
    redirector.rGeneMap = modelMatrix.controlMap
    #redirector.modelName = modelName
    redirector.naturalObjectiveName = objectiveName
    redirector.syntheticObjectiveName = syntheticObjectiveName
    
    
    #--------------------------------------------------------
    # Debugging option which tests addition / removal of 
    # reactions from the objective
    #--------------------------------------------------------
    
    if "toggle0" in options.control.split(","):
        if verbose: print "-----------control test toggle 0-------------------"
        redirector.testDesignOptimization(modelMatrix)
    if "toggle" in options.control.split(","):
        if verbose: print "-----------control test toggle all-------------------"
        redirector.testDesignOptimization(modelMatrix,fullTest=True)
        
    (ltReport,oPredVal,sPredVal,finalCheckValue,fObjective) = redirector.optimizeControl(modelMatrix)
    
    finalPredictionValue = ltReport["flux"]       
    if verbose: print "Final Production: %s" % (finalPredictionValue[syntheticObjectiveName])

    #-----------------------------
    # Write Report
    #----------------------------
       
    if options.isReport:
        
        try:
            print "Writing Full Model Report in %s" % (options.resultDirectory)
            redirector.writeReport(ltReport,fluxModel,oPredVal,sPredVal,searchSize,searchIter,fObjective,resultsDirectory)
        except Exception, e:
            print "Unable to write report: %s" % (e)
        try:
            targetReportName = "Target_Report_M_%s_N_%s_S_%s_K_%s_I_%s.txt" % (modelName,objectiveName,syntheticObjectiveName,options.searchNeighborhood,options.iterations)
            print "Writing Optimization target Report %s" % (targetReportName)
            iteration = options.preStart + options.iterations
            redirector.writeAnnotatedTargets(fObjective, modelMatrix, annotationName = "bnumber", regex="[a-zA-Z0-9\(\)]+", iteration = iteration, oPrediction = oPredVal, nPrediction = finalPredictionValue)
        except:
            print "failed to write %s" % (targetReportName)
    def controlReport(self,model,controlLibraries,controlMap,targets,outputName):
        report = Report()
        controlMapList = {}
        if self.geneMap:
            report.addColumnHash("geneticControl",model.controlMap)
        
        for (name, prefix, coeffMap) in controlLibraries:
            report.addColumnHash(name,coeffMap)
            for (target,value) in coeffMap.items():
                if target not in controlMapList.keys():
                    controlMapList[target] = {}
                if value not in controlMapList[target].keys():
                    controlMapList[target][value] = []
                controlMapList[target][value].append(name) 
        
        rControlMap = {}
        tags = controlMap.keys()
        tags.sort()
        for tag in tags:
            valueSetMap = controlMap[tag]
            report.addColumnHash(tag,valueSetMap)
            for (k,valueSet) in valueSetMap.items():
                if k not in rControlMap.keys():
                    rControlMap[k] = {}
                rValueMap = rControlMap[k]
                for v in valueSet:
                    if v not in rValueMap.keys():
                        rValueMap[v] = []
                    rValueMap[v].append(tag)
                rControlMap[k] = rValueMap

        iControlMapList = {}
        for (key,data) in controlMapList.items():
            if data != None:
                list = data.keys()
                l = reduceVector(list)
                iControlMapList[key] = l

        targetNameMap = {}
        for target in targets:
            targetNameMap[target] = "Target"
    
        report.addColumnHash("control target", targetNameMap)        
        report.addColumnHash("complete list of control Library", controlMapList)    
        report.addColumnHash("control Reduced", iControlMapList)
        report.addColumnHash("complete control discovered", rControlMap)
        writer = ReportWriter()
        writer.setFile(outputName)
        
        writer.write(report)
        writer.closeFile()
        
        return None
Exemple #11
0
 def modelReport(self,dir=1,prediction=None):
     report = Report()
     delta = 1e-6
     for rowName in self.getRowNames():
         rLimit = self.floatLimit(self.getRowLimit(rowName))
         rValues =self.getRowValueMap(rowName)
         rString = self._reportRow(rValues,rLimit,prediction)
         report.addElement(rowName,"Type","row")
         report.addElement(rowName,"Equation",rString)
         rLimitS = "(%s,%s)" % (rLimit[0],rLimit[1])
         report.addElement(rowName,"Limit",rLimitS)
         if prediction != None:
             rValue = self._vectorValue(rValues, prediction)
             rValue = round(rValue,6)
             rValid = rLimit[0]-delta < rValue < rLimit[1] + delta
             report.addElement(rowName,"Value",rValue)
             report.addElement(rowName,"Valid",rValid)
     for colName in self.getColumnNames():
         cLimit = self.floatLimit(self.getColumnLimit(colName))
         cValues =self.getColumnValueMap(colName)
         cString = self._reportRow(cValues,cLimit,prediction)
         report.addElement(colName,"Type","column")
         report.addElement(colName,"Equation",cString)
         if prediction != None:
             if colName in prediction.keys():
                 cValue = prediction[colName]
                 cValid = cLimit[0]-delta < cValue < cLimit[1] + delta
                 report.addElement(colName,"Value",cValue)
                 report.addElement(colName,"Valid",cValid)
         
     return report
    def parseAlignments(self,records,featureLocations):
        result = Report()
        index = 0
        
        logFile = open("oligoLog.txt","w")
        targetMap = {}
        
        for r in records:
            id = r.id

            features = featureLocations[index]
            hits =  len(features)
            genomicStart = features[0].location.start.position
            genomicEnd = features[0].location.end.position
            genomicStrand = features[0].strand
            laggingComplementStrand = self.strandChooser(features[0])
            
            if "alignment" in features[0].qualifiers.keys():
                aMatch = features[0].qualifiers["alignment"]
            else: 
                aMatch = ''
            
            targetMap[id] = (genomicStart + genomicEnd)/2
            
            logFile.write(id+"\n")
            logFile.write(aMatch+"\n")
            #if self.verbose: print aMatch
            
            s = str(r.seq)
            originalString = s
            
            result.add(id,"original", originalString) 
            result.add(id,"hits", hits) 
            result.add(id,"genomic_start", genomicStart) 
            result.add(id,"genomic_end", genomicEnd) 
            result.add(id,"genomic_strand", genomicStrand)
            result.add(id,"match", aMatch)
        
        return result
 def getControlReport(self,genes,targetRecord,sequence,boundary=0,range=1000):
     '''
     Create report of control regions for listed genes
     '''
     result = Report()
     seqProp = RecombinationOligoFactory()
     
     sdata = str(sequence).lower() 
     promoters = {}
     locations = {}
     arrow= ["<-","-","->"]
     
     if self.verbose: print "finding local features"
     
     localFeatures = self.localFeatures(genes,targetRecord,range=range)
 
     if self.verbose: print "features found, creating report"
     
     for feature in genes:
         name = feature.qualifiers["gene"][0]
         locTag = feature.qualifiers["locus_tag"][0]
         start = feature.location.start.position
         end = feature.location.end.position
         strand = feature.strand
         
         result.add(name,"locus_tag",locTag)                                                     
         result.add(name,"gene_start",start)                                                     
         result.add(name,"gene_end",end)                                                     
         result.add(name,"gene_strand",strand)                                                     
         
         if strand == 1:
             loc = start
         if strand == -1:
             loc = end
             
         rbsSeq = self.getSequenceRegion(sdata, loc, 3, boundary, strand)
         oligoStrandRbs = seqProp.strandChooser(feature)
             
         result.add(name,"rbs_start",loc)                                                     
         result.add(name,"rbs_region",rbsSeq)
         result.add(name,"rbs_Oligo_Strand",str(oligoStrandRbs))
         
         iLocalFeatures = localFeatures[name]
                                                    
         count = 0
         
         for tFeature in iLocalFeatures:
             count = count + 1
             tName = tFeature.qualifiers["gene"][0]
             tStart = tFeature.location.start.position
             tEnd = tFeature.location.end.position
             tStrand = tFeature.strand
             oligoStrand = seqProp.strandChooser(tFeature)
             iArrow = arrow[tStrand + 1]
             if tStrand == strand:
                 tSize = -1*tStrand
                 pSeq = self.getSequenceRegion(sdata, tStart, tSize, boundary, strand)
             tag = "%s:[%s %s %s] t[%s] = %s" % (tName,tStart,iArrow,tEnd,oligoStrand,pSeq)
             colName = "promoter_%s" % (count)
             result.add(name,colName,tag)
         
     return result
    def findPrimers(self,seq,targetMap,boundary,oligoSize,searchSize,targetTm):
        '''
        @input targetMap: a list of genomic locations with sequence names
        
        find a list of sequencing primers for a list of target locations
        
        usage:
        set boundary and oligo size
        read in report, list of locations
        run find sequence primers.
        write report of result
        '''
        result = Report()
 
        for k in targetMap.keys():
            targetLocation = targetMap[k]
            
            upLocation = targetLocation - boundary
            upStart = targetLocation - boundary - searchSize - oligoSize
            upEnd = targetLocation - boundary + searchSize
            upSeq = seq[upStart:upEnd]
            
            downLocation = targetLocation + boundary
            downStart = targetLocation + boundary - searchSize
            downEnd = targetLocation + boundary + searchSize + oligoSize
            downSeq = seq[downStart:downEnd]
            downSeq = downSeq.reverse_complement()
            
            start = searchSize
            (uTm,uAdjust,oUpSeq) = self.scanOligoTm(upSeq,start,oligoSize,searchSize,targetTm)
            (dTm,dAdjust,oDownSeq) = self.scanOligoTm(downSeq,start,oligoSize,searchSize,targetTm)
            dAdjust = -dAdjust
            
            ucLocation = upLocation + uAdjust
            dcLocation = downLocation + dAdjust
            
            result.add(k,"sequencing location",targetLocation)
            
            result.add(k,"foward primer",oUpSeq)
            result.add(k,"foward adjust",uAdjust)
            result.add(k,"foward location",ucLocation)
            result.add(k,"foward TM",uTm)
            
            result.add(k,"reverse primer",oDownSeq)
            result.add(k,"reverse adjust",dAdjust)
            result.add(k,"reverse location",dcLocation + dAdjust)
            result.add(k,"reverse TM",dTm)
            
        return result        
    def generateTargetingOligos(self, records, featureLocations, tagRE, boundary, searchSize, cutOff):
        '''
        Generate a list of oligos for recombination in target locations
        and return report with the targets and sequencing oligos
        
        All oligos printed 5' -> 3'
        Control upstream will be to the left if strands are preserved and to the right 
        if strands are switched when matching lagging complement
        
        oligos are selected discovered as an optimized subsection of the presented sequences 
        
        @records: sequences from which to select oligos
        @featureLocations: a list of locations that place the features in a genome
        @tagRE: regular expression for finding taged sequence with in feature sequences.
        @bounary: oligo flanking region size
        @searchSize: distance in base pairs to search for optimal oligo
        @cutOff: limit of viable fold change energy for chose oligos.
        '''
        
        result = Report()
        index = 0
        
        logFile = open("oligoLog.txt","w")
        targetMap = {}
        sRegions = []
        
        for r in records:
            id = r.id

            features = featureLocations[index]
            hits =  len(features)
            genomicStart = features[0].location.start.position
            genomicEnd = features[0].location.end.position
            genomicStrand = features[0].strand
            laggingComplementStrand = self.strandChooser(features[0])
            
            if "alignment" in features[0].qualifiers.keys():
                aMatch = features[0].qualifiers["alignment"]
            else: 
                aMatch = ''
            
            targetMap[id] = (genomicStart + genomicEnd)/2
            
            logFile.write(id+"\n")
            logFile.write(aMatch+"\n")
            #if self.verbose: print aMatch
            
            s = str(r.seq)
            originalString = s
            
            #Find larget section using special targeting tag
            matchTag = re.search(tagRE,s)
            if matchTag == None:
                tagLoc = len(s)/2
            else:
                targetTag = matchTag.group(0)
                tagLoc = s.index(targetTag) + len(targetTag)/2
                
            if self.verbose: print "Target [%s] location [%s]" % (targetTag,tagLoc)

            start = int(tagLoc - boundary)
            end = int(tagLoc + boundary)
            
            #!May need a little touch up
            if start < 0:
                start = 0
                end = int(boundary*2)
            if end > len(s):
                end = len(s)
            
            if self.verbose: print"region %s -> %s of %s" % (start,end,len(s))

            lowSearchBound = start - searchSize - 5
            highSearchBound = end + searchSize + 5
            
            if lowSearchBound < 0:
                lowSearchBound = 0
            if highSearchBound > len(s):
                highSearchBound = len(s)
                
            if genomicStrand == laggingComplementStrand:            
                s = r.seq[lowSearchBound:highSearchBound]
                sx = r.seq[start:end]
            else:
                s = r.seq[lowSearchBound:highSearchBound].reverse_complement()
                sx = r.seq[start:end].reverse_complement()
            
            searchEnd = (end-start+searchSize+5)
            searchStart = searchSize + 5
            
            try:
                testSeqs = self.optimizeSecondaryStructure(s, searchStart, searchEnd, searchSize, cutOff, ratio = 2)
                testSeqs.sort()
                if len(testSeqs) == 0:
                    (score,adjust,foldScore,bestSeq) = ("na","na","na","na")
                else:
                    (score,adjust,foldScore,bestSeq) = testSeqs.pop(0)
            except:
                testSeqs = []    
                (score,adjust,foldScore,bestSeq) = ("na","na","na",sx)
                print "failed to exicute secondary structure test"
                #print "[%s]" % (s)
            
            #bestSeq = self.addStars(bestSeq,self.stars)
            if len(bestSeq) < boundary*2:
                print "Short Sequence"
            if self.verbose: print "%s best %s S:%s [%s] (%s)" % (len(testSeqs), adjust, score, foldScore, len(bestSeq))
            if self.verbose: print "[%s]" % (bestSeq)
            
            result.add(id,"original", originalString) 
            result.add(id,"hits", hits) 
            result.add(id,"genomic_start", genomicStart) 
            result.add(id,"genomic_end", genomicEnd) 
            result.add(id,"genomic_strand", genomicStrand) 
            result.add(id,"lagging_complement_strand", laggingComplementStrand) 
            result.add(id,"best", bestSeq) 
            result.add(id,"fold score", foldScore) 
            result.add(id,"off center", adjust) 
            
            #append to list of sequence regions
            sRegion = r
            sRegion.seq = sx
            sRegions.append(sRegion)
            
            index = index + 1
        
        logFile.close()
        
        return (targetMap,result,sRegions)
        self.headerNames = ["Row Names"]
    
    def write(self, report):
        headerNames = self.headerNames
        headerNames.extend(report.returnColumnNames())
        self.writeLineArray(headerNames)
        rowNames = report.returnRowNames()
        for rowName in rowNames:
            nameArray = [rowName]
            rowArray = report.returnRowArray(rowName)
            nameArray.extend(rowArray)
            self.writeLineArray(nameArray)
            
if __name__=='__main__':
    hash = {"sad":"happy","mad":"calm"}
    stuff = Report()
    stuff.addReportColumnHash("nerd",hash)
    hash2 = {"sad":"crabby","crazy":"cool",}
    hash3 = {"bad":"foolish","great":"hysterical"}
    stuff.addReportColumnHash("loop", hash2)
    stuff.addReportColumnHash("please", hash3)
    print stuff.returnColumnNames()
    print stuff.returnRowNames()
    print stuff.returnRowArray("mad")
    print stuff.returnRowArray("sad")
    
    morestuff = ReportWriter()
    filename = 'testfile'
    morestuff.setFile(filename)
    morestuff.writer(stuff)
    morestuff.closeFile()