Source code for PseudoNetCDF.noaafiles._l100

__all__ = ['l100']
from datetime import datetime
from PseudoNetCDF import PseudoNetCDFFile
import numpy as np

_edges = [0, 4, 12, 20, 28, 35, 43, 50, 57, 64, 72, 79, 88, 95]
_starts = _edges[:-1]
_ends = _edges[1:]
_ses = [se for se in zip(_starts, _ends)]
_orignames = ('Level Press Alt Pottp Temp FtempV Hum Ozone Ozone ' +
              'Ozone Ptemp O3_DN O3_Res').split()
_names = ('Level Press Alt Pottp Temp FtempV Hum Ozone_mPa Ozone_ppmv ' +
          'Ozone_atmcm Ptemp O3_DN O3_Res').split()
_units = 'Num hPa km K C C % mPa ppmv atmcm C 10^11/cc DU'.split()


[docs]class l100(PseudoNetCDFFile):
[docs] @classmethod def isMine(cls, path): """ Must have correct names on line 28 """ try: lines = cls._getmeta(path) mynames = lines[-2].split() for chk, new in zip(_orignames[:8], mynames): if chk != new: return False else: return True except Exception: return False
@classmethod def _getmeta(cls, path): # get metadata lines infile = open(path) lines = [] for li in range(100): line = infile.readline() lines.append(line) if line.startswith('Level'): lines.append(infile.readline()) break else: lines = lines[:29] return lines def __init__(self, path): try: import pandas as pd except Exception: raise ImportError('l100 sonde files requires pandas; ' + 'install pandas (e.g., pip install pandas)') self._path = path metalines = l100._getmeta(path) datastartline = len(metalines) for line in metalines: if ':' in line: parts = line.split(':') key = parts[0].strip().replace(' ', '_') val = ':'.join(parts[1:]).strip() setattr(self, key, val) dataset = pd.read_fwf(path, colspecs=_ses, skiprows=datastartline, names=_names, na_values=['99.90', '99.99', '999', '99.999', '999.999', '99.9990', '9999']) self.createDimension('site', 1) self.createDimension('level', dataset.shape[0]) for key, unit in zip(_names, _units): vals = dataset[key] outvar = self.createVariable(key, vals.dtype, ('site', 'level')) outvar.long_name = key outvar.units = unit outvar[0, :] = vals ldate = datetime.strptime( self.Launch_Date + ' ' + self.Launch_Time, '%d %B %Y %H:%M:%S %Z') rdate = datetime(1970, 1, 1) seconds = (ldate - rdate).total_seconds() lonvar = self.createVariable('longitude', 'd', ('site',)) lonvar.long_name = 'longitude' lonvar.units = 'degrees' lonvar[:] = eval(self.Longitude) latvar = self.createVariable('latitude', 'd', ('site',)) latvar.long_name = 'latitude' latvar.units = 'degrees' latvar[:] = eval(self.Latitude) tvar = self.createVariable('time', 'd', ('site',)) tvar.units = 'seconds since 1970-01-01 00:00:00+0000' tvar[:] = seconds self.description = ''.join(metalines)
[docs] def avgSigma(self, vglvls=None, vgtop=None, hyai=None, hybi=None, inplace=False, copyall=True, levelname='LAY'): """ vglvls - sigma coordinate vgtop - top in Pa hyai - hybrid eta-component hPa hybi - hybrid sigma-component """ if inplace: outf = self else: outf = self.copy(props=True, dimensions=True, variables=copyall, data=copyall) myp = self.variables['Press'][:] # hPa myo = self.variables['Ozone_mPa'][:] * 1e1 # mPa -> cPa psfc = myp[0, 0] if vglvls is not None: outpress_edges = vglvls * (psfc - vgtop / 100) + vgtop / 100 nlvls = vglvls.size - 1 elif hyai is not None: outpress_edges = hyai + hybi * psfc nlvls = hyai.size - 1 outf.createDimension(levelname, nlvls) abovebottom = myp[0, :, None] <= outpress_edges[None, :-1] belowtop = myp[0, :, None] > outpress_edges[None, 1:] invglvl = abovebottom & belowtop out = np.ma.masked_all((1, nlvls), dtype='d') for li in range(nlvls): idx = invglvl[:, li] if not idx.any(): continue lps = myp[:, idx] lops = np.ma.masked_invalid(myo[:, idx]) lopsmask = np.ma.getmaskarray(lops) lp = np.ma.masked_where(lopsmask, lps).sum(-1) lop = lops.sum(-1) out[:, li] = lop / lp outv = outf.createVariable( 'O3', 'f', ('site', levelname), missing_value=-999) outv.units = 'ppm' outv.description = 'Pressure-weighted average vmr in ppm' outv[:] = np.ma.filled(out[:], outv.missing_value) return outf