def write_chem_species(ncfile, filetimes): nlev = ncfile.dimensions['lev'].size # Find all GEOS variables in the categories defined as static variables b = bpch(filetimes.unique_files()[0]) gc_moz_names = { } # this will be a dictionary with the GC name as the key and the MOZART-like name as the value for k in b.variables.keys(): for cat in gc_categories: if cat in k: gc_moz_names[k] = geos_to_moz_name(k) b.close() for gc_name, moz_name in gc_moz_names.iteritems(): if __debug_level__ > 1: shell_msg(' Writing {0} as {1}'.format(gc_name, moz_name)) val = [] for fname in filetimes.unique_files(): b = bpch(fname) this_val = b.variables[gc_name] this_unit = b.variables[gc_name].units if this_unit == 'molec/cm3': if __debug_level__ > 1: shell_msg('Converting molec/cm3 to VMR') airden = b.variables['TIME-SER_AIRDEN'] this_val /= airden else: if __debug_level__ > 1: scale = unit_conversion(1.0, 'vmr', this_unit, 'ppp') shell_msg(' Scaling by {0}'.format(scale)) this_val = unit_conversion(this_val, 'vmr', this_unit, 'ppp') sz = list(this_val.shape) n_to_add = nlev - sz[1] if n_to_add > 0: sz[1] = n_to_add padding = np.empty(sz) padding.fill(fill_val) this_val = np.concatenate([this_val, padding], 1) val.append( flip_dim(this_val, 1) ) # remember, GEOS-Chem defines z=1 as surface; MOZART says that's TOA b.close() ncfile.createVariable(moz_name, np.float32, dimensions=('time', 'lev', 'lat', 'lon')) ncfile.variables[moz_name][:] = np.concatenate(val, 0) ncfile.variables[moz_name].units = 'VMR'
def get_values(wd, species, group, month, debug=False): print 'Extracting data from the bpch.' bpch_fname = wd + month + ".ctm.bpch" print str(bpch_fname) bpch_data = bpch(bpch_fname) if debug: print 'Data groups:' print bpch_data.groups print 'Group species:' print bpch_data.groups[group].variables species_data = bpch_data.groups[group].variables[species] # Extract only the data which is in the troposphere. # This gives us lots of zeroes, which is bad. time_in_trop = bpch_data.groups['TIME-TPS'].variables['TIMETROP'] species_data = np.multiply(species_data[:, :38, :, :], time_in_trop) # Trying surface ozone instead of tropospheric ozone species_data = species_data[0, 0, :, :] units = bpch_data.groups[group].variables[species].units start_time = bpch_data.groups[group].variables['tau0'] end_time = bpch_data.groups[group].variables['tau1'] start_time, end_time = extract_month(start_time, end_time) return species_data, units, start_time, end_time
def get_values( wd, species, group, month, debug=False ): print 'Extracting data from the bpch.' bpch_fname = wd + month + ".ctm.bpch" print str(bpch_fname) bpch_data = bpch(bpch_fname) if debug: print 'Data groups:' print bpch_data.groups print 'Group species:' print bpch_data.groups[group].variables species_data = bpch_data.groups[group].variables[species] # Extract only the data which is in the troposphere. # This gives us lots of zeroes, which is bad. time_in_trop = bpch_data.groups['TIME-TPS'].variables['TIMETROP'] species_data = np.multiply(species_data[:,:38,:,:], time_in_trop) # Trying surface ozone instead of tropospheric ozone species_data = species_data[0,0,:,:] units = bpch_data.groups[group].variables[species].units start_time = bpch_data.groups[group].variables['tau0'] end_time = bpch_data.groups[group].variables['tau1'] start_time, end_time = extract_month(start_time, end_time) return species_data, units, start_time, end_time;
def get_species_data_from_bpch(wd, species, group, debug=True): print 'Extracting data from the bpch.' bpch_fname = wd + month + ".ctm.bpch" # bpch_fname = wd + "ctm.bpch" bpch_data = bpch(bpch_fname) if debug: print 'Data groups:' print bpch_data.groups print 'Group species:' print bpch_data.groups[group].variables species_data = bpch_data.groups[group].variables[species] units = bpch_data.groups[group].variables[species].units start_time = bpch_data.groups[group].variables['tau0'] end_time = bpch_data.groups[group].variables['tau1'] # Turn time from hours from the equinox to YYYY-MM-DD epoch = datetime.datetime(1985, 1, 1) start_time = epoch + datetime.timedelta(hours=start_time[0]) end_time = epoch + datetime.timedelta(hours=end_time[0]) # Obtain only the date start_time = start_time.date() end_time = end_time.date() return species_data, units, start_time, end_time
def get_species_data_from_bpch(wd, species, group, debug=True): print 'Extracting data from the bpch.' bpch_fname = wd + "ctm.bpch" # print months # for month in months: slice = [2] tmp_data = bpch(bpch_fname, timeslice=[slice]) if debug: print 'Data groups:' print tmp_data.groups tmp_data_group = tmp_data.groups[group] if debug: print 'Group species:' print tmp_data_group.variables tmp_data_species = tmp_data_group.variables[species] tmp_data_units = tmp_data_species.units print tmp_data_species.shape data = tmp_data_species # print range(6)[timeslice] # combine list into single array debug = True if debug: print 'data length = ' + str(data.dimensions) # print data print 'data units = ' + tmp_data_units # print data return data
def get_species_data_from_bpch(wd,species,group, debug=True): print 'Extracting data from the bpch.' bpch_fname = wd+"ctm.bpch" # print months # for month in months: slice = [2] tmp_data = bpch(bpch_fname,timeslice = [slice] ) if debug: print 'Data groups:' print tmp_data.groups tmp_data_group = tmp_data.groups[group] if debug: print 'Group species:' print tmp_data_group.variables tmp_data_species = tmp_data_group.variables[species] tmp_data_units = tmp_data_species.units print tmp_data_species.shape data=tmp_data_species # print range(6)[timeslice] # combine list into single array debug = True if debug: print 'data length = ' + str(data.dimensions) # print data print 'data units = ' + tmp_data_units # print data return data;
def get_species_data_from_bpch(wd,species,group, debug=True): print 'Extracting data from the bpch.' bpch_fname = wd + month + ".ctm.bpch" # bpch_fname = wd + "ctm.bpch" bpch_data = bpch(bpch_fname) if debug: print 'Data groups:' print bpch_data.groups print 'Group species:' print bpch_data.groups[group].variables species_data = bpch_data.groups[group].variables[species] units = bpch_data.groups[group].variables[species].units start_time = bpch_data.groups[group].variables['tau0'] end_time = bpch_data.groups[group].variables['tau1'] # Turn time from hours from the equinox to YYYY-MM-DD epoch = datetime.datetime(1985,1,1) start_time = epoch + datetime.timedelta(hours=start_time[0]) end_time = epoch + datetime.timedelta(hours=end_time[0]) # Obtain only the date start_time = start_time.date() end_time = end_time.date() return species_data, units, start_time, end_time;
def write_chem_species(ncfile, filetimes): nlev = ncfile.dimensions['lev'].size # Find all GEOS variables in the categories defined as static variables b = bpch(filetimes.unique_files()[0]) gc_moz_names = {} # this will be a dictionary with the GC name as the key and the MOZART-like name as the value for k in b.variables.keys(): for cat in gc_categories: if cat in k: gc_moz_names[k] = geos_to_moz_name(k) b.close() for gc_name, moz_name in gc_moz_names.iteritems(): if __debug_level__ > 1: shell_msg(' Writing {0} as {1}'.format(gc_name, moz_name)) val = [] for fname in filetimes.unique_files(): b = bpch(fname) this_val = b.variables[gc_name] this_unit = b.variables[gc_name].units if this_unit == 'molec/cm3': if __debug_level__ > 1: shell_msg('Converting molec/cm3 to VMR') airden = b.variables['TIME-SER_AIRDEN'] this_val /= airden else: if __debug_level__ > 1: scale = unit_conversion(1.0, 'vmr', this_unit, 'ppp') shell_msg(' Scaling by {0}'.format(scale)) this_val = unit_conversion(this_val, 'vmr', this_unit, 'ppp') sz = list(this_val.shape) n_to_add = nlev - sz[1] if n_to_add > 0: sz[1] = n_to_add padding = np.empty(sz) padding.fill(fill_val) this_val = np.concatenate([this_val, padding], 1) val.append(flip_dim(this_val, 1)) # remember, GEOS-Chem defines z=1 as surface; MOZART says that's TOA b.close() ncfile.createVariable(moz_name, np.float32, dimensions=('time','lev','lat','lon')) ncfile.variables[moz_name][:] = np.concatenate(val, 0) ncfile.variables[moz_name].units = 'VMR'
def bpch(fi,group,tracer): from bpch import bpch ## print 'Using file: '+fi bc=bpch(fi) gr=bc.groups[str(group)] tracer=str(tracer) data=gr.variables[tracer] lat=bc.variables['latitude'] lon=bc.variables['longitude'] tau0 = bc.variables['tau0'] layer = bc.variables['layer'] return data, lat, lon, layer, tau0
def populate_times(self, bfiles): tmp_name_list = [] tmp_date_list = [] for filename in bfiles: f = bpch(filename) times = f.variables['time'] for t in times: tmp_date_list.append(gc_base_date + dt.timedelta(hours=t)) tmp_name_list.append(filename) date_list = sorted(tmp_date_list) name_list = [] for d in date_list: i = tmp_date_list.index(d) name_list.append(tmp_name_list[i]) return name_list, date_list
co = np.empty((len(files), len(lat_c), len(lon_c))) nox = np.empty((len(files), len(lat_c), len(lon_c))) acet = np.empty((len(files), len(lat_c), len(lon_c))) isop = np.empty((len(files), len(lat_c), len(lon_c))) c2h6 = np.empty((len(files), len(lat_c), len(lon_c))) c3h8 = np.empty((len(files), len(lat_c), len(lon_c))) ald2 = np.empty((len(files), len(lat_c), len(lon_c))) alk4 = np.empty((len(files), len(lat_c), len(lon_c))) ch2o = np.empty((len(files), len(lat_c), len(lon_c))) mek = np.empty((len(files), len(lat_c), len(lon_c))) prpe = np.empty((len(files), len(lat_c), len(lon_c))) for i in range(len(files)): data = bpch( files[i], tracerinfo= '/work/home/db876/modelling/GEOS_CHEM/v90103/2x2.5/2x2.5_GEOS5_fullgrid/run/valid_tracerinfo.dat' ) group_pl = data.groups['PORL-L=$'] po3 = group_pl.variables['PO3'] lo3 = group_pl.variables['LO3'] po3 = po3[:, 0, :, :] lo3 = lo3[:, 0, :, :] o3_prod[i, :, :] = po3 o3_loss[i, :, :] = lo3 #need to convert voc species from ppbC to ppbV by dividing by number of Carbon atoms in molecule group_ave = data.groups['IJ-AVG-$'] o3[i, :, :] = group_ave.variables['O3'][:, 0, :, :] co[i, :, :] = group_ave.variables['CO'][:, 0, :, :] nox[i, :, :] = group_ave.variables['NOx'][:, 0, :, :]
def define_dimensions(ncfile, filetimes): """ Defines all relevant dimensions in the netCDF file and writes any time invariant variables used to describe those dimensions. :param ncfile: an instance of netCDF4.Dataset that is the file to be written to :param filetimes: a FilesAndTimes instance listing all the BPCH files :return: """ if not isinstance(ncfile, ncdf.Dataset): raise TypeError('ncfile must be an instance of netCDF4.Dataset') if not isinstance(filetimes, FilesAndTimes): raise TypeError('filetimes must be an instance of FilesAndTimes') bfile = bpch(filetimes.files[0]) lon = bfile.variables['longitude'] lon[lon < 0] += 360 # MOZART gives longitude W as positive numbers where -179 -> 181 and -1 -> 359 lat = bfile.variables['latitude'] psurf = bfile.variables['PEDGE-$_PSURF'] # Write the dimensions ncfile.createDimension('lon', size=len(lon)) ncfile.createDimension('lat', size=len(lat)) ncfile.createDimension('lev', size=len(gc_hya_mid)) ncfile.createDimension('ilev', size=len(gc_hya)) ncfile.createDimension('time', size=0) # unlimited # and the variables that define their values ncfile.createVariable('lon', np.float32, dimensions=('lon')) ncfile.variables['lon'][:] = lon ncfile.variables['lon'].long_name = 'longitude' ncfile.variables['lon'].units = 'degrees_east' ncfile.createVariable('lat', np.float32, dimensions=('lat')) ncfile.variables['lat'][:] = lat ncfile.variables['lat'].long_name = 'latitude' ncfile.variables['lat'].units = 'degrees_north' # Time dimensions ncfile.createVariable('time', np.float64, dimensions=('time')) ncfile.variables['time'].long_name = 'simulation_time' ncfile.variables['time'].units = 'days since 0000-01-01' ncfile.variables['time'].calendar = 'gregorian' ncfile.createVariable('secs', np.int32, dimensions=('time')) ncfile.variables['secs'].long_name = 'seconds to complete elapsed days' ncfile.variables['secs'].units = 's' ncfile.createVariable('date', np.int32, dimensions=('time')) ncfile.variables[ 'date'].long_name = 'current date as 8 digit integer (YYYYMMDD)' ncfile.createVariable('datesec', np.int32, dimensions=('time')) ncfile.variables['datesec'].long_name = 'seconds to complete current date' ncfile.variables['datesec'].units = 's' date_int, date_sec, days_since, sec_since = mozdate_array( filetimes.datetimes) ncfile.variables['date'][:] = date_int ncfile.variables['datesec'][:] = date_sec ncfile.variables['time'][:] = days_since ncfile.variables['secs'][:] = sec_since # GEOS-Chem uses the hybrid sigma-eta coordinate system # (http://wiki.seas.harvard.edu/geos-chem/index.php/GEOS-Chem_vertical_grids#Vertical_grids_for_GEOS-5.2C_GEOS-FP.2C_MERRA.2C_and_MERRA-2) # and we usually run on the 47-layer reduced vertical grid. The A and B coefficients are given at the above link # and the formula for converting to actual pressure levels is given at # http://wiki.seas.harvard.edu/geos-chem/index.php/GEOS-Chem_vertical_grids#Hybrid_grid_definition # and is Pedge(I,J,L) = Ap(L) + [ Bp(L) * Psurface(I,J) ], Pcenter(I,J,L) = [ Pedge(I,J,L) + Pedge(I,J,L+1) ]/2 # # In MOZBC, pressures are computed as ps_mozi(I,J) * hybm + ps0 * hyam; where hybm and hyam are vectors (that are # the same for every column) of the A and B corefficients at level midpoints, ps_mozi is the MOZART surface pressure # interpolated to the WRF grid, and ps0 is just a constant, always 100000 Pa. The GEOS-Chem B parameter and the # MOZART B parameter are both unitless. The GC and MOZART A parameters just differ by a scaling factor, A_moz * P0 = # A_gc * 100 (GC A is in hPa, moz P0 has units of Pa). # # MOZART uses the GMAO standard that the first index in the vertical dimension is the top of the # atmosphere, whereas GEOS-Chem says the first index is the surface. ncfile.createVariable('lev', np.float32, dimensions='lev') ncfile.variables['lev'][:] = 1000 * (gc_hya_mid + gc_hyb_mid) ncfile.variables[ 'lev'].long_name = 'hybrid level at layer midpoints (1000*(A+B))' ncfile.variables['lev'].units = 'hybrid_sigma_pressure' ncfile.variables['lev'].positive = 'down' ncfile.variables['lev'].A_var = 'hyam' ncfile.variables['lev'].B_var = 'hybm' ncfile.variables['lev'].P0_var = 'P0' ncfile.variables['lev'].PS_var = 'PS' ncfile.variables['lev'].bounds = 'ilev' ncfile.createVariable('ilev', np.float32, dimensions='ilev') ncfile.variables['ilev'][:] = 1000 * (gc_hya + gc_hyb) ncfile.variables[ 'ilev'].long_name = 'hybrid level at layer interface (1000*(A+B))' ncfile.variables['ilev'].units = 'hybrid_sigma_pressure' ncfile.variables['ilev'].positive = 'down' ncfile.variables['ilev'].A_var = 'hyai' ncfile.variables['ilev'].B_var = 'hybi' ncfile.variables['ilev'].P0_var = 'P0' ncfile.variables['ilev'].PS_var = 'PS' ncfile.createVariable('hyam', np.float32, dimensions='lev') ncfile.variables['hyam'][:] = gc_hya_mid ncfile.variables[ 'hyam'].long_name = 'hybrid A coefficient at layer midpoints' ncfile.createVariable('hybm', np.float32, dimensions='lev') ncfile.variables['hybm'][:] = gc_hyb_mid ncfile.variables[ 'hybm'].long_name = 'hybrid B coefficient at layer midpoints' ncfile.createVariable('hyai', np.float32, dimensions='ilev') ncfile.variables['hyai'][:] = gc_hya ncfile.variables[ 'hyai'].long_name = 'hybrid A coefficient at layer interfaces' ncfile.createVariable('hybi', np.float32, dimensions='ilev') ncfile.variables['hybi'][:] = gc_hyb ncfile.variables[ 'hybi'].long_name = 'hybrid B coefficient at layer interfaces' ncfile.createVariable('P0', np.float32) # scalar ncfile.variables['P0'][:] = 1e5 ncfile.variables['P0'].long_name = 'reference pressure' ncfile.variables['P0'].units = 'Pa' bfile.close() # Surface pressure has a time component, so first we need to concatenate all the values ps_list = [] for fname in filetimes.unique_files(): b = bpch(fname) ps_list.append(b.variables['PEDGE-$_PSURF'][:, 0, :, :].squeeze() * 100) # get surface only and convert from hPa to Pa b.close() ncfile.createVariable('PS', np.float32, dimensions=('time', 'lat', 'lon')) ncfile.variables['PS'][:] = np.concatenate(ps_list, 0) ncfile.variables['PS'].units = 'Pa'
import glob import datetime as datetime species = 'O3' #set up plot fig = plt.figure(figsize=(20, 12)) ax = fig.add_axes([.05, .1, .9, .8]) fig.patch.set_facecolor('white') #bpch_fname = "bpch_files/4x5_GEOS5/ctm.bpch_4x5_GEOS5_2006-2012" bpch_fname = "/work/home/bn506/Rate_Sensetivity/Batch_runs/HO2_NO_p0/ctm.bpch" get_times = [1] f = bpch(bpch_fname) #,timeslice = get_times) #lat = f.dimensions['lat'] #lat = f.variables['lat'] #lon = f.variables['lon'] lat = np.arange(-88, 90, 4) lat = np.insert(lat, 0, -90) lat = np.append(lat, 90) lon = np.arange(-182.5, 179, 5) print lon tautime = f.variables['tau0'] tautime_end = f.variables['tau1']
def get_species_data_from_bpch(wd,species,group,month, debug=True): print 'Extracting data from the bpch.' bpch_fname = wd + month + ".ctm.bpch" # print months # for month in months: bpch_data = bpch(bpch_fname ) if debug: print 'Data groups:' print bpch_data.groups print 'Group species:' print bpch_data.groups[group].variables species_data = bpch_data.groups[group].variables[species] units = bpch_data.groups[group].variables[species].units start_time = bpch_data.groups[group].variables['tau0'] end_time = bpch_data.groups[group].variables['tau1'] start_time, end_time = extract_month(start_time, end_time) # #Turn species data from ppbv to moles #Convert from ppbv to species_moles air_mass = bpch_data.groups['BXHGHT-$'].variables['AD'] air_moles = (air_mass*1E3)# / ( 0.78*28.0 + 0.22*32.0 ) species_moles = air_moles * species_data # Get tropopause information Fraction_of_time_in_the_troposphere = bpch_data.groups["TIME-TPS"].variables['TIMETROP'] if debug: print Fraction_of_time_in_the_troposphere # Extract only moles in the troposphere # by multipling the 4d species concentrations by the fraction of time they were in the troposphere ( 1 = aff trop, 0 = no trop, other = tropopause ). species_moles = np.multiply(species_moles[:,:38,:,:] , Fraction_of_time_in_the_troposphere) if debug: print 'species_moles shape = ' + str(species_moles.shape) # get the total column moles. total_column = species_moles[0,:,:,:].sum( axis=0 ) # total_column[t,lat,lon] if debug: print' total_column shape = ' + str(total_column.shape) # Get the surface area print 'Getting the surface area.' surface_area = bpch_data.groups['DXYP'].variables['AREA'] if debug: print 'surface_area shape = ' + str(surface_area.shape) # surface_area[ lat, long ] #Convert from total mols to total Volume conversion_factor = 1E-7#1E-12 * 6.02e23 / 2.69e20 column_volume = np.multiply( total_column, conversion_factor ) #Convert to Dobson units. dobson_data = np.divide( column_volume , surface_area ) if debug: print 'dobson_data shape = ' + str(dobson_data.shape) return dobson_data, units, start_time, end_time;
def pacific_ol(area,dates,pacific_sat_dir,geos_dir,save_location,geosfilestr='ts_satellite_omi'): #==Options== #(ref_n,ref_s,ref_e,ref_w) = (40.,0.,180.,160.) #reference area. (ref_n,ref_s,ref_e,ref_w) = area #reference area. load_pickle = False #update an existing pickle (True) or create a new one (False) do_obs = True #work out median obs in reference sector do_geos = True #work out median model column in reference sector #dates first_date = date(2014,1,1) last_date = date(2014,12,31) (first_date,last_date) = dates #get a list of dates list_of_dates = [] dateclock = first_date while dateclock <= last_date: list_of_dates.append(dateclock) dateclock += td(days=1) #Load/save loaction #pickle_location = "/group_workspaces/jasmin/geoschem/local_users/lsurl/CL_PP/bark_2014b.p" #data locations #pacific_data_dir = "/group_workspaces/cems2/nceo_generic/nceo_ed/OMHCHO_pacific_bark/" #geos_dir = "/group_workspaces/jasmin/geoschem/local_users/lsurl/runs/geosfp_2x25_tropchem_2012-2014/" #==Processing== #assign dates to files if do_obs: files_in_obs_folder = [f for f in listdir(pacific_sat_dir) if isfile(join(pacific_sat_dir, f))] #all files in folder files_in_obs_folder = [f for f in files_in_obs_folder if f.startswith('OMI-Aura_L2-OMHCHO_')] #only OMI files obs_file_dates = [] for f in files_in_obs_folder: this_year = int(f[19:23]) this_month = int(f[24:26]) this_day= int(f[26:28]) obs_file_dates.append(date(this_year,this_month,this_day)) if do_geos: geosfilestr ='ts_satellite_omi' print "Looking for ND51 files that begin with '%s'." %geosfilestr files_in_geos_folder = [f for f in listdir(geos_dir) if isfile(join(geos_dir, f))] #all files in folder print len(files_in_geos_folder) #print files_in_geos_folder files_in_geos_folder = [f for f in files_in_geos_folder if f.startswith(geosfilestr)] #only ND51 files print len(files_in_geos_folder) geos_file_dates = [] for f in files_in_geos_folder: this_year = int(f[len(geosfilestr)+1:len(geosfilestr)+5]) this_month = int(f[len(geosfilestr)+5:len(geosfilestr)+7]) this_day= int(f[len(geosfilestr)+7:len(geosfilestr)+9]) geos_file_dates.append(date(this_year,this_month,this_day)) all_corrections = [] #Cycle through dates for dateclock in list_of_dates: today_correction = correction(dateclock) #observation median if do_obs: today_files = [files_in_obs_folder[i] for i in range(0,len(files_in_obs_folder)) if obs_file_dates[i] == dateclock] today_SC = np.array([]) for f in today_files: try: f_HDF = h5py.File(join(pacific_sat_dir, f)) except IOError: #dud files #print "Cannot open %s" %f continue #shorthands df = f_HDF['HDFEOS']['SWATHS']['OMI Total Column Amount HCHO']['Data Fields'] gf = f_HDF['HDFEOS']['SWATHS']['OMI Total Column Amount HCHO']['Geolocation Fields'] #get data this_lat = np.array(gf['Latitude']).flatten() this_lon = np.array(gf['Longitude']).flatten() this_SC = np.array(df['ColumnAmount']).flatten() this_XTQF = np.array(gf['XtrackQualityFlags']).flatten() this_MDQF = np.array(df['MainDataQualityFlag']).flatten() #geo and quality filter keep = np.logical_and.reduce((this_lat > ref_s, this_lat < ref_n, this_lon > ref_w, this_lon < ref_e, this_XTQF == 0, this_MDQF == 0, this_SC != np.nan)) this_SC = this_SC[keep] #print len(this_SC) today_SC = np.append(today_SC,this_SC) today_correction.med_obs = np.median(today_SC) print "Median observed slant column for %s: %g" %(dateclock.strftime("%Y-%m-%d"),today_correction.med_obs) #geos median if do_geos: today_files = [files_in_geos_folder[i] for i in range(0,len(files_in_geos_folder)) if geos_file_dates[i] == dateclock] if len(today_files) != 1: today_correction.med_geos = np.nan print "Median modelled vertical column for %s: nan" %dateclock.strftime("%Y-%m-%d") else: f = bpch(join(geos_dir, today_files[0])) this_hcho = np.array(f.variables["IJ-AVG-$_CH2O"]) * 1e-9 #convert to v/v box_height = np.array(f.variables['BXHGHT-$_BXHEIGHT']) * 100 #box height in cm air_den = np.array(f.variables['TIME-SER_AIRDEN']) # air density molec.cm-3 air_amount = np.multiply(box_height,air_den) #air per grid box molec.cm-2 this_data_col = np.sum(np.multiply(this_hcho,air_amount),axis=1) #column molec.cm-2 today_correction.med_geos = np.median(this_data_col) print "Median modelled vertical column for %s: %g" %(dateclock.strftime("%Y-%m-%d"),today_correction.med_geos) all_corrections.append(today_correction) print "saving..." cPickle.dump(all_corrections,open(save_location,"wb"))
no2_prod = np.empty((len(files), 91, 144)) no2_loss = np.empty((len(files), 91, 144)) ox_prod = np.empty((len(files), 91, 144)) ox_loss = np.empty((len(files), 91, 144)) o3_ave = np.empty((len(files), 91, 144)) no2_ave = np.empty((len(files), 91, 144)) no_ave = np.empty((len(files), 91, 144)) isop_ave = np.empty((len(files), 91, 144)) up_flx = np.empty((len(files), 91, 144)) for i in range(len(files)): data = bpch(files[i], tracerinfo='valid_tracerinfo.dat') group_pl = data.groups['PORL-L=$'] group_ave = data.groups['IJ-AVG-$'] group_up = data.groups['UP-FLX-$'] po3 = group_pl.variables['PO3'] print po3.units lo3 = group_pl.variables['LO3'] pno2 = group_pl.variables['PNO2'] lno2 = group_pl.variables['LNO2'] pox = group_pl.variables['POX'] lox = group_pl.variables['LOX'] o3_a = group_ave.variables['O3'] no_a = group_ave.variables['NOx'] #no2_a = group_ave.variables['NO2'] isop_a = group_ave.variables['ISOP']
def get_species_data_from_bpch(wd, species, group, month, debug=True): print 'Extracting data from the bpch.' bpch_fname = wd + month + ".ctm.bpch" # print months # for month in months: bpch_data = bpch(bpch_fname) if debug: print 'Data groups:' print bpch_data.groups print 'Group species:' print bpch_data.groups[group].variables species_data = bpch_data.groups[group].variables[species] units = bpch_data.groups[group].variables[species].units start_time = bpch_data.groups[group].variables['tau0'] end_time = bpch_data.groups[group].variables['tau1'] start_time, end_time = extract_month(start_time, end_time) # #Turn species data from ppbv to moles #Convert from ppbv to species_moles air_mass = bpch_data.groups['BXHGHT-$'].variables['AD'] air_moles = (air_mass * 1E3) # / ( 0.78*28.0 + 0.22*32.0 ) species_moles = air_moles * species_data # Get tropopause information Fraction_of_time_in_the_troposphere = bpch_data.groups[ "TIME-TPS"].variables['TIMETROP'] if debug: print Fraction_of_time_in_the_troposphere # Extract only moles in the troposphere # by multipling the 4d species concentrations by the fraction of time they were in the troposphere ( 1 = aff trop, 0 = no trop, other = tropopause ). species_moles = np.multiply(species_moles[:, :38, :, :], Fraction_of_time_in_the_troposphere) if debug: print 'species_moles shape = ' + str(species_moles.shape) # get the total column moles. total_column = species_moles[0, :, :, :].sum( axis=0) # total_column[t,lat,lon] if debug: print ' total_column shape = ' + str(total_column.shape) # Get the surface area print 'Getting the surface area.' surface_area = bpch_data.groups['DXYP'].variables['AREA'] if debug: print 'surface_area shape = ' + str(surface_area.shape) # surface_area[ lat, long ] #Convert from total mols to total Volume conversion_factor = 1E-7 #1E-12 * 6.02e23 / 2.69e20 column_volume = np.multiply(total_column, conversion_factor) #Convert to Dobson units. dobson_data = np.divide(column_volume, surface_area) if debug: print 'dobson_data shape = ' + str(dobson_data.shape) return dobson_data, units, start_time, end_time
import glob import datetime as datetime species = 'CHBr3' #set up plot fig=plt.figure(figsize=(20,12)) ax = fig.add_axes([.05, .1, .9, .8]) fig.patch.set_facecolor('white') #bpch_fname = "bpch_files/4x5_GEOS5/ctm.bpch_4x5_GEOS5_2006-2012" bpch_fname = "/home/bn506/GEOS-Run/Budget/Flex/ctm.bpch" get_times = [4,5,6,8,9] f = bpch(bpch_fname,timeslice = get_times) #lat = f.dimensions['lat'] #lat = f.variables['lat'] #lon = f.variables['lon'] lat = np.arange(-88,90,4) lat = np.insert(lat,0,-90) lat = np.append(lat,90) lon = np.arange(-182.5,179,5) print lon tautime = f.variables['tau0'] tautime_end = f.variables['tau1']
o3_loss = np.empty((len(files),len(lat_c),len(lon_c))) o3 = np.empty((len(files),len(lat_c),len(lon_c))) co = np.empty((len(files),len(lat_c),len(lon_c))) nox = np.empty((len(files),len(lat_c),len(lon_c))) acet = np.empty((len(files),len(lat_c),len(lon_c))) isop = np.empty((len(files),len(lat_c),len(lon_c))) c2h6 = np.empty((len(files),len(lat_c),len(lon_c))) c3h8 = np.empty((len(files),len(lat_c),len(lon_c))) ald2 = np.empty((len(files),len(lat_c),len(lon_c))) alk4 = np.empty((len(files),len(lat_c),len(lon_c))) ch2o = np.empty((len(files),len(lat_c),len(lon_c))) mek = np.empty((len(files),len(lat_c),len(lon_c))) prpe = np.empty((len(files),len(lat_c),len(lon_c))) for i in range(len(files)): data = bpch(files[i],tracerinfo='/work/home/db876/modelling/GEOS_CHEM/v90103/2x2.5/2x2.5_GEOS5_fullgrid/run/valid_tracerinfo.dat') group_pl = data.groups['PORL-L=$'] po3 = group_pl.variables['PO3'] lo3 = group_pl.variables['LO3'] po3 = po3[:,0,:,:] lo3 = lo3[:,0,:,:] o3_prod[i,:,:] = po3 o3_loss[i,:,:] = lo3 #need to convert voc species from ppbC to ppbV by dividing by number of Carbon atoms in molecule group_ave = data.groups['IJ-AVG-$'] o3[i,:,:] = group_ave.variables['O3'][:,0,:,:] co[i,:,:] = group_ave.variables['CO'][:,0,:,:] nox[i,:,:] = group_ave.variables['NOx'][:,0,:,:] acet[i,:,:] = group_ave.variables['ACET'][:,0,:,:]/3. isop[i,:,:] = group_ave.variables['ISOP'][:,0,:,:]/5.
def define_dimensions(ncfile, filetimes): """ Defines all relevant dimensions in the netCDF file and writes any time invariant variables used to describe those dimensions. :param ncfile: an instance of netCDF4.Dataset that is the file to be written to :param filetimes: a FilesAndTimes instance listing all the BPCH files :return: """ if not isinstance(ncfile, ncdf.Dataset): raise TypeError('ncfile must be an instance of netCDF4.Dataset') if not isinstance(filetimes, FilesAndTimes): raise TypeError('filetimes must be an instance of FilesAndTimes') bfile = bpch(filetimes.files[0]) lon = bfile.variables['longitude'] lon[lon<0] += 360 # MOZART gives longitude W as positive numbers where -179 -> 181 and -1 -> 359 lat = bfile.variables['latitude'] psurf = bfile.variables['PEDGE-$_PSURF'] # Write the dimensions ncfile.createDimension('lon', size=len(lon)) ncfile.createDimension('lat', size=len(lat)) ncfile.createDimension('lev', size=len(gc_hya_mid)) ncfile.createDimension('ilev', size=len(gc_hya)) ncfile.createDimension('time', size=0) # unlimited # and the variables that define their values ncfile.createVariable('lon', np.float32, dimensions=('lon')) ncfile.variables['lon'][:] = lon ncfile.variables['lon'].long_name = 'longitude' ncfile.variables['lon'].units = 'degrees_east' ncfile.createVariable('lat', np.float32, dimensions=('lat')) ncfile.variables['lat'][:] = lat ncfile.variables['lat'].long_name = 'latitude' ncfile.variables['lat'].units = 'degrees_north' # Time dimensions ncfile.createVariable('time', np.float64, dimensions=('time')) ncfile.variables['time'].long_name = 'simulation_time' ncfile.variables['time'].units = 'days since 0000-01-01' ncfile.variables['time'].calendar = 'gregorian' ncfile.createVariable('secs', np.int32, dimensions=('time')) ncfile.variables['secs'].long_name = 'seconds to complete elapsed days' ncfile.variables['secs'].units = 's' ncfile.createVariable('date', np.int32, dimensions=('time')) ncfile.variables['date'].long_name = 'current date as 8 digit integer (YYYYMMDD)' ncfile.createVariable('datesec', np.int32, dimensions=('time')) ncfile.variables['datesec'].long_name = 'seconds to complete current date' ncfile.variables['datesec'].units = 's' date_int, date_sec, days_since, sec_since = mozdate_array(filetimes.datetimes) ncfile.variables['date'][:] = date_int ncfile.variables['datesec'][:] = date_sec ncfile.variables['time'][:] = days_since ncfile.variables['secs'][:] = sec_since # GEOS-Chem uses the hybrid sigma-eta coordinate system # (http://wiki.seas.harvard.edu/geos-chem/index.php/GEOS-Chem_vertical_grids#Vertical_grids_for_GEOS-5.2C_GEOS-FP.2C_MERRA.2C_and_MERRA-2) # and we usually run on the 47-layer reduced vertical grid. The A and B coefficients are given at the above link # and the formula for converting to actual pressure levels is given at # http://wiki.seas.harvard.edu/geos-chem/index.php/GEOS-Chem_vertical_grids#Hybrid_grid_definition # and is Pedge(I,J,L) = Ap(L) + [ Bp(L) * Psurface(I,J) ], Pcenter(I,J,L) = [ Pedge(I,J,L) + Pedge(I,J,L+1) ]/2 # # In MOZBC, pressures are computed as ps_mozi(I,J) * hybm + ps0 * hyam; where hybm and hyam are vectors (that are # the same for every column) of the A and B corefficients at level midpoints, ps_mozi is the MOZART surface pressure # interpolated to the WRF grid, and ps0 is just a constant, always 100000 Pa. The GEOS-Chem B parameter and the # MOZART B parameter are both unitless. The GC and MOZART A parameters just differ by a scaling factor, A_moz * P0 = # A_gc * 100 (GC A is in hPa, moz P0 has units of Pa). # # MOZART uses the GMAO standard that the first index in the vertical dimension is the top of the # atmosphere, whereas GEOS-Chem says the first index is the surface. ncfile.createVariable('lev', np.float32, dimensions='lev') ncfile.variables['lev'][:] = 1000*(gc_hya_mid + gc_hyb_mid) ncfile.variables['lev'].long_name = 'hybrid level at layer midpoints (1000*(A+B))' ncfile.variables['lev'].units = 'hybrid_sigma_pressure' ncfile.variables['lev'].positive = 'down' ncfile.variables['lev'].A_var = 'hyam' ncfile.variables['lev'].B_var = 'hybm' ncfile.variables['lev'].P0_var = 'P0' ncfile.variables['lev'].PS_var = 'PS' ncfile.variables['lev'].bounds = 'ilev' ncfile.createVariable('ilev', np.float32, dimensions='ilev') ncfile.variables['ilev'][:] = 1000*(gc_hya + gc_hyb) ncfile.variables['ilev'].long_name = 'hybrid level at layer interface (1000*(A+B))' ncfile.variables['ilev'].units = 'hybrid_sigma_pressure' ncfile.variables['ilev'].positive = 'down' ncfile.variables['ilev'].A_var = 'hyai' ncfile.variables['ilev'].B_var = 'hybi' ncfile.variables['ilev'].P0_var = 'P0' ncfile.variables['ilev'].PS_var = 'PS' ncfile.createVariable('hyam', np.float32, dimensions='lev') ncfile.variables['hyam'][:] = gc_hya_mid ncfile.variables['hyam'].long_name = 'hybrid A coefficient at layer midpoints' ncfile.createVariable('hybm', np.float32, dimensions='lev') ncfile.variables['hybm'][:] = gc_hyb_mid ncfile.variables['hybm'].long_name = 'hybrid B coefficient at layer midpoints' ncfile.createVariable('hyai', np.float32, dimensions='ilev') ncfile.variables['hyai'][:] = gc_hya ncfile.variables['hyai'].long_name = 'hybrid A coefficient at layer interfaces' ncfile.createVariable('hybi', np.float32, dimensions='ilev') ncfile.variables['hybi'][:] = gc_hyb ncfile.variables['hybi'].long_name = 'hybrid B coefficient at layer interfaces' ncfile.createVariable('P0', np.float32) # scalar ncfile.variables['P0'][:] = 1e5 ncfile.variables['P0'].long_name = 'reference pressure' ncfile.variables['P0'].units = 'Pa' bfile.close() # Surface pressure has a time component, so first we need to concatenate all the values ps_list = [] for fname in filetimes.unique_files(): b = bpch(fname) ps_list.append(b.variables['PEDGE-$_PSURF'][:,0,:,:].squeeze()*100) # get surface only and convert from hPa to Pa b.close() ncfile.createVariable('PS', np.float32, dimensions=('time', 'lat', 'lon')) ncfile.variables['PS'][:] = np.concatenate(ps_list, 0) ncfile.variables['PS'].units = 'Pa'