IDS metadata¶
Besides the data structure, the IMAS Data Dictionary also defines metadata
associated with elements in the IDS, such as coordinate information, units, etc.
IMAS-Python provides the IDSMetadata API for
interacting with this metadata.
On this page you find several examples for querying and using the metadata of IDS elements.
See also
IMAS-Python advanced training: Using Data Dictionary metadata
Overview of available metadata¶
An overview of available metadata is given in the API documentation for
IDSMetadata.
The documented attributes are always available, but additional metadata from the data
dictionary may be available as well.
For example, the data dictionary indicates a lifecycle_last_change on all IDS
toplevels (in which DD version was that IDS last updated). This is not listed in the
metadata documentation, but you can still access it. See the following code sample:
>>> import imas
>>> core_profiles = imas.IDSFactory().core_profiles()
>>> core_profiles.metadata.lifecycle_last_change
'3.39.0'
Using coordinates of quantities¶
All multi-dimensional quantities in an IDS have coordinate information. These can be data nodes (for example 2D floating point data) or array of structure nodes.
Get coordinate values¶
Each data node and array of structures has a coordinates attribute. By
indexing this attribute, you can retrieve the coordinate values for that
dimension. For example, coordinates[2] attempts to retrieve the coordinate
values for the third dimension of the data.
When another quantity in the IDS is used as a coordinate, that quantity is looked up. See below example.
>>> core_profiles = imas.IDSFactory().core_profiles()
>>> core_profiles.profiles_1d.resize(1)
>>> profile = core_profiles.profiles_1d[0]
>>> profile.grid.rho_tor_norm = [0, 0.15, 0.3, 0.45, 0.6]
>>> # Electron temperature has rho_tor_norm as coordinate:
>>> profile.electrons.temperature.coordinates[0]
IDSNumericArray("/core_profiles/profiles_1d/1/grid/rho_tor_norm", array([0. , 0.15, 0.3 , 0.45, 0.6 ]))
When a coordinate is just an index, IMAS-Python generates a
numpy.arange() with the same length as the data. See below
example.
>>> pf_active = imas.IDSFactory().pf_active()
>>> pf_active.coil.resize(10)
>>> # Coordinate1 of coil is an index 1...N
>>> pf_active.coil.coordinates[0]
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
Time coordinates
Time coordinates are a special case: the coordinates depend on whether the IDS is in homogeneous time mode or not. IMAS-Python handles this transparently.
>>> core_profiles = imas.IDSFactory().core_profiles()
>>> # profiles_1d is a time-dependent array of structures:
>>> core_profiles.profiles_1d.coordinates[0]
[...]
ValueError: Invalid IDS time mode: ids_properties/homogeneous_time is <IDSInt0D (IDS:core_profiles, ids_properties/homogeneous_time, empty INT_0D)>, was expecting 0 or 1.
>>> core_profiles.ids_properties.homogeneous_time = \\
... imas.ids_defs.IDS_TIME_MODE_HOMOGENEOUS
>>> # In homogeneous time mode, the root /time array is used
>>> core_profiles.time = [0, 1]
>>> core_profiles.profiles_1d.resize(2)
>>> core_profiles.profiles_1d.coordinates[0]
IDSNumericArray("/core_profiles/time", array([0., 1.]))
>>> # But in heterogeneous time mode, profiles_1d/time is used instead
>>> core_profiles.ids_properties.homogeneous_time = \\
... imas.ids_defs.IDS_TIME_MODE_HETEROGENEOUS
>>> core_profiles.profiles_1d.coordinates[0]
array([-9.e+40, -9.e+40])
Alternative coordinates
Sometimes the Data Dictionary indicates that multiple other quantities could be
used as a coordinate. For example, the
distribution(i1)/profiles_2d(itime)/density(:,:) quantity in the
distributions IDS has as first coordinate
distribution(i1)/profiles_2d(itime)/grid/r OR
distribution(i1)/profiles_2d(itime)/grid/rho_tor_norm. This means that either
r or rho_tor_norm can be used as coordinate. When requesting such a
coordinate from IMAS-Python, four things may happen:
When
ris empty andrho_tor_normnot,coordinates[0]will returnrho_tor_norm.When
rho_tor_normis empty andrnot,coordinates[0]will returnr.When both
randrho_tor_normare not empty, IMAS-Python raises an error because it cannot determine which of the two coordinates should be used.Similarly, an error is raised by IMAS-Python when neither
rnorrho_tor_normare set.
See also
API documentation for IDSCoordinates
Query coordinate information¶
In IMAS-Python you can query coordinate information in two ways:
Directly query the coordinate attribute on the metadata:
<quantity>.metadata.coordinate2gives you the coordinate information for the second dimension of the quantity.Use the
coordinatesattribute:<quantity>.metadata.coordinatesis a tuple containing all coordinate information for the quantity.
The coordinate information from the Data Dictionary is parsed and stored in an
IDSCoordinate. The Data Dictionary has
several types of coordinate information:
When the coordinate is an index, the Data Dictionary indicates this via
1...N. When a literalNis given, no restrictions apply.It is also possible to have a specific value for
N, for example1...3. Then, this dimension can contain at most 3 items.When another quantity in the IDS is used as a coordinate, the coordinate indicates the path to that other quantity.
Todo
Detailed coordinate descriptions should happen in the DD docs. Link to that when available.
>>> pf_active = imas.IDSFactory().pf_active()
>>> # coordinate1 of pf_active/coil is an index (the number of the coil)
>>> pf_active.coil.metadata.coordinate1
IDSCoordinate('1...N')
>>> pf_active.coil.resize(1)
>>> # pf_active/coil/current_limit_max is 2D, so has two coordinates
>>> # Both refer to another quantity in the IDS
>>> pf_active.coil[0].current_limit_max.metadata.coordinates
(IDSCoordinate('coil(i1)/b_field_max'), IDSCoordinate('coil(i1)/temperature'))
See also
API documentation for IDSCoordinate.
Query alternative coordinates¶
Starting in Data Dictionary 4.0, a coordinate quantity may indicate alternatives for
itself. These alternatives are stored in the metadata attribute
alternative_coordinates.
For example, most quantities in profiles_1d of the core_profiles IDS have
profiles_1d/grid/rho_tor_norm as coordinate. However, there are alternatives
that may be used instead (e.g. rho_tor, psi, …). This is then indicated in
the metadata of rho_tor_norm:
>>> import imas
>>> import rich
>>> dd4 = imas.IDSFactory("4.0.0")
>>> core_profiles = dd4.core_profiles()
>>> rich.print(cp.profiles_1d[0].grid.rho_tor_norm.metadata.alternative_coordinates)
(
IDSPath('profiles_1d(itime)/grid/rho_tor'),
IDSPath('profiles_1d(itime)/grid/psi'),
IDSPath('profiles_1d(itime)/grid/volume'),
IDSPath('profiles_1d(itime)/grid/area'),
IDSPath('profiles_1d(itime)/grid/surface'),
IDSPath('profiles_1d(itime)/grid/rho_pol_norm')
)