barronh / pseudonetcdf

PseudoNetCDF like NetCDF except for many scientific format backends
GNU Lesser General Public License v3.0
77 stars 35 forks source link

Make CAMx inputs from new NWP #22

Closed environ88 closed 7 years ago

environ88 commented 7 years ago

I have a NWP model that I want to drive the CAMx model but is not one of the standard model (MM5, WRF, RAMS) supported by CAMx. Does Pseudonetcdf allows me to convert more general NWP data format such as Netcdf or Grib1 to CAMx format ? Thanks in advance for your help.

barronh commented 7 years ago

PseudoNetCDF can read many formats (NetCDF=yes, grib1=not yet) and write out many formats (all CAMx binary inputs=yes).

I would start by trying to create input data from your NWP for a known case, like the CAMx testcase. The code below should get you started. It was written as a quick response and may contain typos.

import shutil
from PseudoNetCDF import PNC
input_nc_path = '/path/to/some/file.nc'
template_uamiv_path = '/path/to/camx/testcase/camxv6.2d_met.20020603.12k.bin'
output_uamiv_path = '/path/to/camx/newcase/input.uamiv'

# copy an existing file
shutil.copy(template_uamiv_path, output_uamiv_path)

# pncargs includes all specified and inferred options as well as
# ifiles - a list of read files
inpncargs = PNC(input_nc_path)
infile = inpncargs.ifiles[0]
outpncargs = PNC('--format=uamiv,mode=“r+“', output_uamiv_path)
outfile = outpncargs.ifiles[0]

# this is where we update the input variables
for varkey, varobj in outfile.variables.items():
    # ... create a variable of new values newvalues ...
    #     ... get a variable from infile ...
    #     ... do some processing and data translation ...
    # ... newvalues must be consistent in shape and units (see CAMx mannual) ...
    # ... as a silly example, I set the new values to the old values ...
    newvalues = varobj[:]

    # Assign new values to variable
    varobj[:] = newvalues
    # Syncing is not strictly necessary, but always make me feel safer
    outfile.sync()

# For a known case that is intended to be the same, this might not be necessary
for propkey in outfile.ncattrs():
    oldpropval = getattr(outfile, propkey)
    # ... create a variable with the new value
    # ... as a silly example, I set the new value to the old value ...
    newpropval = oldpropval
    setattr(outfile, propkey, newpropval)
    print(propk, 'old:', oldpropval, 'new:', newpropval)

You can also create CAMx inputs without copying an existing one. That relies more on creating a PseudoNetCDF file and variables that look like a CAMx file. To see one, run the following command:

pncdump --header --format=uamiv /path/to/camx/testcase/camxv6.2d_met.20020603.12k.bin

You can create one with commands like:

from PseudoNetCDF import PseudoNetCDFFile
from PseudoNetCDF.pncgen import pncgen

newf = PseudoNetCDFFile()
newf.createDimension('TSTEP', 25)
newf.createDimension('LAY', ?)
newf.createDimension('ROW', ?)
newf.createDimension('COL', ?)
newf.createDimension('DATE-TIME', 2)
newf.createDimension('VAR', ?)
newf.NROWS = ?
newf.NCOLS = ?
...
newf.XORIG = ?
...
newf.createDimension('COL', ?)

var = newf.createVariable(...)
var.units = '...'
var[:] = '...'

pncgen(newf, '/path/for/output.bin', format = 'uamiv')