pytecplot 1.5.2__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.
- pytecplot-1.5.2.dist-info/LICENSE.html +77 -0
- pytecplot-1.5.2.dist-info/METADATA +508 -0
- pytecplot-1.5.2.dist-info/RECORD +97 -0
- pytecplot-1.5.2.dist-info/WHEEL +5 -0
- pytecplot-1.5.2.dist-info/top_level.txt +1 -0
- tecplot/__init__.py +94 -0
- tecplot/annotation/__init__.py +7 -0
- tecplot/annotation/annotation.py +223 -0
- tecplot/annotation/geometry.py +369 -0
- tecplot/annotation/georeference.py +33 -0
- tecplot/annotation/image.py +185 -0
- tecplot/annotation/iter.py +105 -0
- tecplot/annotation/polyline.py +381 -0
- tecplot/annotation/text.py +744 -0
- tecplot/constant.py +401 -0
- tecplot/data/__init__.py +34 -0
- tecplot/data/array.py +645 -0
- tecplot/data/create.py +1 -0
- tecplot/data/dataset.py +1809 -0
- tecplot/data/extract.py +544 -0
- tecplot/data/face_neighbors.py +494 -0
- tecplot/data/facemap.py +814 -0
- tecplot/data/load.py +2075 -0
- tecplot/data/nodemap.py +577 -0
- tecplot/data/operate.py +928 -0
- tecplot/data/query.py +334 -0
- tecplot/data/save.py +343 -0
- tecplot/data/variable.py +280 -0
- tecplot/data/zone.py +841 -0
- tecplot/exception.py +201 -0
- tecplot/export/__init__.py +13 -0
- tecplot/export/animation.py +521 -0
- tecplot/export/export_setup.py +318 -0
- tecplot/export/image.py +577 -0
- tecplot/export/print_setup.py +218 -0
- tecplot/export/time_animation.py +607 -0
- tecplot/extension/__init__.py +14 -0
- tecplot/extension/ipython.py +68 -0
- tecplot/layout/__init__.py +20 -0
- tecplot/layout/frame.py +1285 -0
- tecplot/layout/layout.py +488 -0
- tecplot/layout/page.py +541 -0
- tecplot/legend/__init__.py +4 -0
- tecplot/legend/contour_legend.py +516 -0
- tecplot/legend/legend.py +141 -0
- tecplot/legend/line_legend.py +66 -0
- tecplot/legend/rgb_coloring_legend.py +291 -0
- tecplot/legend/scatter_legend.py +136 -0
- tecplot/macro.py +339 -0
- tecplot/plot/__init__.py +62 -0
- tecplot/plot/axes.py +881 -0
- tecplot/plot/axis.py +1350 -0
- tecplot/plot/blanking.py +584 -0
- tecplot/plot/contour.py +1302 -0
- tecplot/plot/effects.py +162 -0
- tecplot/plot/fieldmap.py +2159 -0
- tecplot/plot/grid.py +758 -0
- tecplot/plot/isosurface.py +1167 -0
- tecplot/plot/labels.py +338 -0
- tecplot/plot/linemap.py +1905 -0
- tecplot/plot/linking.py +489 -0
- tecplot/plot/plot.py +1791 -0
- tecplot/plot/rgb_coloring.py +281 -0
- tecplot/plot/scatter.py +396 -0
- tecplot/plot/slice.py +1544 -0
- tecplot/plot/streamtrace.py +1949 -0
- tecplot/plot/symbol.py +567 -0
- tecplot/plot/ticks.py +666 -0
- tecplot/plot/title.py +380 -0
- tecplot/plot/vector.py +679 -0
- tecplot/plot/view.py +868 -0
- tecplot/session/__init__.py +112 -0
- tecplot/session/aux_data.py +276 -0
- tecplot/session/config.py +92 -0
- tecplot/session/session.py +425 -0
- tecplot/session/state_changed.py +225 -0
- tecplot/session/style.py +504 -0
- tecplot/tecutil/__init__.py +16 -0
- tecplot/tecutil/arglist.py +230 -0
- tecplot/tecutil/captured_output.py +177 -0
- tecplot/tecutil/constant.py +1312 -0
- tecplot/tecutil/index_set.py +118 -0
- tecplot/tecutil/lock.py +36 -0
- tecplot/tecutil/message_pb2.py +39 -0
- tecplot/tecutil/preamble.py +54 -0
- tecplot/tecutil/stringlist.py +114 -0
- tecplot/tecutil/sv.py +1662 -0
- tecplot/tecutil/tecutil.py +12402 -0
- tecplot/tecutil/tecutil_client.py +627 -0
- tecplot/tecutil/tecutil_connector.py +937 -0
- tecplot/tecutil/tecutil_rpc.py +6845 -0
- tecplot/tecutil/util.py +332 -0
- tecplot/text/__init__.py +3 -0
- tecplot/text/font.py +224 -0
- tecplot/text/label_format.py +374 -0
- tecplot/text/textbox.py +106 -0
- tecplot/version.py +41 -0
tecplot/data/dataset.py
ADDED
|
@@ -0,0 +1,1809 @@
|
|
|
1
|
+
import collections
|
|
2
|
+
import ctypes
|
|
3
|
+
import fnmatch
|
|
4
|
+
import itertools as it
|
|
5
|
+
import logging
|
|
6
|
+
import re
|
|
7
|
+
import warnings
|
|
8
|
+
|
|
9
|
+
from collections.abc import Iterable
|
|
10
|
+
from functools import reduce
|
|
11
|
+
from keyword import iskeyword
|
|
12
|
+
from textwrap import dedent, TextWrapper
|
|
13
|
+
|
|
14
|
+
from ..tecutil import _tecutil, _tecutil_connector
|
|
15
|
+
from ..constant import *
|
|
16
|
+
from ..exception import *
|
|
17
|
+
from .. import layout, macro, session, tecutil, version
|
|
18
|
+
from ..tecutil import (IndexSet, ListWrapper, StringList,
|
|
19
|
+
flatten_args, lock, lock_attributes, sv)
|
|
20
|
+
from .variable import Variable
|
|
21
|
+
from .zone import ClassicFEZone, OrderedZone, PolyFEZone, Zone
|
|
22
|
+
|
|
23
|
+
log = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@lock_attributes
|
|
27
|
+
class SolutionTimeClustering(object):
|
|
28
|
+
"""Settings for controlling solution time clustering of solution times.
|
|
29
|
+
|
|
30
|
+
By default, a dataset's zones solution times are organized into time steps
|
|
31
|
+
with the assumption that they are distributed linearly, and are grouped
|
|
32
|
+
together if they are within the following solution time tolerance::
|
|
33
|
+
|
|
34
|
+
(tolerance_factor)*(max_time - min_time) + absolute_tolerance
|
|
35
|
+
|
|
36
|
+
Where by default the tolerance_factor is 1.0e-6 and the absolute_tolerance
|
|
37
|
+
is 0.0.
|
|
38
|
+
"""
|
|
39
|
+
def __init__(self, dataset):
|
|
40
|
+
self.dataset = dataset
|
|
41
|
+
|
|
42
|
+
def __str__(self):
|
|
43
|
+
"""Brief string representation.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
`str`: Brief representation of this `SolutionTimeClustering`,
|
|
47
|
+
showing the options controlling how solution times are grouped into
|
|
48
|
+
time steps.
|
|
49
|
+
|
|
50
|
+
Example::
|
|
51
|
+
|
|
52
|
+
>>> dataset = frame.dataset
|
|
53
|
+
>>> print(dataset.solution_time_clustering)
|
|
54
|
+
SolutionTimeClustering
|
|
55
|
+
time_scaling: TimeScaling.Linear
|
|
56
|
+
absolute_tolerance: 0.0
|
|
57
|
+
tolerance_factor: 1.0e-6
|
|
58
|
+
"""
|
|
59
|
+
fmt = dedent('''\
|
|
60
|
+
SolutionTimeClustering:
|
|
61
|
+
time_scaling: {}
|
|
62
|
+
absolute_tolerance: {}
|
|
63
|
+
tolerance_factor: {}''')
|
|
64
|
+
return fmt.format(self.time_scaling, self.absolute_tolerance,
|
|
65
|
+
self.tolerance_factor)
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
@lock()
|
|
69
|
+
def time_scaling(self):
|
|
70
|
+
"""`TimeScaling`: Scaling used to cluster zones by their solution times.
|
|
71
|
+
|
|
72
|
+
Identifies if the dataset's zone solution times are distributed linearly
|
|
73
|
+
or logarithmically. (Default: `TimeScaling.Linear`)
|
|
74
|
+
|
|
75
|
+
Possible values: `TimeScaling.Linear`, `TimeScaling.Logarithmic`.
|
|
76
|
+
|
|
77
|
+
Example usage::
|
|
78
|
+
|
|
79
|
+
>>> from tecplot.constant import TimeScaling
|
|
80
|
+
>>> dataset.solution_time_clustering.time_scaling = \\
|
|
81
|
+
... TimeScaling.Logarithmic
|
|
82
|
+
|
|
83
|
+
.. versionadded:: 2021.2
|
|
84
|
+
Solution time clustering requires Tecplot 360 2021 R2 or later.
|
|
85
|
+
"""
|
|
86
|
+
return _tecutil.SolutionTimeGetTimeScaling(self.dataset.uid)
|
|
87
|
+
|
|
88
|
+
@time_scaling.setter
|
|
89
|
+
@lock()
|
|
90
|
+
def time_scaling(self, time_scaling):
|
|
91
|
+
value = TimeScaling(time_scaling).value
|
|
92
|
+
if not _tecutil.SolutionTimeSetTimeScaling(self.dataset.uid, value):
|
|
93
|
+
raise TecplotSystemError()
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
@lock()
|
|
97
|
+
def absolute_tolerance(self):
|
|
98
|
+
"""`float`: Absolute tolerance used to cluster zones by their solution times.
|
|
99
|
+
|
|
100
|
+
Absolute tolerance applied to each solution time when clustering with
|
|
101
|
+
nearby times. (Default: 0.0)
|
|
102
|
+
|
|
103
|
+
Example usage::
|
|
104
|
+
|
|
105
|
+
>>> dataset.solution_time_clustering.absolute_tolerance = 0.0025
|
|
106
|
+
|
|
107
|
+
.. versionadded:: 2021.2
|
|
108
|
+
Solution time clustering requires Tecplot 360 2021 R2 or later.
|
|
109
|
+
"""
|
|
110
|
+
return _tecutil.SolutionTimeGetAbsoluteTolerance(self.dataset.uid)
|
|
111
|
+
|
|
112
|
+
@absolute_tolerance.setter
|
|
113
|
+
@lock()
|
|
114
|
+
def absolute_tolerance(self, absolute_tolerance):
|
|
115
|
+
uid = self.dataset.uid
|
|
116
|
+
value = float(absolute_tolerance)
|
|
117
|
+
if not _tecutil.SolutionTimeSetAbsoluteTolerance(uid, value):
|
|
118
|
+
raise TecplotSystemError()
|
|
119
|
+
|
|
120
|
+
@property
|
|
121
|
+
@lock()
|
|
122
|
+
def tolerance_factor(self):
|
|
123
|
+
"""`float`: Tolerance factor used to cluster zones by solution times.
|
|
124
|
+
|
|
125
|
+
Tolerance factor, which is multiplied by the overall solution time
|
|
126
|
+
delta and applied to each solution time when clustering nearby times.
|
|
127
|
+
(Default: 1.0e-6)
|
|
128
|
+
|
|
129
|
+
Example usage::
|
|
130
|
+
|
|
131
|
+
>>> dataset.solution_time_clustering.tolerance_factor = 1.0e-4
|
|
132
|
+
|
|
133
|
+
.. versionadded:: 2021.2
|
|
134
|
+
Solution time clustering requires Tecplot 360 2021 R2 or later.
|
|
135
|
+
"""
|
|
136
|
+
return _tecutil.SolutionTimeGetToleranceFactor(self.dataset.uid)
|
|
137
|
+
|
|
138
|
+
@tolerance_factor.setter
|
|
139
|
+
@lock()
|
|
140
|
+
def tolerance_factor(self, tolerance_factor):
|
|
141
|
+
uid = self.dataset.uid
|
|
142
|
+
value = float(tolerance_factor)
|
|
143
|
+
if not _tecutil.SolutionTimeSetToleranceFactor(uid, value):
|
|
144
|
+
raise TecplotSystemError()
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
@lock_attributes
|
|
148
|
+
class Dataset(object):
|
|
149
|
+
"""Table of `Arrays <Array>` identified by `Zone <data_access>` and `Variable`.
|
|
150
|
+
|
|
151
|
+
This is the primary data container within the Tecplot Engine. A `Dataset <tecplot.data.Dataset>`
|
|
152
|
+
can be shared among several `Frames <layout.Frame>`, though any particular
|
|
153
|
+
`Dataset <tecplot.data.Dataset>` object will have a handle to at least one of them. Any
|
|
154
|
+
modification of a shared `Dataset <tecplot.data.Dataset>` will be reflected in all `Frames
|
|
155
|
+
<layout.Frame>` that use it.
|
|
156
|
+
|
|
157
|
+
Though a `Dataset <tecplot.data.Dataset>` is usually attached to a `Frame <layout.Frame>` and the plot style
|
|
158
|
+
associated with that, it can be thought of as independent from any style or
|
|
159
|
+
plotting representation. Each `Dataset <tecplot.data.Dataset>` consists of a list of `Variables
|
|
160
|
+
<Variable>` which are used by one or more of a list of `Zones
|
|
161
|
+
<data_access>`. The `Variable` determines the data type, while the `Zone
|
|
162
|
+
<data_access>` determines the layout such as shape and ordered vs
|
|
163
|
+
unordered.
|
|
164
|
+
|
|
165
|
+
The actual data are found at the intersection of a `Zone <data_access>` and
|
|
166
|
+
`Variable` and the resulting object is an `Array`. The data array can be
|
|
167
|
+
obtained using either path::
|
|
168
|
+
|
|
169
|
+
>>> # These two lines obtain the same object "x"
|
|
170
|
+
>>> x = dataset.zone('My Zone').values('X')
|
|
171
|
+
>>> x = dataset.variable('X').values('My Zone')
|
|
172
|
+
|
|
173
|
+
A `Dataset <tecplot.data.Dataset>` is the object returned by most data-loading operations in
|
|
174
|
+
|PyTecplot|::
|
|
175
|
+
|
|
176
|
+
>>> dataset = tecplot.data.load_tecplot('my_data.plt')
|
|
177
|
+
|
|
178
|
+
Under `Dataset <tecplot.data.Dataset>`, there are a number methods to create and delete `Zones
|
|
179
|
+
<data_access>` and `variables <Variable>`.
|
|
180
|
+
"""
|
|
181
|
+
def __init__(self, uid, frame):
|
|
182
|
+
self.uid = uid
|
|
183
|
+
self.frame = frame
|
|
184
|
+
|
|
185
|
+
def __repr__(self):
|
|
186
|
+
"""Executable string representation.
|
|
187
|
+
|
|
188
|
+
Returns:
|
|
189
|
+
`str`: Internal representation of this `Dataset <tecplot.data.Dataset>`.
|
|
190
|
+
|
|
191
|
+
The string returned can be executed to generate a
|
|
192
|
+
clone of this `Dataset <tecplot.data.Dataset>` object::
|
|
193
|
+
|
|
194
|
+
>>> dataset = frame.dataset
|
|
195
|
+
>>> print(repr(dataset))
|
|
196
|
+
Dataset(uid=21, frame=Frame(uid=11, page=Page(uid=1)))
|
|
197
|
+
>>> exec('dataset_clone = '+repr(dataset))
|
|
198
|
+
>>> dataset_clone
|
|
199
|
+
Dataset(uid=21, frame=Frame(uid=11, page=Page(uid=1)))
|
|
200
|
+
>>> dataset == dataset_clone
|
|
201
|
+
True
|
|
202
|
+
"""
|
|
203
|
+
return 'Dataset(uid={uid}, frame={frame})'.format(
|
|
204
|
+
uid=self.uid, frame=repr(self.frame))
|
|
205
|
+
|
|
206
|
+
def __str__(self):
|
|
207
|
+
"""Brief string representation.
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
`str`: Brief representation of this `Dataset <tecplot.data.Dataset>`, showing
|
|
211
|
+
`Zones <data_access>` and `Variables <Variable>`.
|
|
212
|
+
|
|
213
|
+
Example::
|
|
214
|
+
|
|
215
|
+
>>> dataset = frame.dataset
|
|
216
|
+
>>> print(dataset)
|
|
217
|
+
Dataset: 'My Dataset'
|
|
218
|
+
Zones: 'Rectangular zone'
|
|
219
|
+
Variables: 'x', 'y', 'z'
|
|
220
|
+
"""
|
|
221
|
+
fmt = dedent('''\
|
|
222
|
+
Dataset: '{}'
|
|
223
|
+
Zones: {}
|
|
224
|
+
Variables: {}''')
|
|
225
|
+
maxwidth = 79
|
|
226
|
+
wrapper = ListWrapper(initial_width=maxwidth - len(' Zones: '),
|
|
227
|
+
subsequent_indent=' ',
|
|
228
|
+
subsequent_width=maxwidth)
|
|
229
|
+
zones = wrapper.fill(self.zone_names)
|
|
230
|
+
wrapper.initial_width = maxwidth - len(' Variables: ')
|
|
231
|
+
variables = wrapper.fill(self.variable_names)
|
|
232
|
+
return fmt.format(self.title, zones, variables)
|
|
233
|
+
|
|
234
|
+
def __eq__(self, other):
|
|
235
|
+
"""Checks for equality in the |Tecplot Engine|.
|
|
236
|
+
|
|
237
|
+
Returns:
|
|
238
|
+
`bool`: `True` if the unique ID numbers are the same for both
|
|
239
|
+
`Datasets <tecplot.data.Dataset>`.
|
|
240
|
+
|
|
241
|
+
This can be useful for determining if two `Frames <layout.Frame>`
|
|
242
|
+
are holding on to the same `Dataset <tecplot.data.Dataset>`::
|
|
243
|
+
|
|
244
|
+
>>> frame1.dataset == frame2.dataset
|
|
245
|
+
True
|
|
246
|
+
"""
|
|
247
|
+
return self.uid == other.uid
|
|
248
|
+
|
|
249
|
+
def __ne__(self, other):
|
|
250
|
+
return not self.__eq__(other)
|
|
251
|
+
|
|
252
|
+
def __contains__(self, obj):
|
|
253
|
+
if obj.dataset == self:
|
|
254
|
+
if isinstance(obj, Variable) and obj == self.variable(obj.index):
|
|
255
|
+
return True
|
|
256
|
+
elif isinstance(obj, Zone) and obj == self.zone(obj.index):
|
|
257
|
+
return True
|
|
258
|
+
return False
|
|
259
|
+
|
|
260
|
+
@property
|
|
261
|
+
def aux_data(self):
|
|
262
|
+
"""Auxiliary data for this dataset.
|
|
263
|
+
|
|
264
|
+
Returns:
|
|
265
|
+
`AuxData`
|
|
266
|
+
|
|
267
|
+
This is the auxiliary data attached to the dataset. Such data is
|
|
268
|
+
written to the layout file by default and can be retrieved later.
|
|
269
|
+
Example usage::
|
|
270
|
+
|
|
271
|
+
>>> frame = tp.active_frame()
|
|
272
|
+
>>> aux = frame.dataset.aux_data
|
|
273
|
+
>>> aux['Result'] = '3.14159'
|
|
274
|
+
>>> print(aux['Result'])
|
|
275
|
+
3.14159
|
|
276
|
+
"""
|
|
277
|
+
return session.AuxData(self.frame, AuxDataObjectType.Dataset)
|
|
278
|
+
|
|
279
|
+
@property
|
|
280
|
+
def title(self):
|
|
281
|
+
"""`str`: Title of this `Dataset <tecplot.data.Dataset>`.
|
|
282
|
+
|
|
283
|
+
Example usage::
|
|
284
|
+
|
|
285
|
+
>>> dataset.title = 'My Data'
|
|
286
|
+
|
|
287
|
+
.. versionchanged:: 2017.3 of Tecplot 360
|
|
288
|
+
The dataset title property requires Tecplot 360 2017 R3 or later.
|
|
289
|
+
"""
|
|
290
|
+
success, title, _, _ = _tecutil.DataSetGetInfoByUniqueID(self.uid)
|
|
291
|
+
if not success:
|
|
292
|
+
raise TecplotSystemError()
|
|
293
|
+
return title
|
|
294
|
+
|
|
295
|
+
@title.setter
|
|
296
|
+
@lock()
|
|
297
|
+
def title(self, title):
|
|
298
|
+
if not _tecutil.DataSetSetTitleByUniqueID(self.uid, title):
|
|
299
|
+
raise TecplotSystemError()
|
|
300
|
+
|
|
301
|
+
@property
|
|
302
|
+
def solution_time_clustering(self):
|
|
303
|
+
"""`SolutionTimeClustering`: Solution time clustering options.
|
|
304
|
+
|
|
305
|
+
Example usage::
|
|
306
|
+
|
|
307
|
+
>>> from tecplot.constant import TimeScaling
|
|
308
|
+
>>> dataset.solution_time_clustering.time_scaling = \\
|
|
309
|
+
... TimeScaling.Logarithmic
|
|
310
|
+
|
|
311
|
+
.. versionadded:: 2021.2
|
|
312
|
+
Solution time clustering requires Tecplot 360 2021 R2 or later.
|
|
313
|
+
"""
|
|
314
|
+
if __debug__:
|
|
315
|
+
reqver = (2021, 2)
|
|
316
|
+
if version.sdk_version_info < reqver:
|
|
317
|
+
msg = 'Solution time clustering options require 2021 R2 or later.'
|
|
318
|
+
raise TecplotOutOfDateEngineError(reqver, msg)
|
|
319
|
+
return SolutionTimeClustering(self)
|
|
320
|
+
|
|
321
|
+
@property
|
|
322
|
+
def num_zones(self):
|
|
323
|
+
"""`int`: Number of `Zones <data_access>` in this `Dataset <tecplot.data.Dataset>`.
|
|
324
|
+
|
|
325
|
+
This count includes disabled zones which were skipped when loading the
|
|
326
|
+
data. Example usage::
|
|
327
|
+
|
|
328
|
+
>>> for i in range(dataset.num_zones):
|
|
329
|
+
... zone = dataset.zone(i)
|
|
330
|
+
"""
|
|
331
|
+
return _tecutil.DataSetGetNumZonesByUniqueID(self.uid)
|
|
332
|
+
|
|
333
|
+
def zone(self, pattern):
|
|
334
|
+
"""Returns `Zone <data_access>` by index or string pattern.
|
|
335
|
+
|
|
336
|
+
Parameters:
|
|
337
|
+
pattern (`int`, `str` or `re.Pattern <re.compile>`): Zero-based
|
|
338
|
+
index, case-insensitive `glob-style pattern string
|
|
339
|
+
<fnmatch.fnmatch>` or a compiled `regex pattern instance
|
|
340
|
+
<re.compile>` used to match the zones by name. A negative index
|
|
341
|
+
is interpreted as counting from the end of the available zones.
|
|
342
|
+
|
|
343
|
+
Returns:
|
|
344
|
+
`OrderedZone`, `ClassicFEZone` or `PolyFEZone` depending on the
|
|
345
|
+
zone type, `None` no matching `zone <data_access>` name was found.
|
|
346
|
+
|
|
347
|
+
Raises:
|
|
348
|
+
`TecplotIndexError`
|
|
349
|
+
|
|
350
|
+
.. note::
|
|
351
|
+
|
|
352
|
+
A `Dataset <tecplot.data.Dataset>` can contain `zones <data_access>` with identical names
|
|
353
|
+
and only the first match found is returned. This is not guaranteed
|
|
354
|
+
to be deterministic and care should be taken to have only
|
|
355
|
+
`zones <data_access>` with unique names when this feature is used.
|
|
356
|
+
|
|
357
|
+
The `Zone.name <OrderedZone.name>` attribute is used to match the
|
|
358
|
+
*pattern* to the desired `Zone <data_access>` though this is not
|
|
359
|
+
necessarily unique::
|
|
360
|
+
|
|
361
|
+
>>> ds = frame.dataset
|
|
362
|
+
>>> print(ds)
|
|
363
|
+
Dataset:
|
|
364
|
+
Zones: ['Rectangular zone']
|
|
365
|
+
Variables: ['x', 'y', 'z']
|
|
366
|
+
>>> rectzone = ds.zone('Rectangular zone')
|
|
367
|
+
>>> rectzone == ds.zone(0)
|
|
368
|
+
True
|
|
369
|
+
|
|
370
|
+
.. warning:: **Zone and variable ordering may change between releases**
|
|
371
|
+
|
|
372
|
+
Due to possible changes in data loaders or data formats over time,
|
|
373
|
+
the ordering of zones and variables may be different between
|
|
374
|
+
versions of Tecplot 360. Therefore it is recommended to always
|
|
375
|
+
reference zones and variables **by name** instead of by index.
|
|
376
|
+
"""
|
|
377
|
+
if isinstance(pattern, Zone):
|
|
378
|
+
return pattern
|
|
379
|
+
_dispatch = {
|
|
380
|
+
ZoneType.Ordered: OrderedZone,
|
|
381
|
+
ZoneType.FELineSeg: ClassicFEZone,
|
|
382
|
+
ZoneType.FETriangle: ClassicFEZone,
|
|
383
|
+
ZoneType.FEQuad: ClassicFEZone,
|
|
384
|
+
ZoneType.FETetra: ClassicFEZone,
|
|
385
|
+
ZoneType.FEBrick: ClassicFEZone,
|
|
386
|
+
ZoneType.FEPolygon: PolyFEZone,
|
|
387
|
+
ZoneType.FEPolyhedron: PolyFEZone}
|
|
388
|
+
pattern_type = getattr(re, 'Pattern', getattr(re, '_pattern_type', None))
|
|
389
|
+
if isinstance(pattern, (str, pattern_type)):
|
|
390
|
+
try:
|
|
391
|
+
return next(self.zones(pattern))
|
|
392
|
+
except StopIteration:
|
|
393
|
+
pass
|
|
394
|
+
else:
|
|
395
|
+
if pattern < 0:
|
|
396
|
+
pattern += self.num_zones
|
|
397
|
+
try:
|
|
398
|
+
if __debug__:
|
|
399
|
+
# ensure zone is enabled
|
|
400
|
+
if not _tecutil.ZoneIsEnabledByDataSetID(self.uid, pattern + 1):
|
|
401
|
+
msg = 'zone {} is not enabled'.format(pattern)
|
|
402
|
+
raise TecplotIndexError(msg)
|
|
403
|
+
uid = _tecutil.ZoneGetUniqueIDByDataSetID(self.uid,
|
|
404
|
+
pattern + 1)
|
|
405
|
+
ztype = _tecutil.ZoneGetTypeByDataSetID(self.uid, pattern + 1)
|
|
406
|
+
return _dispatch[ztype](uid, self)
|
|
407
|
+
except (TecplotSystemError, TecplotLogicError) as e:
|
|
408
|
+
raise TecplotIndexError(str(e))
|
|
409
|
+
|
|
410
|
+
@property
|
|
411
|
+
def _zone_indices(self):
|
|
412
|
+
"""Zero-based indices of all enabled zones in the dataset."""
|
|
413
|
+
success, ptr = _tecutil.ZoneGetEnabledByDataSetID(self.uid)
|
|
414
|
+
if not success:
|
|
415
|
+
raise TecplotSystemError()
|
|
416
|
+
indices = ctypes.cast(ptr, IndexSet)
|
|
417
|
+
try:
|
|
418
|
+
return list(indices)
|
|
419
|
+
finally:
|
|
420
|
+
indices.dealloc()
|
|
421
|
+
|
|
422
|
+
@property
|
|
423
|
+
def _zone_uids(self):
|
|
424
|
+
"""Unique IDs for all enabled zones in the dataset."""
|
|
425
|
+
try:
|
|
426
|
+
success, nuids, uids_ptr = _tecutil.ZoneGetUniqueIDsByDataSetID(self.uid)
|
|
427
|
+
if not success:
|
|
428
|
+
raise TecplotSystemError()
|
|
429
|
+
try:
|
|
430
|
+
return uids_ptr[:nuids]
|
|
431
|
+
finally:
|
|
432
|
+
if not _tecutil_connector.connected:
|
|
433
|
+
_tecutil.ArrayDealloc(uids_ptr)
|
|
434
|
+
except (AttributeError, TecplotSystemError) as err:
|
|
435
|
+
try:
|
|
436
|
+
return [_tecutil.ZoneGetUniqueIDByDataSetID(self.uid, zone_index + 1)
|
|
437
|
+
for zone_index in self._zone_indices]
|
|
438
|
+
except:
|
|
439
|
+
raise err
|
|
440
|
+
|
|
441
|
+
@property
|
|
442
|
+
def _zone_types(self):
|
|
443
|
+
"""`ZoneType`s of all enabled zones in the dataset."""
|
|
444
|
+
try:
|
|
445
|
+
success, ntypes, types_ptr = _tecutil.ZoneGetTypesByDataSetID(self.uid)
|
|
446
|
+
if not success:
|
|
447
|
+
raise TecplotSystemError()
|
|
448
|
+
try:
|
|
449
|
+
return [ZoneType(types_ptr[i]) for i in range(ntypes)]
|
|
450
|
+
finally:
|
|
451
|
+
if not _tecutil_connector.connected:
|
|
452
|
+
_tecutil.ArrayDealloc(types_ptr)
|
|
453
|
+
except (AttributeError, TecplotSystemError) as err:
|
|
454
|
+
try:
|
|
455
|
+
return [_tecutil.ZoneGetTypeByDataSetID(self.uid, zone_index + 1)
|
|
456
|
+
for zone_index in self._zone_indices]
|
|
457
|
+
except:
|
|
458
|
+
try:
|
|
459
|
+
with self.frame.activated():
|
|
460
|
+
return [_tecutil.ZoneGetType(zone_index + 1)
|
|
461
|
+
for zone_index in self._zone_indices]
|
|
462
|
+
except:
|
|
463
|
+
raise err
|
|
464
|
+
|
|
465
|
+
@property
|
|
466
|
+
def zone_names(self):
|
|
467
|
+
"""A `list` of names for all zones in the dataset.
|
|
468
|
+
|
|
469
|
+
.. warning:: **Newlines in string identifiers may affect performance.**
|
|
470
|
+
|
|
471
|
+
When iterating over many items by name, such as must be done when
|
|
472
|
+
fetching an item via pattern matching, PyTecplot will optimize the
|
|
473
|
+
search only if there are no newline characters in the searched
|
|
474
|
+
items. Iterating over strings that contain newlines will be slower
|
|
475
|
+
and therefore, it is best to avoid using newlines in string
|
|
476
|
+
identifiers or names of objects such as `Zones <data_access>` or
|
|
477
|
+
`Variables <Variable>`.
|
|
478
|
+
|
|
479
|
+
Example usage::
|
|
480
|
+
|
|
481
|
+
>>> print(dataset.zone_names)
|
|
482
|
+
['Zone A', 'Zone B', 'Zone C']
|
|
483
|
+
"""
|
|
484
|
+
try:
|
|
485
|
+
success, ptr = _tecutil.ZoneGetNamesByDataSetID(self.uid)
|
|
486
|
+
if not success:
|
|
487
|
+
raise TecplotSystemError()
|
|
488
|
+
names = ctypes.cast(ptr, StringList)
|
|
489
|
+
try:
|
|
490
|
+
return list(names)
|
|
491
|
+
finally:
|
|
492
|
+
names.dealloc()
|
|
493
|
+
except (AttributeError, TecplotSystemError) as err:
|
|
494
|
+
try:
|
|
495
|
+
success, ptr = _tecutil.ZoneGetEnabledNamesByDataSetID(self.uid)
|
|
496
|
+
if not success:
|
|
497
|
+
raise TecplotSystemError()
|
|
498
|
+
names = ctypes.cast(ptr, StringList)
|
|
499
|
+
try:
|
|
500
|
+
return list(names)
|
|
501
|
+
finally:
|
|
502
|
+
names.dealloc()
|
|
503
|
+
except:
|
|
504
|
+
try:
|
|
505
|
+
return [z.name for z in self.zones()]
|
|
506
|
+
except:
|
|
507
|
+
raise err
|
|
508
|
+
|
|
509
|
+
def zones(self, pattern=None):
|
|
510
|
+
"""Yields all `Zones <data_access>` matching a *pattern*.
|
|
511
|
+
|
|
512
|
+
Parameters:
|
|
513
|
+
pattern (`str` or `re.Pattern <re.compile>`, optional):
|
|
514
|
+
Case-insensitive `glob-style pattern string <fnmatch.fnmatch>`
|
|
515
|
+
or a compiled `regex pattern instance <re.compile>` used to
|
|
516
|
+
match zone names.
|
|
517
|
+
|
|
518
|
+
Returns:
|
|
519
|
+
Generator of `OrderedZones <OrderedZone>`, `ClassicFEZones
|
|
520
|
+
<ClassicFEZone>` or `PolyFEZones <PolyFEZone>` depending on the
|
|
521
|
+
zone types. All `zones <data_access>` if *pattern* is not
|
|
522
|
+
specified.
|
|
523
|
+
|
|
524
|
+
If **pattern** is a string, this will be interpreted as a
|
|
525
|
+
case-insensitive `glob-style pattern <fnmatch.fnmatch>`. Example using
|
|
526
|
+
glob which will match all zones starting with "A" or "a"::
|
|
527
|
+
|
|
528
|
+
>>> for zone in dataset.zones('A*'):
|
|
529
|
+
... x_array = zone.variable('X')
|
|
530
|
+
|
|
531
|
+
Alternatively, a regular-expression may be compiled using `re.compile`
|
|
532
|
+
which will be used directly. This example shows a case-sensitive regex
|
|
533
|
+
search::
|
|
534
|
+
|
|
535
|
+
>>> import re
|
|
536
|
+
>>> pattern = re.compile('[A-Z]*')
|
|
537
|
+
>>> for zone in dataset.zones(pattern):
|
|
538
|
+
... x_array = zone.variable('X')
|
|
539
|
+
|
|
540
|
+
Use list comprehension to construct a list of all zones with 'Wing'
|
|
541
|
+
in the zone name. In contrast to the `Dataset.zones()` method, this
|
|
542
|
+
is case-sensitive::
|
|
543
|
+
|
|
544
|
+
>>> wing_zones = [Z for Z in dataset.zones() if 'Wing' in Z.name]
|
|
545
|
+
|
|
546
|
+
.. warning:: **Zone and variable ordering may change between releases**
|
|
547
|
+
|
|
548
|
+
Due to possible changes in data loaders or data formats over time,
|
|
549
|
+
the ordering of zones and variables may be different between
|
|
550
|
+
versions of Tecplot 360. Therefore it is recommended to always
|
|
551
|
+
reference zones and variables **by name** instead of by index.
|
|
552
|
+
"""
|
|
553
|
+
_dispatch = {
|
|
554
|
+
ZoneType.Ordered: OrderedZone,
|
|
555
|
+
ZoneType.FELineSeg: ClassicFEZone,
|
|
556
|
+
ZoneType.FETriangle: ClassicFEZone,
|
|
557
|
+
ZoneType.FEQuad: ClassicFEZone,
|
|
558
|
+
ZoneType.FETetra: ClassicFEZone,
|
|
559
|
+
ZoneType.FEBrick: ClassicFEZone,
|
|
560
|
+
ZoneType.FEPolygon: PolyFEZone,
|
|
561
|
+
ZoneType.FEPolyhedron: PolyFEZone}
|
|
562
|
+
|
|
563
|
+
if pattern:
|
|
564
|
+
pattern_type = getattr(re, 'Pattern', getattr(re, '_pattern_type', None))
|
|
565
|
+
if not isinstance(pattern, pattern_type):
|
|
566
|
+
regex = re.compile(fnmatch.translate(pattern), re.IGNORECASE)
|
|
567
|
+
else:
|
|
568
|
+
regex = pattern
|
|
569
|
+
|
|
570
|
+
if __debug__:
|
|
571
|
+
found = False
|
|
572
|
+
for uid, typ, name in zip(self._zone_uids, self._zone_types, self.zone_names):
|
|
573
|
+
if regex.match(name):
|
|
574
|
+
if __debug__:
|
|
575
|
+
found = True
|
|
576
|
+
yield _dispatch[typ](uid, self)
|
|
577
|
+
|
|
578
|
+
if __debug__:
|
|
579
|
+
if (
|
|
580
|
+
not found and
|
|
581
|
+
isinstance(pattern, str) and
|
|
582
|
+
any(c in pattern for c in '*?[]')
|
|
583
|
+
):
|
|
584
|
+
msg = 'no zones found matching: "{}"'.format(pattern)
|
|
585
|
+
warning = TecplotPatternMatchWarning(pattern, msg, 'glob')
|
|
586
|
+
warnings.warn(warning)
|
|
587
|
+
else:
|
|
588
|
+
for uid, typ in zip(self._zone_uids, self._zone_types):
|
|
589
|
+
yield _dispatch[typ](uid, self)
|
|
590
|
+
|
|
591
|
+
@property
|
|
592
|
+
def num_variables(self):
|
|
593
|
+
"""`int`: Number of `Variables <Variable>` in this `Dataset <tecplot.data.Dataset>`.
|
|
594
|
+
|
|
595
|
+
This count includes disabled variables which were skipped when the data
|
|
596
|
+
was loaded. Example usage::
|
|
597
|
+
|
|
598
|
+
>>> for i in range(dataset.num_variables):
|
|
599
|
+
... variable = dataset.variable(i)
|
|
600
|
+
"""
|
|
601
|
+
return _tecutil.DataSetGetNumVarsByUniqueID(self.uid)
|
|
602
|
+
|
|
603
|
+
def variable(self, pattern):
|
|
604
|
+
"""Returns the `Variable` by index or string pattern.
|
|
605
|
+
|
|
606
|
+
Parameters:
|
|
607
|
+
pattern (`int`, `str` or `re.Pattern <re.compile>`): Zero-based
|
|
608
|
+
index, case-insensitive `glob-style pattern string
|
|
609
|
+
<fnmatch.fnmatch>` or a compiled `regex pattern instance
|
|
610
|
+
<re.compile>` used to match the variable by name. A negative
|
|
611
|
+
index is interpreted as counting from the end of the available
|
|
612
|
+
variable.
|
|
613
|
+
|
|
614
|
+
Returns:
|
|
615
|
+
`Variable` or `None` if no matching `Variable` name was found.
|
|
616
|
+
|
|
617
|
+
Raises:
|
|
618
|
+
`TecplotIndexError`
|
|
619
|
+
|
|
620
|
+
.. note::
|
|
621
|
+
|
|
622
|
+
A `Dataset <tecplot.data.Dataset>` can contain `variables <Variable>` with identical names
|
|
623
|
+
and only the first match found is returned. This is not guaranteed
|
|
624
|
+
to be deterministic and care should be taken to have only
|
|
625
|
+
`variables <Variable>` with unique names when this feature is used.
|
|
626
|
+
|
|
627
|
+
The `Variable.name` attribute is used to match the *pattern* to the
|
|
628
|
+
desired `Variable` though this is not necessarily unique::
|
|
629
|
+
|
|
630
|
+
>>> ds = frame.dataset
|
|
631
|
+
>>> print(ds)
|
|
632
|
+
Dataset:
|
|
633
|
+
Zones: ['Rectangular zone']
|
|
634
|
+
Variables: ['x', 'y', 'z']
|
|
635
|
+
>>> x = ds.variable('x')
|
|
636
|
+
>>> x == ds.variable(0)
|
|
637
|
+
True
|
|
638
|
+
|
|
639
|
+
.. warning:: **Zone and variable ordering may change between releases**
|
|
640
|
+
|
|
641
|
+
Due to possible changes in data loaders or data formats over time,
|
|
642
|
+
the ordering of zones and variables may be different between
|
|
643
|
+
versions of Tecplot 360. Therefore it is recommended to always
|
|
644
|
+
reference zones and variables **by name** instead of by index.
|
|
645
|
+
"""
|
|
646
|
+
if isinstance(pattern, Variable):
|
|
647
|
+
return pattern
|
|
648
|
+
pattern_type = getattr(re, 'Pattern', getattr(re, '_pattern_type', None))
|
|
649
|
+
if isinstance(pattern, (str, pattern_type)):
|
|
650
|
+
try:
|
|
651
|
+
return next(self.variables(pattern))
|
|
652
|
+
except StopIteration:
|
|
653
|
+
pass
|
|
654
|
+
else:
|
|
655
|
+
if pattern < 0:
|
|
656
|
+
pattern += self.num_variables
|
|
657
|
+
if 0 <= pattern < self.num_variables:
|
|
658
|
+
if __debug__:
|
|
659
|
+
if not _tecutil.VarIsEnabledByDataSetID(self.uid, pattern + 1):
|
|
660
|
+
msg = 'variable {} is not enabled'.format(pattern)
|
|
661
|
+
raise TecplotIndexError(msg)
|
|
662
|
+
return Variable(_tecutil.VarGetUniqueIDByDataSetID(
|
|
663
|
+
self.uid, pattern + 1), self)
|
|
664
|
+
raise TecplotIndexError
|
|
665
|
+
|
|
666
|
+
@property
|
|
667
|
+
def _variable_indices(self):
|
|
668
|
+
"""Yields zero-based indices for all enabled variables in the dataset."""
|
|
669
|
+
success, ptr = _tecutil.VarGetEnabledByDataSetID(self.uid)
|
|
670
|
+
if not success:
|
|
671
|
+
raise TecplotSystemError()
|
|
672
|
+
indices = ctypes.cast(ptr, IndexSet)
|
|
673
|
+
try:
|
|
674
|
+
for i in indices:
|
|
675
|
+
yield i
|
|
676
|
+
finally:
|
|
677
|
+
indices.dealloc()
|
|
678
|
+
|
|
679
|
+
@property
|
|
680
|
+
def _variable_uids(self):
|
|
681
|
+
"""`list` of Unique IDs for all enabled variables in the dataset."""
|
|
682
|
+
try:
|
|
683
|
+
success, nuids, uids_ptr = _tecutil.VarGetUniqueIDsByDataSetID(self.uid)
|
|
684
|
+
if not success:
|
|
685
|
+
raise TecplotSystemError()
|
|
686
|
+
try:
|
|
687
|
+
return uids_ptr[:nuids]
|
|
688
|
+
finally:
|
|
689
|
+
if not _tecutil_connector.connected:
|
|
690
|
+
_tecutil.ArrayDealloc(uids_ptr)
|
|
691
|
+
except (AttributeError, TecplotSystemError) as err:
|
|
692
|
+
try:
|
|
693
|
+
return [_tecutil.VarGetUniqueIDByDataSetID(self.uid, variable_index + 1)
|
|
694
|
+
for variable_index in self._variable_indices]
|
|
695
|
+
except:
|
|
696
|
+
raise err
|
|
697
|
+
|
|
698
|
+
@property
|
|
699
|
+
def variable_names(self):
|
|
700
|
+
"""A `list` of names for all variables in the dataset.
|
|
701
|
+
|
|
702
|
+
.. warning:: **Newlines in string identifiers may affect performance.**
|
|
703
|
+
|
|
704
|
+
When iterating over many items by name, such as must be done when
|
|
705
|
+
fetching an item via pattern matching, PyTecplot will optimize the
|
|
706
|
+
search only if there are no newline characters in the searched
|
|
707
|
+
items. Iterating over strings that contain newlines will be slower
|
|
708
|
+
and therefore, it is best to avoid using newlines in string
|
|
709
|
+
identifiers or names of objects such as `Zones <data_access>` or
|
|
710
|
+
`Variables <Variable>`.
|
|
711
|
+
|
|
712
|
+
Example usage::
|
|
713
|
+
|
|
714
|
+
>>> print(dataset.variable_names)
|
|
715
|
+
['x', 'y', 'z', 's']
|
|
716
|
+
"""
|
|
717
|
+
try:
|
|
718
|
+
success, ptr = _tecutil.VarGetNamesByDataSetID(self.uid)
|
|
719
|
+
if not success:
|
|
720
|
+
raise TecplotSystemError()
|
|
721
|
+
names = ctypes.cast(ptr, StringList)
|
|
722
|
+
try:
|
|
723
|
+
return list(names)
|
|
724
|
+
finally:
|
|
725
|
+
names.dealloc()
|
|
726
|
+
except (AttributeError, TecplotSystemError) as err:
|
|
727
|
+
try:
|
|
728
|
+
success, ptr = _tecutil.VarGetEnabledNamesByDataSetID(self.uid)
|
|
729
|
+
if not success:
|
|
730
|
+
raise TecplotSystemError()
|
|
731
|
+
names = ctypes.cast(ptr, StringList)
|
|
732
|
+
try:
|
|
733
|
+
return list(names)
|
|
734
|
+
finally:
|
|
735
|
+
names.dealloc()
|
|
736
|
+
except:
|
|
737
|
+
try:
|
|
738
|
+
return [z.name for z in self.variables()]
|
|
739
|
+
except:
|
|
740
|
+
raise err
|
|
741
|
+
|
|
742
|
+
def variables(self, pattern=None):
|
|
743
|
+
"""Yields all `Variables <Variable>` matching a *pattern*.
|
|
744
|
+
|
|
745
|
+
Parameters:
|
|
746
|
+
pattern (`str` or `re.Pattern <re.compile>`, optional):
|
|
747
|
+
Case-insensitive `glob-style pattern string <fnmatch.fnmatch>`
|
|
748
|
+
or a compiled `regex pattern instance <re.compile>` used to
|
|
749
|
+
match variable names.
|
|
750
|
+
|
|
751
|
+
Returns:
|
|
752
|
+
Generator of `Variables <Variable>`. All `Variables <Variable>` if
|
|
753
|
+
*pattern* is not specified.
|
|
754
|
+
|
|
755
|
+
Example using case-insensitive glob-style matching::
|
|
756
|
+
|
|
757
|
+
>>> for variable in dataset.variables('A*'):
|
|
758
|
+
... array = variable.values('My Zone')
|
|
759
|
+
|
|
760
|
+
Example using (case-sensitive) regex::
|
|
761
|
+
|
|
762
|
+
>>> import re
|
|
763
|
+
>>> for variable in dataset.variables(re.compile(r'A.*')):
|
|
764
|
+
... array = variable.values('My Zone')
|
|
765
|
+
|
|
766
|
+
.. warning:: **Zone and variable ordering may change between releases**
|
|
767
|
+
|
|
768
|
+
Due to possible changes in data loaders or data formats over time,
|
|
769
|
+
the ordering of zones and variables may be different between
|
|
770
|
+
versions of Tecplot 360. Therefore it is recommended to always
|
|
771
|
+
reference zones and variables **by name** instead of by index.
|
|
772
|
+
"""
|
|
773
|
+
if pattern:
|
|
774
|
+
pattern_type = getattr(re, 'Pattern', getattr(re, '_pattern_type', None))
|
|
775
|
+
if not isinstance(pattern, pattern_type):
|
|
776
|
+
regex = re.compile(fnmatch.translate(pattern), re.IGNORECASE)
|
|
777
|
+
else:
|
|
778
|
+
regex = pattern
|
|
779
|
+
|
|
780
|
+
if __debug__:
|
|
781
|
+
found = False
|
|
782
|
+
for uid, name in zip(self._variable_uids, self.variable_names):
|
|
783
|
+
if regex.match(name):
|
|
784
|
+
if __debug__:
|
|
785
|
+
found = True
|
|
786
|
+
yield Variable(uid, self)
|
|
787
|
+
|
|
788
|
+
if __debug__:
|
|
789
|
+
if (
|
|
790
|
+
not found and
|
|
791
|
+
isinstance(pattern, str) and
|
|
792
|
+
any(c in pattern for c in '*?[]')
|
|
793
|
+
):
|
|
794
|
+
msg = 'no variables found matching: "{}"'.format(pattern)
|
|
795
|
+
warning = TecplotPatternMatchWarning(pattern, msg)
|
|
796
|
+
warnings.warn(warning)
|
|
797
|
+
else:
|
|
798
|
+
for uid in self._variable_uids:
|
|
799
|
+
yield Variable(uid, self)
|
|
800
|
+
|
|
801
|
+
@property
|
|
802
|
+
def VariablesNamedTuple(self):
|
|
803
|
+
r"""A `collections.namedtuple` object using variable names.
|
|
804
|
+
|
|
805
|
+
The variable names are transformed to be unique, valid identifiers
|
|
806
|
+
suitable for use as the key-list for a `collections.namedtuple`.
|
|
807
|
+
This means that all invalid characters such as spaces and dashes
|
|
808
|
+
are converted to underscores, Python keywords are appended by an
|
|
809
|
+
underscore, leading numbers or empty names are prepended with a "v"
|
|
810
|
+
and duplicate variable names are indexed starting with zero, padded
|
|
811
|
+
left with zeros variable names duplicated more than nine times. The
|
|
812
|
+
following table gives some specific examples:
|
|
813
|
+
|
|
814
|
+
==================== ===========================
|
|
815
|
+
Variable names Resulting namedtuple fields
|
|
816
|
+
==================== ===========================
|
|
817
|
+
``'x', 'y'`` ``'x', 'y'``
|
|
818
|
+
``'x', 'x'`` ``'x0', 'x1'``
|
|
819
|
+
``'X', 'Y=f(X)'`` ``'X', 'Y_f_X_'``
|
|
820
|
+
``'x 2', '_', '_'`` ``'x_2', 'v0', 'v1'``
|
|
821
|
+
``'def', 'if'`` ``'def_', 'if_'``
|
|
822
|
+
``'1', '2', '3'`` ``'v1', 'v2', 'v3'``
|
|
823
|
+
==================== ===========================
|
|
824
|
+
|
|
825
|
+
This example shows how one can use this n-tuple type with the
|
|
826
|
+
result from a call to `tecplot.data.query.probe_at_position`:
|
|
827
|
+
|
|
828
|
+
.. code-block:: python
|
|
829
|
+
|
|
830
|
+
from os import path
|
|
831
|
+
import tecplot as tp
|
|
832
|
+
|
|
833
|
+
examples_dir = tp.session.tecplot_examples_directory()
|
|
834
|
+
datafile = path.join(examples_dir,'SimpleData','DownDraft.plt')
|
|
835
|
+
dataset = tp.data.load_tecplot(datafile)
|
|
836
|
+
result = tp.data.query.probe_at_position(0,0.1,0.3)
|
|
837
|
+
data = dataset.VariablesNamedTuple(*result.data)
|
|
838
|
+
|
|
839
|
+
# prints: (RHO, E) = (1.17, 252930.37)
|
|
840
|
+
msg = '(RHO, E) = ({:.2f}, {:.2f})'
|
|
841
|
+
print(msg.format(data.RHO, data.E))
|
|
842
|
+
"""
|
|
843
|
+
# First we clean up variable names
|
|
844
|
+
# and keep a count of each name used
|
|
845
|
+
names = []
|
|
846
|
+
count = {}
|
|
847
|
+
for vname in self.variable_names:
|
|
848
|
+
# sub invalid characters with underscores
|
|
849
|
+
name = re.sub(r'\W|^(?=\d)', r'_', vname)
|
|
850
|
+
# remove leading underscores
|
|
851
|
+
name = re.sub(r'^_+', r'', name)
|
|
852
|
+
# prepend leading number with 'v'
|
|
853
|
+
name = re.sub(r'^(\d)', r'v\1', name)
|
|
854
|
+
# append keywords with underscore
|
|
855
|
+
if iskeyword(name):
|
|
856
|
+
name = name + '_'
|
|
857
|
+
# force non-empty variable names using 'v'
|
|
858
|
+
if name == '':
|
|
859
|
+
name = 'v'
|
|
860
|
+
# add name to list
|
|
861
|
+
names.append(name)
|
|
862
|
+
# keep track of names to identify duplicates
|
|
863
|
+
if name not in count:
|
|
864
|
+
count[name] = 0
|
|
865
|
+
count[name] += 1
|
|
866
|
+
|
|
867
|
+
# append index, with padded zeros
|
|
868
|
+
numbered = count.copy()
|
|
869
|
+
for i,name in enumerate(names):
|
|
870
|
+
if count[name] > 1:
|
|
871
|
+
names[i] = '{0}{1:0{2}d}'.format(name,
|
|
872
|
+
count[name] - numbered[name], len(str(count[name] - 1)))
|
|
873
|
+
numbered[name] -= 1
|
|
874
|
+
|
|
875
|
+
return collections.namedtuple('DatasetVariables', names)
|
|
876
|
+
|
|
877
|
+
@lock()
|
|
878
|
+
def copy_zones(self, *zones, **kwargs):
|
|
879
|
+
"""Copies `Zones <data_access>` within this `Dataset <tecplot.data.Dataset>`.
|
|
880
|
+
|
|
881
|
+
Parameters:
|
|
882
|
+
*zones (`Zone <data_access>`, optional): Specific `Zones
|
|
883
|
+
<data_access>` to copy. All zones will be copied if none are
|
|
884
|
+
supplied.
|
|
885
|
+
shared_variables (`bool` or `list` of `Variables <Variable>`):
|
|
886
|
+
Share all variables between the original and generated zones if
|
|
887
|
+
`True` or the list of Variables to be shared. Variable sharing
|
|
888
|
+
allows you to lower the use of physical memory (RAM). When
|
|
889
|
+
sharing a variable the memory used by the source zone is shared
|
|
890
|
+
with the copied zone. Alterations to the variable in one zone
|
|
891
|
+
will affect the other. See also `Dataset.branch_variables()`.
|
|
892
|
+
Default: `False`.
|
|
893
|
+
i_range (`tuple` of `integers <int>`, optional):
|
|
894
|
+
Range (min, max, step) along the ``i`` dimension for ordered
|
|
895
|
+
data. Min and max are zero-based indicies where max is
|
|
896
|
+
inclusive. If step causes max to be skipped, max will be
|
|
897
|
+
included. If `None` (default), the entire range will be copied.
|
|
898
|
+
j_range (`tuple` of `integers <int>`, optional):
|
|
899
|
+
Range (min, max, step) along the ``j`` dimension for ordered
|
|
900
|
+
data. Min and max are zero-based indicies where max is
|
|
901
|
+
inclusive. If step causes max to be skipped, max will be
|
|
902
|
+
included. If `None` (default), the entire range will be copied.
|
|
903
|
+
k_range (`tuple` of `integers <int>`, optional):
|
|
904
|
+
Range (min, max, step) along the ``k`` dimension for ordered
|
|
905
|
+
data. Min and max are zero-based indicies where max is
|
|
906
|
+
inclusive. If step causes max to be skipped, max will be
|
|
907
|
+
included. If `None` (default), the entire range will be copied.
|
|
908
|
+
|
|
909
|
+
Returns:
|
|
910
|
+
`list` of the newly created `Zones <data_access>`.
|
|
911
|
+
|
|
912
|
+
.. note:: **Performance considerations for data manipulations.**
|
|
913
|
+
|
|
914
|
+
When performing many data-manipulation operations including adding
|
|
915
|
+
zones, adding variables, modifying field data or connectivity, and
|
|
916
|
+
especially in connected mode, it is recommended to do this all with
|
|
917
|
+
the `tecplot.session.suspend()`. This will prevent the Tecplot
|
|
918
|
+
engine from trying to "keep up" with the changes. Tecplot will be
|
|
919
|
+
notified of all changes made upon exit of this context. This may
|
|
920
|
+
result in significant performance gains for long operations.
|
|
921
|
+
|
|
922
|
+
.. code-block:: python
|
|
923
|
+
|
|
924
|
+
import tecplot as tp
|
|
925
|
+
|
|
926
|
+
ds = tp.active_page().add_frame().create_dataset('D', ['x','y','z'])
|
|
927
|
+
z = ds.add_ordered_zone('Z1', (3,3,3))
|
|
928
|
+
ds.copy_zones(z, i_range=(1, -1, 2), share_variables=True)
|
|
929
|
+
"""
|
|
930
|
+
share_variables = kwargs.pop('share_variables', False)
|
|
931
|
+
i_range = kwargs.pop('i_range', None)
|
|
932
|
+
j_range = kwargs.pop('j_range', None)
|
|
933
|
+
k_range = kwargs.pop('k_range', None)
|
|
934
|
+
|
|
935
|
+
if not share_variables:
|
|
936
|
+
branch_variables = list(self.variables())
|
|
937
|
+
elif isinstance(share_variables, Iterable):
|
|
938
|
+
for idx, var in enumerate(share_variables):
|
|
939
|
+
if not isinstance(var, Variable):
|
|
940
|
+
share_variables[idx]= self.variable(var)
|
|
941
|
+
|
|
942
|
+
branch_variables = [v for v in self.variables()
|
|
943
|
+
if v not in share_variables]
|
|
944
|
+
else:
|
|
945
|
+
branch_variables = []
|
|
946
|
+
|
|
947
|
+
num_zones = self.num_zones
|
|
948
|
+
|
|
949
|
+
with tecutil.ArgList() as arglist:
|
|
950
|
+
if not zones:
|
|
951
|
+
zones = self.zones()
|
|
952
|
+
with IndexSet(*zones) as zoneset:
|
|
953
|
+
arglist[sv.SOURCEZONES] = zoneset
|
|
954
|
+
|
|
955
|
+
for dim, rng in zip(['I', 'J', 'K'], [i_range, j_range, k_range]):
|
|
956
|
+
if rng is not None:
|
|
957
|
+
rng = tecutil.IndexRange(*rng)
|
|
958
|
+
if rng.min is not None:
|
|
959
|
+
arglist[dim + 'MIN'] = tecutil.Index(rng.min)
|
|
960
|
+
if rng.max is not None:
|
|
961
|
+
arglist[dim + 'MAX'] = tecutil.Index(rng.max)
|
|
962
|
+
if rng.step is not None:
|
|
963
|
+
step = int(rng.step)
|
|
964
|
+
if step > 0:
|
|
965
|
+
arglist[dim + 'SKIP'] = step
|
|
966
|
+
elif step < 0:
|
|
967
|
+
msg = 'Negative step not supported.'
|
|
968
|
+
raise TecplotLogicError(msg)
|
|
969
|
+
_tecutil.ZoneCopyX(arglist)
|
|
970
|
+
|
|
971
|
+
new_zones = [self.zone(i) for i in range(num_zones, self.num_zones)]
|
|
972
|
+
|
|
973
|
+
for zone in new_zones:
|
|
974
|
+
for var in branch_variables:
|
|
975
|
+
self.branch_variables(zone, var, True)
|
|
976
|
+
|
|
977
|
+
return new_zones
|
|
978
|
+
|
|
979
|
+
def mirror_zones(self, mirror_variables, *zones):
|
|
980
|
+
"""Mirrors `Zones <data_access>` within this `Dataset <tecplot.data.Dataset>`.
|
|
981
|
+
|
|
982
|
+
Each mirror zone has a name of the form "Mirror of zone *sourcezone*",
|
|
983
|
+
where *sourcezone* is the number of the zone from which the mirrored
|
|
984
|
+
zone was created. The variables in the newly created zones are shared
|
|
985
|
+
with their corresponding source zones, except for variables to be
|
|
986
|
+
mirrored as specified.
|
|
987
|
+
|
|
988
|
+
Parameters:
|
|
989
|
+
mirror_variables (`Variable` or `list` of `Variables <Variable>`):
|
|
990
|
+
Variables in the new zone to be multiplied by :math:`-1` after
|
|
991
|
+
the zone is copied. the variables may be `Variable` objects,
|
|
992
|
+
`str` names or `int` indices.
|
|
993
|
+
*zones (`Zones <data_access>`, optional): Specific `Zones
|
|
994
|
+
<data_access>` to mirror. All zones will be mirrored if none
|
|
995
|
+
are supplied. The values may also be `str` names or `int`
|
|
996
|
+
indices.
|
|
997
|
+
|
|
998
|
+
Returns:
|
|
999
|
+
Generator of mirrored zones.
|
|
1000
|
+
|
|
1001
|
+
This example show how to mirror all zones across the xy-plane in 3D::
|
|
1002
|
+
|
|
1003
|
+
>>> mirrored_zones = dataset.mirror_zones('Z')
|
|
1004
|
+
"""
|
|
1005
|
+
if (
|
|
1006
|
+
isinstance(mirror_variables, str) or
|
|
1007
|
+
not isinstance(mirror_variables, Iterable)
|
|
1008
|
+
):
|
|
1009
|
+
mirror_variables = [mirror_variables]
|
|
1010
|
+
|
|
1011
|
+
mvars = (v if isinstance(v, Variable) else self.variable(v)
|
|
1012
|
+
for v in mirror_variables)
|
|
1013
|
+
mvars = ','.join([str(v.index + 1) for v in mvars])
|
|
1014
|
+
|
|
1015
|
+
if not zones:
|
|
1016
|
+
mzones = '1-{}'.format(self.num_zones)
|
|
1017
|
+
else:
|
|
1018
|
+
mzones = (z if isinstance(z, Zone) else self.zone(z)
|
|
1019
|
+
for z in tecutil.flatten_args(*zones))
|
|
1020
|
+
mzones = ','.join([str(z.index + 1) for z in mzones])
|
|
1021
|
+
|
|
1022
|
+
num_zones = self.num_zones
|
|
1023
|
+
cmd = '$!CreateMirrorZones SourceZones = [{0}] MirrorVars = [{1}]'
|
|
1024
|
+
macro.execute_command(cmd.format(mzones, mvars))
|
|
1025
|
+
return (self.zone(i) for i in range(num_zones, self.num_zones))
|
|
1026
|
+
|
|
1027
|
+
@lock()
|
|
1028
|
+
def add_variable(self, name, dtypes=None, locations=None):
|
|
1029
|
+
"""Add a single `Variable` to the active `Dataset <tecplot.data.Dataset>`.
|
|
1030
|
+
|
|
1031
|
+
Parameters:
|
|
1032
|
+
name (`str`): The name of the new `Variable`. This does not
|
|
1033
|
+
have to be unique.
|
|
1034
|
+
dtypes (`FieldDataType` or `list` of `FieldDataType`, optional):
|
|
1035
|
+
Data types of this `Variable` for each `Zone <data_access>` in
|
|
1036
|
+
the currently active `Dataset <tecplot.data.Dataset>`. Options are:
|
|
1037
|
+
`FieldDataType.Float`, `Double <FieldDataType.Double>`,
|
|
1038
|
+
`Int32`, `Int16`, `Byte` and `Bit`. If a single value, this
|
|
1039
|
+
will be duplicated for all `Zones <data_access>`. (default:
|
|
1040
|
+
`None`)
|
|
1041
|
+
locations (`ValueLocation` or `list` of `ValueLocation`, optional):
|
|
1042
|
+
Point locations of this `Variable` for each
|
|
1043
|
+
`Zone <data_access>` in the currently active `Dataset <tecplot.data.Dataset>`. Options
|
|
1044
|
+
are: `Nodal` and `CellCentered`. If a single value, this will
|
|
1045
|
+
be duplicated for all `Zones <data_access>`. (default: `None`)
|
|
1046
|
+
|
|
1047
|
+
Returns:
|
|
1048
|
+
`Variable`
|
|
1049
|
+
|
|
1050
|
+
.. note:: **Performance considerations for data manipulations.**
|
|
1051
|
+
|
|
1052
|
+
When performing many data-manipulation operations including adding
|
|
1053
|
+
zones, adding variables, modifying field data or connectivity, and
|
|
1054
|
+
especially in connected mode, it is recommended to do this all with
|
|
1055
|
+
the `tecplot.session.suspend()`. This will prevent the Tecplot
|
|
1056
|
+
engine from trying to "keep up" with the changes. Tecplot will be
|
|
1057
|
+
notified of all changes made upon exit of this context. This may
|
|
1058
|
+
result in significant performance gains for long operations.
|
|
1059
|
+
|
|
1060
|
+
The added `Variable` will be available for use in each `Zone
|
|
1061
|
+
<data_access>` of the dataset. This method should be used in
|
|
1062
|
+
conjunction with other data creation methods such as
|
|
1063
|
+
`Dataset.add_zone`:
|
|
1064
|
+
|
|
1065
|
+
.. code-block:: python
|
|
1066
|
+
:emphasize-lines: 7-8
|
|
1067
|
+
|
|
1068
|
+
import math
|
|
1069
|
+
import tecplot as tp
|
|
1070
|
+
from tecplot.constant import PlotType
|
|
1071
|
+
|
|
1072
|
+
# Setup Tecplot dataset
|
|
1073
|
+
dataset = tp.active_frame().create_dataset('Data')
|
|
1074
|
+
dataset.add_variable('x')
|
|
1075
|
+
dataset.add_variable('s')
|
|
1076
|
+
zone = dataset.add_ordered_zone('Zone', 100)
|
|
1077
|
+
|
|
1078
|
+
# Fill the dataset
|
|
1079
|
+
x = [0.1 * i for i in range(100)]
|
|
1080
|
+
zone.values('x')[:] = x
|
|
1081
|
+
zone.values('s')[:] = [math.sin(i) for i in x]
|
|
1082
|
+
|
|
1083
|
+
# Set plot type to XYLine
|
|
1084
|
+
tp.active_frame().plot(PlotType.XYLine).activate()
|
|
1085
|
+
|
|
1086
|
+
tp.export.save_png('add_variables.png', 600, supersample=3)
|
|
1087
|
+
|
|
1088
|
+
.. figure:: /_static/images/add_variables.png
|
|
1089
|
+
:width: 300px
|
|
1090
|
+
:figwidth: 300px
|
|
1091
|
+
"""
|
|
1092
|
+
assert len(name) <= 128, 'Variable names are limited to 128 characters'
|
|
1093
|
+
with self.frame.activated():
|
|
1094
|
+
dataset = self.frame.dataset
|
|
1095
|
+
new_variable_index = dataset.num_variables
|
|
1096
|
+
with tecutil.ArgList(NAME=name) as arglist:
|
|
1097
|
+
if dtypes is not None:
|
|
1098
|
+
if not hasattr(dtypes, '__iter__'):
|
|
1099
|
+
dtypes = [dtypes] * dataset.num_zones
|
|
1100
|
+
arglist['VARDATATYPE'] = dtypes
|
|
1101
|
+
if locations is not None:
|
|
1102
|
+
if not hasattr(locations, '__iter__'):
|
|
1103
|
+
locations = [locations] * dataset.num_zones
|
|
1104
|
+
arglist['VALUELOCATION'] = locations
|
|
1105
|
+
|
|
1106
|
+
if __debug__:
|
|
1107
|
+
msg = 'new variable: ' + name
|
|
1108
|
+
for k, v in arglist.items():
|
|
1109
|
+
msg += '\n {} = {}'.format(k, v)
|
|
1110
|
+
log.debug(msg)
|
|
1111
|
+
if not _tecutil.DataSetAddVarX(arglist):
|
|
1112
|
+
raise TecplotSystemError()
|
|
1113
|
+
return dataset.variable(new_variable_index)
|
|
1114
|
+
|
|
1115
|
+
@lock()
|
|
1116
|
+
def add_zone(self, zone_type, name, shape, dtypes=None, locations=None,
|
|
1117
|
+
face_neighbor_mode=None, parent_zone=None, solution_time=None,
|
|
1118
|
+
strand_id=None, index=None):
|
|
1119
|
+
"""Add a single `Zone <data_access>` to this `Dataset <tecplot.data.Dataset>`.
|
|
1120
|
+
|
|
1121
|
+
Parameters:
|
|
1122
|
+
zone_type (`ZoneType`): The type of `Zone <data_access>` to be
|
|
1123
|
+
created. Possible values are: `Ordered`, `FETriangle`,
|
|
1124
|
+
`FEQuad`, `FETetra`, `FEBrick`, `FELineSeg`, `FEPolyhedron` and
|
|
1125
|
+
`FEPolygon`.
|
|
1126
|
+
name (`str`): Name of the new `Zone <data_access>`. This
|
|
1127
|
+
does not have to be unique.
|
|
1128
|
+
shape (`int` or `list` of `integers <int>`): Specifies
|
|
1129
|
+
the length and dimension (up to three) of the new `Zone
|
|
1130
|
+
<data_access>`. A 1D `Zone <data_access>` is assumed if a
|
|
1131
|
+
single `int` is given. This is **(i, j, k)** for ordered `Zones
|
|
1132
|
+
<data_access>`, **(num_points, num_elements)** for
|
|
1133
|
+
finite-element `Zones <data_access>` and **(num_points,
|
|
1134
|
+
num_elements, num_faces)** for polytope `Zones <data_access>`
|
|
1135
|
+
where the number of faces is known.
|
|
1136
|
+
dtypes (`FieldDataType`, `list` of `FieldDataType`, optional): Data
|
|
1137
|
+
types of this `Zone <data_access>` for each `Variable` in the
|
|
1138
|
+
currently active `Dataset <tecplot.data.Dataset>`. Options are: `Float
|
|
1139
|
+
<FieldDataType.Float>`, `Double <FieldDataType.Double>`,
|
|
1140
|
+
`Int32`, `Int16`, `Byte` and `Bit`. If a single value, this
|
|
1141
|
+
will be duplicated for all `Variables <Variable>`. If `None`
|
|
1142
|
+
then the type of the first `Variable`, defaulting to
|
|
1143
|
+
`FieldDataType.Float`, is used for all. (default: `None`)
|
|
1144
|
+
locations (`ValueLocation`, `list` of `ValueLocation`, optional):
|
|
1145
|
+
Point locations of this `Zone <data_access>` for each
|
|
1146
|
+
`Variable` in the currently active `Dataset <tecplot.data.Dataset>`. Options are:
|
|
1147
|
+
`Nodal` and `CellCentered`. If a single value, this will be
|
|
1148
|
+
duplicated for all `Variables <Variable>`. If `None` then the
|
|
1149
|
+
type of the first `Variable`, defaulting to `Nodal`, is used
|
|
1150
|
+
for all. (default: `None`)
|
|
1151
|
+
face_neighbor_mode (`FaceNeighborMode`, optional): Specifies the
|
|
1152
|
+
face-neighbor mode for this zone. Options are:
|
|
1153
|
+
`FaceNeighborMode.LocalOneToOne` (default),
|
|
1154
|
+
`FaceNeighborMode.LocalOneToMany`,
|
|
1155
|
+
`FaceNeighborMode.GlobalOneToOne` or
|
|
1156
|
+
`FaceNeighborMode.GlobalOneToMany`.
|
|
1157
|
+
parent_zone (`Zone <data_access>`, optional): A parent `Zone
|
|
1158
|
+
<data_access>` to be used when generating surface-restricted
|
|
1159
|
+
streamtraces.
|
|
1160
|
+
solution_time (`float`, optional): Solution time for this zone.
|
|
1161
|
+
(default: 0)
|
|
1162
|
+
strand_id (`int`, optional): Associate this new `Zone
|
|
1163
|
+
<data_access>` with a particular strand.
|
|
1164
|
+
index (`int`, optional): Number of the zone to add or
|
|
1165
|
+
replace. If omitted or set to `None`, the new zone will be
|
|
1166
|
+
appended to the dataset. This value can be set to the number of
|
|
1167
|
+
a zone that already exists thereby replacing the existing zone.
|
|
1168
|
+
(default: `None`)
|
|
1169
|
+
|
|
1170
|
+
Returns:
|
|
1171
|
+
`Zone <data_access>`
|
|
1172
|
+
|
|
1173
|
+
.. warning:: **Setting connectivity in connected mode.**
|
|
1174
|
+
|
|
1175
|
+
When connected to a running instance of Tecplot 360 using the
|
|
1176
|
+
TecUtil Server, care must be taken to ensure that the GUI does not
|
|
1177
|
+
try to render the data between the creation of the zone and the
|
|
1178
|
+
setting of the connectivity, through the `Facemap` or `Nodemap`
|
|
1179
|
+
objects. This can be achieved by setting the plot type of the
|
|
1180
|
+
frame(s) holding on to the dataset to `PlotType.Sketch` before
|
|
1181
|
+
creating the zone and only going to `PlotType.Cartesian3D` after
|
|
1182
|
+
the connectivity is set. Tecplot 360 may get into a bad state,
|
|
1183
|
+
corrupting loaded data, if it attempts to render (especially
|
|
1184
|
+
polytope) data without connectivity.
|
|
1185
|
+
|
|
1186
|
+
.. note:: **Performance considerations for data manipulations.**
|
|
1187
|
+
|
|
1188
|
+
When performing many data-manipulation operations including adding
|
|
1189
|
+
zones, adding variables, modifying field data or connectivity, and
|
|
1190
|
+
especially in connected mode, it is recommended to do this all with
|
|
1191
|
+
the `tecplot.session.suspend()`. This will prevent the Tecplot
|
|
1192
|
+
engine from trying to "keep up" with the changes. Tecplot will be
|
|
1193
|
+
notified of all changes made upon exit of this context. This may
|
|
1194
|
+
result in significant performance gains for long operations.
|
|
1195
|
+
|
|
1196
|
+
The added `Zone <data_access>` will be able to use all `Variables
|
|
1197
|
+
<Variable>` defined in the dataset. This method should be used in
|
|
1198
|
+
conjunction with other data creation methods such as
|
|
1199
|
+
`Frame.create_dataset`. Example usage::
|
|
1200
|
+
|
|
1201
|
+
>>> from tecplot.constant import ZoneType
|
|
1202
|
+
>>> zone = dataset.add_zone(ZoneType.Ordered, 'Zone', (10, 10, 10))
|
|
1203
|
+
|
|
1204
|
+
.. note::
|
|
1205
|
+
|
|
1206
|
+
The relationship and meaning of this method's parameters change
|
|
1207
|
+
depending on the type of zone being created. Therefore, it is
|
|
1208
|
+
recommended to use the more specific zone creation methods:
|
|
1209
|
+
|
|
1210
|
+
* `Dataset.add_ordered_zone`
|
|
1211
|
+
* `Dataset.add_fe_zone`
|
|
1212
|
+
* `Dataset.add_poly_zone`
|
|
1213
|
+
"""
|
|
1214
|
+
if __debug__:
|
|
1215
|
+
if self.num_variables == 0:
|
|
1216
|
+
errmsg = dedent('''\
|
|
1217
|
+
Can not create a zone on a dataset with no variables.
|
|
1218
|
+
Add at least one variable to this dataset before
|
|
1219
|
+
creating any zones.''')
|
|
1220
|
+
raise TecplotLogicError(errmsg)
|
|
1221
|
+
|
|
1222
|
+
with self.frame.activated():
|
|
1223
|
+
dataset = self.frame.dataset
|
|
1224
|
+
new_zone_index = dataset.num_zones if index is None else index
|
|
1225
|
+
with tecutil.ArgList(ZONETYPE=zone_type, NAME=name) as arglist:
|
|
1226
|
+
# convert shape to (imax, jmax, kmax)
|
|
1227
|
+
if not hasattr(shape, '__iter__'):
|
|
1228
|
+
shape = [shape]
|
|
1229
|
+
for k, v in zip([sv.IMAX, sv.JMAX, sv.KMAX], shape):
|
|
1230
|
+
arglist[k] = v
|
|
1231
|
+
|
|
1232
|
+
# expand data types and locations to length of num_variables
|
|
1233
|
+
for key, val in zip([sv.VARDATATYPE, sv.VALUELOCATION],
|
|
1234
|
+
[dtypes, locations]):
|
|
1235
|
+
if val is not None:
|
|
1236
|
+
if not hasattr(val, '__iter__'):
|
|
1237
|
+
val = [val] * dataset.num_variables
|
|
1238
|
+
arglist[key] = val
|
|
1239
|
+
|
|
1240
|
+
if solution_time is not None:
|
|
1241
|
+
arglist[sv.SOLUTIONTIME] = float(solution_time)
|
|
1242
|
+
|
|
1243
|
+
if strand_id is not None:
|
|
1244
|
+
arglist[sv.STRANDID] = int(strand_id)
|
|
1245
|
+
|
|
1246
|
+
if parent_zone is not None:
|
|
1247
|
+
arglist[sv.PARENTZONE] = parent_zone.index + 1
|
|
1248
|
+
|
|
1249
|
+
if face_neighbor_mode is not None:
|
|
1250
|
+
arglist[sv.FACENEIGHBORMODE] = FaceNeighborMode(
|
|
1251
|
+
face_neighbor_mode)
|
|
1252
|
+
|
|
1253
|
+
if index is not None:
|
|
1254
|
+
arglist[sv.ZONE] = index + 1
|
|
1255
|
+
|
|
1256
|
+
if __debug__:
|
|
1257
|
+
shp = '({})'.format(','.join(str(s) for s in shape))
|
|
1258
|
+
msg = 'new dataset shape: ' + shp
|
|
1259
|
+
for k, v in arglist.items():
|
|
1260
|
+
msg += '\n {} = {}'.format(k, v)
|
|
1261
|
+
log.debug(msg)
|
|
1262
|
+
|
|
1263
|
+
if not _tecutil.DataSetAddZoneX(arglist):
|
|
1264
|
+
raise TecplotSystemError()
|
|
1265
|
+
|
|
1266
|
+
new_zone = dataset.zone(new_zone_index)
|
|
1267
|
+
session.zone_added(new_zone)
|
|
1268
|
+
return new_zone
|
|
1269
|
+
|
|
1270
|
+
def add_ordered_zone(self, name, shape, **kwargs):
|
|
1271
|
+
"""Add a single ordered `Zone <data_access>` to this `Dataset <tecplot.data.Dataset>`.
|
|
1272
|
+
|
|
1273
|
+
Parameters:
|
|
1274
|
+
name (`str`): Name of the new `Zone <data_access>`. This
|
|
1275
|
+
does not have to be unique.
|
|
1276
|
+
shape (`int` or `list` of `integers <int>`): Specifies
|
|
1277
|
+
the length and dimension **(i, j, k)** of the new
|
|
1278
|
+
`Zone <data_access>`. A 1D `Zone <data_access>` is assumed if a
|
|
1279
|
+
single `int` is given.
|
|
1280
|
+
**kwargs: These arguments are passed to `Dataset.add_zone`.
|
|
1281
|
+
|
|
1282
|
+
.. seealso:: `Dataset.add_zone`
|
|
1283
|
+
|
|
1284
|
+
Keyword arguments are passed to the parent zone creation method
|
|
1285
|
+
`Dataset.add_zone`.
|
|
1286
|
+
|
|
1287
|
+
.. note:: **Performance considerations for data manipulations.**
|
|
1288
|
+
|
|
1289
|
+
When performing many data-manipulation operations including adding
|
|
1290
|
+
zones, adding variables, modifying field data or connectivity, and
|
|
1291
|
+
especially in connected mode, it is recommended to do this all with
|
|
1292
|
+
the `tecplot.session.suspend()`. This will prevent the Tecplot
|
|
1293
|
+
engine from trying to "keep up" with the changes. Tecplot will be
|
|
1294
|
+
notified of all changes made upon exit of this context. This may
|
|
1295
|
+
result in significant performance gains for long operations.
|
|
1296
|
+
|
|
1297
|
+
This example creates a 10x10x10 ordered zone of double-precision
|
|
1298
|
+
floating-point numbers::
|
|
1299
|
+
|
|
1300
|
+
>>> from tecplot.constant import FieldDataType
|
|
1301
|
+
>>> my_zone = dataset.add_zone('My Zone', (10, 10, 10),
|
|
1302
|
+
... dtype=FieldDataType.Double)
|
|
1303
|
+
|
|
1304
|
+
Here is a full example:
|
|
1305
|
+
|
|
1306
|
+
.. code-block:: python
|
|
1307
|
+
:emphasize-lines: 12,17,22
|
|
1308
|
+
|
|
1309
|
+
import numpy as np
|
|
1310
|
+
import tecplot as tp
|
|
1311
|
+
from tecplot.constant import PlotType, Color
|
|
1312
|
+
|
|
1313
|
+
# Generate data
|
|
1314
|
+
x = np.linspace(-4, 4, 100)
|
|
1315
|
+
|
|
1316
|
+
# Setup Tecplot dataset
|
|
1317
|
+
dataset = tp.active_frame().create_dataset('Data', ['x', 'y'])
|
|
1318
|
+
|
|
1319
|
+
# Create a zone
|
|
1320
|
+
zone = dataset.add_ordered_zone('sin(x)', len(x))
|
|
1321
|
+
zone.values('x')[:] = x
|
|
1322
|
+
zone.values('y')[:] = np.sin(x)
|
|
1323
|
+
|
|
1324
|
+
# Create another zone
|
|
1325
|
+
zone = dataset.add_ordered_zone('cos(x)', len(x))
|
|
1326
|
+
zone.values('x')[:] = x
|
|
1327
|
+
zone.values('y')[:] = np.cos(x)
|
|
1328
|
+
|
|
1329
|
+
# And one more zone
|
|
1330
|
+
zone = dataset.add_ordered_zone('tan(x)', len(x))
|
|
1331
|
+
zone.values('x')[:] = x
|
|
1332
|
+
zone.values('y')[:] = np.tan(x)
|
|
1333
|
+
|
|
1334
|
+
# Set plot type to XYLine
|
|
1335
|
+
plot = tp.active_frame().plot(PlotType.XYLine)
|
|
1336
|
+
plot.activate()
|
|
1337
|
+
|
|
1338
|
+
# Show all linemaps and make the lines a bit thicker
|
|
1339
|
+
for lmap in plot.linemaps():
|
|
1340
|
+
lmap.show = True
|
|
1341
|
+
lmap.line.line_thickness = 0.6
|
|
1342
|
+
|
|
1343
|
+
plot.legend.show = True
|
|
1344
|
+
|
|
1345
|
+
tp.export.save_png('add_ordered_zones.png', 600, supersample=3)
|
|
1346
|
+
|
|
1347
|
+
.. figure:: /_static/images/add_ordered_zones.png
|
|
1348
|
+
:width: 300px
|
|
1349
|
+
:figwidth: 300px
|
|
1350
|
+
"""
|
|
1351
|
+
return self.add_zone(ZoneType.Ordered, name, shape, **kwargs)
|
|
1352
|
+
|
|
1353
|
+
def add_fe_zone(self, zone_type, name, num_points, num_elements, **kwargs):
|
|
1354
|
+
r"""Add a single finite-element `Zone <data_access>` to this `Dataset <tecplot.data.Dataset>`.
|
|
1355
|
+
|
|
1356
|
+
Parameters:
|
|
1357
|
+
zone_type (`ZoneType`): The type of `Zone <data_access>` to be
|
|
1358
|
+
created. Possible values are: `FETriangle`, `FEQuad`,
|
|
1359
|
+
`FETetra`, `FEBrick` and `FELineSeg`.
|
|
1360
|
+
name (`str`): Name of the new `Zone <data_access>`. This
|
|
1361
|
+
does not have to be unique.
|
|
1362
|
+
num_points (`int`): Number of points (nodes) in this
|
|
1363
|
+
zone.
|
|
1364
|
+
num_elements (`int`): Number of elements in this zone.
|
|
1365
|
+
The nodemap will have the shape (num_points, num_elements).
|
|
1366
|
+
**kwargs: These arguments are passed to `Dataset.add_zone`.
|
|
1367
|
+
|
|
1368
|
+
.. seealso:: `Dataset.add_zone`
|
|
1369
|
+
|
|
1370
|
+
Keyword arguments are passed to the parent zone creation method
|
|
1371
|
+
`Dataset.add_zone`.
|
|
1372
|
+
|
|
1373
|
+
.. warning:: **Setting connectivity in connected mode.**
|
|
1374
|
+
|
|
1375
|
+
When connected to a running instance of Tecplot 360 using the
|
|
1376
|
+
TecUtil Server, care must be taken to ensure that the GUI does not
|
|
1377
|
+
try to render the data between the creation of the zone and the
|
|
1378
|
+
setting of the connectivity, through the `Facemap` or `Nodemap`
|
|
1379
|
+
objects. This can be achieved by setting the plot type of the
|
|
1380
|
+
frame(s) holding on to the dataset to `PlotType.Sketch` before
|
|
1381
|
+
creating the zone and only going to `PlotType.Cartesian3D` after
|
|
1382
|
+
the connectivity is set. Tecplot 360 may get into a bad state,
|
|
1383
|
+
corrupting loaded data, if it attempts to render (especially
|
|
1384
|
+
polytope) data without connectivity.
|
|
1385
|
+
|
|
1386
|
+
.. note:: **Performance considerations for data manipulations.**
|
|
1387
|
+
|
|
1388
|
+
When performing many data-manipulation operations including adding
|
|
1389
|
+
zones, adding variables, modifying field data or connectivity, and
|
|
1390
|
+
especially in connected mode, it is recommended to do this all with
|
|
1391
|
+
the `tecplot.session.suspend()`. This will prevent the Tecplot
|
|
1392
|
+
engine from trying to "keep up" with the changes. Tecplot will be
|
|
1393
|
+
notified of all changes made upon exit of this context. This may
|
|
1394
|
+
result in significant performance gains for long operations.
|
|
1395
|
+
|
|
1396
|
+
The number of points (also known as nodes) per finite-element is
|
|
1397
|
+
determined from the ``zone_type`` parameter. The follow table shows the
|
|
1398
|
+
number of points per element for the available zone types along with
|
|
1399
|
+
the resulting shape of the nodemap based on the number of points
|
|
1400
|
+
specified (:math:`N`):
|
|
1401
|
+
|
|
1402
|
+
============== ============== ========================
|
|
1403
|
+
Zone Type Points/Element Nodemap Shape
|
|
1404
|
+
============== ============== ========================
|
|
1405
|
+
``FELineSeg`` 2 (:math:`N`, :math:`2 N`)
|
|
1406
|
+
``FETriangle`` 3 (:math:`N`, :math:`3 N`)
|
|
1407
|
+
``FEQuad`` 4 (:math:`N`, :math:`4 N`)
|
|
1408
|
+
``FETetra`` 4 (:math:`N`, :math:`4 N`)
|
|
1409
|
+
``FEBrick`` 8 (:math:`N`, :math:`8 N`)
|
|
1410
|
+
============== ============== ========================
|
|
1411
|
+
|
|
1412
|
+
For more details, see the "working with datasets" examples shipped with
|
|
1413
|
+
PyTecplot in the Tecplot 360 distribution.
|
|
1414
|
+
"""
|
|
1415
|
+
assert zone_type in [ZoneType.FETriangle, ZoneType.FEQuad,
|
|
1416
|
+
ZoneType.FETetra, ZoneType.FEBrick,
|
|
1417
|
+
ZoneType.FELineSeg]
|
|
1418
|
+
return self.add_zone(zone_type, name, (num_points, num_elements),
|
|
1419
|
+
**kwargs)
|
|
1420
|
+
|
|
1421
|
+
def add_poly_zone(self, zone_type, name, num_points, num_elements,
|
|
1422
|
+
num_faces, **kwargs):
|
|
1423
|
+
"""Add a single polygonal `Zone <data_access>` to this `Dataset <tecplot.data.Dataset>`.
|
|
1424
|
+
|
|
1425
|
+
Parameters:
|
|
1426
|
+
zone_type (`ZoneType`): The type of `Zone <data_access>` to be
|
|
1427
|
+
created. Possible values are: `FEPolyhedron` and `FEPolygon`.
|
|
1428
|
+
name (`str`): Name of the new `Zone <data_access>`. This
|
|
1429
|
+
does not have to be unique.
|
|
1430
|
+
num_points (`int`): Number of points in this zone.
|
|
1431
|
+
num_elements (`int`): Number of elements in this zone.
|
|
1432
|
+
num_faces (`int`): Number of faces in this zone.
|
|
1433
|
+
**kwargs: These arguments are passed to `Dataset.add_zone`.
|
|
1434
|
+
|
|
1435
|
+
.. seealso:: `Dataset.add_zone`
|
|
1436
|
+
|
|
1437
|
+
Keyword arguments are passed to the parent zone creation method
|
|
1438
|
+
`Dataset.add_zone`.
|
|
1439
|
+
|
|
1440
|
+
.. warning:: **Setting connectivity in connected mode.**
|
|
1441
|
+
|
|
1442
|
+
When connected to a running instance of Tecplot 360 using the
|
|
1443
|
+
TecUtil Server, care must be taken to ensure that the GUI does not
|
|
1444
|
+
try to render the data between the creation of the zone and the
|
|
1445
|
+
setting of the connectivity, through the `Facemap` or `Nodemap`
|
|
1446
|
+
objects. This can be achieved by setting the plot type of the
|
|
1447
|
+
frame(s) holding on to the dataset to `PlotType.Sketch` before
|
|
1448
|
+
creating the zone and only going to `PlotType.Cartesian3D` after
|
|
1449
|
+
the connectivity is set. Tecplot 360 may get into a bad state,
|
|
1450
|
+
corrupting loaded data, if it attempts to render (especially
|
|
1451
|
+
polytope) data without connectivity.
|
|
1452
|
+
|
|
1453
|
+
.. note:: **Performance considerations for data manipulations.**
|
|
1454
|
+
|
|
1455
|
+
When performing many data-manipulation operations including adding
|
|
1456
|
+
zones, adding variables, modifying field data or connectivity, and
|
|
1457
|
+
especially in connected mode, it is recommended to do this all with
|
|
1458
|
+
the `tecplot.session.suspend()`. This will prevent the Tecplot
|
|
1459
|
+
engine from trying to "keep up" with the changes. Tecplot will be
|
|
1460
|
+
notified of all changes made upon exit of this context. This may
|
|
1461
|
+
result in significant performance gains for long operations.
|
|
1462
|
+
|
|
1463
|
+
.. note:: The **num_faces** is the number of *unique faces*.
|
|
1464
|
+
|
|
1465
|
+
The number of unique faces, given an element map can be obtained
|
|
1466
|
+
using the following function for polygon data::
|
|
1467
|
+
|
|
1468
|
+
def num_unique_faces(elementmap):
|
|
1469
|
+
return len(set( tuple(sorted([e[i], e[(i+1)%len(e)]]))
|
|
1470
|
+
for e in elementmap for i in range(len(e)) ))
|
|
1471
|
+
|
|
1472
|
+
This function creates a unique set of node pairs (edges around
|
|
1473
|
+
the polygons) and counts them. For polyhedron data, the following
|
|
1474
|
+
can be used::
|
|
1475
|
+
|
|
1476
|
+
def num_unique_faces(elementmap):
|
|
1477
|
+
return len(set( tuple(sorted(f)) for e in elementmap
|
|
1478
|
+
for f in e ))
|
|
1479
|
+
|
|
1480
|
+
which merely counts the number of unique faces defined in the
|
|
1481
|
+
element map.
|
|
1482
|
+
|
|
1483
|
+
For more details, see the "working with datasets" examples shipped with
|
|
1484
|
+
PyTecplot in the Tecplot 360 distribution.
|
|
1485
|
+
"""
|
|
1486
|
+
assert zone_type in [ZoneType.FEPolyhedron, ZoneType.FEPolygon]
|
|
1487
|
+
return self.add_zone(zone_type, name, (num_points, num_elements,
|
|
1488
|
+
num_faces), **kwargs)
|
|
1489
|
+
|
|
1490
|
+
@lock()
|
|
1491
|
+
def delete_variables(self, *variables):
|
|
1492
|
+
"""Remove `Variables <Variable>` from this `Dataset <tecplot.data.Dataset>`.
|
|
1493
|
+
|
|
1494
|
+
Parameters:
|
|
1495
|
+
*variables (`Variable` or index `int`): Variables to
|
|
1496
|
+
remove from this dataset.
|
|
1497
|
+
|
|
1498
|
+
.. code-block:: python
|
|
1499
|
+
:emphasize-lines: 3
|
|
1500
|
+
|
|
1501
|
+
>>> print(dataset.variable_names)
|
|
1502
|
+
['X','Y','Z']
|
|
1503
|
+
>>> dataset.delete_variables(dataset.variable('Z'))
|
|
1504
|
+
>>> print(dataset.variable_names)
|
|
1505
|
+
['X','Y']
|
|
1506
|
+
|
|
1507
|
+
.. Warning::
|
|
1508
|
+
Deleting `Variables <Variable>` invalidates iterators referencing
|
|
1509
|
+
them in the containing `Dataset <tecplot.data.Dataset>` such as those obtained from
|
|
1510
|
+
`Dataset.variables()`. It is recommended to create a list of the
|
|
1511
|
+
`Variables <Variable>` you want to delete and to pass that into a
|
|
1512
|
+
single call to `Dataset.delete_variables()`
|
|
1513
|
+
|
|
1514
|
+
Notes:
|
|
1515
|
+
Multiple `Variables <Variable>` can be deleted at once, though the
|
|
1516
|
+
last `Variable` can not be deleted. The following example deletes
|
|
1517
|
+
all but the first `Variable` in the `Dataset <tecplot.data.Dataset>` (usually ``X``)::
|
|
1518
|
+
|
|
1519
|
+
>>> # Try to delete all variables:
|
|
1520
|
+
>>> dataset.delete_variables(dataset.variables())
|
|
1521
|
+
>>> # Dataset requires at least one variable to
|
|
1522
|
+
>>> # exist, so it leaves the first one:
|
|
1523
|
+
>>> print(dataset.variable_names)
|
|
1524
|
+
['X']
|
|
1525
|
+
"""
|
|
1526
|
+
variables = flatten_args(*variables)
|
|
1527
|
+
with self.frame.activated():
|
|
1528
|
+
with IndexSet(*variables) as vlist:
|
|
1529
|
+
_tecutil.DataSetDeleteVar(vlist)
|
|
1530
|
+
|
|
1531
|
+
@lock()
|
|
1532
|
+
def delete_zones(self, *zones):
|
|
1533
|
+
"""Remove `Zones <data_access>` from this `Dataset <tecplot.data.Dataset>`.
|
|
1534
|
+
|
|
1535
|
+
Parameters:
|
|
1536
|
+
*zones (`Zones <data_access>` or index `integers <int>`): Zones to
|
|
1537
|
+
remove from this dataset.
|
|
1538
|
+
|
|
1539
|
+
.. code-block:: python
|
|
1540
|
+
:emphasize-lines: 3
|
|
1541
|
+
|
|
1542
|
+
>>> print(dataset.zone_names)
|
|
1543
|
+
['Zone 1', 'Zone 2']
|
|
1544
|
+
>>> dataset.delete_zones(dataset.zone('Zone 2'))
|
|
1545
|
+
>>> print(dataset.zone_names)
|
|
1546
|
+
['Zone 1']
|
|
1547
|
+
|
|
1548
|
+
.. Warning::
|
|
1549
|
+
Deleting `Zones <data_access>` invalidates iterators referencing
|
|
1550
|
+
them in the containing `Dataset <tecplot.data.Dataset>` such as those obtained from
|
|
1551
|
+
`Dataset.zones()`. It is recommended to create a list of the `Zones
|
|
1552
|
+
<data_access>` you want to delete and to pass that into a single
|
|
1553
|
+
call to `Dataset.delete_zones()`
|
|
1554
|
+
|
|
1555
|
+
Notes:
|
|
1556
|
+
Multiple `Zones <data_access>` can be deleted at once, though the
|
|
1557
|
+
last `Zone <data_access>` can not be deleted. The following example
|
|
1558
|
+
deletes all but the first `Zone <data_access>` in the `Dataset <tecplot.data.Dataset>`::
|
|
1559
|
+
|
|
1560
|
+
>>> dataset.delete_zones(dataset.zones())
|
|
1561
|
+
"""
|
|
1562
|
+
zones = flatten_args(*zones)
|
|
1563
|
+
with self.frame.activated():
|
|
1564
|
+
with IndexSet(*zones) as zlist:
|
|
1565
|
+
_tecutil.DataSetDeleteZone(zlist)
|
|
1566
|
+
|
|
1567
|
+
@property
|
|
1568
|
+
def num_solution_times(self):
|
|
1569
|
+
"""`int` (read-only): Number of solution times in the dataset.
|
|
1570
|
+
|
|
1571
|
+
This property is read-only. Solution times are grouped according to the
|
|
1572
|
+
current solution time clustering settings (see
|
|
1573
|
+
`Dataset.solution_time_clustering`). Example usage::
|
|
1574
|
+
|
|
1575
|
+
>>> print(dataset.num_solution_times)
|
|
1576
|
+
10
|
|
1577
|
+
|
|
1578
|
+
.. versionadded:: 2017.3
|
|
1579
|
+
Solution time manipulation requires Tecplot 360 2017 R3 or later.
|
|
1580
|
+
"""
|
|
1581
|
+
res = _tecutil.SolutionTimeGetNumTimeStepsByDataSetID(self.uid)
|
|
1582
|
+
success, value = res
|
|
1583
|
+
if not success:
|
|
1584
|
+
raise TecplotSystemError()
|
|
1585
|
+
return value
|
|
1586
|
+
|
|
1587
|
+
@property
|
|
1588
|
+
def solution_times(self):
|
|
1589
|
+
"""`list` of `floats <float>`: Solution times in the dataset.
|
|
1590
|
+
|
|
1591
|
+
This property is read-only. Solution times are grouped according to the
|
|
1592
|
+
current solution time clustering settings (see
|
|
1593
|
+
`Dataset.solution_time_clustering`). Example usage::
|
|
1594
|
+
|
|
1595
|
+
>>> print(dataset.solution_times)
|
|
1596
|
+
[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
|
|
1597
|
+
|
|
1598
|
+
.. versionadded:: 2017.3
|
|
1599
|
+
Solution time manipulation requires Tecplot 360 2017 R3 or later.
|
|
1600
|
+
"""
|
|
1601
|
+
res = _tecutil.SolutionTimeGetSolutionTimesByDataSetID(self.uid)
|
|
1602
|
+
success, ntimes, times = res
|
|
1603
|
+
if not success:
|
|
1604
|
+
raise TecplotSystemError()
|
|
1605
|
+
ret = list(times[:ntimes])
|
|
1606
|
+
if not _tecutil_connector.connected:
|
|
1607
|
+
_tecutil.ArrayDealloc(times)
|
|
1608
|
+
return ret
|
|
1609
|
+
|
|
1610
|
+
@lock()
|
|
1611
|
+
def branch_variables(self, zones, variables, copy_data=True):
|
|
1612
|
+
"""Breaks data sharing between zones.
|
|
1613
|
+
|
|
1614
|
+
Parameters:
|
|
1615
|
+
zones (`list` of `Zones <data_access>`): Zones to be branched.
|
|
1616
|
+
variables (`list` of `Variables <Variable>`): Variables to be
|
|
1617
|
+
branched.
|
|
1618
|
+
copy_data (`bool`, optional): Allocate space for the branched
|
|
1619
|
+
values and copy the data. If `False`, the new variables will
|
|
1620
|
+
be passive. (default: `True`)
|
|
1621
|
+
|
|
1622
|
+
.. seealso:: `Dataset.share_variables()`
|
|
1623
|
+
|
|
1624
|
+
Variable sharing allows you to lower the use of physical memory (RAM).
|
|
1625
|
+
When sharing a variable the memory used by the source zone is shared
|
|
1626
|
+
with the copied zone. Alterations to the variable in one zone will
|
|
1627
|
+
affect the other. Example usage::
|
|
1628
|
+
|
|
1629
|
+
>>> z = dataset.zone('My Zone')
|
|
1630
|
+
>>> zcopy = z.copy(share_variables=True)
|
|
1631
|
+
>>> print([zn.index for zn in z.values(0).shared_zones])
|
|
1632
|
+
[0,1]
|
|
1633
|
+
>>> dataset.branch_variables(zcopy,dataset.variable(0))
|
|
1634
|
+
>>> print([zn.index for zn in z.values(0).shared_zones])
|
|
1635
|
+
[]
|
|
1636
|
+
>>> print([zn.index for zn in z.values(1).shared_zones])
|
|
1637
|
+
[0,1]
|
|
1638
|
+
"""
|
|
1639
|
+
if not isinstance(zones, Iterable):
|
|
1640
|
+
zones = [zones]
|
|
1641
|
+
if not isinstance(variables, Iterable):
|
|
1642
|
+
variables = [variables]
|
|
1643
|
+
|
|
1644
|
+
for var in variables:
|
|
1645
|
+
varidx = getattr(var, 'index', self.variable(var).index)
|
|
1646
|
+
for zone in zones:
|
|
1647
|
+
zoneidx = getattr(zone, 'index', self.zone(zone).index)
|
|
1648
|
+
if not _tecutil.DataValueBranchShared(zoneidx + 1, varidx + 1,
|
|
1649
|
+
copy_data):
|
|
1650
|
+
raise TecplotSystemError()
|
|
1651
|
+
|
|
1652
|
+
@lock()
|
|
1653
|
+
def share_variables(self, source_zone, destination_zones, variables):
|
|
1654
|
+
"""Share field data between zones.
|
|
1655
|
+
|
|
1656
|
+
This method links the underlying data `arrays <Array>` of the
|
|
1657
|
+
destination `zones <data_access>` to the data of the source `zone
|
|
1658
|
+
<data_access>`. Modifying the array data of one zone will affect all
|
|
1659
|
+
others in this group.
|
|
1660
|
+
|
|
1661
|
+
Parameters:
|
|
1662
|
+
source_zone (`Zone <data_access>`): Zone which provides data to be
|
|
1663
|
+
shared.
|
|
1664
|
+
destination_zones (`list` of `Zones <data_access>`): Zones
|
|
1665
|
+
where data will be overwritten.
|
|
1666
|
+
variables (`list` of `Variables <Variable>`): Variables to be
|
|
1667
|
+
shared.
|
|
1668
|
+
|
|
1669
|
+
.. seealso:: `Dataset.branch_variables()`
|
|
1670
|
+
|
|
1671
|
+
Example usage::
|
|
1672
|
+
|
|
1673
|
+
>>> z = dataset.zone('My Zone')
|
|
1674
|
+
>>> zcopy = z.copy(share_variables=False)
|
|
1675
|
+
>>> print([zn.index for zn in z.values(0).shared_zones])
|
|
1676
|
+
[]
|
|
1677
|
+
>>> dataset.share_variables(zcopy,[z],[dataset.variable(0)])
|
|
1678
|
+
>>> print([zn.index for zn in z.values(0).shared_zones])
|
|
1679
|
+
[0,1]
|
|
1680
|
+
>>> print([zn.index for zn in z.values(1).shared_zones])
|
|
1681
|
+
[]
|
|
1682
|
+
"""
|
|
1683
|
+
if not isinstance(destination_zones, Iterable):
|
|
1684
|
+
destination_zones = [destination_zones]
|
|
1685
|
+
if not isinstance(variables, Iterable):
|
|
1686
|
+
variables = [variables]
|
|
1687
|
+
|
|
1688
|
+
for var in variables:
|
|
1689
|
+
varidx = getattr(var, 'index', self.variable(var).index)
|
|
1690
|
+
for zone in destination_zones:
|
|
1691
|
+
zoneidx = getattr(zone, 'index', self.zone(zone).index)
|
|
1692
|
+
source_zoneidx = getattr(source_zone, 'index',
|
|
1693
|
+
self.zone(source_zone).index)
|
|
1694
|
+
if not _tecutil.DataValueIsSharingOk(source_zoneidx+1,
|
|
1695
|
+
zoneidx+1, varidx+1):
|
|
1696
|
+
raise TecplotSystemError()
|
|
1697
|
+
_tecutil.DataValueShare(source_zoneidx+1, zoneidx+1, varidx+1)
|
|
1698
|
+
|
|
1699
|
+
@lock()
|
|
1700
|
+
def branch_connectivity(self, zones):
|
|
1701
|
+
"""Breaks connectivity sharing between zones.
|
|
1702
|
+
|
|
1703
|
+
Parameters:
|
|
1704
|
+
zones (`list` of `Zones <data_access>`): Zones to be branched.
|
|
1705
|
+
|
|
1706
|
+
.. seealso:: `Dataset.share_connectivity()`
|
|
1707
|
+
|
|
1708
|
+
Example usage::
|
|
1709
|
+
|
|
1710
|
+
>>> z = dataset.zone('My Zone')
|
|
1711
|
+
>>> zcopy = z.copy()
|
|
1712
|
+
>>> print([zn.index for zn in z.shared_connectivity])
|
|
1713
|
+
[0,1]
|
|
1714
|
+
>>> dataset.branch_connectivity(zcopy)
|
|
1715
|
+
>>> print([zn.index for zn in z.shared_connectivity])
|
|
1716
|
+
[]
|
|
1717
|
+
"""
|
|
1718
|
+
if not isinstance(zones, Iterable):
|
|
1719
|
+
zones = [zones]
|
|
1720
|
+
|
|
1721
|
+
for zone in zones:
|
|
1722
|
+
|
|
1723
|
+
try:
|
|
1724
|
+
zoneidx = getattr(zone, 'index')
|
|
1725
|
+
except:
|
|
1726
|
+
zoneidx = self.zone(zone).index
|
|
1727
|
+
if not _tecutil.DataConnectBranchShared(zoneidx + 1):
|
|
1728
|
+
raise TecplotSystemError()
|
|
1729
|
+
|
|
1730
|
+
@lock()
|
|
1731
|
+
def share_connectivity(self, source_zone, destination_zones):
|
|
1732
|
+
"""Share connectivity between zones.
|
|
1733
|
+
|
|
1734
|
+
This method links the connectivity (`nodemap` or `facemap`) of the
|
|
1735
|
+
destination `zones <data_access>` to the connectivity of the source
|
|
1736
|
+
zone. Modifying the connectivity of one zone will affect all others in
|
|
1737
|
+
this group.
|
|
1738
|
+
|
|
1739
|
+
Parameters:
|
|
1740
|
+
source_zone (`Zone <data_access>`): Zone which provides data to be
|
|
1741
|
+
shared.
|
|
1742
|
+
destination_zones (`list` of `Zones <data_access>`): Zones where
|
|
1743
|
+
connectivity list will be overwritten.
|
|
1744
|
+
|
|
1745
|
+
.. seealso:: `Dataset.branch_connectivity()`
|
|
1746
|
+
|
|
1747
|
+
Example usage::
|
|
1748
|
+
|
|
1749
|
+
>>> z = dataset.zone('My Zone')
|
|
1750
|
+
>>> zcopy = z.copy()
|
|
1751
|
+
>>> print([zn.index for zn in z.shared_connectivity])
|
|
1752
|
+
[0,1]
|
|
1753
|
+
>>> dataset.branch_connectivity(zcopy)
|
|
1754
|
+
>>> print([zn.index for zn in z.shared_connectivity])
|
|
1755
|
+
[]
|
|
1756
|
+
>>> dataset.share_connectivity(z,zcopy)
|
|
1757
|
+
>>> print([zn.index for zn in z.shared_connectivity])
|
|
1758
|
+
[0,1]
|
|
1759
|
+
"""
|
|
1760
|
+
if not isinstance(destination_zones, Iterable):
|
|
1761
|
+
destination_zones = [destination_zones]
|
|
1762
|
+
|
|
1763
|
+
def _index(obj):
|
|
1764
|
+
i = getattr(obj, 'index', None)
|
|
1765
|
+
if i is None:
|
|
1766
|
+
i = self.zone(obj).index
|
|
1767
|
+
return i
|
|
1768
|
+
|
|
1769
|
+
for zone in destination_zones:
|
|
1770
|
+
idst = _index(zone)
|
|
1771
|
+
isrc = _index(source_zone)
|
|
1772
|
+
if not _tecutil.DataConnectIsSharingOk(isrc + 1, idst + 1):
|
|
1773
|
+
raise TecplotSystemError()
|
|
1774
|
+
_tecutil.DataConnectShare(isrc + 1, idst + 1)
|
|
1775
|
+
|
|
1776
|
+
|
|
1777
|
+
@property
|
|
1778
|
+
@lock()
|
|
1779
|
+
def dataset(frame):
|
|
1780
|
+
"""`Dataset <tecplot.data.Dataset>` attached to this `Frame <layout.Frame>`.
|
|
1781
|
+
|
|
1782
|
+
Returns:
|
|
1783
|
+
`Dataset <tecplot.data.Dataset>`: The object holding onto the data associated with this
|
|
1784
|
+
`Frame <layout.Frame>`.
|
|
1785
|
+
|
|
1786
|
+
If no `Dataset <tecplot.data.Dataset>` has been created for this `Frame <layout.Frame>`, a new one is created
|
|
1787
|
+
and returned::
|
|
1788
|
+
|
|
1789
|
+
>>> dataset = frame.dataset
|
|
1790
|
+
"""
|
|
1791
|
+
if not frame.has_dataset:
|
|
1792
|
+
frame.create_dataset(frame.name + ' Dataset')
|
|
1793
|
+
dataset_uid = _tecutil.FrameGetDataSetUniqueIDByFrameID(frame.uid)
|
|
1794
|
+
return Dataset(dataset_uid, frame)
|
|
1795
|
+
|
|
1796
|
+
|
|
1797
|
+
@property
|
|
1798
|
+
def has_dataset(frame):
|
|
1799
|
+
"""`bool`: Checks to see if the `Frame <layout.Frame>` as an attached `Dataset <tecplot.data.Dataset>`
|
|
1800
|
+
|
|
1801
|
+
Example usage::
|
|
1802
|
+
|
|
1803
|
+
>>> if not frame.has_dataset:
|
|
1804
|
+
... dataset = frame.create_dataset('Dataset', ['x','y','z','p'])
|
|
1805
|
+
"""
|
|
1806
|
+
return _tecutil.DataSetIsAvailableForFrame(frame.uid)
|
|
1807
|
+
|
|
1808
|
+
layout.Frame.dataset = dataset
|
|
1809
|
+
layout.Frame.has_dataset = has_dataset
|