### Install via Pip Source: https://pseudonetcdf.readthedocs.io/en/latest/installing.html Use pip to install PseudoNetCDF directly from the GitHub repository. ```bash pip install http://github.com/barronh/pseudonetcdf.git ``` -------------------------------- ### Initialize arltrajdump Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/noaafiles/_tdump.html Example usage for initializing the arltrajdump parser. ```python if __name__ == '__main__': f = arltrajdump('tdump_008') ``` -------------------------------- ### Implement custom help action for file formats Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/pncparse.html This class handles the --help-format command-line argument by inspecting the reader's constructor and printing usage examples. ```python def __call__(self, parser, namespace, values, option_string=None): file_format = values[0].split(',')[0] print('') print('All formats require a "path". Some formats also ') print('take extra arguments. All arguments other than ') print('the input path must be specified using keyword') print('arguments.') print('') helpformat = allreaders[file_format] try: import inspect print('Example:') idef = inspect.getargspec(helpformat.__init__) args = idef.args[2:] if idef.defaults is None: defs = [''] * len(args) else: defs = (len(args) - len(idef.defaults)) * \ [''] + list(idef.defaults) longform = ( 'pncdump -f ' + ','.join([file_format] + [karg + "=%s" % kdef for karg, kdef in zip(args, defs)]) + ' path') shortform = ( 'pncdump -f ' + ','.join([file_format] + [karg + "=%s" % kdef for karg, kdef in zip(args, defs) if kdef == '']) + ' path') print(shortform) if longform != shortform: print('') print('Extended example with keywords:') print(longform) print('') print('* Any keyword with a non "" default ' + 'can be omitted.') print('') except Exception: print('** Short help not available for ' + file_format) print('') if 'y' == input('Hit Y/y to see detailed help\n').lower(): help(helpformat) setattr(namespace, self.dest, values) setattr(namespace, 'help', True) ``` -------------------------------- ### Install via Conda Source: https://pseudonetcdf.readthedocs.io/en/latest/installing.html Use the conda package manager to install PseudoNetCDF. ```bash conda install pseudonetcdf ``` -------------------------------- ### PNC Function Usage Examples Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/pncparse.html Examples demonstrating how to use the PNC function for single file, multiple file, and action-based processing. ```python # Single File out = PNC('--format=netcdf', inpath) infile = out.ifiles[0] O3 = infile.variables['O3'] # Multiple Files out = PNC('--format=netcdf', inpath1, inpath2) infile1, infile2 = out.ifiles O3_1 = infile1.variables['O3'] O3_2 = infile2.variables['O3'] # With Actions out = PNC('dump', '--variables=O3', '--format=netcdf', inpath) ``` -------------------------------- ### Initialize WOUDC Sonde Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/woudcfiles/_woudc.html Example instantiation of a WOUDC sonde object from a CSV file. ```python if __name__ == "__main__": f = woudcsonde('20150813.ECC.1Z.1Z27925.JMA.csv') ``` -------------------------------- ### Initialize PseudoNetCDF Interface Source: https://pseudonetcdf.readthedocs.io/en/latest/modules.html Examples for initializing the PNC interface for single files, multiple files, or performing specific actions. ```python # Single File out = PNC(‘–format=netcdf’, inpath) infile = out.ifiles[0] O3 = infile.variables[‘O3’] ``` ```python # Multiple Files out = PNC(‘–format=netcdf’, inpath1, inpath2) infile1, infile2 = out.ifiles O3_1 = infile1.variables[‘O3’] O3_2 = infile2.variables[‘O3’] ``` ```python # With Actions out = PNC(‘dump’, ‘–variables=O3’, ‘–format=netcdf’, inpath) ``` -------------------------------- ### Execute PseudoNetCDF Actions Source: https://pseudonetcdf.readthedocs.io/en/latest/modules.html Example of using the PNC command-line interface to dump specific variables from a file. ```python out = PNC(‘dump’, ‘–variables=O3’, ‘–format=netcdf’, inpath) ``` -------------------------------- ### Manage file destinations and variable options Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/core/_files.html Methods for getting and setting file destination paths and variable creation options. ```python def get_dest(self): """ Returns the path where a new file is created on some action If None, a file is created in memory. Else, a netcdf file is created on disk. """ return self.__dict__.get('_destination', None) def set_dest(self, path, **options): """ Sets the path where a new file is created on some action Arguments --------- path : path for new file options : options for new file creation Returns ------- None """ options['filename'] = path self.__dict__['_destination'] = options def get_varopt(self): """ Get options Arguments --------- None Returns ------- options : dictionary of optiosn """ return self.__dict__.get('_varopt', {}).copy() def set_varopt(self, **options): """ Set options to be used when creating any Variable Arguments --------- options : options for new Variable creation Returns ------- None """ self.__dict__['_varopt'] = options ``` -------------------------------- ### Manage Variable Options Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/core/_files.html Methods to get or set options used when creating new variables in a destination file. ```python def get_varopt(self): """ Get options Arguments --------- None Returns ------- options : dictionary of options """ return getattr(self, '_varopt', {}).copy() ``` ```python def set_varopt(self, **options): """ Set options to be used when creating any Variable Arguments --------- **options : options for createVariable optional keywords to be supplied when creating new variables in destination file Returns ------- None """ return object.__setattr__(self, '_varopt', options) ``` -------------------------------- ### Define Argument Parser Options Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/pncparse.html Example of adding custom arguments to a PseudoNetCDF parser using the padd function. ```python padd('--no-squeeze', dest='squeeze', default=True, action='store_false', help=('Squeeze automatically removes singleton dimensions; ' + 'disabling requires user to remove singleton dimensions ' + 'with --remove-singleton option')) padd("--figroot", help='Path for base of figure (suffixed by action)') ``` -------------------------------- ### Create a Test File Source: https://pseudonetcdf.readthedocs.io/en/latest/examples/oddsandends.html Generates a basic IOAPI-like file with a dummy variable and grid metadata for testing purposes. ```python import PseudoNetCDF as pnc # create a GRIDDESC with open('GRIDDESC', 'w') as gf: gf.write( "' '\n'LamCon_40N_97W'\n 2 33.000 45.000 -97.000 -97.000 40.000\n" + "' '\n'12US1'\n'LamCon_40N_97W' " + "-2556000.0 -1728000.0 12000.0 12000.0 459 299 1\n' '" ) # Create a Template gf = pnc.pncopen('GRIDDESC', format='griddesc') gf.SDATE = 2016001 gf.updatetflag(overwrite=True) delattr(gf, 'VAR-LIST') gf.updatemeta() gf.save('test.nc').close() ``` -------------------------------- ### arlpackedbit.__init__ Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/noaafiles/_arl.html Initializes the arlpackedbit reader and unpacks the contents of the specified ARL file. ```APIDOC ## __init__(path, shape=None, cache=False, earth_radius=6370000, synchlon=None, synchlat=None) ### Description Reads and parses an ARL packed bit file, creating a PseudoNetCDF object with the unpacked data. ### Parameters - **path** (string) - Required - Path to the ARL packed bit formatted file. - **shape** (tuple or None) - Optional - Override the derived shape of the file. - **cache** (bool) - Optional - Whether to enable caching. - **earth_radius** (scalar) - Optional - Radius of the earth used in converting projected coordinates to lat/lon. - **synchlon** (scalar) - Optional - Override for the SYNCHLON variable precision. - **synchlat** (scalar) - Optional - Override for the SYNCHLAT variable precision. ### Returns - **arlf** (arlpackedbit) - A PseudoNetCDF file object containing the unpacked data. ``` -------------------------------- ### slice_dim Source: https://pseudonetcdf.readthedocs.io/en/latest/modules.html Subsets variable dimensions based on start, stop, and stride parameters. ```APIDOC ## slice_dim(f, slicedef, fuzzydim=True) ### Description Subsets variables by slicing specific dimensions. ### Parameters - **f** (file) - The input file object. - **slicedef** (string) - Definition string in the format 'dim,start,stop,stride'. - **fuzzydim** (boolean) - Whether to use fuzzy dimension matching. ``` -------------------------------- ### Create File Instances Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/core/_files.html Class methods to initialize new file objects from existing variables or files. ```python @classmethod def from_ncvs(cls, *invars, **invarkw): """ Arguments --------- invars : list NetCDF-like variable must have standard_name, long_name or name invarkw : kwds NetCDF-like variables Returns ------- outf : PseudoNetcdf-like file """ outf = cls() for invar in invars: for dk, ds in zip(invar.dimensions, invar.shape): if dk in outf.dimensions: assert(ds == len(outf.dimensions[dk])) else: outf.createDimension(dk, ds) outf.copyVariable(invar) for inkey, invar in invarkw.items(): for dk, ds in zip(invar.dimensions, invar.shape): if dk in outf.dimensions: assert(ds == len(outf.dimensions[dk])) else: outf.createDimension(dk, ds) outf.copyVariable(invar, key=inkey) return outf ``` ```python @classmethod def from_ncf(cls, infile): """ Arguments --------- infile : PseudoNetCDF-like file Returns ------- outf : PseudoNetcdf-like file """ outf = cls() for pk in infile.ncattrs(): pv = getattr(infile, pk) setattr(outf, pk, pv) for dk, dv in infile.dimensions.items(): outf.copyDimension(dv, key=dk) for vk, vv in infile.variables.items(): outf.copyVariable(vv, key=vk) return outf ``` -------------------------------- ### Initialize IOAPI Metavariables and Variables Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/camxfiles/uamiv/Memmap.html Sets up IOAPI-compliant metadata and creates time-flag variables for CAMx files. ```python # Add IOAPI metavariables self.NLAYS = len(self.dimensions['LAY']) self.NROWS = len(self.dimensions['ROW']) self.NCOLS = len(self.dimensions['COL']) self.NVARS = len(self.dimensions['VAR']) self.NSTEPS = len(self.dimensions['TSTEP']) varlist = "".join([i.ljust(16) for i in self.__var_names__]) setattr(self, 'VAR-LIST', varlist) self.NAME = self.__emiss_hdr['name'][0, :, 0].copy().view('S10')[ 0].decode() self.NOTE = self.__emiss_hdr['note'][0, :, 0].copy().view('S60')[ 0].decode() self.ITZON = self.__emiss_hdr['itzon'][0] self.FTYPE = 1 self.VGTYP = 2 self.VGTOP = 10000. self.VGLVLS = linspace(0, 1, self.NLAYS + 1)[::-1] self.GDNAM = "CAMx " self.UPNAM = "CAMx " self.FILEDESC = "CAMx " # Create variables self.variables = PseudoNetCDFVariables( self.__variables, ['TFLAG', 'ETFLAG'] + self.__var_names__) tflag = ConvertCAMxTime(self.__memmap__['DATE']['BDATE'], self.__memmap__['DATE']['BTIME'], self.NVARS) etflag = ConvertCAMxTime(self.__memmap__['DATE']['EDATE'], self.__memmap__['DATE']['ETIME'], self.NVARS) tflagv = self.createVariable('TFLAG', 'i', ('TSTEP', 'VAR', 'DATE-TIME'), values=tflag, units='DATE-TIME', long_name='TFLAG'.ljust(16), var_desc='TFLAG'.ljust(80)) etflagv = self.createVariable('ETFLAG', 'i', ('TSTEP', 'VAR', 'DATE-TIME'), values=etflag, units='DATE-TIME', long_name='ETFLAG'.ljust(16), var_desc='Ending TFLAG'.ljust(80)) self.SDATE, self.STIME = self.variables['TFLAG'][0, 0, :] self.TSTEP = etflagv[0, 0, 1] - tflagv[0, 0, 1] if P_ALP is not None: self.P_ALP = P_ALP if P_BET is not None: self.P_BET = P_BET if P_GAM is not None: self.P_GAM = P_GAM if XCENT is not None: self.XCENT = XCENT if YCENT is not None: self.YCENT = YCENT if GDTYP is not None: self.GDTYP = GDTYP ``` -------------------------------- ### Iterate Time Records Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/noaafiles/_cdump.html Loops through the file to extract start and stop time records. ```python start = np.fromfile(infile, dtype=thdr, count=1) starts.append(start['f1'][0]) stop = np.fromfile(infile, dtype=thdr, count=1) stops.append(stop['f1'][0]) ``` -------------------------------- ### Initialize Parser with getparser2 Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/pncparse.html Creates a parent parser for PseudoNetCDF with optional action commands. ```python def getparser2(actions=False): rdesc = RawDescriptionHelpFormatter parent_parser = PNCArgumentParser(description="PseudoNetCDF", formatter_class=rdesc, add_help=False, prog='PNC') if actions: add_action_commands( parent_parser, withbasic=True, add_help=False) else: add_basic_options(parent_parser) return parent_parser ``` -------------------------------- ### Get Variables from PseudoNetCDF Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/core/_functions.html Extracts a subset of variables from a file object, optionally filtering by coordinate keys. ```python def getvarpnc(f, varkeys, coordkeys=None, copy=True): if coordkeys is None: coordkeys = f.getCoords() coordkeys = set(coordkeys) if varkeys is None: varkeys = list(f.variables.keys()) varkeys = [k for k in varkeys if k not in coordkeys] else: newvarkeys = list(set(varkeys).intersection(f.variables.keys())) newvarkeys = [varkey for varkey in varkeys if varkey in newvarkeys] oldvarkeys = list(set(varkeys)) oldvarkeys.sort() skipping = set(oldvarkeys).difference(newvarkeys) if len(skipping): warn('Skipping %s' % ', '.join(skipping)) varkeys = newvarkeys if hasattr(f, 'copy'): outf = f.copy(props=True, dimensions=False, variables=False, data=False) else: from PseudoNetCDF.sci_var import WrapPNC outf = WrapPNC(f).copy(props=True, dimensions=False, variables=False, data=False) ``` -------------------------------- ### Initialize and inspect uamiv file Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/camxfiles/uamiv/Memmap.html Demonstrates how to open a CAMx uamiv file and inspect its variables, dimensions, and data structure. ```python >>> uamiv_path = 'camx_uamiv.bin' >>> uamivfile = uamiv(uamiv_path) >>> uamivfile.variables.keys() ['TFLAG', 'O3', 'NO', 'NO2', ...] >>> tflag = uamivfile.variables['TFLAG'] >>> tflag.dimensions ('TSTEP', 'VAR', 'DATE-TIME') >>> tflag[0,0,:] array([2005185, 0]) >>> tflag[-1,0,:] array([2005185, 240000]) >>> v = uamivfile.variables['O3'] >>> v.dimensions ('TSTEP', 'LAY', 'ROW', 'COL') >>> v.shape (25, 28, 65, 83) >>> uamivfile.dimensions {'TSTEP': 25, 'LAY': 28, 'ROW': 65, 'COL': 83} ``` -------------------------------- ### Variable Attribute Management Methods Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/core/_variables.html Methods for getting, setting, and deleting NetCDF-style attributes on variable objects. ```python def __delattr__(self, k): if k in self._ncattrs: self._ncattrs = tuple([k_ for k_ in self._ncattrs if k_ != k]) object.__delattr__(self, k) def setncattr(self, k, v): return setattr(self, k, v) def getncattr(self, k): return getattr(self, k) def setncatts(self, attdict): for pk, pv in attdict.items(): setattr(self, pk, pv) def getncatts(self): outd = OrderedDict() for pk in self.ncattrs(): outd[pk] = getattr(self, pk) return outd [docs] def ncattrs(self): """ Returns ------- ncattrs : tuple of strings attributes that have been user defined """ return self._ncattrs ``` -------------------------------- ### Access Documentation Source: https://pseudonetcdf.readthedocs.io/en/latest/quick.html Use the built-in help function to inspect PseudoNetCDF objects. ```python help(pnc.pncopen) ``` -------------------------------- ### Initialize PseudoNetCDFFile from existing file Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/core/_files.html Class method to create a new PseudoNetCDFFile instance by copying attributes, dimensions, and variables from an existing file. ```python @classmethod def from_ncf(cls, infile): outf = PseudoNetCDFFile() for pk in infile.ncattrs(): pv = getattr(infile, pk) setattr(outf, pk, pv) for dk, dv in infile.dimensions.items(): outf.copyDimension(dv, key=dk) for vk, vv in infile.variables.items(): outf.copyVariable(vv, key=vk) return outf ``` -------------------------------- ### Object Initialization Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/core/_files.html Handles the creation and initialization of PseudoNetCDFFile instances. ```python def __new__(mcl, *args, **kwds): new = super(PseudoNetCDFFile, mcl).__new__(mcl) new.variables = OrderedDict() new.dimensions = PseudoNetCDFDimensions() new._ncattrs = () new._operator_exclude_vars = () return new def __init__(self, *args, **properties): mode = properties.pop('mode', 'w') self._mode = mode for k, v in properties.items(): setattr(self, k, v) ``` -------------------------------- ### Get Vertical Level Text Representations Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/noaafiles/_arl.html Converts a list of vertical level floats into formatted 6-character strings. ```python def getvgtxts(vglvls): vgtxts = [] for vglvl in vglvls: if vglvl == 0: dp = 0 else: dp = np.floor(np.log10(vglvl) + 1) tmpl = '%%6.%df' % np.minimum(5, (5 - dp)) vgtxt = (tmpl % vglvl)[-6:] if len(vgtxt) != 6: raise ValueError('Unable to format vglvl:' + str(vglvl)) vgtxts.append(vgtxt) return vgtxts ``` -------------------------------- ### Execute Test Suite Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/geoschemfiles/_bpchmaster.html Standard entry point for running the unit test suite. ```python def runTest(self): pass if __name__ == '__main__': unittest.main() ``` -------------------------------- ### Load trajectory data with pandas Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/noaafiles/_tdump.html Reads trajectory data from a file using pandas, requiring the pandas library to be installed. ```python try: import pandas as pd except Exception: raise ImportError('arltrajdump requires pandas; ' + 'install pandas (e.g., pip install pandas)') # , parse_dates = ['YEAR MONTH DAY HOUR MINUTE'.split()]) data = pd.read_csv(f, delimiter='\s+', names=(('trajid metgridid year month day hour ' + 'minute forecast_hour age latitude ' + 'longitude altitude').split() + diagnostics[1:])) ``` -------------------------------- ### Initialize and verify cdump file Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/noaafiles/_cdump.html Demonstrates how to check if a file is a valid cdump format and initialize the reader. ```python if __name__ == '__main__': print(arlconcdump.isMine('cdump24')) f = arlconcdump('cdump24') ``` -------------------------------- ### pncmfopen(*args, stackdim=None, **kwds) Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/_getreader.html Opens multiple files and stacks them along a specified dimension. ```APIDOC ## pncmfopen(*args, stackdim=None, **kwds) ### Description Opens a list of files using pncopen and stacks them into a single PseudoNetCDF object along the provided dimension. ### Parameters - **args** (tuple) - args[0] must be a list of file paths. - **stackdim** (str) - The dimension name upon which to stack the files. - **kwds** (dict) - Additional arguments passed to pncopen. ### Returns - **pfile** (PseudoNetCDF) - The stacked file object. ``` -------------------------------- ### Get and Set File Destination Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/core/_files.html Methods to retrieve or define the destination path for new file creation. If the destination is None, files are created in memory. ```python def get_dest(self): """ Returns ------- path : str path where a new file is created on some action Notes ----- If None, a file is created in memory. Else, a netcdf file is created on disk. """ return getattr(self, '_destination', None) ``` ```python def set_dest(self, path, **options): """ Sets the path where a new file is created on some action Arguments --------- path : str path for new file **options : keywords for constructor options for new file creation Returns ------- None """ options['filename'] = path return object.__setattr__(self, '_destination', options) ``` -------------------------------- ### Get File Path Source: https://pseudonetcdf.readthedocs.io/en/latest/readers/cmaq.html Retrieves the file system path or OPeNDAP URL used to open the dataset. Requires netCDF4 version 4.1.2 or higher. ```python filepath(self,encoding=None) ``` -------------------------------- ### Initialize CAMx UAMIV Grid and Data Mapping Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/camxfiles/uamiv/Memmap.html Extracts grid metadata, sets up memory-mapped file structures, and calculates time-step dimensions for UAMIV files. ```python self.XORIG = self.__grid_hdr['xorg'][0] self.YORIG = self.__grid_hdr['yorg'][0] self.XCELL = self.__grid_hdr['delx'][0] self.YCELL = self.__grid_hdr['dely'][0] self.PLON = plon = self.__grid_hdr['plon'][0] self.PLAT = plat = self.__grid_hdr['plat'][0] self.TLAT1 = tlat1 = self.__grid_hdr['tlat1'][0] self.TLAT2 = tlat2 = self.__grid_hdr['tlat2'][0] self.IUTM = iutm = self.__grid_hdr['iutm'][0] self.ISTAG = self.__grid_hdr['istag'][0] self.CPROJ = cproj = self.__grid_hdr['iproj'][0] if hasattr(self, 'GDTYP'): GDTYPE = self.GDTYP else: GDTYPE = self.GDTYP = {0: 1, 1: 5, 2: 2, 3: 6}[cproj] if ( cproj == 0 or not all([x == 0 for x in [plon, plat, tlat1, tlat2, iutm, cproj]]) ): # Map CAMx projection constants to IOAPI self.XCENT = plon self.YCENT = plat if GDTYPE in (1, 2): self.P_ALP = tlat1 self.P_BET = tlat2 self.P_GAM = plon elif GDTYPE == 5: self.P_ALP = iutm self.P_BET = 0. self.P_GAM = 0. elif GDTYPE == 6: self.P_ALP = {90: 1, -90: -1}[plat] self.P_BET = tlat1 self.P_GAM = plon else: raise ValueError('Unknown projection') nx = self.__grid_hdr['nx'][0] ny = self.__grid_hdr['ny'][0] nz = max(self.__grid_hdr['nz'], array([1]))[0] offset += self.__grid_hdr.dtype.itemsize * self.__grid_hdr.size self.__cell_hdr = memmap( self.__rffile, mode=self.__mode, dtype=self.__cell_hdr_fmt, shape=1, offset=offset) offset += self.__cell_hdr.dtype.itemsize * self.__cell_hdr.size + 4 self.__spc_hdr = memmap(self.__rffile, mode=self.__mode, dtype=self.__spc_fmt, shape=nspec, offset=offset) offset += self.__spc_hdr.dtype.itemsize * self.__spc_hdr.size + 4 date_time_fmt = dtype(dict( names=['SPAD', 'BDATE', 'BTIME', 'EDATE', 'ETIME', 'EPAD'], formats=['i', 'i', 'f', 'i', 'f', 'i'])).newbyteorder(ep) date_time_block_size = 6 spc_1_lay_fmt = dtype(dict( names=['SPAD', 'IONE', 'SPC', 'DATA', 'EPAD'], formats=['i', 'i', '(10,4)S1', '(%d,%d)f' % (ny, nx), 'i'])).newbyteorder(ep) spc_1_lay_block_size = 13 + nx * ny spc_3d_fmt = dtype((spc_1_lay_fmt, (nz,))) # Get species names from spc_hdr var_names = [spc[:, 0].copy().view('S10')[0] for spc in self.__spc_hdr] var_names = [v.decode() if hasattr(v, 'decode') else v for v in var_names] self.__var_names__ = [''.join(v).strip() for v in var_names] data_block_fmt = dtype(dict( names=['DATE'] + self.__var_names__, formats=[date_time_fmt] + [spc_3d_fmt] * nspec)) data_block_size = (date_time_block_size + nspec * nz * spc_1_lay_block_size) f = open(self.__rffile) f.seek(0, 2) size = f.tell() f.close() del f ntimes = float(size - offset) / 4. / data_block_size if int(ntimes) != ntimes: raise ValueError( ("Partial time output (%f times); partial time indicates " + "incomplete file.") % ntimes) ntimes = int(ntimes) self.createDimension('LAY', nz) self.createDimension('COL', nx) self.createDimension('ROW', ny) tstep = self.createDimension('TSTEP', ntimes) tstep.setunlimited(True) self.createDimension('VAR', nspec) self.__memmap__ = memmap(self.__rffile, mode=self.__mode, dtype=data_block_fmt, offset=offset) ``` -------------------------------- ### Define basic command-line options Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/pncparse.html Configures standard arguments for PseudoNetCDF command-line tools, including file formats, verbosity, and processing flags. ```python def add_basic_options(parser): padd = parser.add_argument parser.add_argument('ifiles', nargs='*', help='path to a file formatted as type -f') parser.add_argument("--verbose", dest="verbose", action="count", default=0, help="Provides verbosity with pncgen") try: padd("--help", dest="help", action=_HelpAction, default=False, help="Displays help") except Exception: pass padd('--pnc', action='append', default=[], help='Set of pseudonetcdf commands to be process separately') padd("-f", "--format", dest="format", default='netcdf', metavar='{see --list-formats for choices}', help=("File format (default netcdf), can be one of the choices " + "listed, or an expression that evaluates to a reader. " + "Keyword arguments are passed via ,kwd=value.")) padd("--list-formats", dest="help", default=None, action=_HelpListFormats, help="Show format options for -f") padd("--help-format", dest='helpformat', action=_HelpFormat, default=None, help="Show help for file format (must be one of the options for -f)") padd("--sep", dest="separator", action='store_true', default=False, help=("Used to separate groups of arguments for parsing (e.g., " + "pncgen -- [options1] file(s)1 [--sep [options2] file(s)2 " + "[... [--sep [optionsN] file(s)N]] ")) padd("--inherit", dest="inherit", action="store_true", default=False, help=("Allow subparsed sections (separated with -- and --sep) to " + "inherit from global options (-f, --format is always " + "inherited).")) padd("--diskless", dest="diskless", action="store_true", default=False, help="Load file into memory; useful for subsequent processing") padd("--mangle", dest="mangle", action="store_true", default=False, help="Remove non-standard ascii from names") padd("--rename", dest="rename", action="append", default=[], help=("Provide pairs of strings to be substituted " + "--rename=type,oldkey,newkey (type: v = variable; d = " + "dimension;)")) padd("--remove-singleton", dest="removesingleton", type=lambda x: [k for k in x.split(',') if k != ''], default=[], help="Remove singleton (length 1) dimensions") padd("--coordkeys", dest="coordkeys", type=str, action=AggCommaString, default=_coordkeys, metavar="key1,key2", help="Variables to be ignored in pncbo.") ``` -------------------------------- ### Configure Parser with getparser Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/pncparse.html Constructs a full PseudoNetCDF argument parser with options for output, plotting, mapping, and interactivity. ```python def getparser(has_ofile, plot_options=False, map_options=False, interactive=False, actions=False): """getparser produces a parser for PseudoNetCDF Parameters ---------- has_ofile : boolean Requires the outpath option and processes existence check plot_options : boolean, optional Adds options for plotting including matplotlibrc, spatial overlays, and normalization options, default is False interactive : boolean, optional Adds for interactive option, default is False Returns ------- parser : ArgumentParser with options that are processable with pncparse """ parser = PNCArgumentParser(description="""PseudoNetCDF Argument Parsing """, formatter_class=RawDescriptionHelpFormatter) parser.epilog = _pncepilog add_basic_options(parser) if interactive: add_interactive_options(parser) if actions: add_action_commands(parser, add_help=False) else: # Only has output file if pncgen is called. if has_ofile: add_output_options(parser) else: add_dump_options(parser) if plot_options: add_plot_options(parser) if map_options: add_map_options(parser) return parser ``` -------------------------------- ### Import PseudoNetCDF Source: https://pseudonetcdf.readthedocs.io/en/latest/quick.html Import the library using the standard alias. ```python import PseudoNetCDF as pnc ``` -------------------------------- ### Extracting Boundary Conditions with PseudoNetCDF Source: https://pseudonetcdf.readthedocs.io/en/latest/examples/cmaqbcon.html Creates a grid description file and extracts perimeter data from an existing IOAPI file to generate a boundary condition file. ```python import PseudoNetCDF as pnc # create a GRIDDESC with open('GRIDDESC', 'w') as gf: gf.write( "' '\n'LamCon_40N_97W'\n 2 33.000 45.000 -97.000 -97.000 40.000\n" + "' '\n'12US1'\n'LamCon_40N_97W' " + "-2556000.0 -1728000.0 12000.0 12000.0 459 299 1\n' '" ) # Create a Template gf = pnc.pncopen('GRIDDESC', format='griddesc', FTYPE=2) concf = pnc.pncopen('CONC.nc', format='ioapi') i, j = concf.ll2ij( gf.variables['longitude'][:], gf.variables['latitude'][:] ) bconf = concf.sliceDimensions(COL=i, ROW=j, newdims=('PERIM',)) bconf.FTYPE = 2 bconf.save('bcon.nc', format='NETCDF3_CLASSIC') ``` -------------------------------- ### Stack Files Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/core/_functions.html Initializes a file structure for stacking multiple files along a new dimension. ```python def stack_files(fs, stackdim, coordkeys=None): """ Create files with dimensions extended by stacking. Currently, there is no sanity check... """ f = PseudoNetCDFFile() tmpf = fs[0] if coordkeys is None: coordkeys = tmpf.getCoords() ``` -------------------------------- ### Prepare Files for Processing Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/pncparse.html Prepares file lists by applying operators and expressions before processing. ```python def pncprep(args): # nifiles = len(args.ifiles) - has_ofile ipaths = args.ifiles[:] fs = getfiles(ipaths, args) fs = subsetfiles(fs, args) fs = seqpncbo(args.operators, fs, coordkeys=args.coordkeys) for expr in args.expressions: fs = [pncexpr(expr, f) for f in fs] for script in args.expressionscripts: expr = open(script).read() fs = [pncexpr(expr, f) for f in fs] args.ifiles = fs if getattr(args, 'cdlname', None) is None: try: args.cdlname = args.ipath[0] except Exception: args.cdlname = 'unknown' return fs, args ``` -------------------------------- ### Create New File Instance Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/core/_files.html Internal method to instantiate a new file object of the same class or type. ```python def _newlike(self): """ Internal function to return a file of the same class if a PseudoNetCDFFile """ if self.get_dest() is not None: outf = netcdf(**self.get_dest()) elif isinstance(self, PseudoNetCDFFile): outt = type(self) outf = outt.__new__(outt) else: outf = PseudoNetCDFFile() outf.set_varopt(**self.get_varopt()) return outf ``` -------------------------------- ### IOAPI Default Metadata Configuration Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/cmaqfiles/_ioapi.html Initializes default IOAPI metadata attributes using an OrderedDict. ```python from PseudoNetCDF.pncwarn import warn from ..core._files import PseudoNetCDFFile, netcdf from collections import OrderedDict from PseudoNetCDF._getwriter import registerwriter import numpy as np import datetime today = datetime.datetime.today() # Assuming some fo the most common # options _i = _ioapi_defaults = OrderedDict() _i['IOAPI_VERSION'] = "N/A".ljust(80) _i['EXEC_ID'] = "????????????????".ljust(80) _i['FTYPE'] = 1 _i['CDATE'] = int(today.strftime('%Y%j')) _i['CTIME'] = int(today.strftime('%H%M%S')) _i['WDATE'] = int(today.strftime('%Y%j')) _i['WTIME'] = int(today.strftime('%H%M%S')) _i['NTHIK'] = 1 _i['GDTYP'] = 1 _i['P_ALP'] = 33. _i['P_BET'] = 45. _i['P_GAM'] = -97. _i['XCENT'] = -97. _i['YCENT'] = 40. _i['VGTYP'] = 2 _i['VGTOP'] = np.float32(5000) _i['GDNAM'] = "UNKNOWN " _i['UPNAM'] = "MAKEIOAPI " _i['FILEDESC'] = "".ljust(80) _i['HISTORY'] = "" ``` -------------------------------- ### Multi-file Dataset Opening Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/core/_files.html Opens multiple files and stacks them along a specified dimension. ```python @classmethod def open_mfdataset(cls, *paths, stackdim=None, **kwds): files = [cls(p, **kwds) for p in paths] file1 = files[0] if stackdim is None: for dk, dv in file1.dimensions.items(): if dv.isunlimited(): stackdim = dk else: for dk in list(file1.dimensions): if dk in ('TSTEP', 'time', 'Time', 't'): stackdim = dk else: raise ValueError( 'No dimension is unlimited or time; ' + 'must specify stackdim' ) return file1.stack(files[1:], stackdim=stackdim) ``` -------------------------------- ### Initialize Data Record Parsing Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/noaafiles/_cdump.html Sets up the data structures and formats required to iterate through time-series records in the CDUMP file. ```python thdr = np.dtype('>i,>6i,>i') nopackdfmt = '>({},{})f'.format(nlats, nlons) nopackfmt = np.dtype( dict( names=['B', 'POL', 'LAY', 'data', 'E'], formats=['>i', '>S4', '>i', nopackdfmt, '>i'] ) ) ``` -------------------------------- ### Initialize data block iteration Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/geoschemfiles/_bpch.html Prepares the file pointer and memory mapping to iterate through data blocks in the BPCH file. ```python if ( len(tracer_names) == 0 and not isinstance(tracer_names, defaultdictfromkey) ): raise IOError("Error parsing %s for Tracer data" % tracerinfo) file_size = os.stat(bpch_path).st_size offset = _general_header_type.itemsize data_types = [] first_header = None keys = [] self._groups = OrderedDefaultDict(set) while first_header is None or \ offset < file_size: header = memmap(bpch_path, offset=offset, shape=( 1,), dtype=_datablock_header_type, mode=mode)[0] ``` -------------------------------- ### HelpAction and HelpListFormats Actions Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/pncparse.html Custom argparse Actions for displaying help information and listing available file formats supported by the library. ```python class _HelpAction(Action): def __init__(self, option_strings, dest=SUPPRESS, default=SUPPRESS, help=None): super(_HelpAction, self).__init__( option_strings=option_strings, dest=dest, default=default, nargs=0, help=help) def __call__(self, parser, namespace, values, option_string=None): parser.print_help() setattr(namespace, self.dest, True) class _HelpListFormats(Action): def __init__(self, option_strings, dest=SUPPRESS, default=SUPPRESS, help=None): super(_HelpListFormats, self).__init__( option_strings=option_strings, dest=dest, default=default, nargs=0, help=help) def __call__(self, parser, namespace, values, option_string=None): print('The formats listed below are available ' + 'for the following options') print('-f FORMAT or --format FORMAT or --help-format FORMAT') print('where FORMAT is one of the options below') print('\t' + '\n\t'.join(_readernames)) print('**Some readers are listed twice (e.g., without dotted form)') setattr(namespace, 'help', True) ``` -------------------------------- ### pncopen(*args, **kwds) Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/_getreader.html Opens a file using a supported PseudoNetCDF format, with support for auto-detection and CF convention wrapping. ```APIDOC ## pncopen(*args, **kwds) ### Description Opens any PseudoNetCDF supported format. It handles format auto-detection, optional CF convention addition, and diskless file handling. ### Parameters - **args** (tuple) - Arguments for opening the file. - **kwds** (dict) - Keywords for the reader. - **format** (string) - Optional name of the reader; defaults to auto-detect. - **addcf** (boolean) - Whether to add CF conventions; default is False. - **diskless** (boolean) - Whether to use diskless mode; default is False. - **help** (boolean) - If True, returns help information for the reader. ### Returns - **pfile** (PseudoNetCDF) - The opened file object. ``` -------------------------------- ### Initialize ARL Grid and Coordinate Variables Source: https://pseudonetcdf.readthedocs.io/en/latest/_modules/PseudoNetCDF/noaafiles/_arl.html Configures grid dimensions and coordinate variables based on ARL header properties. Handles both projected and geographic coordinate systems. ```python if synchlat is None: self._synchlat = float(self.SYNCHLAT) else: self._synchlat = synchlat gridx = float(t0hdr['GRIDX']) * 1000. nx = props['NX'] ny = props['NY'] if gridx != 0: self.XSIZE = self.YSIZE = gridx self.createDimension('x', nx) self.createDimension('y', ny) x = self.createVariable('x', 'f', ('x',)) x[:] = np.arange(x[:].size) * gridx y = self.createVariable('y', 'f', ('y',)) y[:] = np.arange(y[:].size) * gridx self._addcrs() else: self.createDimension('x', nx) self.createDimension('y', ny) self.createDimension('nv', 2) x = self.createVariable('x', 'f', ('x',)) x.standard_name = 'longitude' x.units = 'degrees' xe = self.createVariable('x_bounds', 'f', ('x', 'nv')) xe.standard_name = 'longitude_bounds' xe.units = 'degrees' x[:] = np.arange(0, nx) * float(self.REFLON) + self._synchlon xe[:-1, 1] = x[:1] + np.diff(x) / 2 xe[1:, 0] = x[1:] - np.diff(x) / 2 xe[0, 0] = x[0] - np.diff(x)[0] / 2 xe[1, 1] = x[1] + np.diff(x)[1] / 2 y = self.createVariable('y', 'f', ('y',)) y.standard_name = 'latitude' y.units = 'degrees' ye = self.createVariable('y_bounds', 'f', ('y', 'nv')) ye.standard_name = 'latitude_bounds' ye.units = 'degrees' y[:] = np.arange(0, ny) * float(self.REFLAT) + self._synchlat ye[:-1, 1] = y[:1] + np.diff(y) / 2 ye[1:, 0] = y[1:] - np.diff(y) / 2 ye[0, 0] = y[0] - np.diff(y)[0] / 2 ye[1, 1] = y[1] + np.diff(y)[1] / 2 ```