# -*- coding: utf-8 -*- # ============================================================================ # ============================================================================ ''' carboKB_*.py Software to interpret the KnowledgeBase for Pickup by Modelling Software Chris Jenkins INSTAAR Donald Potts UCSC Peter Burgess RHUL a Started: 12 May 2011 from code formerly inside carboLOT Version 2: 16 May 2011 CJJ at INSTAAR ''' # ========================= 2 2 2 2 2 2 2 2 2 2 2 2 ========================== # ============================================================================ import time import math as MATH # ============================================================================ # ============================================================================ ''' Structure: getKnowledgeBase() Reads the organism-knowledegebase into arrays reconcileValuesKB(kbDataA) Tidies up the KB data as it proceeds into arrays: brings human-friendly syntaxes into machine-syntaxes interpHabiRange(enviroPrpty,habitatS) Calculates a organism parameter (eg suitability) from an enviro value of a grid cell by interpolating to a position in a linear set from the KnowledgeBase. Other explanations: 1. Arrays are generally marked with an ending "a" or "A" 2. Strings are generally marked with an ending "s" or "S" 3. Data directly taken from the Knowledge Base is prefixed with "kb" 4. The parameter names of the KB have a web syntax eg organism.param.subparam 5. Usually, counters use "i" or "n", and elements of an array may use "ë" 6. Terms and Arrays are named this way forwhatWhatCoords and then the a/s/e/n/i suffix: eg "crStocksMapA" organism-stock at Yth row-Xth col in array ''' # ============================================================================ def myMAIN(): global kbINf, kbOUTf global nullsA global nowClock nowClock=time.clock() global pi loudQ=False #Determines whether run screen is verbose #(Not a global: different each module)iCr,kbWdHabittA nullsA=[-99.,"-"] #Note in the table all null fields are blank "" #On reading all null entries in kbCoverageA etc are made "-", # which will trip up float() operations pi=MATH.pi #Which file to use the KnowledgeBase eg "KB_3.txt" ---- global kbFileName kbFileName="_carboKB_7" #(Conceivably, users may substitute their own) #Banner .... print "*"*70;print print "\t"*3,"Program carboKB_*.py"; print print "\t","Chris Jenkins INSTAAR, Peter Burgess RHUL, Donald Potts UCSC" print "\t"*4,"May 2011 onwards" print "\t"*4,"Using input table: ",kbFileName print;print "*"*70;print kbINf=open(kbFileName+".txt","r") kbOUTf=open(kbFileName+".okb","w") #Interrogate organism KnowledgeBase ----------- foo=getKnowledgeBase() kbINf.close() #Close files kbOUTf.close() return # ============================================================================ def getKnowledgeBase(): global kbOrgnsmA,numOrgnsms global kbCoverageA,kbGrowthA,kbSkeletalA,\ kbZonesA,kbMortalityA,kbReprodA,\ kbWdHabittA,kbTempHabittA,kbParHabittA global kbSize #Harvests some of the Knowledge Base data into RAM # per property with creatr1,.. as elements. #Note the KB at present is 7cols wide, with '|' in the last column # deviations will be reported as errors by the program. #print;print ">>getKnowledgeBase:" loudQ=False #Controls the amount of output to screen #Initializations... kbCoverageA=[]; kbGrowthA=[]; kbSkeletalA=[];\ kbZonesA=[]; kbMortalityA=[]; kbReprodA=[];\ kbWdHabittA=[]; kbTempHabittA=[];kbParHabittA=[] kbCoverageU=[]; kbGrowthU=[]; kbSkeletalU=[];\ kbZonesU=[]; kbMortalityU=[]; kbReprodU=[];\ kbWdHabittU=[]; kbTempHabittU=[];kbParHabittU=[] kbOrgnsmA=[]; kbOrgnsm="" '''As 7 Sep 2010 Organism= Marginopora vertebralis 9 Foraminiferida : Miliolina .Alternatives Other taxa included .Size linear size (diam) .Occupancy Observed areal coverages .Tissue.AreaFraction Areal fraction (vertical view) of living tissue .Skeleton.GrowthRate linear extension .Skeleton.Morphology Descriptive .Skeleton.Zonation [Zone#,%Presence] Set (Note:subfloor to superstructure) .Skeleton.Disintegrated.VolumeFraction Fraction volume it will disintegrate to after death/transport/burial .Skeleton.Disintegrated.ClastSize Clast/grain size after death/transport/burial .Skeleton.AreaFraction Areal proportion of colony arms (view vertically) .Enviro.Limits Limitations on growth/fecundity/survival .Enviro.Prefs Preferences for growth/fecundity/survival .Enviro.Range.irrad [EnviroParam, Fitness] LineSet .Enviro.Range.salin [EnviroParam, Fitness] LineSet .Enviro.Range.nutr word .Enviro.Range.temp [EnviroParam, Fitness] LineSet .Enviro.Range.wd [EnviroParam, Fitness] LineSet .Mortality.Longevity .Mortality.Rate .Mortality.Type Causes of mortality even in optimum conditions (e.g predation, dieback) .Repro.Clone.ProductionRate Clones produced per adult per year under normal conditions .Repro.Clone.SuccessRate Successful formation of colonies from clones (e.g., unattached colonies) .Repro.Clone.Type .Repro.Spawn.MaturitySize Organism/colony size to commence spawning .Repro.Spawn.ProductionRate Spawn (eggs,larvae) produced per adult per year .Repro.Spawn.SuccessRate Propagules surviving to grow; /m2 instantaneously .Repro.Spawn.Type The process of reproduction; seasonality''' #Find the entry... while kbINf: kbINs=kbINf.readline().lower() if kbINs=="": break #EOF kbINs=kbINs.strip().replace("'","").replace('"','') kbINa=kbINs.split("\t") #Tab delimited kbINa=[kbIN.strip().lower() for kbIN in kbINa] #(Strips hanging spaces from array terms) if len(kbINa)<>8 or kbINa[7]<>"|": print "Error in KB structure: kbINa=",kbINa raw_input("Stop !") else: kbINa=kbINa[:] #Main processing ------------------------- #print kbINa if kbINa[1]=='': pass #Blank elif kbINa[1][0]=='#': pass #Comments elif kbINa[1]=="all_end": break elif kbINa[1]=="organism=": #Detect each organism (genus or species level) kbOrgnsm=kbINa[2] #Have detected the organism (genus or species level) print;print "-"*50 print "Reading KB on: kbOrgnsm",kbOrgnsm kbOrgnsmA.append(kbOrgnsm) #Make room for new entries (which will remain # blank if no data found) kbCoverageA.append(["-","-","-"]) kbSkeletalA.append(["-","-",'-',"-"]) kbZonesA.append(["-","-","-","-"]) kbGrowthA.append(["-"]); kbMortalityA.append(["-","-"]) kbWdHabittA.append("-"); kbTempHabittA.append("-") kbParHabittA.append("-") kbReprodA.append([["-","-"],["-","-"]]) #ie: [Clone,Spawn] / [Rate,Success] kbCoverageU.append(['-','-','-']) kbSkeletalU.append(['-','-','-','-']) kbZonesU.append(['-','-','-','-']) kbGrowthU.append(['-']); kbMortalityU.append(['-','-']) kbWdHabittU.append('-'); kbTempHabittU.append('-') kbParHabittU.append('-') kbReprodU.append([['-','-'],['-','-']]) kbSize=-99. elif kbINa[1]==".alternativetaxa": pass #Blank line elif kbOrgnsm<>"": #First do reconciling and deal with nulls --------------- # and in this will replace certain kbINa entries. if kbINa[3]=='': if kbINa[2]<>'': #Error trap (needs to be a unit with any value) print "No unit found with value: kbINa[2:4]=",kbINa[2:4] raw_input("!") else: if loudQ: print "Both value and units empty" kbINa[2]="-" #Sets nulls kbINa[3]="-" elif kbINa[3]=="$": #Meant to be string data if kbINa[2]=="": if loudQ: print "Both value and units empty for string",kbINa[3] kbINa[2]="-" #Sets nulls kbINa[3]="-" foo=kbVocabulary(kbINa) else: #All types of numerical data (including linear sets) if loudQ: print "numerical:",kbINa[1] if kbINa[2]=="": if loudQ: print "Both value and units empty for numerical",kbINa[3] kbINa[2]="-" #Sets nulls kbINa[3]="-" else: if loudQ: print " >>reconcileValuesKB:",kbINa[1] kbINa=reconcileValuesKB(kbINa) #And for numerical, submit for adjustment in units... if loudQ: print " >>reconcileUnitsKB:",kbINa[1] kbINa=reconcileUnitsKB(kbINa) if loudQ: print "After reconcilings: kbINa=",kbINa #Now process per input parameter and # assign the found values to the RAM arrays -------------- print "kbINa=",kbINa[1:3] if kbINa[1]==".alternativetaxa": pass elif kbINa[1]==".size": try: kbCoverageA[-1][0]=float(kbINa[2]) kbCoverageU[-1][0]=kbINa[3] except: kbCoverageA[-1][0]=0.1 #Default by CJJ kbCoverageU[-1][0]="OnNull: m" try: kbSize=float(kbINa[2]) #Local convenient name except: kbSize==-99. raw_input("Colony size needed but unknown ! ("+\ str(kbSize)+")") #Note: This acts as trap for other cases # (all organisms need occupancy) elif kbINa[1]==".tissue.areafraction": print "kbINa=",kbINa try: kbCoverageA[-1][1]=float(kbINa[2]) kbCoverageU[-1][1]=kbINa[3] except: kbCoverageA[-1][1]=0.5 #(ie default is 50% frame fraction) kbCoverageU[-1][1]="OnNull: fxn" elif kbINa[1]==".occupancy": try: kbCoverageA[-1][2]=float(kbINa[2]) kbCoverageU[-1][2]=kbINa[3] except: kbCoverageA[-1][2]=0.3 kbCoverageU[-1][2]="OnNull: fxn" elif kbINa[1]==".skeleton.morphology": #kbMorphA[-1][0]="" #kbMorphU[-1][0]="$" #kbMorphA[-1][1]=[0.,100.,0.,0.] #kbMorphU[-1][1]="[%]" pass elif kbINa[1]==".skeleton.zonation": try: kbZonesSa=kbINa[2].replace("[","").replace("]","").split(";") kbZonesA[-1]=map(float,kbZonesSa) kbZonesU[-1]=['%','%','%','%'] except: kbZonesA[-1]=[0.,0.,100.,0.] kbZonesU[-1]=['OnNull: %','OnNull: %','OnNull: %','OnNull: %'] #ie: default is 100% frame fraction just above the seabed #print "kbZonesA=",kbZonesA elif kbINa[1]==".skeleton.growthrate": try: kbGrowthA[-1]=float(kbINa[2]) kbGrowthU[-1]=kbINa[3] #Ie absolute rate divided by colony sze => relative except: kbGrowthA[-1]=kbSize*0.03 #ie 3cm/yr for 1m Org ?Reasonable kbGrowthU[-1]="OnNull: m/yr" #Default ~3% growth elif kbINa[1]==".skeleton.disintegrated.fraction": try: kbSkeletalA[-1][0]=float(kbINa[2]) kbSkeletalU[-1][0]=kbINa[3] #fxn except: kbSkeletalA[-1][0]=0.2 kbSkeletalU[-1][0]="OnNull: fxn" elif kbINa[1]==".skeleton.disintegrated.grainsize": try: kbSkeletalA[-1][1]=float(kbINa[2]) kbSkeletalU[-1][1]=kbINa[3] #m except: kbSkeletalA[-1][1]=0.05 #5cm kbSkeletalU[-1][1]="OnNull: m" elif kbINa[1]==".skeleton.porosity": kbSkeletalA[-1][2]=0.8 #General value kbSkeletalU[-1][2]="fxn" elif kbINa[1]==".skeleton.areafraction": print "kbINa=",kbINa try: kbSkeletalA[-1][3]=float(kbINa[2]) kbSkeletalU[-1][3]=kbINa[3] except: kbSkeletalA[-1][3]=0.5 #(ie default is 50% frame fraction) kbSkeletalU[-1][3]="OnNull: fxn" elif kbINa[1]==".enviro.threats": pass elif kbINa[1]==".enviro.prefs": pass elif kbINa[1]==".enviro.range.wd": if kbINa[2]<>"-": kbWdHabittA[-1]=kbINa[2] #Still in % at this stage kbWdHabittU[-1]=kbINa[3] else: kbWdHabittA[-1]="0,0" kbWdHabittU[-1]="OnNull: m" elif kbINa[1]==".enviro.range.temp": if kbINa[2]<>"-": kbTempHabittA[-1]=kbINa[2] kbTempHabittU[-1]=kbINa[3] else: kbTempHabittA[-1]="0,0" kbTempHabittU[-1]="OnNull: degc" elif kbINa[1]==".enviro.range.irrad": if kbINa[2]<>"-": kbParHabittA[-1]=kbINa[2] kbParHabittU[-1]=kbINa[3] else: kbParHabittA[-1]="0,0" kbParHabittU[-1]="OnNull: mol_photons/m2/d" elif kbINa[1]==".enviro.range.nutr": pass elif kbINa[1]==".enviro.range.salin": pass elif kbINa[1]==".enviro.range.oxygen": pass elif kbINa[1]==".mortality.rate": try: kbMortalityA[-1][0]=float(kbINa[2]) kbMortalityU[-1][0]=kbINa[3] except: kbMortalityA[-1][0]=0.05 kbMortalityU[-1][0]="OnNull: fxn/yr" #see: "http://www.springerlink.com/content/rrjq7p8vq45221x8/fulltext.pdf" elif kbINa[1]==".mortality.longevity": try: kbMortalityA[-1][1]=float(kbINa[2]) kbMortalityU[-1][1]=kbINa[3] except: kbMortalityA[-1][1]=kbSize/0.05 #ie 5cm/yr kbMortalityU[-1][1]="OnNull: yr" elif kbINa[1]==".mortality.type": pass elif kbINa[1]==".repro.clone.productionrate": try: kbReprodA[-1][0][0]=float(kbINa[2]) kbReprodU[-1][0][0]=kbINa[3] except: kbReprodA[-1][0][0]=10. #10 rames/yr kbReprodU[-1][0][0]="OnNull: #/yr" elif kbINa[1]==".repro.clone.successrate": try: kbReprodA[-1][0][1]=float(kbINa[2]) kbReprodU[-1][0][1]=kbINa[3] except: kbReprodA[-1][0][1]=0.1 kbReprodU[-1][0][1]="OnNull: fxn" #Default success for cloning is zero elif kbINa[1]==".repro.clone.type": pass elif kbINa[1]==".repro.spawn.maturitysize": pass elif kbINa[1]==".repro.spawn.productionrate": try: kbReprodA[-1][1][0]=float(kbINa[2]) kbReprodU[-1][1][0]=kbINa[3] except: kbReprodA[-1][1][0]=100. kbReprodU[-1][1][0]="OnNull: #/yr" elif kbINa[1]==".repro.spawn.successrate": try: kbReprodA[-1][1][1]=float(kbINa[2]) kbReprodU[-1][1][1]=kbINa[3] except: kbReprodA[-1][1][1]=0.01 #=1% kbReprodU[-1][1][1]="OnNull: fxn" elif kbINa[1]==".repro.spawn.type": pass else: raw_input("parameter not in program ! ("+kbINa[1]+")") else: #In case something else in kb field print "Look what I found in a kb field ! ..." print "kbINa,kbOrgnsm=",kbINa,kbOrgnsm raw_input("!") #------------------------------------------------------------- numOrgnsms=len(kbOrgnsmA) #Echo the results to file and screen ----------------------------------- runYMDHMs="".join(map(str,time.localtime()[:5])) outS="\n" outS+="-"*72+"\n" outS+="Compiled Knowledge Base at:"+runYMDHMs+"\n" #kbOUTf.write("#"+outS.replace("\n","\n#")) print outS '''outS="|"+".. | ".join(["kbOrgnsmA","kbCoverageA","kbGrowthA","kbSkeletalA",\ "kbZonesA","kbWdHabittA","kbTempHabittA","kbParHabittA",\ "kbMortalityA","kbReprodA"])+"\n" outS+="|"+".. | ".join(map(str,[len(kbOrgnsmA),len(kbCoverageA),len(kbGrowthA),len(kbSkeletalA),\ len(kbZonesA),len(kbWdHabittA),len(kbTempHabittA),len(kbParHabittA),\ len(kbMortalityA),len(kbReprodA)]))+"\n" outS+="\n" print outS''' outS="\n" outS+="Synopsis of the Organism KB parameters -----------------"+"\n" outS+="\t"+"kbOrgnsmA[iCr]=Organism name"+"\n" outS+="\n" outS+="\t"+"kbCoverageA[iCr][0]=Colony Size (m)"+"\n" outS+="\t"+"kbCoverageA[iCr][1]=Colony Frame Fraction (fxn)"+"\n" outS+= "\t"+"kbCoverageA[iCr][2]=Observed Carrying Capacity (area_fxn)"+"\n" outS+="\n" outS+= "\t"+"kbGrowthA[iCr][0]=Colony Growth Rate (m/yr)"+"\n" outS+="\n" outS+= "\t"+"kbSkeletalA[iCr][0]=Disintegrated volume fraction (fxn)"+"\n" outS+= "\t"+"kbSkeletalA[iCr][1]=Disintegrated grainsize (m)"+"\n" outS+= "\t"+"kbSkeletalA[iCr][2]=Porosity (fxn)"+"\n" outS+="\n" outS+= "\t"+"kbZonesA[iCr]=Vertical 4-Zone Presences (%)"+"\n" outS+="\n" outS+= "\t"+"kbWdHabittA[iCr]=Habitat by WD ([m,fxn])"+"\n" outS+= "\t"+"kbTempHabittA[iCr]=Habitat by Temperature ([degC,fxn])"+"\n" outS+= "\t"+"kbParHabittA[iCr]=Habitat by Irradiance ([mol_photons/m2/d,fxn])"+"\n" outS+="\n" outS+= "\t"+"kbMortalityA[iCr][0]=Mortality (fxn per individ /yr)"+"\n" outS+="\n" outS+= "\t"+"kbReprodA[iCr][0][0]=Cloning Reproduction Rate (fxn/yr)"+"\n" outS+= "\t"+"kbReprodA[iCr][0][0]=Cloning Reproduction Success (fxn)"+"\n" outS+= "\t"+"kbReprodA[iCr][1][0]=Spawning Reproduction Rate (fxn/yr)"+"\n" outS+= "\t"+"kbReprodA[iCr][1][0]=Spawning Reproduction Success (fxn)"+"\n" outS+= "\t"+"(Note: units are shown as expected by the modelling)"+"\n" outS+="\n" kbOUTf.write(outS.replace("\n","\n#")) print outS #Output KB values for the organisms ----------------------- outS="\n#"+"For each: parameterName"+"\t"+\ "parameterValues"+"\t"+\ "parameterUnits"+"\n" kbOUTf.write(outS) print outS for iCr in range(numOrgnsms): outS="\n" outS+="Organism\t"+str(iCr)+"|"+kbOrgnsmA[iCr] outS+="\n Covrg\t"+"|".join(map(str,kbCoverageA[iCr]))+\ "\t"+"|".join(map(str,kbCoverageU[iCr]))+\ "\n Grwth\t"+"["+str(kbGrowthA[iCr])+"]"+\ "\t"+"["+str(kbGrowthU[iCr])+"]"+\ "\n Skltl\t"+"|".join(map(str,kbSkeletalA[iCr]))+\ "\t"+"|".join(map(str,kbSkeletalU[iCr]))+\ "\n Zones\t"+"|".join(map(str,kbZonesA[iCr]))+\ "\t"+"|".join(map(str,kbZonesU[iCr]))+\ "\n HabWd\t"+str(kbWdHabittA[iCr])+\ "\t"+str(kbWdHabittU[iCr])+\ "\n HabTemp\t"+str(kbTempHabittA[iCr])+\ "\t"+str(kbTempHabittU[iCr])+\ "\n HabPar\t"+str(kbParHabittA[iCr])+\ "\t"+str(kbParHabittU[iCr])+\ "\n MortR\t"+"|".join(map(str,kbMortalityA[iCr]))+\ "\t"+"|".join(map(str,kbMortalityU[iCr]))+\ "\n ReprR\t"+"|".join(map(str,kbReprodA[iCr]))+\ "\t"+"|".join(map(str,kbReprodU[iCr]))+"\n" outS=outS.replace("[","").replace("]","") #No [] whatsoever ! outS=outS.replace("'","").replace('"','') #No '" whatsoever ! kbOUTf.write(outS) print outS print;print "<>kbVocabulary: kbINa=",kbINa if ".enviro.range.irrad": #Irradiance - available from MODIS & Gattuso kbIrradVocabA=[["bright","~600"],\ ["euphotic","6:600"],\ ["upper_euphotic","60:600"],\ ["lower_euphotic","6:60"],\ ["disphotic","0.6:6"],\ ["aphotic","<0.6"],\ ["dark_zone","<0.6"]] kbIrradWord=[]; kbIrradValu=[] for kbIrradVocab in kbIrradVocabA: kbIrradWord.append(kbIrradVocab[0]) kbIrradValu.append(kbIrradVocab[1]) #print "kbIrradWord=",kbIrradWord try: kbDataA=[kbIrradValu[kbIrradWord\ .index(kbINa[2].lower())],"umol photons/m2/s1"] except: #print "Word not in vocab" kbDataA=["",""] elif ".enviro.range.salin": #Salinity - available from WOA05 kbSalinVocabA=[["fresh","<0.5"],\ ["brackish","0.5:25"],\ ["steno","25:35"],\ ["hypersaline",">35"]] kbSalinWord=[]; kbSalinValu=[] for kbSalinVocab in kbSalinVocabA: kbSalinWord.append(kbSalinVocab[0]) kbSalinValu.append(kbSalinVocab[1]) #print "kbSalinWord=",kbSalinWord try: kbDataA=[kbSalinValu[kbSalinWord\ .index(kbINa[2].lower())],"ppt"] except: #print "Word not in vocab" kbDataA=["",""] elif ".enviro.range.nutr": '''#Chlorophyll - available from MODIS for surface kbChlorVocabA=[["eutrophic","1.0:10.0"],\ ["mesotrophic","0.1:1.0"],\ ["oligotrophic","<0.1"]] kbChlorWord=[]; kbChlorValu=[] for kbChlorVocab in kbChlorVocabA: kbChlorWord.append(kbChlorVocab[0]) kbChlorValu.append(kbChlorVocab[1]) print "kbChlorWord=",kbChlorWord try: kbDataA=[kbChlorValu[kbChlorWord\ .index(kbINa[2].lower())],"chl-a mg/m3"] except: print "Word not in Chlor vocab" kbDataA=["",""]''' #Nitrate (available from WOA05) kbNitratVocabA=[["eutrophic","1.0:10.0"],\ ["mesotrophic","0.1:1.0"],\ ["oligotrophic","<0.1"]] kbNitratWord=[]; kbNitratValu=[] for kbNitratVocab in kbNitratVocabA: kbNitratWord.append(kbNitratVocab[0]) kbNitratValu.append(kbNitratVocab[1]) #print "kbChlorWord=",kbNitratWord try: kbDataA=[kbNitratValu[kbNitratWord\ .index(kbINa[2].lower())],"uMol/ltr"] except: #print "Word not in vocab" kbDataA=["",""] else: #print "Other!" kbDataA=["",""] if loudQ: print "<>reconcileValuesKB:" changedQ=False #Detects an operation kbData2,kbData3=kbDataA[2:4] if loudQ: print "kbData2,kbData3=",kbData2,kbData3 #Strip off the doubt flags from the Value and Units field entries: kbData2=kbData2.replace("?","").replace("!","").replace("~","") kbData2=kbData2.replace("_w","").replace("_h","").replace("_l","") #ie: wide,high,long kbData3=kbData3.replace("?","").replace("!","").replace("~","") #Meant to be numeric try: foo=float(kbData2) changedQ=True #Already a number and kbData2 will be evaluated except: #Not a number,but meant to be ... #Ranging data... if ">>" in kbData2: #(Note: this will fail below if >> is in just text) kbData2="("+kbData2.replace(">>","+")+")/2" changedQ=True if ":" in kbData2: #(Note: this will fail below if >> is in just text) kbData2="("+kbData2.replace(":","+")+")/2" changedQ=True #Max/Avg/Min data nTerms=0 if "mx=" in kbData2: #Rate to half the value kbData2=kbData2.replace("mx=","0.5*").replace(";","+") nTerms+=1 changedQ=True if "mn=" in kbData2: #Rate to double the value kbData2=kbData2.replace("mn=","2.0*").replace(";","+") nTerms+=1 changedQ=True if "av=" in kbData2: #Just accept it kbData2=kbData2.replace("av=","1.0*").replace(";","+") nTerms+=1 changedQ=True if "~=" in kbData2: #Override the ~: just accept it kbData2=kbData2.replace("~=","1.0*").replace(";","+") nTerms+=1 changedQ=True if nTerms>0: kbData2="( "+kbData2+" ) /"+str(nTerms) #Multidim data... if "x" in kbData2: #(Note: this will fail below if >> is in just text) kbData2=kbData2.replace("x","*") changedQ=True #Arithmetic data... if "+" in kbData2 or "*" in kbData2: #(Note: this will fail below if >> is in just text) #kbData2=kbData2.replace("+","+") #Trivial changedQ=True #Convert to numerical data type --------------------- if loudQ: print "kbData2,kbData3=",kbData2,kbData3 if changedQ: if loudQ: print "kbDataA[2],kbData2=",kbDataA[2],kbData2 try: kbDataA[2]=str(eval(kbData2)) #A number except: raw_input("Could not eval: kbData2= "+kbData2) #------------------------------------------------------------------ if loudQ: print "kbDataA[2:4]=",kbDataA[2:4] #if changedQ: raw_input("<>reconcileUnitsKB: kbDataA[1:4]=",kbDataA[1:4] if kbDataA[1].strip()=="": return kbDataA #Abort if null data changedQ=False #Detects an operation #The data fields renamed... kbDat1=kbDataA[1].lower() kbDat2=kbDataA[2].lower() kbDat3=kbDataA[3].lower() '''All: ["#/m2",-99],["%",-99],["mm/yr",-99],\ ["$",-99],["m",-99],["%/yr",-99],\ ["#/adult",-99],["#/m2/yr",-99],["mm/day",-99],\ ["mm",-99],["microns",-99],["yr",-99],\ ["degC",-99],["psu",-99],\ ["ml/l",-99],["mol_photons/m2/d",-99],\ ["#/day",-99],["cm",-99],["cm/yr",-99],\ ["#/m2/yr",-99],["yr",-99],["%/adult",-99],\ ["#/yr",-99],["yr",-99] ]''' if loudQ: print "kbDat1,kbDat2,kbDat3=",kbDat1,kbDat2,kbDat3 #For some [0] can just multiply the value # by [1] to get standardized values... growthUa=[["mm/yr",0.001],["mm/day",3.65],["cm/yr",0.01],["m/yr",1.0]] #m/yr standard sizeUa=[["m",1.],["mm",0.001],["microns",0.000001],["cm",0.01]] #m=standard poprateUa=[["%/mo",0.00083],["%/day",0.0000273],["%/yr",0.01],\ ["%/m2/yr",0.01],["%",0.01],\ ["#/adult",1.0]] #fxn/yr=standard timeUa=[["yr",1.0],["mo",0.083],["day",0.00273]] # yr=Standard stockUa=[["#/m2",1.0]] #=Standard salinUa=[["psu",1.0]] #=Standard #Light will be treated separately (lineset) amountUa=[["%",0.01],["fxn",1.],["fxn",1.]] #fxn=Standard if ".occupancy" in kbDat1 and kbDat2<>"": #Standard capacity unit will be #/m2 #Non-empty term... if kbDat3=="#/m2": kbDataA[2]=float(kbDat2) #OK else: if loudQ: print ".capacity Units not #/m2 ! ("+kbDat3+")" #Will try to fix them using colony size if are % coverage if kbDat3=="%" and kbSize<>-99.: #Number in 1m2 square % percent kbDataA[2]=float(kbDat2)/100./kbSize**2 #(Note: the % is areal coverage; size comes in via global; # it is in cm) kbDataA[3]="#/m2" if loudQ: print "Changed occupancy % to #" print "kbDat2,1./kbSize**2,kbDataA[2],kbSize=",\ kbDat2,1./kbSize**2,kbDataA[2],kbSize changedQ=True elif ".fraction" in kbDat1 or ".areafraction" in kbDat1\ and kbDat2<>"-": #Applies to frame fxn, tissue fxn, disintegrated volume, # porosity (1-solid carb) #Non-empty term... for amountU in amountUa: if amountU[0]==kbDat3: if loudQ: print "Gotcha: kbDat1,kbDat2,kbDat3,amountU=",\ kbDat1,kbDat2,kbDat3,amountU kbDataA[2]=float(kbDat2)*amountU[1] kbDataA[3]="fxn" #Set to fraction ... elif ".growthrate" in kbDat1 and kbDat2<>"-": #Non-empty term... #Standard growthrate unit will be m/yr if kbDat3=="%/yr" and kbSize<>-99.: kbDataA[2]=float(kbDat2)/100.*kbSize kbDataA[3]="m/yr" #Set to standard size ... #Changed % to m if kbDat3=="%wt/yr" and kbSize<>-99.: #Will try to fix them using colony size if are % wt kbDataA[2]=float(kbDat2)/100.*kbSize**3 #ie based on volume kbDataA[3]="m/yr" changedQ=True for growthU in growthUa: #Scan to find the unit if growthU[0]==kbDat3: if loudQ: print "Gotcha: kbDat1,kbDat2,kbDat3,growthU=",\ kbDat1,kbDat2,kbDat3,growthU kbDataA[2]=float(kbDat2)*growthU[1] kbDataA[3]="m/yr" #Set to standard size ... changedQ=True elif ".irrad" in kbDat1 and kbDat2<>"-": #Standard PAR irradiance unit: mol_photons/m2/d if kbDat3=="umol_photons/m2/s": try: #Will try to fix them using colony size if are % wt kbDataA[2]=float(kbDat2)*(12.*60.*60.)/1.E6 #ie based on day length kbDataA[3]="mol_photons/m2/d" if loudQ: print "PAR irrad: kbDat2,kbDataA[2],kbDat3,kbDataA[3]=",\ kbDat2,kbDataA[2],kbDat3,kbDataA[3] changedQ=True except: #Lineset structure ... kbDataSetA=kbDataA[2].replace("[","").replace("]","").split(";") kN=-1 if loudQ: print "Old: kbDataSetA=",kbDataSetA for kbDS in kbDataSetA: kN+=1 kbDSa=kbDS.split(",") kbDSa=[str(float(kbDSa[0])*(12.*60.*60.)/1.E6),kbDSa[1]] #kbDSa[1] % term unchanged kbDataSetA[kN]=",".join(kbDSa) if loudQ: print "New: kbDataSetA=",kbDataSetA kbDataA[2]=";".join(kbDataSetA) kbDataA[3]="mol_photons/m2/d" #Set to day unit ... changedQ=True elif ".longevity" in kbDat1 and kbDat2<>"-": #Standard longevity unit will be yr #Non-empty term... for timeU in timeUa: if timeU[0]==kbDat3: if loudQ: print "Gotcha: kbDat1,kbDat2,kbDat3,timeU=",\ kbDat1,kbDat2,kbDat3,timeU kbDataA[2]=float(kbDat2)*timeU[1] kbDataA[3]="yr" #Set to standard size ... changedQ=True #Standard size unit will be cm elif (".size" in kbDat1 or \ ".grainsize" in kbDat1) \ and kbDat2<>"-": #Non-empty term... for sizeU in sizeUa: if sizeU[0]==kbDat3: if loudQ: print "Gotcha: kbDat1,kbDat2,kbDat3,sizeU=",\ kbDat1,kbDat2,kbDat3,sizeU kbDataA[2]=float(kbDat2)*sizeU[1] kbDataA[3]="m" #Set to standard size ... changedQ=True #Standard frequency (rate per individual) unit will be fxn/yr # also for rate (eg mortality) elif (".productionrate" in kbDat1 or \ ".successrate" in kbDat1 or \ ".rate" in kbDat1) and kbDat2<>"-": if loudQ: print "Fix units for recruitm: kbDat2,kbDat3",kbDat2,kbDat3 #is it a number unit ? if kbDat3=="%": if loudQ: print "Fix % units for recruitm: kbDat2,kbDat3",kbDat2,kbDat3 kbDataA[2]=float(kbDat2)/100. kbDataA[3]="fxn/yr" #Will assume that % means /yr overall if loudQ: print "unit revised: kbDataA[2:4]=",kbDataA[2:4] #(Now can proceed as usual) changedQ=True if kbDat3=="%/yr": if loudQ: print "Fix %/yr units for recruitm: kbDat2,kbDat3",kbDat2,kbDat3 kbDataA[2]=float(kbDat2)/100. kbDataA[3]="fxn/yr" if loudQ: print "unit revised: kbDataA[2:4]=",kbDataA[2:4] #(Now can proceed as usual) changedQ=True #is it a number unit ? elif kbDat3 in ["#/yr"]: #(Note: this is a really difficult parameter to work with. #We may take DPotts advice and just calculate recruitments on av.) #Normalize against possible number/m2 based on organism size ... if loudQ: print "Fix # units for recruitm: kbDat2,kbDat3",kbDat2,kbDat3 #kbDataA[2] Unchanged kbDataA[3]="fxn/yr" if loudQ: print "unit revised: kbDataA[2:4],kbAbund=",kbDataA[2:4],kbAbund changedQ=True #(Now can proceed as usual) #is it a number/area unit ? elif kbDat3 in ["#/m2","#/yr/m2"]: #(Note: this is a really difficult parameter to work with. #We may take DPotts advice and just calculate recruitments on av.) #Normalize against possible number/m2 based on organism size ... if loudQ: print "Fix # units for recruitm: kbDat2,kbDat3",kbDat2,kbDat3 kbDataA[2]=float(kbDat2)/(1./kbSize**2) #fxn #Assumed #/yr is also /m2 ! ; also assume is yearly) kbDataA[2]=min(1.0,kbDataA[2]) #and limit it to 100% kbDataA[3]="fxn/yr" if loudQ: print "unit revised: kbDataA[2:4],kbAbund=",kbDataA[2:4],kbAbund changedQ=True #(Now can proceed as usual) #Non-empty term... for poprateU in poprateUa: if poprateU[0]==kbDat3: if loudQ: print "Gotcha poprate: kbDat1,kbDat2,kbDat3,poprateU=",\ kbDat1,kbDat2,kbDat3,poprateU kbDataA[2]=float(kbDat2)*poprateU[1] kbDataA[3]="fxn/yr" #Set to standard size ... changedQ=True else: #print "No units action" pass if changedQ: kbDataA[3]+=":from "+kbDat3 if loudQ: print "New Units: kbDataA[:4]=",kbDataA[:4] return kbDataA # ============================================================================ # ============================================================================ foo=myMAIN() #Finish ----------------------- print "End of Interpreting the Knowledge Base "+"="*40