pytdlpack

Introduction

pytdlpack is a Python interface to reading/writing TDLPACK files via official MOS-2000 (MOS2K) Fortran-based source files. The necessary MOS2K source files are included in this package and are available as module, tdlpack.

TDLPACK is a GRIB-like binary data format that is exclusive to MOS2K Fortran-based sofftware system. This software system was developed at the Meteorological Development Laboratory (MDL) within NOAA/NWS and its primary purpose is to perform statistical post-processing of meteorological data.

TDLPACK-formatted data are contained in two type of Fortran-based files; sequential or random-access. Sequential files are variable length, record-based, and unformatted. Random-access files are fixed-length and direct-access. pytdlpack accommodates reading and writing of both types of TDLPACK files.

TDLPACK format is based on the World Meteorological Organizations (WMO) GRIdded Binary (GRIB) code, but has been tailored to MDL needs for data -- mainly the ability to store 1D (vector), datasets such as station observations, along with 2D grids.

There also exists two other types of records in a TDLPACK file: station call letter record and trailer record. A station call letter record can exist in both types of TDLPACK files and contains a stream of alphanumeric characters (CHARACTER(LEN=8)). A trailer record exists to signal the MOS2K system that another station call letter record is about to be read or we have reached the end of the file (EOF). A trailer record is not written to a random-access file.

For more information on the MOS-2000 software system and TDLPACK foremat, user is referred to the official MOS-2000 documentation.

In order for pytdlpack to read/write TDLPACK files, we need to compile the necessary MOS2K Fortran source code into a shared object library. This is handled by the setup process as the Fortran source is compiled with f2py (included with Numpy). The following are some important items to note regarding MOS2K source files included:

  • Several Fortran 90+ source files have been created to better interface to MOS2K Fortran 77 code.
  • The only modification made to MOS2K source files is changing the filename variable, CFILX from CHARACTER*60 to CHARACTER*1024 in the appropropriate subroutines where random-access file IO occurs.

Download

Requires

  • Python 3.6+
  • numpy array module, version 1.12 or later.
  • setuptools, version 18.0 or later.
  • GNU or Intel Fortran compiler (if installing from source).

Install

pip3 install pytdlpack

Build and Install from Source

python3 setup.py build_ext --fcompiler=[gnu95|intelem] build
python3 setup.py install [--user | --prefix=PREFIX]

Tutorial

  1. Creating/Opening/Closing a TDLPACK file.
  2. Reading a TDLPACK file.
  3. Writing a TDLPACK file.
  4. Creating a TDLPACK Station Record.
  5. Creating a TDLPACK Record.
  6. Packing/Unpacking a TDLPACK Record.

1) Creating/Opening/Closing a TDLPACK file.

To create a TDLPACK file from Python, you call the pytdlpack.open function and provide the file name and mode='w' or 'a'. For mode='a', this will append to an existing file. When creating a new file, the default file format is 'sequential', but the user can also specify the format with format='sequential' or 'random-access'. If the new file is random-access, then the user can also specify ra_template='small' or 'large'. The default is 'small' and 'large' is recommended for a high-resolution grids (i.e. ~ > 2M total points).

Example: Create a new sequential file:

>>> import pytdlpack
>>> f = pytdlpack.open('test.sq',mode='w')

Example: Create a new random-access file:

>>> import pytdlpack
>>> f = pytdlpack.open('test.sq',mode='w',format='random-access',ra_template='small')

To open an existing TDLPACK file, simply provide the filename since the default mode is read.

import pytdlpack
>>> f = pytdlpack.open('test.sq')
>>> type(f)
<class 'pytdlpack._pytdlpack.TdlpackFile'>
>>> f
byte_order = >
data_type =
eof = False
format = sequential
fortran_lun = 65535
mode = r
name = test.sq
position = 0
ra_master_key = None
size = 998672

To close a TDLPACK file is straightforward.

>>> f.close()

2) Reading a TDLPACK file.

When a TDLPACK file is opened, an instance of class pytdlpack.TdlpackFile is created. To read a record the file, use the class method pytdlpack.TdlpackFile.read. By default only 1 record is returned and the TDLPACK indentification sections are unpacked.

Example: Reading a gridded TDLPACK record.

>>> x = f.read()
>>> x
grid_length = 2539.703
id = [223254166         0         6         0]
ioctet = 998656
ipack = [1347175508  255654144 1191249890 ...          0          0          0]
is0 = [1347175508     998649          0          0          0          0
          0          0          0          0          0          0
          0          0          0          0          0          0
          0          0          0          0          0          0
          0          0          0          0          0          0
          0          0          0          0          0          0
          0          0          0          0          0          0
          0          0          0          0          0          0
          0          0          0          0          0          0]
is1 = [        71          1       2018         12          4          0
          0 2018120400  223254166          0          6          0
          6          0         66          0          1          0
          0          0          0         32          0          0
          0          0          0          0          0          0
          0          0          0          0          0          0
          0          0          0          0          0          0
          0          0          0          0          0          0
          0          0          0          0          0          0]
is2 = [     28       3    2345    1597  192290 2337234  950000 2539703  250000
       0       0       0       0       0       0       0       0       0
       0       0       0       0       0       0       0       0       0
       0       0       0       0       0       0       0       0       0
       0       0       0       0       0       0       0       0       0
       0       0       0       0       0       0       0       0       0]
is4 = [ 998538      12 3744965       0       0       0       0       0       0
       0       0       0       0       0       0       0       0       0
       0       0       0       0       0       0       0       0       0
       0       0       0       0       0       0       0       0       0
       0       0       0       0       0       0       0       0       0
       0       0       0       0       0       0       0       0       0]
lead_time = 6
lower_left_latitude = 19.229
lower_left_longitude = 233.7234
map_proj = 3
number_of_values = 3744965
nx = 2345
ny = 1597
origin_longitude = 95.0
plain =
primary_missing_value = 0.0
reference_date = 2018120400
secondary_missing_value = 0.0
standard_latitude = 25.0
type = grid

You can also have pytdlpack.TdlpackFile.read read the entire file with optional keyword all = True. Reading all records at once is not recommened if the file is large in size.

>>> x = f.read(all=True)

Here, x will become a list of instances of either pytdlpack.TdlpackStationRecord, pytdlpack.TdlpackRecord, or pytdlpack.TdlpackTrailerRecord.

If the file being read a TDLPACK random-access (format='random-access'), then you can also provide the id= argument to search for a specific record.

>>> import pytdlpack
>>> f = pytdlpack.open('test.ra')
>>> x = f.read(id=[400001000,0,0,0])
>>> type(x)
<class 'pytdlpack._pytdlpack.TdlpackStationRecord'>

3) Writing a TDLPACK file.

Writing to a TDLPACK file is as easy as reading. The following uses variable x, from above, is an instance of pytdlpack.TdlpackStationRecord that has been packed.

Example: Write to a new TDLPACK sequential file.

>>> import pytdlpack
>>> f.open("new.sq",mode="w",format="sequential")
>>> f.write(x)
>>> f.close()

4) Creating a TDLPACK Station Record.

The constructor for pytdlpack.TdlpackStationRecord provides two methods of instantiation via the traditional kwargs (see pytdlpack.TdlpackStationRecord.__init__) or simply providing ccall = ... (recommended)**. The value passed to the ccall= argument can be a single call letter string, list, tuple, or comma-delimited string of station call letter records.

>>> import pytdlpack
>>> stations = pytdlpack.TdlpackStationRecord(['KBWI','KDCA','KIAD'])
>>> stations
ccall = ['KBWI', 'KDCA', 'KIAD']
id = [400001000         0         0         0]
ioctet = 0
ipack = []
number_of_stations = 3

5) Creating a TDLPACK Record.

The recommended method for creating a pytdlpack.TdlpackRecord is to pass the TDLPACK indentification arrays, plain language string, and data to the approproiate keyword. Please see pytdlpack.TdlpackRecord.__init__ for more info.

>>> import numpy as np
>>> record = pytdlpack.TdlpackRecord(date=2019070100,id=[4210008, 0, 24, 0],lead=24,
plain="GFS WIND SPEED",grid=grid_def,data=<np.float32 array>)

The user is encouraged to read the official MOS-2000 documentation (specifically Chapter 5) on construction of these arrays and proper encoding.

6) Packing/Unpacking a TDLPACK Record.

Once any of the three classes of TDLPACK records have been instantiated, you can pack the record using the class method pack. Using the example from Section 5, record is now an instance of pytdlpack.TdlpackRecord. You can pack this record with the following:

>>> record.pack()

To unpack a packed TDLPACK record, perform:

>>> record.unpack()

The pytdlpack.TdlpackRecord.unpack class method for TDLPACK data records, contains optional arguments data= (to control the unpacking of data) and missing_value= (to set a different missing value other than what is contained in the record). For TDLPACK data records, pytdlpack.TdlpackRecord.unpack automatically unpacks the TDLPACK meta-data.

