Exemplo n.º 1
0
def read_gc(fname,varname,cat='IJ-AVG-$',
            gc_dir = '/short/m19/jaf574/GC.v11-01/runs.v11-02e/geosfp_025x03125_tropchem_au.base/',
            **kwargs):

    # Some species involve multiple GEOS-Chem species...
    varname_gc = gcname_to_names(varname)

    # Expand wildcard if necessary and link to directory
    if '*' in fname:
        fname = glob(gc_dir+fname)
    else:
        fname = [gc_dir + f for f in fname]
    # Put files in order!
    fname.sort()

    # Read using xbpch
    # one file
    if isinstance(fname,str):
       ds = open_bpchdataset(fname,categories=[cat,],fields=varname_gc,
                             diaginfo_file=gc_dir+'diaginfo.dat',
                             tracerinfo_file=gc_dir+'tracerinfo.dat',**kwargs)

    # multiple files
    else:
       ds = open_mfbpchdataset(fname,dask=True,categories=[cat,],fields=varname_gc,
                             diaginfo_file=gc_dir+'diaginfo.dat',
                             tracerinfo_file=gc_dir+'tracerinfo.dat',**kwargs)

    # load dataset
    ds.load()

    # extract variables
    cat=cat.replace('$','S').replace('-','_')
    dfg = ds[[cat+'_'+v for v in varname_gc]]

    # If needed, sum GEOS-Chem variables
    if len(varname_gc) > 1:
        dfg = sum_gc_vars(dfg, [cat+'_'+v for v in varname_gc],
                                varname=cat+'_'+varname)

    return dfg
Exemplo n.º 2
0
    # Print month
    print('Processing month: {}'.format(mstr))

    # File names (EDIT THESE ACCORDINGLY)
    bpch_file = join(bpchdir, 'trac_avg.GC_12.4.0.2016{}01'.format(mstr))
    tinfo_file = join(bpchdir, 'tracerinfo.dat')
    dinfo_file = join(bpchdir, 'diaginfo.dat')
    ncfile = join(ncdir, 'GEOSChem.TagCOInputs.2016{}01.nc'.format(mstr))    

    # Open the bpch file and save it into an xarray Dataset object
    # NOTE: For best results, also specify the corresponding
    # tracerinfo.dat diaginfo.dat metadata files.
    try:
        ds = xb.open_bpchdataset(filename=bpch_file,
                                 tracerinfo_file=tinfo_file,
                                 diaginfo_file=dinfo_file)
    except FileNotFoundError:
        print('Could not find file {}'.format(bpch_file))
        raise

    # ------------------------------------------------------------------
    # Further manipulate the Dataset
    # ------------------------------------------------------------------
    
    # Only extract the bpch fields we need for the tagged CO
    varlist = ['PORL_L_S_PCO', 'PORL_L_S_LCO', 
               'PORL_L_S_PCO_CH4', 'PORL_L_S_PCO_NMVO']
    ds = ds[varlist]

    # Transpose the order of the xarray Dataset object read by
