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/extract.py
ADDED
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
import ctypes
|
|
2
|
+
|
|
3
|
+
from ..tecutil import _tecutil
|
|
4
|
+
from ..constant import *
|
|
5
|
+
from ..exception import *
|
|
6
|
+
from .. import layout, macro, tecutil, version
|
|
7
|
+
from ..tecutil import sv
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@tecutil.lock()
|
|
11
|
+
def extract_blanked_zones(*zones, **kwargs):
|
|
12
|
+
"""Extract subsets of `Zones`_ based on blanking conditions of the plot.
|
|
13
|
+
|
|
14
|
+
Parameters:
|
|
15
|
+
*zones (`Zones`_, required): Set of source zones to extract.
|
|
16
|
+
|
|
17
|
+
Keyword Arguments:
|
|
18
|
+
plot (`Cartesian3DFieldPlot` or other data-backed plot type, optional):
|
|
19
|
+
The plot that defines the blanking conditions. By default, the
|
|
20
|
+
active plot will be used.
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
`Zones`_: A `list` of the extracted zones.
|
|
24
|
+
|
|
25
|
+
A new zone will be created for each zone specified unless blanking dictates
|
|
26
|
+
that all cells and points in the entire zone are blanked. The following
|
|
27
|
+
example extracts all zones in the dataset:
|
|
28
|
+
|
|
29
|
+
.. code-block:: python
|
|
30
|
+
|
|
31
|
+
import os
|
|
32
|
+
|
|
33
|
+
import tecplot as tp
|
|
34
|
+
from tecplot.constant import *
|
|
35
|
+
|
|
36
|
+
examples_dir = tp.session.tecplot_examples_directory()
|
|
37
|
+
datafile = os.path.join(examples_dir, 'SimpleData', 'VortexShedding.plt')
|
|
38
|
+
|
|
39
|
+
dataset = tp.data.load_tecplot(datafile)
|
|
40
|
+
|
|
41
|
+
plot = tp.active_frame().plot()
|
|
42
|
+
plot.show_contour = True
|
|
43
|
+
|
|
44
|
+
xax = plot.axes.x_axis
|
|
45
|
+
xax.min = -0.005
|
|
46
|
+
xax.max = 0.015
|
|
47
|
+
yax = plot.axes.y_axis
|
|
48
|
+
yax.min = -0.01
|
|
49
|
+
yax.max = 0.002
|
|
50
|
+
|
|
51
|
+
# Setup value blanking
|
|
52
|
+
vblank = plot.value_blanking
|
|
53
|
+
constraint = vblank.constraint(0)
|
|
54
|
+
constraint.variable_index = 1
|
|
55
|
+
constraint.comparison_operator = RelOp.GreaterThan
|
|
56
|
+
constraint.active = True
|
|
57
|
+
vblank.active = True
|
|
58
|
+
|
|
59
|
+
# Use list comprehension to get all zones assocaitated with
|
|
60
|
+
# a specific strand, in this case strand 1
|
|
61
|
+
in_zns = [zn for zn in dataset.zones() if zn.strand == 1]
|
|
62
|
+
|
|
63
|
+
# Extract all zones assocaitated with strand 1
|
|
64
|
+
ext_zns = tp.data.extract.extract_blanked_zones(in_zns)
|
|
65
|
+
|
|
66
|
+
# Place all extracted zones into the same strand
|
|
67
|
+
for zn in ext_zns:
|
|
68
|
+
zn.strand = 2
|
|
69
|
+
|
|
70
|
+
# Turn off plotting for the original zone and turn on plotting
|
|
71
|
+
# of the extracted zones.
|
|
72
|
+
plot.fieldmap(0).show = False
|
|
73
|
+
plot.fieldmap(1).show = True
|
|
74
|
+
|
|
75
|
+
tp.export.save_time_animation_mpeg4('extract_blanked_zones.mp4',
|
|
76
|
+
width=400, end_time=0.0004,
|
|
77
|
+
supersample=3)
|
|
78
|
+
|
|
79
|
+
.. raw:: html
|
|
80
|
+
|
|
81
|
+
<video controls>
|
|
82
|
+
<source src="../_static/videos/extract_blanked_zones.m4v" type="video/mp4">
|
|
83
|
+
I'm sorry; your browser doesn't support HTML5 MPEG4/H.264 video.
|
|
84
|
+
</video>
|
|
85
|
+
|
|
86
|
+
.. versionadded:: 2020.1
|
|
87
|
+
Extracting blanked zones requires Tecplot 360 2020 R1 or later.
|
|
88
|
+
"""
|
|
89
|
+
if __debug__:
|
|
90
|
+
if version.sdk_version_info < (2020,):
|
|
91
|
+
msg = 'Extracting blanked zones not supported.'
|
|
92
|
+
raise TecplotOutOfDateEngineError((2020,), msg)
|
|
93
|
+
|
|
94
|
+
if not zones:
|
|
95
|
+
msg = 'extract_blanked_zones(*zones) requires at least one zone'
|
|
96
|
+
raise TecplotLogicError(msg)
|
|
97
|
+
plot = kwargs.get('plot', None)
|
|
98
|
+
if not plot:
|
|
99
|
+
plot = layout.active_frame().plot()
|
|
100
|
+
dataset = plot.frame.dataset
|
|
101
|
+
num_zones = dataset.num_zones
|
|
102
|
+
with plot.activated():
|
|
103
|
+
zones = tecutil.flatten_args(*zones)
|
|
104
|
+
zone_indices = (getattr(z, 'index', z) for z in zones)
|
|
105
|
+
cmd = 'Zones = [{}]'.format(','.join(str(z + 1) for z in zone_indices))
|
|
106
|
+
macro.execute_extended_command('ExtractBlankedZones', cmd)
|
|
107
|
+
return [dataset.zone(i) for i in range(num_zones, dataset.num_zones)]
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@tecutil.lock()
|
|
111
|
+
def extract_line(points, num_points=None, frame=None, dataset=None):
|
|
112
|
+
"""Create new zone from a line in the dataset.
|
|
113
|
+
|
|
114
|
+
Parameters:
|
|
115
|
+
points (``2D numeric array``): The points defining the line in two or
|
|
116
|
+
three dimensions. This array must be of the shape *(N, D)* where
|
|
117
|
+
*N* is the number points and *D* is the number of dimensions. That
|
|
118
|
+
is, it must take the form ``[(x0, y0, z0), (x1, y1, z1) ...]``.
|
|
119
|
+
Points that do not lie within the dataset volume will be removed
|
|
120
|
+
from the resulting zone.
|
|
121
|
+
num_points (`int`, optional): The number of points to evenly
|
|
122
|
+
distribute along the polyline. (default: length of *points* or *N*)
|
|
123
|
+
frame (`Frame <layout.Frame>`, optional): A `Frame <layout.Frame>` that holds the `Dataset <tecplot.data.Dataset>` to
|
|
124
|
+
operate on which must match *dataset* if given. (default: currently
|
|
125
|
+
active `Frame <layout.Frame>`)
|
|
126
|
+
dataset (`Dataset <tecplot.data.Dataset>`, optional): The `Dataset <tecplot.data.Dataset>` to operate on which must
|
|
127
|
+
be attached to *frame* if given. (default: currently active
|
|
128
|
+
`Dataset <tecplot.data.Dataset>`)
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
A 1D `OrderedZone` representing a line through the data. Points outside
|
|
132
|
+
of the dataset will be removed from the extracted zone resulting in
|
|
133
|
+
fewer points than input.
|
|
134
|
+
|
|
135
|
+
.. warning::
|
|
136
|
+
|
|
137
|
+
Line extraction is only available when the plot type is set to
|
|
138
|
+
`Cartesian2D` or `Cartesian3D`::
|
|
139
|
+
|
|
140
|
+
>>> from tecplot.constant import PlotType
|
|
141
|
+
>>> frame.plot_type = PlotType.Cartesian3D
|
|
142
|
+
|
|
143
|
+
This example shows how to extract a zone along a line, overlaying the
|
|
144
|
+
result in a new frame:
|
|
145
|
+
|
|
146
|
+
.. code-block:: python
|
|
147
|
+
:emphasize-lines: 26
|
|
148
|
+
|
|
149
|
+
import numpy as np
|
|
150
|
+
from os import path
|
|
151
|
+
|
|
152
|
+
import tecplot as tp
|
|
153
|
+
from tecplot.constant import *
|
|
154
|
+
|
|
155
|
+
examples_dir = tp.session.tecplot_examples_directory()
|
|
156
|
+
datafile = path.join(examples_dir, 'SimpleData', 'VortexShedding.plt')
|
|
157
|
+
dataset = tp.data.load_tecplot(datafile)
|
|
158
|
+
|
|
159
|
+
frame = tp.active_frame()
|
|
160
|
+
frame.activate()
|
|
161
|
+
plot = frame.plot()
|
|
162
|
+
plot.contour(0).variable = dataset.variable("P(N/M2)")
|
|
163
|
+
plot.show_contour = True
|
|
164
|
+
plot.contour(0).levels.reset(num_levels=11)
|
|
165
|
+
plot.contour(0).colormap_name = 'Sequential - Yellow/Green/Blue'
|
|
166
|
+
|
|
167
|
+
plot.axes.y_axis.min = -0.01
|
|
168
|
+
plot.axes.y_axis.max = 0.01
|
|
169
|
+
plot.axes.x_axis.min = -0.005
|
|
170
|
+
plot.axes.x_axis.max = 0.015
|
|
171
|
+
|
|
172
|
+
xx = np.linspace(0, 0.01, 100)
|
|
173
|
+
yy = np.zeros(100)
|
|
174
|
+
line = tp.data.extract.extract_line(zip(xx, yy))
|
|
175
|
+
|
|
176
|
+
plot.show_mesh = True
|
|
177
|
+
plot.fieldmap(0).mesh.show = False
|
|
178
|
+
|
|
179
|
+
frame = tp.active_page().add_frame()
|
|
180
|
+
frame.position = (3.0, 0.5)
|
|
181
|
+
frame.height = 2
|
|
182
|
+
frame.width = 4
|
|
183
|
+
plot = tp.active_frame().plot(PlotType.XYLine)
|
|
184
|
+
plot.activate()
|
|
185
|
+
|
|
186
|
+
plot.delete_linemaps()
|
|
187
|
+
lmap = plot.add_linemap('data', line, x=dataset.variable('P(N/M2)'),
|
|
188
|
+
y=dataset.variable('T(K)'))
|
|
189
|
+
lmap.line.line_thickness = 2.0
|
|
190
|
+
plot.axes.x_axis(0).title.font.size = 10
|
|
191
|
+
plot.axes.y_axis(0).title.font.size = 10
|
|
192
|
+
plot.axes.viewport.left = 20
|
|
193
|
+
plot.axes.viewport.bottom = 20
|
|
194
|
+
plot.view.fit()
|
|
195
|
+
|
|
196
|
+
tp.export.save_png("extract_line.png", region=ExportRegion.AllFrames,
|
|
197
|
+
width=600, supersample=3)
|
|
198
|
+
|
|
199
|
+
.. figure:: /_static/images/extract_line.png
|
|
200
|
+
:width: 300px
|
|
201
|
+
:figwidth: 300px
|
|
202
|
+
"""
|
|
203
|
+
if dataset is None:
|
|
204
|
+
if frame is None:
|
|
205
|
+
frame = layout.active_frame()
|
|
206
|
+
dataset = frame.dataset
|
|
207
|
+
elif frame is None:
|
|
208
|
+
frame = dataset.frame
|
|
209
|
+
|
|
210
|
+
if __debug__:
|
|
211
|
+
if frame.plot_type not in [PlotType.Cartesian2D, PlotType.Cartesian3D]:
|
|
212
|
+
msg = 'must be in a cartesian plot type to extract a line'
|
|
213
|
+
raise TecplotLogicError(msg)
|
|
214
|
+
if dataset != frame.dataset:
|
|
215
|
+
msg = 'dataset is not attached to given frame'
|
|
216
|
+
raise TecplotLogicError(msg)
|
|
217
|
+
|
|
218
|
+
new_zone_index = dataset.num_zones
|
|
219
|
+
|
|
220
|
+
try:
|
|
221
|
+
_ = points[0]
|
|
222
|
+
except TypeError:
|
|
223
|
+
points = list(points)
|
|
224
|
+
|
|
225
|
+
ndim = len(points[0])
|
|
226
|
+
if num_points is None:
|
|
227
|
+
num_points = len(points)
|
|
228
|
+
|
|
229
|
+
n = len(points)
|
|
230
|
+
xx = (ctypes.c_double * n)(*(float(p[0]) for p in points))
|
|
231
|
+
yy = (ctypes.c_double * n)(*(float(p[1]) for p in points))
|
|
232
|
+
zz = (ctypes.c_double * n)(*([0.]*len(xx)
|
|
233
|
+
if ndim < 3
|
|
234
|
+
else (float(p[2]) for p in points)))
|
|
235
|
+
|
|
236
|
+
extract_through_volume = ndim == 3
|
|
237
|
+
only_points_on_line = num_points == len(points)
|
|
238
|
+
include_distance = False
|
|
239
|
+
to_file = False
|
|
240
|
+
filename = None
|
|
241
|
+
|
|
242
|
+
try:
|
|
243
|
+
if not _tecutil.ExtractFromPolyline(xx, yy, zz, len(xx),
|
|
244
|
+
extract_through_volume,
|
|
245
|
+
only_points_on_line,
|
|
246
|
+
include_distance, num_points,
|
|
247
|
+
to_file, filename):
|
|
248
|
+
raise TecplotSystemError()
|
|
249
|
+
except TecplotLogicError as e:
|
|
250
|
+
# If some of the points are outside of the data, the zone
|
|
251
|
+
# is still extracted and this exception is not technically
|
|
252
|
+
# an error. A different message is generated if all of the
|
|
253
|
+
# points are outside of the data which is re-raised.
|
|
254
|
+
if 'Probe Position is outside of the data' not in str(e):
|
|
255
|
+
raise
|
|
256
|
+
|
|
257
|
+
return dataset.zone(new_zone_index)
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
@tecutil.lock()
|
|
261
|
+
def extract_slice(origin=(0, 0, 0), normal=(0, 0, 1), source=None,
|
|
262
|
+
mode=ExtractMode.SingleZone, copy_cell_centers=None,
|
|
263
|
+
assign_strand_ids=None,
|
|
264
|
+
transient_mode=TransientOperationMode.SingleSolutionTime,
|
|
265
|
+
frame=None, dataset=None, **kw):
|
|
266
|
+
"""Create new zone from a plane in the dataset.
|
|
267
|
+
|
|
268
|
+
Parameters:
|
|
269
|
+
origin (array of three `floats <float>`): Point in space,
|
|
270
|
+
:math:`(x, y, z)`, that lies on the slice plane.
|
|
271
|
+
normal (array of three `floats <float>`): Vector direction,
|
|
272
|
+
:math:`(x, y, z)`, indicating the normal of the slice plane.
|
|
273
|
+
source (`SliceSource`): Source zone types to consider when extracting
|
|
274
|
+
the slice. Possible values: `SliceSource.LinearZones`,
|
|
275
|
+
`SliceSource.SurfaceZones`, `SliceSource.SurfacesOfVolumeZones`,
|
|
276
|
+
`SliceSource.VolumeZones` (default).
|
|
277
|
+
mode (`ExtractMode`): Controls how many zones are created. Possible
|
|
278
|
+
values are: `ExtractMode.SingleZone` (default),
|
|
279
|
+
`ExtractMode.OneZonePerConnectedRegion` and
|
|
280
|
+
`ExtractMode.OneZonePerSourceZone`.
|
|
281
|
+
copy_cell_centers (`bool`): If `True`, cell-center
|
|
282
|
+
values will be copied when possible to the extracted slice plane.
|
|
283
|
+
Cell-centers are copied when a variable is cell-centered for all
|
|
284
|
+
the source zones through which the slice passes. Otherwise,
|
|
285
|
+
extracted planes use node-centered data, which is calculated by
|
|
286
|
+
interpolation. (default: `False`)
|
|
287
|
+
assign_strand_ids (`bool`): Automatically assign strand IDs
|
|
288
|
+
to the data extracted from transient sources. This is only
|
|
289
|
+
available if *multiple_zones* is `False`. (default: `True`)
|
|
290
|
+
transient_mode (`TransientOperationMode`): Determines which solution
|
|
291
|
+
times are used to extract slices when transient data is available
|
|
292
|
+
in the dataset. Possible values are
|
|
293
|
+
`TransientOperationMode.SingleSolutionTime` (default) or
|
|
294
|
+
`TransientOperationMode.AllSolutionTimes`.
|
|
295
|
+
frame (`Frame <layout.Frame>`, optional): A `Frame <layout.Frame>` that holds the `Dataset <tecplot.data.Dataset>` to
|
|
296
|
+
operate on which must match *dataset* if given. (default: currently
|
|
297
|
+
active `Frame <layout.Frame>`)
|
|
298
|
+
dataset (`Dataset <tecplot.data.Dataset>`, optional): The `Dataset <tecplot.data.Dataset>` to operate on which must
|
|
299
|
+
be attached to *frame* if given. (default: currently active
|
|
300
|
+
`Dataset <tecplot.data.Dataset>`)
|
|
301
|
+
|
|
302
|
+
Returns:
|
|
303
|
+
One or a `list` of `Zones <data_access>` representing a planar slice.
|
|
304
|
+
|
|
305
|
+
.. warning::
|
|
306
|
+
|
|
307
|
+
Slicing is only available when the plot type is set to 3D::
|
|
308
|
+
|
|
309
|
+
>>> from tecplot.constant import PlotType
|
|
310
|
+
>>> frame.plot_type = PlotType.Cartesian3D
|
|
311
|
+
|
|
312
|
+
.. note::
|
|
313
|
+
|
|
314
|
+
The extracted zone is returned if **mode** is `ExtractMode.SingleZone`
|
|
315
|
+
and **transient_mode** is `TransientOperationMode.SingleSolutionTime`,
|
|
316
|
+
otherwise a `generator <https://docs.python.org/3/reference/expressions.html#generator-expressions>`_
|
|
317
|
+
of the extracted zones.
|
|
318
|
+
|
|
319
|
+
.. seealso:: `tecplot.plot.SliceGroup.extract()`
|
|
320
|
+
|
|
321
|
+
This example shows extracting a slice zone from the surface a wing:
|
|
322
|
+
|
|
323
|
+
.. code-block:: python
|
|
324
|
+
:emphasize-lines: 16-20
|
|
325
|
+
|
|
326
|
+
import os
|
|
327
|
+
import tecplot as tp
|
|
328
|
+
from tecplot.constant import PlotType, SliceSource
|
|
329
|
+
|
|
330
|
+
examples_dir = tp.session.tecplot_examples_directory()
|
|
331
|
+
datafile = os.path.join(examples_dir, 'OneraM6wing',
|
|
332
|
+
'OneraM6_SU2_RANS.plt')
|
|
333
|
+
dataset = tp.data.load_tecplot(datafile)
|
|
334
|
+
|
|
335
|
+
frame = tp.active_frame()
|
|
336
|
+
frame.plot_type = PlotType.Cartesian3D
|
|
337
|
+
|
|
338
|
+
# set active plot to 3D and extract
|
|
339
|
+
# an arbitrary slice from the surface
|
|
340
|
+
# data on the wing
|
|
341
|
+
extracted_slice = tp.data.extract.extract_slice(
|
|
342
|
+
origin=(0, 0.25, 0),
|
|
343
|
+
normal=(0, 1, 0),
|
|
344
|
+
source=SliceSource.SurfaceZones,
|
|
345
|
+
dataset=dataset)
|
|
346
|
+
|
|
347
|
+
# switch plot type in current frame, clear plot
|
|
348
|
+
plot = frame.plot(PlotType.XYLine)
|
|
349
|
+
plot.activate()
|
|
350
|
+
plot.delete_linemaps()
|
|
351
|
+
|
|
352
|
+
# create line plot from extracted zone data
|
|
353
|
+
cp_linemap = plot.add_linemap(
|
|
354
|
+
name='Quarter-chord C_p',
|
|
355
|
+
zone=extracted_slice,
|
|
356
|
+
x=dataset.variable('x'),
|
|
357
|
+
y=dataset.variable('Pressure_Coefficient'))
|
|
358
|
+
|
|
359
|
+
# set style of linemap plot and
|
|
360
|
+
# update axes limits to show data
|
|
361
|
+
cp_linemap.line.color = tp.constant.Color.Blue
|
|
362
|
+
cp_linemap.line.line_thickness = 0.8
|
|
363
|
+
cp_linemap.y_axis.reverse = True
|
|
364
|
+
plot.view.fit()
|
|
365
|
+
|
|
366
|
+
# export image of pressure coefficient as a function of x
|
|
367
|
+
tp.export.save_png('wing_slice_pressure_coeff.png', 600, supersample=3)
|
|
368
|
+
|
|
369
|
+
.. figure:: /_static/images/wing_slice_pressure_coeff.png
|
|
370
|
+
:width: 300px
|
|
371
|
+
:figwidth: 300px
|
|
372
|
+
"""
|
|
373
|
+
if 'multiple_zones' in kw:
|
|
374
|
+
tecutil.api_changed('''\
|
|
375
|
+
"multiple_zones" has been removed, please use "mode" instead.''',
|
|
376
|
+
'0.13', '2018 R2')
|
|
377
|
+
|
|
378
|
+
if dataset is None:
|
|
379
|
+
if frame is None:
|
|
380
|
+
frame = layout.active_frame()
|
|
381
|
+
dataset = frame.dataset
|
|
382
|
+
elif frame is None:
|
|
383
|
+
frame = dataset.frame
|
|
384
|
+
|
|
385
|
+
mode = ExtractMode(mode)
|
|
386
|
+
transient_mode = TransientOperationMode(transient_mode)
|
|
387
|
+
|
|
388
|
+
if __debug__:
|
|
389
|
+
if frame.dataset != dataset:
|
|
390
|
+
raise TecplotLogicError('Dataset is not attached to frame.')
|
|
391
|
+
if frame.plot_type is not PlotType.Cartesian3D:
|
|
392
|
+
msg = 'Plot Type must be Cartesian3D to create a slice.'
|
|
393
|
+
raise TecplotLogicError(msg)
|
|
394
|
+
|
|
395
|
+
with frame.activated():
|
|
396
|
+
nzones = dataset.num_zones
|
|
397
|
+
with tecutil.ArgList() as arglist:
|
|
398
|
+
arglist[sv.ORIGINX] = float(origin[0])
|
|
399
|
+
arglist[sv.ORIGINY] = float(origin[1])
|
|
400
|
+
arglist[sv.ORIGINZ] = float(origin[2])
|
|
401
|
+
arglist[sv.NORMALX] = float(normal[0])
|
|
402
|
+
arglist[sv.NORMALY] = float(normal[1])
|
|
403
|
+
arglist[sv.NORMALZ] = float(normal[2])
|
|
404
|
+
if source is not None:
|
|
405
|
+
arglist[sv.SLICESOURCE] = SliceSource(source)
|
|
406
|
+
if mode != ExtractMode.SingleZone:
|
|
407
|
+
arglist[sv.EXTRACTMODE] = mode
|
|
408
|
+
arglist[sv.COPYCELLCENTEREDVALUES] = copy_cell_centers
|
|
409
|
+
if assign_strand_ids is not None:
|
|
410
|
+
arglist[sv.AUTOSTRANDTRANSIENTDATA] = bool(assign_strand_ids)
|
|
411
|
+
if transient_mode != TransientOperationMode.SingleSolutionTime:
|
|
412
|
+
arglist[sv.TRANSIENTOPERATIONMODE] = transient_mode
|
|
413
|
+
if not _tecutil.CreateSliceZoneFromPlneX(arglist):
|
|
414
|
+
raise TecplotSystemError()
|
|
415
|
+
if dataset.num_zones == nzones:
|
|
416
|
+
raise TecplotLogicError('No zones found when extracting slice')
|
|
417
|
+
|
|
418
|
+
if (
|
|
419
|
+
mode == ExtractMode.SingleZone and
|
|
420
|
+
transient_mode == TransientOperationMode.SingleSolutionTime
|
|
421
|
+
):
|
|
422
|
+
return dataset.zone(nzones)
|
|
423
|
+
else:
|
|
424
|
+
return (dataset.zone(i) for i in range(nzones, dataset.num_zones))
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
@tecutil.lock()
|
|
428
|
+
def extract_connected_regions(*zones, **kwargs):
|
|
429
|
+
"""Create new zones from regions of connected cells.
|
|
430
|
+
|
|
431
|
+
Parameters:
|
|
432
|
+
*zones (`Zones`_, required): Source zones from which to extract
|
|
433
|
+
connected regions. All source zones must be finite-element
|
|
434
|
+
zones, either classic FE or polygonal/polyhedral.
|
|
435
|
+
|
|
436
|
+
Keyword Arguments:
|
|
437
|
+
assign_strand_ids (`bool`, optional): Automatically assign strand IDs
|
|
438
|
+
to the zones extracted from transient sources. If True the
|
|
439
|
+
resulting zones will be all be assigned to the same newly created
|
|
440
|
+
strand id. (default: `True`)
|
|
441
|
+
frame (`Frame <layout.Frame>`, optional): A `Frame <layout.Frame>` that holds the `Dataset <tecplot.data.Dataset>` to
|
|
442
|
+
operate on which must match *dataset* if given. (default: currently
|
|
443
|
+
active `Frame <layout.Frame>`)
|
|
444
|
+
dataset (`Dataset <tecplot.data.Dataset>`, optional): The `Dataset <tecplot.data.Dataset>` to operate on which must
|
|
445
|
+
be attached to *frame* if given. (default: currently active
|
|
446
|
+
`Dataset <tecplot.data.Dataset>`)
|
|
447
|
+
|
|
448
|
+
Returns:
|
|
449
|
+
A `list` of the extracted `Zones <data_access>`.
|
|
450
|
+
|
|
451
|
+
.. versionadded:: 2020.2
|
|
452
|
+
Extracting connected regions requires Tecplot 360 2020 R2 or later.
|
|
453
|
+
"""
|
|
454
|
+
if __debug__:
|
|
455
|
+
if version.sdk_version_info < (2020, 2):
|
|
456
|
+
msg = 'Extracting connected regions not supported.'
|
|
457
|
+
raise TecplotOutOfDateEngineError((2020, 2), msg)
|
|
458
|
+
|
|
459
|
+
if not zones:
|
|
460
|
+
msg = 'extract_connected_regions(*zones) requires at least one zone'
|
|
461
|
+
raise TecplotLogicError(msg)
|
|
462
|
+
assign_strand_ids = kwargs.get('assign_strand_ids', True)
|
|
463
|
+
frame = kwargs.get('frame', None)
|
|
464
|
+
dataset = kwargs.get('dataset', None)
|
|
465
|
+
|
|
466
|
+
if dataset is None:
|
|
467
|
+
if frame is None:
|
|
468
|
+
frame = layout.active_frame()
|
|
469
|
+
dataset = frame.dataset
|
|
470
|
+
elif frame is None:
|
|
471
|
+
frame = dataset.frame
|
|
472
|
+
|
|
473
|
+
if __debug__:
|
|
474
|
+
if not frame.has_dataset:
|
|
475
|
+
msg = 'The specified frame (or active frame if no frame is ' + \
|
|
476
|
+
'specified) must have a data set.'
|
|
477
|
+
raise TecplotLogicError(msg)
|
|
478
|
+
|
|
479
|
+
nzones = dataset.num_zones
|
|
480
|
+
|
|
481
|
+
zone_tuple = tecutil.flatten_args(*zones)
|
|
482
|
+
with frame.activated():
|
|
483
|
+
with tecutil.ArgList() as arglist, \
|
|
484
|
+
tecutil.IndexSet(zone_tuple) as zone_set:
|
|
485
|
+
arglist[sv.SOURCEZONES] = zone_set
|
|
486
|
+
arglist[sv.FRAME] = frame.uid
|
|
487
|
+
arglist[sv.AUTOSTRANDTRANSIENTDATA] = assign_strand_ids
|
|
488
|
+
if not _tecutil.ExtractConnectedRegionsX(arglist):
|
|
489
|
+
raise TecplotSystemError()
|
|
490
|
+
return [dataset.zone(i) for i in range(nzones, dataset.num_zones)]
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
@tecutil.lock()
|
|
494
|
+
def triangulate(*zones, **kwargs):
|
|
495
|
+
"""Create a new zone by forming triangles from points in 2D zones.
|
|
496
|
+
|
|
497
|
+
Arguments:
|
|
498
|
+
*zones (`Zones`_): Set of 2-dimensional source zones to triangulate.
|
|
499
|
+
|
|
500
|
+
Keyword Arguments:
|
|
501
|
+
boundary_zones (`list` of :math:`I`-Ordered `Zones`_, optional): Set
|
|
502
|
+
of :math:`I`-ordered zones that define the boundaries across which
|
|
503
|
+
no triangles can be created. (default: `None`)
|
|
504
|
+
include_boundary_points (`bool`, optional): If `True`, boundary points
|
|
505
|
+
will be used to create triangles. (default: `False`)
|
|
506
|
+
keep_factor (`float` in the range [0.0, 0.5], optional): The smaller
|
|
507
|
+
the number, the more likely it will be that highly obtuse triangles
|
|
508
|
+
will be created opening toward the outside of the triangulated
|
|
509
|
+
zone.
|
|
510
|
+
plot (`Cartesian2DFieldPlot`, optional): The plot defining the
|
|
511
|
+
:math:`(x, y)` variables in the dataset. If not set, the active
|
|
512
|
+
plot will be used which must be of type `Cartesian2DFieldPlot`.
|
|
513
|
+
|
|
514
|
+
Returns:
|
|
515
|
+
`ClassicFEZone`: The resulting triangulated zone.
|
|
516
|
+
|
|
517
|
+
The active plot or the plot specified must be of type
|
|
518
|
+
`Cartesian2DFieldPlot` and the boundary zones, if supplied, may only be
|
|
519
|
+
:math:`I`-ordered zones. This example creates a new zone by triangulating
|
|
520
|
+
data points from two other `Zones`_::
|
|
521
|
+
|
|
522
|
+
>>> zone0 = dataset.zone('Zone 0')
|
|
523
|
+
>>> zone1 = dataset.zone('Zone 1')
|
|
524
|
+
>>> new_zone = tp.data.extract.triangulate(zone0, zone1)
|
|
525
|
+
"""
|
|
526
|
+
boundary_zones = kwargs.get('boundary_zones', None)
|
|
527
|
+
include_boundary_points = bool(kwargs.get('include_boundary_points', False))
|
|
528
|
+
keep_factor = float(kwargs.get('keep_factor', 0.25))
|
|
529
|
+
plot = kwargs.get('plot', None)
|
|
530
|
+
if not plot:
|
|
531
|
+
plot = layout.active_frame().plot()
|
|
532
|
+
|
|
533
|
+
with plot.activated():
|
|
534
|
+
zones = tecutil.flatten_args(*zones)
|
|
535
|
+
dataset = zones[0].dataset
|
|
536
|
+
num_zones = dataset.num_zones
|
|
537
|
+
with tecutil.optional(tecutil.IndexSet, zones) as zones:
|
|
538
|
+
with tecutil.optional(tecutil.IndexSet, boundary_zones) as bzones:
|
|
539
|
+
res = _tecutil.Triangulate(zones, bool(bzones), bzones,
|
|
540
|
+
include_boundary_points, keep_factor)
|
|
541
|
+
success, num_coincident_points = res
|
|
542
|
+
if not success:
|
|
543
|
+
raise TecplotSystemError()
|
|
544
|
+
return dataset.zone(num_zones)
|