>>> record.unpack(data=True,missing_value=-9999.0)
 1# init for pytdlpack package
 2from ._pytdlpack import *
 3from ._pytdlpack import __doc__,__pdoc__
 4
 5from ._grid_definitions import grids
 6
 7from .version import version as __version__
 8
 9__all__ = ['__version__','TdlpackFile','TdlpackRecord','TdlpackStationRecord','TdlpackTrailerRecord',
10           'open','create_grid_definition','grids']
__version__ = '1.1.3'
class TdlpackFile:
346class TdlpackFile(object):
347    """
348    TDLPACK File with associated information.
349
350    Attributes
351    ----------
352
353    **`byte_order : str`**
354
355    Byte order of TDLPACK file using definitions as defined by Python built-in struct module.
356
357    **`data_type : {'grid', 'station'}`**
358
359    Type of data contained in the file.
360
361    **`eof : bool`**
362
363    True if we have reached end of file.
364
365    **`format : {'random-access', 'sequential'}`**
366
367    File format of TDLPACK file.
368
369    **`fortran_lun : np.int32`**
370
371    Fortran unit number for file access. If the file is not open, then this value is -1.
372
373    **`mode : str`**
374
375    Access mode (see pytdlpack.open() docstring).
376
377    **`name : str`**
378
379    File name.
380
381    **`position : int`**
382
383    The current record being read from file. If the file type is 'random-access', then this
384    value is -1.
385
386    **`size : int`**
387
388    File size in units of bytes.
389    """
390    counter = 0
391    def __init__(self,**kwargs):
392        """Contructor"""
393        type(self).counter += 1
394        self.byte_order = ''
395        self.data_type = ''
396        self.eof = False
397        self.format = ''
398        self.fortran_lun = np.int32(-1)
399        self.mode = ''
400        self.name = ''
401        self.position = np.int32(0)
402        self.ra_master_key = None
403        for k, v in kwargs.items():
404            setattr(self,k,v)
405
406    def __repr__(self):
407        strings = []
408        keys = self.__dict__.keys()
409        for k in keys:
410            if not k.startswith('_'):
411                strings.append('%s = %s\n'%(k,self.__dict__[k]))
412        return ''.join(strings)
413
414    def __enter__(self):
415        """no additional setup as opening with context manager is not required"""
416        return self
417
418    def __exit__(self,type,value,traceback):
419        """
420        """
421        self.close()
422
423    def __iter__(self):
424        """
425        """
426        return self
427
428    def __next__(self):
429        """
430        """
431        if not self.eof:
432            rec = self.read()
433            if self.eof and isinstance(rec,type(None)):
434                raise StopIteration
435            else:
436                return rec
437        else:
438            raise StopIteration
439
440    def _determine_record_type(self,ipack,ioctet):
441        kwargs = {}
442        if ipack[0] == 0 and ipack[4] == 9999 and ioctet == 24:
443            kwargs['ipack'] = deepcopy(ipack)
444            kwargs['ioctet'] = deepcopy(ioctet)
445            kwargs['id'] = np.int32([0,0,0,0])
446            return TdlpackTrailerRecord(**kwargs)
447        if ipack[0] > 0:
448            kwargs['ipack'] = deepcopy(ipack)
449            kwargs['ioctet'] = deepcopy(ioctet)
450            header = struct.unpack('>4s',ipack[0].byteswap())[0]
451            if _IS_PYTHON3:
452                header = header.decode()
453            if header in ["PLDT","TDLP"] :
454                if not self.data_type: self.data_type = 'grid'
455                kwargs['id'] = deepcopy(ipack[5:9])
456                kwargs['reference_date'] = deepcopy(ipack[4])
457                kwargs['lead_time'] = np.int32(str(ipack[7])[-3:])
458                kwargs['_filelun'] = self.fortran_lun
459                kwargs['_starecindex'] = len(_starecdict[self.fortran_lun])-1 if len(_starecdict[self.fortran_lun]) > 0 else 0
460                return TdlpackRecord(**kwargs)
461            else:
462                if not self.data_type: self.data_type = 'station'
463                kwargs['id'] = np.int32([400001000,0,0,0])
464                kwargs['number_of_stations'] = np.int32(deepcopy(ioctet/NCHAR))
465                return TdlpackStationRecord(**kwargs)
466        else:
467            #raise
468            pass #for now
469
470    def backspace(self):
471        """
472        Position file backwards by one record.
473        """
474        if self.fortran_lun == -1:
475            raise IOError("File is not opened.")
476
477        if self.format == 'sequential':
478            _ier = np.int32(0)
479            _ier = tdlpack.backspacefile(self.fortran_lun)
480            if _ier == 0:
481                self.position -= 1
482            else:
483                raise IOError("Could not backspace file. ier = "+str(_ier))
484
485    def close(self):
486        """
487        Close a TDLPACK file.
488        """
489        _ier = np.int32(0)
490        if self.format == 'random-access':
491            _ier = tdlpack.clfilm(FORTRAN_STDOUT_LUN,self.fortran_lun)
492        elif self.format == 'sequential':
493            _ier = tdlpack.closefile(FORTRAN_STDOUT_LUN,self.fortran_lun,np.int32(2))
494        if _ier == 0:
495            try:
496                del _starecdict[self.fortran_lun]
497            except(KeyError):
498                pass
499            self.eof = False
500            self.fortran_lun = -1
501            self.position = 0
502            type(self).counter -= 1
503        else:
504            raise IOError("Trouble closing file. ier = "+str(_ier))
505
506    def read(self,all=False,unpack=True,id=[9999,0,0,0]):
507        """
508        Read a record from a TDLPACK file.
509
510        Parameters
511        ----------
512
513        **`all : bool, optional`**
514
515        Read all records from file. The default is False.
516
517        **`unpack : bool, optional`**
518
519        Unpack TDLPACK identification sections.  Note that data are not unpacked.  The default is True.
520
521        **`id : array_like or list, optional`**
522
523        Provide an ID to search for. This can be either a Numpy.int32 array with shape (4,) or list
524        with length 4.  The default is [9999,0,0,0] which will signal the random access IO reader
525        to sequentially read the file.
526
527        Returns
528        -------
529
530        **`record [records] : instance [list]`**
531
532        An instance of list of instances contaning `pytdlpack.TdlpackStationRecord`,
533        `pytdlpack.TdlpackRecord`, or `pytdlpack.TdlpackTrailerRecord`
534        """
535        if self.fortran_lun == -1:
536            raise IOError("File is not opened.")
537
538        record = None
539        records = []
540        while True:
541            _ipack = np.array((),dtype=np.int32)
542            _ioctet = np.int32(0)
543            _ier = np.int32(0)
544            if self.format == 'random-access':
545                id = np.int32(id)
546                _nvalue = np.int32(0)
547                _ipack,_nvalue,_ier = tdlpack.rdtdlm(FORTRAN_STDOUT_LUN,self.fortran_lun,self.name,id,ND5,L3264B)
548                if _ier == 0:
549                    _ioctet = _nvalue*NBYPWD
550                    record = self._determine_record_type(_ipack,_ioctet)
551                elif _ier == 153:
552                    self.eof = True
553                    break
554                else:
555                    #raise
556                    pass # for now
557            elif self.format == 'sequential':
558                _ioctet,_ipack,_ier = tdlpack.readfile(FORTRAN_STDOUT_LUN,self.name,self.fortran_lun,ND5,L3264B,np.int32(2))
559                if _ier == 0:
560                    record = self._determine_record_type(_ipack,_ioctet)
561                    self.position += 1
562                elif _ier == -1:
563                    self.eof = True
564                    break
565
566            if unpack: record.unpack()
567
568            if type(record) is TdlpackStationRecord:
569                _starecdict[self.fortran_lun].append(record.stations)
570
571            if all:
572                records.append(record)
573            else:
574                break
575
576        if len(records) > 0:
577            return records
578        else:
579            return record
580
581    def rewind(self):
582        """
583        Position file to the beginning.
584        """
585        if self.fortran_lun == -1:
586            raise IOError("File is not opened.")
587
588        if self.format == 'sequential':
589            _ier = np.int32(0)
590            _ier = tdlpack.rewindfile(self.fortran_lun)
591            if _ier == 0:
592                self.position = 0
593                self.eof = False
594            else:
595                raise IOError("Could not rewind file. ier = "+str(_ier))
596
597    def write(self,record):
598        """
599        Write a packed TDLPACK record to file.
600
601        Parameters
602        ----------
603
604        **`record : instance`**
605
606        An instance of either `pytdlpack.TdlpackStationRecord`, `pytdlpack.TdlpackRecord`,
607        or `pytdlpack.TdlpackTrailerRecord`.  `record` should contain a packed data.
608        """
609        #pdb.set_trace()
610        if self.fortran_lun == -1:
611            raise IOError("File is not opened.")
612        if self.mode == "r":
613            raise IOError("File is read-only.")
614
615        _ier = np.int32(0)
616        _ntotby = np.int32(0)
617        _ntotrc = np.int32(0)
618        _nreplace = np.int32(0)
619        _ncheck = np.int32(0)
620
621        if type(record) is TdlpackStationRecord:
622            if self.position == 0: self.data_type = 'station'
623            _nwords = record.number_of_stations*2
624            if self.format == 'random-access':
625                _ier = tdlpack.wrtdlm(FORTRAN_STDOUT_LUN,self.fortran_lun,self.name,
626                                       record.id,record.ipack[0:_nwords],_nreplace,
627                                       _ncheck,L3264B)
628            elif self.format == 'sequential':
629                _ntotby,_ntotrc,_ier = tdlpack.writep(FORTRAN_STDOUT_LUN,self.fortran_lun,
630                                       record.ipack[0:_nwords],_ntotby,_ntotrc,L3264B)
631        elif type(record) is TdlpackRecord:
632            if self.position == 0: self.data_type = 'grid'
633            _nwords = np.int32(record.ioctet/NBYPWD)
634            if self.format == 'random-access':
635                record.ipack[0] = record.ipack[0].byteswap()
636                _ier = tdlpack.wrtdlm(FORTRAN_STDOUT_LUN,self.fortran_lun,self.name,
637                                       record.id,record.ipack[0:_nwords],_nreplace,
638                                       _ncheck,L3264B)
639            elif self.format == 'sequential':
640                _ntotby,_ntotrc,_ier = tdlpack.writep(FORTRAN_STDOUT_LUN,self.fortran_lun,
641                                       record.ipack[0:_nwords],_ntotby,_ntotrc,L3264B)
642        elif type(record) is TdlpackTrailerRecord:
643            _ier = tdlpack.trail(FORTRAN_STDOUT_LUN,self.fortran_lun,L3264B,L3264W,_ntotby,
644                           _ntotrc)
645        if _ier == 0:
646            self.position += 1
647            self.size = os.path.getsize(self.name)

TDLPACK File with associated information.

Attributes

byte_order : str

Byte order of TDLPACK file using definitions as defined by Python built-in struct module.

data_type : {'grid', 'station'}

Type of data contained in the file.

eof : bool

True if we have reached end of file.

format : {'random-access', 'sequential'}

File format of TDLPACK file.

fortran_lun : np.int32

Fortran unit number for file access. If the file is not open, then this value is -1.

mode : str

Access mode (see pytdlpack.open() docstring).

name : str

File name.

position : int

The current record being read from file. If the file type is 'random-access', then this value is -1.

size : int

File size in units of bytes.

TdlpackFile(**kwargs)
391    def __init__(self,**kwargs):
392        """Contructor"""
393        type(self).counter += 1
394        self.byte_order = ''
395        self.data_type = ''
396        self.eof = False
397        self.format = ''
398        self.fortran_lun = np.int32(-1)
399        self.mode = ''
400        self.name = ''
401        self.position = np.int32(0)
402        self.ra_master_key = None
403        for k, v in kwargs.items():
404            setattr(self,k,v)

