-
Notifications
You must be signed in to change notification settings - Fork 12
Python specific
This page contains python-specific information for using titanlib.
After installing the package, titanlib can be loaded with import titanlib. There are no submodules in titanlib, so all functions are accessed with titanlib.<function>. Read the header file documentation to see available functions. All functions available in the C++ library are also made available in python, with the same function signature. For example, the C++ function:
vec2 range_check(const vec &values, const vec &min, const vec& max)can be used in python as follows:
>>> import titanlib
>>> titanlib.range_check([-20, 11, 2], [-15], [10])
array([1, 1, 0], dtype=int32)The SWIG interface does type checking and casting when required, and the following types can be used:
| C++ type | Python types |
|---|---|
float |
Any scalar |
int |
Any scalar |
vec |
1D np.array, list, tuple |
vec2 |
2D np.array, list of lists, tuple of tuples |
ivec |
1D np.array, list, tuple |
For best performance, use numpy arrays since these already store their data sequentially in C. Using tuples or lists incur a significant conversion penalty for large datasets.
All python vectors are automatically converted to C++ floats when passed to C++ functions that expect floats. Python vectors are automatically converted to C++ ints when passed to C++ functions that expect ints. This means you can pass numpy arrays of any numeric dtype, such as float32, float64, int32. However, arrays with dtypes of float32 and int32 are ideal, since then no conversion from (for example) float64 is made.
titanlib's Python bindings use positional arguments only — keyword arguments (e.g., debug=True, obs_to_check=obs_to_check) are not supported and will cause an error.
To use an optional argument, you must also pass all preceding optional arguments explicitly with their default values.
For instance :
# With obs_to_check — append it after the required arguments
flags = titanlib.buddy_check(points, values, radius, num_min,
threshold, max_elev_diff, elev_gradient, min_std,
num_iterations, obs_to_check)# With accept_isolated=False — append it after basic
accept_isolated=False
flags, scores = titanlib.sct_resistant(points, values, obs_to_check,
background_values, background_elab_type,
num_min_outer, num_max_outer, inner_radius, outer_radius,
num_iterations, num_min_prof, min_elev_diff,
min_horizontal_scale, max_horizontal_scale,
kth_closest_obs_horizontal_scale, vertical_scale,
value_mina, value_maxa, value_minv, value_maxv,
eps2, tpos, tneg, debug, basic, accept_isolated)The indices parameter in the Dataset method controls which flags in the Dataset get updated, when going through the Dataset's internal flag management. This is useful when chaining multiple QC checks on the same Dataset, but not all the stations should go through the same tests. Even if indices are given to the Dataset class, the QC test still runs on all unflagged stations (so neighbors are available), but only the flags for stations specified in indices are written back — and once a station has a non-zero flag, it is permanently excluded from all subsequent tests.
The indices parameter in the Dataset method controls which stations' flags get updated after a QC test. This is useful when chaining multiple QC checks on the same Dataset, but not all stations should go through the same tests. Even when indices is specified, the QC test still runs on all unflagged stations — so that neighbors are available for spatial checks — but only the flags for stations in indices are written back. Once a station has a non-zero flag, it is permanently excluded from all subsequent tests run on that Dataset.
For sct_resistant and sct_dual, when chaining QC tests using Dataset methods, if using accept_isolated = False, the observations that get 11 or 12 as flag will be excluded from the next tests (treated as bad observations). If using accept_isolated = True, the observation can be tested with the next tests (example chained tests with different radius).
The indices parameter is not used in the free functions (e.g., titanlib.sct_resistant, titanlib.sct_dual), which return flags directly without any internal state.
dataset.sct_resistant(obs_to_check, background_values, background_elab_type,
num_min_outer, num_max_outer, inner_radius, outer_radius,
num_iterations, num_min_prof, min_elev_diff,
min_horizontal_scale, max_horizontal_scale,
kth_closest_obs_horizontal_scale, vertical_scale,
value_mina, value_maxa, value_minv, value_maxv,
eps2, tpos, tneg, debug, basic,
[0, 5, 10, 12], # indices: only update flags for these observations, for instance test for station you trust less
True # accept_isolated (default is True), isolated observations can be used in the next tests
)When arrays are returned from the C++ function back to python, they are converted to numpy arrays either of dtype float32 or int32 depending on the output type on the C++ side.
To get ready for the examples in the next sections, run the code below to set up necessary variables (you will also need the test datasets). This retrieves air temperature and precipitation from the observation, analysis, and forecast files as well as metadata about the stations.
import titanlib
import netCDF4
import numpy as np
with netCDF4.Dataset('obs.nc', 'r') as file:
lats = file.variables['latitude'][:, 0]
lons = file.variables['longitude'][:, 0]
points = titanlib.Points(lats, lons)
temp_obs = file.variables['air_temperature_2m'][:]
precip_obs = file.variables['precipitation_amount'][:]Copyright © 2019-2023 Norwegian Meteorological Institute