def main(): #-----------Setting up and unsing option parser----------------------- parser=OptionParser(usage= usage, version=version) logger=logging.getLogger("exportToEMEP.py") parser.add_option("-l", "--loglevel", action="store",dest="loglevel",default=2, help="Sets the loglevel (0-3 where 3=full logging)") parser.add_option("-u", "--user", action="store", dest="user", default=None, help="Specify user manually") parser.add_option("-e", "--edb", action="store", dest="edb", default=None, help="Name of target edb") parser.add_option("-t", "--template", action="store",dest="cf",default=None, help="Generate default controlfile") parser.add_option("-f", "--force", action="store_true",dest="force",default=False, help="To start the process without confirming the domain") (options, args) = parser.parse_args() #------------Setting up logging capabilities ----------- rootLogger=logger.RootLogger(int(options.loglevel)) log=rootLogger.getLogger(sys.argv[0]) if options.cf!=None: generateCf(path.abspath(options.cf)) log.info("Wrote default controlfile") sys.exit() if len(args)!=1: parser.error("Incorrect number of arguments") domainName=os.environ["AVDBNAME"] dmn = domain.Domain(domainName) if options.edb ==None: parser.error("Need to specify edb using flag -e") if options.user ==None: parser.error("Need to specify user using flag -u") if not options.force: answer=raw_input("Chosen dbase is: "+domainName+", continue(y/n)?") if answer=="y": dmn=domain.Domain() else: sys.exit("Interrupted by user") if not dmn.edbExistForUser(options.edb,options.user): log.error("Edb "+options.edb+" does not exist for user "+options.user+" in domain "+domainName) sys.exit() edb=Edb(dmn.name,options.user,options.edb) rsrc=rsrc.Rsrc(edb.rsrcPath()) #Opening controlfile cf=controlfile.ControlFile(fileName=path.abspath(args[0])) substances=cf.findStringList("substances:") outputDir=cf.findExistingPath("outputDir:") acIndex=cf.findInt("acIndex:") #Get activity code tree codes=codetable.CodeTable(edb.rsrcPath(),acIndex=acIndex) datadb=datadb.Datadb(dmn,options.user,edb.name) datadb.read() substDict=dmn.listSubstanceIndices() #List grid names gridNames=edb.listGrids() for ac in codes.ac: if ac=="all": continue pdb.set_trace() log.debug("Activity code: "+ac) dataMarker = emepgrid.emepRaster() rasterDict={} substancesWithData=[] #Rereads grid list for each category to not fill the memory with emission grids #Grid data is only read for grids with current ac gridList=[] for gridName in gridNames: grd=Egrid(dmn.name,options.user,edb.name,gridName) grd.readAsc() if grd.hasFuel(): log.warning("Only support for non-fuel grids implemented, no processing done for grid "+gridName) break gridList.append(grd) for subst in substances: log.debug("Substance: "+subst) substInd=substDict[subst] totEmisRast=raster.Raster(Xll=1190000,Yll=6110000,Ncols=720,Nrows=1560,Cellsize=1000,init=0) for grd in gridList: if grd.par["ACTIVITYCODE"].val[0]==ac: if len(grd.substances)==0: grd.readData() totEmisRast=totEmisRast+grd.substances.get(substInd,0) for src in datadb.sources: if src.par["ACTIVITYCODE"].val[0]==ac: row,col=totEmisRast.getIndex(src.par["X1"].val,src.par["Y1"].val) totEmisRast.data[row,col]+=src.getEmis(substInd,rsrc,"ton/year") pdb.set_trace() if not totEmisRast.sum()==0: if subst not in substancesWithData: substancesWithData.append(subst) __RT90__="+proj=tmerc +lat_0=0 +lon_0=15d48\\'29.8\\\" +x_0=1500000 +k_0=1 +ellps=bessel +towgs84=414.1,41.3,603.1,-0.855,2.141,-7.023,0" emepRast = emepgrid.sortToEmep(totEmisRast,__RT90__,printInfo=True) dataMarker.data = numpy.where(emepRast.data > 0, 1, dataMarker.data) rasterDict[subst]=emepRast categoryDirPath = path.join(outputDir, ac) if not path.isdir(categoryDirPath): os.mkdir(categoryDirPath) fileName = path.join(categoryDirPath, "Emep50km_" + subst+ ".asc") emepRast.write(fileName) log.info("Emissions in EMEP-projection for substance: " + subst + "written to outputDir for category: " + ac) if len(rasterDict)>0: #creating substance header in the same order as the substances in the template header = "i\tj\t" #headerList=["SO2","NOx","NH3","NMVOC","CO","TSP","PM10","PM25","Pb ","Cd","Hg","As","Cr","Cu","Ni","Se","Zn","Aldrin","Chlordane","Chlordecone","Dieldrin","Endrin","Heptachlor","Hexabromobiphenyl","Mirex","Toxaphene","HCH","DDT","PCB","DIOX","PAH","HCB","PCP","SCCP"] for s in substancesWithData: header += s + "\t" #remove the tab after the last column and add a newline instead header = header[: - 1]+ "\n" #Creating file for EMEP-data fileName = "CLRTAP_" + ac + ".txt" categoryDirPath = path.join(outputDir, ac) if not path.isdir(categoryDirPath): os.mkdir(categoryDirPath) fid = open(path.join(categoryDirPath, fileName), 'w') fid.writelines(header) #Writing indexes and data for all non-zero elements for row in range(dataMarker.nrows): for col in range(dataMarker.ncols): if dataMarker.data[row, col] > 0: (i, j) = dataMarker.getCentreCoords(row, col) fid.write(str(i) + "\t" + str(j) + "\t") for substWithData in substancesWithData[:-1]: fid.write(str(rasterDict[substWithData].data[row, col]) + "\t") fid.write(str(rasterDict[substancesWithData[-1]].data[row, col]) + "\n") fid.close() log.info("wrote emissions to clrtap-file: " + path.join(categoryDirPath, fileName)) log.info("Finished")
def extractByGeocode(argDict): """Extracts sources by geocode and saves to edb's for other users specified in a file with users, and optionally edb's, specified for each geocode""" edb = argDict["edb"] mapping = argDict["edbMapping"] codeLevel = argDict["codeLevel"] codeIndex = argDict["codeIndex"] # Processing grid sources for grd in argDict["grids"]: if not match(grd.par["NAME"].val, argDict["filters"]): continue # dict with (user,edb) as key and a list of gc to be included as value subEdbs = {} allFound = True for gc in mapping: # The mapping can contain only users for each geocode, in that case # The users are stored as values and the original edb name is used # as default # If both user and edb name is given, the values are given in a # list for each gc if isinstance(mapping[gc], list): tmp_user = mapping[gc][0] tmp_edb = mapping[gc][1] else: tmp_user = mapping[gc] tmp_edb = edb.name subEdb = Edb(argDict["domain"], tmp_user, tmp_edb) if (tmp_user, tmp_edb) in subEdbs: subEdbs[(tmp_user, tmp_edb)].append(gc) else: subEdbs[(tmp_user, tmp_edb)] = [gc] # Check if edb exist, and if so if grid exist # (to save time when updating) if subEdb.exists(): if grd.name not in subEdb.listGrids(): allFound = False continue else: allFound = False if allFound: log.info( "Splitted grid " + "%s already exist for all" % grd.name + " geocodes, remove to update") continue log.debug("Reading grid: %s" % grd.name) grd.readData() for user_edb, gcList in subEdbs.iteritems(): subEdb = Edb(argDict["domain"], user_edb[0], user_edb[1]) subEdb.rsrc = edb.rsrc # extract data from grid that maches any of the geocodes in gcList subGrid = grd.sliceByGeoCode( codeLevel - 1, map(int, gcList), subEdb ) if subGrid is not None: if not subEdb.exists(): subEdb.create(edbRsrc=edb.rsrcPath()) log.debug("Created edb for user %s" % subEdb.user) log.debug( "Writing grid: %s to edb %s for user %s" % ( grd.name, subEdb.name, subEdb.user) ) subGrid.load() if argDict["sources"] is not None: sub_source_writers = {} # subCompanydbs = {} # subFacilitydbs = {} # Read substance groups subgrpdb = Subgrpdb(edb) subgrpdb.read() facilitydb = Facilitydb(edb) facilitydb.read() companydb = Companydb(edb) companydb.read() for src in argDict["sources"]: if not match(src.NAME, argDict["filters"]): continue # gc = int(src.GEOCODE[codeIndex - 1][codeLevel - 1]) gc = int(src.GEOCODE[codeIndex - 1].split(".")[codeLevel - 1]) if src.PX is not None and src.PX != 0: facility = facilitydb.index[(src.PX, src.PY)] company = companydb.index[facility["COMPANY"]] # If no mapping is provided for a gc it is ignored if gc not in mapping: continue # create sub-edb and corresponding db:s if gc not in sub_source_writers: tmp_user = mapping[gc] subEdb = Edb(argDict["domain"], tmp_user, edb.name) # If a sub-edb does not exist, # create a new one with edb.rsrc from original edb if not subEdb.exists(): subEdb.create(edbRsrc=edb.rsrcPath()) sub_source_writers[gc] = ModelWriter( SourceStream(subEdb, mode='w') ) # subCompanydbs[gc] = Companydb(subEdb) # subFacilitydbs[gc] = Facilitydb(subEdb) # Write substance groups to subEdb subgrpdb.setEdb(subEdb) log.info("Writing subgrpdb for user %s" % subEdb.user) subgrpdb.write() # subCompanydbs[gc].append(company, force=True) # subFacilitydbs[gc].append(facility,force=True) sub_source_writers[gc].write(src) # write all sources for gc in sub_source_writers: # log.info("Writing companies to edb for gc %i" % gc) # subCompanydbs[gc].write() # log.info("Writing facilities to edb for gc %i" % gc) # subFacilitydbs[gc].write() log.info("Writing sources to edb for gc %i" % gc) return argDict
def main(): actionList = [ 'addSubstance', 'removeSubstance', 'mapSubstances', 'addCodeTree', 'removeCodeTree', 'moveCodeTree', 'extractByGeocode', 'uniteGrids', 'scale' ] # setting up parser parser = argparse.ArgumentParser( description=__doc__, formatter_class=argparse.ArgumentDefaultsHelpFormatter ) utils.add_standard_command_options(parser) parser.add_argument("-d", "--doc", action="store_true", dest="doc", help="Prints more detailed documentation and exit") parser.add_argument("-u", "--user", action="store", dest="user", default=None, help="Specify user manually") parser.add_argument("-e", "--edb", action="store", dest="edb", default=None, help="Name of target edb") parser.add_argument("-s", "--substance", action="store", dest="substance", help="Name of substance to add or remove") parser.add_argument("--substanceFactorFile", action="store", dest="substanceFactorFile", help="File with substance factors") parser.add_argument("--substanceMapping", action="store", dest="substanceMapping", help="File with mapping for substance indices") parser.add_argument("--codeMapping", action="store", dest="codeMapping", help="File with mapping from old codes to new") parser.add_argument("--edbMapping", action="store", dest="edbMapping", help="File with mapping from gc to edb") parser.add_argument("-f", "--force", action="store_true", dest="force", default=False, help="Start the process without confirming the domain") parser.add_argument("--factor", action="store", type=float, dest="factor", help="Factor used to scale emissions") parser.add_argument( "-n", "--names", action="store", dest="sourceNames", default=['.*'], nargs='*', help="Space separated list of regular expressions" ) parser.add_argument( "--sourceTypes", action="store", dest="sourceTypes", nargs='*', default=['griddb', 'sources'], choices=["griddb", "sources", "subgrpdb", "svehdb", "vehdb"], help="Source types to process" ) parser.add_argument( "--codeType", action="store", dest="codeType", default='ac', help="Code type to process" ) parser.add_argument( "--codeIndex", action="store", dest="codeIndex", default=1, type=int, help="Index of code tree to use in processing" ) parser.add_argument( "--newIndex", action="store", dest="newIndex", default=None, help="New index when moving an already defined code tree" ) parser.add_argument( "--codeLevel", action="store", dest="codeLevel", default=1, type=int, help="Level of code tree to use in processing") parser.add_argument( "--actions", action="store", dest="actions", nargs='*', choices=actionList, help="Action list" ) args = parser.parse_args() if args.doc: print doc sys.exit() # if len(args) > 0: # log.error("Incorrect number of arguments") # sys.exit(1) if args.edb is None: log.error("Need to specify edb") sys.exit(1) if args.user is None: log.error("Need to specify user") sys.exit(1) dmn = Domain() edb = Edb(dmn, args.user, args.edb) subdb = Subdb(edb) subdb.read() rsrc = Rsrc(edb.rsrcPath()) # Check if edb exist if not edb.exists(): log.error("Edb " + args.edb + " does not exist for user " + args.user + " in domain " + dmn.name) sys.exit(1) if args.codeType.lower() == "ac": codeType = "ACTIVITYCODE" elif args.codeType.lower() == "gc": codeType = "GEOCODE" else: parser.error("codeType should be either 'gc' or 'ac'") if args.codeIndex < 1: raise ValueError("Minimum code index is 1") if args.codeIndex > 1 and codeType == "gc": raise OSError("Multiple geocode trees not implemented") for a in args.actions: if a not in actionList: parser.error("Unknown action %s" % a) log.info("User: "******"Edb: " + args.edb) loadGridData = False # Set values in argsDict argDict = { "edb": edb, "user": args.user, "domain": dmn, "grids": [], "filters": args.sourceNames, "codeType": codeType, "codeIndex": args.codeIndex, "codeLevel": args.codeLevel, "sources": None, "griddb": None, "subgrpdb": None, "roaddb": None, "vehdb": None, "svehdb": None, "rsrc": rsrc } # ----- Reading sources from edb ------------------------------- if 'griddb' in args.sourceTypes: grids = [] gridNames = edb.listGrids() for name in gridNames: grd = egrid.Egrid(edb, name) grd.readAsc() grids.append(grd) argDict["grids"] = grids if 'sources' in args.sourceTypes: argDict["sources"] = list(ModelReader(SourceStream(edb, mode='r'))) if 'roaddb' in args.sourceTypes: log.error("Not implemented with new roaddb-structure") sys.exit(1) if 'subgrpdb' in args.sourceTypes: subgrpdb = Subgrpdb(edb) subgrpdb.read() argDict["subgrpdb"] = subgrpdb # emfacdbdb = Emfacdb(edb) # emfacdb.read() # argDict["subgrpdb"] = subgrpdb if 'svehdb' in args.sourceTypes: svehdb = Svehdb(edb) svehdb.read() argDict["svehdb"] = svehdb # TODO: add option for vehdb # parse additional args # -----addSubstance-------------------------------------- if "addSubstance" in args.actions: if args.substance is None: parser.error("Action addSubstance needs" + "--substance to be specified") if args.substanceFactorFile is None: parser.error("Option addSubstance also needs" + "--substanceFactorFile to be specified") if args.substance not in subdb.substIndices: raise ValueError( "Substance %s not in substance list" % args.substance) substanceNameFactorDict = parseMapping( path.abspath(args.substanceFactorFile), valueType=float) substanceFactorDict = {} # Converts mapping between substance name and factor to # mapping between substance index and factor for name, factor in substanceNameFactorDict.iteritems(): if name not in subdb.substIndices: raise KeyError( "Substance : %s not found in substance list" % name ) ind = subdb.substIndices[name] substanceFactorDict[ind] = factor argDict["substanceFactorDict"] = substanceFactorDict argDict["substance"] = subdb.substIndices[args.substance] # ----removeSubstance------------------------------------ if "removeSubstance" in args.actions: if args.substance is None: parser.error("Action removeSubstance needs" + "--substance to be specified") if args.substance not in subdb.substIndices: log.error("Substance %s not in substance list" % args.substance) sys.exit(1) argDict["substance"] = subdb.substIndices[args.substance] # ----mapSubstances-------------------------------------- if "mapSubstances" in args.actions: if args.substanceMapping is None: parser.error("Action mapSubstances needs" + "--substanceMapping to be specified") substanceMappingFile = path.abspath(args.substanceMapping) substanceMapping = parseMapping( substanceMappingFile, keyType=int, valueType=int ) argDict["substanceMapping"] = substanceMapping # ----addCodeTree----------------------------------------- if "addCodeTree" in args.actions: if args.codeMapping is None: parser.error("Action addCodeTree needs" + "--codeMapping to be specified") if args.newIndex is None: parser.error("Action addCodeTree needs" + "--newIndex to be specified") codeMappingFile = path.abspath(args.codeMapping) codeMapping = parseMapping(codeMappingFile) argDict["codeMapping"] = codeMapping argDict["newIndex"] = int(args.newIndex) # ----removeCodeTree------------------------------------- # Only arguments with default values needed, no validation is needed # ----moveCodeTree--------------------------------------- if "moveCodeTree" in args.actions: if args.newIndex is None: parser.error("Action moveCodeTree needs" + "--newIndex to be specified") try: argDict["newIndex"] = int(args.newIndex) except ValueError: log.error("newIndex must be an integer value") sys.exit(1) # ----extractByGeocode----------------------------------- if "extractByGeocode" in args.actions: if args.edbMapping is None: parser.error("Action extractByGeocode needs" + "--edbMapping to be specified") log.info("Slicing edb by geocode") edbMappingFile = path.abspath(args.edbMapping) # Geocode has to be int edbMapping = parseMapping(edbMappingFile, keyType=int) argDict["edbMapping"] = edbMapping if 'scale' in args.actions: argDict['substance'] = subdb.substIndices[args.substance] argDict['factor'] = args.factor if args.factor is None: log.error("Must specify --factor") sys.exit(1) if args.substance is None: log.error("Must specify --substance") sys.exit(1) # Processing actions for action in args.actions: log.info("Running action: %s" % action) argDict = eval(action)(argDict) # Writes each processed grid to edb if loadGridData: for grd in argDict["grids"]: if not match(grd["NAME"], argDict["filters"]) or grd.hasSubgrp(): continue else: log.debug( "Wrote grid %s to edb: %s, user: %s" % ( grd.par["NAME"].val, grd.edb.name, grd.user) ) grd.load() else: for grd in argDict["grids"]: if not match(grd["NAME"], argDict["filters"]) or grd.hasSubgrp(): continue else: log.debug( "Wrote .asc-file for grid %s to edb: %s, user: %s" % ( grd.par["NAME"].val, grd.edb.name, grd.user) ) grd.writeAsc(grd.getAscPath()) # Writes each processed database to edb if argDict["sources"] is not None: with SourceStream(edb, mode="w") as stream: model_writer = ModelWriter(stream) for src in argDict["sources"]: log.debug('Wrote source %s' % src.NAME) model_writer.write(src) for dbName in ["roaddb", "subgrpdb", "svehdb", "vehdb"]: if argDict[dbName] is not None: argDict[dbName].write() log.info( "Wrote %s to edb: %s, user: %s" % ( dbName, edb.name, edb.user) )
def main(): # Parse command line arguments parser = argparse.ArgumentParser(description=__doc__) utils.add_standard_command_options(parser) parser.add_argument("controlfile", metavar='CONTROLFILE', action="store", help="Controlfile for topdown processing") parser.add_argument("-t", "--template", metavar='TEMPLATEFILE', action="store",dest="cf",default=None, help="Generate default controlfile") args = parser.parse_args() if args.cf is not None: generateCf(args.cf) log.info("Wrote default controlfile") sys.exit(0) log.info("Starting topdown processing") # Opening controlfile cf = ControlFile(args.controlfile) dmn = Domain() log.info("Reading topdown table") tdTableName = cf.findExistingPath("topDownTable:") tdTable = DataTable() tdTable.keys.append("Code") tdTable.read(tdTableName,delimiter=";") log.info("Reading national totals table") natTotalTableName = cf.findExistingPath("nationalTotalTable:") natTable = DataTable(desc=[{"id": "Code", "type":unicode}, {"id": "description", "type":unicode}]) natTable.keys.append("Code") natTable.read(natTotalTableName, units=True, defaultType=str) notationKeys = ["NE", "NO", "NA", "IE"] log.debug("Remove notation keys from national totals table") for row in natTable.data: for i in range(len(row)): if row[i] in notationKeys: row[i] = None log.debug("Convert all emission columns in national totals to float") for colId in natTable.listIds(): if colId not in ["Code","description"]: natTable.convertCol(colId,float) log.debug("Store units from national totals for each substance in dict") natUnits={} for col in natTable.desc: if col.get("units",None)!=None: natUnits[col["id"]]=col["units"] log.debug("Read remaining data from control file") bottomupEdbName = cf.findString("bottomUpEdb:") topDownEdbName = cf.findString("topDownEdb:") emissionsEdbName = cf.findString("emissionsEdb:") userName = cf.findString("user:"******"year:") #initialize edb objects buEdb = Edb(dmn,userName,bottomupEdbName) tdEdb = Edb(dmn,userName,topDownEdbName) eEdb = Edb(dmn,userName,emissionsEdbName) log.info("Reading/preparing EDB:s") log.info("Reading subdb") subdb = Subdb(eEdb) subdb.read() log.info("Reading subgrpdb") subgrpdb = SubgrpStream(buEdb) subgrpdb.read() log.info("Reading facilitydb") facilityIn = FacilityStream(buEdb) log.info("Reading companydb") companyIn = CompanyStream(buEdb) facilityOut = FacilityStream(eEdb,mode="w") companyOut = CompanyStream(eEdb,mode="w") log.info("Writing company db to result edb") companyOut.write(companyIn.read()) log.info("Writing facility db to result edb") facilityOut.write(facilityIn.read()) if not buEdb.exists(): log.error("Edb " + buEdb.name + " does not exist for user " + userName + " in domain " + dmn.name) sys.exit(1) if not tdEdb.exists(): log.error("Edb " + tdEdb.name + " does not exist for user " + userName + " in domain " + dmn.name) sys.exit(1) if not eEdb.exists(): log.error("Edb " + eEdb.name + " does not exist for user " + userName + " in domain " + dmn.name) sys.exit(1) keys = tdEdb.listGrids() msg = "%i keys found in edb: %s" % (len(keys), tdEdb.name) log.info(msg) # sourcedb from bottom-up edb with SourceStream(buEdb, mode='rb') as source_instream: source_reader = ModelReader(source_instream) bu_sources = list(source_reader) log.info( "%i point sources found in edb: %s" % ( len(bu_sources), buEdb.name) ) # Empty sourcedb of the result edb if cf.findBoolean("emptyEmissionSourcedb:"): eEdb.empty_sourcedb() e_sources = [] log.info("Removed point sources from edb: %s" % (eEdb.name)) else: # sourcedb from emission edb (result edb) with SourceStream(eEdb, mode='rb') as source_instream: source_reader = ModelReader(source_instream) e_sources = list(source_reader) msg = "%i point sources found in edb: %s" % (len(e_sources), eEdb.name) log.info(msg) if not path.exists(eEdb.rsrcPath()): log.error("No edb.rsrc exists for emission edb") sys.exit() else: rsrc = Rsrc(eEdb.rsrcPath()) acIndex = cf.findInt("acIndex:") codeDepth = rsrc.ac[acIndex-1].depth substances = cf.findStringList("substances:") for subst in substances: if subst not in subdb.substIndices: log.error("Substance: " + subst + " not in Airviro substance list") sys.exit() # Initialize trace for debug and additional logging if cf.findBoolean("trace:") == True: log.info("Initializing trace for detailed logging") trace = TraceDef( active=True, substances=cf.findStringList("trace.substances:"), logfile=cf.findString("trace.logfile:"), regdefgc=cf.findIntList("trace.regdef.gc:", optional=True, default=None), gcDefRaster=cf.findExistingPath("trace.gcraster:") ) else: trace = TraceDef(active=False) log.info("Initializing result table") resTablePath = cf.findString("resTable:") resTable = DataTable(desc=[{"id": "Code", "type": unicode}]) resTable.keys.append("Code") for subst in substances: resTable.addCol({"id": subst, "type": float, "unit": "%"}) # Create emission grid template (with geocodes) log.info("Reading emission grid template") eGridTemplatePath = cf.findExistingPath("emisGridTemplatePath:") eGridTemplate = Egrid(eEdb,"name") if eGridTemplatePath[-4:] == ".asc": eGridTemplatePath=eGridTemplatePath[:-4] eGridTemplate.readData(eGridTemplatePath) eGridTemplate.substances = {} eGridTemplate.par["SUBSTANCE"].val = [] dd = {"key": None, "regstat": None, "regdef": None, "bu_sources": bu_sources, "psIndices": [], "units": natUnits, "rsrc": rsrc, "subdb": subdb, "trace": trace, "subgrpdb": subgrpdb } # Process all rows in the topdown table for row in tdTable.data: code = row[tdTable.colIndex["Code"]] active = row[tdTable.colIndex["Active"]] statType = row[tdTable.colIndex["Stat_type"]] if active == "no": continue log.info("Code: "+code) distributed=False # Add '-' to the code to reach max length (fix for a GUI bug) airviroCode = code # while len(airviroCode.split(".")) < codeDepth: # airviroCode += ".-" tdrow = tdTable.data[tdTable.rowIndex([code])] nrow = natTable.data[natTable.rowIndex([code])] # Create a resTable row to fill with data resrow = [None] * resTable.ncols resrow[0] = code # Check if national totals are non-zero nonZero = False for val in nrow: if val != None: if val > 0: nonZero = True break # Filter out indices for pointsources with the current ac # Also including sources coded with sub-codes # This allows to estimate top-down emissions on a higher code-level psIndices = [] for i, ps in enumerate(bu_sources): codeMatch = False for emis in ps.EMISSION: # It is assumed that the first code is used while processing topdown ac = emis.ACTCODE[0] if ac[-1] == ".": ac=ac[:-1] # if ac[:len(code)] == code: if ac == code: codeMatch = True break if not codeMatch: for emis in ps.SUBGRP: # It is assumed that the first code is used while processing topdown ac = emis.ACTCODE[0] if ac[:len(code)] == code: codeMatch = True break if codeMatch: psIndices.append(i) dd["psIndices"] = psIndices keyName = row[tdTable.colIndex["Key"]] #If no distribution key specified and no ps in bottom-up edb - cont. if keyName is None and psIndices == []: log.debug("No key and no point sources found for code: %s, skipping..." % code) resTable.addRow(resrow) continue if psIndices!=[]: msg = "--Found %i pointsources" % len(psIndices) log.info(msg) if keyName is not None: if keyName not in keys: log.error("No such key: " + keyName) sys.exit() msg = "--Key: %s" % keyName log.info(msg) keyGrid = Egrid(tdEdb, keyName) keyGrid.readData() log.debug("Read key: " + keyName + " from topdownEdb") # create emission grid to store distributed emissions eGrid = deepcopy(eGridTemplate) eGrid.name = code.replace(".", "_") eGrid.par["NAME"].val = code eGrid.par["INFO2"].val = "Distribution key: " + keyGrid.par["NAME"].val eGrid.par["ACTIVITYCODE"].val = [airviroCode.split(".")] regstatName = row[tdTable.colIndex["Regstat"]] regdefName = row[tdTable.colIndex["Regdef"]] if regstatName is not None: if regdefName is None: log.error("No region definition given for regional statistics: " + regstatName) sys.exit(1) regstatPath = path.join(dmn.domainPath(), "topdown", "regstat", regstatName) regstat = DataTable() log.info("regstatPath: "+regstatPath) regstat.read(regstatPath, units=True, defaultType=float, delimiter=";") if not "Geocode" in regstat.listIds(): log.error("No Geocode column found in regstat") sys.exit(1) regstat.convertCol("Geocode", int) regstat.keys.append("Geocode") # Making Geocode the primary key # create list of unique geo codes geocodes = [row[regstat.colIndex["Geocode"]] for row in regstat.data] geocodes = unique(geocodes) for colId in regstat.listIds(): if colId.lower() == "year": rows = [] regstat.convertCol(colId, int) # Make it possible to accumulate year regstat.setKeys(regstat.keys + [colId]) # Calculates the total emission for each geocode # in case there are multiple rows for different fuels etc colsToSum = regstat.listIds() colsToSum.remove(colId) colsToSum.remove("Geocode") for gc in geocodes: # sums all numeric values in colsToSum for # rows matching row id [gc,year] #returns an accumulated row and appends it to rows rowId = regstat.dict2RowId({"Geocode": gc, colId: year}) rows.append(regstat.accumulate(rowId, "sum", colsToSum)) regstat.data = rows # replace original rows with accumulated rows regstat.keys.remove(colId) break # dd["regstat"] = regstat regdef = Raster() regdefPath = path.join(dmn.domainPath(), "topdown", "regdef", regdefName) regdef.read(regdefPath) dd["regstat"] = regstat dd["regdef"] = regdef else: dd["regstat"] = None dd["regdef"] = None if dd["regstat"] is not None and len(bu_sources) > 0 and statType == "fixed": log.info("--Regionalizing pointsources") dd = regionalizePS(dd, code) if keyName is not None and nonZero: regionalizedDefault = False # Spatial distribution of emissions for subst in substances: sInd = subdb.substIndices[subst] toUnit = dd["units"][subst] + "/year" ntot = nrow[natTable.colIndex[subst]] pstot = 0 for i in dd["psIndices"]: source = dd["bu_sources"][i] # TODO: should give reference to subgrps to include emis from them pstot += source.get_emis( sInd, toUnit, eEdb, actcodes=[code] ) if ntot is None or ntot == 0: if pstot > 0: # 9999 is used as marker for no national total resrow[resTable.colIndex[subst]] = 9999.0 log.warning( "Nattot is 0 but ps tot is: %f %s" % (pstot, toUnit)) continue nrest = ntot - pstot resrow[resTable.colIndex[subst]] = 100.0 if abs(nrest / ntot) < 0.0001: nrest = 0 log.info( "--Rest is < 0.01 % of national total, rounded to zero" ) continue elif nrest < 0: log.warning( "--National rest is below zero, %4.2f proc for %s" % ( -1 * nrest / ntot * 100, subst) ) dd["trace"].write() # continue log.info( "---Substance: "+subst+ ", rest is: " + str(nrest) + toUnit + " = " + str(nrest / ntot * 100.0) + "%" ) try: keyRast = keyGrid.substances[sInd] except KeyError: keyRast = keyGrid.substances[subdb.substIndices["all"]] dd["key"] = keyRast if dd["regstat"] is not None: if (subst not in regstat.colIndex and sInd not in keyGrid.substances and not regionalizedDefault): dd = regionalizeKey(dd, subst, code) regionalizedDefault = True else: dd = regionalizeKey(dd, subst, code) emisRast = distribute(dd["key"], nrest) emisRast = emisRast * unitConvFac(toUnit, "ton/year") eGrid.addData(emisRast, dd["subdb"].substIndices[subst]) distributed = True else: # resTable is filled # In case all national totals are zero but there are ps for subst in substances: sInd = dd["subdb"].substIndices[subst] toUnit = dd["units"][subst] + "/year" ntot = nrow[natTable.colIndex[subst]] pstot = 0 for i in dd["psIndices"]: source = dd["bu_sources"][i] # subgrps are not used! pstot += source.get_emis(sInd, toUnit, buEdb, actcodes=[code]) if ntot!=0 and ntot is not None: resrow[resTable.colIndex[subst]] = pstot / ntot * 100.0 else: resrow[resTable.colIndex[subst]] = -999.0 if len(dd["psIndices"]) > 0: tmp_sources = (bu_sources[i] for i in dd["psIndices"]) with SourceStream(eEdb, mode='wb') as out_source_stream: source_writer = ModelWriter(out_source_stream) for source in tmp_sources: source_writer.write(source) log.debug("Wrote ps to emission edb") if distributed: eGrid.load() log.debug("Wrote emission grid to emission edb") dd["trace"].write() resTable.addRow(resrow) resTableFile = open(resTablePath,"w") resTable.write(resTableFile) log.info("Finished topdown process")