imas-python 0.1.dev1618__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of imas-python might be problematic. Click here for more details.
- imas/__init__.py +34 -0
- imas/__main__.py +17 -0
- imas/_util.py +260 -0
- imas/_version.py +16 -0
- imas/assets/IDSDef2MDSpreTree.xsl +161 -0
- imas/assets/IDS_fake_toplevel.xml +318 -0
- imas/assets/IDS_minimal.xml +37 -0
- imas/assets/IDS_minimal_2.xml +37 -0
- imas/assets/IDS_minimal_struct_array.xml +43 -0
- imas/assets/IDS_minimal_types.xml +169 -0
- imas/assets/ITER_134173_106_core_profiles.ids +2438 -0
- imas/assets/ITER_134173_106_equilibrium.ids +3172 -0
- imas/assets/README.md +5 -0
- imas/assets/core_profiles.ids +2438 -0
- imas/assets/equilibrium.ids +3172 -0
- imas/backends/__init__.py +12 -0
- imas/backends/db_entry_impl.py +122 -0
- imas/backends/imas_core/__init__.py +4 -0
- imas/backends/imas_core/al_context.py +391 -0
- imas/backends/imas_core/db_entry_al.py +405 -0
- imas/backends/imas_core/db_entry_helpers.py +200 -0
- imas/backends/imas_core/imas_interface.py +216 -0
- imas/backends/imas_core/mdsplus_model.py +367 -0
- imas/backends/imas_core/uda_support.py +56 -0
- imas/backends/netcdf/__init__.py +4 -0
- imas/backends/netcdf/db_entry_nc.py +176 -0
- imas/backends/netcdf/ids2nc.py +306 -0
- imas/backends/netcdf/nc2ids.py +302 -0
- imas/backends/netcdf/nc_metadata.py +357 -0
- imas/backends/netcdf/nc_validate.py +53 -0
- imas/command/cli.py +239 -0
- imas/command/db_analysis.py +290 -0
- imas/command/helpers.py +45 -0
- imas/command/timer.py +77 -0
- imas/db_entry.py +802 -0
- imas/dd_helpers.py +300 -0
- imas/dd_zip.py +297 -0
- imas/exception.py +107 -0
- imas/ids_base.py +149 -0
- imas/ids_convert.py +920 -0
- imas/ids_coordinates.py +400 -0
- imas/ids_data_type.py +115 -0
- imas/ids_defs.py +171 -0
- imas/ids_factory.py +108 -0
- imas/ids_identifiers.py +125 -0
- imas/ids_metadata.py +307 -0
- imas/ids_path.py +254 -0
- imas/ids_primitive.py +510 -0
- imas/ids_struct_array.py +233 -0
- imas/ids_structure.py +331 -0
- imas/ids_toplevel.py +381 -0
- imas/setup_logging.py +64 -0
- imas/test/test_all_dd_versions.py +28 -0
- imas/test/test_cli.py +44 -0
- imas/test/test_dbentry.py +104 -0
- imas/test/test_dd_helpers.py +134 -0
- imas/test/test_dd_zip.py +29 -0
- imas/test/test_deepcopy.py +25 -0
- imas/test/test_exception.py +12 -0
- imas/test/test_get_sample.py +388 -0
- imas/test/test_hash.py +188 -0
- imas/test/test_helpers.py +354 -0
- imas/test/test_identifiers.py +105 -0
- imas/test/test_ids2nc.py +166 -0
- imas/test/test_ids_ascii_data.py +39 -0
- imas/test/test_ids_convert.py +415 -0
- imas/test/test_ids_coordinates.py +165 -0
- imas/test/test_ids_data_type.py +40 -0
- imas/test/test_ids_factory.py +35 -0
- imas/test/test_ids_metadata.py +66 -0
- imas/test/test_ids_mixin.py +20 -0
- imas/test/test_ids_path.py +192 -0
- imas/test/test_ids_primitive.py +109 -0
- imas/test/test_ids_struct_array.py +89 -0
- imas/test/test_ids_structure.py +70 -0
- imas/test/test_ids_toplevel.py +55 -0
- imas/test/test_ids_validate.py +343 -0
- imas/test/test_latest_dd_autofill.py +74 -0
- imas/test/test_latest_dd_manual.py +38 -0
- imas/test/test_latest_dd_resample.py +102 -0
- imas/test/test_lazy_loading.py +201 -0
- imas/test/test_list_occurrences.py +82 -0
- imas/test/test_minimal.py +37 -0
- imas/test/test_minimal_conversion.py +44 -0
- imas/test/test_minimal_io.py +21 -0
- imas/test/test_minimal_struct_array_io.py +60 -0
- imas/test/test_minimal_types.py +436 -0
- imas/test/test_minimal_types_io.py +70 -0
- imas/test/test_minimal_types_io_automatic.py +66 -0
- imas/test/test_nbc_change.py +408 -0
- imas/test/test_nc_autofill.py +13 -0
- imas/test/test_nc_entry.py +28 -0
- imas/test/test_nc_metadata.py +153 -0
- imas/test/test_nc_validation.py +197 -0
- imas/test/test_snippets.py +25 -0
- imas/test/test_static_ids.py +39 -0
- imas/test/test_str_1d.py +99 -0
- imas/test/test_time_slicing.py +182 -0
- imas/test/test_uda_support.py +12 -0
- imas/test/test_util.py +209 -0
- imas/training.py +45 -0
- imas/util.py +526 -0
- imas_python-0.1.dev1618.dist-info/LICENSE.txt +165 -0
- imas_python-0.1.dev1618.dist-info/METADATA +288 -0
- imas_python-0.1.dev1618.dist-info/RECORD +108 -0
- imas_python-0.1.dev1618.dist-info/WHEEL +5 -0
- imas_python-0.1.dev1618.dist-info/entry_points.txt +3 -0
- imas_python-0.1.dev1618.dist-info/top_level.txt +1 -0
imas/__init__.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# This file is part of imas-python.
|
|
2
|
+
# You should have received the imas-python LICENSE file with this project.
|
|
3
|
+
|
|
4
|
+
# isort: skip_file
|
|
5
|
+
|
|
6
|
+
from packaging.version import Version as _V
|
|
7
|
+
|
|
8
|
+
from ._version import version as __version__ # noqa: F401
|
|
9
|
+
from ._version import version_tuple # noqa: F401
|
|
10
|
+
|
|
11
|
+
# Import logging _first_
|
|
12
|
+
from . import setup_logging
|
|
13
|
+
|
|
14
|
+
# Import main user API objects in the imas module
|
|
15
|
+
from .db_entry import DBEntry
|
|
16
|
+
from .ids_factory import IDSFactory
|
|
17
|
+
from .ids_convert import convert_ids
|
|
18
|
+
from .ids_identifiers import identifiers
|
|
19
|
+
|
|
20
|
+
# Load the imas-python IMAS AL/DD core
|
|
21
|
+
from . import (
|
|
22
|
+
db_entry,
|
|
23
|
+
dd_helpers,
|
|
24
|
+
dd_zip,
|
|
25
|
+
util,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
PUBLISHED_DOCUMENTATION_ROOT = (
|
|
29
|
+
"https://sharepoint.iter.org/departments/POP/CM/IMDesign/"
|
|
30
|
+
"Code%20Documentation/imas-python-doc"
|
|
31
|
+
)
|
|
32
|
+
"""URL to the published documentation."""
|
|
33
|
+
OLDEST_SUPPORTED_VERSION = _V("3.22.0")
|
|
34
|
+
"""Oldest Data Dictionary version that is supported by imas-python."""
|
imas/__main__.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# This file is part of imas-python.
|
|
2
|
+
# You should have received the imas-python LICENSE file with this project.
|
|
3
|
+
"""Support module to run imas as a module:
|
|
4
|
+
|
|
5
|
+
.. code-block:: bash
|
|
6
|
+
:caption: Options to run imas CLI interface
|
|
7
|
+
|
|
8
|
+
# Run as a module (implemented in imas/__main__.py)
|
|
9
|
+
python -m imas
|
|
10
|
+
|
|
11
|
+
# Run as "program" (see project.scripts in pyproject.toml)
|
|
12
|
+
imas
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from imas.command.cli import cli
|
|
16
|
+
|
|
17
|
+
cli()
|
imas/_util.py
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# This file is part of imas-python.
|
|
2
|
+
# You should have received the imas-python LICENSE file with this project.
|
|
3
|
+
"""This file contains the implementation of all utility functions that need external
|
|
4
|
+
modules. Implementation has been removed from util.py to improve the performance of
|
|
5
|
+
``import imas``.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import copy
|
|
9
|
+
import logging
|
|
10
|
+
from difflib import Match, SequenceMatcher
|
|
11
|
+
from typing import Union
|
|
12
|
+
|
|
13
|
+
import numpy
|
|
14
|
+
import rich
|
|
15
|
+
import scipy.interpolate
|
|
16
|
+
from rich.columns import Columns
|
|
17
|
+
from rich.console import Group
|
|
18
|
+
from rich.panel import Panel
|
|
19
|
+
from rich.pretty import Pretty
|
|
20
|
+
from rich.table import Table
|
|
21
|
+
from rich.text import Text
|
|
22
|
+
from rich.tree import Tree
|
|
23
|
+
|
|
24
|
+
from imas.ids_base import IDSBase
|
|
25
|
+
from imas.ids_data_type import IDSDataType
|
|
26
|
+
from imas.ids_defs import IDS_TIME_MODE_HOMOGENEOUS
|
|
27
|
+
from imas.ids_metadata import IDSMetadata
|
|
28
|
+
from imas.ids_primitive import IDSPrimitive
|
|
29
|
+
from imas.ids_struct_array import IDSStructArray
|
|
30
|
+
from imas.ids_structure import IDSStructure
|
|
31
|
+
from imas.ids_toplevel import IDSToplevel
|
|
32
|
+
from imas.util import idsdiffgen, visit_children
|
|
33
|
+
|
|
34
|
+
logger = logging.getLogger(__name__)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def resample_impl(node, old_time, new_time, homogeneousTime, inplace, **kwargs):
|
|
38
|
+
if homogeneousTime is None:
|
|
39
|
+
homogeneousTime = node._time_mode
|
|
40
|
+
|
|
41
|
+
if homogeneousTime is None:
|
|
42
|
+
raise ValueError(
|
|
43
|
+
"homogeneous_time is not specified in ids_properties nor given"
|
|
44
|
+
" as keyword argument"
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
if homogeneousTime != IDS_TIME_MODE_HOMOGENEOUS:
|
|
48
|
+
# TODO: implement also for IDS_TIME_MODE_INDEPENDENT
|
|
49
|
+
# (and what about converting between time modes? this gets tricky fast)
|
|
50
|
+
raise NotImplementedError(
|
|
51
|
+
"resample is only implemented for IDS_TIME_MODE_HOMOGENEOUS"
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
def visitor(el):
|
|
55
|
+
if not el.has_value:
|
|
56
|
+
return
|
|
57
|
+
if el.metadata.type.is_dynamic and el.metadata.name != "time":
|
|
58
|
+
# effectively a guard to get only idsPrimitive
|
|
59
|
+
# TODO: also support time axes as dimension of IDSStructArray
|
|
60
|
+
time_axis = None
|
|
61
|
+
if hasattr(el, "coordinates"):
|
|
62
|
+
time_axis = el.coordinates.time_index
|
|
63
|
+
if time_axis is None:
|
|
64
|
+
logger.warning(
|
|
65
|
+
"No time axis found for dynamic structure %s", node._path
|
|
66
|
+
)
|
|
67
|
+
interpolator = scipy.interpolate.interp1d(
|
|
68
|
+
old_time.value, el.value, axis=time_axis, **kwargs
|
|
69
|
+
)
|
|
70
|
+
el.value = interpolator(new_time)
|
|
71
|
+
|
|
72
|
+
if not inplace:
|
|
73
|
+
el = copy.deepcopy(node)
|
|
74
|
+
else:
|
|
75
|
+
el = node
|
|
76
|
+
|
|
77
|
+
visit_children(visitor, el)
|
|
78
|
+
|
|
79
|
+
if isinstance(el, IDSToplevel):
|
|
80
|
+
el.time = new_time
|
|
81
|
+
else:
|
|
82
|
+
logger.warning(
|
|
83
|
+
"Performing resampling on non-toplevel. "
|
|
84
|
+
"Be careful to adjust your time base manually"
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
return el
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def print_tree_impl(structure, hide_empty_nodes):
|
|
91
|
+
with numpy.printoptions(threshold=5, linewidth=1024, precision=4):
|
|
92
|
+
rich.print(_make_tree(structure, hide_empty_nodes))
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _make_tree(structure, hide_empty_nodes=True, *, tree=None):
|
|
96
|
+
"""Build the ``rich.tree.Tree`` for display in :py:meth:`print_tree`.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
structure: IDS structure to add to the tree
|
|
100
|
+
hide_empty_nodes: Show or hide nodes without value.
|
|
101
|
+
|
|
102
|
+
Keyword Args:
|
|
103
|
+
tree: If provided, child items will be added to this Tree object. Otherwise a
|
|
104
|
+
new Tree is constructed.
|
|
105
|
+
"""
|
|
106
|
+
if tree is None:
|
|
107
|
+
tree = Tree(f"[magenta]{structure.metadata.name}")
|
|
108
|
+
|
|
109
|
+
if not isinstance(structure, (IDSStructure, IDSStructArray)):
|
|
110
|
+
raise TypeError()
|
|
111
|
+
|
|
112
|
+
iterator = structure
|
|
113
|
+
if hide_empty_nodes and isinstance(structure, IDSStructure):
|
|
114
|
+
iterator = structure.iter_nonempty_(accept_lazy=True)
|
|
115
|
+
for child in iterator:
|
|
116
|
+
if isinstance(child, IDSPrimitive):
|
|
117
|
+
if not child.has_value:
|
|
118
|
+
value = "[bright_black]-"
|
|
119
|
+
else:
|
|
120
|
+
value = Pretty(child.value)
|
|
121
|
+
txt = f"[yellow]{child.metadata.name}[/]:"
|
|
122
|
+
group = Columns([txt, value])
|
|
123
|
+
tree.add(group)
|
|
124
|
+
else:
|
|
125
|
+
if isinstance(child, IDSStructure):
|
|
126
|
+
txt = f"[magenta]{child._path}[/]"
|
|
127
|
+
ntree = tree.add(txt)
|
|
128
|
+
elif isinstance(child, IDSStructArray):
|
|
129
|
+
ntree = tree
|
|
130
|
+
if not child.has_value:
|
|
131
|
+
tree.add(f"[magenta]{child._path}[][/]")
|
|
132
|
+
_make_tree(child, hide_empty_nodes, tree=ntree)
|
|
133
|
+
|
|
134
|
+
return tree
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def print_metadata_tree_impl(
|
|
138
|
+
structure: Union[IDSMetadata, IDSBase], maxdepth: int
|
|
139
|
+
) -> None:
|
|
140
|
+
def _make_tree(tree: Tree, metadata: IDSMetadata, depth: int):
|
|
141
|
+
for child in metadata._children.values():
|
|
142
|
+
if child.data_type in (IDSDataType.STRUCTURE, IDSDataType.STRUCT_ARRAY):
|
|
143
|
+
newtree = tree.add(f"[magenta]{child.path_doc}[/]")
|
|
144
|
+
if maxdepth == 0 or depth < maxdepth:
|
|
145
|
+
_make_tree(newtree, child, depth + 1)
|
|
146
|
+
else:
|
|
147
|
+
newtree.add("[bright_black]<hidden>[/]")
|
|
148
|
+
else:
|
|
149
|
+
tree.add(f"[yellow]{child.path_doc}")
|
|
150
|
+
|
|
151
|
+
metadata = structure if isinstance(structure, IDSMetadata) else structure.metadata
|
|
152
|
+
tree = Tree(f"[magenta]{metadata.name}")
|
|
153
|
+
_make_tree(tree, metadata, 1)
|
|
154
|
+
rich.print(tree)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def inspect_impl(ids_node, hide_empty_nodes):
|
|
158
|
+
if not isinstance(ids_node, IDSBase):
|
|
159
|
+
return rich.inspect(ids_node)
|
|
160
|
+
# Title
|
|
161
|
+
if isinstance(ids_node, IDSToplevel):
|
|
162
|
+
title = f"IDS: [green]{ids_node.metadata.name}"
|
|
163
|
+
elif isinstance(ids_node, IDSStructure):
|
|
164
|
+
title = f"IDS structure: [green]{ids_node._path}"
|
|
165
|
+
elif isinstance(ids_node, IDSStructArray):
|
|
166
|
+
title = f"IDS array of structures: [green]{ids_node._path}"
|
|
167
|
+
else:
|
|
168
|
+
title = f"IDS value: [green]{ids_node._path}"
|
|
169
|
+
if ids_node._version:
|
|
170
|
+
title += f" [/](DD version [bold cyan]{ids_node._version}[/])"
|
|
171
|
+
|
|
172
|
+
renderables = []
|
|
173
|
+
# Documentation
|
|
174
|
+
renderables.append(Text(ids_node.metadata.documentation, style="inspect.help"))
|
|
175
|
+
|
|
176
|
+
# Value
|
|
177
|
+
if isinstance(ids_node, (IDSStructArray, IDSPrimitive)):
|
|
178
|
+
val = Pretty(ids_node.value, indent_guides=True, max_length=10, max_string=60)
|
|
179
|
+
value_text = Text.assemble(("value", "inspect.attr"), (" =", "inspect.equals"))
|
|
180
|
+
table = Table.grid(padding=(0, 1), expand=False)
|
|
181
|
+
table.add_column(justify="right")
|
|
182
|
+
table.add_row(value_text, val)
|
|
183
|
+
renderables.append(Panel(table, border_style="inspect.value.border"))
|
|
184
|
+
|
|
185
|
+
attrs = set(name for name in dir(ids_node) if not name.startswith("_"))
|
|
186
|
+
child_nodes = set()
|
|
187
|
+
if isinstance(ids_node, IDSStructure):
|
|
188
|
+
child_nodes = set(ids_node._children)
|
|
189
|
+
attrs -= child_nodes
|
|
190
|
+
attrs -= {"value"}
|
|
191
|
+
|
|
192
|
+
# Properties
|
|
193
|
+
if attrs:
|
|
194
|
+
attrs_table = Table.grid(padding=(0, 1), expand=False)
|
|
195
|
+
attrs_table.add_column(justify="right")
|
|
196
|
+
|
|
197
|
+
for attr in sorted(attrs):
|
|
198
|
+
try:
|
|
199
|
+
value = getattr(ids_node, attr)
|
|
200
|
+
except Exception:
|
|
201
|
+
continue
|
|
202
|
+
if callable(value):
|
|
203
|
+
continue
|
|
204
|
+
|
|
205
|
+
key_text = Text.assemble((attr, "inspect.attr"), (" =", "inspect.equals"))
|
|
206
|
+
attrs_table.add_row(key_text, Pretty(value))
|
|
207
|
+
|
|
208
|
+
renderables.append(Panel(attrs_table, title="Attributes"))
|
|
209
|
+
|
|
210
|
+
if child_nodes:
|
|
211
|
+
child_table = Table.grid(padding=(0, 1), expand=False)
|
|
212
|
+
child_table.add_column(justify="right")
|
|
213
|
+
|
|
214
|
+
for child in sorted(child_nodes):
|
|
215
|
+
value = getattr(ids_node, child)
|
|
216
|
+
if hide_empty_nodes and not value.has_value:
|
|
217
|
+
continue
|
|
218
|
+
key_text = Text.assemble((child, "inspect.attr"), (" =", "inspect.equals"))
|
|
219
|
+
child_table.add_row(key_text, Pretty(value))
|
|
220
|
+
|
|
221
|
+
renderables.append(Panel(child_table, title="Child nodes", style="cyan"))
|
|
222
|
+
|
|
223
|
+
rich.print(Panel.fit(Group(*renderables), title=title, border_style="scope.border"))
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def idsdiff_impl(struct1: IDSStructure, struct2: IDSStructure) -> None:
|
|
227
|
+
diff_table = Table("Value in structure 1", "Value in structure 2")
|
|
228
|
+
|
|
229
|
+
for description, child1, child2 in idsdiffgen(struct1, struct2):
|
|
230
|
+
if not isinstance(child1, IDSBase) and not isinstance(child2, IDSBase):
|
|
231
|
+
txt1 = f"{description}: {child1}"
|
|
232
|
+
txt2 = f"{description}: {child2}"
|
|
233
|
+
else:
|
|
234
|
+
txt1 = "-" if child1 is None else repr(child1)
|
|
235
|
+
txt2 = "-" if child2 is None else repr(child2)
|
|
236
|
+
|
|
237
|
+
seqmat = SequenceMatcher()
|
|
238
|
+
seqmat.set_seqs(txt1, txt2)
|
|
239
|
+
|
|
240
|
+
out1 = Text()
|
|
241
|
+
out2 = Text()
|
|
242
|
+
prevmatch = Match(0, 0, 0)
|
|
243
|
+
for match in seqmat.get_matching_blocks():
|
|
244
|
+
if match.a > prevmatch.a + prevmatch.size:
|
|
245
|
+
out1.append(txt1[prevmatch.a + prevmatch.size : match.a], "bold red")
|
|
246
|
+
if match.b > prevmatch.b + prevmatch.size:
|
|
247
|
+
out2.append(txt2[prevmatch.b + prevmatch.size : match.b], "bold green")
|
|
248
|
+
out1.append(txt1[match.a : match.a + match.size])
|
|
249
|
+
out2.append(txt2[match.b : match.b + match.size])
|
|
250
|
+
prevmatch = match
|
|
251
|
+
out1.append(txt1[match.a + match.size :], style="bold red")
|
|
252
|
+
out2.append(txt2[match.b + match.size :], style="bold green")
|
|
253
|
+
|
|
254
|
+
diff_table.add_row(out1, out2)
|
|
255
|
+
diff_table.add_section()
|
|
256
|
+
|
|
257
|
+
if diff_table.row_count:
|
|
258
|
+
rich.print(diff_table)
|
|
259
|
+
else:
|
|
260
|
+
rich.print("Structures", struct1, "and", struct2, "are identical")
|
imas/_version.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# file generated by setuptools_scm
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
TYPE_CHECKING = False
|
|
4
|
+
if TYPE_CHECKING:
|
|
5
|
+
from typing import Tuple, Union
|
|
6
|
+
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
7
|
+
else:
|
|
8
|
+
VERSION_TUPLE = object
|
|
9
|
+
|
|
10
|
+
version: str
|
|
11
|
+
__version__: str
|
|
12
|
+
__version_tuple__: VERSION_TUPLE
|
|
13
|
+
version_tuple: VERSION_TUPLE
|
|
14
|
+
|
|
15
|
+
__version__ = version = '0.1.dev1618'
|
|
16
|
+
__version_tuple__ = version_tuple = (0, 1, 'dev1618')
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<xsl:stylesheet xmlns:yaslt="http://www.mod-xslt2.com/ns/1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0" extension-element-prefixes="yaslt" xmlns:fn="http://www.w3.org/2005/02/xpath-functions" xmlns:local="http://www.example.com/functions/local" exclude-result-prefixes="local xs">
|
|
3
|
+
<xsl:param name="DD_GIT_DESCRIBE" as="xs:string" required="yes"/>
|
|
4
|
+
<xsl:param name="AL_GIT_DESCRIBE" as="xs:string" required="yes"/>
|
|
5
|
+
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
|
|
6
|
+
<!-- This script transforms the IDSDef.xml file into an XML file which will be used to build the MDS+ tree-->
|
|
7
|
+
<!-- It contains the full data structure and describes it in terms of MDS+ terminology (node, member) and types (TEXT,NUMERIC,SIGNAL)-->
|
|
8
|
+
<!-- This XML file has then to be processed by the Java routine CompileTree to create the MDS+ tree (part of the MDS+ libraries) -->
|
|
9
|
+
<!-- Time dependent numeric signals are of the SIGNAL type -->
|
|
10
|
+
<!-- Time independent numeric signals are of the NUMERIC type -->
|
|
11
|
+
<!-- Only Vector of strings (str_1d_type) are of the TEXT type --> <!-- Not sure the vector of strings with time-dependence will work with a TEXT declaration, though -->
|
|
12
|
+
<!-- Written by F. Imbeaux -->
|
|
13
|
+
|
|
14
|
+
<!-- Function for multiplying the number of descendents with timebasepath attribute by the occurrence of the child AoS -->
|
|
15
|
+
<xsl:function name="local:count-dynamic-fields" as="xs:integer">
|
|
16
|
+
<xsl:param name="current" as="node()"/>
|
|
17
|
+
<xsl:param name="level" as="xs:integer"/>
|
|
18
|
+
<xsl:param name="aos" as="xs:boolean"/>
|
|
19
|
+
<xsl:value-of select="$current/@maxoccur*count($current//field[@type='dynamic' and (($aos and @data_type='struct_array') or (not($aos) and not(@data_type='struct_array'))) and count(ancestor::field[@data_type='struct_array'])=$level])+$current/@maxoccur*sum($current//field[@data_type='struct_array' and not(@maxoccur='unbounded') and count(ancestor::field[@data_type='struct_array'])=$level]/local:count-dynamic-fields(.,$level+1,$aos))"/>
|
|
20
|
+
</xsl:function>
|
|
21
|
+
|
|
22
|
+
<!-- Scan for top-level elements -->
|
|
23
|
+
<xsl:template match = "/*">
|
|
24
|
+
<tree>
|
|
25
|
+
<member NAME="REF_INFO" USAGE="NUMERIC"/>
|
|
26
|
+
<node NAME="VERSION">
|
|
27
|
+
<member NAME="DATA_DICT" USAGE="TEXT"><data>"<xsl:value-of select="$DD_GIT_DESCRIBE"/>"</data></member>
|
|
28
|
+
<member NAME="ACC_LAYER" USAGE="TEXT"><data>"<xsl:value-of select="$AL_GIT_DESCRIBE"/>"</data></member>
|
|
29
|
+
<member NAME="BACK_MAJOR" USAGE="NUMERIC"></member>
|
|
30
|
+
<member NAME="BACK_MINOR" USAGE="NUMERIC"></member>
|
|
31
|
+
</node>
|
|
32
|
+
|
|
33
|
+
<xsl:apply-templates select = "IDS"/>
|
|
34
|
+
</tree>
|
|
35
|
+
</xsl:template>
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
<!-- First, we scan at the IDS level -->
|
|
40
|
+
<xsl:template match = "IDS">
|
|
41
|
+
<node>
|
|
42
|
+
<xsl:attribute name="NAME"><xsl:value-of select="@name"/></xsl:attribute>
|
|
43
|
+
<xsl:apply-templates select = "field"/>
|
|
44
|
+
|
|
45
|
+
<!-- Create subtrees for IDS occurrence. If parameter maxoccur is not defined, 10 additional occurrences are created-->
|
|
46
|
+
<xsl:call-template name = "addOccurrence" >
|
|
47
|
+
<xsl:with-param name = "iteration" select = "if (@maxoccur) then @maxoccur else 10" />
|
|
48
|
+
</xsl:call-template>
|
|
49
|
+
|
|
50
|
+
</node>
|
|
51
|
+
</xsl:template>
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
<!-- Then we scan the fields recursively -->
|
|
56
|
+
<xsl:template match = "field">
|
|
57
|
+
<xsl:choose>
|
|
58
|
+
<xsl:when test="@data_type='structure'">
|
|
59
|
+
<!-- this is a structure : write as node and scan the child elements recursively -->
|
|
60
|
+
<node>
|
|
61
|
+
<xsl:attribute name="NAME"><xsl:value-of select="@name"/></xsl:attribute>
|
|
62
|
+
|
|
63
|
+
<xsl:apply-templates select = "field"/>
|
|
64
|
+
</node>
|
|
65
|
+
</xsl:when>
|
|
66
|
+
<xsl:when test="@data_type='struct_array'">
|
|
67
|
+
<node>
|
|
68
|
+
<xsl:attribute name="NAME"><xsl:value-of select="@name"/></xsl:attribute>
|
|
69
|
+
<member>
|
|
70
|
+
<xsl:attribute name="NAME">static</xsl:attribute>
|
|
71
|
+
<xsl:attribute name="USAGE">NUMERIC</xsl:attribute>
|
|
72
|
+
</member>
|
|
73
|
+
<node>
|
|
74
|
+
<xsl:attribute name="NAME">timed_aos</xsl:attribute>
|
|
75
|
+
<xsl:call-template name = "makeAosSubtrees" >
|
|
76
|
+
<xsl:with-param name = "instances" select = "if (@type='dynamic') then 1 else local:count-dynamic-fields(.,1,true())" />
|
|
77
|
+
</xsl:call-template>
|
|
78
|
+
</node>
|
|
79
|
+
<node>
|
|
80
|
+
<xsl:attribute name="NAME">timed_data</xsl:attribute>
|
|
81
|
+
<xsl:call-template name = "makeDataSubtrees" >
|
|
82
|
+
<xsl:with-param name = "instances" select = "if (@type='dynamic') then 0 else local:count-dynamic-fields(.,1,false())"/>
|
|
83
|
+
</xsl:call-template>
|
|
84
|
+
</node>
|
|
85
|
+
</node>
|
|
86
|
+
</xsl:when>
|
|
87
|
+
<xsl:otherwise>
|
|
88
|
+
<!-- this is a bottom element -->
|
|
89
|
+
<member>
|
|
90
|
+
<xsl:attribute name="NAME"><xsl:value-of select="@name"/></xsl:attribute>
|
|
91
|
+
<!-- There used to be an instruction to use NUMERIC for dynamic str_1d_type fields, not sure if this was on purpose or some mis-use of logical operator precedence -->
|
|
92
|
+
<xsl:attribute name="USAGE"><xsl:value-of select="if(@type='dynamic') then 'SIGNAL' else 'NUMERIC'"/></xsl:attribute>
|
|
93
|
+
</member></xsl:otherwise>
|
|
94
|
+
</xsl:choose>
|
|
95
|
+
</xsl:template>
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
<!-- Additional IDS occurrence creation -->
|
|
99
|
+
<xsl:template name="addOccurrence">
|
|
100
|
+
<xsl:param name="iteration"/>
|
|
101
|
+
<xsl:variable name="current" select="."/>
|
|
102
|
+
<xsl:for-each select="1 to $iteration">
|
|
103
|
+
<node>
|
|
104
|
+
<xsl:attribute name="NAME">
|
|
105
|
+
<xsl:value-of select="."/>
|
|
106
|
+
</xsl:attribute>
|
|
107
|
+
<xsl:apply-templates select = "$current/field"/>
|
|
108
|
+
</node>
|
|
109
|
+
</xsl:for-each>
|
|
110
|
+
</xsl:template>
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
<!-- Aos timed node creation: Aos childs-->
|
|
114
|
+
<xsl:template name="makeAosSubtrees">
|
|
115
|
+
<xsl:param name="instances" select="100"/>
|
|
116
|
+
<xsl:for-each select="1 to xs:integer(1+(($instances - 1) div 1000))">
|
|
117
|
+
<xsl:variable name="group" select="."/>
|
|
118
|
+
<node>
|
|
119
|
+
<xsl:attribute name="NAME"><xsl:value-of select="concat('group_',.)"/></xsl:attribute>
|
|
120
|
+
<xsl:for-each select="1 to 1000">
|
|
121
|
+
<xsl:variable name="item" select="($group - 1) * 1000 + ."/>
|
|
122
|
+
<xsl:if test="$item <= $instances">
|
|
123
|
+
<node>
|
|
124
|
+
<xsl:attribute name="NAME"><xsl:value-of select="concat('item_',.)"/></xsl:attribute>
|
|
125
|
+
<member>
|
|
126
|
+
<xsl:attribute name="NAME">aos</xsl:attribute>
|
|
127
|
+
<xsl:attribute name="USAGE">NUMERIC</xsl:attribute>
|
|
128
|
+
</member>
|
|
129
|
+
<member>
|
|
130
|
+
<xsl:attribute name="NAME">time</xsl:attribute>
|
|
131
|
+
<xsl:attribute name="USAGE">NUMERIC</xsl:attribute>
|
|
132
|
+
</member>
|
|
133
|
+
</node>
|
|
134
|
+
</xsl:if>
|
|
135
|
+
</xsl:for-each>
|
|
136
|
+
</node>
|
|
137
|
+
</xsl:for-each>
|
|
138
|
+
</xsl:template>
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
<!-- Aos timed node creation: Data childs -->
|
|
142
|
+
<xsl:template name="makeDataSubtrees">
|
|
143
|
+
<xsl:param name="instances"/>
|
|
144
|
+
<xsl:for-each select="1 to xs:integer(1+(($instances - 1) div 1000))">
|
|
145
|
+
<xsl:variable name="group" select="."/>
|
|
146
|
+
<node>
|
|
147
|
+
<xsl:attribute name="NAME"><xsl:value-of select="concat('group_',.)"/></xsl:attribute>
|
|
148
|
+
<xsl:for-each select="1 to 1000">
|
|
149
|
+
<xsl:variable name="item" select="($group - 1) * 1000 + ."/>
|
|
150
|
+
<xsl:if test="$item <= $instances">
|
|
151
|
+
<member>
|
|
152
|
+
<xsl:attribute name="NAME"><xsl:value-of select="concat('item_',$item)"/></xsl:attribute>
|
|
153
|
+
<xsl:attribute name="USAGE">NUMERIC</xsl:attribute>
|
|
154
|
+
</member>
|
|
155
|
+
</xsl:if>
|
|
156
|
+
</xsl:for-each>
|
|
157
|
+
</node>
|
|
158
|
+
</xsl:for-each>
|
|
159
|
+
</xsl:template>
|
|
160
|
+
|
|
161
|
+
</xsl:stylesheet>
|