tecio-python 0.2.0__tar.gz → 0.2.2__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.2.0 → tecio_python-0.2.2}/NOTICE +2 -2
- {tecio_python-0.2.0/tecio_python.egg-info → tecio_python-0.2.2}/PKG-INFO +1 -1
- {tecio_python-0.2.0 → tecio_python-0.2.2}/pyproject.toml +3 -2
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/_containers.py +2 -2
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/_io.py +46 -38
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/_meta.py +4 -4
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/cli/__init__.py +3 -3
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/cli/tec2mat.py +21 -21
- tecio_python-0.2.2/tecio/cli/tecaux.py +971 -0
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/cli/tecdump.py +4 -4
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/cli/tecextract.py +6 -6
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/cli/tecfix.py +4 -4
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/cli/tecmerge.py +12 -12
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/cli/teconvert.py +3 -3
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/cli/tecscale.py +7 -7
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/cli/tecslice.py +12 -12
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/cli/tecstats.py +4 -4
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/dat/__init__.py +1 -1
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/dat/_read.py +33 -21
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/dat/_write.py +22 -22
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/libtecio.py +73 -16
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/plt/_read.py +21 -21
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/plt/_write.py +35 -35
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/szl/_read.py +3 -3
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/szl/_write.py +50 -28
- {tecio_python-0.2.0 → tecio_python-0.2.2/tecio_python.egg-info}/PKG-INFO +1 -1
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio_python.egg-info/SOURCES.txt +1 -0
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio_python.egg-info/entry_points.txt +1 -0
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tests/test_cli.py +669 -19
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tests/test_io.py +1 -1
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tests/test_libtecio.py +1 -1
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tests/test_write.py +82 -3
- {tecio_python-0.2.0 → tecio_python-0.2.2}/LICENSE +0 -0
- {tecio_python-0.2.0 → tecio_python-0.2.2}/README.md +0 -0
- {tecio_python-0.2.0 → tecio_python-0.2.2}/setup.cfg +0 -0
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/__init__.py +0 -0
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/_utils.py +0 -0
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/plt/__init__.py +0 -0
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio/szl/__init__.py +0 -0
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio_python.egg-info/dependency_links.txt +0 -0
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio_python.egg-info/requires.txt +0 -0
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tecio_python.egg-info/top_level.txt +0 -0
- {tecio_python-0.2.0 → tecio_python-0.2.2}/tests/test_read.py +0 -0
|
@@ -2,8 +2,8 @@ tecio-python
|
|
|
2
2
|
Copyright 2025 John Meersman
|
|
3
3
|
|
|
4
4
|
This product requires the Tecplot TecIO library, which is proprietary software
|
|
5
|
-
owned by Tecplot, Inc. and is not covered by this license.
|
|
6
|
-
|
|
5
|
+
owned by Tecplot, Inc. and is not covered by this license. Tecplot and TecIO
|
|
6
|
+
are trademarks of Tecplot, Inc.
|
|
7
7
|
|
|
8
8
|
The license agreement for the TecIO compiled shared libraries is located at:
|
|
9
9
|
lib/tecio_license_agreement.txt
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tecio-python
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
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/
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "tecio-python"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.2"
|
|
8
8
|
description = "Python interface for reading and writing Tecplot data files"
|
|
9
9
|
|
|
10
10
|
readme = "README.md"
|
|
@@ -37,6 +37,8 @@ Issues = "https://github.com/meersman/tecio/issues"
|
|
|
37
37
|
Changelog = "https://github.com/meersman/tecio/blob/main/docs/changelog.md"
|
|
38
38
|
|
|
39
39
|
[project.scripts]
|
|
40
|
+
tec2mat = "tecio.cli.tec2mat:main"
|
|
41
|
+
tecaux = "tecio.cli.tecaux:main"
|
|
40
42
|
teconvert = "tecio.cli.teconvert:main"
|
|
41
43
|
tecdump = "tecio.cli.tecdump:main"
|
|
42
44
|
tecextract = "tecio.cli.tecextract:main"
|
|
@@ -45,7 +47,6 @@ tecmerge = "tecio.cli.tecmerge:main"
|
|
|
45
47
|
tecscale = "tecio.cli.tecscale:main"
|
|
46
48
|
tecslice = "tecio.cli.tecslice:main"
|
|
47
49
|
tecstats = "tecio.cli.tecstats:main"
|
|
48
|
-
tec2mat = "tecio.cli.tec2mat:main"
|
|
49
50
|
|
|
50
51
|
[project.optional-dependencies]
|
|
51
52
|
dev = [
|
|
@@ -138,7 +138,7 @@ class VariableList(Generic[_VarT]):
|
|
|
138
138
|
"""Read-only sequence of variables with positional *and* named access.
|
|
139
139
|
|
|
140
140
|
Drop-in for the ``list`` previously returned by ``ReadZone.variable``:
|
|
141
|
-
iteration, ``len()``, and integer indexing are unchanged.
|
|
141
|
+
iteration, ``len()``, and integer indexing are unchanged. A string key
|
|
142
142
|
resolves a variable by its exact, case-sensitive name.
|
|
143
143
|
|
|
144
144
|
Subscripting returns the variable *object*; use its ``.values`` (or the
|
|
@@ -157,7 +157,7 @@ class VariableList(Generic[_VarT]):
|
|
|
157
157
|
def __init__(self, variables: list[_VarT]) -> None:
|
|
158
158
|
self._items: list[_VarT] = variables
|
|
159
159
|
# Built lazily on first name lookup so purely positional use pays no
|
|
160
|
-
# cost.
|
|
160
|
+
# cost. For SZL this also avoids issuing a C call per variable name
|
|
161
161
|
# until a name is actually requested.
|
|
162
162
|
self._name_index: dict[str, int] | None = None
|
|
163
163
|
|
|
@@ -5,15 +5,15 @@ Supported modes mirror Python's built-in :func:`open`:
|
|
|
5
5
|
====== ============================================================================
|
|
6
6
|
Mode Behaviour
|
|
7
7
|
====== ============================================================================
|
|
8
|
-
``r`` Open existing file for reading.
|
|
8
|
+
``r`` Open existing file for reading. Raises :exc:`FileNotFoundError` if the file
|
|
9
9
|
does not exist.
|
|
10
|
-
``w`` Open file for writing.
|
|
10
|
+
``w`` Open file for writing. Overwrites any existing file.
|
|
11
11
|
``x`` Exclusive creation — open for writing only if the file does **not** already
|
|
12
|
-
exist.
|
|
12
|
+
exist. Raises :exc:`FileExistsError` otherwise.
|
|
13
13
|
``a`` Append — stream all zones from the existing file into a new temporary file,
|
|
14
|
-
then continue writing new zones into that same file.
|
|
14
|
+
then continue writing new zones into that same file. On
|
|
15
15
|
:meth:`~AppendWrite.close` the temporary file atomically replaces the
|
|
16
|
-
original path.
|
|
16
|
+
original path. Returns an :class:`AppendWrite` object whose write API is
|
|
17
17
|
identical to the format's ``Write`` class.
|
|
18
18
|
``a+`` Append-read — same streaming copy as ``a``, but the returned
|
|
19
19
|
:class:`AppendReadWrite` object also exposes the full ``Read`` API populated
|
|
@@ -24,14 +24,14 @@ Supported modes mirror Python's built-in :func:`open`:
|
|
|
24
24
|
Note:
|
|
25
25
|
``"a"`` and ``"a+"`` work by reading the source file in full and re-writing it
|
|
26
26
|
zone-by-zone into a temporary sibling file, then leaving the ``Write`` handle open
|
|
27
|
-
for the caller to add further zones.
|
|
28
|
-
renamed over the original path (POSIX) or replaced (Windows).
|
|
27
|
+
for the caller to add further zones. On close the temporary file is atomically
|
|
28
|
+
renamed over the original path (POSIX) or replaced (Windows). This is the only safe
|
|
29
29
|
approach because PLT and SZL are sequential binary formats with no in-place editing
|
|
30
30
|
capability.
|
|
31
31
|
|
|
32
32
|
Note:
|
|
33
33
|
FEPOLYGON and FEPOLYHEDRON zones are not copied during append operations because the
|
|
34
|
-
``Write`` API does not yet expose a poly-zone writer.
|
|
34
|
+
``Write`` API does not yet expose a poly-zone writer. A :exc:`NotImplementedError`
|
|
35
35
|
is raised if such zones are encountered in the source file.
|
|
36
36
|
"""
|
|
37
37
|
|
|
@@ -120,7 +120,9 @@ def _copy_zones(reader: szl.Read | plt.Read, writer: szl.Write | plt.Write) -> N
|
|
|
120
120
|
"""Stream all zones from *reader* into the open *writer*.
|
|
121
121
|
|
|
122
122
|
Each zone is copied variable-by-variable at its original data type and value
|
|
123
|
-
location.
|
|
123
|
+
location. Both variable sharing (``var_sharing``) and FE connectivity sharing
|
|
124
|
+
(``con_sharing``) are preserved: a zone that shares its connectivity is
|
|
125
|
+
re-emitted as a share rather than a duplicated node map.
|
|
124
126
|
|
|
125
127
|
Args:
|
|
126
128
|
reader: An already-opened ``Read`` instance.
|
|
@@ -148,7 +150,7 @@ def _copy_zones(reader: szl.Read | plt.Read, writer: szl.Write | plt.Write) -> N
|
|
|
148
150
|
|
|
149
151
|
for var in zone.variable:
|
|
150
152
|
passive_vars.append(var.is_passive())
|
|
151
|
-
sv = var.shared_zone # None or
|
|
153
|
+
sv = var.shared_zone # None, or the 1-based source-zone index shared from
|
|
152
154
|
# Write API expects 0 = no sharing, positive = 1-based zone source.
|
|
153
155
|
var_sharing.append((sv) if sv is not None else 0)
|
|
154
156
|
value_locations.append(var.value_location)
|
|
@@ -187,10 +189,16 @@ def _copy_zones(reader: szl.Read | plt.Read, writer: szl.Write | plt.Write) -> N
|
|
|
187
189
|
if zt == ZoneType.ORDERED:
|
|
188
190
|
writer.write_ijk_zone(data=active_data, **common_kw)
|
|
189
191
|
else:
|
|
192
|
+
# Forward connectivity sharing: when shared, pass ``con_sharing`` and omit
|
|
193
|
+
# the node map so the writer derives the node/cell counts from the source
|
|
194
|
+
# zone; otherwise write this zone's own node map.
|
|
195
|
+
cv = zone.shared_connectivity # None, or 1-based source-zone index
|
|
196
|
+
con_sharing = cv if cv is not None else 0
|
|
190
197
|
writer.write_fe_zone(
|
|
191
198
|
zone_type=zt,
|
|
192
199
|
data=active_data,
|
|
193
|
-
node_map=zone.node_map,
|
|
200
|
+
node_map=None if con_sharing else zone.node_map,
|
|
201
|
+
con_sharing=con_sharing,
|
|
194
202
|
**common_kw,
|
|
195
203
|
)
|
|
196
204
|
|
|
@@ -203,9 +211,9 @@ def _copy_zones(reader: szl.Read | plt.Read, writer: szl.Write | plt.Write) -> N
|
|
|
203
211
|
class AppendWrite:
|
|
204
212
|
"""Write handle returned by :func:`tecio.open` with ``mode='a'``.
|
|
205
213
|
|
|
206
|
-
Appends new zones to an existing Tecplot file.
|
|
214
|
+
Appends new zones to an existing Tecplot file. Internally the existing file is
|
|
207
215
|
stream-copied zone-by-zone into a temporary sibling file, and the write handle is
|
|
208
|
-
left open past all copied zones so new zones can be appended.
|
|
216
|
+
left open past all copied zones so new zones can be appended. On :meth:`close` (or
|
|
209
217
|
context-manager exit) the temporary file is atomically renamed over the original
|
|
210
218
|
path — a POSIX rename on Unix, :func:`Path.replace` on Windows.
|
|
211
219
|
|
|
@@ -217,7 +225,7 @@ class AppendWrite:
|
|
|
217
225
|
|
|
218
226
|
Note:
|
|
219
227
|
FEPOLYGON and FEPOLYHEDRON zones cannot be copied because the Write API does not
|
|
220
|
-
yet expose a poly-zone writer.
|
|
228
|
+
yet expose a poly-zone writer. A :exc:`NotImplementedError` is raised during
|
|
221
229
|
``open()`` if such zones are present in the source file.
|
|
222
230
|
|
|
223
231
|
Example:
|
|
@@ -262,32 +270,32 @@ class AppendWrite:
|
|
|
262
270
|
"""Append a structured IJK-ordered zone.
|
|
263
271
|
|
|
264
272
|
Delegates to the underlying format writer's ``write_ijk_zone``
|
|
265
|
-
(e.g. :meth:`tecio.szl.Write.write_ijk_zone`).
|
|
273
|
+
(e.g. :meth:`tecio.szl.Write.write_ijk_zone`). All parameters from that method
|
|
266
274
|
are accepted here with one exception: ``variables`` is not meaningful because
|
|
267
275
|
the variable list is fixed at open time from the existing file.
|
|
268
276
|
|
|
269
277
|
Args:
|
|
270
278
|
data (Sequence[ndarray]): One NumPy array per **active** variable
|
|
271
|
-
(non-passive, non-shared).
|
|
272
|
-
automatically.
|
|
273
|
-
title (str | None): Zone title.
|
|
279
|
+
(non-passive, non-shared). Shape ``(imax[, jmax[, kmax]])`` is inferred
|
|
280
|
+
automatically. Fortran (column-major) order is assumed.
|
|
281
|
+
title (str | None): Zone title. Defaults to ``"IJK_Zone_{n}"``.
|
|
274
282
|
value_locations (Sequence[ValueLocation] | None): Per-variable
|
|
275
|
-
:class:`~tecio.libtecio.ValueLocation` for active variables.
|
|
283
|
+
:class:`~tecio.libtecio.ValueLocation` for active variables. Defaults
|
|
276
284
|
to all :attr:`~tecio.libtecio.ValueLocation.NODAL`.
|
|
277
285
|
passive_vars (Sequence[bool | int] | None): Per-variable passive flag for
|
|
278
286
|
the **full** variable list (length = total variables in the file, not
|
|
279
|
-
just active ones).
|
|
287
|
+
just active ones). Defaults to all ``False``.
|
|
280
288
|
var_sharing (Sequence[int] | None): Per-variable share-from zone index
|
|
281
289
|
(1-based, counting all zones including those copied from the original
|
|
282
|
-
file). ``0`` = no sharing.
|
|
290
|
+
file). ``0`` = no sharing. Defaults to all ``0``. Sharing grid
|
|
283
291
|
coordinates from zone 1 is a common pattern for transient data to avoid
|
|
284
292
|
duplicating large arrays.
|
|
285
|
-
solution_time (float): Solution time for transient data.
|
|
293
|
+
solution_time (float): Solution time for transient data. Defaults to
|
|
286
294
|
``0.0``.
|
|
287
|
-
strand_id (int): Strand ID grouping related time steps.
|
|
288
|
-
strand ID animate together in Tecplot 360.
|
|
295
|
+
strand_id (int): Strand ID grouping related time steps. Zones with the same
|
|
296
|
+
strand ID animate together in Tecplot 360. Defaults to ``0`` (static).
|
|
289
297
|
aux (dict[str, str] | None): Zone-level auxiliary data as ``{name: value}``
|
|
290
|
-
pairs.
|
|
298
|
+
pairs. Defaults to ``None``.
|
|
291
299
|
|
|
292
300
|
Example:
|
|
293
301
|
Append a time step, sharing the grid from zone 1:
|
|
@@ -313,7 +321,7 @@ class AppendWrite:
|
|
|
313
321
|
FEPOLYGON and FEPOLYHEDRON are not supported.
|
|
314
322
|
|
|
315
323
|
Args:
|
|
316
|
-
zone_type (ZoneType): Element topology.
|
|
324
|
+
zone_type (ZoneType): Element topology. One of:
|
|
317
325
|
:attr:`~tecio.libtecio.ZoneType.FELINESEG`,
|
|
318
326
|
:attr:`~tecio.libtecio.ZoneType.FETRIANGLE`,
|
|
319
327
|
:attr:`~tecio.libtecio.ZoneType.FEQUADRILATERAL`,
|
|
@@ -341,7 +349,7 @@ class AppendWrite:
|
|
|
341
349
|
face_nbr_mode (FaceNeighborMode | None): Face-neighbor mode. Defaults to
|
|
342
350
|
:attr:`~tecio.libtecio.FaceNeighborMode.LOCAL_ONE_TO_ONE`. Ignored when
|
|
343
351
|
``face_neighbors`` is ``None``.
|
|
344
|
-
solution_time (float): Solution time.
|
|
352
|
+
solution_time (float): Solution time. Defaults to ``0.0``.
|
|
345
353
|
strand_id (int): Strand ID. Defaults to ``0``.
|
|
346
354
|
aux (dict[str, str] | None): Zone-level auxiliary data.
|
|
347
355
|
|
|
@@ -403,7 +411,7 @@ class AppendReadWrite(AppendWrite):
|
|
|
403
411
|
"""Read + write handle returned by :func:`tecio.open` with ``mode='a+'``.
|
|
404
412
|
|
|
405
413
|
Inherits all write methods from :class:`AppendWrite` and additionally exposes the
|
|
406
|
-
full read interface populated from the **original** file.
|
|
414
|
+
full read interface populated from the **original** file. The read data reflects
|
|
407
415
|
the file as it existed before any new zones were appended — zones written during the
|
|
408
416
|
current session are not visible via :attr:`zone` until the file is closed and
|
|
409
417
|
re-opened.
|
|
@@ -664,7 +672,7 @@ def open(
|
|
|
664
672
|
"""Open a Tecplot file for reading, writing, or appending.
|
|
665
673
|
|
|
666
674
|
Selects the correct format handler from the file extension and returns the
|
|
667
|
-
appropriate reader or writer.
|
|
675
|
+
appropriate reader or writer. All handles are context managers.
|
|
668
676
|
|
|
669
677
|
Args:
|
|
670
678
|
path (str | os.PathLike): File path. Extension determines the format handler:
|
|
@@ -679,9 +687,9 @@ def open(
|
|
|
679
687
|
- ``'w'`` -- Open Tecplot file for writing, truncating the file first.
|
|
680
688
|
- ``'x'`` -- Open Tecplot file for exclusive creation, failing if the file
|
|
681
689
|
already exists.
|
|
682
|
-
- ``'a'`` -- Append new zones to an existing file.
|
|
690
|
+
- ``'a'`` -- Append new zones to an existing file. The file is
|
|
683
691
|
stream-copied to a temporary file; on close the temporary atomically
|
|
684
|
-
replaces the original.
|
|
692
|
+
replaces the original. Raises :exc:`FileNotFoundError` if the file does
|
|
685
693
|
not exist (use ``'w'`` to create a new file).
|
|
686
694
|
- ``'a+'`` -- Same as ``'a'`` but the returned handle also exposes the full
|
|
687
695
|
read API populated from the original file.
|
|
@@ -709,9 +717,9 @@ def open(
|
|
|
709
717
|
- Dataset title string embedded in the file header.
|
|
710
718
|
* - ``variables``
|
|
711
719
|
- ``None``
|
|
712
|
-
- Variable name list.
|
|
720
|
+
- Variable name list. For SZL and PLT this may be deferred to the first
|
|
713
721
|
:meth:`~tecio.szl.Write.write_ijk_zone` or
|
|
714
|
-
:meth:`~tecio.szl.Write.write_fe_zone` call.
|
|
722
|
+
:meth:`~tecio.szl.Write.write_fe_zone` call. Required at open time for
|
|
715
723
|
DAT.
|
|
716
724
|
* - ``file_type``
|
|
717
725
|
- ``FileType.FULL``
|
|
@@ -721,7 +729,7 @@ def open(
|
|
|
721
729
|
|
|
722
730
|
Keyword Args (modes ``'a'``, ``'a+'``):
|
|
723
731
|
``title``, ``variables``, and ``file_type`` default to the values read from the
|
|
724
|
-
existing file.
|
|
732
|
+
existing file. In most cases you should **not** pass these — they are
|
|
725
733
|
documented here for completeness.
|
|
726
734
|
|
|
727
735
|
.. list-table::
|
|
@@ -733,7 +741,7 @@ def open(
|
|
|
733
741
|
- Description
|
|
734
742
|
* - ``title``
|
|
735
743
|
- From file
|
|
736
|
-
- Override the dataset title in the output file.
|
|
744
|
+
- Override the dataset title in the output file. Rarely needed — the
|
|
737
745
|
existing title is preserved by default.
|
|
738
746
|
* - ``variables``
|
|
739
747
|
- From file
|
|
@@ -742,7 +750,7 @@ def open(
|
|
|
742
750
|
and any new zones.
|
|
743
751
|
* - ``file_type``
|
|
744
752
|
- From file
|
|
745
|
-
- Override the file type.
|
|
753
|
+
- Override the file type. Rarely needed.
|
|
746
754
|
|
|
747
755
|
Returns:
|
|
748
756
|
- ``'r'`` → :class:`tecio.szl.Read`, :class:`tecio.plt.Read`, or
|
|
@@ -785,7 +793,7 @@ def open(
|
|
|
785
793
|
|
|
786
794
|
if ext not in _HANDLERS:
|
|
787
795
|
raise ValueError(
|
|
788
|
-
f"Unsupported file extension: '{ext}'.
|
|
796
|
+
f"Unsupported file extension: '{ext}'. Supported: {sorted(_HANDLERS)}"
|
|
789
797
|
)
|
|
790
798
|
|
|
791
799
|
if mode == "r":
|
|
@@ -807,5 +815,5 @@ def open(
|
|
|
807
815
|
|
|
808
816
|
else:
|
|
809
817
|
raise ValueError(
|
|
810
|
-
f"Unrecognised mode '{mode}'.
|
|
818
|
+
f"Unrecognised mode '{mode}'. Supported modes: 'r', 'w', 'x', 'a', 'a+'"
|
|
811
819
|
)
|
|
@@ -2,7 +2,7 @@ r"""Structural metadata records shared by the Tecplot file writers.
|
|
|
2
2
|
|
|
3
3
|
The writer for each output format -- SZL (``.szplt``), PLT (``.plt``), and ASCII DAT
|
|
4
4
|
(``.dat``) -- keeps a running, in-memory description of what it has committed to disk:
|
|
5
|
-
the dataset header, auxiliary-data counts, and one record per zone.
|
|
5
|
+
the dataset header, auxiliary-data counts, and one record per zone. Defining that
|
|
6
6
|
description once here lets all three writers share a single representation instead of
|
|
7
7
|
each maintaining ad-hoc bookkeeping.
|
|
8
8
|
|
|
@@ -16,10 +16,10 @@ Design notes:
|
|
|
16
16
|
never the variable data arrays, so the record stays cheap in memory even for files
|
|
17
17
|
with many zones.
|
|
18
18
|
* ``slots=True`` removes the per-instance ``__dict__``, and immutable tuple fields
|
|
19
|
-
keep the per-variable lists compact.
|
|
19
|
+
keep the per-variable lists compact. A :class:`ZoneMeta` is a write-once snapshot
|
|
20
20
|
and is therefore ``frozen``; :class:`WriterMeta` is mutable because it grows as
|
|
21
21
|
zones are written.
|
|
22
|
-
* Enum types are imported only under :data:`typing.TYPE_CHECKING`.
|
|
22
|
+
* Enum types are imported only under :data:`typing.TYPE_CHECKING`. With ``from
|
|
23
23
|
__future__ import annotations`` the annotations are never evaluated at runtime,
|
|
24
24
|
which keeps this module free of any import cycle with :mod:`tecio.libtecio`.
|
|
25
25
|
"""
|
|
@@ -104,7 +104,7 @@ class WriterMeta:
|
|
|
104
104
|
"""Running record of everything a writer has committed to a file.
|
|
105
105
|
|
|
106
106
|
Populated incrementally as the file header, auxiliary data, and zones are
|
|
107
|
-
written, so it always reflects the current on-disk state.
|
|
107
|
+
written, so it always reflects the current on-disk state. It is the single
|
|
108
108
|
source of truth for cross-zone validation (for example, resolving the shape
|
|
109
109
|
of a shared variable) and is suitable for summarising the writer state.
|
|
110
110
|
|
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
Binary data formats such as ``.plt`` and ``.szplt`` are opaque to standard shell
|
|
4
4
|
utilities, meaning any inspection or manipulation of their contents typically requires
|
|
5
|
-
either dedicated post-processing software or a non-trivial amount of scripting.
|
|
5
|
+
either dedicated post-processing software or a non-trivial amount of scripting. For
|
|
6
6
|
routine tasks encountered in CFD and related workflows, verifying zone extents,
|
|
7
7
|
extracting a subset of variables, computing summary statistics, this overhead is
|
|
8
8
|
disproportionate to the complexity of the task itself.
|
|
9
9
|
|
|
10
10
|
The tools collected here address this by exposing the most common file-level operations
|
|
11
11
|
as console scripts, executable directly from the terminal and composable with standard
|
|
12
|
-
shell pipelines.
|
|
12
|
+
shell pipelines. Each tool is intentionally narrow in scope: it does one thing and
|
|
13
13
|
surfaces its result without requiring the user to open a GUI or write any Python.
|
|
14
14
|
|
|
15
15
|
All scripts are installed automatically alongside the :mod:`tecio` package and are
|
|
16
|
-
available on ``PATH`` immediately after installation.
|
|
16
|
+
available on ``PATH`` immediately after installation. Every tool accepts ``--help`` for
|
|
17
17
|
a full description of its arguments.
|
|
18
18
|
|
|
19
19
|
"""
|
|
@@ -2,10 +2,10 @@ r"""Convert a Tecplot data file to a MATLAB ``.mat`` file.
|
|
|
2
2
|
|
|
3
3
|
MATLAB is widely used for engineering analysis and post-processing, but it cannot read
|
|
4
4
|
Tecplot binary files directly, and the Tecplot ASCII format is awkward to parse on the
|
|
5
|
-
MATLAB side.
|
|
5
|
+
MATLAB side. Moving data across normally requires a Tecplot license or a hand-written
|
|
6
6
|
reader. ``tec2mat`` bridges this gap by reading any supported Tecplot format
|
|
7
7
|
(``.szplt``, ``.plt``, or ``.dat``) and writing a single MATLAB ``.mat`` file via
|
|
8
|
-
:func:`scipy.io.savemat`.
|
|
8
|
+
:func:`scipy.io.savemat`. Each input file maps to exactly one output file
|
|
9
9
|
(``flow.szplt`` -> ``flow.mat``): every zone becomes a named struct, every variable is
|
|
10
10
|
preserved at its native precision, and connectivity and metadata are retained so the
|
|
11
11
|
dataset can be reconstructed in MATLAB without a Tecplot installation.
|
|
@@ -22,26 +22,26 @@ dataset can be reconstructed in MATLAB without a Tecplot installation.
|
|
|
22
22
|
|
|
23
23
|
:Options:
|
|
24
24
|
``-o PATH``, ``--output PATH``
|
|
25
|
-
Output file path.
|
|
25
|
+
Output file path. Defaults to the input file stem with a ``.mat`` extension in
|
|
26
26
|
the same directory as the input file.
|
|
27
27
|
|
|
28
28
|
``-f``, ``--force``
|
|
29
|
-
Overwrite the output file if it already exists.
|
|
29
|
+
Overwrite the output file if it already exists. Without this flag the command
|
|
30
30
|
exits with an error rather than silently clobbering an existing file.
|
|
31
31
|
|
|
32
32
|
``-c``, ``--compress``
|
|
33
33
|
Compress the variable arrays inside the ``.mat`` file (passes
|
|
34
|
-
``do_compression=True`` to :func:`scipy.io.savemat`).
|
|
34
|
+
``do_compression=True`` to :func:`scipy.io.savemat`). Reduces file size at the
|
|
35
35
|
cost of some write/read time.
|
|
36
36
|
|
|
37
37
|
``--oned-as {column,row}``
|
|
38
38
|
Orientation for one-dimensional arrays (finite-element nodal/cell vectors and
|
|
39
39
|
the per-variable metadata arrays) in the ``.mat`` file. ``column`` (the
|
|
40
|
-
default) writes ``N x 1`` column vectors; ``row`` writes ``1 x N``.
|
|
40
|
+
default) writes ``N x 1`` column vectors; ``row`` writes ``1 x N``. Has no
|
|
41
41
|
effect on the two- and three-dimensional arrays of ordered zones.
|
|
42
42
|
|
|
43
43
|
:Returns:
|
|
44
|
-
A single MATLAB ``.mat`` file written to the output path.
|
|
44
|
+
A single MATLAB ``.mat`` file written to the output path. Exit code is ``0`` on
|
|
45
45
|
success and non-zero if the input file cannot be read or the output file already
|
|
46
46
|
exists and ``--force`` is not set.
|
|
47
47
|
|
|
@@ -75,14 +75,14 @@ Output structure:
|
|
|
75
75
|
if this zone shares its connectivity
|
|
76
76
|
|
|
77
77
|
Variable arrays are stored at their on-disk NumPy dtype, so single/double/integer
|
|
78
|
-
precision is preserved.
|
|
78
|
+
precision is preserved. The real variable names are kept only in ``info.var_names``
|
|
79
79
|
because they are frequently not valid MATLAB field names (e.g. ``"X [ft]"``); the
|
|
80
80
|
per-zone data is addressed by 1-based index (``var_1`` ...) instead.
|
|
81
81
|
|
|
82
82
|
Passive and shared variables carry no data: their ``var_<k>`` field is an empty
|
|
83
|
-
matrix ``[]``.
|
|
83
|
+
matrix ``[]``. A shared variable is therefore never duplicated on disk -- the data
|
|
84
84
|
lives in its source zone and ``var_shared_from`` records where, so the MATLAB user
|
|
85
|
-
can dereference it (see the examples below).
|
|
85
|
+
can dereference it (see the examples below). Shared FE connectivity follows the
|
|
86
86
|
same convention: a zone sharing its node map has no ``node_map`` field at all, only
|
|
87
87
|
``node_map_shared_from``.
|
|
88
88
|
|
|
@@ -111,7 +111,7 @@ Examples:
|
|
|
111
111
|
x = d.zone_1.var_1; % first variable of the first zone
|
|
112
112
|
p = d.zone_1.var_3; % third variable
|
|
113
113
|
|
|
114
|
-
Variables shared from another zone are stored once.
|
|
114
|
+
Variables shared from another zone are stored once. Resolve them with a small
|
|
115
115
|
helper that follows ``var_shared_from``::
|
|
116
116
|
|
|
117
117
|
function v = tecvar(d, zoneIdx, varIdx)
|
|
@@ -142,17 +142,17 @@ See Also:
|
|
|
142
142
|
converting it.
|
|
143
143
|
|
|
144
144
|
Note:
|
|
145
|
-
``tec2mat`` requires SciPy (:mod:`scipy.io`).
|
|
145
|
+
``tec2mat`` requires SciPy (:mod:`scipy.io`). Install it with ``pip install
|
|
146
146
|
scipy`` if it is not already available.
|
|
147
147
|
|
|
148
148
|
Note:
|
|
149
149
|
:func:`scipy.io.savemat` writes the MAT version 5 format and assembles the whole
|
|
150
|
-
file in memory before writing.
|
|
150
|
+
file in memory before writing. Very large datasets are therefore limited by
|
|
151
151
|
available memory and by the ~4 GB-per-variable ceiling of the MAT v5 format.
|
|
152
152
|
|
|
153
153
|
Note:
|
|
154
154
|
FEPOLYGON and FEPOLYHEDRON zones are written with their variable data, but their
|
|
155
|
-
face-based connectivity cannot be read and the ``node_map`` field is omitted.
|
|
155
|
+
face-based connectivity cannot be read and the ``node_map`` field is omitted. A
|
|
156
156
|
warning is printed for each such zone.
|
|
157
157
|
"""
|
|
158
158
|
|
|
@@ -191,7 +191,7 @@ def _parse_args(argv: Sequence[str] | None = None) -> argparse.Namespace:
|
|
|
191
191
|
prog="tec2mat",
|
|
192
192
|
description=(
|
|
193
193
|
# -|-------------------|---------------------------------------------|
|
|
194
|
-
"Convert a Tecplot file to a MATLAB .mat file.
|
|
194
|
+
"Convert a Tecplot file to a MATLAB .mat file. Each input file maps\n"
|
|
195
195
|
"to one output file, with every zone stored as a named struct."
|
|
196
196
|
),
|
|
197
197
|
epilog=(
|
|
@@ -219,7 +219,7 @@ def _parse_args(argv: Sequence[str] | None = None) -> argparse.Namespace:
|
|
|
219
219
|
default=None,
|
|
220
220
|
metavar="PATH",
|
|
221
221
|
help=(
|
|
222
|
-
"Output file path.
|
|
222
|
+
"Output file path. Defaults to the input file stem with a "
|
|
223
223
|
".mat extension in the same directory as the input."
|
|
224
224
|
),
|
|
225
225
|
)
|
|
@@ -247,7 +247,7 @@ def _parse_args(argv: Sequence[str] | None = None) -> argparse.Namespace:
|
|
|
247
247
|
help=(
|
|
248
248
|
"Orientation for 1-D arrays (FE vectors and per-variable "
|
|
249
249
|
"metadata). 'column' (default) writes Nx1 vectors; 'row' "
|
|
250
|
-
"writes 1xN.
|
|
250
|
+
"writes 1xN. Ordered-zone arrays are unaffected."
|
|
251
251
|
),
|
|
252
252
|
)
|
|
253
253
|
return parser.parse_args(argv)
|
|
@@ -263,7 +263,7 @@ def _build_info_dict(reader: Any) -> dict[str, Any]:
|
|
|
263
263
|
|
|
264
264
|
The returned dict is stored by :func:`scipy.io.savemat` as a MATLAB struct named
|
|
265
265
|
``info``, holding the dataset title, file type, zone/variable counts, and the
|
|
266
|
-
ordered list of real variable names as a MATLAB cell array.
|
|
266
|
+
ordered list of real variable names as a MATLAB cell array. The real names are
|
|
267
267
|
kept here as metadata because they are frequently not valid MATLAB field names
|
|
268
268
|
(e.g. ``"X [ft]"``); the per-zone arrays are addressed by 1-based index instead.
|
|
269
269
|
|
|
@@ -288,12 +288,12 @@ def _build_info_dict(reader: Any) -> dict[str, Any]:
|
|
|
288
288
|
def _zone_to_dict(zone: Any, num_vars: int) -> dict[str, Any]:
|
|
289
289
|
"""Build one zone's struct for the output file.
|
|
290
290
|
|
|
291
|
-
The returned dict becomes a MATLAB struct (named ``zone_<n>`` by the caller).
|
|
291
|
+
The returned dict becomes a MATLAB struct (named ``zone_<n>`` by the caller). It
|
|
292
292
|
contains the zone metadata, one ``var_<k>`` field per dataset variable (1-based),
|
|
293
293
|
and, for simple finite-element zones, the ``node_map`` connectivity array.
|
|
294
294
|
|
|
295
295
|
Each ``var_<k>`` holds the variable's data array at its native NumPy dtype, so the
|
|
296
|
-
on-disk precision is preserved on the MATLAB side.
|
|
296
|
+
on-disk precision is preserved on the MATLAB side. Passive and shared variables
|
|
297
297
|
carry no data: their ``var_<k>`` field is an empty matrix ``[]`` and the
|
|
298
298
|
per-variable metadata records how to interpret it:
|
|
299
299
|
|
|
@@ -377,7 +377,7 @@ def _zone_to_dict(zone: Any, num_vars: int) -> dict[str, Any]:
|
|
|
377
377
|
d["var_dtypes"] = np.array(dtypes, dtype=object)
|
|
378
378
|
d["var_shared_from"] = shared_from
|
|
379
379
|
|
|
380
|
-
# Connectivity for simple FE zones only.
|
|
380
|
+
# Connectivity for simple FE zones only. Ordered zones have no node map, and poly
|
|
381
381
|
# zones expose none through the readers.
|
|
382
382
|
#
|
|
383
383
|
# A zone that shares connectivity is handled the same way as a shared variable
|