"""
Conversions
-----------
Conversions are used to aggregate the ``NADCON5.0`` source and output data
.. autoclass:: nc5ng.nc5data.Conversion
:members:
"""
from .nadcon5_input import RegionData, ControlData, InData, ExclusionData
from .nadcon5_output import VectorData, PointData
from .nadcon5_types import MetaMixin, GMTMetaMixin
from .services import region_bounds
import logging
import itertools
[docs]class Conversion(MetaMixin, GMTMetaMixin):
""" A Conversion agregates all parts of a NADCON5 Datum Conversion and serves
as the primary user interface into the dataset
A Conversion is created based on region, source, target datum, and gridspacing
the same parameters that go into the data build pipeline
Conversions maintain a large set of data in memory (when loaded) and have accessors for data
Creating a conversion is simple
::
c = Conversion('conus', 'ussd', 'nad27')``
The output data of a conversion can be accessed directly by output prefix
::
v1 = c.output_data['vmacdlat']
v2 = c.output_data['vmacdlon']
Output data is indexed by PID, to extract all PID's with lat and lon conversions in this data set
::
shared_pids = [ i for i in v1 if i in v2 ]
All point data for a single point can be examined directly, including its source data
::
point = v[shared_pids[0]]
point.source
"""
[docs] class ConversionOutput(object):
"""
ConversionOutput holds all output data associated with a conversion
On construction attempts to load all known valid output files by iterating through known combinations of output types
:par region: The ``RegionData`` index to plot (e.g. ``'conus'``)
:par old_datum: The source datum for conversion (e.g. ``'ussd'``)
:par new_datum: The target datum for conversion (e.g. ``'nad27'``)
:par grid_spacing: The conversion grid spacing (e.g. ``900``)
"""
def __init__(self, region, old_datum, new_datum, grid_spacing, load_all = False, **kwargs):
self._output_data = {}
vdir = ['lat', 'lon', 'eht','hor']
vclass = ['a','t','d','r']
vout = ['cd','dd','gi']
vunit = ['m', 's']
surface = [True, False]
c_pars = itertools.product(vdir, vclass,vout)
v_pars = itertools.product(vdir, vclass, vout,vunit,surface)
local_kwargs = {}
if 'out_fdir' in kwargs:
local_kwargs['fdir'] = kwargs['out_fdir']
print ("Loading Coverage Files")
for c in c_pars:
print ("Trying to Load Coverage File args - %s"%str(c))
try:
cov = PointData(region,old_datum, new_datum, grid_spacing, *c, **local_kwargs)
print ("Finished Loading Coverage File - %s"%cov.shorthand)
except (ValueError, FileNotFoundError) as e:
print ("Could not find Coverage File")
print (e)
continue
self._output_data[cov.shorthand] = cov
print ("Loading Vector Files")
for v in v_pars:
print ("Trying to Load Vector File args - %s"%str(v))
try:
vec = VectorData(region, old_datum, new_datum, grid_spacing, *v, **local_kwargs)
print ("Finished Loading Vector File - %s"%vec.shorthand)
except (ValueError, FileNotFoundError) as e:
print ("Could not find Vector File")
print (e)
continue
self._output_data[vec.shorthand] = vec
def __contains__(self, item):
return ( item in self.raw_data ) or ( item in self.pid_set )
def __getitem__(self, key):
if key in self.raw_data:
return self.raw_data[key]
elif key in self.pid_set:
return { d_k:d_v[key] for d_k, d_v in self.raw_data.items() if key in d_v.indices }
else:
return None
@property
def raw_data(self):
return self._output_data
@property
def pid_set(self):
return self._pid_set
@property
def input_data(self):
return self._input_data
@property
def output_data(self):
return self._output_data
def __init__(self, region, old_datum, new_datum, grid_spacing = '900', **kwargs):
self._input_data = self.ConversionInput(region, old_datum, new_datum, **kwargs)
self._output_data = self.ConversionOutput(region, old_datum, new_datum, grid_spacing, **kwargs)
self._meta={'region':region,
'old_datum':old_datum,
'new_datum':new_datum,
'grid_spacing':grid_spacing,
**kwargs}
self._gmt_meta={
'region':region_bounds(region)
}
if 'gmt' in kwargs:
self._gmt_meta.update(kwargs['gmt'])