tecio-python 0.3.2__tar.gz → 0.4.0__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.
Files changed (49) hide show
  1. {tecio_python-0.3.2/tecio_python.egg-info → tecio_python-0.4.0}/PKG-INFO +1 -1
  2. tecio_python-0.4.0/plugins/matlab/contourfe.m +111 -0
  3. tecio_python-0.4.0/plugins/matlab/tecmat2struct.m +137 -0
  4. {tecio_python-0.3.2 → tecio_python-0.4.0}/plugins/paraview/TecplotTecioReader.py +9 -0
  5. tecio_python-0.4.0/plugins/paraview/TecplotTecioWriter.py +651 -0
  6. {tecio_python-0.3.2 → tecio_python-0.4.0}/pyproject.toml +32 -4
  7. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/__init__.py +29 -3
  8. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_dat_read.py +296 -81
  9. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_dat_write.py +206 -146
  10. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_io.py +338 -73
  11. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_meta.py +6 -6
  12. tecio_python-0.4.0/tecio/_plt_legacy.py +400 -0
  13. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_plt_read.py +180 -41
  14. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_plt_write.py +195 -125
  15. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_reader.py +82 -37
  16. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_szl_read.py +68 -61
  17. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_szl_write.py +249 -188
  18. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_writer.py +380 -134
  19. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/cli/tec2mat.py +21 -11
  20. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/cli/tecaux.py +77 -93
  21. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/cli/tecdump.py +1 -1
  22. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/cli/tecextract.py +68 -86
  23. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/cli/tecfix.py +45 -64
  24. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/cli/tecmerge.py +343 -66
  25. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/cli/teconvert.py +22 -37
  26. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/cli/tecscale.py +185 -109
  27. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/cli/tecslice.py +75 -100
  28. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/cli/tecstats.py +41 -41
  29. {tecio_python-0.3.2 → tecio_python-0.4.0/tecio_python.egg-info}/PKG-INFO +1 -1
  30. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio_python.egg-info/SOURCES.txt +5 -0
  31. {tecio_python-0.3.2 → tecio_python-0.4.0}/tests/test_cli.py +336 -137
  32. {tecio_python-0.3.2 → tecio_python-0.4.0}/tests/test_io.py +201 -23
  33. {tecio_python-0.3.2 → tecio_python-0.4.0}/tests/test_libtecio.py +22 -18
  34. {tecio_python-0.3.2 → tecio_python-0.4.0}/tests/test_read.py +6 -6
  35. tecio_python-0.4.0/tests/test_read_legacy.py +648 -0
  36. {tecio_python-0.3.2 → tecio_python-0.4.0}/tests/test_write.py +261 -33
  37. {tecio_python-0.3.2 → tecio_python-0.4.0}/LICENSE +0 -0
  38. {tecio_python-0.3.2 → tecio_python-0.4.0}/NOTICE +0 -0
  39. {tecio_python-0.3.2 → tecio_python-0.4.0}/README.md +0 -0
  40. {tecio_python-0.3.2 → tecio_python-0.4.0}/setup.cfg +0 -0
  41. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_constants.py +0 -0
  42. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_containers.py +0 -0
  43. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_utils.py +0 -0
  44. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/cli/__init__.py +0 -0
  45. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/libtecio.py +0 -0
  46. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio_python.egg-info/dependency_links.txt +0 -0
  47. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio_python.egg-info/entry_points.txt +0 -0
  48. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio_python.egg-info/requires.txt +0 -0
  49. {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio_python.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tecio-python
3
- Version: 0.3.2
3
+ Version: 0.4.0
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/
@@ -0,0 +1,111 @@
1
+ function f = contourfe(dim, x, y, z, c, node_map, varargin)
2
+ % Filled patch contour for unstructured 2D/3D surface zones
3
+ %
4
+ % Call:
5
+ % h = contourfe(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
@@ -0,0 +1,137 @@
1
+ function zones = tecmat2struct(d)
2
+ % Reshape a loaded tec2mat .mat struct into a struct array of zones with
3
+ % dataset variables accessible by name.
4
+ %
5
+ % tec2mat outputs (info, zone_1, zone_2, ...) and variables by position
6
+ % (var_1, var_2, ...) because valid Tecplot variable names can include
7
+ % characters that are not valid MATLAB identifiers (e.g. "X [ft]"). When the
8
+ % variable names are known to be valid identifiers, this function lets you
9
+ % reformat the structures such that variables can be accessed by name, e.g.
10
+ % plot(zones(1).x, zones(1).pressure) instead of plot(zone_1.var_1,
11
+ % zone_1.var_3).
12
+ %
13
+ % Call:
14
+ % zones = tecmat2struct(d)
15
+ %
16
+ % Args:
17
+ % d: struct returned by load() on a tec2mat .mat file, i.e. the struct
18
+ % has fields info, zone_1, zone_2, ...
19
+ %
20
+ % Returns:
21
+ % zones: 1 x info.num_zones struct array. Every element has the same
22
+ % fields, so this is a normal MATLAB struct array (zones(i),
23
+ % [zones.pressure], etc. all work):
24
+ % .title, .zone_type, .solution_time, .strand_id
25
+ % .I, .J, .K ordered zones; [] for FE zones
26
+ % .num_nodes, .num_elements FE zones; [] for ordered zones
27
+ % .node_map FE zones (resolved through
28
+ % node_map_shared_from if the zone
29
+ % shares connectivity); [] otherwise
30
+ % .face_neighbor_mode, .num_face_connections, .face_connections
31
+ % FE zones with face-neighbor data;
32
+ % '' / [] / [] otherwise
33
+ % .<variable name> one field per dataset variable
34
+ % whose real name is a valid MATLAB
35
+ % identifier (see isvarname). Passive
36
+ % in a zone -> []. Shared -> resolved
37
+ % to the source zone's data, so every
38
+ % zones(i) is self-contained.
39
+ %
40
+ % Notes:
41
+ % - A variable name that is not a valid MATLAB identifier is skipped with a
42
+ % warning; it remains accessible the original way, via zone_<n>.var_<k> and
43
+ % info.var_names{k}.
44
+ % - Shared variables/connectivity are branched (copied from referenced zone's
45
+ % data into every zone that shares it). This can create large memory
46
+ % usage for files whose zones heavily share a static grid across many time
47
+ % steps.
48
+ %
49
+ % Example:
50
+ % d = load('flow.mat');
51
+ % zones = tecmat2struct(d);
52
+ % plot(zones(1).x, zones(1).pressure);
53
+
54
+ if ~isfield(d, 'info')
55
+ error('tecmat2struct:badInput', ...
56
+ 'Input does not look like a tec2mat output struct (no ''info'' field).');
57
+ end
58
+
59
+ numZones = double(d.info.num_zones);
60
+ numVars = double(d.info.num_vars);
61
+ varNames = d.info.var_names;
62
+
63
+ % Reserved field names already used for zone metadata (variable names that
64
+ % collides with a reserved metadat name is skipped).
65
+ reserved = {'title', 'zone_type', 'solution_time', 'strand_id', ...
66
+ 'I', 'J', 'K', 'num_nodes', 'num_elements', 'node_map', ...
67
+ 'face_neighbor_mode', 'num_face_connections', 'face_connections'};
68
+
69
+ % Validate variable names up once so every zone gets the exact same set of
70
+ % variable fields in the same order.
71
+ validName = false(1, numVars);
72
+ for vi = 1:numVars
73
+ name = strtrim(char(varNames{vi}));
74
+ if ~isvarname(name)
75
+ warning('tecmat2struct:invalidName', ...
76
+ ['Variable %d (''%s'') is not a valid MATLAB identifier; skipping. ' ...
77
+ 'Access it via zone_<n>.var_%d instead.'], vi, name, vi);
78
+ elseif any(strcmp(name, reserved))
79
+ warning('tecmat2struct:reservedName', ...
80
+ ['Variable %d (''%s'') collides with a zone metadata field; skipping. ' ...
81
+ 'Access it via zone_<n>.var_%d instead.'], vi, name, vi);
82
+ else
83
+ validName(vi) = true;
84
+ end
85
+ end
86
+ varIdx = find(validName);
87
+
88
+ for zi = numZones:-1:1 % descending so the first iteration preallocates zones(1)
89
+ zsrc = d.(sprintf('zone_%d', zi));
90
+
91
+ out = struct( ...
92
+ 'title', zsrc.title, ...
93
+ 'zone_type', zsrc.zone_type, ...
94
+ 'solution_time', zsrc.solution_time, ...
95
+ 'strand_id', zsrc.strand_id, ...
96
+ 'I', [], 'J', [], 'K', [], ...
97
+ 'num_nodes', [], 'num_elements', [], 'node_map', [], ...
98
+ 'face_neighbor_mode', '', 'num_face_connections', [], ...
99
+ 'face_connections', []);
100
+
101
+ if isfield(zsrc, 'I')
102
+ out.I = zsrc.I;
103
+ out.J = zsrc.J;
104
+ out.K = zsrc.K;
105
+ end
106
+ if isfield(zsrc, 'num_nodes')
107
+ out.num_nodes = zsrc.num_nodes;
108
+ out.num_elements = zsrc.num_elements;
109
+ end
110
+ if isfield(zsrc, 'node_map')
111
+ out.node_map = zsrc.node_map;
112
+ elseif isfield(zsrc, 'node_map_shared_from')
113
+ srcZone = d.(sprintf('zone_%d', zsrc.node_map_shared_from));
114
+ out.node_map = srcZone.node_map;
115
+ end
116
+ if isfield(zsrc, 'face_neighbor_mode')
117
+ out.face_neighbor_mode = zsrc.face_neighbor_mode;
118
+ out.num_face_connections = zsrc.num_face_connections;
119
+ out.face_connections = zsrc.face_connections;
120
+ end
121
+
122
+ for vi = varIdx
123
+ name = strtrim(char(varNames{vi}));
124
+ status = zsrc.var_status{vi};
125
+ if strcmp(status, 'shared')
126
+ srcIdx = zsrc.var_shared_from(vi);
127
+ srcZone = d.(sprintf('zone_%d', srcIdx));
128
+ out.(name) = srcZone.(sprintf('var_%d', vi));
129
+ else
130
+ % 'active' carries real data; 'passive' is already [].
131
+ out.(name) = zsrc.(sprintf('var_%d', vi));
132
+ end
133
+ end
134
+
135
+ zones(zi) = out;
136
+ end
137
+ 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