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.
- {tecio_python-0.3.2/tecio_python.egg-info → tecio_python-0.4.0}/PKG-INFO +1 -1
- tecio_python-0.4.0/plugins/matlab/contourfe.m +111 -0
- tecio_python-0.4.0/plugins/matlab/tecmat2struct.m +137 -0
- {tecio_python-0.3.2 → tecio_python-0.4.0}/plugins/paraview/TecplotTecioReader.py +9 -0
- tecio_python-0.4.0/plugins/paraview/TecplotTecioWriter.py +651 -0
- {tecio_python-0.3.2 → tecio_python-0.4.0}/pyproject.toml +32 -4
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/__init__.py +29 -3
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_dat_read.py +296 -81
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_dat_write.py +206 -146
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_io.py +338 -73
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_meta.py +6 -6
- tecio_python-0.4.0/tecio/_plt_legacy.py +400 -0
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_plt_read.py +180 -41
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_plt_write.py +195 -125
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_reader.py +82 -37
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_szl_read.py +68 -61
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_szl_write.py +249 -188
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_writer.py +380 -134
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/cli/tec2mat.py +21 -11
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/cli/tecaux.py +77 -93
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/cli/tecdump.py +1 -1
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/cli/tecextract.py +68 -86
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/cli/tecfix.py +45 -64
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/cli/tecmerge.py +343 -66
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/cli/teconvert.py +22 -37
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/cli/tecscale.py +185 -109
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/cli/tecslice.py +75 -100
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/cli/tecstats.py +41 -41
- {tecio_python-0.3.2 → tecio_python-0.4.0/tecio_python.egg-info}/PKG-INFO +1 -1
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio_python.egg-info/SOURCES.txt +5 -0
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tests/test_cli.py +336 -137
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tests/test_io.py +201 -23
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tests/test_libtecio.py +22 -18
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tests/test_read.py +6 -6
- tecio_python-0.4.0/tests/test_read_legacy.py +648 -0
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tests/test_write.py +261 -33
- {tecio_python-0.3.2 → tecio_python-0.4.0}/LICENSE +0 -0
- {tecio_python-0.3.2 → tecio_python-0.4.0}/NOTICE +0 -0
- {tecio_python-0.3.2 → tecio_python-0.4.0}/README.md +0 -0
- {tecio_python-0.3.2 → tecio_python-0.4.0}/setup.cfg +0 -0
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_constants.py +0 -0
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_containers.py +0 -0
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/_utils.py +0 -0
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/cli/__init__.py +0 -0
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio/libtecio.py +0 -0
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio_python.egg-info/dependency_links.txt +0 -0
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio_python.egg-info/entry_points.txt +0 -0
- {tecio_python-0.3.2 → tecio_python-0.4.0}/tecio_python.egg-info/requires.txt +0 -0
- {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
|
+
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
|
|