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.
Files changed (97) hide show
  1. pytecplot-1.5.2.dist-info/LICENSE.html +77 -0
  2. pytecplot-1.5.2.dist-info/METADATA +508 -0
  3. pytecplot-1.5.2.dist-info/RECORD +97 -0
  4. pytecplot-1.5.2.dist-info/WHEEL +5 -0
  5. pytecplot-1.5.2.dist-info/top_level.txt +1 -0
  6. tecplot/__init__.py +94 -0
  7. tecplot/annotation/__init__.py +7 -0
  8. tecplot/annotation/annotation.py +223 -0
  9. tecplot/annotation/geometry.py +369 -0
  10. tecplot/annotation/georeference.py +33 -0
  11. tecplot/annotation/image.py +185 -0
  12. tecplot/annotation/iter.py +105 -0
  13. tecplot/annotation/polyline.py +381 -0
  14. tecplot/annotation/text.py +744 -0
  15. tecplot/constant.py +401 -0
  16. tecplot/data/__init__.py +34 -0
  17. tecplot/data/array.py +645 -0
  18. tecplot/data/create.py +1 -0
  19. tecplot/data/dataset.py +1809 -0
  20. tecplot/data/extract.py +544 -0
  21. tecplot/data/face_neighbors.py +494 -0
  22. tecplot/data/facemap.py +814 -0
  23. tecplot/data/load.py +2075 -0
  24. tecplot/data/nodemap.py +577 -0
  25. tecplot/data/operate.py +928 -0
  26. tecplot/data/query.py +334 -0
  27. tecplot/data/save.py +343 -0
  28. tecplot/data/variable.py +280 -0
  29. tecplot/data/zone.py +841 -0
  30. tecplot/exception.py +201 -0
  31. tecplot/export/__init__.py +13 -0
  32. tecplot/export/animation.py +521 -0
  33. tecplot/export/export_setup.py +318 -0
  34. tecplot/export/image.py +577 -0
  35. tecplot/export/print_setup.py +218 -0
  36. tecplot/export/time_animation.py +607 -0
  37. tecplot/extension/__init__.py +14 -0
  38. tecplot/extension/ipython.py +68 -0
  39. tecplot/layout/__init__.py +20 -0
  40. tecplot/layout/frame.py +1285 -0
  41. tecplot/layout/layout.py +488 -0
  42. tecplot/layout/page.py +541 -0
  43. tecplot/legend/__init__.py +4 -0
  44. tecplot/legend/contour_legend.py +516 -0
  45. tecplot/legend/legend.py +141 -0
  46. tecplot/legend/line_legend.py +66 -0
  47. tecplot/legend/rgb_coloring_legend.py +291 -0
  48. tecplot/legend/scatter_legend.py +136 -0
  49. tecplot/macro.py +339 -0
  50. tecplot/plot/__init__.py +62 -0
  51. tecplot/plot/axes.py +881 -0
  52. tecplot/plot/axis.py +1350 -0
  53. tecplot/plot/blanking.py +584 -0
  54. tecplot/plot/contour.py +1302 -0
  55. tecplot/plot/effects.py +162 -0
  56. tecplot/plot/fieldmap.py +2159 -0
  57. tecplot/plot/grid.py +758 -0
  58. tecplot/plot/isosurface.py +1167 -0
  59. tecplot/plot/labels.py +338 -0
  60. tecplot/plot/linemap.py +1905 -0
  61. tecplot/plot/linking.py +489 -0
  62. tecplot/plot/plot.py +1791 -0
  63. tecplot/plot/rgb_coloring.py +281 -0
  64. tecplot/plot/scatter.py +396 -0
  65. tecplot/plot/slice.py +1544 -0
  66. tecplot/plot/streamtrace.py +1949 -0
  67. tecplot/plot/symbol.py +567 -0
  68. tecplot/plot/ticks.py +666 -0
  69. tecplot/plot/title.py +380 -0
  70. tecplot/plot/vector.py +679 -0
  71. tecplot/plot/view.py +868 -0
  72. tecplot/session/__init__.py +112 -0
  73. tecplot/session/aux_data.py +276 -0
  74. tecplot/session/config.py +92 -0
  75. tecplot/session/session.py +425 -0
  76. tecplot/session/state_changed.py +225 -0
  77. tecplot/session/style.py +504 -0
  78. tecplot/tecutil/__init__.py +16 -0
  79. tecplot/tecutil/arglist.py +230 -0
  80. tecplot/tecutil/captured_output.py +177 -0
  81. tecplot/tecutil/constant.py +1312 -0
  82. tecplot/tecutil/index_set.py +118 -0
  83. tecplot/tecutil/lock.py +36 -0
  84. tecplot/tecutil/message_pb2.py +39 -0
  85. tecplot/tecutil/preamble.py +54 -0
  86. tecplot/tecutil/stringlist.py +114 -0
  87. tecplot/tecutil/sv.py +1662 -0
  88. tecplot/tecutil/tecutil.py +12402 -0
  89. tecplot/tecutil/tecutil_client.py +627 -0
  90. tecplot/tecutil/tecutil_connector.py +937 -0
  91. tecplot/tecutil/tecutil_rpc.py +6845 -0
  92. tecplot/tecutil/util.py +332 -0
  93. tecplot/text/__init__.py +3 -0
  94. tecplot/text/font.py +224 -0
  95. tecplot/text/label_format.py +374 -0
  96. tecplot/text/textbox.py +106 -0
  97. tecplot/version.py +41 -0
@@ -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)