Contructor

counter = 0
byte_order
data_type
eof
format
fortran_lun
mode
name
position
ra_master_key
def backspace(self):
470    def backspace(self):
471        """
472        Position file backwards by one record.
473        """
474        if self.fortran_lun == -1:
475            raise IOError("File is not opened.")
476
477        if self.format == 'sequential':
478            _ier = np.int32(0)
479            _ier = tdlpack.backspacefile(self.fortran_lun)
480            if _ier == 0:
481                self.position -= 1
482            else:
483                raise IOError("Could not backspace file. ier = "+str(_ier))

Position file backwards by one record.

def close(self):
485    def close(self):
486        """
487        Close a TDLPACK file.
488        """
489        _ier = np.int32(0)
490        if self.format == 'random-access':
491            _ier = tdlpack.clfilm(FORTRAN_STDOUT_LUN,self.fortran_lun)
492        elif self.format == 'sequential':
493            _ier = tdlpack.closefile(FORTRAN_STDOUT_LUN,self.fortran_lun,np.int32(2))
494        if _ier == 0:
495            try:
496                del _starecdict[self.fortran_lun]
497            except(KeyError):
498                pass
499            self.eof = False
500            self.fortran_lun = -1
501            self.position = 0
502            type(self).counter -= 1
503        else:
504            raise IOError("Trouble closing file. ier = "+str(_ier))

Close a TDLPACK file.

def read(self, all=False, unpack=True, id=[9999, 0, 0, 0]):
506    def read(self,all=False,unpack=True,id=[9999,0,0,0]):
507        """
508        Read a record from a TDLPACK file.
509
510        Parameters
511        ----------
512
513        **`all : bool, optional`**
514
515        Read all records from file. The default is False.
516
517        **`unpack : bool, optional`**
518
519        Unpack TDLPACK identification sections.  Note that data are not unpacked.  The default is True.
520
521        **`id : array_like or list, optional`**
522
523        Provide an ID to search for. This can be either a Numpy.int32 array with shape (4,) or list
524        with length 4.  The default is [9999,0,0,0] which will signal the random access IO reader
525        to sequentially read the file.
526
527        Returns
528        -------
529
530        **`record [records] : instance [list]`**
531
532        An instance of list of instances contaning `pytdlpack.TdlpackStationRecord`,
533        `pytdlpack.TdlpackRecord`, or `pytdlpack.TdlpackTrailerRecord`
534        """
535        if self.fortran_lun == -1:
536            raise IOError("File is not opened.")
537
538        record = None
539        records = []
540        while True:
541            _ipack = np.array((),dtype=np.int32)
542            _ioctet = np.int32(0)
543            _ier = np.int32(0)
544            if self.format == 'random-access':
545                id = np.int32(id)
546                _nvalue = np.int32(0)
547                _ipack,_nvalue,_ier = tdlpack.rdtdlm(FORTRAN_STDOUT_LUN,self.fortran_lun,self.name,id,ND5,L3264B)
548                if _ier == 0:
549                    _ioctet = _nvalue*NBYPWD
550                    record = self._determine_record_type(_ipack,_ioctet)
551                elif _ier == 153:
552                    self.eof = True
553                    break
554                else:
555                    #raise
556                    pass # for now
557            elif self.format == 'sequential':
558                _ioctet,_ipack,_ier = tdlpack.readfile(FORTRAN_STDOUT_LUN,self.name,self.fortran_lun,ND5,L3264B,np.int32(2))
559                if _ier == 0:
560                    record = self._determine_record_type(_ipack,_ioctet)
561                    self.position += 1
562                elif _ier == -1:
563                    self.eof = True
564                    break
565
566            if unpack: record.unpack()
567
568            if type(record) is TdlpackStationRecord:
569                _starecdict[self.fortran_lun].append(record.stations)
570
571            if all:
572                records.append(record)
573            else:
574                break
575
576        if len(records) > 0:
577            return records
578        else:
579            return record

Read a record from a TDLPACK file.

Parameters

all : bool, optional

Read all records from file. The default is False.

unpack : bool, optional

Unpack TDLPACK identification sections. Note that data are not unpacked. The default is True.

id : array_like or list, optional

Provide an ID to search for. This can be either a Numpy.int32 array with shape (4,) or list with length 4. The default is [9999,0,0,0] which will signal the random access IO reader to sequentially read the file.

Returns

record [records] : instance [list]

An instance of list of instances contaning pytdlpack.TdlpackStationRecord, pytdlpack.TdlpackRecord, or pytdlpack.TdlpackTrailerRecord

def rewind(self):
581    def rewind(self):
582        """
583        Position file to the beginning.
584        """
585        if self.fortran_lun == -1:
586            raise IOError("File is not opened.")
587
588        if self.format == 'sequential':
589            _ier = np.int32(0)
590            _ier = tdlpack.rewindfile(self.fortran_lun)
591            if _ier == 0:
592                self.position = 0
593                self.eof = False
594            else:
595                raise IOError("Could not rewind file. ier = "+str(_ier))

Position file to the beginning.

def write(self, record):
597    def write(self,record):
598        """
599        Write a packed TDLPACK record to file.
600
601        Parameters
602        ----------
603
604        **`record : instance`**
605
606        An instance of either `pytdlpack.TdlpackStationRecord`, `pytdlpack.TdlpackRecord`,
607        or `pytdlpack.TdlpackTrailerRecord`.  `record` should contain a packed data.
608        """
609        #pdb.set_trace()
610        if self.fortran_lun == -1:
611            raise IOError("File is not opened.")
612        if self.mode == "r":
613            raise IOError("File is read-only.")
614
615        _ier = np.int32(0)
616        _ntotby = np.int32(0)
617        _ntotrc = np.int32(0)
618        _nreplace = np.int32(0)
619        _ncheck = np.int32(0)
620
621        if type(record) is TdlpackStationRecord:
622            if self.position == 0: self.data_type = 'station'
623            _nwords = record.number_of_stations*2
624            if self.format == 'random-access':
625                _ier = tdlpack.wrtdlm(FORTRAN_STDOUT_LUN,self.fortran_lun,self.name,
626                                       record.id,record.ipack[0:_nwords],_nreplace,
627                                       _ncheck,L3264B)
628            elif self.format == 'sequential':
629                _ntotby,_ntotrc,_ier = tdlpack.writep(FORTRAN_STDOUT_LUN,self.fortran_lun,
630                                       record.ipack[0:_nwords],_ntotby,_ntotrc,L3264B)
631        elif type(record) is TdlpackRecord:
632            if self.position == 0: self.data_type = 'grid'
633            _nwords = np.int32(record.ioctet/NBYPWD)
634            if self.format == 'random-access':
635                record.ipack[0] = record.ipack[0].byteswap()
636                _ier = tdlpack.wrtdlm(FORTRAN_STDOUT_LUN,self.fortran_lun,self.name,
637                                       record.id,record.ipack[0:_nwords],_nreplace,
638                                       _ncheck,L3264B)
639            elif self.format == 'sequential':
640                _ntotby,_ntotrc,_ier = tdlpack.writep(FORTRAN_STDOUT_LUN,self.fortran_lun,
641                                       record.ipack[0:_nwords],_ntotby,_ntotrc,L3264B)
642        elif type(record) is TdlpackTrailerRecord:
643            _ier = tdlpack.trail(FORTRAN_STDOUT_LUN,self.fortran_lun,L3264B,L3264W,_ntotby,
644                           _ntotrc)
645        if _ier == 0:
646            self.position += 1
647            self.size = os.path.getsize(self.name)

Write a packed TDLPACK record to file.

Parameters

record : instance

An instance of either pytdlpack.TdlpackStationRecord, pytdlpack.TdlpackRecord, or pytdlpack.TdlpackTrailerRecord. record should contain a packed data.

