Easily extended way to build classes for structured and unstructured geophysical data.
Project description
Geo-skeletons
Geo-skeletons is an easy extendable way to build python classes to represent gridded and non-gridded geophysical data. It provides the basic structure to work with spherical and cartesian coordinates, and can be extended to data-specific objects by adding coordinates, data variables and logical masks. It also integrates with the geo-parameters module to provide easy access to metadata.
Quick Installation
To get started with geo-skeletons, you can install it with pip or conda:
$ pip install geo-skeletons
or
$ conda install -c conda-forge geo-skeletons
Please see https://data-skeletons.readthedocs.io/en/latest/ for a documentation.
For example, to create a python class representing wind data as x, and y components, but connencted magnitude and direction wrappers for convinience:
from geo_skeletons import GriddedSkeleton
from geo_skeletons.decorators import add_datavar, add_time, add_magnitude
import geo_parameters as gp
import pandas as pd
@add_magnitude(gp.wind.Wind("wind"), x="u", y="v", direction=gp.wind.WindDir("wdir"))
@add_datavar(gp.wind.YWind("v"))
@add_datavar(gp.wind.XWind("u"))
@add_time()
class Wind(GriddedSkeleton):
pass
>> Wind.core
------------------------------ Coordinate groups -------------------------------
Spatial: (y, x)
Grid: (y, x)
Gridpoint: (time)
All: (time, y, x)
------------------------------------- Data -------------------------------------
Variables:
u (time, y, x): 0.1 [m/s] x_wind
v (time, y, x): 0.1 [m/s] y_wind
Masks:
*empty*
Magnitudes:
wind: magnitude of (u,v) [m/s] wind_speed
Directions:
wdir: direction of (u,v) [deg] wind_from_direction
--------------------------------------------------------------------------------
To create an instance of this class, provide the coordinate values at initialization. The spatial coordinates can be either lon/lat or UTM x/y. Here we will use spherical coordinates, but set the spatial resolution to about 4 km.
data = Wind(
lon=(0, 10),
lat=(60, 70),
#Shorthand for pd.date_range("2020-01-01 00:00", "2020-01-10 00:00", freq="1h")
time=("2020-01-01 00:00", "2020-01-10 00:00"),
)
data.set_spacing(dm=4000)
>> data
<Wind (GriddedSkeleton)>
------------------------------ Coordinate groups -------------------------------
Spatial: (lat, lon)
Grid: (lat, lon)
Gridpoint: (time)
All: (time, lat, lon)
------------------------------------ Xarray ------------------------------------
<xarray.Dataset> Size: 5kB
Dimensions: (time: 217, lat: 282, lon: 140)
Coordinates:
* time (time) datetime64[ns] 2kB 2020-01-01 ... 2020-01-10
* lat (lat) float64 2kB 60.0 60.04 60.07 60.11 ... 69.89 69.93 69.96 70.0
* lon (lon) float64 1kB 0.0 0.07194 0.1439 0.2158 ... 9.856 9.928 10.0
Data variables:
*empty*
---------------------------------- Empty data ----------------------------------
Empty variables:
u (time, lat, lon): 0.1 [m/s] x_wind
v (time, lat, lon): 0.1 [m/s] y_wind
-------------------------- Magnitudes and directions ---------------------------
wind: magnitude of (u,v) [m/s] wind_speed
wdir: direction of (u,v) [deg] wind_from_direction
--------------------------------------------------------------------------------
As we can see, no data is yet stored in the underlying xarray Dataset. We can now set and get the data:
>> data.set_u(3) # For non-constant value set numpy array
>> data.set_v(6)
The wind speed and direction can be retrieved and is calculated from the x,y-components:
>> data.wind()
array([[[6.70820393, 6.70820393, 6.70820393, ..., 6.70820393,
6.70820393, 6.70820393],
[6.70820393, 6.70820393, 6.70820393, ..., 6.70820393,
6.70820393, 6.70820393],
[6.70820393, 6.70820393, 6.70820393, ..., 6.70820393,
6.70820393, 6.70820393],
...,
>> data.wdir()
array([[[206.56505118, 206.56505118, 206.56505118, ..., 206.56505118,
206.56505118, 206.56505118],
[206.56505118, 206.56505118, 206.56505118, ..., 206.56505118,
206.56505118, 206.56505118],
[206.56505118, 206.56505118, 206.56505118, ..., 206.56505118,
206.56505118, 206.56505118],
...,
>> data.wdir(dir_type='to')
array([[[26.56505118, 26.56505118, 26.56505118, ..., 26.56505118,
26.56505118, 26.56505118],
[26.56505118, 26.56505118, 26.56505118, ..., 26.56505118,
26.56505118, 26.56505118],
[26.56505118, 26.56505118, 26.56505118, ..., 26.56505118,
26.56505118, 26.56505118],
...,
The direction (direction from) was parsed using the metadata in the gp.Wind.WindDir-parameters standard_name (wind_from_direction). The direction of the data can also be specified when setting data.
For example, to set the wind direction that is in mathematical convention (radians, 0=east, pi/2=north). Here we set data that is transposed and has an extra trivial dimension, but it can be reshaped by providing information about non-trivial dimensions:
# Defined over 'lat', 'lon', 'ensamble', 'time', instead of the 'time','lat','lon' that we want.
>> wind_data = np.full((282,140,1,217),0)
# We can ignore the trivial 'ensemble' dimension that we don't use
>> data.set_wdir(wind_data, coords=('lat','lon','time'), dir_type='math')
>> data
<Wind (GriddedSkeleton)>
------------------------------ Coordinate groups -------------------------------
Spatial: (lat, lon)
Grid: (lat, lon)
Gridpoint: (time)
All: (time, lat, lon)
------------------------------------ Xarray ------------------------------------
<xarray.Dataset> Size: 137MB
Dimensions: (time: 217, lat: 282, lon: 140)
Coordinates:
* time (time) datetime64[ns] 2kB 2020-01-01 ... 2020-01-10
* lat (lat) float64 2kB 60.0 60.04 60.07 60.11 ... 69.89 69.93 69.96 70.0
* lon (lon) float64 1kB 0.0 0.07194 0.1439 0.2158 ... 9.856 9.928 10.0
Data variables:
u (time, lat, lon) float64 69MB 6.708 6.708 6.708 ... 6.708 6.708
v (time, lat, lon) float64 69MB 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0
-------------------------- Magnitudes and directions ---------------------------
wind: magnitude of (u,v) [m/s] wind_speed
wdir: direction of (u,v) [deg] wind_from_direction
--------------------------------------------------------------------------------
We can see that the wind speed is kept as it is and the direction is rotated in a way that correspons to westerly winds, and this is also what we get when the wind direction is retrieved:
>> data.wdir()
array([[[270., 270., 270., ..., 270., 270., 270.],
[270., 270., 270., ..., 270., 270., 270.],
[270., 270., 270., ..., 270., 270., 270.],
...,
For large data the arrays can be stored as dask arrays. This can be activated for an instance:
>> data.dask.activate()
>> data.u()
dask.array<array, shape=(217, 282, 140), dtype=float64, chunksize=(217, 282, 140), chunktype=numpy.ndarray>
>> data.u(dask=False)
array([[[6.70820393, 6.70820393, 6.70820393, ..., 6.70820393,
6.70820393, 6.70820393],
[6.70820393, 6.70820393, 6.70820393, ..., 6.70820393,
6.70820393, 6.70820393],
[6.70820393, 6.70820393, 6.70820393, ..., 6.70820393,
6.70820393, 6.70820393],
...,
>> data.u(dask=False, data_array=True, lon=slice(0,1), time='2020-01-01 15:00')
<xarray.DataArray 'u' (lat: 282, lon: 14)> Size: 32kB
array([[6.70820393, 6.70820393, 6.70820393, ..., 6.70820393, 6.70820393,
6.70820393],
[6.70820393, 6.70820393, 6.70820393, ..., 6.70820393, 6.70820393,
6.70820393],
[6.70820393, 6.70820393, 6.70820393, ..., 6.70820393, 6.70820393,
6.70820393],
...,
[6.70820393, 6.70820393, 6.70820393, ..., 6.70820393, 6.70820393,
6.70820393],
[6.70820393, 6.70820393, 6.70820393, ..., 6.70820393, 6.70820393,
6.70820393],
[6.70820393, 6.70820393, 6.70820393, ..., 6.70820393, 6.70820393,
6.70820393]])
Coordinates:
time datetime64[ns] 8B 2020-01-01T15:00:00
* lat (lat) float64 2kB 60.0 60.04 60.07 60.11 ... 69.89 69.93 69.96 70.0
* lon (lon) float64 112B 0.0 0.07194 0.1439 ... 0.7914 0.8633 0.9353
To have this as the default behavious for the class, just add the @activate_dask-decorator.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file geo_skeletons-0.20.1.tar.gz
.
File metadata
- Download URL: geo_skeletons-0.20.1.tar.gz
- Upload date:
- Size: 1.1 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.10.12
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | b52346110ac35b18b497573847cd388c055b75077f27447788625fd832f95e00 |
|
MD5 | 49eab7eeef13135926d685a6fbbdeb3f |
|
BLAKE2b-256 | be1809d7c21f2e2ad4f712c6f94b4a06b98a6ad31786bd00aa8ff4b387387c73 |