2. Resources¶
What are the different formats implemented in my configuration ? (some may be deactivated in config for simpler installation)
>>> import epygram
>>> epygram.init_env()
>>> epygram.config.implemented_formats
['netCDF', 'GRIB', 'GeoPoints', 'TIFFMF', 'FA', 'LFI', 'DDHLFA', 'LFA']
There is a proxy to open an existing resource without making an explicit reference to its format, e.g.:
>>> a_resource = epygram.formats.resource('ICMSHAROM+0042', 'r')
(where ‘r’ stands for ‘read’ opening mode and ‘ICMSHAROM+0042’ is the filename of the resource), that uses the underneath guessing function, that you may find useful (?)
>>> epygram.formats.guess('ICMSHAROM+0042')
'FA'
For opening a new resource in writing mode, specifying the format is though necessary:
>>> a_resource = epygram.formats.resource('ICMSHAROM+0042_new', 'w', fmt='FA')
All resources of different formats share a set of common methods, such as
listfields()
, readfield()
and writefield()
, that behave
similarly: readfield()
always return the same kind of objects:
Fields
.
2.1. Explore resources¶
Let’s open an historic FA file from AROME and explore it.
>>> r = epygram.formats.resource('ICMSHAROM+0042', 'r')
>>> r.format
'FA'
>>> type(r)
<class 'epygram.formats.FA.FA'>
>>> r.isopen
True
>>> r.openmode
'r'
But I may want later to add a field in this resource ? Let’s reopen it with ‘append’ mode.
>>> r.close()
>>> r.isopen
False
>>> r.open(openmode='a')
>>> r.openmode
'a'
Where is my resource stored ?
>>> r.container.absdir
'/home/mary/worktmp/'
>>> r.container.basename
'ICMSHAROM+0042'
>>> print r.container.abspath
'/home/mary/worktmp/ICMSHAROM+0042'
Now let’s explore what’s inside this FA file.
>>> r.empty
False
# there are fields in there
>>> r.listfields()
['SURFTENS.TURB.ZO', 'SURFTENS.TURB.ME',
...
'S090WIND.V.PHYS']
>>> len(r.listfields())
1237
2.1.1. Some FA additional properties¶
The case of FA is a bit specific in that the temporal and geometric metadata is common to the whole resource and shared by all fields. Therefore, the resource “has a geometry”:
>>> print r.geometry
D3ProjectedGeometry containing:
_center_lon: Angle containing:
_degrees: 2.0
_radians: 0.0349065850399
_origin_value: 0.0349065850399
_origin_unit: radians
projection:
reference_lat: Angle containing:
_cos_sin: (0.6858183529273761, 0.7277727576572106)
_degrees: 46.7
_radians: 0.815068760681
_origin_value: 0.815068760681
_origin_unit: radians
reference_lon: Angle containing:
...
and optionally a spectral geometry as well:
>>> print r.spectral_geometry
SpectralGeometry containing:
truncation:
in_X: 719
in_Y: 767
shape: elliptic
space: bi-fourier
and also a validity (embedded in a list of 1 element, because time can be a dimension of fields):
>>> print r.validity[0]
FieldValidity containing:
_basis: 2014-12-01 00:00:00
_date_time: 2014-12-02 18:00:00
_statistical_process_on_duration: None
_cumulativeduration: 3:00:00
Here, we can see the validity is 2014-12-02 18:00:00, starting from basis 2014-12-01 00:00:00, which mean the term of the resource is 18h.
Also, has been included a function to look for fields with a generic seed, e.g.:
>>> r.find_fields_in_resource('*RAY*')
['SOMMFLU.RAY.SOLA', 'SURFFLU.RAY.SOLA', 'SOMMFLU.RAY.THER', 'SURFFLU.RAY.THER',
'S001RAYT SOL CL', 'S090RAYT SOL CL', 'S001RAYT THER CL', 'S090RAYT THER CL',
'SURFRAYT DIR SUR', 'TOPRAYT DIR SOM', 'SURFRAYT SOLA DE', 'SURFRAYT THER DE',
'SOMMRAYT.SOLAIRE', 'SURFRAYT.SOLAIRE', 'SOMMRAYT.TERREST', 'SURFRAYT.TERREST']
>>> r.find_fields_in_resource('S06[1-3]WIND.?.PHYS')
['S061WIND.U.PHYS', 'S061WIND.V.PHYS', 'S062WIND.U.PHYS', 'S062WIND.V.PHYS',
'S063WIND.U.PHYS', 'S063WIND.V.PHYS']
>>> r.find_fields_in_resource(['S090TEMP*', 'SURF*'])
...
The encoding of fields is also available:
on request:
>>> r.fieldencoding('SURFTEMPERATURE') {'spectral': False, 'KSTRON': 0, 'KPUILA': 0, 'KNGRIB': 2, 'KNBITS': 16} >>> r.fieldencoding('SPECSURFGEOPOTEN') {'spectral': True, 'KSTRON': 0, 'KPUILA': 0, 'KNGRIB': 0, 'KNBITS': 0}
and stored by time of reading:
>>> r.readfield('S001TEMPERATURE') >>> r.fieldscompression {'S001TEMPERATURE': {'KNBPDG': 18, 'KSTRON': 106, 'KPUILA': 1, 'KNGRIB': 2, 'KNBCSP': 18}, ... }
2.2. Field identifier (fid)¶
FA fields are identified by a character string name. Other formats may identify fields differently, for instance GRIB with a set of key:value pairs.
As an example for GRIB, the epygram.formats.GRIB.GRIB.listfields
method
returns a list of dicts:
>>> g = epygram.formats.resource('GRIDHSTFRANGP0025+0003', 'r')
>>> g.format
'GRIB'
>>> g.listfields()
[{'typeOfLevel': 'surface', 'indicatorOfTypeOfLevel': 1, 'name': 'Temperature',
'level': 0, 'table2Version': 1, 'editionNumber': 1, 'shortName': 't',
'paramId': 130, 'indicatorOfParameter': 11},
...
]
Field identifiers as an attribute of epygram.fields — Fields objects will be detailed in section Field identifier of the tutorial.
2.3. Juggling with resources¶
Transferring a field from one resource to another is almost as simple as telling it:
>>> source_r = epygram.formats.resource('ICMSHAROM+0042', 'r')
>>> dest_r = epygram.formats.resource('ICMSHAROM+0042_bis', 'a')
>>> f = source_r.readfield('SURFTEMPERATURE')
>>> type(f)
<class 'epygram.fields.H2DField.H2DField'>
>>> dest_r.writefield(f)
# [2016/05/04-15:20:53][epygram.formats.FA][writefield:0980][INFO]: there
already is a field with the same name in this FA: overwrite.
2.4. Resource modifiers¶
Sometimes, fields in a resource does not take the appropriate form. For example, 3D plots require 3D fields; animations require fields with time evolution; complex treatments can require to work on a subdomain; and some applications can need variables that are not in the resource but can be computed from it. To deal with this problems, one can implement the transforms or use one of the resource modifiers provided by epygram:
CombineLevelsResource takes one resource and tries to expose 3D fields built from the H2D fields actually present in the resource
MultiValiditiesResource takes several resources. Each resource must contain the same fields but for different validities; the new resource join the different fields to return a field with a time dimension
SubdomainResource takes one resource and return the fields on a sub-domain defined by a geometry or by indexes bounds
DiagnosticsResource takes one resource and tries to compute new fields from the fields contained in the resource. For example, one can request the temperature field and the resource returns it if it is already in the resource or computes it from potential temperature.
All this modifiers should work in a pipeline if needed (one can compute diagnostics on a multivalidities resource for example).
Here are some examples to build a resource modifier:
>>> from footprints import proxy as fpx
>>> r = epygram.formats.resource(filename, 'r')
>>> rDiag = fpx.resource_modificator(name='Diagnostics', resource=r, openmode='r', ...)
>>> r3d = fpx.resource_modificator(name='CombineLevels', resource=r)
>>> r_time = fpx.resource_modificator(name='MultiValidities', resources=[r1, r2, ...])
>>> r_subdo = fpx.resource_modificator(name='Subdomain', resource=r, geometry=geom)