class TdlpackRecord:
 649class TdlpackRecord(object):
 650    """
 651    Defines a TDLPACK data record object.  Once data are unpacked (TdlpackRecord.unpack(data=True)),
 652    values are accessible using "fancy indexing".
 653
 654    For gridded records, use grid index values and/or ranges (e.g. rec[0,0]).
 655
 656    For station records, use the station ID string: (e.g. rec['KPHL']).
 657
 658    Attributes
 659    ----------
 660
 661    **`data : array_like`**
 662
 663    Data values.
 664
 665    **`grid_length : float`**
 666
 667    Distance between grid points in units of meters.
 668
 669    **`id : array_like`**
 670
 671    ID of the TDLPACK data record. This is a NumPy 1D array of dtype=np.int32.
 672
 673    **`ioctet : int`**
 674
 675    Size of the packed TDLPACK data record in bytes.
 676
 677    **`ipack : array_like`**
 678
 679    Packed TDLPACK data record. This is a NumPy 1D array of dtype=np.int32.
 680
 681    **`is0 : array_like`**
 682
 683    TDLPACK Section 0 (Indicator Section).
 684
 685    **`is1 : array_like`**
 686
 687    TDLPACK Section 1 (Product Definition Section).
 688
 689    **`is2 : array_like`**
 690
 691    TDLPACK Section 2 (Grid Definition Section)
 692
 693    **`is4 : array_like`**
 694
 695    TDLPACK Section 4 (Data Section).
 696
 697    **`lead_time : int`**
 698
 699    Forecast lead time in units of hours.
 700
 701    **`lower_left_latitude : float`**
 702
 703    Latitude of lower left grid point
 704
 705    **`lower_left_longitude : float`**
 706
 707    Longitude of lower left grid point
 708
 709    **`number_of_values : int`**
 710
 711    Number of data values.
 712
 713    **`nx : int`**
 714
 715    Number of points in the x-direction (West-East).
 716
 717    **`ny : int`**
 718
 719    Number of points in the y-direction (West-East).
 720
 721    **`origin_longitude : float`**
 722
 723    Originating longitude of projected grid.
 724
 725    **`plain : str`**
 726
 727    Plain language description of TDLPACK record.
 728
 729    **`primary_missing_value : float`**
 730
 731    Primary missing value.
 732
 733    **`reference_date : int`**
 734
 735    Reference date from the TDLPACK data record in YYYYMMDDHH format.
 736
 737    **`secondary_missing_value : float`**
 738
 739    Secondary missing value.
 740
 741    **`standard_latitude : float`**
 742
 743    Latitude at which the grid length applies.
 744
 745    **`type : {'grid', 'station'}`**
 746
 747    Identifies the type of data.  This implies that data are 1D for type = 'station'
 748    and data are 2D for type = 'grid'.
 749
 750    """
 751    counter = 0
 752    def __init__(self,date=None,id=None,lead=None,plain=None,grid=None,data=None,
 753                 missing_value=None,**kwargs):
 754        """
 755        Constructor
 756
 757        Parameters
 758        ----------
 759
 760        **`date : int, optional`**
 761
 762        Forecast initialization or observation date in YYYYMMDDHH format.
 763
 764        **`id : list or 1-D array, optional`**
 765
 766        List or 1-D array of length 4 containing the 4-word (integer) MOS-2000 ID of the data
 767        to be put into TdlpackRecord
 768
 769        **`lead : int, optional`**
 770
 771        Lead time (i.e. forecast projection) in hours of the data.  NOTE: This can be omitted
 772
 773        **`plain : str, optional`**
 774
 775        Plain language descriptor.  This is limited to 32 characters, though here
 776        the input can be longer (will be cut off when packing).
 777
 778        **`grid : dict , optional`**
 779
 780        A dictionary containing grid definition attributes.  See
 781        Dictionary of grid specs (created from create_grid_def_dict)
 782
 783        **`data : array_like, optional`**
 784
 785        Data values.
 786
 787        **`missing_value : float or list of floats, optional`**
 788
 789        Provide either a primary missing value or primary and secondary as list.
 790
 791        **`**kwargs : dict, optional`**
 792
 793        Dictionary of class attributes (keys) and class attributes (values).
 794        """
 795        type(self).counter += 1
 796        self._metadata_unpacked = False
 797        self._data_unpacked = False
 798        self.plain = ''
 799        if len(kwargs) == 0:
 800            # Means we are creating TdlpackRecord instance from the other function
 801            # input, NOT the kwargs Dict.
 802            self.id = id
 803            self.reference_date = date
 804            self.type = 'station'
 805            self.is0 = np.zeros(ND7,dtype=np.int32)
 806            self.is1 = np.zeros(ND7,dtype=np.int32)
 807            self.is2 = np.zeros(ND7,dtype=np.int32)
 808            self.is4 = np.zeros(ND7,dtype=np.int32)
 809
 810            self.is1[2] = np.int32(date/1000000)
 811            self.is1[3] = np.int32((date/10000)-(self.is1[2]*100))
 812            self.is1[4] = np.int32((date/100)-(self.is1[2]*10000)-(self.is1[3]*100))
 813            self.is1[5] = np.int32(date-((date/100)*100))
 814            self.is1[6] = np.int32(0)
 815            self.is1[7] = np.int32(date)
 816            self.is1[8] = np.int32(id[0])
 817            self.is1[9] = np.int32(id[1])
 818            self.is1[10] = np.int32(id[2])
 819            self.is1[11] = np.int32(id[3])
 820            if lead is None:
 821                self.is1[12] = np.int32(self.is1[10]-((self.is1[10]/1000)*1000))
 822            else:
 823                self.is1[12] = np.int32(lead)
 824            self.is1[13] = np.int32(0)
 825            self.is1[14] = np.int32(self.is1[8]-((self.is1[8]/100)*100))
 826            self.is1[15] = np.int32(0)
 827            self.is1[16] = np.int32(0)
 828            self.is1[17] = np.int32(0)
 829            self.is1[18] = np.int32(0)
 830            self.is1[19] = np.int32(0)
 831            self.is1[20] = np.int32(0)
 832            self.is1[21] = NCHAR_PLAIN
 833            if plain is None:
 834                self.plain = ' '*NCHAR_PLAIN
 835            else:
 836                self.plain = plain
 837                for n,p in enumerate(plain):
 838                    self.is1[22+n] = np.int32(ord(p))
 839
 840            if grid is not None and type(grid) is dict or data.shape == 2:
 841                # Gridded Data
 842                self.type = 'grid'
 843                self.is1[1] = np.int32(1) # Set IS1[1] = 1
 844                self.is2[1] = np.int32(grid['proj'])
 845                self.is2[2] = np.int32(grid['nx'])
 846                self.is2[3] = np.int32(grid['ny'])
 847                self.is2[4] = np.int32(grid['latll']*10000)
 848                self.is2[5] = np.int32(grid['lonll']*10000)
 849                self.is2[6] = np.int32(grid['orientlon']*10000)
 850                self.is2[7] = np.int32(grid['meshlength']*1000) # Value in dict is in units of meters.
 851                self.is2[8] = np.int32(grid['stdlat']*10000)
 852                self.nx = np.int32(grid['nx'])
 853                self.ny = np.int32(grid['ny'])
 854            if len(data) > 0:
 855                self.data = np.array(data,dtype=np.float32)
 856                self.number_of_values = len(data)
 857                self._data_unpacked = True
 858            else:
 859                raise ValueError
 860
 861            if missing_value is None:
 862                self.primary_missing_value = np.int32(0)
 863                self.secondary_missing_value = np.int32(0)
 864            else:
 865                if type(missing_value) is list:
 866                    if len(missing_value) == 1:
 867                        self.primary_missing_value = np.int32(missing_value[0])
 868                    elif len(missing_value) == 2:
 869                        self.primary_missing_value = np.int32(missing_value[0])
 870                        self.secondary_missing_value = np.int32(missing_value[1])
 871                else:
 872                    self.primary_missing_value = np.int32(missing_value)
 873                    self.secondary_missing_value = np.int32(0)
 874
 875        else:
 876            # Instantiate via **kwargs
 877            for k,v in kwargs.items():
 878                setattr(self,k,v)
 879
 880    def __getitem__(self,indices):
 881        """
 882        """
 883        if self.type == 'grid':
 884            if not isinstance(indices,tuple):
 885                indices = tuple(indices)
 886        elif self.type == 'station':
 887            if isinstance(indices,str):
 888                indices = tuple([_starecdict[self._filelun][self._starecindex].index(indices)])
 889
 890        try:
 891            return self.data[indices]
 892        except(AttributeError):
 893            return None
 894
 895    def __setitem__(self,indices,values):
 896        """
 897        """
 898        if self.type == 'grid':
 899            if not isinstance(indices,tuple):
 900                indices = tuple(indices)
 901        elif self.type == 'station':
 902            if isinstance(indices,str):
 903                indices = tuple([_starecdict[self._filelun][self._starecindex].index(indices)])
 904
 905        self.data[indices] = values
 906
 907    def __repr__(self):
 908        strings = []
 909        keys = self.__dict__.keys()
 910        for k in keys:
 911            if not k.startswith('_'):
 912                strings.append('%s = %s\n'%(k,self.__dict__[k]))
 913        return ''.join(strings)
 914
 915    def pack(self,dec_scale=None,bin_scale=None):
 916        """
 917        Pack a TDLPACK record.
 918
 919        Parameters
 920        ----------
 921
 922        **`dec_scale : int, optional, default = 1`**
 923
 924        Decimal Scale Factor used to when packing TdlpackRecord data [DEFAULT is 1].
 925
 926        **`bin_scale : int, optional, default = 0`**
 927
 928        Binary Scale Factor used to when packing TdlpackRecord data [DEFAULT is 0]. NOTE:
 929        binary scale factor is currently NOT SUPPORTED in MOS-2000 software. It is added
 930        here for completeness.
 931        """
 932
 933        # Make sure data are unpacked
 934        if not self._data_unpacked:
 935            self.unpack(data=True)
 936
 937        _ier = np.int32(0)
 938        self.ipack = np.zeros((ND5),dtype=np.int32)
 939
 940        if dec_scale is not None:
 941            self.is1[16] = np.int32(dec_scale)
 942
 943        if bin_scale is not None:
 944            self.is1[17] = np.int32(bin_scale)
 945
 946        # Pack plain langauge into IS1 array.
 947        self.plain = self.plain.ljust(NCHAR_PLAIN)
 948        for n,p in enumerate(self.plain):
 949            self.is1[22+n] = np.int32(ord(p))
 950
 951        # Handle potential NaN values
 952        if self.primary_missing_value == 0:
 953            self.primary_missing_value == DEFAULT_MISSING_VALUE
 954        self.data = np.where(np.isnan(self.data),np.float32(self.primary_missing_value),
 955                             self.data)
 956
 957        if self.type == 'grid':
 958            _a = np.zeros((self.is2[2],self.is2[3]),dtype=np.float32,order='F')
 959            _ia = np.zeros((self.is2[2],self.is2[3]),dtype=np.int32,order='F')
 960            _ic = np.zeros((self.is2[2]*self.is2[3]),dtype=np.int32)
 961
 962            self.ioctet,_ier = tdlpack.pack2d(FORTRAN_STDOUT_LUN,self.data,_ia,_ic,self.is0,
 963                               self.is1,self.is2,self.is4,self.primary_missing_value,
 964                               self.secondary_missing_value,self.ipack,MINPK,_lx,L3264B)
 965        elif self.type == 'station':
 966            _ic = np.zeros((self.number_of_values),dtype=np.int32)
 967            self.ioctet,_ier = tdlpack.pack1d(FORTRAN_STDOUT_LUN,self.data,_ic,self.is0,
 968                               self.is1,self.is2,self.is4,self.primary_missing_value,
 969                               self.secondary_missing_value,self.ipack,MINPK,
 970                               _lx,L3264B)
 971
 972    def unpack(self,data=False,missing_value=None):
 973        """
 974        Unpacks the TDLPACK identification sections and data (optional).
 975
 976        Parameters
 977        ----------
 978
 979        **`data : bool, optional`**
 980
 981        If True, unpack data values. The default is False.
 982
 983        **`missing_value : float, optional`**
 984
 985        Set a missing value. If a missing value exists for the TDLPACK data record,
 986        it will be replaced with this value.
 987        """
 988        _ier = np.int32(0)
 989        if not self._metadata_unpacked:
 990            if self.ipack.shape[0] < ND5_META_MAX:
 991                _nd5_local = self.ipack.shape[0]
 992            else:
 993                _nd5_local = ND5_META_MAX
 994            _data_meta = np.zeros((_nd5_local),dtype=np.int32)
 995            _iwork_meta = np.zeros((_nd5_local),dtype=np.int32)
 996            _data_meta,_ier = tdlpack.unpack(FORTRAN_STDOUT_LUN,self.ipack[0:_nd5_local],
 997                              _iwork_meta,_is0,_is1,_is2,_is4,_misspx,
 998                              _misssx,np.int32(1),L3264B)
 999            if _ier == 0:
