示例#1
0
 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])))
示例#2
0
 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
示例#3
0
 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
示例#4
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)
示例#5
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)
示例#6
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
示例#7
0
    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)
示例#8
0
    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)
示例#9
0
    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])))
示例#10
0
 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)
示例#11
0
 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)
示例#12
0
 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)
示例#13
0
 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)
示例#14
0
 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
示例#15
0
 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
示例#16
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)
    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
       }
示例#17
0
    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
示例#18
0
    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)
示例#19
0
    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
示例#20
0
    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)
示例#21
0
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
示例#22
0
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
示例#23
0
    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]
示例#24
0
    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
示例#25
0
    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