Skip to content

Commit fbd5285

Browse files
smitharapacesm
andauthored
Cached models (#97)
* Adding flag to bypass the server-side cached models. * Describe magnetic model handling and caching * Bump version to 0.11.3 --------- Co-authored-by: Martin Paces <[email protected]>
1 parent 0e74835 commit fbd5285

9 files changed

+159
-2
lines changed

docs/available_parameters.rst

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
.. _Swarm parameters:
2+
13
Available parameters for Swarm
24
==============================
35

@@ -208,6 +210,8 @@ SW_OPER_VOBS_1M_2\_:SecularVariation ``SiteCode,B_SV,sigma_SV``
208210

209211
----
210212

213+
.. _Swarm models:
214+
211215
``models``
212216
----------
213217

docs/capabilities.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ VirES provides more than just *access* to data. Some operations can be peformed
2222
| :py:meth:`viresclient.SwarmRequest.get_orbit_number`
2323
| :py:meth:`viresclient.SwarmRequest.get_times_for_orbits`
2424
**Geomagnetic model evaluation**
25-
| Forwards evaluation of magnetic field models when a magnetic dataset is selected (e.g. ``MAGx_LR``)
25+
| Forwards evaluation of magnetic field models when a magnetic dataset is selected (e.g. ``MAGx_LR``). For more detail, see :ref:`Geomagnetic model handling`.
2626
| :py:meth:`viresclient.SwarmRequest.available_models`
2727
| :py:meth:`viresclient.SwarmRequest.get_model_info`
2828
| `models` option in :py:meth:`viresclient.SwarmRequest.set_products`

docs/geomagnetic_models.rst

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
Geomagnetic model handling
2+
==========================
3+
4+
Model evaluation
5+
----------------
6+
7+
The geomagnetic models provided by VirES are all based on spherical harmonics, though they differ in their parameterisation and time-dependence. They provide predictions of the different geomagnetic field sources (e.g. core, lithosphere, ionosphere, magnetosphere) and are generally valid near to Earth's surface (i.e. at ground level and in LEO). To select appropriate models for your use case, you should refer to the scientific publications related to these models.
8+
9+
In VirES, we provide model evaluations calculated at the same sample points as the data products. This means that the spherical harmonic expansion is made at the time and location of each datapoint (e.g. in the case of ``MAGx_LR``, at every second). The main purpose is to provide the data-model residuals, or magnetic perturbations, useful for studying the external magnetic field, typically ionospheric in origin.
10+
11+
*Pending:* In a future VirES release, some interpolation will be used to provide the magnetic model predictions along the 50Hz ``MAGx_HR`` products (to improve speed). The predictions at the 1Hz (``MAGx_LR``) locations will be used and a cubic interpolation performed to provide the predictions at the 50Hz locations.
12+
13+
The magnetic data products provide the magnetic field vector as the parameter ``B_NEC`` in the NEC (North, East, Centre) frame, as well as the magnetic field intensity/magnitude (scalar), ``F``. When also requesting models from VirES (by supplying the ``models`` kwarg to :py:meth:`viresclient.SwarmRequest.set_products`), the corresponding model predictions will be returned in parameters named ``B_NEC_<model-name>`` or ``F_<model-name>``. Alternatively, the data-model residual alone, named ``B_NEC_res_<model-name>`` or ``F_res_<model-name>`` can be returned directly by also supplying the kwarg ``residuals=True``. Models should be provided as a list, like ``models=["CHAOS", "IGRF"]``.
14+
15+
Available models
16+
----------------
17+
18+
See :ref:`Available parameters for Swarm / models<Swarm models>` for the list of available models.
19+
20+
You can use :py:meth:`viresclient.SwarmRequest.available_models` and :py:meth:`viresclient.SwarmRequest.get_model_info` to query the details of models.
21+
22+
Composed and custom models
23+
--------------------------
24+
25+
When providing ``models`` to :py:meth:`viresclient.SwarmRequest.set_products`, they can be customised:
26+
27+
| *Rename:*
28+
| ``models=["Model='CHAOS-Core'"]``
29+
| This will provide the ``CHAOS-Core`` model renamed to ``Model``, so that the returned parameters will include ``B_NEC_Model`` instead of ``B_NEC_CHAOS-Core``.
30+
31+
| *Compose (combine):*
32+
| ``models=["Model='CHAOS-Core' + 'CHAOS-Static'"]``
33+
| This sums together the contribution from ``CHAOS-Core`` and ``CHAOS-Static`` into a custom model called ``Model``.
34+
35+
| *Customise:*
36+
| ``models=["Model='CHAOS-Core'(max_degree=20) + 'CHAOS-Static'(min_degree=21,max_degree=80)"]``
37+
| This limits the spherical harmonic degree used in the model calculation.
38+
39+
Note that single and double quotes are interchangeable, and must be used sometimes in order to enclose a model name and thus distinguish usage of a hyphen (``-``) in the model name from an arithmetic minus.
40+
41+
For more examples, see https://notebooks.vires.services/notebooks/02b__viresclient-available-data#manipulation-of-models
42+
43+
You can query information about your selected models using :py:meth:`viresclient.SwarmRequest.get_model_info`:
44+
45+
.. code-block:: python
46+
47+
from viresclient import SwarmRequest
48+
49+
request = SwarmRequest()
50+
51+
request.get_model_info(
52+
models=["Model='CHAOS-Core'(max_degree=20) + 'CHAOS-Static'(min_degree=21,max_degree=80)"]
53+
)
54+
55+
.. code-block::
56+
57+
{'Model': {'expression': "'CHAOS-Core'(max_degree=20,min_degree=1) + 'CHAOS-Static'(max_degree=80,min_degree=21)",
58+
'validity': {'start': '1997-02-07T05:23:17.067838Z',
59+
'end': '2024-03-01T02:57:24.851521Z'},
60+
'sources': ['CHAOS-7_static.shc',
61+
'SW_OPER_MCO_SHA_2X_19970101T000000_20230807T235959_0715',
62+
'SW_OPER_MCO_SHA_2X_20230808T000000_20240229T235959_0715']}}
63+
64+
Model caching
65+
-------------
66+
67+
To speed up usage of commonly used expensive models, the server stores and uses a cache of some of the model values (so that they do not always need to be evaluated from scratch). This should happen transparently so you generally do not need to worry about it, but it may be helpful to understand when the cache might *not* be used, causing data requests to take longer.
68+
69+
.. note::
70+
71+
The caching mechanism can be bypassed (forcing direct evaluation of models) by supplying ``ignore_cached_models=True`` in :py:meth:`viresclient.SwarmRequest.set_products`
72+
73+
Cached models (these are chosen as they are both expensive and commonly used)::
74+
75+
CHAOS-Static
76+
MIO_SHA_2C-Primary
77+
MIO_SHA_2C-Secondary
78+
MLI_SHA_2C
79+
80+
The predictions for these models are cached only at the positions and times defined by the following products (i.e. low resolution magnetic products)::
81+
82+
SW_OPER_MAGx_LR_1B (x=A,B,C)
83+
GRACE_x_MAG (x=A,B)
84+
GFx_OPER_FGM_ACAL_CORR (x=1,2)
85+
GO_MAG_ACAL_CORR
86+
GO_MAG_ACAL_CORR_ML
87+
CS_OPER_MAG
88+
89+
The logic describing when the cache is used is as follows:
90+
91+
.. image:: https://mermaid.ink/img/pako:eNqFkk1v2zAMhv8KoVMLND20PRlDiyYxugKxW6wekCAeBkZiEgGyFEhUt6Dpf5_8kSw7zQdDfvnyISnzQ0inSGRibdwvuUXPUE1rC-l5vChSyIB0dq030SNrZx8uhyCMRveHN0ar0KsDjM_lSQzsmgMsenF8UemGjLaUWO_kScFqDxLllh6-rPz9pD21ZRi1DWCQKTA0bfFjuXHHXVA4wPxcKd2pSv-eL78H6tk_emWxzN_RxATtkUkerC0B5jfD183fLpWjANYx0G-UbPbQIMvtWcd0vblOBjsqHp9-zr7BzjsVJUMgQ5JJXR6ZXZMvvCV_9KQBbv-JtoivJ0RLf83L6XP5lEH5UsEir-C5eJ3lRV5W-TSl3w3pt8tZahY9aMvkd850P6gFxKDtBvrehluY3y0ncaUlhF034v9yxJVoyDeoVdqNj5ZRizRGQ7XI0lHRGqPhWtT2M1njTqX7zZVm50W2RhPoSmBk97a3UmTsIx1NU40bj83JRV1S0S9ht4uffwB28dYw?type=png
92+
:alt: Flowchart showing the cache usage logic
93+
94+
*Custom* configured models, e.g. ``CHAOS-Static(max_degree=80)``, are not cached and must be evaluated directly.
95+
96+
*Composed models*, i.e. ``Model = Model1 + Model2``, will use the cache for sub-models where available. For example, choosing ``CHAOS-Core + CHAOS-Static`` will make use of the cache for ``CHAOS-Static`` (an expensive model), but will directly evaluate ``CHAOS-Core`` (a cheap model), and combine the result. The same is true for *alias* models such as ``CHAOS`` (which equates to ``CHAOS-Core + CHAOS-Static + CHAOS-MMA``).
97+
98+
When the source products or model are updated, the cache needs to be re-generated accordingly. This means means there is some delay before the cache is available again (while the changes are still being processed). In cases where the cache has been obsoleted, the system falls back to evaluating the model directly. In short, the caching mechanism prefers model consistency over performance.
99+
100+
Model values through HAPI
101+
-------------------------
102+
103+
What is HAPI? See https://notebooks.vires.services/notebooks/02h1_hapi
104+
105+
When accessing magnetic datasets, there are additional HAPI parameters available::
106+
107+
B_NEC_Model
108+
F_Model
109+
B_NEC_res_Model
110+
F_res_Model
111+
112+
These give, respectively, vector and scalar magnetic model values and data-model residuals using the full CHAOS model (core + lithosphere + magnetosphere). These are provided through the cache as described above.

docs/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Introduction
2525
capabilities
2626
available_parameters
2727
available_parameters_aeolus
28+
geomagnetic_models
2829
notebook_intro
2930
release_notes
3031

docs/release_notes.rst

+6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ Release notes
44
Change log
55
----------
66

7+
Changes from 0.11.2 to 0.11.3
8+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
9+
10+
- Added ``ignore_cached_models=True`` in :py:meth:`viresclient.SwarmRequest.set_products`
11+
- Added description of model handling in docs
12+
713
Changes from 0.11.1 to 0.11.2
814
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
915

src/viresclient/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,4 @@
3535
from ._config import ClientConfig, set_token
3636
from ._data_handling import ReturnedData, ReturnedDataFile
3737

38-
__version__ = "0.11.2"
38+
__version__ = "0.11.3"

src/viresclient/_client_swarm.py

+18
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ class SwarmWPSInputs(WPSInputs):
263263
"sampling_step",
264264
"response_type",
265265
"custom_shc",
266+
"ignore_cached_models",
266267
]
267268