1000                self._metadata_unpacked = True
1001                self.is0 = deepcopy(_is0)
1002                self.is1 = deepcopy(_is1)
1003                self.is2 = deepcopy(_is2)
1004                self.is4 = deepcopy(_is4)
1005                self.id = self.is1[8:12]
1006
1007        # Set attributes from is1[].
1008        self.lead_time = np.int32(str(self.is1[10])[-3:])
1009        if not self.plain:
1010            if self.is1[21] > 0:
1011                for n in np.nditer(self.is1[22:(22+self.is1[21])]):
1012                    self.plain += chr(n)
1013            else:
1014                self.plain = ' '*NCHAR_PLAIN
1015
1016        # Set attributes from is2[].
1017        if self.is1[1] == 0:
1018            self.type = 'station'
1019            self.map_proj = None
1020            self.nx = None
1021            self.ny = None
1022            self.lower_left_latitude = None
1023            self.lower_left_longitude = None
1024            self.origin_longitude = None
1025            self.grid_length = None
1026            self.standard_latitude = None
1027            if np.sum(self.is2) > 0: self.is2 = np.zeros((ND7),dtype=np.int32)
1028        elif self.is1[1] == 1:
1029            self.type = 'grid'
1030            self.map_proj = self.is2[1]
1031            self.nx = self.is2[2]
1032            self.ny = self.is2[3]
1033            self.lower_left_latitude = self.is2[4]/10000.
1034            self.lower_left_longitude = self.is2[5]/10000.
1035            self.origin_longitude = self.is2[6]/10000.
1036            self.grid_length = self.is2[7]/1000.
1037            self.standard_latitude = self.is2[8]/10000.
1038            self.grid_def = create_grid_definition(proj=self.map_proj,nx=self.nx,ny=self.ny,
1039                            latll=self.lower_left_latitude,lonll=self.lower_left_longitude,
1040                            orientlon=self.origin_longitude,stdlat=self.standard_latitude,
1041                            meshlength=self.grid_length)
1042            self.proj_string = _create_proj_string(self.grid_def)
1043
1044        # Set attributes from is4[].
1045        self.number_of_values = self.is4[2]
1046        self.primary_missing_value = deepcopy(np.float32(self.is4[3]))
1047        self.secondary_missing_value = deepcopy(np.float32(self.is4[4]))
1048
1049        if data:
1050            self._data_unpacked = True
1051            _nd5_local = max(self.is4[2],int(self.ioctet/NBYPWD))
1052            _iwork = np.zeros((_nd5_local),dtype=np.int32)
1053            _data = np.zeros((_nd5_local),dtype=np.float32)
1054            # Check to make sure the size of self.ipack is long enough. If not, then
1055            # we will "append" to self.ipack.
1056            if self.ipack.shape[0] < _nd5_local:
1057                pad = np.zeros((_nd5_local-self.ipack.shape[0]),dtype=np.int32)
1058                self.ipack = np.append(self.ipack,pad)
1059            _data,_ier = tdlpack.unpack(FORTRAN_STDOUT_LUN,self.ipack[0:_nd5_local],
1060                                         _iwork,self.is0,self.is1,self.is2,self.is4,
1061                                         _misspx,_misssx,np.int32(2),L3264B)
1062            if _ier == 0:
1063                _data = deepcopy(_data[0:self.number_of_values+1])
1064            else:
1065                _data = np.zeros((self.number_of_values),dtype=np.float32)+DEFAULT_MISSING_VALUE
1066            self.data = deepcopy(_data[0:self.number_of_values])
1067            if missing_value is not None:
1068                self.data = np.where(self.data==self.primary_missing_value,np.float32(missing_value),self.data)
1069                self.primary_missing_value = np.float32(missing_value)
1070            if self.type == 'grid':
1071                self.data = np.reshape(self.data[0:self.number_of_values],(self.nx,self.ny),order='F')
1072
1073    def latlons(self):
1074        """
1075        Returns a tuple of latitudes and lontiude numpy.float32 arrays for the TDLPACK record.
1076        If the record is station, then return is None.
1077
1078        Returns
1079        -------
1080
1081        **`lats,lons : array_like`**
1082
1083        Numpy.float32 arrays of grid latitudes and longitudes.  If `self.grid = 'station'`, then None are returned.
1084        """
1085        lats = None
1086        lons = None
1087        if self.type == 'grid':
1088            _ier = np.int32(0)
1089            lats = np.zeros((self.nx,self.ny),dtype=np.float32,order='F')
1090            lons = np.zeros((self.nx,self.ny),dtype=np.float32,order='F')
1091            lats,lons,_ier = tdlpack.gridij_to_latlon(FORTRAN_STDOUT_LUN,self.nx,self.ny,
1092                             self.map_proj,self.grid_length,self.origin_longitude,
1093                             self.standard_latitude,self.lower_left_latitude,
1094                             self.lower_left_longitude)
1095        return (lats,lons)

Defines a TDLPACK data record object. Once data are unpacked (TdlpackRecord.unpack(data=True)), values are accessible using "fancy indexing".

For gridded records, use grid index values and/or ranges (e.g. rec[0,0]).

For station records, use the station ID string: (e.g. rec['KPHL']).

Attributes

data : array_like

Data values.

grid_length : float

Distance between grid points in units of meters.

id : array_like

ID of the TDLPACK data record. This is a NumPy 1D array of dtype=np.int32.

ioctet : int

Size of the packed TDLPACK data record in bytes.

ipack : array_like

Packed TDLPACK data record. This is a NumPy 1D array of dtype=np.int32.

is0 : array_like

TDLPACK Section 0 (Indicator Section).

is1 : array_like

TDLPACK Section 1 (Product Definition Section).

is2 : array_like

TDLPACK Section 2 (Grid Definition Section)

is4 : array_like

TDLPACK Section 4 (Data Section).

lead_time : int

Forecast lead time in units of hours.

lower_left_latitude : float

Latitude of lower left grid point

lower_left_longitude : float

Longitude of lower left grid point

number_of_values : int

Number of data values.

nx : int

Number of points in the x-direction (West-East).

ny : int

Number of points in the y-direction (West-East).

origin_longitude : float

Originating longitude of projected grid.

plain : str

Plain language description of TDLPACK record.

primary_missing_value : float

Primary missing value.

reference_date : int

Reference date from the TDLPACK data record in YYYYMMDDHH format.

secondary_missing_value : float

Secondary missing value.

standard_latitude : float

Latitude at which the grid length applies.

type : {'grid', 'station'}

Identifies the type of data. This implies that data are 1D for type = 'station' and data are 2D for type = 'grid'.

TdlpackRecord( date=None, id=None, lead=None, plain=None, grid=None, data=None, missing_value=None, **kwargs)
752    def __init__(self,date=None,id=None,lead=None,plain=None,grid=None,data=None,
753                 missing_value=None,**kwargs):
754        """
755        Constructor
756
757        Parameters
758        ----------
759
760        **`date : int, optional`**
761
762        Forecast initialization or observation date in YYYYMMDDHH format.
763
764        **`id : list or 1-D array, optional`**
765
766        List or 1-D array of length 4 containing the 4-word (integer) MOS-2000 ID of the data
767        to be put into TdlpackRecord
768
769        **`lead : int, optional`**
770
771        Lead time (i.e. forecast projection) in hours of the data.  NOTE: This can be omitted
772
773        **`plain : str, optional`**
774
775        Plain language descriptor.  This is limited to 32 characters, though here
776        the input can be longer (will be cut off when packing).
777
778        **`grid : dict , optional`**
779
780        A dictionary containing grid definition attributes.  See
781        Dictionary of grid specs (created from create_grid_def_dict)
782
783        **`data : array_like, optional`**
784
785        Data values.
786
787        **`missing_value : float or list of floats, optional`**
788
789        Provide either a primary missing value or primary and secondary as list.
790
791        **`**kwargs : dict, optional`**
792
793        Dictionary of class attributes (keys) and class attributes (values).
794        """
795        type(self).counter += 1
796        self._metadata_unpacked = False
797        self._data_unpacked = False
798        self.plain = ''
799        if len(kwargs) == 0:
800            # Means we are creating TdlpackRecord instance from the other function
801            # input, NOT the kwargs Dict.
802            self.id = id
803            self.reference_date = date
804            self.type = 'station'
805            self.is0 = np.zeros(ND7,dtype=np.int32)
806            self.is1 = np.zeros(ND7,dtype=np.int32)
807            self.is2 = np.zeros(ND7,dtype=np.int32)
808            self.is4 = np.zeros(ND7,dtype=np.int32)
809
810            self.is1[2] = np.int32(date/1000000)
811            self.is1[3] = np.int32((date/10000)-(self.is1[2]*100))
812            self.is1[4] = np.int32((date/100)-(self.is1[2]*10000)-(self.is1[3]*100))
813            self.is1[5] = np.int32(date-((date/100)*100))
814            self.is1[6] = np.int32(0)
815            self.is1[7] = np.int32(date)
816            self.is1[8] = np.int32(id[0])
817            self.is1[9] = np.int32(id[1])
818            self.is1[10] = np.int32(id[2])
819            self.is1[11] = np.int32(id[3])
820            if lead is None:
821                self.is1[12] = np.int32(self.is1[10]-((self.is1[10]/1000)*1000))
822            else:
823                self.is1[12] = np.int32(lead)
824            self.is1[13] = np.int32(0)
825            self.is1[14] = np.int32(self.is1[8]-((self.is1[8]/100)*100))
826            self.is1[15] = np.int32(0)
827            self.is1[16] = np.int32(0)
828            self.is1[17] = np.int32(0)
829            self.is1[18] = np.int32(0)
830            self.is1[19] = np.int32(0)
831            self.is1[20] = np.int32(0)
832            self.is1[21] = NCHAR_PLAIN
833            if plain is None:
834                self.plain = ' '*NCHAR_PLAIN
835            else:
836                self.plain = plain
837                for n,p in enumerate(plain):
838                    self.is1[22+n] = np.int32(ord(p))
839
840            if grid is not None and type(grid) is dict or data.shape == 2:
841                # Gridded Data
842                self.type = 'grid'
843                self.is1[1] = np.int32(1) # Set IS1[1] = 1
844                self.is2[1] = np.int32(grid['proj'])
845                self.is2[2] = np.int32(grid['nx'])
846                self.is2[3] = np.int32(grid['ny'])
847                self.is2[4] = np.int32(grid['latll']*10000)
848                self.is2[5] = np.int32(grid['lonll']*10000)
849                self.is2[6] = np.int32(grid['orientlon']*10000)
850                self.is2[7] = np.int32(grid['meshlength']*1000) # Value in dict is in units of meters.
851                self.is2[8] = np.int32(grid['stdlat']*10000)
852                self.nx = np.int32(grid['nx'])
853                self.ny = np.int32(grid['ny'])
854            if len(data) > 0:
855                self.data = np.array(data,dtype=np.float32)
856                self.number_of_values = len(data)
857                self._data_unpacked = True
858            else:
859                raise ValueError
860
861            if missing_value is None:
862                self.primary_missing_value = np.int32(0)
863                self.secondary_missing_value = np.int32(0)
864            else:
865                if type(missing_value) is list:
866                    if len(missing_value) == 1:
867                        self.primary_missing_value = np.int32(missing_value[0])
868                    elif len(missing_value) == 2:
869                        self.primary_missing_value = np.int32(missing_value[0])
870                        self.secondary_missing_value = np.int32(missing_value[1])
871                else:
872                    self.primary_missing_value = np.int32(missing_value)
873                    self.secondary_missing_value = np.int32(0)
874
875        else:
876            # Instantiate via **kwargs
877            for k,v in kwargs.items():
878                setattr(self,k,v)

