tecio-python 0.3.1__tar.gz → 0.3.3__tar.gz
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.
- {tecio_python-0.3.1/tecio_python.egg-info → tecio_python-0.3.3}/PKG-INFO +8 -6
- {tecio_python-0.3.1 → tecio_python-0.3.3}/README.md +7 -5
- tecio_python-0.3.3/plugins/matlab/fecplot.m +111 -0
- {tecio_python-0.3.1/tecio → tecio_python-0.3.3}/plugins/paraview/TecplotTecioReader.py +14 -5
- {tecio_python-0.3.1 → tecio_python-0.3.3}/pyproject.toml +6 -2
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/__init__.py +24 -2
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/_containers.py +21 -21
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/_dat_read.py +437 -68
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/_dat_write.py +149 -270
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/_io.py +275 -24
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/_meta.py +28 -15
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/_plt_read.py +171 -17
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/_plt_write.py +79 -282
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/_reader.py +230 -11
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/_szl_read.py +37 -4
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/_szl_write.py +129 -341
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/_utils.py +3 -1
- tecio_python-0.3.3/tecio/_writer.py +953 -0
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/cli/tec2mat.py +20 -4
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/cli/tecaux.py +20 -10
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/cli/tecdump.py +33 -18
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/cli/tecextract.py +131 -35
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/cli/tecfix.py +22 -8
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/cli/tecmerge.py +361 -50
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/cli/teconvert.py +17 -7
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/cli/tecscale.py +34 -23
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/cli/tecslice.py +27 -10
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/cli/tecstats.py +116 -50
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/libtecio.py +712 -137
- {tecio_python-0.3.1 → tecio_python-0.3.3/tecio_python.egg-info}/PKG-INFO +8 -6
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio_python.egg-info/SOURCES.txt +2 -2
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tests/test_cli.py +130 -130
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tests/test_io.py +212 -34
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tests/test_read.py +99 -41
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tests/test_write.py +371 -117
- tecio_python-0.3.1/tecio/_writer.py +0 -331
- tecio_python-0.3.1/tecio/old_libtecio.py +0 -3689
- {tecio_python-0.3.1 → tecio_python-0.3.3}/LICENSE +0 -0
- {tecio_python-0.3.1 → tecio_python-0.3.3}/NOTICE +0 -0
- {tecio_python-0.3.1 → tecio_python-0.3.3}/setup.cfg +0 -0
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/_constants.py +0 -0
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio/cli/__init__.py +0 -0
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio_python.egg-info/dependency_links.txt +0 -0
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio_python.egg-info/entry_points.txt +0 -0
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio_python.egg-info/requires.txt +0 -0
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tecio_python.egg-info/top_level.txt +0 -0
- {tecio_python-0.3.1 → tecio_python-0.3.3}/tests/test_libtecio.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tecio-python
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: Python interface for reading and writing Tecplot data files
|
|
5
5
|
Project-URL: Homepage, https://github.com/meersman/tecio
|
|
6
6
|
Project-URL: Documentation, https://meersman.github.io/tecio/
|
|
@@ -82,6 +82,8 @@ export TECIO_LIB=/path/to/libtecio.dylib # macOS
|
|
|
82
82
|
|
|
83
83
|
## Quick start
|
|
84
84
|
|
|
85
|
+
Writing a file:
|
|
86
|
+
|
|
85
87
|
```python
|
|
86
88
|
import tecio
|
|
87
89
|
import numpy as np
|
|
@@ -90,7 +92,7 @@ x = np.linspace(0, 2 * np.pi, 100)
|
|
|
90
92
|
y = np.sin(x)
|
|
91
93
|
|
|
92
94
|
with tecio.open("sine.szplt", "w") as tec:
|
|
93
|
-
tec.
|
|
95
|
+
tec.write_ordered_zone(data=[x, y], variables=["x", "y"])
|
|
94
96
|
```
|
|
95
97
|
|
|
96
98
|
Reading a file:
|
|
@@ -98,10 +100,10 @@ Reading a file:
|
|
|
98
100
|
```python
|
|
99
101
|
with tecio.open("sine.szplt", "r") as tec:
|
|
100
102
|
print(tec.variables) # ['x', 'y']
|
|
101
|
-
x = tec.
|
|
102
|
-
y = tec.
|
|
103
|
+
x = tec.zones[0].variables[0].values
|
|
104
|
+
y = tec.zones[0].variables[1].values
|
|
103
105
|
# or
|
|
104
|
-
x, y = tec.
|
|
106
|
+
x, y = tec.zones[0].get_array(["x", "y"])
|
|
105
107
|
```
|
|
106
108
|
|
|
107
109
|
## API
|
|
@@ -129,7 +131,7 @@ Supported formats:
|
|
|
129
131
|
|
|
130
132
|
## Contributing
|
|
131
133
|
|
|
132
|
-
Contributions are welcome
|
|
134
|
+
Contributions are welcome (see [CONTRIBUTING.md](CONTRIBUTING.md) for details).
|
|
133
135
|
|
|
134
136
|
---
|
|
135
137
|
|
|
@@ -38,6 +38,8 @@ export TECIO_LIB=/path/to/libtecio.dylib # macOS
|
|
|
38
38
|
|
|
39
39
|
## Quick start
|
|
40
40
|
|
|
41
|
+
Writing a file:
|
|
42
|
+
|
|
41
43
|
```python
|
|
42
44
|
import tecio
|
|
43
45
|
import numpy as np
|
|
@@ -46,7 +48,7 @@ x = np.linspace(0, 2 * np.pi, 100)
|
|
|
46
48
|
y = np.sin(x)
|
|
47
49
|
|
|
48
50
|
with tecio.open("sine.szplt", "w") as tec:
|
|
49
|
-
tec.
|
|
51
|
+
tec.write_ordered_zone(data=[x, y], variables=["x", "y"])
|
|
50
52
|
```
|
|
51
53
|
|
|
52
54
|
Reading a file:
|
|
@@ -54,10 +56,10 @@ Reading a file:
|
|
|
54
56
|
```python
|
|
55
57
|
with tecio.open("sine.szplt", "r") as tec:
|
|
56
58
|
print(tec.variables) # ['x', 'y']
|
|
57
|
-
x = tec.
|
|
58
|
-
y = tec.
|
|
59
|
+
x = tec.zones[0].variables[0].values
|
|
60
|
+
y = tec.zones[0].variables[1].values
|
|
59
61
|
# or
|
|
60
|
-
x, y = tec.
|
|
62
|
+
x, y = tec.zones[0].get_array(["x", "y"])
|
|
61
63
|
```
|
|
62
64
|
|
|
63
65
|
## API
|
|
@@ -85,7 +87,7 @@ Supported formats:
|
|
|
85
87
|
|
|
86
88
|
## Contributing
|
|
87
89
|
|
|
88
|
-
Contributions are welcome
|
|
90
|
+
Contributions are welcome (see [CONTRIBUTING.md](CONTRIBUTING.md) for details).
|
|
89
91
|
|
|
90
92
|
---
|
|
91
93
|
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
function f = fecplot(dim, x, y, z, c, node_map, varargin)
|
|
2
|
+
% Filled patch contour for unstructured 2D/3D surface zones
|
|
3
|
+
%
|
|
4
|
+
% Call:
|
|
5
|
+
% h = feplot(dim, x, y, z, c, node_map, ...)
|
|
6
|
+
%
|
|
7
|
+
% Args:
|
|
8
|
+
% dim: 2 or 3
|
|
9
|
+
% x,y[,z]: nodal coordinate column vectors (Nx1)
|
|
10
|
+
% c: contour values; either nodal (Nx1) or cell-centered (Mcells x 1)
|
|
11
|
+
% node_map: M x K integer matrix of node indices per cell (K=3 or 4)
|
|
12
|
+
% varargin: name-value pairs forwarded to patch (e.g. 'EdgeColor','none')
|
|
13
|
+
%
|
|
14
|
+
% Returns:
|
|
15
|
+
% f: handle to the patch object
|
|
16
|
+
%
|
|
17
|
+
% Notes:
|
|
18
|
+
% - If c is nodal, uses 'FaceVertexCData' with 'FaceColor'='interp'
|
|
19
|
+
% - If c is cell-centered, uses 'CData' per-face with 'FaceColor'='flat'
|
|
20
|
+
% - For dim==3, z must be provided and plotting uses 3D patch (viewable with lighting)
|
|
21
|
+
% - node_map may contain NaNs for unequal-sided cells; those faces are handled
|
|
22
|
+
|
|
23
|
+
% Validate dim
|
|
24
|
+
if ~ismember(dim, [2,3])
|
|
25
|
+
error('dim must be 2 or 3');
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
% Ensure column vectors
|
|
29
|
+
x = x(:); y = y(:);
|
|
30
|
+
if dim == 3
|
|
31
|
+
if nargin < 4 || isempty(z)
|
|
32
|
+
error('z must be provided for dim==3');
|
|
33
|
+
end
|
|
34
|
+
z = z(:);
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
% Determine number of nodes and faces
|
|
38
|
+
nNodes = numel(x);
|
|
39
|
+
[nFaces, ~] = size(node_map);
|
|
40
|
+
|
|
41
|
+
% Validate node_map indices
|
|
42
|
+
if any(node_map(:) > nNodes) || any(node_map(:) < 0 & ~isnan(node_map(:)))
|
|
43
|
+
error('node_map contains invalid node indices.');
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
% Prepare vertices matrix
|
|
47
|
+
if dim == 2
|
|
48
|
+
verts = [x, y];
|
|
49
|
+
else
|
|
50
|
+
verts = [x, y, z];
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
% Determine if c is nodal or cell-centered
|
|
54
|
+
c = c(:);
|
|
55
|
+
isNodal = (numel(c) == nNodes);
|
|
56
|
+
isCell = (numel(c) == nFaces);
|
|
57
|
+
if ~(isNodal || isCell)
|
|
58
|
+
error('Length of c must match number of nodes (nodal) or number of faces (cell-centered).');
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
% Clean node_map: replace zeros -> NaN (if any), ensure double
|
|
62
|
+
node_map = double(node_map);
|
|
63
|
+
node_map(node_map==0) = NaN;
|
|
64
|
+
|
|
65
|
+
% If node_map contains NaNs for some cells, patch accepts NaN-separated faces.
|
|
66
|
+
% Create faces in appropriate format: patch accepts face vertex indices matrix.
|
|
67
|
+
faces = node_map;
|
|
68
|
+
|
|
69
|
+
% Build patch arguments
|
|
70
|
+
pArgs = varargin;
|
|
71
|
+
|
|
72
|
+
if isNodal
|
|
73
|
+
% Nodal data: use FaceVertexCData with interpolation
|
|
74
|
+
% Create patch with vertices and faces, supply FaceVertexCData
|
|
75
|
+
% Set FaceColor to 'interp' and EdgeColor as provided or 'none' by default
|
|
76
|
+
if ~any(strcmpi('FaceColor',pArgs))
|
|
77
|
+
pArgs = [{'FaceColor','interp'}, pArgs];
|
|
78
|
+
end
|
|
79
|
+
if ~any(strcmpi('EdgeColor',pArgs))
|
|
80
|
+
pArgs = [{'EdgeColor','none'}, pArgs];
|
|
81
|
+
end
|
|
82
|
+
% Create patch
|
|
83
|
+
f = patch('Vertices', verts, 'Faces', faces, 'FaceVertexCData', c, pArgs{:});
|
|
84
|
+
|
|
85
|
+
else
|
|
86
|
+
% Cell-centered: supply per-face CData and use flat coloring
|
|
87
|
+
if ~any(strcmpi('FaceColor',pArgs))
|
|
88
|
+
pArgs = [{'FaceColor','flat'}, pArgs];
|
|
89
|
+
end
|
|
90
|
+
if ~any(strcmpi('EdgeColor',pArgs))
|
|
91
|
+
pArgs = [{'EdgeColor','none'}, pArgs];
|
|
92
|
+
end
|
|
93
|
+
% patch expects CData as Mx1 or Mx3 color; provide as Mx1
|
|
94
|
+
faceCData = c;
|
|
95
|
+
% Create patch
|
|
96
|
+
f = patch('Vertices', verts, 'Faces', faces, 'CData', faceCData, pArgs{:});
|
|
97
|
+
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
% Set colormap and colorbar behavior consistent with contourf
|
|
101
|
+
if ~any(strcmpi('EdgeColor',pArgs))
|
|
102
|
+
set(f,'EdgeColor','none');
|
|
103
|
+
end
|
|
104
|
+
axis equal
|
|
105
|
+
if dim == 3
|
|
106
|
+
view(3)
|
|
107
|
+
camlight headlight
|
|
108
|
+
lighting gouraud
|
|
109
|
+
end
|
|
110
|
+
colorbar
|
|
111
|
+
end
|
|
@@ -170,6 +170,9 @@ _AXIS_SYNONYMS: dict[str, frozenset[str]] = {
|
|
|
170
170
|
"coordx",
|
|
171
171
|
"xcoord",
|
|
172
172
|
"x_coord",
|
|
173
|
+
"xgrid",
|
|
174
|
+
"x-grid",
|
|
175
|
+
"x_grid",
|
|
173
176
|
}),
|
|
174
177
|
"y": frozenset({
|
|
175
178
|
"y",
|
|
@@ -180,6 +183,9 @@ _AXIS_SYNONYMS: dict[str, frozenset[str]] = {
|
|
|
180
183
|
"coordy",
|
|
181
184
|
"ycoord",
|
|
182
185
|
"y_coord",
|
|
186
|
+
"ygrid",
|
|
187
|
+
"y-grid",
|
|
188
|
+
"y_grid",
|
|
183
189
|
}),
|
|
184
190
|
"z": frozenset({
|
|
185
191
|
"z",
|
|
@@ -190,6 +196,9 @@ _AXIS_SYNONYMS: dict[str, frozenset[str]] = {
|
|
|
190
196
|
"coordz",
|
|
191
197
|
"zcoord",
|
|
192
198
|
"z_coord",
|
|
199
|
+
"zgrid",
|
|
200
|
+
"z-grid",
|
|
201
|
+
"z_grid",
|
|
193
202
|
}),
|
|
194
203
|
}
|
|
195
204
|
|
|
@@ -449,7 +458,7 @@ class TecplotReader(VTKPythonAlgorithmBase):
|
|
|
449
458
|
|
|
450
459
|
self._zone_selection.RemoveAllArrays()
|
|
451
460
|
self._zone_keys.clear()
|
|
452
|
-
for zone in reader.
|
|
461
|
+
for zone in reader.zones:
|
|
453
462
|
title = zone.title or f"Zone {zone.zone_index}"
|
|
454
463
|
key = f"{zone.zone_index}: {title}"
|
|
455
464
|
self._zone_keys[zone.zone_index] = key
|
|
@@ -677,7 +686,7 @@ class TecplotReader(VTKPythonAlgorithmBase):
|
|
|
677
686
|
static/always-present geometry, so they're excluded from the time axis and
|
|
678
687
|
instead included at every requested time (see :meth:`RequestData`).
|
|
679
688
|
"""
|
|
680
|
-
times = {zone.solution_time for zone in reader.
|
|
689
|
+
times = {zone.solution_time for zone in reader.zones if zone.strand_id != 0}
|
|
681
690
|
return sorted(times)
|
|
682
691
|
|
|
683
692
|
@smproperty.doublevector(
|
|
@@ -760,7 +769,7 @@ class TecplotReader(VTKPythonAlgorithmBase):
|
|
|
760
769
|
self._add_variable_aux_field_data(output.GetFieldData(), reader)
|
|
761
770
|
|
|
762
771
|
block_index = 0
|
|
763
|
-
for zone in reader.
|
|
772
|
+
for zone in reader.zones:
|
|
764
773
|
key = self._zone_keys.get(zone.zone_index)
|
|
765
774
|
if key is not None and not self._zone_selection.ArrayIsEnabled(key):
|
|
766
775
|
continue
|
|
@@ -990,7 +999,7 @@ class TecplotReader(VTKPythonAlgorithmBase):
|
|
|
990
999
|
n_points = dataset.GetNumberOfPoints()
|
|
991
1000
|
n_cells = dataset.GetNumberOfCells()
|
|
992
1001
|
|
|
993
|
-
for var in zone.
|
|
1002
|
+
for var in zone.variables:
|
|
994
1003
|
if not self._array_selection.ArrayIsEnabled(var.name):
|
|
995
1004
|
continue
|
|
996
1005
|
values = var.values
|
|
@@ -1039,7 +1048,7 @@ class TecplotReader(VTKPythonAlgorithmBase):
|
|
|
1039
1048
|
if name is None:
|
|
1040
1049
|
flat_components.append(None)
|
|
1041
1050
|
continue
|
|
1042
|
-
var = zone.
|
|
1051
|
+
var = zone.variables[name]
|
|
1043
1052
|
values = var.values
|
|
1044
1053
|
if values is None: # passive, or absent in this specific zone
|
|
1045
1054
|
flat_components.append(None)
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "tecio-python"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.3"
|
|
8
8
|
description = "Python interface for reading and writing Tecplot data files"
|
|
9
9
|
|
|
10
10
|
readme = "README.md"
|
|
@@ -69,6 +69,10 @@ mat = ["scipy"]
|
|
|
69
69
|
include = ["tecio*"]
|
|
70
70
|
exclude = ["archive*", "test*"]
|
|
71
71
|
|
|
72
|
+
[tool.setuptools.data-files]
|
|
73
|
+
"share/plugins/paraview" = ["plugins/paraview/*"]
|
|
74
|
+
"share/plugins/matlab" = ["plugins/matlab/*"]
|
|
75
|
+
|
|
72
76
|
[tool.ruff]
|
|
73
77
|
line-length = 88
|
|
74
78
|
target-version = "py310"
|
|
@@ -109,7 +113,7 @@ python-version = "3.11"
|
|
|
109
113
|
output-format = "concise"
|
|
110
114
|
|
|
111
115
|
[[tool.ty.overrides]]
|
|
112
|
-
include = ["
|
|
116
|
+
include = ["plugins/**"]
|
|
113
117
|
|
|
114
118
|
[tool.ty.overrides.rules]
|
|
115
119
|
unresolved-import = "ignore"
|
|
@@ -9,7 +9,7 @@ from importlib import metadata
|
|
|
9
9
|
try:
|
|
10
10
|
__version__ = metadata.version("tecio")
|
|
11
11
|
except metadata.PackageNotFoundError:
|
|
12
|
-
__version__ = "0.3.
|
|
12
|
+
__version__ = "0.3.3"
|
|
13
13
|
|
|
14
14
|
from . import cli, libtecio
|
|
15
15
|
from ._constants import (
|
|
@@ -28,7 +28,20 @@ from ._constants import (
|
|
|
28
28
|
from ._containers import VariableList, ZoneList
|
|
29
29
|
from ._dat_read import TecplotDatReader
|
|
30
30
|
from ._dat_write import TecplotDatWriter
|
|
31
|
-
from ._io import
|
|
31
|
+
from ._io import (
|
|
32
|
+
AppendReadWrite,
|
|
33
|
+
AppendWrite,
|
|
34
|
+
FileSummary,
|
|
35
|
+
ZoneSummary,
|
|
36
|
+
get_file_type,
|
|
37
|
+
get_num_variables,
|
|
38
|
+
get_num_zones,
|
|
39
|
+
get_title,
|
|
40
|
+
get_variable_list,
|
|
41
|
+
get_zone_list,
|
|
42
|
+
open,
|
|
43
|
+
peek,
|
|
44
|
+
)
|
|
32
45
|
from ._plt_read import TecplotPltReader
|
|
33
46
|
from ._plt_write import TecplotPltWriter
|
|
34
47
|
from ._reader import (
|
|
@@ -82,6 +95,15 @@ del _cls
|
|
|
82
95
|
__all__ = [
|
|
83
96
|
"libtecio",
|
|
84
97
|
"open",
|
|
98
|
+
"peek",
|
|
99
|
+
"get_variable_list",
|
|
100
|
+
"get_zone_list",
|
|
101
|
+
"get_num_zones",
|
|
102
|
+
"get_num_variables",
|
|
103
|
+
"get_title",
|
|
104
|
+
"get_file_type",
|
|
105
|
+
"FileSummary",
|
|
106
|
+
"ZoneSummary",
|
|
85
107
|
"cli",
|
|
86
108
|
"AppendWrite",
|
|
87
109
|
"AppendReadWrite",
|
|
@@ -1,35 +1,35 @@
|
|
|
1
1
|
"""Index- and name-based container types for Tecplot data collections.
|
|
2
2
|
|
|
3
|
-
These containers are shared by the ``tecio`` readers: ``Read.
|
|
4
|
-
:class:`ZoneList` of ``ReadZone`` and ``ReadZone.
|
|
3
|
+
These containers are shared by the ``tecio`` readers: ``Read.zones`` returns a
|
|
4
|
+
:class:`ZoneList` of ``ReadZone`` and ``ReadZone.variables`` returns a
|
|
5
5
|
:class:`VariableList` of ``ReadVariable`` for every supported format (SZL, PLT, DAT).
|
|
6
|
-
They depend only on small structural protocols (``.name`` for variables, ``.
|
|
6
|
+
They depend only on small structural protocols (``.name`` for variables, ``.variables``
|
|
7
7
|
for zones) so they import nothing from either hierarchy and cannot introduce a circular
|
|
8
8
|
dependency.
|
|
9
9
|
|
|
10
10
|
Access model:
|
|
11
11
|
|
|
12
|
-
reader.
|
|
13
|
-
reader.
|
|
14
|
-
reader.
|
|
15
|
-
reader.
|
|
16
|
-
reader.
|
|
17
|
-
reader.
|
|
12
|
+
reader.zones # ZoneList
|
|
13
|
+
reader.zones[0] # ReadZone (element)
|
|
14
|
+
reader.zones[1:4] # ZoneList (sub-collection, same kind)
|
|
15
|
+
reader.zones[0].variables # VariableList
|
|
16
|
+
reader.zones[0].variables["x"] # ReadVariable (object: .values, .is_passive)
|
|
17
|
+
reader.zones[0].variables[2] # ReadVariable (0-based index)
|
|
18
18
|
|
|
19
19
|
Subscripting always returns an element or a sub-collection *of the same kind* (never a
|
|
20
20
|
raw array). The underlying NumPy data is pulled with ``get_array`` on a single zone,
|
|
21
21
|
which mirrors the pandas ``df[...]`` split: a scalar key returns one array, a list of
|
|
22
22
|
names returns a tuple of arrays (for unpacking)::
|
|
23
23
|
|
|
24
|
-
p = reader.
|
|
25
|
-
p = reader.
|
|
26
|
-
x, y, z = reader.
|
|
24
|
+
p = reader.zones[0].get_array("p") # ndarray | None
|
|
25
|
+
p = reader.zones[0].get_array(2) # ndarray | None (0-based index)
|
|
26
|
+
x, y, z = reader.zones[0].get_array(["x", "y", "z"]) # tuple, one per name
|
|
27
27
|
|
|
28
28
|
There is deliberately **no** cross-zone array accessor. To pull one variable across
|
|
29
29
|
many zones (e.g. a transient sequence), iterate explicitly so the outer axis is owned by
|
|
30
30
|
your code, and stack only when you know the result is rectangular::
|
|
31
31
|
|
|
32
|
-
seq = [z.get_array("p") for z in reader.
|
|
32
|
+
seq = [z.get_array("p") for z in reader.zones] # list[ndarray | None]
|
|
33
33
|
stack = np.stack(seq) # only if shapes all match
|
|
34
34
|
|
|
35
35
|
Name lookup is exact and case-sensitive throughout, so distinct variables such
|
|
@@ -78,7 +78,7 @@ class _HasVariableList(Protocol):
|
|
|
78
78
|
"""A zone element exposing a name/index-addressable variable container."""
|
|
79
79
|
|
|
80
80
|
@property
|
|
81
|
-
def
|
|
81
|
+
def variables(self) -> VariableList[Any]: ...
|
|
82
82
|
|
|
83
83
|
|
|
84
84
|
_VarT = TypeVar("_VarT", bound=_HasName)
|
|
@@ -137,7 +137,7 @@ def select_variable_arrays(
|
|
|
137
137
|
class VariableList(Generic[_VarT]):
|
|
138
138
|
"""Read-only sequence of variables with positional *and* named access.
|
|
139
139
|
|
|
140
|
-
Drop-in for the ``list`` previously returned by ``ReadZone.
|
|
140
|
+
Drop-in for the ``list`` previously returned by ``ReadZone.variables``:
|
|
141
141
|
iteration, ``len()``, and integer indexing are unchanged. A string key
|
|
142
142
|
resolves a variable by its exact, case-sensitive name.
|
|
143
143
|
|
|
@@ -208,7 +208,7 @@ class VariableList(Generic[_VarT]):
|
|
|
208
208
|
"""Return the variable names in dataset order."""
|
|
209
209
|
return [var.name for var in self._items]
|
|
210
210
|
|
|
211
|
-
def __repr__(self) -> str:
|
|
211
|
+
def __repr__(self) -> str: # pragma: no cover
|
|
212
212
|
n = len(self._items)
|
|
213
213
|
if n == 0:
|
|
214
214
|
return "VariableList([])"
|
|
@@ -229,16 +229,16 @@ class VariableList(Generic[_VarT]):
|
|
|
229
229
|
class ZoneList(Generic[_ZoneT]):
|
|
230
230
|
"""Read-only sequence of zones: positional access and slicing only.
|
|
231
231
|
|
|
232
|
-
Drop-in for the ``list`` previously returned by ``Read.
|
|
233
|
-
and integer indexing are unchanged. Slicing returns another
|
|
234
|
-
plain ``list``) so navigation composes.
|
|
232
|
+
Drop-in for the ``list`` previously returned by ``Read.zones``: iteration,
|
|
233
|
+
``len()``, and integer indexing are unchanged. Slicing returns another
|
|
234
|
+
:class:`ZoneList` (not a plain ``list``) so navigation composes.
|
|
235
235
|
|
|
236
236
|
This container deliberately exposes **no** data-extraction method. Pulling one
|
|
237
237
|
variable across many zones is an explicit loop over the zones, keeping the outer
|
|
238
238
|
(zone) axis owned by the caller (see the module docs).
|
|
239
239
|
|
|
240
240
|
Args:
|
|
241
|
-
zones: Ordered list of zone elements (each exposing ``.
|
|
241
|
+
zones: Ordered list of zone elements (each exposing ``.variables``).
|
|
242
242
|
"""
|
|
243
243
|
|
|
244
244
|
__slots__ = ("_items",)
|
|
@@ -277,7 +277,7 @@ class ZoneList(Generic[_ZoneT]):
|
|
|
277
277
|
return ZoneList(self._items[key])
|
|
278
278
|
return self._items[key]
|
|
279
279
|
|
|
280
|
-
def __repr__(self) -> str:
|
|
280
|
+
def __repr__(self) -> str: # pragma: no cover
|
|
281
281
|
n = len(self._items)
|
|
282
282
|
if n == 0:
|
|
283
283
|
return "ZoneList([])"
|