268269
def __init__(
@@ -276,6 +277,7 @@ def __init__(
276277
sampling_step=None,
277278
response_type=None,
278279
custom_shc=None,
280+
ignore_cached_models=False,
279281
):
280282
# Set up default values
281283
# Obligatory - these must be replaced before the request is made
@@ -290,6 +292,7 @@ def __init__(
290292
self.filters = None if filters is None else filters
291293
self.sampling_step = None if sampling_step is None else sampling_step
292294
self.custom_shc = None if custom_shc is None else custom_shc
295+
self.ignore_cached_models = ignore_cached_models
293296

294297
@property
295298
def collection_ids(self):
@@ -345,6 +348,17 @@ def model_expression(self, model_expression):
345348
else:
346349
raise TypeError("model_expression must be a string")
347350

351+
@property
352+
def ignore_cached_models(self):
353+
return self._ignore_cached_models
354+
355+
@ignore_cached_models.setter
356+
def ignore_cached_models(self, value):
357+
if isinstance(value, bool):
358+
self._ignore_cached_models = value
359+
else:
360+
raise TypeError
361+
348362
@property
349363
def begin_time(self):
350364
return self._begin_time
@@ -1532,6 +1546,7 @@ def set_products(
15321546
auxiliaries=None,
15331547
residuals=False,
15341548
sampling_step=None,
1549+
ignore_cached_models=False,
15351550
):
15361551
"""Set the combination of products to retrieve.
15371552
@@ -1545,6 +1560,7 @@ def set_products(
15451560
auxiliaries (list(str)): from .available_auxiliaries()
15461561
residuals (bool): True if only returning measurement-model residual
15471562
sampling_step (str): ISO_8601 duration, e.g. 10 seconds: PT10S, 1 minute: PT1M
1563+
ignore_cached_models (bool): True if cached models should be ignored and calculated on-the-fly
15481564
15491565
"""
15501566
if self._collection_list is None:
@@ -1643,6 +1659,8 @@ def set_products(
16431659
self._request_inputs.variables = list(variables)
16441660
self._request_inputs.sampling_step = sampling_step
16451661
self._request_inputs.custom_shc = custom_shc
1662+
self._request_inputs.ignore_cached_models = ignore_cached_models
1663+
16461664
return self
16471665

16481666
def set_range_filter(self, parameter, minimum=None, maximum=None, negate=False):

src/viresclient/_wps/templates/vires_fetch_filtered_data.xml

+8
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@
1515
<wps:LiteralData>{{ model_expression|cdata }}</wps:LiteralData>
1616
</wps:Data>
1717
</wps:Input>
18+
{% if ignore_cached_models -%}
19+
<wps:Input>
20+
<ows:Identifier>ignore_cached_models</ows:Identifier>
21+
<wps:Data>
22+
<wps:LiteralData>true</wps:LiteralData>
23+
</wps:Data>
24+
</wps:Input>
25+
{% endif -%}
1826
{% endif -%}
1927
{% if custom_shc -%}
2028
<wps:Input>

src/viresclient/_wps/templates/vires_fetch_filtered_data_async.xml

+8
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@
1515
<wps:LiteralData>{{ model_expression|cdata }}</wps:LiteralData>
1616
</wps:Data>
1717
</wps:Input>
18+
{% if ignore_cached_models -%}
19+
<wps:Input>
20+
<ows:Identifier>ignore_cached_models</ows:Identifier>
21+
<wps:Data>
22+
<wps:LiteralData>true</wps:LiteralData>
23+
</wps:Data>
24+
</wps:Input>
25+
{% endif -%}
1826
{% endif -%}
1927
{% if custom_shc -%}
2028
<wps:Input>

0 commit comments

Comments
 (0)