Constructor

Parameters

date : int, optional

Forecast initialization or observation date in YYYYMMDDHH format.

id : list or 1-D array, optional

List or 1-D array of length 4 containing the 4-word (integer) MOS-2000 ID of the data to be put into TdlpackRecord

lead : int, optional

Lead time (i.e. forecast projection) in hours of the data. NOTE: This can be omitted

plain : str, optional

Plain language descriptor. This is limited to 32 characters, though here the input can be longer (will be cut off when packing).

grid : dict , optional

A dictionary containing grid definition attributes. See Dictionary of grid specs (created from create_grid_def_dict)

data : array_like, optional

Data values.

missing_value : float or list of floats, optional

Provide either a primary missing value or primary and secondary as list.

**kwargs : dict, optional

Dictionary of class attributes (keys) and class attributes (values).

counter = 0
plain
def pack(self, dec_scale=None, bin_scale=None):
915    def pack(self,dec_scale=None,bin_scale=None):
916        """
917        Pack a TDLPACK record.
918
919        Parameters
920        ----------
921
922        **`dec_scale : int, optional, default = 1`**
923
924        Decimal Scale Factor used to when packing TdlpackRecord data [DEFAULT is 1].
925
926        **`bin_scale : int, optional, default = 0`**
927
928        Binary Scale Factor used to when packing TdlpackRecord data [DEFAULT is 0]. NOTE:
929        binary scale factor is currently NOT SUPPORTED in MOS-2000 software. It is added
930        here for completeness.
931        """
932
933        # Make sure data are unpacked
934        if not self._data_unpacked:
935            self.unpack(data=True)
936
937        _ier = np.int32(0)
938        self.ipack = np.zeros((ND5),dtype=np.int32)
939
940        if dec_scale is not None:
941            self.is1[16] = np.int32(dec_scale)
942
943        if bin_scale is not None:
944            self.is1[17] = np.int32(bin_scale)
945
946        # Pack plain langauge into IS1 array.
947        self.plain = self.plain.ljust(NCHAR_PLAIN)
948        for n,p in enumerate(self.plain):
949            self.is1[22+n] = np.int32(ord(p))
950
951        # Handle potential NaN values
952        if self.primary_missing_value == 0:
953            self.primary_missing_value == DEFAULT_MISSING_VALUE
954        self.data = np.where(np.isnan(self.data),np.float32(self.primary_missing_value),
955                             self.data)
956
957        if self.type == 'grid':
958            _a = np.zeros((self.is2[2],self.is2[3]),dtype=np.float32,order='F')
959            _ia = np.zeros((self.is2[2],self.is2[3]),dtype=np.int32,order='F')
960            _ic = np.zeros((self.is2[2]*self.is2[3]),dtype=np.int32)
961
962            self.ioctet,_ier = tdlpack.pack2d(FORTRAN_STDOUT_LUN,self.data,_ia,_ic,self.is0,
963                               self.is1,self.is2,self.is4,self.primary_missing_value,
964                               self.secondary_missing_value,self.ipack,MINPK,_lx,L3264B)
965        elif self.type == 'station':
966            _ic = np.zeros((self.number_of_values),dtype=np.int32)
967            self.ioctet,_ier = tdlpack.pack1d(FORTRAN_STDOUT_LUN,self.data,_ic,self.is0,
968                               self.is1,self.is2,self.is4,self.primary_missing_value,
969                               self.secondary_missing_value,self.ipack,MINPK,
970                               _lx,L3264B)

Pack a TDLPACK record.

Parameters

dec_scale : int, optional, default = 1

Decimal Scale Factor used to when packing TdlpackRecord data [DEFAULT is 1].

bin_scale : int, optional, default = 0

Binary Scale Factor used to when packing TdlpackRecord data [DEFAULT is 0]. NOTE: binary scale factor is currently NOT SUPPORTED in MOS-2000 software. It is added here for completeness.

def unpack(self, data=False, missing_value=None):
 972    def unpack(self,data=False,missing_value=None):
 973        """
 974        Unpacks the TDLPACK identification sections and data (optional).
 975
 976        Parameters
 977        ----------
 978
 979        **`data : bool, optional`**
 980
 981        If True, unpack data values. The default is False.
 982
 983        **`missing_value : float, optional`**
 984
 985        Set a missing value. If a missing value exists for the TDLPACK data record,
 986        it will be replaced with this value.
 987        """
 988        _ier = np.int32(0)
 989        if not self._metadata_unpacked:
 990            if self.ipack.shape[0] < ND5_META_MAX:
 991                _nd5_local = self.ipack.shape[0]
 992            else:
 993                _nd5_local = ND5_META_MAX
 994            _data_meta = np.zeros((_nd5_local),dtype=np.int32)
 995            _iwork_meta = np.zeros((_nd5_local),dtype=np.int32)
 996            _data_meta,_ier = tdlpack.unpack(FORTRAN_STDOUT_LUN,self.ipack[0:_nd5_local],
 997                              _iwork_meta,_is0,_is1,_is2,_is4,_misspx,
 998                              _misssx,np.int32(1),L3264B)
 999            if _ier == 0:
1000                self._metadata_unpacked = True
1001                self.is0 = deepcopy(_is0)
1002                self.is1 = deepcopy(_is1)
1003                self.is2 = deepcopy(_is2)
1004                self.is4 = deepcopy(_is4)
1005                self.id = self.is1[8:12]
1006
1007        # Set attributes from is1[].
1008        self.lead_time = np.int32(str(self.is1[10])[-3:])
1009        if not self.plain:
1010            if self.is1[21] > 0:
1011                for n in np.nditer(self.is1[22:(22+self.is1[21])]):
1012                    self.plain += chr(n)
1013            else:
1014                self.plain = ' '*NCHAR_PLAIN
1015
1016        # Set attributes from is2[].
1017        if self.is1[1] == 0:
1018            self.type = 'station'
1019            self.map_proj = None
1020            self.nx = None
1021            self.ny = None
1022            self.lower_left_latitude = None
1023            self.lower_left_longitude = None
1024            self.origin_longitude = None
1025            self.grid_length = None
1026            self.standard_latitude = None
1027            if np.sum(self.is2) > 0: self.is2 = np.zeros((ND7),dtype=np.int32)
1028        elif self.is1[1] == 1:
1029            self.type = 'grid'
1030            self.map_proj = self.is2[1]
1031            self.nx = self.is2[2]
1032            self.ny = self.is2[3]
1033            self.lower_left_latitude = self.is2[4]/10000.
1034            self.lower_left_longitude = self.is2[5]/10000.
1035            self.origin_longitude = self.is2[6]/10000.
1036            self.grid_length = self.is2[7]/1000.
1037            self.standard_latitude = self.is2[8]/10000.
1038            self.grid_def = create_grid_definition(proj=self.map_proj,nx=self.nx,ny=self.ny,
1039                            latll=self.lower_left_latitude,lonll=self.lower_left_longitude,
1040                            orientlon=self.origin_longitude,stdlat=self.standard_latitude,
1041                            meshlength=self.grid_length)
1042            self.proj_string = _create_proj_string(self.grid_def)
1043
1044        # Set attributes from is4[].
1045        self.number_of_values = self.is4[2]
1046        self.primary_missing_value = deepcopy(np.float32(self.is4[3]))
1047        self.secondary_missing_value = deepcopy(np.float32(self.is4[4]))
1048
1049        if data:
1050            self._data_unpacked = True
1051            _nd5_local = max(self.is4[2],int(self.ioctet/NBYPWD))
1052            _iwork = np.zeros((_nd5_local),dtype=np.int32)
1053            _data = np.zeros((_nd5_local),dtype=np.float32)
1054            # Check to make sure the size of self.ipack is long enough. If not, then
1055            # we will "append" to self.ipack.
1056            if self.ipack.shape[0] < _nd5_local:
1057                pad = np.zeros((_nd5_local-self.ipack.shape[0]),dtype=np.int32)
1058                self.ipack = np.append(self.ipack,pad)
1059            _data,_ier = tdlpack.unpack(FORTRAN_STDOUT_LUN,self.ipack[0:_nd5_local],
1060                                         _iwork,self.is0,self.is1,self.is2,self.is4,
1061                                         _misspx,_misssx,np.int32(2),L3264B)
1062            if _ier == 0:
1063                _data = deepcopy(_data[0:self.number_of_values+1])
1064            else:
1065                _data = np.zeros((self.number_of_values),dtype=np.float32)+DEFAULT_MISSING_VALUE
1066            self.data = deepcopy(_data[0:self.number_of_values])
1067            if missing_value is not None:
1068                self.data = np.where(self.data==self.primary_missing_value,np.float32(missing_value),self.data)
1069                self.primary_missing_value = np.float32(missing_value)
1070            if self.type == 'grid':
1071                self.data = np.reshape(self.data[0:self.number_of_values],(self.nx,self.ny),order='F')

