def test_writeGrid(self): ATM_MODEL_DFILES = os.getenv('ATM_MODEL_DFILES') file0 = os.path.join(ATM_MODEL_DFILES.strip(),'bcmk/geophy.fst') funit = rmn.fstopenall(file0) rec = rmn.fstlir(funit, nomvar='ME') grid0 = rmn.readGrid(funit, rec) rmn.fstcloseall(funit) grid1 = rmn.defGrid_L(180,60,0.,180.,1.,0.5) grid2 = rmn.defGrid_ZE(90,45,10.,11.,1.,0.5,0.,180.,1.,270.) grid3 = rmn.defGrid_YY(31,5,0.,180.,1.,270.) self.erase_testfile() myfile = self.fname funit = rmn.fstopenall(myfile, rmn.FST_RW) rmn.fstecr(funit,rec['d'],rec) rmn.writeGrid(funit, grid0) rmn.writeGrid(funit, grid1) rmn.writeGrid(funit, grid2) rmn.writeGrid(funit, grid3) rmn.fstcloseall(funit) funit = rmn.fstopenall(myfile, rmn.FST_RO) rec = rmn.fstlir(funit, nomvar='ME') grid0b = rmn.readGrid(funit, rec) rmn.fstcloseall(funit) self.erase_testfile() for k in grid0.keys(): if isinstance(grid0[k],np.ndarray): ok = np.any(np.abs(grid0b[k]-grid0[k]) > self.epsilon) self.assertFalse(ok, 'For k=%s, grid0b - grid0 = %s' % (k,str(np.abs(grid0b[k]-grid0[k])))) else: self.assertEqual(grid0b[k],grid0[k], 'For k=%s, expected:%s, got:%s' % (k, str(grid0[k]), str(grid0b[k])))
def test_23qd(self): import os, sys, datetime from scipy.constants import knot as KNOT2MS import numpy as np import rpnpy.librmn.all as rmn import rpnpy.vgd.all as vgd fdate = datetime.date.today().strftime('%Y%m%d') + '00_048' fileNameOut = 'uvfstfile.fst' fileIdIn = rmn.fstopenall(os.getenv('CMCGRIDF')+'/prog/regeta/'+fdate) fileIdOut = rmn.fstopenall(fileNameOut, rmn.FST_RW) vgd.vgd_write(vgd.vgd_read(fileIdIn), fileIdOut) (uu, vv, uvarray, copyGrid) = ({'d': None}, {'d': None}, None, True) for k in rmn.fstinl(fileIdIn, nomvar='UU'): uu = rmn.fstluk(k, dataArray=uu['d']) vv = rmn.fstlir(fileIdIn, nomvar='VV', ip1=uu['ip1'], ip2=uu['ip2'], datev=uu['datev'],dataArray=vv['d']) if uvarray is None: uvarray = np.empty(uu['d'].shape, dtype=uu['d'].dtype, order='FORTRAN') uv = uu.copy() uv.update({'d':uvarray, 'nomvar': 'WSPD'}) uv['d'][:,:] = np.sqrt(uu['d']**2. + vv['d']**2.) * KNOT2MS rmn.fstecr(fileIdOut, uv) if copyGrid: copyGrid = False rmn.writeGrid(fileIdOut, rmn.readGrid(fileIdIn, uu)) rmn.fstcloseall(fileIdIn) rmn.fstcloseall(fileIdOut) os.unlink(fileNameOut) # Remove test file
def test_23qd(self): import os, sys, datetime from scipy.constants import knot as KNOT2MS import numpy as np import rpnpy.librmn.all as rmn import rpnpy.vgd.all as vgd fdate = datetime.date.today().strftime('%Y%m%d') + '00_048' fileNameOut = 'uvfstfile.fst' fileIdIn = rmn.fstopenall( os.getenv('CMCGRIDF') + '/prog/regeta/' + fdate) fileIdOut = rmn.fstopenall(fileNameOut, rmn.FST_RW) vgd.vgd_write(vgd.vgd_read(fileIdIn), fileIdOut) (uu, vv, uvarray, copyGrid) = ({'d': None}, {'d': None}, None, True) for k in rmn.fstinl(fileIdIn, nomvar='UU'): uu = rmn.fstluk(k, dataArray=uu['d']) vv = rmn.fstlir(fileIdIn, nomvar='VV', ip1=uu['ip1'], ip2=uu['ip2'], datev=uu['datev'], dataArray=vv['d']) if uvarray is None: uvarray = np.empty(uu['d'].shape, dtype=uu['d'].dtype, order='FORTRAN') uv = uu.copy() uv.update({'d': uvarray, 'nomvar': 'WSPD'}) uv['d'][:, :] = np.sqrt(uu['d']**2. + vv['d']**2.) * KNOT2MS rmn.fstecr(fileIdOut, uv) if copyGrid: copyGrid = False rmn.writeGrid(fileIdOut, rmn.readGrid(fileIdIn, uu)) rmn.fstcloseall(fileIdIn) rmn.fstcloseall(fileIdOut) os.unlink(fileNameOut) # Remove test file
def test_readGridRef(self): ATM_MODEL_DFILES = os.getenv('ATM_MODEL_DFILES') myfile = os.path.join(ATM_MODEL_DFILES.strip(),'bcmk/geophy.fst') funit = rmn.fstopenall(myfile) rec = rmn.fstlir(funit, nomvar='ME') grid = rmn.readGrid(funit,rec) self.assertEqual(grid['grref'],'E') self.assertEqual(grid['grtyp'],'Z') self.assertEqual(grid['ig1'],2002) self.assertEqual(grid['ig2'],1000) self.assertEqual(grid['ig3'],0) self.assertEqual(grid['ig4'],0) self.assertEqual(grid['ig1ref'],900) self.assertEqual(grid['ig2ref'],0) self.assertEqual(grid['ig3ref'],43200) self.assertEqual(grid['ig4ref'],43200) self.assertEqual(grid['ni'],201) self.assertEqual(grid['nj'],100) self.assertEqual(grid['xg1'],0.) self.assertEqual(grid['xg2'],180.) self.assertEqual(grid['xg3'],0.) self.assertEqual(grid['xg4'],270.) self.assertEqual(grid['xlat1'],0.) self.assertEqual(grid['xlon1'],180.) self.assertEqual(grid['xlat2'],0.) self.assertEqual(grid['xlon2'],270.) self.assertEqual(grid['tag1'],2002) self.assertEqual(grid['tag2'],1000) self.assertEqual(grid['tag3'],0)
def test_readGridRef(self): ATM_MODEL_DFILES = os.getenv('ATM_MODEL_DFILES') myfile = os.path.join(ATM_MODEL_DFILES.strip(), 'bcmk/geophy.fst') funit = rmn.fstopenall(myfile) rec = rmn.fstlir(funit, nomvar='ME') grid = rmn.readGrid(funit, rec) self.assertEqual(grid['grref'], 'E') self.assertEqual(grid['grtyp'], 'Z') self.assertEqual(grid['ig1'], 2002) self.assertEqual(grid['ig2'], 1000) self.assertEqual(grid['ig3'], 0) self.assertEqual(grid['ig4'], 0) self.assertEqual(grid['ig1ref'], 900) self.assertEqual(grid['ig2ref'], 0) self.assertEqual(grid['ig3ref'], 43200) self.assertEqual(grid['ig4ref'], 43200) self.assertEqual(grid['ni'], 201) self.assertEqual(grid['nj'], 100) self.assertEqual(grid['xg1'], 0.) self.assertEqual(grid['xg2'], 180.) self.assertEqual(grid['xg3'], 0.) self.assertEqual(grid['xg4'], 270.) self.assertEqual(grid['xlat1'], 0.) self.assertEqual(grid['xlon1'], 180.) self.assertEqual(grid['xlat2'], 0.) self.assertEqual(grid['xlon2'], 270.) self.assertEqual(grid['tag1'], 2002) self.assertEqual(grid['tag2'], 1000) self.assertEqual(grid['tag3'], 0)
def getGrid(directory): fileName = os.listdir(directory) fileID = rmn.fstopenall(directory + fileName, rmn.FST_RO) getKeys(level=defaultIp1, spc=defaultSpc, fileID=fileID) #now have data for all applicable fields grid = rmn.readGrid(fileID, rec) return grid
def test_13(self): """ Queries: Get Horizontal Grid info This example shows how to get the horizontal grid definition (including axes and ezscint id) from a previsouly read record See also: rpnpy.librmn.fstd98.fstopenall rpnpy.librmn.fstd98.fstlir rpnpy.librmn.fstd98.fstcloseall rpnpy.librmn.grids.readGrid rpnpy.librmn.const """ import os, sys import rpnpy.librmn.all as rmn # Restrict to the minimum the number of messages printed by librmn rmn.fstopt(rmn.FSTOP_MSGLVL, rmn.FSTOPI_MSG_CATAST) # Open file ATM_MODEL_DFILES = os.getenv('ATM_MODEL_DFILES').strip() fileName = os.path.join(ATM_MODEL_DFILES, 'bcmk', 'geophy.fst') try: fileId = rmn.fstopenall(fileName, rmn.FST_RO) except: sys.stderr.write("Problem opening the file: %s\n" % fileName) sys.exit(1) try: # Get/read the MG record r = rmn.fstlir(fileId, nomvar='ME') # Get the grid definition of the record g = rmn.readGrid(fileId, r) print("CB13: %s grtyp/ref=%s/%s, ni/nj=%d,%d, gridID=%d" % (r['nomvar'], g['grtyp'], g['grref'], g['ni'], g['nj'], g['id'])) print(" lat0/lon0 =%f, %f" % (g['lat0'], g['lon0'])) print(" ldlat/dlon =%f, %f" % (g['dlat'], g['dlon'])) print(" xlat`/xlon1=%f, %f; xlat2/xlon2=%f, %f" % (g['xlat1'], g['xlon1'], g['xlat2'], g['xlon2'])) print(" ax: min=%f, max=%f; ay: min=%f, max=%f" % (g['ax'].min(), g['ax'].max(), g['ay'].min(), g['ay'].max())) except: pass finally: # Close file even if an error occured above rmn.fstcloseall(fileId)
def test_13(self): """ Queries: Get Horizontal Grid info This example shows how to get the horizontal grid definition (including axes and ezscint id) from a previsouly read record See also: rpnpy.librmn.fstd98.fstopenall rpnpy.librmn.fstd98.fstlir rpnpy.librmn.fstd98.fstcloseall rpnpy.librmn.grids.readGrid rpnpy.librmn.const """ import os, sys import rpnpy.librmn.all as rmn # Restrict to the minimum the number of messages printed by librmn rmn.fstopt(rmn.FSTOP_MSGLVL,rmn.FSTOPI_MSG_CATAST) # Open file ATM_MODEL_DFILES = os.getenv('ATM_MODEL_DFILES').strip() fileName = os.path.join(ATM_MODEL_DFILES, 'bcmk','geophy.fst') try: fileId = rmn.fstopenall(fileName, rmn.FST_RO) except: sys.stderr.write("Problem opening the file: %s\n" % fileName) sys.exit(1) try: # Get/read the MG record r = rmn.fstlir(fileId, nomvar='ME') # Get the grid definition of the record g = rmn.readGrid(fileId, r) print("CB13: %s grtyp/ref=%s/%s, ni/nj=%d,%d, gridID=%d" % (r['nomvar'], g['grtyp'], g['grref'], g['ni'], g['nj'], g['id'])) print(" lat0/lon0 =%f, %f" % (g['lat0'], g['lon0'])) print(" ldlat/dlon =%f, %f" % (g['dlat'], g['dlon'])) print(" xlat`/xlon1=%f, %f; xlat2/xlon2=%f, %f" % (g['xlat1'], g['xlon1'], g['xlat2'], g['xlon2'])) print(" ax: min=%f, max=%f; ay: min=%f, max=%f" % (g['ax'].min(), g['ax'].max(), g['ay'].min(), g['ay'].max())) except: pass finally: # Close file even if an error occured above rmn.fstcloseall(fileId)
def test_writeGrid(self): ATM_MODEL_DFILES = os.getenv('ATM_MODEL_DFILES') file0 = os.path.join(ATM_MODEL_DFILES.strip(), 'bcmk/geophy.fst') funit = rmn.fstopenall(file0) rec = rmn.fstlir(funit, nomvar='ME') grid0 = rmn.readGrid(funit, rec) rmn.fstcloseall(funit) grid1 = rmn.defGrid_L(180, 60, 0., 180., 1., 0.5) grid2 = rmn.defGrid_ZE(90, 45, 10., 11., 1., 0.5, 0., 180., 1., 270.) grid3 = rmn.defGrid_YY(31, 5, 0., 180., 1., 270.) self.erase_testfile() myfile = self.fname funit = rmn.fstopenall(myfile, rmn.FST_RW) rmn.fstecr(funit, rec['d'], rec) rmn.writeGrid(funit, grid0) rmn.writeGrid(funit, grid1) rmn.writeGrid(funit, grid2) rmn.writeGrid(funit, grid3) rmn.fstcloseall(funit) funit = rmn.fstopenall(myfile, rmn.FST_RO) rec = rmn.fstlir(funit, nomvar='ME') grid0b = rmn.readGrid(funit, rec) rmn.fstcloseall(funit) self.erase_testfile() for k in grid0.keys(): if isinstance(grid0[k], np.ndarray): ok = np.any(np.abs(grid0b[k] - grid0[k]) > self.epsilon) self.assertFalse( ok, 'For k=%s, grid0b - grid0 = %s' % (k, str(np.abs(grid0b[k] - grid0[k])))) else: self.assertEqual( grid0b[k], grid0[k], 'For k=%s, expected:%s, got:%s' % (k, str(grid0[k]), str(grid0b[k])))
def test_13qd(self): import os, sys import rpnpy.librmn.all as rmn rmn.fstopt(rmn.FSTOP_MSGLVL,rmn.FSTOPI_MSG_CATAST) ATM_MODEL_DFILES = os.getenv('ATM_MODEL_DFILES').strip() fileId = rmn.fstopenall(ATM_MODEL_DFILES+'/bcmk/geophy.fst', rmn.FST_RO) r = rmn.fstlir(fileId, nomvar='ME') g = rmn.readGrid(fileId, r) print("CB13qd: %s grtyp/ref=%s/%s, ni/nj=%d,%d, gridID=%d" % (r['nomvar'], g['grtyp'], g['grref'], g['ni'], g['nj'], g['id'])) print(" lat0/lon0 =%f, %f" % (g['lat0'], g['lon0'])) print(" ldlat/dlon =%f, %f" % (g['dlat'], g['dlon'])) print(" xlat`/xlon1=%f, %f; xlat2/xlon2=%f, %f" % (g['xlat1'], g['xlon1'], g['xlat2'], g['xlon2'])) print(" ax: min=%f, max=%f; ay: min=%f, max=%f" % (g['ax'].min(), g['ax'].max(), g['ay'].min(), g['ay'].max())) rmn.fstcloseall(fileId)
def test_13qd(self): import os, sys import rpnpy.librmn.all as rmn rmn.fstopt(rmn.FSTOP_MSGLVL, rmn.FSTOPI_MSG_CATAST) ATM_MODEL_DFILES = os.getenv('ATM_MODEL_DFILES').strip() fileId = rmn.fstopenall(ATM_MODEL_DFILES + '/bcmk/geophy.fst', rmn.FST_RO) r = rmn.fstlir(fileId, nomvar='ME') g = rmn.readGrid(fileId, r) print("CB13qd: %s grtyp/ref=%s/%s, ni/nj=%d,%d, gridID=%d" % (r['nomvar'], g['grtyp'], g['grref'], g['ni'], g['nj'], g['id'])) print(" lat0/lon0 =%f, %f" % (g['lat0'], g['lon0'])) print(" ldlat/dlon =%f, %f" % (g['dlat'], g['dlon'])) print(" xlat`/xlon1=%f, %f; xlat2/xlon2=%f, %f" % (g['xlat1'], g['xlon1'], g['xlat2'], g['xlon2'])) print(" ax: min=%f, max=%f; ay: min=%f, max=%f" % (g['ax'].min(), g['ax'].max(), g['ay'].min(), g['ay'].max())) rmn.fstcloseall(fileId)
def test_readGrid(self): ATM_MODEL_DFILES = os.getenv('ATM_MODEL_DFILES') myfile = os.path.join(ATM_MODEL_DFILES.strip(),'bcmk/2009042700_000') funit = rmn.fstopenall(myfile) rec = rmn.fstlir(funit, nomvar='P0') grid = rmn.readGrid(funit,rec) self.assertEqual(grid['grtyp'],'G') self.assertEqual(grid['ig1'],0) self.assertEqual(grid['ig2'],0) self.assertEqual(grid['ig3'],0) self.assertEqual(grid['ig4'],0) self.assertEqual(grid['xg1'],0.) self.assertEqual(grid['xg2'],0.) self.assertEqual(grid['xg3'],0.) self.assertEqual(grid['xg4'],0.) self.assertEqual(grid['ni'],200) self.assertEqual(grid['nj'],100) self.assertEqual(grid['shape'],(200,100)) self.assertEqual(grid['glb'],True) self.assertEqual(grid['north'],True) self.assertEqual(grid['inverted'],False)
def test_readGrid(self): ATM_MODEL_DFILES = os.getenv('ATM_MODEL_DFILES') myfile = os.path.join(ATM_MODEL_DFILES.strip(), 'bcmk/2009042700_000') funit = rmn.fstopenall(myfile) rec = rmn.fstlir(funit, nomvar='P0') grid = rmn.readGrid(funit, rec) self.assertEqual(grid['grtyp'], 'G') self.assertEqual(grid['ig1'], 0) self.assertEqual(grid['ig2'], 0) self.assertEqual(grid['ig3'], 0) self.assertEqual(grid['ig4'], 0) self.assertEqual(grid['xg1'], 0.) self.assertEqual(grid['xg2'], 0.) self.assertEqual(grid['xg3'], 0.) self.assertEqual(grid['xg4'], 0.) self.assertEqual(grid['ni'], 200) self.assertEqual(grid['nj'], 100) self.assertEqual(grid['shape'], (200, 100)) self.assertEqual(grid['glb'], True) self.assertEqual(grid['north'], True) self.assertEqual(grid['inverted'], False)
def test_41qd(self): import os, sys, datetime import rpnpy.librmn.all as rmn fdate = datetime.date.today().strftime('%Y%m%d') + '00_048' CMCGRIDF = os.getenv('CMCGRIDF').strip() fileNameOut = 'p0fstfileqd.fst' fileIdIn = rmn.fstopenall(os.getenv('CMCGRIDF')+'/prog/regeta/'+fdate) fileIdOut = rmn.fstopenall(fileNameOut, rmn.FST_RW) gOut = rmn.defGrid_ZE(90, 45, 35., 250., 0.5, 0.5, 0., 180., 1., 270.) r = rmn.fstlir(fileIdIn, nomvar='P0') gIn = rmn.readGrid(fileIdIn, r) rmn.ezsetopt(rmn.EZ_OPT_INTERP_DEGREE, rmn.EZ_INTERP_LINEAR) d = rmn.ezsint(gOut, gIn, r) r2 = r.copy() r2.update(gOut) r2.update({'etiket':'my_etk', 'd':d}) rmn.fstecr(fileIdOut, r2) rmn.writeGrid(fileIdOut, gOut) rmn.fstcloseall(fileIdIn) rmn.fstcloseall(fileIdOut) os.unlink(fileNameOut) # Remove test file
def test_41qd(self): import os, sys, datetime import rpnpy.librmn.all as rmn fdate = datetime.date.today().strftime('%Y%m%d') + '00_048' CMCGRIDF = os.getenv('CMCGRIDF').strip() fileNameOut = 'p0fstfileqd.fst' fileIdIn = rmn.fstopenall( os.getenv('CMCGRIDF') + '/prog/regeta/' + fdate) fileIdOut = rmn.fstopenall(fileNameOut, rmn.FST_RW) gOut = rmn.defGrid_ZE(90, 45, 35., 250., 0.5, 0.5, 0., 180., 1., 270.) r = rmn.fstlir(fileIdIn, nomvar='P0') gIn = rmn.readGrid(fileIdIn, r) rmn.ezsetopt(rmn.EZ_OPT_INTERP_DEGREE, rmn.EZ_INTERP_LINEAR) d = rmn.ezsint(gOut, gIn, r) r2 = r.copy() r2.update(gOut) r2.update({'etiket': 'my_etk', 'd': d}) rmn.fstecr(fileIdOut, r2) rmn.writeGrid(fileIdOut, gOut) rmn.fstcloseall(fileIdIn) rmn.fstcloseall(fileIdOut) os.unlink(fileNameOut) # Remove test file
def getGrid(directory): fileName = os.listdir(directory) fileID = rmn.fstopenall(directory+fileName, rmn.FST_RO) getKeys(level=defaultIp1,spc=defaultSpc,fileID=fileID) #now have data for all applicable fields grid=rmn.readGrid(fileID,rec) print ('Grid Type is: ' + grid[grtyp]) ##grid type (one of 'Z', '#', 'Y', 'U') ## note that if there are variable gridtypes, would be problematic when coding in conversion to lat/lon or x/y ## if plotted in latlon, then is not a concern, and can convert to xy for new grid layout to match the basemap return grid ##things wanted out of grid: ## shape, (ni,nj) to resize to ## Returns: { 'id' : grid id, same as input arg 'shape' : (ni, nj) # dimensions of the grid 'ni' : first dimension of the grid 'nj' : second dimension of the grid 'grtyp' : type of geographical projection (one of 'Z', '#', 'Y', 'U') 'ig1' : first grid descriptor 'ig2' : second grid descriptor 'ig3' : third grid descriptor 'ig4' : fourth grid descriptor 'grref' : grid ref type (one of 'A', 'B', 'E', 'G', 'L', 'N', 'S') 'ig1ref' : first grid descriptor of grid ref 'ig2ref' : second grid descriptor of grid ref 'ig3ref' : third grid descriptor of grid ref 'ig4ref' : fourth grid descriptor of grid ref ... list of other parameters is grtyp dependent, See defGrid_* specific function for details }
def test_41(self): """ Horizontal Interpolation See also: """ import os, sys, datetime import rpnpy.librmn.all as rmn fdate = datetime.date.today().strftime('%Y%m%d') + '00_048' CMCGRIDF = os.getenv('CMCGRIDF').strip() fileNameIn = os.path.join(CMCGRIDF, 'prog', 'regeta', fdate) fileNameOut = 'p0fstfile.fst' # Restrict to the minimum the number of messages printed by librmn rmn.fstopt(rmn.FSTOP_MSGLVL, rmn.FSTOPI_MSG_CATAST) try: # Create Destination grid # Note: Destination grid can also be read from a file gp = { 'grtyp': 'Z', 'grref': 'E', 'ni': 90, 'nj': 45, 'lat0': 35., 'lon0': 250., 'dlat': 0.5, 'dlon': 0.5, 'xlat1': 0., 'xlon1': 180., 'xlat2': 1., 'xlon2': 270. } gOut = rmn.encodeGrid(gp) print("CB41: Defined a %s/%s grid of shape=%d, %d" % (gOut['grtyp'], gOut['grref'], gOut['ni'], gOut['nj'])) except: sys.stderr.write("Problem creating grid\n") sys.exit(1) # Open Files try: fileIdIn = rmn.fstopenall(fileNameIn) fileIdOut = rmn.fstopenall(fileNameOut, rmn.FST_RW) except: sys.stderr.write("Problem opening the files: %s, %s\n" % (fileNameIn, fileNameOut)) sys.exit(1) try: # Find and read record to interpolate with its grid r = rmn.fstlir(fileIdIn, nomvar='P0') gIn = rmn.readGrid(fileIdIn, r) print("CB41: Read P0") # Set interpolation options and interpolate rmn.ezsetopt(rmn.EZ_OPT_INTERP_DEGREE, rmn.EZ_INTERP_LINEAR) d = rmn.ezsint(gOut, gIn, r) print("CB41: Interpolate P0") # Create new record to write with interpolated data and r2 = r.copy() # Preserve meta from original record r2.update(gOut) # update grid information r2.update({ # attach data and update specific meta 'etiket': 'my_etk', 'd': d }) # Write record data + meta + grid to file rmn.fstecr(fileIdOut, r2) rmn.writeGrid(fileIdOut, gOut) print("CB41: Wrote interpolated P0 and its grid") except: pass finally: # Properly close files even if an error occured above # This is important when editing to avoid corrupted files rmn.fstcloseall(fileIdIn) rmn.fstcloseall(fileIdOut) os.unlink(fileNameOut) # Remove test file
def test_51(self): """ Vertical Interpolation See also: scipy.interpolate.interp1d """ import os, sys, datetime import numpy as np from scipy.interpolate import interp1d as scipy_interp1d import rpnpy.librmn.all as rmn import rpnpy.vgd.all as vgd MB2PA = 100. # Restrict to the minimum the number of messages printed by librmn rmn.fstopt(rmn.FSTOP_MSGLVL, rmn.FSTOPI_MSG_CATAST) # Open Input file hour = 48 fdate = datetime.date.today().strftime('%Y%m%d') + '00_0' + str(hour) CMCGRIDF = os.getenv('CMCGRIDF').strip() fileNameOut = os.path.join(CMCGRIDF, 'prog', 'regeta', fdate) try: fileIdIn = rmn.fstopenall(fileNameOut, rmn.FST_RO) except: sys.stderr.write("Problem opening the input file: %s\n" % fileNameOut) sys.exit(1) try: # Get the vgrid def present in the file # and the full list of ip1 # and the surface reference field name for the coor vIn = vgd.vgd_read(fileIdIn) ip1listIn0 = vgd.vgd_get(vIn, 'VIPT') rfldNameIn = vgd.vgd_get(vIn, 'RFLD') vkind = vgd.vgd_get(vIn, 'KIND') vver = vgd.vgd_get(vIn, 'VERS') VGD_KIND_VER_INV = dict( (v, k) for k, v in vgd.VGD_KIND_VER.items()) vtype = VGD_KIND_VER_INV[(vkind, vver)] print( "CB51: Found vgrid type=%s (kind=%d, vers=%d) with %d levels, RFLD=%s" % (vtype, vkind, vver, len(ip1listIn0), rfldNameIn)) # Trim the list of thermo ip1 to actual levels in files for TT # since the vgrid in the file is a super set of all levels # and get their "key" ip1Keys = [] rshape = None for ip1 in ip1listIn0: (lval, lkind) = rmn.convertIp(rmn.CONVIP_DECODE, ip1) key = rmn.fstinf(fileIdIn, nomvar='TT', ip2=hour, ip1=rmn.ip1_all(lval, lkind)) if key is not None: print("CB51: Found TT at ip1=%d, ip2=%d" % (ip1, hour)) ip1Keys.append((ip1, key['key'])) if rshape is None: rshape = key['shape'] rshape = (rshape[0], rshape[1], len(ip1Keys)) # Read every level for TT at ip2=hour, re-use 2d array while reading # and store the data in a 3d array # with lower level at nk, top at 0 as in the model r2d = {'d': None} r3d = None k = 0 gIn = None for ip1, key in ip1Keys: try: r2d = rmn.fstluk(key, dataArray=r2d['d']) print("CB51: Read TT at ip1=%d, ip2=%d" % (ip1, hour)) if r3d is None: r3d = r2d.copy() r3d['d'] = np.empty(rshape, dtype=r2d['d'].dtype, order='FORTRAN') r3d['d'][:, :, k] = r2d['d'][:, :] k += 1 if gIn is None: gIn = rmn.readGrid(fileIdIn, r2d) print("CB51: Read the horizontal grid descriptors") except: pass # Add the vgrid and the actual ip1 list in the r3d dict, update shape and nk r3d['vgd'] = vIn r3d['ip1list'] = [x[0] for x in ip1Keys] r3d['shape'] = rshape r3d['nk'] = rshape[2] # Read the Input reference fields rfldIn = None if rfldNameIn: rfldIn = rmn.fstlir(fileIdIn, nomvar=rfldNameIn, ip2=hour) if rfldNameIn.strip() == 'P0': rfldIn['d'][:] *= MB2PA print( "CB51: Read input RFLD=%s at ip2=%d [min=%7.0f, max=%7.0f]" % (rfldNameIn, hour, rfldIn['d'].min(), rfldIn['d'].max())) except: raise # pass finally: # Close file even if an error occured above rmn.fstcloseall(fileIdIn) # Define the destination vertical grid/levels try: lvlsOut = (500., 850., 1000.) vOut = vgd.vgd_new_pres(lvlsOut) ip1listOut = vgd.vgd_get(vOut, 'VIPT') rfldNameOut = vgd.vgd_get(vIn, 'RFLD') rfldOut = None # in this case, Pressure levels, there are no RFLD print("CB51: Defined a Pres vgrid with lvls=%s" % str(lvlsOut)) except: sys.stderr.write("Problem creating a new vgrid\n") sys.exit(1) # Get input and output 3d pressure cubes try: ## if rfldIn is None: ## rfldIn = pIn = vgd.vgd_levels(vIn, ip1list=r3d['ip1list'], rfld=rfldIn['d']) print( "CB51: Computed input pressure cube, k0:[min=%7.0f, max=%7.0f], nk:[min=%7.0f, max=%7.0f]" % (pIn[:, :, 0].min(), pIn[:, :, 0].max(), pIn[:, :, -1].min(), pIn[:, :, -1].max())) if rfldOut is None: rfldOut = rfldIn # provide a dummy rfld for array shape pOut = vgd.vgd_levels(vOut, ip1list=ip1listOut, rfld=rfldOut['d']) print( "CB51: Computed output pressure cube, k0:[min=%7.0f, max=%7.0f], nk:[min=%7.0f, max=%7.0f]" % (pOut[:, :, 0].min(), pOut[:, :, 0].max(), pOut[:, :, -1].min(), pOut[:, :, -1].max())) except: raise sys.stderr.write("Problem computing pressure cubes\n") sys.exit(1) # Use scipy.interpolate.interp1d to vertically interpolate try: ## f = scipy_interp1d(fromLvls, toLvls, kind='cubic', ## assume_sorted=True, bounds_error=False, ## fill_value='extrapolate', copy=False) ## # Unfortunately, looks like interp1d take colomn data ## f = scipy_interp1d(pIn, r3d['d'], kind='cubic', ## bounds_error=False, ## fill_value='extrapolate', copy=False) ## r3dout = f(pOut) ## # Unfortunately, assume_sorted, 'extrapolate' not support in my version ## extrap_value = 'extrapolate' # -99999. ## # Way too slow, needs a C implementation extrap_value = -999. ## for j in range(rshape[1]): ## for i in range(rshape[0]): ## f = scipy_interp1d(pIn[i,j,:], r3d['d'][i,j,:], ## kind='cubic', ## bounds_error=False, ## fill_value=extrap_value, copy=False) ## r1d = f(pOut[i,j,:]) ## #print i,j,r1d except: raise sys.stderr.write("Problem Interpolating data\n") sys.exit(1)
def test_23(self): """ Edit: Read, Edit, Write records with meta, grid and vgrid This example shows how to * select records in a RPNStd file * read the record data + meta * edit/use record data and meta (compute the wind velocity) * write the recod data + meta * copy (read/write) the record grid descriptors * copy (read/write) the file vgrid descriptor See also: rpnpy.librmn.fstd98.fstopt rpnpy.librmn.fstd98.fstopenall rpnpy.librmn.fstd98.fstcloseall rpnpy.librmn.fstd98.fsrinl rpnpy.librmn.fstd98.fsrluk rpnpy.librmn.fstd98.fsrlir rpnpy.librmn.fstd98.fsrecr rpnpy.librmn.grids.readGrid rpnpy.librmn.grids.writeGrid rpnpy.vgd.base.vgd_read rpnpy.vgd.base.vgd_write rpnpy.librmn.const rpnpy.vgd.const """ import os, sys, datetime from scipy.constants import knot as KNOT2MS import numpy as np import rpnpy.librmn.all as rmn import rpnpy.vgd.all as vgd fdate = datetime.date.today().strftime('%Y%m%d') + '00_048' CMCGRIDF = os.getenv('CMCGRIDF').strip() fileNameIn = os.path.join(CMCGRIDF, 'prog', 'regeta', fdate) fileNameOut = 'uvfstfile.fst' # Restrict to the minimum the number of messages printed by librmn rmn.fstopt(rmn.FSTOP_MSGLVL, rmn.FSTOPI_MSG_CATAST) # Open Files try: fileIdIn = rmn.fstopenall(fileNameIn) fileIdOut = rmn.fstopenall(fileNameOut, rmn.FST_RW) except: sys.stderr.write("Problem opening the files: %s, %s\n" % (fileNameIn, fileNameOut)) sys.exit(1) try: # Copy the vgrid descriptor v = vgd.vgd_read(fileIdIn) vgd.vgd_write(v, fileIdOut) print("CB23: Copied the vgrid descriptor") # Loop over the list of UU records to copy uu = {'d': None} vv = {'d': None} uvarray = None copyGrid = True for k in rmn.fstinl(fileIdIn, nomvar='UU'): # Read the UU record data and meta from fileNameIn # Provide data array to re-use memory uu = rmn.fstluk(k, dataArray=uu['d']) # Read the corresponding VV # Provide data array to re-use memory vv = rmn.fstlir(fileIdIn, nomvar='VV', ip1=uu['ip1'], ip2=uu['ip2'], datev=uu['datev'], dataArray=vv['d']) # Compute the wind modulus in m/s # Copy metadata from the UU record # Create / re-use memory space for computation results uv = uu.copy() if uvarray is None: uvarray = np.empty(uu['d'].shape, dtype=uu['d'].dtype, order='FORTRAN') uv['d'] = uvarray uv['d'][:, :] = np.sqrt(uu['d']**2. + vv['d']**2.) uv['d'] *= KNOT2MS # Convert from knot to m/s # Set new record name and Write it to fileNameOut uv['nomvar'] = 'WSPD' rmn.fstecr(fileIdOut, uv) print("CB23: Wrote %s ip1=%d, ip2=%d, dateo=%s : mean=%f" % (uv['nomvar'], uv['ip1'], uv['ip2'], uv['dateo'], uv['d'].mean())) # Read and Write grid (only once, all rec are on the same grid) if copyGrid: copyGrid = False g = rmn.readGrid(fileIdIn, uu) rmn.writeGrid(fileIdOut, g) print("CB23: Copied the grid descriptors") except: pass finally: # Properly close files even if an error occured above # This is important when editing to avoid corrupted files rmn.fstcloseall(fileIdIn) rmn.fstcloseall(fileIdOut) os.unlink(fileNameOut) # Remove test file
def test_51(self): """ Vertical Interpolation See also: scipy.interpolate.interp1d """ import os, sys, datetime import numpy as np from scipy.interpolate import interp1d as scipy_interp1d import rpnpy.librmn.all as rmn import rpnpy.vgd.all as vgd MB2PA = 100. # Restric to the minimum the number of messages printed by librmn rmn.fstopt(rmn.FSTOP_MSGLVL,rmn.FSTOPI_MSG_CATAST) # Open Input file hour = 48 fdate = datetime.date.today().strftime('%Y%m%d') + '00_0' + str(hour) CMCGRIDF = os.getenv('CMCGRIDF').strip() fileNameOut = os.path.join(CMCGRIDF, 'prog', 'regeta', fdate) try: fileIdIn = rmn.fstopenall(fileNameOut, rmn.FST_RO) except: sys.stderr.write("Problem opening the input file: %s\n" % fileNameOut) sys.exit(1) try: # Get the vgrid def present in the file # and the full list of ip1 # and the surface reference field name for the coor vIn = vgd.vgd_read(fileIdIn) ip1listIn0 = vgd.vgd_get(vIn, 'VIPT') rfldNameIn = vgd.vgd_get(vIn, 'RFLD') vkind = vgd.vgd_get(vIn, 'KIND') vver = vgd.vgd_get(vIn, 'VERS') VGD_KIND_VER_INV = dict((v, k) for k, v in vgd.VGD_KIND_VER.iteritems()) vtype = VGD_KIND_VER_INV[(vkind,vver)] print("CB51: Found vgrid type=%s (kind=%d, vers=%d) with %d levels, RFLD=%s" % (vtype, vkind, vver, len(ip1listIn0), rfldNameIn)) # Trim the list of thermo ip1 to actual levels in files for TT # since the vgrid in the file is a super set of all levels # and get their "key" ip1Keys = [] rshape = None for ip1 in ip1listIn0: (lval, lkind) = rmn.convertIp(rmn.CONVIP_DECODE, ip1) key = rmn.fstinf(fileIdIn, nomvar='TT', ip2=hour, ip1=rmn.ip1_all(lval, lkind)) if key is not None: print("CB51: Found TT at ip1=%d, ip2=%d" % (ip1, hour)) ip1Keys.append((ip1, key['key'])) if rshape is None: rshape = key['shape'] rshape = (rshape[0], rshape[1], len(ip1Keys)) # Read every level for TT at ip2=hour, re-use 2d array while reading # and store the data in a 3d array # with lower level at nk, top at 0 as in the model r2d = {'d' : None} r3d = None k = 0 gIn = None for ip1, key in ip1Keys: try: r2d = rmn.fstluk(key, dataArray=r2d['d']) print("CB51: Read TT at ip1=%d, ip2=%d" % (ip1, hour)) if r3d is None: r3d = r2d.copy() r3d['d'] = np.empty(rshape, dtype=r2d['d'].dtype, order='FORTRAN') r3d['d'][:,:,k] = r2d['d'][:,:] k += 1 if gIn is None: gIn = rmn.readGrid(fileIdIn, r2d) print("CB51: Read the horizontal grid descriptors") except: pass # Add the vgrid and the actual ip1 list in the r3d dict, update shape and nk r3d['vgd'] = vIn r3d['ip1list'] = [x[0] for x in ip1Keys] r3d['shape'] = rshape r3d['nk'] = rshape[2] # Read the Input reference fields rfldIn = None if rfldNameIn: rfldIn = rmn.fstlir(fileIdIn, nomvar=rfldNameIn, ip2=hour) if rfldNameIn.strip() == 'P0': rfldIn['d'][:] *= MB2PA print("CB51: Read input RFLD=%s at ip2=%d [min=%7.0f, max=%7.0f]" % (rfldNameIn, hour, rfldIn['d'].min(), rfldIn['d'].max())) except: raise # pass finally: # Close file even if an error occured above rmn.fstcloseall(fileIdIn) # Define the destination vertical grid/levels try: lvlsOut = (500.,850.,1000.) vOut = vgd.vgd_new_pres(lvlsOut) ip1listOut = vgd.vgd_get(vOut, 'VIPT') rfldNameOut = vgd.vgd_get(vIn, 'RFLD') rfldOut = None # in this case, Pressure levels, there are no RFLD print("CB51: Defined a Pres vgrid with lvls=%s" % str(lvlsOut)) except: sys.stderr.write("Problem creating a new vgrid\n") sys.exit(1) # Get input and output 3d pressure cubes try: ## if rfldIn is None: ## rfldIn = pIn = vgd.vgd_levels(vIn, ip1list=r3d['ip1list'], rfld=rfldIn['d']) print("CB51: Computed input pressure cube, k0:[min=%7.0f, max=%7.0f], nk:[min=%7.0f, max=%7.0f]" % (pIn[:,:,0].min(), pIn[:,:,0].max(), pIn[:,:,-1].min(), pIn[:,:,-1].max())) if rfldOut is None: rfldOut = rfldIn # provide a dummy rfld for array shape pOut = vgd.vgd_levels(vOut, ip1list=ip1listOut, rfld=rfldOut['d']) print("CB51: Computed output pressure cube, k0:[min=%7.0f, max=%7.0f], nk:[min=%7.0f, max=%7.0f]" % (pOut[:,:,0].min(), pOut[:,:,0].max(), pOut[:,:,-1].min(), pOut[:,:,-1].max())) except: raise sys.stderr.write("Problem computing pressure cubes\n") sys.exit(1) # Use scipy.interpolate.interp1d to vertically interpolate try: ## f = scipy_interp1d(fromLvls, toLvls, kind='cubic', ## assume_sorted=True, bounds_error=False, ## fill_value='extrapolate', copy=False) ## # Unfortunately, looks like interp1d take colomn data ## f = scipy_interp1d(pIn, r3d['d'], kind='cubic', ## bounds_error=False, ## fill_value='extrapolate', copy=False) ## r3dout = f(pOut) ## # Unfortunately, assume_sorted, 'extrapolate' not support in my version ## extrap_value = 'extrapolate' # -99999. ## # Way too slow, needs a C implementation extrap_value = -999. ## for j in xrange(rshape[1]): ## for i in xrange(rshape[0]): ## f = scipy_interp1d(pIn[i,j,:], r3d['d'][i,j,:], ## kind='cubic', ## bounds_error=False, ## fill_value=extrap_value, copy=False) ## r1d = f(pOut[i,j,:]) ## #print i,j,r1d except: raise sys.stderr.write("Problem Interpolating data\n") sys.exit(1)
def fst_read_3d(fileId, datev=-1, etiket=' ', ip1=-1, ip2=-1, ip3=-1, typvar=' ', nomvar=' ', getPress=False, dtype=None, rank=None, dataArray=None, verbose=False): """ Reads the records matching the research keys into a 3D array along with horizontal and vertical grid info Only provided parameters with value different than default are used as selection criteria field3d = fst_read_3d(fileId, ... ) Args: fileId : unit number associated to the file obtained with fnom+fstouv or fstopenall datev : valid date etiket : label ip1 : vertical levels lists ip2 : forecast hour ip3 : user defined identifier typvar : type of field nomvar : variable name getPress: if true, get the ref. surface field and compute pressure cube dtype : array type of the returned data Default is determined from records' datyp Could be any numpy.ndarray type See: http://docs.scipy.org/doc/numpy/user/basics.types.html rank : try to return an array with the specified rank dataArray (ndarray): (optional) allocated array where to put the data verbose : Print some info when true Returns: None if no matching record, else: { 'd' : data, # 3d field data (numpy.ndarray), Fortran order 'hgrid': hGridInfo, # horizontal grid info as returned by readGrid 'vgrid': vGridInfo, # vertical grid info as returned by vgd_read 'ip1s' : ip1List # List of ip1 of each level (tuple of int) ... # same params list as fstprm (less ip1) 'rfld' : rfld, # (if getPress) 2d reference field value 'phPa' : phPa # (if getPress) 3d pressure values } Raises: TypeError on wrong input arg types ValueError on invalid input arg value FSTDError on any other error Examples: >>> import os, os.path >>> import rpnpy.librmn.all as rmn >>> import rpnpy.utils.fstd3d as fstd3d >>> ATM_MODEL_DFILES = os.getenv('ATM_MODEL_DFILES').strip() >>> filename = os.path.join(ATM_MODEL_DFILES,'bcmk') >>> >>> # Open existing file in Rear Only mode >>> fileId = rmn.fstopenall(filename, rmn.FST_RO) >>> >>> # Find and read p0 meta and data, then print its min,max,mean values >>> tt3d = fstd3d.fst_read_3d(fileId, nomvar='TT') Read TT ip1=97642568 ip2=0 ip3=0 typv=P etk=G133K80P Read the horizontal grid descriptors for TT Read TT ip1=97738568 ip2=0 ip3=0 typv=P etk=G133K80P Read TT ip1=97899568 ip2=0 ip3=0 typv=P etk=G133K80P Read TT ip1=98152568 ip2=0 ip3=0 typv=P etk=G133K80P # ... >>> print("# TT ip2={0} min={1:4.1f} max={2:3.1f} avg={3:4.1f}" ... .format(tt3d['ip2'], tt3d['d'].min(), tt3d['d'].max(), tt3d['d'].mean())) # TT ip2=0 min=-88.4 max=40.3 avg=-36.3 >>> rmn.fstcloseall(fileId) See Also: get_levels_keys get_levels_press fst_write_3d rpnpy.librmn.fstd98.fstlir rpnpy.librmn.fstd98.fstprm rpnpy.librmn.fstd98.fstluk rpnpy.librmn.fstd98.fstopenall rpnpy.librmn.fstd98.fstcloseall rpnpy.librmn.grids.readGrid rpnpy.vgd.base.vgd_read rpnpy.vgd.base.vgd_levels """ # Get the list of ip1 on thermo, momentum levels in this file #TODO: if ip1 is provided get the keys for these ip1 vGrid = None tlevels = get_levels_keys(fileId, nomvar, datev, ip2, ip3, typvar, etiket, vGrid=vGrid, thermoMom='VIPT', verbose=verbose) vGrid = tlevels['vgrid'] mlevels = get_levels_keys(fileId, tlevels['nomvar'], tlevels['datev'], tlevels['ip2'], tlevels['ip3'], tlevels['typvar'], tlevels['etiket'], vGrid=vGrid, thermoMom='VIPM', verbose=verbose) ip1keys = tlevels['ip1keys'] if len(mlevels['ip1keys']) > len(tlevels['ip1keys']): if verbose: print("(fst_read_3d) Using Momentum level list") ip1keys = mlevels['ip1keys'] elif verbose: print("(fst_read_3d) Using Thermo level list") if verbose or len(ip1keys) == 0: print("(fst_read_3d) Found {0} records for {1} ip2={2} ip3={3} datev={4} typvar={5} etiket={6}"\ .format(len(ip1keys), nomvar, ip2, ip3, datev, typvar, etiket)) if len(ip1keys) == 0: return None # Read all 2d records and copy to 3d array r3d = None r2d = {'d': None} k = 0 for ip1, key in ip1keys: r2d = _rmn.fstluk(key, dataArray=r2d['d']) print( "Read {nomvar} ip1={ip1} ip2={ip2} ip3={ip3} typv={typvar} etk={etiket}" .format(**r2d)) if r3d is None: r3d = r2d.copy() rshape = list(r2d['d'].shape[0:2]) + [len(ip1keys)] if dataArray is None: r3d['d'] = _np.empty(rshape, dtype=r2d['d'].dtype, order='FORTRAN') else: if isinstance(dataArray, _np.ndarray) and dataArray.shape == rshape: r3d['d'] = dataArray else: raise TypeError( 'Provided dataArray is not the right type or shape') r3d['hgrid'] = _rmn.readGrid(fileId, r2d) print("Read the horizontal grid descriptors for {nomvar}".format( **r2d)) if r2d['d'].shape[0:2] != r3d['d'].shape[0:2]: raise _rmn.RMNError("Wrong shape for input data.") r3d['d'][:, :, k] = r2d['d'][:, :] k += 1 ip1list = [x[0] for x in ip1keys] r3d.update({ 'shape': r3d['d'].shape, 'ni': r3d['d'].shape[0], 'nj': r3d['d'].shape[1], 'nk': r3d['d'].shape[2], 'ip1': -1, 'ip1s': ip1list, 'vgrid': vGrid }) # Read RFLD and compute pressure on levels if getPress: press = get_levels_press(fileId, vGrid, r3d['d'].shape[0:2], ip1list, tlevels['datev'], tlevels['ip2'], tlevels['ip3'], tlevels['typvar'], tlevels['etiket'], verbose=False) r3d.update({'rfld': press['rfld'], 'phPa': press['phPa']}) return r3d
def fst_read_3d(fileId, datev=-1, etiket=' ', ip1=-1, ip2=-1, ip3=-1, typvar=' ', nomvar=' ', getPress=False, dtype=None, rank=None, dataArray=None, verbose=False): """ Reads the records matching the research keys into a 3D array along with horizontal and vertical grid info Only provided parameters with value different than default are used as selection criteria field3d = fst_read_3d(iunit, ... ) Args: iunit : unit number associated to the file obtained with fnom+fstouv datev : valid date etiket : label ip1 : vertical levels lists ip2 : forecast hour ip3 : user defined identifier typvar : type of field nomvar : variable name getPress: dtype : array type of the returned data Default is determined from records' datyp Could be any numpy.ndarray type See: http://docs.scipy.org/doc/numpy/user/basics.types.html rank : try to return an array with the specified rank dataArray (ndarray): (optional) allocated array where to put the data verbose : Returns: None if no matching record, else: { 'd' : data, # 3d field data (numpy.ndarray), Fortran order 'g' : hGridInfo, # horizontal grid info as returned by readGrid 'v' : vGridInfo, # vertical grid info as returned by vgd_read 'ip1s' : ip1List # List of ip1 of each level (tuple of int) ... # same params list as fstprm (less ip1) } Raises: TypeError on wrong input arg types ValueError on invalid input arg value FSTDError on any other error Examples: >>> import os, os.path >>> import rpnpy.librmn.all as rmn >>> import rpnpy.utils.fstd3d as fstd3d >>> ATM_MODEL_DFILES = os.getenv('ATM_MODEL_DFILES').strip() >>> filename = os.path.join(ATM_MODEL_DFILES,'bcmk') >>> >>> # Open existing file in Rear Only mode >>> funit = rmn.fstopenall(filename, rmn.FST_RO) >>> >>> # Find and read p0 meta and data, then print its min,max,mean values >>> tt3d = fstd3d.fst_read_3d(funit, nomvar='TT') >>> print("# TT ip2={0} min={1} max={2} avg={3}"\ .format(tt3d['ip2'], tt3d['d'].min(), tt3d['d'].max(), tt3d['d'].mean())) # TT ip2=0 min=530.641418 max=1039.641479 avg=966.500000 >>> rmn.fstcloseall(funit) See Also: get_levels_keys fst_write_3d rpnpy.librmn.fstd98.fstlir rpnpy.librmn.fstd98.fstprm rpnpy.librmn.fstd98.fstluk rpnpy.librmn.fstd98.fstopenall rpnpy.librmn.fstd98.fstcloseall rpnpy.librmn.grids.readGrid rpnpy.vgd.base.vgd_read """ # Get the list of ip1 on thermo, momentum levels in this file #TODO: if ip1 is provided get the keys for these ip1 vGrid = None tlevels = get_levels_keys(fileId, nomvar, datev, ip2, ip3, typvar, etiket, vGrid=vGrid, thermoMom='VIPT', verbose=verbose) vGrid = tlevels['v'] mlevels = get_levels_keys(fileId, tlevels['nomvar'], tlevels['datev'], tlevels['ip2'], tlevels['ip3'], tlevels['typvar'], tlevels['etiket'], vGrid=vGrid, thermoMom='VIPM', verbose=verbose) ip1keys = tlevels['ip1keys'] if len(mlevels['ip1keys']) > len(tlevels['ip1keys']): if verbose: print("(fst_read_3d) Using Momentum level list") ip1keys = mlevels['ip1keys'] elif verbose: print("(fst_read_3d) Using Thermo level list") if verbose or len(ip1keys) == 0: print("(fst_read_3d) Found {0} records for {1} ip2={2} ip3={3} datev={4} typvar={5} etiket={6}"\ .format(len(ip1keys), nomvar, ip2, ip3, datev, typvar, etiket)) if len(ip1keys) == 0: return None # Read all 2d records and copy to 3d array r3d = None r2d = {'d' : None} k = 0 for ip1, key in ip1keys: r2d = _rmn.fstluk(key, dataArray=r2d['d']) print("Read {nomvar} ip1={ip1} ip2={ip2} ip3={ip3} typv={typvar} etk={etiket}".format(**r2d)) if r3d is None: r3d = r2d.copy() rshape = list(r2d['d'].shape[0:2]) + [len(ip1keys)] if dataArray is None: r3d['d'] = _np.empty(rshape, dtype=r2d['d'].dtype, order='FORTRAN') else: if isinstance(dataArray,_np.ndarray) and dataArray.shape == rshape: r3d['d'] = dataArray else: raise TypeError('Provided dataArray is not the right type or shape') r3d['g'] = _rmn.readGrid(fileId, r2d) print("Read the horizontal grid descriptors for {nomvar}".format(**r2d)) if r2d['d'].shape[0:2] != r3d['d'].shape[0:2]: raise _rmn.RMNError("Wrong shape for input data.") r3d['d'][:,:,k] = r2d['d'][:,:] k += 1 ip1list = [x[0] for x in ip1keys] r3d.update({ 'shape' : r3d['d'].shape, 'ni' : r3d['d'].shape[0], 'nj' : r3d['d'].shape[1], 'nk' : r3d['d'].shape[2], 'ip1' : -1, 'ip1s' : ip1list, 'v' : vGrid }) # Read RFLD and compute pressure on levels if getPress: press = get_levels_press(fileId, vGrid, r3d['d'].shape[0:2], ip1list, tlevels['datev'], tlevels['ip2'], tlevels['ip3'], tlevels['typvar'], tlevels['etiket'], verbose=False) r3d.update({ 'rfld' : press['rfld'], 'phPa' : press['phPa'] }) return r3d
def _makevars(self): from fstd2nc.mixins import _iter_type, _var_type, _axis_type, _dim_type from collections import OrderedDict from rpnpy.librmn.interp import ezqkdef, EzscintError, ezget_nsubgrids from rpnpy.librmn.all import readGrid, RMNError import numpy as np # Scan through the data, and look for any use of horizontal coordinates. grids = OrderedDict() gridmaps = OrderedDict() lats = OrderedDict() lons = OrderedDict() # Only output 1 copy of 1D coords (e.g. could have repetitions with # horizontal staggering. coords = set() super(XYCoords, self)._makevars() # Make sure any LA/LO records get processed first, so we can apply them as # coordinates to other variables. varlist = self._varlist varlist = [v for v in varlist if v.name in ('LA', 'LO') ] + [v for v in varlist if v.name not in ('LA', 'LO')] for var in varlist: # Don't touch variables with no horizontal grid. if all(a not in var.dims for a in ('i', 'j', 'station_id')): continue # Get grid parameters. ni = int(var.atts['ni']) nj = int(var.atts['nj']) grtyp = var.atts['grtyp'] ig1 = int(var.atts['ig1']) ig2 = int(var.atts['ig2']) ig3 = int(var.atts['ig3']) ig4 = int(var.atts['ig4']) # Uniquely identify the grid for this variable. # # Use a looser identifier for timeseries data (ni/nj have different # meanings here (not grid-related), and could have multiple grtyp # values ('+','Y') that should share the same lat/lon info. if var.atts.get('typvar', '').strip() == 'T': key = ('T', ig1, ig2) else: key = (grtyp, ni, nj, ig1, ig2, ig3, ig4) if grtyp in ('Y', '+'): key = key[1:] # Check if we already defined this grid. if key not in grids: lat = lon = xaxis = yaxis = None # Check if GridMap recognizes this grid. if grtyp not in self._direct_grids: try: grd = readGrid(self._meta_funit, var.atts.copy()) gmap = GridMap.gen_gmap(grd) gmapvar = gmap.gen_gmapvar() gridmaps[key] = gmapvar (xaxis, yaxis, gridaxes, lon, lat) = gmap.gen_xyll() except (TypeError, EzscintError, KeyError, RMNError, ValueError): pass # Wasn't supported. # Otherwise, need to decode the information here. if lat is None or lon is None: latatts = OrderedDict() latatts['long_name'] = 'latitude' latatts['standard_name'] = 'latitude' latatts['units'] = 'degrees_north' lonatts = OrderedDict() lonatts['long_name'] = 'longitude' lonatts['standard_name'] = 'longitude' lonatts['units'] = 'degrees_east' latarray = lonarray = None try: # First, handle non-ezqkdef grids. if grtyp in self._direct_grids: latarray = self._find_coord( var, '^^')['d'].squeeze(axis=2) lonarray = self._find_coord( var, '>>')['d'].squeeze(axis=2) # Handle ezqkdef grids. else: gdid = ezqkdef(ni, nj, grtyp, ig1, ig2, ig3, ig4, self._meta_funit) ll = gdll(gdid) latarray = ll['lat'] lonarray = ll['lon'] xycoords = gdgaxes(gdid) ax = xycoords['ax'].transpose() ay = xycoords['ay'].transpose() # Convert from degenerate 2D arrays to 1D arrays. ax = ax[0, :] ay = ay[:, 0] xaxis = _axis_type('x', {'axis': 'X'}, ax) yaxis = _axis_type('y', {'axis': 'Y'}, ay) except (TypeError, EzscintError, KeyError, RMNError, ValueError): pass # Check for LA/LO variables, and use these as the coordinates if # nothing else available. if latarray is None and var.name == 'LA': var.name = 'lat' var.atts.update(latatts) #grids[key] = list(var.axes) lats[key] = var continue if lonarray is None and var.name == 'LO': var.name = 'lon' var.atts.update(lonatts) grids[key] = list(var.axes) lons[key] = var continue if latarray is None or lonarray is None: warn( _("Unable to get lat/lon coordinates for '%s'") % var.name) continue # Construct lat/lon variables from latarray and lonarray. latarray = latarray.transpose( ) # Switch from Fortran to C order. lonarray = lonarray.transpose( ) # Switch from Fortran to C order. # Case 1: lat/lon can be resolved into 1D Cartesian coordinates. # Calculate the mean lat/lon arrays in double precision. meanlat = np.mean(np.array(latarray, dtype=float), axis=1, keepdims=True) meanlon = np.mean(np.array(lonarray, dtype=float), axis=0, keepdims=True) if latarray.shape[ 1] > 1 and lonarray.shape[1] > 1 and np.allclose( latarray, meanlat) and np.allclose( lonarray, meanlon): # Reduce back to single precision for writing out. meanlat = np.array(meanlat, dtype=latarray.dtype).squeeze() meanlon = np.array(meanlon, dtype=lonarray.dtype).squeeze() # Ensure monotonicity of longitude field. # (gdll may sometimes wrap last longitude to zero). # Taken from old fstd_core.c code. if meanlon[-2] > meanlon[-3] and meanlon[-1] < meanlon[ -2]: meanlon[-1] += 360. latarray = meanlat lonarray = meanlon lat = _axis_type('lat', latatts, latarray) lon = _axis_type('lon', lonatts, lonarray) gridaxes = [lat, lon] # Case 2: lat/lon are series of points. elif latarray.shape[0] == 1 and lonarray.shape[ 0] == 1 and ('i' in var.dims or 'station_id' in var.dims): latarray = latarray[0, :] lonarray = lonarray[0, :] # Special case for station data station_id = var.getaxis('station_id') if station_id is not None: gridaxes = [station_id] # Subset the lat/lon to the stations that are actually found. # Assuming the station id (ip3) starts at 1. if isinstance(station_id, _axis_type): indices = np.array(station_id.array, dtype=int) - 1 latarray = latarray[indices] lonarray = lonarray[indices] else: gridaxes = [var.getaxis('i')] lat = _var_type('lat', latatts, gridaxes, latarray) lon = _var_type('lon', lonatts, gridaxes, lonarray) # Case 3: General 2D lat/lon fields on X/Y coordinate system. elif xaxis is not None and yaxis is not None: gridaxes = [yaxis, xaxis] # Special case: have supergrid data, and the user wants to split it? if grtyp == 'U' and self._subgrid_axis: ngrids = ezget_nsubgrids(gdid) ny = len(yaxis.array) // ngrids yaxis.array = yaxis.array[:ny] subgrid = _dim_type('subgrid', ngrids) gridaxes = [subgrid, yaxis, xaxis] latarray = latarray.reshape(ngrids, ny, -1) lonarray = lonarray.reshape(ngrids, ny, -1) lat = _var_type('lat', latatts, gridaxes, latarray) lon = _var_type('lon', lonatts, gridaxes, lonarray) # Case 4: General 2D lat/lon fields with no coordinate system. elif 'i' in var.dims and 'j' in var.dims: gridaxes = [var.getaxis('j'), var.getaxis('i')] lat = _var_type('lat', latatts, gridaxes, latarray) lon = _var_type('lon', lonatts, gridaxes, lonarray) # --- End of lat/lon/xaxis/yaxis decoding. if lat is None or lon is None: warn( _("Unable to get lat/lon coordinates for '%s'") % var.name) continue # Sanity check on lat/lon - make sure we have something of the right size. if lat.array.shape == lat.shape and lon.array.shape == lon.shape: grids[key] = gridaxes lats[key] = lat lons[key] = lon else: warn(_("Wrong shape of lat/lon for '%s'") % var.name) continue # --- End of grid decoding. gridaxes = grids[key] lat = lats[key] lon = lons[key] # Update the var's horizontal coordinates. newaxes = [] if len(gridaxes) == 1: newaxes = [('i', gridaxes[0])] elif len(gridaxes) == 2: newaxes = [('j', gridaxes[0]), ('i', gridaxes[1])] elif len(gridaxes) == 3: newaxes = [('k', gridaxes[0]), ('j', gridaxes[1]), ('i', gridaxes[2])] else: warn(_("Unusual grid axes for '%s' - ignoring.") % var.name) dims = var.dims for oldname, newaxis in newaxes: if oldname in dims: var.axes[dims.index(oldname)] = newaxis # For 2D lat/lon, need to reference them as coordinates in order for # netCDF viewers to display the field properly. if 'lat' not in var.dims or 'lon' not in var.dims: coordinates = var.atts.get('coordinates', []) coordinates.extend([lon, lat]) var.atts['coordinates'] = coordinates if key in gridmaps: var.atts['grid_mapping'] = gridmaps[key] # Throw out superfluous LA/LO variables, if lat/lon was already decoded. if var.name == 'LA' and ('lat' in var.dims or lat in coordinates): var.name = None if var.name == 'LO' and ('lon' in var.dims or lon in coordinates): var.name = None self._varlist = [v for v in varlist if v.name is not None]
def test_41(self): """ Horizontal Interpolation See also: """ import os, sys, datetime import rpnpy.librmn.all as rmn fdate = datetime.date.today().strftime('%Y%m%d') + '00_048' CMCGRIDF = os.getenv('CMCGRIDF').strip() fileNameIn = os.path.join(CMCGRIDF, 'prog', 'regeta', fdate) fileNameOut = 'p0fstfile.fst' # Restric to the minimum the number of messages printed by librmn rmn.fstopt(rmn.FSTOP_MSGLVL,rmn.FSTOPI_MSG_CATAST) try: # Create Destination grid # Note: Destination grid can also be read from a file gp = { 'grtyp' : 'Z', 'grref' : 'E', 'ni' : 90, 'nj' : 45, 'lat0' : 35., 'lon0' : 250., 'dlat' : 0.5, 'dlon' : 0.5, 'xlat1' : 0., 'xlon1' : 180., 'xlat2' : 1., 'xlon2' : 270. } gOut = rmn.encodeGrid(gp) print("CB41: Defined a %s/%s grid of shape=%d, %d" % (gOut['grtyp'], gOut['grref'], gOut['ni'], gOut['nj'])) except: sys.stderr.write("Problem creating grid\n") sys.exit(1) # Open Files try: fileIdIn = rmn.fstopenall(fileNameIn) fileIdOut = rmn.fstopenall(fileNameOut, rmn.FST_RW) except: sys.stderr.write("Problem opening the files: %s, %s\n" % (fileNameIn, fileNameOut)) sys.exit(1) try: # Find and read record to interpolate with its grid r = rmn.fstlir(fileIdIn, nomvar='P0') gIn = rmn.readGrid(fileIdIn, r) print("CB41: Read P0") # Set interpolation options and interpolate rmn.ezsetopt(rmn.EZ_OPT_INTERP_DEGREE, rmn.EZ_INTERP_LINEAR) d = rmn.ezsint(gOut, gIn, r) print("CB41: Interpolate P0") # Create new record to write with interpolated data and r2 = r.copy() # Preserve meta from original record r2.update(gOut) # update grid information r2.update({ # attach data and update specific meta 'etiket': 'my_etk', 'd' : d }) # Write record data + meta + grid to file rmn.fstecr(fileIdOut, r2) rmn.writeGrid(fileIdOut, gOut) print("CB41: Wrote interpolated P0 and its grid") except: pass finally: # Properly close files even if an error occured above # This is important when editing to avoid corrupted files rmn.fstcloseall(fileIdIn) rmn.fstcloseall(fileIdOut) os.unlink(fileNameOut) # Remove test file
def test_23(self): """ Edit: Read, Edit, Write records with meta, grid and vgrid This example shows how to * select records in a RPNStd file * read the record data + meta * edit/use record data and meta (compute the wind velocity) * write the recod data + meta * copy (read/write) the record grid descriptors * copy (read/write) the file vgrid descriptor See also: rpnpy.librmn.fstd98.fstopt rpnpy.librmn.fstd98.fstopenall rpnpy.librmn.fstd98.fstcloseall rpnpy.librmn.fstd98.fsrinl rpnpy.librmn.fstd98.fsrluk rpnpy.librmn.fstd98.fsrlir rpnpy.librmn.fstd98.fsrecr rpnpy.librmn.grids.readGrid rpnpy.librmn.grids.writeGrid rpnpy.vgd.base.vgd_read rpnpy.vgd.base.vgd_write rpnpy.librmn.const rpnpy.vgd.const """ import os, sys, datetime from scipy.constants import knot as KNOT2MS import numpy as np import rpnpy.librmn.all as rmn import rpnpy.vgd.all as vgd fdate = datetime.date.today().strftime('%Y%m%d') + '00_048' CMCGRIDF = os.getenv('CMCGRIDF').strip() fileNameIn = os.path.join(CMCGRIDF, 'prog', 'regeta', fdate) fileNameOut = 'uvfstfile.fst' # Restrict to the minimum the number of messages printed by librmn rmn.fstopt(rmn.FSTOP_MSGLVL,rmn.FSTOPI_MSG_CATAST) # Open Files try: fileIdIn = rmn.fstopenall(fileNameIn) fileIdOut = rmn.fstopenall(fileNameOut, rmn.FST_RW) except: sys.stderr.write("Problem opening the files: %s, %s\n" % (fileNameIn, fileNameOut)) sys.exit(1) try: # Copy the vgrid descriptor v = vgd.vgd_read(fileIdIn) vgd.vgd_write(v, fileIdOut) print("CB23: Copied the vgrid descriptor") # Loop over the list of UU records to copy uu = {'d': None} vv = {'d': None} uvarray = None copyGrid = True for k in rmn.fstinl(fileIdIn, nomvar='UU'): # Read the UU record data and meta from fileNameIn # Provide data array to re-use memory uu = rmn.fstluk(k, dataArray=uu['d']) # Read the corresponding VV # Provide data array to re-use memory vv = rmn.fstlir(fileIdIn, nomvar='VV', ip1=uu['ip1'], ip2=uu['ip2'], datev=uu['datev'], dataArray=vv['d']) # Compute the wind modulus in m/s # Copy metadata from the UU record # Create / re-use memory space for computation results uv = uu.copy() if uvarray is None: uvarray = np.empty(uu['d'].shape, dtype=uu['d'].dtype, order='FORTRAN') uv['d'] = uvarray uv['d'][:,:] = np.sqrt(uu['d']**2. + vv['d']**2.) uv['d'] *= KNOT2MS # Convert from knot to m/s # Set new record name and Write it to fileNameOut uv['nomvar'] = 'WSPD' rmn.fstecr(fileIdOut, uv) print("CB23: Wrote %s ip1=%d, ip2=%d, dateo=%s : mean=%f" % (uv['nomvar'], uv['ip1'], uv['ip2'], uv['dateo'], uv['d'].mean())) # Read and Write grid (only once, all rec are on the same grid) if copyGrid: copyGrid = False g = rmn.readGrid(fileIdIn, uu) rmn.writeGrid(fileIdOut, g) print("CB23: Copied the grid descriptors") except: pass finally: # Properly close files even if an error occured above # This is important when editing to avoid corrupted files rmn.fstcloseall(fileIdIn) rmn.fstcloseall(fileIdOut) os.unlink(fileNameOut) # Remove test file