Exemplo n.º 3
0
For a given field timeseries, compute seasonal averages over all data and
plot each average on a four-panel figure.
"""
# Author: Daniel Rothenberg
# Version: June 2, 2017

import matplotlib.pyplot as plt
plt.style.use(['seaborn-talk', 'seaborn-ticks'])

import xbpch

# First we read in a sample dataset containing GEOS-Chem output
ds = xbpch.open_bpchdataset(
    "/Users/daniel/workspace/bpch/test_data/ref_e2006_m2008.bpch",
    diaginfo_file="/Users/daniel/Desktop/sample_nd49/diaginfo.dat",
    tracerinfo_file="/Users/daniel/Desktop/sample_nd49/tracerinfo.dat",
    dask=True,
    memmap=True)

# Compute seasonal averages by doing splitting along the "seasons" corresponding
# to each timestep, and taking the average over time in that group
seasonal_o3 = (
    ds['IJ_AVG_S_O3'].isel(lev=0)  # select just surface values
    .groupby('time.season').mean('time'))
print(seasonal_o3)

# Note that we now have a new dimension, "season", corresponding to the groups
# we split the dataset by. We can use this dimension as a 'facet' to assemble
# a collection of plots.
# TODO: Cleanup axis proportions
import cartopy.crs as ccrs
Exemplo n.º 4
0
        print("ERROR: Couldn't find the following input files:")
        for fn in bad_files:
            print("   " + fn)
        sys.exit(1)

    # Else, we should be good to read in and concatenate
    open_kws = {
        "tracerinfo_file": args.tracerinfo,
        "diaginfo_file": args.diaginfo,
        "memmap": True,
        "dask": True
    }

    print("\nReading in file(s)...")
    if len(args.bpch_files) == 1:
        ds = open_bpchdataset(args.bpch_files[0], **open_kws)
    else:
        ds = open_mfbpchdataset(args.bpch_files, **open_kws)

    # This block of code is hack to fix the encoding of attributes
    # on the DataArrays in this Dataset. They are being
    # set at a very low level when we read in the data, and manually
    # specifying the encoding doesn't work.
    # However, deleting them from the attributes dict
    # doesn't end up removing them from the final output file - they get
    # written just fine.
    print("\nDecoding variables...")
    for v in ds.data_vars:
        da = ds[v]
        da = _maybe_del_attr(da, 'scale_factor')
        da = _maybe_del_attr(da, 'units')
Exemplo n.º 5
0
def bpch_2_netcdf(
    bpchfile,  # Name of Bpch file
    tinfo_file,  # tracerinfo.dat and diaginfo,dat fiels
    dinfo_file,
    ncfile,  # Name of netCDF file
    interval=86400.0 * 31.0
):  # Number of seconds in the diagnostic interval (assume 1-month), does not matter for CO2
    # ----------------------------------------------------------------------
    # Open the bpch file and save it into an xarray Dataset object
    # NOTE: For best results, also specify the corresponding
    # tracerinfo.dat diaginfo.dat metadata files.
    # ----------------------------------------------------------------------
    try:
        ds = xb.open_bpchdataset(filename=bpchfile,
                                 tracerinfo_file=tinfo_file,
                                 diaginfo_file=dinfo_file)
    except FileNotFoundError:
        print('Could not find file {}'.format(bpchfile))
        raise

# ----------------------------------------------------------------------
# Further manipulate the Dataset
# ----------------------------------------------------------------------

# Transpose the order of the xarray Dataset object read by
# xbpch so that its dimensions will be in the same order as
# Dataset objects read from netCDF files.
    ds = ds.transpose()

    # Convert the bpch variable names to the same naming
    # convention as the netCDF ("History") diagnostics.
    ds = core.convert_bpch_names_to_netcdf_names(ds)

    # xbpch does not include a time dimension, so we'll add one here
    coords = ds.coords
    coords['time'] = 0.0

    # ------------------------------------------------------------------
    # Further edit variable attributes
    # ------------------------------------------------------------------
    for v in ds.data_vars.keys():

        # Append time to the data array
        ds[v] = xr.concat([ds[v]], 'time')

        # Add long_name attribute for COARDS netCDF compliance
        ds[v].attrs['long_name'] = ds[v].attrs['full_name']

        # Remove some extraneous attributes that xbpch sets
        del ds[v].attrs['name']
        del ds[v].attrs['full_name']
        del ds[v].attrs['scale_factor']
        del ds[v].attrs['hydrocarbon']
        del ds[v].attrs['tracer']
        del ds[v].attrs['category']
        del ds[v].attrs['chemical']
        del ds[v].attrs['original_shape']
        del ds[v].attrs['origin']
        del ds[v].attrs['number']
        del ds[v].attrs['molwt']
        del ds[v].attrs['C']

        # Make the units attribute consistent with the units
        # attribute from the GEOS-Chem History diagnostics
        # NOTE: There probably is a more Pythonic way to code
        # this, but this will work for sure.
        if 'ug/m3' in ds[v].units:
            ds[v].attrs['units'] = 'ug m-3'
        if 'ug Celsius/m3' in ds[v].units:
            ds[v].attrs['units'] = 'ug C m-3'
        if 'count/cm3' in ds[v].units:
            ds[v].attrs['units'] = 'molec m-3'
        if 'cm/s' in ds[v].units:
            ds[v].attrs['units'] = 'cm s-1'
        if 'count/cm2/s' in ds[v].units:
            ds[v].attrs['units'] = 'molec cm-2 s-1'
        if 'kg/m2s' in ds[v].units:
            ds[v].attrs['units'] = 'kg m-2 s-1'
        if 'kg/m2/s' in ds[v].units:
            ds[v].attrs['units'] = 'kg m-2 s-1'
        if 'kg/s' in ds[v].units:
            ds[v].attrs['units'] = 'kg s-1'
        if 'W/m2' in ds[v].units:
            ds[v].attrs['units'] = 'W m-2'
        if 'm/s' in ds[v].units:
            ds[v].attrs['units'] = 'm s-1'
        if 'Pa/s' in ds[v].units:
            ds[v].attrs['units'] = 'Pa s-1'
        if 'g/kg' in ds[v].units:
            ds[v].attrs['units'] = 'g kg-1'
        if v.strip() == 'TotalOC':
            ds[v].attrs['units'] = 'ug m-3'
        if v.strip() in ['HO2concAfterChem']:
            ds[v].attrs['units'] = 'ppb'
        if v.strip() in [
                'O1DconcAfterChem', 'O3PconcAfterChem', 'OHconcAfterChem'
        ]:
            ds[v].attrs['units'] = 'molec cm-3'
        if v.strip() in [
                'Loss_CO', 'Prod_CO', 'Loss_Ox', 'Prod_Ox', 'Prod_SO4'
        ]:
            ds[v].attrs['units'] = 'molec/cm3/s'
        if v.strip() in 'Met_CLDTOPS':
            ds[v].attrs['units'] = 'level'
        if v.strip() in 'Met_PHIS':
            ds[v].attrs['units'] = 'm2 s-1'
        if v.strip() in ['Met_PRECCON', 'Met_PRECTOT']:
            ds[v].attrs['units'] = 'kg m-2 s-1'
        if v.strip() in 'Met_AVGW':
            ds[v].attrs['units'] = 'vol vol-1'
        if v.strip() in 'Met_AIRNUMDEN':
            ds[v].attrs['units'] = 'molec cm-3'
        if v.strip() in ['ProdCOfromCH4', 'ProdCOfromNMVOC']:
            ds[v].attrs['units'] = 'molec cm-3 s-1'

        # Convert these prodloss diagnostics from kg (bpch) to kg/s
        # to be consistent with the GEOS-Chem History diagnostics
        # NOTE: Assume a 1-month interval (
        if v.strip() in [
                'ProdSO4fromH2O2inCloud', 'ProdSO4fromO3inCloud',
                'ProdSO4fromO2inCloudMetal', 'ProdSO4fromO3inSeaSalt',
                'ProdSO4fromHOBrInCloud', 'ProdSO4fromSRO3',
                'ProdSO4fromSRHObr', 'ProdSO4fromO3s'
        ]:
            ds[v].attrs['units'] = 'kg S s-1'
            ds[v] = ds[v] / interval
        if v.strip() in ['LossHNO3onSeaSalt']:
            ds[v].attrs['units'] = 'kg s-1'
            ds[v] = ds[v] / interval

# ------------------------------------------------------------------
# Edit attributes for coordinate dimensions
# ------------------------------------------------------------------

# Time
    ds['time'].attrs['long_name'] = 'time'
    #ds['time'].attrs['units'] = \
    #    'hours since {} 00:00:00.00 UTC'.format(datestr)
    ds['time'].attrs['calendar'] = 'standard'
    ds['time'].attrs['axis'] = 'T'

    # "lon", "lat", "lev"
    ds['lon'].attrs['axis'] = 'X'
    ds['lat'].attrs['axis'] = 'Y'
    ds['lev'].attrs['axis'] = 'Z'
    ds['lev'].attrs['units'] = 'level'

    # Global title
    ds.attrs['title'] = 'Created by bpch2nc.py'
    ds.attrs['conventions'] = 'COARDS'
    ds.attrs['references'] = 'www.geos-chem.org; wiki.geos-chem.org'

    # ------------------------------------------------------------------
    # Create the netCDF file
    # ------------------------------------------------------------------
    ds.to_netcdf(ncfile)
Exemplo n.º 6
0
def read_bpch(path,keys):
    '''
        Read  generic bpch file into dictionary
        keys = keys you want to read
    '''
    paths=path
    if __VERBOSE__:
        print('GC_fio.read_bpch called on paths:')
        print(path)
    multi=False
    if isinstance(path,list):
        path=path[0]
        if len(path) > 1:
            multi=True
    if '*' in path:
        multi=True

    # make sure coordinates are in keys list
    keys = list(set(keys + GC_coords)) # set removes any duplicates

    # assume tracerinfo and diaginfo in same folder:
    # otherwise use my generic one with coalesced info
    splt=path.split('/')
    splt[-1]='tracerinfo.dat'
    tracinf='/'.join(splt)
    if not os.path.isfile(tracinf):
        tracinf='Data/GC_Output/tracerinfo.dat'

    splt[-1]='diaginfo.dat'
    diaginf='/'.join(splt)
    if not os.path.isfile(diaginf):
        diaginf='Data/GC_Output/diaginfo.dat'


    # Improve read performance by only reading requested fields:
    fields=set(); categories=set()
    for key in keys:
        if '_' in key:
            # Split key on the underscores: Category_Field
            c,_,f = key.rpartition('_')
            categories.add(c)
            fields.add(f)
        else:
            fields.add(key)
    if __VERBOSE__:
        print("categories: ",categories)
        print("fields: ",fields)

    # get bpch file:
    data={}
    attrs={}
    bpchargs={'fields':list(fields), 'categories':list(categories),
              'tracerinfo_file':tracinf,'diaginfo_file':diaginf,
              'decode_cf':False,'dask':True}
    mod_times=[]
    if multi:
        ds=open_mfbpchdataset(paths,**bpchargs)
        for p in paths:
            mod_times.append(time.ctime(os.path.getmtime(p)))
    else:
        ds=open_bpchdataset(path,**bpchargs)
        mod_times=[time.ctime(os.path.getmtime(path))]

    data,attrs=dataset_to_dicts(ds,keys)
    data['modification_times']=np.array(mod_times)
    attrs['modification_times']={'desc':'When was file last modified'}
    return data,attrs
Exemplo n.º 7
0
    # lets check for a few dimensions:
    for dims in [ [10,1,1], [100,100,100]]:
        print("testing dummy trop column calculation for dims %s"%str(dims))
        ppbv=np.zeros(dims)+100.    # molec/1e9molecA
        N_air=np.zeros(dims)+1e13   # molecA/m3
        boxH=np.zeros(dims)+1.      # m
        tplev=np.zeros([dims[1],dims[2]]) + 4.4
        # should give 100molec/cm2 per level : tropcol = 440molec/cm2
        out= determine_trop_column(ppbv, N_air, boxH, tplev)
        assert out.shape==(dims[1],dims[2]), 'trop column calc shape is wrong'
        print("PASS: shape is ok from intputs to output")
        assert np.isclose(out[0,0],440.0), 'trop column calc value is wrong, out=%f'%out[0,0]
        print("PASS: Calculated trop column is OK")
        assert np.isclose(np.min(out), np.max(out)), 'Trop column calc has some problem'
        print("PASS: every box matches")



if __name__=='__main__':
    #get_tropchem_data()
    _test_trop_column_calc()

    # How to check fields
    sat_fold='Data/GC_Output/geos5_2x25_tropchem/satellite_output/'
    sat_file=sat_fold+'ts_satellite_omi.20050101.bpch'
    tracinf=sat_fold+'tracerinfo.dat'
    diaginf=sat_fold+'diaginfo.dat'

    ds=open_bpchdataset(sat_file,tracerinfo_file=tracinf,diaginfo_file=diaginf)
    ds.keys()