Unpacks the TDLPACK identification sections and data (optional).

Parameters

data : bool, optional

If True, unpack data values. The default is False.

missing_value : float, optional

Set a missing value. If a missing value exists for the TDLPACK data record, it will be replaced with this value.

def latlons(self):
1073    def latlons(self):
1074        """
1075        Returns a tuple of latitudes and lontiude numpy.float32 arrays for the TDLPACK record.
1076        If the record is station, then return is None.
1077
1078        Returns
1079        -------
1080
1081        **`lats,lons : array_like`**
1082
1083        Numpy.float32 arrays of grid latitudes and longitudes.  If `self.grid = 'station'`, then None are returned.
1084        """
1085        lats = None
1086        lons = None
1087        if self.type == 'grid':
1088            _ier = np.int32(0)
1089            lats = np.zeros((self.nx,self.ny),dtype=np.float32,order='F')
1090            lons = np.zeros((self.nx,self.ny),dtype=np.float32,order='F')
1091            lats,lons,_ier = tdlpack.gridij_to_latlon(FORTRAN_STDOUT_LUN,self.nx,self.ny,
1092                             self.map_proj,self.grid_length,self.origin_longitude,
1093                             self.standard_latitude,self.lower_left_latitude,
1094                             self.lower_left_longitude)
1095        return (lats,lons)

Returns a tuple of latitudes and lontiude numpy.float32 arrays for the TDLPACK record. If the record is station, then return is None.

Returns

lats,lons : array_like

Numpy.float32 arrays of grid latitudes and longitudes. If self.grid = 'station', then None are returned.

class TdlpackStationRecord:
1097class TdlpackStationRecord(object):
1098    """
1099    Defines a TDLPACK Station Call Letter Record.
1100
1101    Attributes
1102    ----------
1103
1104    **`station : list`**
1105
1106    A list of station call letters.
1107
1108    **`id : array_like`**
1109
1110    ID of station call letters. Note: This id is only used for random-access IO.
1111
1112    **`ioctet : int`**
1113
1114    Size of packed station call letter record in bytes.
1115
1116    **`ipack : array_like`**
1117
1118    Array containing the packed station call letter record.
1119
1120    **`number_of_stations: int`**
1121
1122    Size of station call letter record.
1123    """
1124    counter = 0
1125    def __init__(self,stations=None,**kwargs):
1126        """
1127        `pytdlpack.TdlpackStationRecord` Constructor
1128
1129        Parameters
1130        ----------
1131
1132        **`stations : str or list or tuple`**
1133
1134        String of a single station or a list or tuple of stations.
1135        """
1136        type(self).counter += 1
1137
1138        if stations is not None:
1139            if type(stations) is str:
1140                self.stations = [stations]
1141            elif type(stations) is list:
1142                self.stations = stations
1143            elif type(stations) is tuple:
1144                self.stations = list(stations)
1145            else:
1146                pass # TODO: raise error... TypeError
1147            self.number_of_stations = np.int32(len(stations))
1148            self.id = np.int32([400001000,0,0,0])
1149            self.ioctet = np.int32(0)
1150            self.ipack = np.array((),dtype=np.int32)
1151        else:
1152            for k,v in kwargs.items():
1153                setattr(self,k,v)
1154
1155        #self.number_of_stations = np.int32(len(stations))
1156        #self.id = np.int32([400001000,0,0,0])
1157        #self.ioctet = np.int32(0)
1158        #self.ipack = np.array((),dtype=np.int32)
1159
1160    def __repr__(self):
1161        strings = []
1162        keys = self.__dict__.keys()
1163        for k in keys:
1164            if not k.startswith('_'):
1165                strings.append('%s = %s\n'%(k,self.__dict__[k]))
1166        return ''.join(strings)
1167
1168    def pack(self):
1169        """
1170        Pack a Station Call Letter Record.
1171        """
1172        #pdb.set_trace()
1173        self.ioctet = np.int32(self.number_of_stations*NCHAR)
1174        self.ipack = np.ndarray(int(self.ioctet/(L3264B/NCHAR)),dtype=np.int32)
1175        for n,s in enumerate(self.stations):
1176            sta = s.ljust(int(NCHAR),' ')
1177            self.ipack[n*2] = np.copy(np.fromstring(sta[0:int(NCHAR/2)],dtype=np.int32).byteswap())
1178            self.ipack[(n*2)+1] = np.copy(np.fromstring(sta[int(NCHAR/2):int(NCHAR)],dtype=np.int32).byteswap())
1179
1180    def unpack(self):
1181        """
1182        Unpack a Station Call Letter Record.
1183        """
1184        _stations = []
1185        _unpack_string_fmt = '>'+str(NCHAR)+'s'
1186        nrange = range(0,int(self.ioctet/(NCHAR/2)),2)
1187        if _IS_PYTHON3:
1188            nrange = list(range(0,int(self.ioctet/(NCHAR/2)),2))
1189        for n in nrange:
1190            tmp = struct.unpack(_unpack_string_fmt,self.ipack[n:n+2].byteswap())[0]
1191            if _IS_PYTHON3:
1192                tmp = tmp.decode()
1193            _stations.append(tmp.strip(' '))
1194        self.stations = list(deepcopy(_stations))

Defines a TDLPACK Station Call Letter Record.

Attributes

station : list

A list of station call letters.

id : array_like

ID of station call letters. Note: This id is only used for random-access IO.

ioctet : int

Size of packed station call letter record in bytes.

ipack : array_like

Array containing the packed station call letter record.

number_of_stations: int

Size of station call letter record.

TdlpackStationRecord(stations=None, **kwargs)
1125    def __init__(self,stations=None,**kwargs):
1126        """
1127        `pytdlpack.TdlpackStationRecord` Constructor
1128
1129        Parameters
1130        ----------
1131
1132        **`stations : str or list or tuple`**
1133
1134        String of a single station or a list or tuple of stations.
1135        """
1136        type(self).counter += 1
1137
1138        if stations is not None:
1139            if type(stations) is str:
1140                self.stations = [stations]
1141            elif type(stations) is list:
1142                self.stations = stations
1143            elif type(stations) is tuple:
1144                self.stations = list(stations)
1145            else:
1146                pass # TODO: raise error... TypeError
1147            self.number_of_stations = np.int32(len(stations))
1148            self.id = np.int32([400001000,0,0,0])
1149            self.ioctet = np.int32(0)
1150            self.ipack = np.array((),dtype=np.int32)
1151        else:
1152            for k,v in kwargs.items():
1153                setattr(self,k,v)
1154
1155        #self.number_of_stations = np.int32(len(stations))
1156        #self.id = np.int32([400001000,0,0,0])
1157        #self.ioctet = np.int32(0)
1158        #self.ipack = np.array((),dtype=np.int32)

pytdlpack.TdlpackStationRecord Constructor

Parameters

stations : str or list or tuple

String of a single station or a list or tuple of stations.

counter = 0
def pack(self):
1168    def pack(self):
1169        """
1170        Pack a Station Call Letter Record.
1171        """
1172        #pdb.set_trace()
1173        self.ioctet = np.int32(self.number_of_stations*NCHAR)
1174        self.ipack = np.ndarray(int(self.ioctet/(L3264B/NCHAR)),dtype=np.int32)
1175        for n,s in enumerate(self.stations):
1176            sta = s.ljust(int(NCHAR),' ')
1177            self.ipack[n*2] = np.copy(np.fromstring(sta[0:int(NCHAR/2)],dtype=np.int32).byteswap())
1178            self.ipack[(n*2)+1] = np.copy(np.fromstring(sta[int(NCHAR/2):int(NCHAR)],dtype=np.int32).byteswap())

Pack a Station Call Letter Record.

def unpack(self):
1180    def unpack(self):
1181        """
1182        Unpack a Station Call Letter Record.
1183        """
1184        _stations = []
1185        _unpack_string_fmt = '>'+str(NCHAR)+'s'
1186        nrange = range(0,int(self.ioctet/(NCHAR/2)),2)
1187        if _IS_PYTHON3:
1188            nrange = list(range(0,int(self.ioctet/(NCHAR/2)),2))
1189        for n in nrange:
1190            tmp = struct.unpack(_unpack_string_fmt,self.ipack[n:n+2].byteswap())[0]
1191            if _IS_PYTHON3:
1192                tmp = tmp.decode()
1193            _stations.append(tmp.strip(' '))
1194        self.stations = list(deepcopy(_stations))

Unpack a Station Call Letter Record.

class TdlpackTrailerRecord:
1196class TdlpackTrailerRecord(object):
1197    """
1198    Defines a TDLPACK Trailer Record.
1199    """
1200    counter = 0
1201    def __init__(self, **kwargs):
1202        """
1203        `pytdlpack.TdlpackTrailerRecord` Constructor
1204        """
1205        type(self).counter += 0
1206        for k, v in kwargs.items():
1207            setattr(self, k, v)
1208
1209    def __repr__(self):
1210        strings = []
1211        keys = self.__dict__.keys()
1212        for k in keys:
1213            if not k.startswith('_'):
1214                strings.append('%s = %s\n'%(k,self.__dict__[k]))
1215        return ''.join(strings)
1216
1217    def pack(self):
1218        pass
1219
1220    def unpack(self):
1221        pass

Defines a TDLPACK Trailer Record.

