#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
V2DGeometry:
Contains the classe for Vertical 2D geometry of fields.
"""
import numpy
from footprints import FootprintBase, FPList
from epygram.util import RecursiveObject
[docs]class V2DGeometry(RecursiveObject, FootprintBase):
"""
Handles the geometry for a Vertical 2-Dimension Field (section).
For now, the grid of a V2DGeometry is defined as a collection of columns
of V1DGeometry.
"""
_collector = ('geometry',)
_footprint = dict(
attr=dict(
structure=dict(
values=set(['V2D'])),
grid=dict(
type=FPList,
info="Handles description of the grid, as a collection of\
V1DGeometry objects."),
position_on_grid=dict(
optional=True,
info="Position of points w/r to the vertical grid.",
values=set(['mass', 'flux']),
default='mass')
)
)
@property
[docs] def dimensions(self):
""" Returns the dimensions of the grid as a dict. """
return {'X':len(self.grid), 'Z':self.grid[0].grid['fieldlevels_number']}
@property
[docs] def ends(self):
"""
Returns the coordinates of the two ends of the section as a tuple of
tuples.
"""
return ((self.grid[0].hlocation['lon'],
self.grid[0].hlocation['lat']),
(self.grid[-1].hlocation['lon'],
self.grid[-1].hlocation['lat']))
@property
[docs] def coordinate(self):
"""
Returns the coordinate type of the section (actually, that of its first
profile, but all profiles should have the same coordinate).
"""
return self.grid[0].coordinate
[docs] def hybridP2pressure(self, Psurf, gridposition=None):
"""
Converts a hybrid_pressure coordinate grid into pressure.
*Psurf* is the transect of surface pressure, needed for integration of
Ai and Bi.
If *gridposition* is given ('mass' or 'flux'), the target grid is
computed accordingly. If not, the pressures are computed at the
hybrid-pressure gridposition (i.e. flux generally).
"""
for p in range(self.dimensions['X']):
self.grid[p].hybridP2pressure(Psurf[p], gridposition=gridposition)
[docs] def hybridP2altitude(self, R, T, Psurf, Pdep=None, Phi_surf=None):
"""
Converts a hybrid_pressure coordinate grid into altitude of mass levels.
- *R* is the section array of specific gas constant (J/kg/K).
- *T* is the section array of temperature (K).
- *Psurf* is the transect of surface pressure, needed for integration
of Ai and Bi.
- *Pdep* is the optional section array of NH pressure departures.
- *Phi_surf* is the optional transect of surface geopotential.
If given, the final coordinate is altitude above sea level,
else height above ground surface.
"""
if Pdep == None:
Pdep = numpy.zeros((self.dimensions['Y'], self.dimensions['X']))
if Phi_surf == None:
Phi_surf = numpy.zeros(self.dimensions['X'])
for p in range(self.dimensions['X']):
self.grid[p].hybridP2altitude(R[:, p], T[:, p], Psurf[p],
Pdep=Pdep[:, p], Phi_surf=Phi_surf[p])
[docs] def hybridH2altitude(self, Zsurf, gridposition=None, conv2height=False):
"""
Converts a hybrid_height coordinate grid into pressure.
*Zsurf* is the transect of surface altitude, needed for integration of
Ai and Bi.
If *gridposition* is given ('mass' or 'flux'), the target grid is
computed accordingly. If not, the altitudes are computed at the
hybrid-height gridposition (i.e. flux generally).
If conv2height is True, conversion into height is performed instead
of altitude.
"""
for p in range(self.dimensions['X']):
self.grid[p].hybridH2altitude(Zsurf[p],
gridposition=gridposition,
conv2height=conv2height)
[docs] def pressure2altitude(self, R, T, Pdep=None, Phi_surf=None):
"""
Converts a pressure coordinate grid (on mass or flux levels)
to altitude on mass levels).
- *R* is the section array of specific gas constant (J/kg/K).
- *T* is the section array of temperature (K).
- *Pdep* is the optional section array of NH pressure departures.
- *Phi_surf* is the optional transect of surface geopotential.
If given, the final coordinate is altitude above sea level,
else height above ground surface.
"""
if Pdep == None:
Pdep = numpy.zeros((self.dimensions['Y'], self.dimensions['X']))
if Phi_surf == None:
Phi_surf = numpy.zeros(self.dimensions['X'])
for p in range(self.dimensions['X']):
self.grid[p].pressure2altitude(R[:, p], T[:, p],
Pdep=Pdep[:, p],
Phi_surf=Phi_surf[p])
[docs] def distance(self, end1, end2):
"""
Computes the distance between two points of the grid.
*end1* must be a tuple (lon, lat).
*end2* must be a tuple (lon, lat).
This method must be implemented when this class is instantiated
(bound method from a horizontal geometry).
"""
raise NotImplementedError("this method must be implemented when class\
is instantiated.")
[docs] def azimuth(self, end1, end2):
"""
Initial bearing from *end1* to *end2* points in geometry.
*end1* must be a tuple (lon, lat).
*end2* must be a tuple (lon, lat).
This method must be implemented when this class is instantiated
(bound method from a horizontal geometry).
"""
raise NotImplementedError("this method must be implemented when class\
is instantiated.")