TdlpackTrailerRecord(**kwargs)
1201    def __init__(self, **kwargs):
1202        """
1203        `pytdlpack.TdlpackTrailerRecord` Constructor
1204        """
1205        type(self).counter += 0
1206        for k, v in kwargs.items():
1207            setattr(self, k, v)
counter = 0
def pack(self):
1217    def pack(self):
1218        pass
def unpack(self):
1220    def unpack(self):
1221        pass
def open(name, mode='r', format=None, ra_template=None):
1223def open(name, mode='r', format=None, ra_template=None):
1224    """
1225    Opens a TDLPACK File for reading/writing.
1226
1227    Parameters
1228    ----------
1229    **`name : str`**
1230
1231    TDLPACK file name.  This string is expanded into an absolute path via os.path.abspath().
1232
1233    **`mode : {'r', 'w', 'a', 'x'}, optional`**
1234
1235    Access mode. `'r'` means read only; `'w'` means write (existing file is overwritten);
1236    `'a'` means to append to the existing file; `'x'` means to write to a new file (if
1237    the file exists, an error is raised).
1238
1239    **`format : {'sequential', 'random-access'}, optional`**
1240
1241    Type of TDLPACK File when creating a new file.  This parameter is ignored if the
1242    file access mode is `'r'` or `'a'`.
1243
1244    **`ra_template : {'small', 'large'}, optional`**
1245
1246    Template used to create new random-access file. The default is 'small'.  This parameter
1247    is ignored if the file access mode is `'r'` or `'a'` or if the file format is `'sequential'`.
1248
1249    Returns
1250    -------
1251    **`pytdlpack.TdlpackFile`**
1252
1253    Instance of class TdlpackFile.
1254    """
1255    _byteorder = np.int32(0)
1256    _filetype = np.int32(0)
1257    _lun = np.int32(0)
1258    _ier = np.int32(0)
1259    name = os.path.abspath(name)
1260
1261    if format is None: format = 'sequential'
1262    if mode == 'w' or mode == 'x':
1263
1264        if format == 'random-access':
1265            if not ra_template: ra_template = 'small'
1266            if ra_template == 'small':
1267                _maxent = np.int32(300)
1268                _nbytes = np.int32(2000)
1269            elif ra_template == 'large':
1270                _maxent = np.int32(840)
1271                _nbytes = np.int32(20000)
1272            _filetype = np.int32(1)
1273            _lun,_byteorder,_filetype,_ier = tdlpack.openfile(FORTRAN_STDOUT_LUN,name,mode,L3264B,_byteorder,_filetype,
1274                                             ra_maxent=_maxent,ra_nbytes=_nbytes)
1275        elif format == 'sequential':
1276            _filetype = np.int32(2)
1277            _lun,_byteorder,_filetype,_ier = tdlpack.openfile(FORTRAN_STDOUT_LUN,name,mode,L3264B,_byteorder,_filetype)
1278
1279    elif mode == 'r' or mode == 'a':
1280        if os.path.isfile(name):
1281            _lun,_byteorder,_filetype,_ier = tdlpack.openfile(FORTRAN_STDOUT_LUN,name,mode,L3264B,_byteorder,_filetype)
1282        else:
1283            raise IOError("File not found.")
1284
1285    if _ier == 0:
1286        kwargs = {}
1287        if _byteorder == -1:
1288            kwargs['byte_order'] = '<'
1289        elif _byteorder == 1:
1290            kwargs['byte_order'] = '>'
1291        if _filetype == 1:
1292            kwargs['format'] = 'random-access'
1293            kwargs['ra_master_key'] = _read_ra_master_key(name)
1294        elif _filetype == 2:
1295            kwargs['format'] = 'sequential'
1296        kwargs['fortran_lun'] = deepcopy(_lun)
1297        kwargs['mode'] = mode
1298        kwargs['name'] = name
1299        kwargs['position'] = np.int32(0)
1300        if mode == 'r' or mode == 'a': kwargs['size'] = os.path.getsize(name)
1301    else:
1302        raise IOError("Could not open TDLPACK file"+name+". Error return from tdlpack.openfile = "+str(_ier))
1303
1304    _starecdict[_lun] = []
1305
1306    return TdlpackFile(**kwargs)

Opens a TDLPACK File for reading/writing.

Parameters

name : str

TDLPACK file name. This string is expanded into an absolute path via os.path.abspath().

mode : {'r', 'w', 'a', 'x'}, optional

Access mode. 'r' means read only; 'w' means write (existing file is overwritten); 'a' means to append to the existing file; 'x' means to write to a new file (if the file exists, an error is raised).

format : {'sequential', 'random-access'}, optional

Type of TDLPACK File when creating a new file. This parameter is ignored if the file access mode is 'r' or 'a'.

ra_template : {'small', 'large'}, optional

Template used to create new random-access file. The default is 'small'. This parameter is ignored if the file access mode is 'r' or 'a' or if the file format is 'sequential'.

Returns

pytdlpack.TdlpackFile

Instance of class TdlpackFile.

def create_grid_definition( name=None, proj=None, nx=None, ny=None, latll=None, lonll=None, orientlon=None, stdlat=None, meshlength=None):
1308def create_grid_definition(name=None,proj=None,nx=None,ny=None,latll=None,lonll=None,
1309                           orientlon=None,stdlat=None,meshlength=None):
1310    """
1311    Create a dictionary of grid specs.  The user has the option to
1312    populate the dictionary via the args or create an empty dict.
1313
1314    Parameters
1315    ----------
1316
1317    **`name : str, optional`**
1318
1319    String that identifies a predefined grid.
1320
1321    **`proj : int, optional`**
1322
1323    Map projection of the grid (3 = Lambert Conformal; 5 = Polar Stereographic;
1324    7 = Mercator). NOTE: This parameter is optional if data are station-based.
1325
1326    **`nx : int, optional`**
1327
1328    Number of points in X-direction (East-West). NOTE: This parameter is optional if
1329    data are station-based.
1330
1331    **`ny : int, optional`**
1332
1333    Number of points in Y-direction (North-South). NOTE: This parameter is optional if
1334    data are station-based.
1335
1336    **`latll : float, optional`**
1337
1338    Latitude in decimal degrees of lower-left grid point.  NOTE: This parameter is optional if
1339    data are station-based.
1340
1341    **`lonll : float, optional`**
1342
1343    Longitude in decimal degrees of lower-left grid point.  NOTE: This parameter is optional if
1344    data are station-based.
1345
1346    **`orientlon : float, optional`**
1347
1348    Longitude in decimal degrees of the central meridian.  NOTE: This parameter is optional if
1349    data are station-based.
1350
1351    **`stdlat : float, optional`**
1352
1353    Latitude in decimal degrees of the standard latitude.  NOTE: This parameter is optional if
1354    data are station-based.
1355
1356    **`meshlength : float, optional`**
1357
1358    Distance in meters between grid points.  NOTE: This parameter is optional if
1359    data are station-based.
1360
1361    Returns
1362    -------
1363
1364    **`griddict : dict`**
1365
1366    Dictionary whose keys are the named parameters of this function.
1367    """
1368    griddict = {}
1369    if name is not None:
1370        from ._grid_definitions import grids
1371        griddict = grids[name]
1372    else:
1373        griddict['proj'] = proj
1374        griddict['nx'] = nx
1375        griddict['ny'] = ny
1376        griddict['latll'] = latll
1377        griddict['lonll'] = lonll
1378        griddict['orientlon'] = orientlon
1379        griddict['stdlat'] = stdlat
1380        griddict['meshlength'] = meshlength
1381    return griddict

Create a dictionary of grid specs. The user has the option to populate the dictionary via the args or create an empty dict.

Parameters

name : str, optional

String that identifies a predefined grid.

proj : int, optional

Map projection of the grid (3 = Lambert Conformal; 5 = Polar Stereographic; 7 = Mercator). NOTE: This parameter is optional if data are station-based.

nx : int, optional

Number of points in X-direction (East-West). NOTE: This parameter is optional if data are station-based.

ny : int, optional

Number of points in Y-direction (North-South). NOTE: This parameter is optional if data are station-based.

latll : float, optional

Latitude in decimal degrees of lower-left grid point. NOTE: This parameter is optional if data are station-based.

lonll : float, optional

Longitude in decimal degrees of lower-left grid point. NOTE: This parameter is optional if data are station-based.

orientlon : float, optional

Longitude in decimal degrees of the central meridian. NOTE: This parameter is optional if data are station-based.

stdlat : float, optional

Latitude in decimal degrees of the standard latitude. NOTE: This parameter is optional if data are station-based.

meshlength : float, optional

Distance in meters between grid points. NOTE: This parameter is optional if data are station-based.

Returns

griddict : dict

Dictionary whose keys are the named parameters of this function.

grids = {'nbmak': {'proj4_alias': 'stere', 'proj': 5, 'nx': 1649, 'ny': 1105, 'latll': 40.5301, 'lonll': 178.5713, 'stdlat': 60.0, 'orientlon': 150.0, 'meshlength': 2976.560059}, 'nbmco': {'proj4_alias': 'lcc', 'proj': 3, 'nx': 2345, 'ny': 1597, 'latll': 19.229, 'lonll': 126.2766, 'stdlat': 25.0, 'orientlon': 95.0, 'meshlength': 2539.702881}, 'nbmhi': {'proj4_alias': 'merc', 'proj': 7, 'nx': 625, 'ny': 561, 'latll': 14.3515, 'lonll': 164.9695, 'stdlat': 20.0, 'orientlon': 160.0, 'meshlength': 2500.0}, 'nbmoc': {'proj4_alias': 'merc', 'proj': 7, 'nx': 2517, 'ny': 1817, 'latll': -30.4192, 'lonll': 230.0942, 'stdlat': 20.0, 'orientlon': 360.0, 'meshlength': 10000.0}, 'nbmpr': {'proj4_alias': 'merc', 'proj': 7, 'nx': 353, 'ny': 257, 'latll': 16.828, 'lonll': 68.1954, 'stdlat': 20.0, 'orientlon': 65.0, 'meshlength': 1250.0}, 'gfs23': {'proj4_alias': 'stere', 'proj': 5, 'nx': 593, 'ny': 337, 'latll': 2.832, 'lonll': 150.0003, 'stdlat': 60.0, 'orientlon': 105.0, 'meshlength': 23812.5}, 'gfs47': {'proj4_alias': 'stere', 'proj': 5, 'nx': 297, 'ny': 169, 'latll': 2.832, 'lonll': 150.0003, 'stdlat': 60.0, 'orientlon': 105.0, 'meshlength': 47625.0}, 'gfs95': {'proj4_alias': 'stere', 'proj': 5, 'nx': 149, 'ny': 85, 'latll': 2.832, 'lonll': 150.0003, 'stdlat': 60.0, 'orientlon': 105.0, 'meshlength': 95250.0}, 'nam151': {'proj4_alias': 'stere', 'proj': 5, 'nx': 425, 'ny': 281, 'latll': 0.7279, 'lonll': 150.3583, 'stdlat': 60.0, 'orientlon': 110.0, 'meshlength': 33812.0}, 'nam221': {'proj4_alias': 'lcc', 'proj': 3, 'nx': 349, 'ny': 198, 'latll': 9.5803, 'lonll': 150.7806, 'stdlat': 50.0, 'orientlon': 107.0, 'meshlength': 32463.410156}}