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/plot/plot.py
ADDED
|
@@ -0,0 +1,1791 @@
|
|
|
1
|
+
import contextlib
|
|
2
|
+
import fnmatch
|
|
3
|
+
import re
|
|
4
|
+
import warnings
|
|
5
|
+
|
|
6
|
+
from ..tecutil import _tecutil, _tecutil_connector, sv
|
|
7
|
+
from ..constant import *
|
|
8
|
+
from ..exception import *
|
|
9
|
+
from .. import legend, session, tecutil, text, version
|
|
10
|
+
from .axes import (Cartesian2DFieldAxes, Cartesian3DFieldAxes, SketchAxes,
|
|
11
|
+
PolarLineAxes, XYLineAxes)
|
|
12
|
+
from .contour import ContourGroup
|
|
13
|
+
from .fieldmap import (Cartesian2DFieldmap, Cartesian2DFieldmapCollection,
|
|
14
|
+
Cartesian3DFieldmap, Cartesian3DFieldmapCollection,
|
|
15
|
+
FieldmapCollection)
|
|
16
|
+
from .isosurface import IsosurfaceGroup
|
|
17
|
+
from .streamtrace import StreamtraceRodRibbon, Streamtraces
|
|
18
|
+
from .vector import Vector2D, Vector3D
|
|
19
|
+
from . import (blanking, effects, labels, linking, linemap,
|
|
20
|
+
rgb_coloring, scatter, slice, view)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Plot(session.Style):
|
|
24
|
+
def __init__(self, frame, *svargs):
|
|
25
|
+
self.frame = frame
|
|
26
|
+
super().__init__(*svargs, uniqueid=frame.uid)
|
|
27
|
+
|
|
28
|
+
def __eq__(self, that):
|
|
29
|
+
return isinstance(that, type(self)) and self.frame == that.frame
|
|
30
|
+
|
|
31
|
+
def __ne__(self, that):
|
|
32
|
+
return not (self == that)
|
|
33
|
+
|
|
34
|
+
@contextlib.contextmanager
|
|
35
|
+
def activated(self):
|
|
36
|
+
"""Context to ensure this plot is active.
|
|
37
|
+
|
|
38
|
+
Example usage::
|
|
39
|
+
|
|
40
|
+
>>> from tecplot.constant import PlotType
|
|
41
|
+
>>> frame = tecplot.active_frame()
|
|
42
|
+
>>> frame.plot_type = PlotType.XYLine # set active plot type
|
|
43
|
+
>>> plot = frame.plot(PlotType.Cartesian3D) # get inactive plot
|
|
44
|
+
>>> print(frame.plot_type)
|
|
45
|
+
PlotType.XYLine
|
|
46
|
+
>>> with plot.activated():
|
|
47
|
+
... print(frame.plot_type) # 3D plot temporarily active
|
|
48
|
+
PlotType.Cartesian3D
|
|
49
|
+
>>> print(frame.plot_type) # original plot type restored
|
|
50
|
+
PlotType.XYLine
|
|
51
|
+
"""
|
|
52
|
+
with self.frame.activated():
|
|
53
|
+
orig_plot = self.frame.plot()
|
|
54
|
+
try:
|
|
55
|
+
self.activate()
|
|
56
|
+
yield self
|
|
57
|
+
finally:
|
|
58
|
+
orig_plot.activate()
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class SketchPlot(Plot):
|
|
62
|
+
"""A plot space with no data attached.
|
|
63
|
+
|
|
64
|
+
.. code-block:: python
|
|
65
|
+
:emphasize-lines: 5,8-9
|
|
66
|
+
|
|
67
|
+
import tecplot as tp
|
|
68
|
+
from tecplot.constant import PlotType
|
|
69
|
+
|
|
70
|
+
frame = tp.active_frame()
|
|
71
|
+
plot = frame.plot(PlotType.Sketch)
|
|
72
|
+
|
|
73
|
+
frame.add_text('Hello, World!', (36, 50), size=34)
|
|
74
|
+
plot.axes.x_axis.show = True
|
|
75
|
+
plot.axes.y_axis.show = True
|
|
76
|
+
|
|
77
|
+
tp.export.save_png('plot_sketch.png', 600, supersample=3)
|
|
78
|
+
|
|
79
|
+
.. figure:: /_static/images/plot_sketch.png
|
|
80
|
+
:width: 300px
|
|
81
|
+
:figwidth: 300px
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
def activate(self):
|
|
85
|
+
"""Make this the active plot type on the parent frame.
|
|
86
|
+
|
|
87
|
+
Example usage::
|
|
88
|
+
|
|
89
|
+
>>> from tecplot.constant import PlotType
|
|
90
|
+
>>> plot = frame.plot(PlotType.Sketch)
|
|
91
|
+
>>> plot.activate()
|
|
92
|
+
"""
|
|
93
|
+
self.frame.plot_type = PlotType.Sketch
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def axes(self):
|
|
97
|
+
"""`SketchAxes`: Axes (x and y) for the sketch plot.
|
|
98
|
+
|
|
99
|
+
Example usage::
|
|
100
|
+
|
|
101
|
+
>>> from tecplot.constant import PlotType
|
|
102
|
+
>>> frame.plot_type = PlotType.Sketch
|
|
103
|
+
>>> frame.plot().axes.x_axis.show = True
|
|
104
|
+
"""
|
|
105
|
+
return SketchAxes(self)
|
|
106
|
+
|
|
107
|
+
@property
|
|
108
|
+
def linking_between_frames(self):
|
|
109
|
+
"""`SketchPlotLinkingBetweenFrames`: Style linking between frames.
|
|
110
|
+
|
|
111
|
+
Example usage::
|
|
112
|
+
|
|
113
|
+
>>> plot.linking_between_frames.group = 1
|
|
114
|
+
>>> plot.linking_between_frames.link_solution_time = True
|
|
115
|
+
"""
|
|
116
|
+
return linking.SketchPlotLinkingBetweenFrames(self.frame)
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def linking_within_frame(self):
|
|
120
|
+
"""`LinkingWithinFrame`: Style linking within the frame.
|
|
121
|
+
|
|
122
|
+
Example usage::
|
|
123
|
+
|
|
124
|
+
>>> plot.linking_within_frame.link_gridline_style = True
|
|
125
|
+
"""
|
|
126
|
+
return linking.LinkingWithinFrame(self.frame)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class FieldPlot(Plot):
|
|
130
|
+
"""Plot containing data associated with style through fieldmaps.
|
|
131
|
+
|
|
132
|
+
.. code-block:: python
|
|
133
|
+
|
|
134
|
+
from os import path
|
|
135
|
+
import tecplot as tp
|
|
136
|
+
from tecplot.constant import PlotType
|
|
137
|
+
|
|
138
|
+
examples_dir = tp.session.tecplot_examples_directory()
|
|
139
|
+
infile = path.join(examples_dir, 'SimpleData', 'F18.plt')
|
|
140
|
+
dataset = tp.data.load_tecplot(infile)
|
|
141
|
+
|
|
142
|
+
frame = tp.active_frame()
|
|
143
|
+
plot = frame.plot(PlotType.Cartesian3D)
|
|
144
|
+
plot.activate()
|
|
145
|
+
plot.show_contour = True
|
|
146
|
+
plot.use_translucency = True
|
|
147
|
+
plot.contour(0).variable = dataset.variable('S')
|
|
148
|
+
|
|
149
|
+
# ensure consistent output between interactive (connected) and batch
|
|
150
|
+
plot.contour(0).levels.reset_to_nice()
|
|
151
|
+
|
|
152
|
+
# save image to file
|
|
153
|
+
tp.export.save_png('plot_field.png', 600, supersample=3)
|
|
154
|
+
|
|
155
|
+
.. figure:: /_static/images/plot_field.png
|
|
156
|
+
:width: 300px
|
|
157
|
+
:figwidth: 300px
|
|
158
|
+
"""
|
|
159
|
+
def __init__(self, frame):
|
|
160
|
+
super().__init__(frame, sv.FIELDLAYERS)
|
|
161
|
+
|
|
162
|
+
def contour(self, index):
|
|
163
|
+
"""`ContourGroup`: Plot-local `ContourGroup` style control.
|
|
164
|
+
|
|
165
|
+
Example usage::
|
|
166
|
+
|
|
167
|
+
>>> contour = frame.plot().contour(0)
|
|
168
|
+
>>> contour.colormap_name = 'Magma'
|
|
169
|
+
"""
|
|
170
|
+
return ContourGroup(index, self)
|
|
171
|
+
|
|
172
|
+
@property
|
|
173
|
+
def streamtraces(self):
|
|
174
|
+
"""`Streamtraces`: Plot-local `streamtrace <Streamtraces>` attributes.
|
|
175
|
+
|
|
176
|
+
Example usage::
|
|
177
|
+
|
|
178
|
+
>>> streamtraces = frame.plot().streamtraces
|
|
179
|
+
>>> streamtraces.color = Color.Blue
|
|
180
|
+
"""
|
|
181
|
+
return Streamtraces(self)
|
|
182
|
+
|
|
183
|
+
def slice(self, index):
|
|
184
|
+
tecutil.api_changed('''\
|
|
185
|
+
Access to 3D slice groups from 2D plots has been removed.
|
|
186
|
+
Use frame.plot(PlotType.Cartesian3D).slice() to access
|
|
187
|
+
slice groups.''', '0.13', '2018 R2')
|
|
188
|
+
|
|
189
|
+
def isosurface(self, index):
|
|
190
|
+
tecutil.api_changed('''\
|
|
191
|
+
Access to 3D isosurface groups from 2D plots has been removed.
|
|
192
|
+
Use frame.plot(PlotType.Cartesian3D).isosurface() to access
|
|
193
|
+
isosurface groups.''', '0.13', '2018 R2')
|
|
194
|
+
|
|
195
|
+
@property
|
|
196
|
+
def rgb_coloring(self):
|
|
197
|
+
"""`RGBColoring`: RGB contour flooding style control.
|
|
198
|
+
|
|
199
|
+
Example usage::
|
|
200
|
+
|
|
201
|
+
>>> plot.rgb_coloring.red_variable = dataset.variable('gas')
|
|
202
|
+
>>> plot.rgb_coloring.green_variable = dataset.variable('oil')
|
|
203
|
+
>>> plot.rgb_coloring.blue_variable = dataset.variable('water')
|
|
204
|
+
>>> plot.show_contour = True
|
|
205
|
+
>>> plot.fieldmaps().contour.flood_contour_group = plot.rgb_coloring
|
|
206
|
+
"""
|
|
207
|
+
return rgb_coloring.RGBColoring(self)
|
|
208
|
+
|
|
209
|
+
@property
|
|
210
|
+
def scatter(self):
|
|
211
|
+
"""`Scatter`: Plot-local `Scatter` style control.
|
|
212
|
+
|
|
213
|
+
Example usage::
|
|
214
|
+
|
|
215
|
+
>>> scatter = frame.plot().scatter
|
|
216
|
+
>>> scatter.variable = dataset.variable('P')
|
|
217
|
+
"""
|
|
218
|
+
return scatter.Scatter(self)
|
|
219
|
+
|
|
220
|
+
@property
|
|
221
|
+
def show_contour(self):
|
|
222
|
+
"""`bool`: Enable contours for this plot.
|
|
223
|
+
|
|
224
|
+
Example usage::
|
|
225
|
+
|
|
226
|
+
>>> frame.plot().show_contour = True
|
|
227
|
+
"""
|
|
228
|
+
return self._get_style(bool, sv.SHOWCONTOUR)
|
|
229
|
+
|
|
230
|
+
@show_contour.setter
|
|
231
|
+
def show_contour(self, show):
|
|
232
|
+
self._set_style(bool(show), sv.SHOWCONTOUR)
|
|
233
|
+
|
|
234
|
+
@property
|
|
235
|
+
def show_edge(self):
|
|
236
|
+
"""`bool`: Enable zone edge lines for this plot.
|
|
237
|
+
|
|
238
|
+
Example usage::
|
|
239
|
+
|
|
240
|
+
>>> frame.plot().show_edge = True
|
|
241
|
+
"""
|
|
242
|
+
return self._get_style(bool, sv.SHOWEDGE)
|
|
243
|
+
|
|
244
|
+
@show_edge.setter
|
|
245
|
+
def show_edge(self, show):
|
|
246
|
+
self._set_style(bool(show), sv.SHOWEDGE)
|
|
247
|
+
|
|
248
|
+
@property
|
|
249
|
+
def show_mesh(self):
|
|
250
|
+
"""`bool`: Enable mesh lines for this plot.
|
|
251
|
+
|
|
252
|
+
Example usage::
|
|
253
|
+
|
|
254
|
+
>>> frame.plot().show_mesh = True
|
|
255
|
+
"""
|
|
256
|
+
return self._get_style(bool, sv.SHOWMESH)
|
|
257
|
+
|
|
258
|
+
@show_mesh.setter
|
|
259
|
+
def show_mesh(self, show):
|
|
260
|
+
self._set_style(bool(show), sv.SHOWMESH)
|
|
261
|
+
|
|
262
|
+
@property
|
|
263
|
+
def show_scatter(self):
|
|
264
|
+
"""`bool`: Enable scatter symbols for this plot.
|
|
265
|
+
|
|
266
|
+
Example usage::
|
|
267
|
+
|
|
268
|
+
>>> frame.plot().show_scatter = True
|
|
269
|
+
"""
|
|
270
|
+
return self._get_style(bool, sv.SHOWSCATTER)
|
|
271
|
+
|
|
272
|
+
@show_scatter.setter
|
|
273
|
+
def show_scatter(self, show):
|
|
274
|
+
self._set_style(bool(show), sv.SHOWSCATTER)
|
|
275
|
+
|
|
276
|
+
@property
|
|
277
|
+
def show_shade(self):
|
|
278
|
+
"""`bool`: Enable surface shading effect for this plot.
|
|
279
|
+
|
|
280
|
+
Example usage::
|
|
281
|
+
|
|
282
|
+
>>> frame.plot().show_shade = True
|
|
283
|
+
"""
|
|
284
|
+
return self._get_style(bool, sv.SHOWSHADE)
|
|
285
|
+
|
|
286
|
+
@show_shade.setter
|
|
287
|
+
def show_shade(self, show):
|
|
288
|
+
self._set_style(bool(show), sv.SHOWSHADE)
|
|
289
|
+
|
|
290
|
+
@property
|
|
291
|
+
def show_slices(self):
|
|
292
|
+
"""`bool`: Show slices for this plot.
|
|
293
|
+
|
|
294
|
+
Example usage::
|
|
295
|
+
|
|
296
|
+
>>> frame.plot().show_slices(True)
|
|
297
|
+
"""
|
|
298
|
+
with self.frame.activated():
|
|
299
|
+
return session.get_style(bool, sv.SLICELAYERS, sv.SHOW,
|
|
300
|
+
uniqueid=self.frame.uid)
|
|
301
|
+
|
|
302
|
+
@show_slices.setter
|
|
303
|
+
def show_slices(self, show):
|
|
304
|
+
with self.frame.activated():
|
|
305
|
+
session.set_style(bool(show), sv.SLICELAYERS, sv.SHOW,
|
|
306
|
+
uniqueid=self.frame.uid)
|
|
307
|
+
|
|
308
|
+
@property
|
|
309
|
+
def show_isosurfaces(self):
|
|
310
|
+
"""`bool`: Show isosurfaces for this plot.
|
|
311
|
+
|
|
312
|
+
Example usage::
|
|
313
|
+
|
|
314
|
+
>>> frame.plot().show_isosurfaces(True)
|
|
315
|
+
"""
|
|
316
|
+
with self.frame.activated():
|
|
317
|
+
return session.get_style(bool, sv.ISOSURFACELAYERS, sv.SHOW,
|
|
318
|
+
uniqueid=self.frame.uid)
|
|
319
|
+
|
|
320
|
+
@show_isosurfaces.setter
|
|
321
|
+
def show_isosurfaces(self, show):
|
|
322
|
+
with self.frame.activated():
|
|
323
|
+
session.set_style(bool(show), sv.ISOSURFACELAYERS, sv.SHOW,
|
|
324
|
+
uniqueid=self.frame.uid)
|
|
325
|
+
|
|
326
|
+
@property
|
|
327
|
+
def show_streamtraces(self):
|
|
328
|
+
"""`bool`: Enable drawing `Streamtraces` on this plot.
|
|
329
|
+
|
|
330
|
+
Example usage::
|
|
331
|
+
|
|
332
|
+
>>> frame.plot().show_streamtraces = True
|
|
333
|
+
"""
|
|
334
|
+
with self.frame.activated():
|
|
335
|
+
return session.get_style(bool, sv.STREAMTRACELAYERS, sv.SHOW,
|
|
336
|
+
uniqueid=self.frame.uid)
|
|
337
|
+
|
|
338
|
+
@show_streamtraces.setter
|
|
339
|
+
def show_streamtraces(self, show):
|
|
340
|
+
with self.frame.activated():
|
|
341
|
+
session.set_style(bool(show), sv.STREAMTRACELAYERS, sv.SHOW,
|
|
342
|
+
uniqueid=self.frame.uid)
|
|
343
|
+
|
|
344
|
+
@property
|
|
345
|
+
def show_vector(self):
|
|
346
|
+
"""`bool`: Enable drawing of vectors.
|
|
347
|
+
|
|
348
|
+
Example usage::
|
|
349
|
+
|
|
350
|
+
>>> frame.plot().show_vector = True
|
|
351
|
+
"""
|
|
352
|
+
return self._get_style(bool, sv.SHOWVECTOR)
|
|
353
|
+
|
|
354
|
+
@show_vector.setter
|
|
355
|
+
def show_vector(self, show):
|
|
356
|
+
self._set_style(bool(show), sv.SHOWVECTOR)
|
|
357
|
+
|
|
358
|
+
@property
|
|
359
|
+
def num_fieldmaps(self):
|
|
360
|
+
"""`int`: Number of all fieldmaps in this plot.
|
|
361
|
+
|
|
362
|
+
Example usage::
|
|
363
|
+
|
|
364
|
+
>>> print(frame.plot().num_fieldmaps)
|
|
365
|
+
3
|
|
366
|
+
"""
|
|
367
|
+
return _tecutil.FieldMapGetCountForFrame(self.frame.uid)
|
|
368
|
+
|
|
369
|
+
def _fieldmap_indices(self, *keys):
|
|
370
|
+
result = set()
|
|
371
|
+
for key in tecutil.flatten_args(*keys):
|
|
372
|
+
if isinstance(key, FieldmapCollection):
|
|
373
|
+
result |= key._indices
|
|
374
|
+
elif isinstance(key, int):
|
|
375
|
+
result.add(key)
|
|
376
|
+
else:
|
|
377
|
+
index = getattr(key, 'index', self.fieldmap_index(key))
|
|
378
|
+
result.add(index)
|
|
379
|
+
return result
|
|
380
|
+
|
|
381
|
+
def fieldmap_index(self, zone):
|
|
382
|
+
"""The index of the fieldmap associated with a `Zone <data_access>`.
|
|
383
|
+
|
|
384
|
+
Parameters:
|
|
385
|
+
zone (`Zone <data_access>`): The `Zone <data_access>` object that
|
|
386
|
+
belongs to the `Dataset <data.Dataset>` associated with this plot.
|
|
387
|
+
|
|
388
|
+
Returns:
|
|
389
|
+
`Index`
|
|
390
|
+
|
|
391
|
+
Example usage::
|
|
392
|
+
|
|
393
|
+
>>> fmap_index = plot.fieldmap_index(dataset.zone('Zone'))
|
|
394
|
+
>>> plot.fieldmap(fmap_index).show_mesh = True
|
|
395
|
+
"""
|
|
396
|
+
with self.frame.activated():
|
|
397
|
+
return tecutil.Index(_tecutil.ZoneGetFieldMap(zone.index + 1) - 1)
|
|
398
|
+
|
|
399
|
+
@property
|
|
400
|
+
def active_fieldmap_indices(self):
|
|
401
|
+
"""`set`: Set of active fieldmaps by index.
|
|
402
|
+
|
|
403
|
+
This example sets the first three fieldmaps active, disabling all
|
|
404
|
+
others. It then turns on scatter symbols for just these three::
|
|
405
|
+
|
|
406
|
+
>>> plot.active_fieldmap_indices = [0, 1, 2]
|
|
407
|
+
>>> plot.fieldmaps(0, 1, 2).scatter.show = True
|
|
408
|
+
"""
|
|
409
|
+
return session.get_style(set, sv.ACTIVEFIELDMAPS,
|
|
410
|
+
uniqueid=self.frame.uid)
|
|
411
|
+
|
|
412
|
+
@active_fieldmap_indices.setter
|
|
413
|
+
def active_fieldmap_indices(self, values):
|
|
414
|
+
session.set_style(set(values), sv.ACTIVEFIELDMAPS,
|
|
415
|
+
uniqueid=self.frame.uid)
|
|
416
|
+
|
|
417
|
+
@property
|
|
418
|
+
def num_solution_times(self):
|
|
419
|
+
"""`int`: Number of solution times for all active fieldmaps.
|
|
420
|
+
|
|
421
|
+
.. note::
|
|
422
|
+
|
|
423
|
+
This only returns the number of *active* solution times. When
|
|
424
|
+
assigning strands and solution times to zones, the zones are
|
|
425
|
+
placed into an *inactive* fieldmap that must be subsequently
|
|
426
|
+
activated. See example below.
|
|
427
|
+
|
|
428
|
+
.. code-block:: python
|
|
429
|
+
|
|
430
|
+
>>> # place all zones into a single fieldmap (strand: 1)
|
|
431
|
+
>>> # with incrementing solution times
|
|
432
|
+
>>> for time, zone in enumerate(dataset.zones()):
|
|
433
|
+
... zone.strand = 1
|
|
434
|
+
... zone.solution_time = time
|
|
435
|
+
...
|
|
436
|
+
>>> # We must activate the fieldmap to ensure the plot's
|
|
437
|
+
>>> # solution times have been updated. Since we placed
|
|
438
|
+
>>> # all zones into a single fieldmap, we can assume the
|
|
439
|
+
>>> # first fieldmap (index: 0) is the one we want.
|
|
440
|
+
>>> plot.active_fieldmaps += [0]
|
|
441
|
+
>>>
|
|
442
|
+
>>> # now the plot's solution times are available.
|
|
443
|
+
>>> print(plot.num_solution_times)
|
|
444
|
+
10
|
|
445
|
+
>>> print(plot.solution_times)
|
|
446
|
+
[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
|
|
447
|
+
|
|
448
|
+
.. versionadded:: 2017.2
|
|
449
|
+
Solution time manipulation requires Tecplot 360 2017 R2 or later.
|
|
450
|
+
"""
|
|
451
|
+
success, result = _tecutil.SolutionTimeGetNumTimeStepsForFrame(
|
|
452
|
+
self.frame.uid)
|
|
453
|
+
if not success:
|
|
454
|
+
raise TecplotSystemError()
|
|
455
|
+
return result
|
|
456
|
+
|
|
457
|
+
@property
|
|
458
|
+
def solution_times(self):
|
|
459
|
+
"""`list` of `floats <float>`: `List <list>` of active solution times.
|
|
460
|
+
|
|
461
|
+
.. note::
|
|
462
|
+
|
|
463
|
+
This only returns the list of *active* solution times. When
|
|
464
|
+
assigning strands and solution times to zones, the zones are placed
|
|
465
|
+
into an *inactive* fieldmap that must be subsequently activated.
|
|
466
|
+
See example below.
|
|
467
|
+
|
|
468
|
+
Example usage::
|
|
469
|
+
|
|
470
|
+
>>> print(plot.solution_times)
|
|
471
|
+
[0.0, 1.0, 2.0]
|
|
472
|
+
|
|
473
|
+
.. versionadded:: 2017.2
|
|
474
|
+
Solution time manipulation requires Tecplot 360 2017 R2 or later.
|
|
475
|
+
"""
|
|
476
|
+
res = _tecutil.SolutionTimeGetSolutionTimesForFrame(self.frame.uid)
|
|
477
|
+
success, ntimes, times = res
|
|
478
|
+
if not success:
|
|
479
|
+
raise TecplotSystemError()
|
|
480
|
+
ret = list(times[:ntimes])
|
|
481
|
+
if not _tecutil_connector.connected:
|
|
482
|
+
_tecutil.ArrayDealloc(times)
|
|
483
|
+
return ret
|
|
484
|
+
|
|
485
|
+
@property
|
|
486
|
+
def transient_zone_visibility(self):
|
|
487
|
+
"""`TransientZoneVisibility`: Policy to determine transient visibility of zones.
|
|
488
|
+
|
|
489
|
+
Possible values: `ZonesAtOrBeforeSolutionTime`, `ZonesAtSolutionTime`.
|
|
490
|
+
|
|
491
|
+
Example usage::
|
|
492
|
+
|
|
493
|
+
>>> from tecplot.constant import TransientZoneVisibility
|
|
494
|
+
>>> plot.transient_zone_visibility = \\
|
|
495
|
+
... TransientZoneVisibility.ZonesAtSolutionTime
|
|
496
|
+
|
|
497
|
+
.. versionadded:: 2021.2
|
|
498
|
+
Transient zone visibility requires Tecplot 360 2021 R2 or later.
|
|
499
|
+
"""
|
|
500
|
+
if __debug__:
|
|
501
|
+
reqver = (2021, 2)
|
|
502
|
+
if version.sdk_version_info < reqver:
|
|
503
|
+
msg = 'Transient zone visibility requires 2021 R2 or later.'
|
|
504
|
+
raise TecplotOutOfDateEngineError(reqver, msg)
|
|
505
|
+
style = session.Style(sv.GLOBALTIME, **self._kw)
|
|
506
|
+
return style._get_style(TransientZoneVisibility, sv.TRANSIENTZONEVISIBILITY)
|
|
507
|
+
|
|
508
|
+
@transient_zone_visibility.setter
|
|
509
|
+
def transient_zone_visibility(self, value):
|
|
510
|
+
if __debug__:
|
|
511
|
+
reqver = (2021, 2)
|
|
512
|
+
if version.sdk_version_info < reqver:
|
|
513
|
+
msg = 'Transient zone visibility requires 2021 R2 or later.'
|
|
514
|
+
raise TecplotOutOfDateEngineError(reqver, msg)
|
|
515
|
+
style = session.Style(sv.GLOBALTIME, **self._kw)
|
|
516
|
+
style._set_style(TransientZoneVisibility(value), sv.TRANSIENTZONEVISIBILITY)
|
|
517
|
+
|
|
518
|
+
@property
|
|
519
|
+
def solution_time(self):
|
|
520
|
+
"""`float`: The current solution time.
|
|
521
|
+
|
|
522
|
+
Example usage::
|
|
523
|
+
|
|
524
|
+
>>> print(plot.solution_times)
|
|
525
|
+
[0.0, 1.0, 2.0]
|
|
526
|
+
>>> plot.solution_time = 1.0
|
|
527
|
+
|
|
528
|
+
.. note:: **Possible side-effect when connected to Tecplot 360.**
|
|
529
|
+
|
|
530
|
+
Changing the solution times in the dataset or modifying the
|
|
531
|
+
active fieldmaps in a frame may trigger a change in the active
|
|
532
|
+
plot's solution time by the Tecplot 360 interface. This is done
|
|
533
|
+
to keep the GUI controls consistent. In batch mode, no such
|
|
534
|
+
side-effect will take place and the user must take care to set
|
|
535
|
+
the plot's solution time with the `plot.solution_time
|
|
536
|
+
<Cartesian3DFieldPlot.solution_time>` or
|
|
537
|
+
`plot.solution_timestep
|
|
538
|
+
<Cartesian3DFieldPlot.solution_timestep>` properties.
|
|
539
|
+
|
|
540
|
+
.. versionadded:: 2017.2
|
|
541
|
+
Solution time manipulation requires Tecplot 360 2017 R2 or later.
|
|
542
|
+
"""
|
|
543
|
+
return _tecutil.SolutionTimeGetCurrentForFrame(self.frame.uid)
|
|
544
|
+
|
|
545
|
+
@solution_time.setter
|
|
546
|
+
@tecutil.lock()
|
|
547
|
+
def solution_time(self, value):
|
|
548
|
+
with self.frame.activated():
|
|
549
|
+
res = _tecutil.SolutionTimeSetCurrent(float(value))
|
|
550
|
+
if res not in [SetValueReturnCode.Ok,
|
|
551
|
+
SetValueReturnCode.DuplicateValue]:
|
|
552
|
+
raise TecplotSystemError()
|
|
553
|
+
|
|
554
|
+
@property
|
|
555
|
+
def solution_timestep(self):
|
|
556
|
+
"""`int`: The zero-based index of the current solution time.
|
|
557
|
+
|
|
558
|
+
A negative index is interpreted as counting from the end of the
|
|
559
|
+
available solution timesteps. Example usage::
|
|
560
|
+
|
|
561
|
+
>>> print(plot.solution_times)
|
|
562
|
+
[0.0, 1.0, 2.0]
|
|
563
|
+
>>> print(plot.solution_time)
|
|
564
|
+
0.0
|
|
565
|
+
>>> plot.solution_timestep += 1
|
|
566
|
+
>>> print(plot.solution_time)
|
|
567
|
+
1.0
|
|
568
|
+
|
|
569
|
+
.. note:: **Possible side-effect when connected to Tecplot 360.**
|
|
570
|
+
|
|
571
|
+
Changing the solution times in the dataset or modifying the
|
|
572
|
+
active fieldmaps in a frame may trigger a change in the active
|
|
573
|
+
plot's solution time by the Tecplot 360 interface. This is done
|
|
574
|
+
to keep the GUI controls consistent. In batch mode, no such
|
|
575
|
+
side-effect will take place and the user must take care to set
|
|
576
|
+
the plot's solution time with the `plot.solution_time
|
|
577
|
+
<Cartesian3DFieldPlot.solution_time>` or
|
|
578
|
+
`plot.solution_timestep
|
|
579
|
+
<Cartesian3DFieldPlot.solution_timestep>` properties.
|
|
580
|
+
|
|
581
|
+
.. versionadded:: 2017.2
|
|
582
|
+
Solution time manipulation requires Tecplot 360 2017 R2 or later.
|
|
583
|
+
"""
|
|
584
|
+
success, result = _tecutil.SolutionTimeGetCurrentTimeStepForFrame(
|
|
585
|
+
self.frame.uid)
|
|
586
|
+
if not success:
|
|
587
|
+
raise TecplotSystemError()
|
|
588
|
+
return result - 1
|
|
589
|
+
|
|
590
|
+
@solution_timestep.setter
|
|
591
|
+
def solution_timestep(self, timestep):
|
|
592
|
+
timestep = int(timestep)
|
|
593
|
+
if timestep < 0:
|
|
594
|
+
timestep = self.num_solution_times + timestep
|
|
595
|
+
success, time = _tecutil.SolutionTimeGetSolutionTimeAtTimeStepForFrame(
|
|
596
|
+
self.frame.uid, int(timestep) + 1)
|
|
597
|
+
if not success:
|
|
598
|
+
raise TecplotSystemError()
|
|
599
|
+
self.solution_time = time
|
|
600
|
+
|
|
601
|
+
@property
|
|
602
|
+
def ijk_blanking(self):
|
|
603
|
+
"""`IJKBlanking`: Mask off cells by :math:`(i, j, k)` index.
|
|
604
|
+
|
|
605
|
+
Example usage::
|
|
606
|
+
|
|
607
|
+
>>> plot.ijk_blanking.min_percent = (50, 50)
|
|
608
|
+
>>> plot.ijk_blanking.active = True
|
|
609
|
+
"""
|
|
610
|
+
return blanking.IJKBlanking(self)
|
|
611
|
+
|
|
612
|
+
@property
|
|
613
|
+
def data_labels(self):
|
|
614
|
+
"""`FieldPlotDataLabels`: Node and cell labels.
|
|
615
|
+
|
|
616
|
+
This object controls displaying labels for every node and/or cell in
|
|
617
|
+
the dataset. Example usage::
|
|
618
|
+
|
|
619
|
+
>>> plot.data_labels.show_cell_labels = True
|
|
620
|
+
>>> plot.data_labels.step_index = 10
|
|
621
|
+
"""
|
|
622
|
+
return labels.FieldPlotDataLabels(self)
|
|
623
|
+
|
|
624
|
+
@property
|
|
625
|
+
def linking_within_frame(self):
|
|
626
|
+
"""`FieldPlotLinkingWithinFrame`: Style linking within the frame.
|
|
627
|
+
|
|
628
|
+
Example usage::
|
|
629
|
+
|
|
630
|
+
>>> plot.linking_within_frame.link_gridline_style = True
|
|
631
|
+
"""
|
|
632
|
+
return linking.FieldPlotLinkingWithinFrame(self.frame)
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
class Cartesian2DFieldPlot(FieldPlot):
|
|
636
|
+
"""2D plot containing field data associated with style through fieldmaps.
|
|
637
|
+
|
|
638
|
+
.. code-block:: python
|
|
639
|
+
:emphasize-lines: 10-17,23-24
|
|
640
|
+
|
|
641
|
+
from os import path
|
|
642
|
+
import tecplot as tp
|
|
643
|
+
from tecplot.constant import PlotType
|
|
644
|
+
|
|
645
|
+
examples_dir = tp.session.tecplot_examples_directory()
|
|
646
|
+
infile = path.join(examples_dir, 'SimpleData', 'HeatExchanger.plt')
|
|
647
|
+
dataset = tp.data.load_tecplot(infile)
|
|
648
|
+
|
|
649
|
+
frame = tp.active_frame()
|
|
650
|
+
plot = frame.plot(PlotType.Cartesian2D)
|
|
651
|
+
plot.activate()
|
|
652
|
+
|
|
653
|
+
plot.vector.u_variable = dataset.variable('U(M/S)')
|
|
654
|
+
plot.vector.v_variable = dataset.variable('V(M/S)')
|
|
655
|
+
|
|
656
|
+
plot.contour(2).variable = dataset.variable('T(K)')
|
|
657
|
+
plot.contour(2).colormap_name = 'Sequential - Yellow/Green/Blue'
|
|
658
|
+
|
|
659
|
+
for z in dataset.zones():
|
|
660
|
+
fmap = plot.fieldmap(z)
|
|
661
|
+
fmap.contour.flood_contour_group = plot.contour(2)
|
|
662
|
+
|
|
663
|
+
plot.show_contour = True
|
|
664
|
+
plot.show_vector = True
|
|
665
|
+
|
|
666
|
+
# ensure consistent output between interactive (connected) and batch
|
|
667
|
+
plot.contour(2).levels.reset_to_nice()
|
|
668
|
+
|
|
669
|
+
# save image to file
|
|
670
|
+
tp.export.save_png('plot_field2d.png', 600, supersample=3)
|
|
671
|
+
|
|
672
|
+
.. figure:: /_static/images/plot_field2d.png
|
|
673
|
+
:width: 300px
|
|
674
|
+
:figwidth: 300px
|
|
675
|
+
"""
|
|
676
|
+
|
|
677
|
+
def activate(self):
|
|
678
|
+
"""Make this the active plot type on the parent frame.
|
|
679
|
+
|
|
680
|
+
Example usage::
|
|
681
|
+
|
|
682
|
+
>>> from tecplot.constant import PlotType
|
|
683
|
+
>>> plot = frame.plot(PlotType.Cartesian2D)
|
|
684
|
+
>>> plot.activate()
|
|
685
|
+
"""
|
|
686
|
+
self.frame.plot_type = PlotType.Cartesian2D
|
|
687
|
+
|
|
688
|
+
@property
|
|
689
|
+
def axes(self):
|
|
690
|
+
"""`Cartesian2DFieldAxes`: Axes style control for this plot.
|
|
691
|
+
|
|
692
|
+
Example usage::
|
|
693
|
+
|
|
694
|
+
>>> from tecplot.constant import PlotType
|
|
695
|
+
>>> frame.plot_type = PlotType.Cartesian2D
|
|
696
|
+
>>> axes = frame.plot().axes
|
|
697
|
+
>>> axes.x_axis.variable = dataset.variable('U')
|
|
698
|
+
>>> axes.y_axis.variable = dataset.variable('V')
|
|
699
|
+
"""
|
|
700
|
+
return Cartesian2DFieldAxes(self)
|
|
701
|
+
|
|
702
|
+
def fieldmap(self, key):
|
|
703
|
+
"""Returns a `Cartesian2DFieldmap` by `Zone <data_access>` or index.
|
|
704
|
+
|
|
705
|
+
Parameters:
|
|
706
|
+
key (`Zone <data_access>` or `int`): The `Zone <data_access>` must
|
|
707
|
+
be in the `Dataset <data.Dataset>` attached to the associated frame of this
|
|
708
|
+
plot. A negative index is interpreted as counting from the end
|
|
709
|
+
of the available fieldmaps.
|
|
710
|
+
|
|
711
|
+
Example usage::
|
|
712
|
+
|
|
713
|
+
>>> fmap = plot.fieldmap(dataset.zone(0))
|
|
714
|
+
>>> fmap.scatter.show = True
|
|
715
|
+
"""
|
|
716
|
+
if isinstance(key, int):
|
|
717
|
+
index = self.num_fieldmaps + key if key < 0 else key
|
|
718
|
+
else:
|
|
719
|
+
index = self.fieldmap_index(key)
|
|
720
|
+
return Cartesian2DFieldmap(self, index)
|
|
721
|
+
|
|
722
|
+
def fieldmaps(self, *keys):
|
|
723
|
+
"""`Cartesian2DFieldmapCollection` by `Zones <data_access>` or indices.
|
|
724
|
+
|
|
725
|
+
Parameters:
|
|
726
|
+
keys (`list` of `Zones <data_access>` or `ints <int>`): The
|
|
727
|
+
`Zones <data_access>` must be in the `Dataset <data.Dataset>` attached to the
|
|
728
|
+
associated frame of this plot. Negative indices are interpreted
|
|
729
|
+
as counting from the end of the available fieldmaps.
|
|
730
|
+
|
|
731
|
+
Example usage::
|
|
732
|
+
|
|
733
|
+
>>> fmaps = plot.fieldmaps(dataset.zone(0), dataset.zone(1))
|
|
734
|
+
>>> fmaps.scatter.show = True
|
|
735
|
+
|
|
736
|
+
.. versionchanged:: 0.9
|
|
737
|
+
`fieldmaps` was changed from a property (0.8 and earlier) to a
|
|
738
|
+
method requiring parentheses.
|
|
739
|
+
"""
|
|
740
|
+
indices = self._fieldmap_indices(*keys)
|
|
741
|
+
if not indices:
|
|
742
|
+
indices = range(self.num_fieldmaps)
|
|
743
|
+
return Cartesian2DFieldmapCollection(self, *indices)
|
|
744
|
+
|
|
745
|
+
@property
|
|
746
|
+
def active_fieldmaps(self):
|
|
747
|
+
"""`Cartesian2DFieldmapCollection`: Active fieldmaps in this plot.
|
|
748
|
+
|
|
749
|
+
Example usage::
|
|
750
|
+
|
|
751
|
+
>>> plot.active_fieldmaps.vector.show = True
|
|
752
|
+
|
|
753
|
+
.. note:: **Possible side-effect when connected to Tecplot 360.**
|
|
754
|
+
|
|
755
|
+
Changing the solution times in the dataset or modifying the
|
|
756
|
+
active fieldmaps in a frame may trigger a change in the active
|
|
757
|
+
plot's solution time by the Tecplot 360 interface. This is done
|
|
758
|
+
to keep the GUI controls consistent. In batch mode, no such
|
|
759
|
+
side-effect will take place and the user must take care to set
|
|
760
|
+
the plot's solution time with the `plot.solution_time
|
|
761
|
+
<Cartesian3DFieldPlot.solution_time>` or
|
|
762
|
+
`plot.solution_timestep
|
|
763
|
+
<Cartesian3DFieldPlot.solution_timestep>` properties.
|
|
764
|
+
"""
|
|
765
|
+
indices = self.active_fieldmap_indices
|
|
766
|
+
return Cartesian2DFieldmapCollection(self, *indices)
|
|
767
|
+
|
|
768
|
+
@active_fieldmaps.setter
|
|
769
|
+
def active_fieldmaps(self, fmaps):
|
|
770
|
+
indices = getattr(fmaps, 'fieldmap_indices', fmaps)
|
|
771
|
+
self.active_fieldmap_indices = indices
|
|
772
|
+
|
|
773
|
+
@property
|
|
774
|
+
def vector(self):
|
|
775
|
+
"""`Vector2D`: Vector variable and style control for this plot.
|
|
776
|
+
|
|
777
|
+
Example usage::
|
|
778
|
+
|
|
779
|
+
>>> plot.vector.u_variable = dataset.variable('U')
|
|
780
|
+
"""
|
|
781
|
+
return Vector2D(self)
|
|
782
|
+
|
|
783
|
+
@property
|
|
784
|
+
def draw_order(self):
|
|
785
|
+
"""`TwoDDrawOrder`: The order in which objects are drawn to the screen.
|
|
786
|
+
|
|
787
|
+
Possible values: `TwoDDrawOrder.ByZone`, `TwoDDrawOrder.ByLayer`.
|
|
788
|
+
|
|
789
|
+
The order is either by `Zone <data_access>` or by visual layer
|
|
790
|
+
(contour, mesh, etc.)::
|
|
791
|
+
|
|
792
|
+
>>> plot.draw_order = TwoDDrawOrder.ByZone
|
|
793
|
+
"""
|
|
794
|
+
return self._get_style(TwoDDrawOrder, sv.TWODDRAWORDER)
|
|
795
|
+
|
|
796
|
+
@draw_order.setter
|
|
797
|
+
def draw_order(self, order):
|
|
798
|
+
self._set_style(TwoDDrawOrder(order), sv.TWODDRAWORDER)
|
|
799
|
+
|
|
800
|
+
@property
|
|
801
|
+
def view(self):
|
|
802
|
+
"""`Cartesian2DFieldView`: Axes orientation and limits adjustments.
|
|
803
|
+
|
|
804
|
+
Example usage::
|
|
805
|
+
|
|
806
|
+
>>> plot.view.fit()
|
|
807
|
+
"""
|
|
808
|
+
return view.Cartesian2DFieldView(self)
|
|
809
|
+
|
|
810
|
+
@property
|
|
811
|
+
def value_blanking(self):
|
|
812
|
+
"""`ValueBlanking`: Mask off cells by value.
|
|
813
|
+
|
|
814
|
+
Example usage::
|
|
815
|
+
|
|
816
|
+
>>> plot.value_blanking.constraint(0).comparison_value = 3.14
|
|
817
|
+
>>> plot.value_blanking.constraint(0).active = True
|
|
818
|
+
"""
|
|
819
|
+
return blanking.ValueBlankingCartesian2D(self)
|
|
820
|
+
|
|
821
|
+
@property
|
|
822
|
+
def linking_between_frames(self):
|
|
823
|
+
"""`Cartesian2DPlotLinkingBetweenFrames`: Style linking between frames.
|
|
824
|
+
|
|
825
|
+
Example usage::
|
|
826
|
+
|
|
827
|
+
>>> plot.linking_between_frames.group = 1
|
|
828
|
+
>>> plot.linking_between_frames.link_solution_time = True
|
|
829
|
+
"""
|
|
830
|
+
return linking.Cartesian2DPlotLinkingBetweenFrames(self.frame)
|
|
831
|
+
|
|
832
|
+
|
|
833
|
+
class Cartesian3DFieldPlot(FieldPlot):
|
|
834
|
+
"""3D plot containing field data associated with style through fieldmaps.
|
|
835
|
+
|
|
836
|
+
.. code-block:: python
|
|
837
|
+
:emphasize-lines: 10-14
|
|
838
|
+
|
|
839
|
+
from os import path
|
|
840
|
+
import tecplot as tp
|
|
841
|
+
from tecplot.constant import PlotType
|
|
842
|
+
|
|
843
|
+
examples_dir = tp.session.tecplot_examples_directory()
|
|
844
|
+
infile = path.join(examples_dir, 'SimpleData', 'SpaceShip.lpk')
|
|
845
|
+
dataset = tp.load_layout(infile)
|
|
846
|
+
|
|
847
|
+
frame = tp.active_frame()
|
|
848
|
+
plot = frame.plot(PlotType.Cartesian3D)
|
|
849
|
+
plot.activate()
|
|
850
|
+
plot.use_lighting_effect = False
|
|
851
|
+
plot.show_streamtraces = False
|
|
852
|
+
plot.use_translucency = True
|
|
853
|
+
|
|
854
|
+
# ensure consistent output between interactive (connected) and batch
|
|
855
|
+
plot.contour(0).levels.reset_to_nice()
|
|
856
|
+
|
|
857
|
+
# save image to file
|
|
858
|
+
tp.export.save_png('plot_field3d.png', 600, supersample=3)
|
|
859
|
+
|
|
860
|
+
.. figure:: /_static/images/plot_field3d.png
|
|
861
|
+
:width: 300px
|
|
862
|
+
:figwidth: 300px
|
|
863
|
+
"""
|
|
864
|
+
|
|
865
|
+
def activate(self):
|
|
866
|
+
"""Make this the active plot type on the parent frame.
|
|
867
|
+
|
|
868
|
+
Example usage::
|
|
869
|
+
|
|
870
|
+
>>> from tecplot.constant import PlotType
|
|
871
|
+
>>> plot = frame.plot(PlotType.Cartesian3D)
|
|
872
|
+
>>> plot.activate()
|
|
873
|
+
"""
|
|
874
|
+
self.frame.plot_type = PlotType.Cartesian3D
|
|
875
|
+
|
|
876
|
+
@property
|
|
877
|
+
def axes(self):
|
|
878
|
+
"""`Cartesian3DFieldAxes`: Axes style control for this plot.
|
|
879
|
+
|
|
880
|
+
Example usage::
|
|
881
|
+
|
|
882
|
+
>>> from tecplot.constant import PlotType
|
|
883
|
+
>>> frame.plot_type = PlotType.Cartesian3D
|
|
884
|
+
>>> axes = frame.plot().axes
|
|
885
|
+
>>> axes.x_axis.variable = dataset.variable('U')
|
|
886
|
+
>>> axes.y_axis.variable = dataset.variable('V')
|
|
887
|
+
>>> axes.z_axis.variable = dataset.variable('W')
|
|
888
|
+
"""
|
|
889
|
+
return Cartesian3DFieldAxes(self)
|
|
890
|
+
|
|
891
|
+
def fieldmap(self, key):
|
|
892
|
+
"""Returns a `Cartesian3DFieldmap` by `Zone <data_access>` or index.
|
|
893
|
+
|
|
894
|
+
Parameters:
|
|
895
|
+
key (`Zone <data_access>` or `int`): The `Zone
|
|
896
|
+
<data_access>` must be in the `Dataset <data.Dataset>` attached to the
|
|
897
|
+
associated frame of this plot. A negative index is interpreted
|
|
898
|
+
as counting from the end of the available fieldmaps.
|
|
899
|
+
|
|
900
|
+
Example usage::
|
|
901
|
+
|
|
902
|
+
>>> fmap = plot.fieldmap(dataset.zone(0))
|
|
903
|
+
>>> fmap.scatter.show = True
|
|
904
|
+
"""
|
|
905
|
+
if isinstance(key, int):
|
|
906
|
+
index = self.num_fieldmaps + key if key < 0 else key
|
|
907
|
+
else:
|
|
908
|
+
index = self.fieldmap_index(key)
|
|
909
|
+
return Cartesian3DFieldmap(self, index)
|
|
910
|
+
|
|
911
|
+
def fieldmaps(self, *keys):
|
|
912
|
+
"""`Cartesian3DFieldmapCollection` by `Zones <data_access>` or indices.
|
|
913
|
+
|
|
914
|
+
Parameters:
|
|
915
|
+
keys (`list` of `Zones <data_access>` or `integers <int>`): The
|
|
916
|
+
`Zones <data_access>` must be in the `Dataset <data.Dataset>` attached to the
|
|
917
|
+
associated frame of this plot. Negative indices are interpreted
|
|
918
|
+
as counting from the end of the available fieldmaps.
|
|
919
|
+
|
|
920
|
+
Example usage::
|
|
921
|
+
|
|
922
|
+
>>> fmaps = plot.fieldmaps(dataset.zone(0), dataset.zone(1))
|
|
923
|
+
>>> fmaps.scatter.show = True
|
|
924
|
+
|
|
925
|
+
.. versionchanged:: 0.9
|
|
926
|
+
`fieldmaps` was changed from a property (0.8 and earlier) to a
|
|
927
|
+
method requiring parentheses.
|
|
928
|
+
"""
|
|
929
|
+
indices = self._fieldmap_indices(*keys)
|
|
930
|
+
if not indices:
|
|
931
|
+
indices = range(self.num_fieldmaps)
|
|
932
|
+
return Cartesian3DFieldmapCollection(self, *indices)
|
|
933
|
+
|
|
934
|
+
@property
|
|
935
|
+
def active_fieldmaps(self):
|
|
936
|
+
"""`Cartesian3DFieldmapCollection`: Active fieldmaps in this plot.
|
|
937
|
+
|
|
938
|
+
Example usage::
|
|
939
|
+
|
|
940
|
+
>>> plot.active_fieldmaps.vector.show = True
|
|
941
|
+
|
|
942
|
+
.. note:: **Possible side-effect when connected to Tecplot 360.**
|
|
943
|
+
|
|
944
|
+
Changing the solution times in the dataset or modifying the
|
|
945
|
+
active fieldmaps in a frame may trigger a change in the active
|
|
946
|
+
plot's solution time by the Tecplot 360 interface. This is done
|
|
947
|
+
to keep the GUI controls consistent. In batch mode, no such
|
|
948
|
+
side-effect will take place and the user must take care to set
|
|
949
|
+
the plot's solution time with the `plot.solution_time
|
|
950
|
+
<Cartesian3DFieldPlot.solution_time>` or
|
|
951
|
+
`plot.solution_timestep
|
|
952
|
+
<Cartesian3DFieldPlot.solution_timestep>` properties.
|
|
953
|
+
"""
|
|
954
|
+
indices = self.active_fieldmap_indices
|
|
955
|
+
return Cartesian3DFieldmapCollection(self, *indices)
|
|
956
|
+
|
|
957
|
+
@active_fieldmaps.setter
|
|
958
|
+
def active_fieldmaps(self, fmaps):
|
|
959
|
+
indices = getattr(fmaps, 'fieldmap_indices',
|
|
960
|
+
[getattr(fmap, 'index', fmap) for fmap in fmaps])
|
|
961
|
+
self.active_fieldmap_indices = indices
|
|
962
|
+
|
|
963
|
+
def slice(self, index):
|
|
964
|
+
"""`SliceGroup`: Plot-local `slice <SliceGroup>` style control.
|
|
965
|
+
|
|
966
|
+
Example usage::
|
|
967
|
+
|
|
968
|
+
>>> from tecplot.constant import Color
|
|
969
|
+
>>> slice0 = frame.plot().slice(0)
|
|
970
|
+
>>> slice0.mesh.show = True
|
|
971
|
+
>>> slice0.mesh.color = Color.Blue
|
|
972
|
+
"""
|
|
973
|
+
return slice.SliceGroup(self, index)
|
|
974
|
+
|
|
975
|
+
def slices(self, *indices):
|
|
976
|
+
"""`SliceGroupCollection`: Plot-local slice style control.
|
|
977
|
+
|
|
978
|
+
Example setting setting mesh color of all slices to blue::
|
|
979
|
+
|
|
980
|
+
>>> from tecplot.constant import Color
|
|
981
|
+
>>> slices = frame.plot().slices()
|
|
982
|
+
>>> slices.mesh.show = True
|
|
983
|
+
>>> slices.mesh.color = Color.Blue
|
|
984
|
+
|
|
985
|
+
Example turning on the first two slice's contour layer::
|
|
986
|
+
|
|
987
|
+
>>> slices = frame.plot().slices(0, 1)
|
|
988
|
+
>>> slices.contour.show = True
|
|
989
|
+
"""
|
|
990
|
+
return slice.SliceGroupCollection(self, *indices)
|
|
991
|
+
|
|
992
|
+
def isosurface(self, index):
|
|
993
|
+
"""`IsosurfaceGroup`: Plot-local `isosurface <IsosurfaceGroup>` settings.
|
|
994
|
+
|
|
995
|
+
Example usage::
|
|
996
|
+
|
|
997
|
+
>>> isosurface_0 = frame.plot().isosurface(0)
|
|
998
|
+
>>> isosurface_0.mesh.color = Color.Blue
|
|
999
|
+
"""
|
|
1000
|
+
return IsosurfaceGroup(index, self)
|
|
1001
|
+
|
|
1002
|
+
@property
|
|
1003
|
+
def vector(self):
|
|
1004
|
+
"""`Vector3D`: Vector variable and style control for this plot.
|
|
1005
|
+
|
|
1006
|
+
Example usage::
|
|
1007
|
+
|
|
1008
|
+
>>> plot.vector.u_variable = dataset.variable('U')
|
|
1009
|
+
"""
|
|
1010
|
+
return Vector3D(self)
|
|
1011
|
+
|
|
1012
|
+
@property
|
|
1013
|
+
def view(self):
|
|
1014
|
+
"""`Cartesian3DView`: Viewport, axes orientation and limits adjustments.
|
|
1015
|
+
|
|
1016
|
+
Example usage::
|
|
1017
|
+
|
|
1018
|
+
>>> plot.view.fit()
|
|
1019
|
+
"""
|
|
1020
|
+
return view.Cartesian3DView(self)
|
|
1021
|
+
|
|
1022
|
+
@property
|
|
1023
|
+
def use_lighting_effect(self):
|
|
1024
|
+
"""`bool`: Enable lighting effect for all objects within this plot.
|
|
1025
|
+
|
|
1026
|
+
Example usage::
|
|
1027
|
+
|
|
1028
|
+
>>> frame.plot().use_lighting_effect = True
|
|
1029
|
+
"""
|
|
1030
|
+
return self._get_style(bool, sv.USELIGHTINGEFFECT)
|
|
1031
|
+
|
|
1032
|
+
@use_lighting_effect.setter
|
|
1033
|
+
def use_lighting_effect(self, value):
|
|
1034
|
+
self._set_style(bool(value), sv.USELIGHTINGEFFECT)
|
|
1035
|
+
|
|
1036
|
+
@property
|
|
1037
|
+
def use_translucency(self):
|
|
1038
|
+
"""`bool`: Enable translucent effect for all objects within this plot.
|
|
1039
|
+
|
|
1040
|
+
Example usage::
|
|
1041
|
+
|
|
1042
|
+
>>> frame.plot().use_translucency = True
|
|
1043
|
+
"""
|
|
1044
|
+
return self._get_style(bool, sv.USETRANSLUCENCY)
|
|
1045
|
+
|
|
1046
|
+
@use_translucency.setter
|
|
1047
|
+
def use_translucency(self, show):
|
|
1048
|
+
self._set_style(bool(show), sv.USETRANSLUCENCY)
|
|
1049
|
+
|
|
1050
|
+
@property
|
|
1051
|
+
def light_source(self):
|
|
1052
|
+
"""`LightSource`: Control the direction and effects of lighting.
|
|
1053
|
+
|
|
1054
|
+
Example usage::
|
|
1055
|
+
|
|
1056
|
+
>>> plot.light_source.intensity = 70.0
|
|
1057
|
+
"""
|
|
1058
|
+
return effects.LightSource(self)
|
|
1059
|
+
|
|
1060
|
+
@property
|
|
1061
|
+
def value_blanking(self):
|
|
1062
|
+
"""`ValueBlanking`: Mask off cells by value.
|
|
1063
|
+
|
|
1064
|
+
Example usage::
|
|
1065
|
+
|
|
1066
|
+
>>> plot.value_blanking.constraint(0).comparison_value = 3.14
|
|
1067
|
+
>>> plot.value_blanking.constraint(0).active = True
|
|
1068
|
+
"""
|
|
1069
|
+
return blanking.ValueBlankingCartesian3D(self)
|
|
1070
|
+
|
|
1071
|
+
@property
|
|
1072
|
+
def line_lift_fraction(self):
|
|
1073
|
+
"""`float`: Lift lines above plot by percentage distance to the eye.
|
|
1074
|
+
|
|
1075
|
+
Example usage::
|
|
1076
|
+
|
|
1077
|
+
>>> plot.line_lift_fraction = 0.6
|
|
1078
|
+
"""
|
|
1079
|
+
style = session.Style(sv.GLOBALTHREED, **self._kw)
|
|
1080
|
+
return style._get_style(float, sv.LINELIFTFRACTION)
|
|
1081
|
+
|
|
1082
|
+
@line_lift_fraction.setter
|
|
1083
|
+
def line_lift_fraction(self, value):
|
|
1084
|
+
style = session.Style(sv.GLOBALTHREED, **self._kw)
|
|
1085
|
+
style._set_style(float(value), sv.LINELIFTFRACTION)
|
|
1086
|
+
|
|
1087
|
+
@property
|
|
1088
|
+
def near_plane_fraction(self):
|
|
1089
|
+
"""`float`: position of the "near plane".
|
|
1090
|
+
|
|
1091
|
+
In a 3D plot, the "near plane" acts as a windshield. Anything in front
|
|
1092
|
+
of this plane does not display. Example usage::
|
|
1093
|
+
|
|
1094
|
+
>>> plot.near_plane_fraction = 0.1
|
|
1095
|
+
"""
|
|
1096
|
+
style = session.Style(sv.GLOBALTHREED, **self._kw)
|
|
1097
|
+
return style._get_style(float, sv.NEARPLANEFRACTION)
|
|
1098
|
+
|
|
1099
|
+
@near_plane_fraction.setter
|
|
1100
|
+
def near_plane_fraction(self, value):
|
|
1101
|
+
style = session.Style(sv.GLOBALTHREED, **self._kw)
|
|
1102
|
+
style._set_style(float(value), sv.NEARPLANEFRACTION)
|
|
1103
|
+
|
|
1104
|
+
@property
|
|
1105
|
+
def perform_extra_sorting(self):
|
|
1106
|
+
"""`bool`: Use a more robust depth sorting algorithm for display.
|
|
1107
|
+
|
|
1108
|
+
When printing 3D plots in a vector graphics format, Tecplot 360 must
|
|
1109
|
+
sort the objects so that it can draw those farthest from the screen
|
|
1110
|
+
first and those closest to the screen last. By default, Tecplot 360
|
|
1111
|
+
uses a quick sorting algorithm. This is not always accurate and does
|
|
1112
|
+
not detect problems such as intersecting objects. When
|
|
1113
|
+
``perform_extra_sorting`` set to `True`, Tecplot 360 uses a slower,
|
|
1114
|
+
more accurate approach that detects and resolves such problems. Example
|
|
1115
|
+
usage::
|
|
1116
|
+
|
|
1117
|
+
>>> plot.perform_extra_sorting = True
|
|
1118
|
+
"""
|
|
1119
|
+
style = session.Style(sv.GLOBALTHREED, **self._kw)
|
|
1120
|
+
return style._get_style(bool, sv.PERFORMEXTRA3DSORTING)
|
|
1121
|
+
|
|
1122
|
+
@perform_extra_sorting.setter
|
|
1123
|
+
def perform_extra_sorting(self, value):
|
|
1124
|
+
style = session.Style(sv.GLOBALTHREED, **self._kw)
|
|
1125
|
+
style._set_style(bool(value), sv.PERFORMEXTRA3DSORTING)
|
|
1126
|
+
|
|
1127
|
+
@property
|
|
1128
|
+
def symbol_lift_fraction(self):
|
|
1129
|
+
"""`float`: Lift symbols above plot by percentage distance to the eye.
|
|
1130
|
+
|
|
1131
|
+
Example usage::
|
|
1132
|
+
|
|
1133
|
+
>>> plot.symbol_lift_fraction = 0.6
|
|
1134
|
+
"""
|
|
1135
|
+
style = session.Style(sv.GLOBALTHREED, **self._kw)
|
|
1136
|
+
return style._get_style(float, sv.SYMBOLLIFTFRACTION)
|
|
1137
|
+
|
|
1138
|
+
@symbol_lift_fraction.setter
|
|
1139
|
+
def symbol_lift_fraction(self, value):
|
|
1140
|
+
style = session.Style(sv.GLOBALTHREED, **self._kw)
|
|
1141
|
+
style._set_style(float(value), sv.SYMBOLLIFTFRACTION)
|
|
1142
|
+
|
|
1143
|
+
@property
|
|
1144
|
+
def vector_lift_fraction(self):
|
|
1145
|
+
"""`float`: Lift vectors above plot by percentage distance to the eye.
|
|
1146
|
+
|
|
1147
|
+
Example usage::
|
|
1148
|
+
|
|
1149
|
+
>>> plot.vector_lift_fraction = 0.6
|
|
1150
|
+
"""
|
|
1151
|
+
style = session.Style(sv.GLOBALTHREED, **self._kw)
|
|
1152
|
+
return style._get_style(float, sv.VECTORLIFTFRACTION)
|
|
1153
|
+
|
|
1154
|
+
@vector_lift_fraction.setter
|
|
1155
|
+
def vector_lift_fraction(self, value):
|
|
1156
|
+
style = session.Style(sv.GLOBALTHREED, **self._kw)
|
|
1157
|
+
style._set_style(float(value), sv.VECTORLIFTFRACTION)
|
|
1158
|
+
|
|
1159
|
+
@property
|
|
1160
|
+
def linking_between_frames(self):
|
|
1161
|
+
"""`Cartesian3DPlotLinkingBetweenFrames`: Style linking between frames.
|
|
1162
|
+
|
|
1163
|
+
Example usage::
|
|
1164
|
+
|
|
1165
|
+
>>> plot.linking_between_frames.group = 1
|
|
1166
|
+
>>> plot.linking_between_frames.link_solution_time = True
|
|
1167
|
+
"""
|
|
1168
|
+
return linking.Cartesian3DPlotLinkingBetweenFrames(self.frame)
|
|
1169
|
+
|
|
1170
|
+
|
|
1171
|
+
class LinePlot(Plot):
|
|
1172
|
+
"""Plot with line data and associated style through linemaps.
|
|
1173
|
+
|
|
1174
|
+
.. code-block:: python
|
|
1175
|
+
|
|
1176
|
+
from os import path
|
|
1177
|
+
import tecplot as tp
|
|
1178
|
+
from tecplot.constant import PlotType, Color, LinePattern
|
|
1179
|
+
|
|
1180
|
+
examples_dir = tp.session.tecplot_examples_directory()
|
|
1181
|
+
infile = path.join(examples_dir, 'SimpleData', 'Rainfall.dat')
|
|
1182
|
+
dataset = tp.data.load_tecplot(infile)
|
|
1183
|
+
|
|
1184
|
+
frame = tp.active_frame()
|
|
1185
|
+
frame.plot_type = PlotType.XYLine
|
|
1186
|
+
plot = frame.plot()
|
|
1187
|
+
plot.show_symbols = True
|
|
1188
|
+
|
|
1189
|
+
# save image to file
|
|
1190
|
+
tp.export.save_png('plot_line.png', 600, supersample=3)
|
|
1191
|
+
|
|
1192
|
+
.. figure:: /_static/images/plot_line.png
|
|
1193
|
+
:width: 300px
|
|
1194
|
+
:figwidth: 300px
|
|
1195
|
+
"""
|
|
1196
|
+
|
|
1197
|
+
def __init__(self, frame):
|
|
1198
|
+
super().__init__(frame, sv.LINEPLOTLAYERS)
|
|
1199
|
+
|
|
1200
|
+
@tecutil.lock()
|
|
1201
|
+
def delete_linemaps(self, *linemaps):
|
|
1202
|
+
r"""Clear all linemaps within this plot.
|
|
1203
|
+
|
|
1204
|
+
Parameters:
|
|
1205
|
+
\*linemaps (:ref:`Linemap`, `int` or `str`):
|
|
1206
|
+
One or more of the following: :ref:`Linemap` objects, linemap
|
|
1207
|
+
indices (zero-based) or linemap names. If none are given, all
|
|
1208
|
+
linemaps will be deleted.
|
|
1209
|
+
|
|
1210
|
+
Example usage::
|
|
1211
|
+
|
|
1212
|
+
>>> plot.delete_linemaps()
|
|
1213
|
+
>>> print(plot.num_linemaps)
|
|
1214
|
+
0
|
|
1215
|
+
"""
|
|
1216
|
+
if not linemaps:
|
|
1217
|
+
return _tecutil.LineMapDelete(None)
|
|
1218
|
+
with tecutil.IndexSet() as indices:
|
|
1219
|
+
for lmap in tecutil.flatten_args(*linemaps):
|
|
1220
|
+
try:
|
|
1221
|
+
# try as a Linemap object
|
|
1222
|
+
indices.append(lmap.index)
|
|
1223
|
+
except (AttributeError, TypeError):
|
|
1224
|
+
try:
|
|
1225
|
+
# try as a linemap index
|
|
1226
|
+
indices.append(lmap)
|
|
1227
|
+
except TypeError:
|
|
1228
|
+
# assume name pattern
|
|
1229
|
+
for submap in self.linemaps(lmap):
|
|
1230
|
+
indices.append(submap.index)
|
|
1231
|
+
return _tecutil.LineMapDelete(indices)
|
|
1232
|
+
|
|
1233
|
+
@property
|
|
1234
|
+
def num_linemaps(self):
|
|
1235
|
+
"""`int`: Number of linemaps held by this plot.
|
|
1236
|
+
|
|
1237
|
+
Example usage::
|
|
1238
|
+
|
|
1239
|
+
>>> print(plot.num_linemaps)
|
|
1240
|
+
3
|
|
1241
|
+
"""
|
|
1242
|
+
return _tecutil.LineMapGetCountForFrame(self.frame.uid)
|
|
1243
|
+
|
|
1244
|
+
def _linemap_indices_by_name(self, pattern):
|
|
1245
|
+
pattern_type = getattr(re, 'Pattern', getattr(re, '_pattern_type', None))
|
|
1246
|
+
if not isinstance(pattern, pattern_type):
|
|
1247
|
+
regex = re.compile(fnmatch.translate(pattern), re.IGNORECASE)
|
|
1248
|
+
else:
|
|
1249
|
+
regex = pattern
|
|
1250
|
+
|
|
1251
|
+
indices = set()
|
|
1252
|
+
with self.frame.activated():
|
|
1253
|
+
found = False
|
|
1254
|
+
for i in range(self.num_linemaps):
|
|
1255
|
+
try:
|
|
1256
|
+
_, name = _tecutil.LineMapGetName(i + 1)
|
|
1257
|
+
name = name or ''
|
|
1258
|
+
except (AttributeError, TecplotSystemError):
|
|
1259
|
+
name = ''
|
|
1260
|
+
if regex.match(name):
|
|
1261
|
+
found = True
|
|
1262
|
+
indices.add(i)
|
|
1263
|
+
if __debug__:
|
|
1264
|
+
if (
|
|
1265
|
+
not found and
|
|
1266
|
+
isinstance(pattern, str) and
|
|
1267
|
+
any(c in pattern for c in '*?[]')
|
|
1268
|
+
):
|
|
1269
|
+
msg = 'no linemaps found matching: "{}"'.format(pattern)
|
|
1270
|
+
warning = TecplotPatternMatchWarning(pattern, msg)
|
|
1271
|
+
warnings.warn(warning)
|
|
1272
|
+
return indices
|
|
1273
|
+
|
|
1274
|
+
def _linemap_indices(self, *keys):
|
|
1275
|
+
"""
|
|
1276
|
+
convert keys to a set of indices where keys are:
|
|
1277
|
+
* int: get one linemap index (converting negative values)
|
|
1278
|
+
* regex pattern: match by name
|
|
1279
|
+
* glob-style string: match by name
|
|
1280
|
+
if no keys are given, get all linemaps indices
|
|
1281
|
+
"""
|
|
1282
|
+
indices = set()
|
|
1283
|
+
if keys:
|
|
1284
|
+
for key in keys:
|
|
1285
|
+
if isinstance(key, int):
|
|
1286
|
+
index = key + self.num_linemaps if key < 0 else key
|
|
1287
|
+
if index >= self.num_linemaps:
|
|
1288
|
+
msg = 'linemap index out of range: ' + str(index)
|
|
1289
|
+
raise TecplotIndexError(msg)
|
|
1290
|
+
indices.add(index)
|
|
1291
|
+
else:
|
|
1292
|
+
indices |= self._linemap_indices_by_name(key)
|
|
1293
|
+
else:
|
|
1294
|
+
indices |= set(range(self.num_linemaps))
|
|
1295
|
+
return indices
|
|
1296
|
+
|
|
1297
|
+
@tecutil.lock()
|
|
1298
|
+
def _add_linemap(self, name, zone, show=True):
|
|
1299
|
+
with self.frame.activated():
|
|
1300
|
+
new_linemap_index = self.num_linemaps
|
|
1301
|
+
if not _tecutil.LineMapCreate():
|
|
1302
|
+
raise TecplotSystemError()
|
|
1303
|
+
linemap = self.linemap(new_linemap_index)
|
|
1304
|
+
if name is not None:
|
|
1305
|
+
linemap.name = name
|
|
1306
|
+
if zone is not None:
|
|
1307
|
+
linemap.zone_index = getattr(zone, 'index', zone)
|
|
1308
|
+
if show is not None:
|
|
1309
|
+
linemap.show = show
|
|
1310
|
+
return linemap
|
|
1311
|
+
|
|
1312
|
+
@property
|
|
1313
|
+
def legend(self):
|
|
1314
|
+
"""`LineLegend`: Line plot legend style and placement control.
|
|
1315
|
+
|
|
1316
|
+
Example usage::
|
|
1317
|
+
|
|
1318
|
+
>>> plot.legend.show = True
|
|
1319
|
+
"""
|
|
1320
|
+
return legend.LineLegend(self)
|
|
1321
|
+
|
|
1322
|
+
@property
|
|
1323
|
+
def active_linemap_indices(self):
|
|
1324
|
+
"""`set` of `integers <int>`: `set` of all active linemaps by index.
|
|
1325
|
+
|
|
1326
|
+
Numbers are zero-based indices to the linemaps::
|
|
1327
|
+
|
|
1328
|
+
>>> active_indices = plot.active_linemap_indices
|
|
1329
|
+
>>> active_lmaps = [plot.linemap(i) for i in active_indices]
|
|
1330
|
+
"""
|
|
1331
|
+
return session.get_style(set, sv.ACTIVELINEMAPS,
|
|
1332
|
+
uniqueid=self.frame.uid)
|
|
1333
|
+
|
|
1334
|
+
@property
|
|
1335
|
+
def show_lines(self):
|
|
1336
|
+
"""`bool`: Enable lines for this plot.
|
|
1337
|
+
|
|
1338
|
+
Example usage::
|
|
1339
|
+
|
|
1340
|
+
>>> plot.show_lines = True
|
|
1341
|
+
"""
|
|
1342
|
+
return self._get_style(bool, sv.SHOWLINES)
|
|
1343
|
+
|
|
1344
|
+
@show_lines.setter
|
|
1345
|
+
def show_lines(self, value):
|
|
1346
|
+
self._set_style(bool(value), sv.SHOWLINES)
|
|
1347
|
+
|
|
1348
|
+
@property
|
|
1349
|
+
def show_symbols(self):
|
|
1350
|
+
"""`bool`: Enable symbols at line vertices for this plot.
|
|
1351
|
+
|
|
1352
|
+
Example usage::
|
|
1353
|
+
|
|
1354
|
+
>>> plot.show_symbols = True
|
|
1355
|
+
"""
|
|
1356
|
+
return self._get_style(bool, sv.SHOWSYMBOLS)
|
|
1357
|
+
|
|
1358
|
+
@show_symbols.setter
|
|
1359
|
+
def show_symbols(self, value):
|
|
1360
|
+
self._set_style(bool(value), sv.SHOWSYMBOLS)
|
|
1361
|
+
|
|
1362
|
+
@property
|
|
1363
|
+
def value_blanking(self):
|
|
1364
|
+
"""`ValueBlanking`: Mask off points by value.
|
|
1365
|
+
|
|
1366
|
+
Example usage::
|
|
1367
|
+
|
|
1368
|
+
>>> plot.value_blanking.constraint(0).comparison_value = 3.14
|
|
1369
|
+
>>> plot.value_blanking.constraint(0).active = True
|
|
1370
|
+
"""
|
|
1371
|
+
return blanking.ValueBlanking(self)
|
|
1372
|
+
|
|
1373
|
+
@property
|
|
1374
|
+
def base_font(self):
|
|
1375
|
+
"""`BaseFont`: Default typeface style control.
|
|
1376
|
+
|
|
1377
|
+
Example usage::
|
|
1378
|
+
|
|
1379
|
+
>>> plot.base_font.typeface = 'Times'
|
|
1380
|
+
"""
|
|
1381
|
+
return text.BaseFont(sv.GLOBALLINEPLOT, **self._kw)
|
|
1382
|
+
|
|
1383
|
+
@property
|
|
1384
|
+
def data_labels(self):
|
|
1385
|
+
"""`LinePlotDataLabels`: Node and cell labels.
|
|
1386
|
+
|
|
1387
|
+
This object controls displaying labels for every node and/or cell in
|
|
1388
|
+
the dataset. Example usage::
|
|
1389
|
+
|
|
1390
|
+
>>> plot.data_labels.show_node_labels = True
|
|
1391
|
+
>>> plot.data_labels.step_index = 10
|
|
1392
|
+
"""
|
|
1393
|
+
return labels.LinePlotDataLabels(self)
|
|
1394
|
+
|
|
1395
|
+
@property
|
|
1396
|
+
def linking_within_frame(self):
|
|
1397
|
+
"""`DataPlotLinkingWithinFrame`: Style linking within the frame.
|
|
1398
|
+
|
|
1399
|
+
Example usage::
|
|
1400
|
+
|
|
1401
|
+
>>> plot.linking_within_frame.link_gridline_style = True
|
|
1402
|
+
"""
|
|
1403
|
+
return linking.DataPlotLinkingWithinFrame(self.frame)
|
|
1404
|
+
|
|
1405
|
+
|
|
1406
|
+
class XYLinePlot(LinePlot):
|
|
1407
|
+
"""Cartesian plot with line data and associated style through linemaps.
|
|
1408
|
+
|
|
1409
|
+
.. code-block:: python
|
|
1410
|
+
:emphasize-lines: 10-14
|
|
1411
|
+
|
|
1412
|
+
from os import path
|
|
1413
|
+
import tecplot as tp
|
|
1414
|
+
from tecplot.constant import PlotType, FillMode
|
|
1415
|
+
|
|
1416
|
+
examples_dir = tp.session.tecplot_examples_directory()
|
|
1417
|
+
infile = path.join(examples_dir, 'SimpleData', 'SunSpots.plt')
|
|
1418
|
+
dataset = tp.data.load_tecplot(infile)
|
|
1419
|
+
|
|
1420
|
+
frame = tp.active_frame()
|
|
1421
|
+
plot = frame.plot(PlotType.XYLine)
|
|
1422
|
+
plot.activate()
|
|
1423
|
+
plot.show_symbols = True
|
|
1424
|
+
plot.linemap(0).symbols.fill_mode = FillMode.UseLineColor
|
|
1425
|
+
plot.linemap(0).symbols.size = 1
|
|
1426
|
+
|
|
1427
|
+
tp.export.save_png('plot_xyline.png', 600, supersample=3)
|
|
1428
|
+
|
|
1429
|
+
.. figure:: /_static/images/plot_xyline.png
|
|
1430
|
+
:width: 300px
|
|
1431
|
+
:figwidth: 300px
|
|
1432
|
+
"""
|
|
1433
|
+
|
|
1434
|
+
def activate(self):
|
|
1435
|
+
"""Make this the active plot type on the parent frame.
|
|
1436
|
+
|
|
1437
|
+
Example usage::
|
|
1438
|
+
|
|
1439
|
+
>>> from tecplot.constant import PlotType
|
|
1440
|
+
>>> plot = frame.plot(PlotType.XYLine)
|
|
1441
|
+
>>> plot.activate()
|
|
1442
|
+
"""
|
|
1443
|
+
self.frame.plot_type = PlotType.XYLine
|
|
1444
|
+
|
|
1445
|
+
def linemaps(self, *keys):
|
|
1446
|
+
"""`XYLinemapCollection` by index or name.
|
|
1447
|
+
|
|
1448
|
+
Parameters:
|
|
1449
|
+
keys (`int`, `str` or `re.Pattern <re.compile>`): Zero-based
|
|
1450
|
+
index, case-insensitive `glob-style pattern string
|
|
1451
|
+
<fnmatch.fnmatch>` or a compiled `regex pattern instance
|
|
1452
|
+
<re.compile>` used to match the linemaps by name. A negative
|
|
1453
|
+
index is interpreted as counting from the end of the available
|
|
1454
|
+
linemaps.
|
|
1455
|
+
|
|
1456
|
+
Example usage, adjusting the line thickness for all lines in the plot::
|
|
1457
|
+
|
|
1458
|
+
>>> plot.linemaps().line.line_thickness = 1.4
|
|
1459
|
+
"""
|
|
1460
|
+
indices = self._linemap_indices(*keys)
|
|
1461
|
+
return linemap.XYLinemapCollection(self, *indices)
|
|
1462
|
+
|
|
1463
|
+
def linemap(self, pattern):
|
|
1464
|
+
"""Returns a specific linemap within this plot.
|
|
1465
|
+
|
|
1466
|
+
Parameters:
|
|
1467
|
+
pattern (`int`, `str` or `re.Pattern <re.compile>`): Zero-based
|
|
1468
|
+
index, case-insensitive
|
|
1469
|
+
`glob-style pattern string <fnmatch.fnmatch>` or a compiled
|
|
1470
|
+
`regex pattern instance <re.compile>` used to match the
|
|
1471
|
+
linemaps by name. A negative index is interpreted as counting
|
|
1472
|
+
from the end of the available linemaps.
|
|
1473
|
+
|
|
1474
|
+
Returns:
|
|
1475
|
+
`XYLinemap` corresponding to *pattern* or `None` if *pattern* was
|
|
1476
|
+
passed in as a `str` or `regex pattern instance <re.compile>` and
|
|
1477
|
+
no matching linemap was found.
|
|
1478
|
+
|
|
1479
|
+
.. note::
|
|
1480
|
+
|
|
1481
|
+
Plots can contain linemaps with identical names and only the first
|
|
1482
|
+
match found is returned. This is not guaranteed to be deterministic
|
|
1483
|
+
and care should be taken to have only linemaps with unique names
|
|
1484
|
+
when this feature is used.
|
|
1485
|
+
|
|
1486
|
+
Example usage::
|
|
1487
|
+
|
|
1488
|
+
>>> plot.linemap(0).error_bar.show = True
|
|
1489
|
+
"""
|
|
1490
|
+
try:
|
|
1491
|
+
return next(iter(self.linemaps(pattern)))
|
|
1492
|
+
except StopIteration:
|
|
1493
|
+
pass
|
|
1494
|
+
|
|
1495
|
+
@property
|
|
1496
|
+
def active_linemaps(self):
|
|
1497
|
+
"""`XYLinemapCollection`: Active linemaps in this plot.
|
|
1498
|
+
|
|
1499
|
+
Example usage::
|
|
1500
|
+
|
|
1501
|
+
>>> plot.active_linemaps.show_symbols = True
|
|
1502
|
+
"""
|
|
1503
|
+
indices = self.active_linemap_indices
|
|
1504
|
+
return linemap.XYLinemapCollection(self, *indices)
|
|
1505
|
+
|
|
1506
|
+
def add_linemap(self, name=None, zone=None, x=None, y=None, show=True):
|
|
1507
|
+
"""Add a linemap using the specified zone and variables.
|
|
1508
|
+
|
|
1509
|
+
Parameters:
|
|
1510
|
+
|
|
1511
|
+
name (`str`): Name of the linemap which can be used for
|
|
1512
|
+
retrieving with `XYLinePlot.linemap`. If `None`, then the
|
|
1513
|
+
linemap will not have a name. Default: `None`.
|
|
1514
|
+
zone (`Zone <data_access>`): The data to be used when drawing this
|
|
1515
|
+
linemap. If `None`, then |Tecplot Engine| will select a zone.
|
|
1516
|
+
Default: `None`.
|
|
1517
|
+
x (`Variable`): The ``x`` variable which must be from the same
|
|
1518
|
+
`Dataset <data.Dataset>` as ``y`` and ``zone``. If `None`, then
|
|
1519
|
+
|Tecplot Engine| will select an x variable. Default: `None`.
|
|
1520
|
+
y (`Variable`): The ``y`` variable which must be from the same
|
|
1521
|
+
`Dataset <data.Dataset>` as ``x`` and ``zone``. If `None`, then
|
|
1522
|
+
|Tecplot Engine| will select a ``y`` variable. Default: `None`.
|
|
1523
|
+
show (`bool`, optional): Enable this linemap as soon as
|
|
1524
|
+
it's added. (default: `True`). If `None`, then |Tecplot Engine|
|
|
1525
|
+
will determine if the linemap should be enabled.
|
|
1526
|
+
|
|
1527
|
+
Returns:
|
|
1528
|
+
`XYLinemap`
|
|
1529
|
+
|
|
1530
|
+
Example usage::
|
|
1531
|
+
|
|
1532
|
+
>>> lmap = plot.add_linemap('Line 1', dataset.zone('Zone'),
|
|
1533
|
+
... dataset.variable('X'),
|
|
1534
|
+
... dataset.variable('Y'))
|
|
1535
|
+
>>> lmap.line.line_thickness = 0.8
|
|
1536
|
+
"""
|
|
1537
|
+
lmap = self._add_linemap(name, zone, show)
|
|
1538
|
+
if x is not None:
|
|
1539
|
+
lmap.x_variable = x
|
|
1540
|
+
if y is not None:
|
|
1541
|
+
lmap.y_variable = y
|
|
1542
|
+
return lmap
|
|
1543
|
+
|
|
1544
|
+
@property
|
|
1545
|
+
def axes(self):
|
|
1546
|
+
"""`XYLineAxes`: Axes style control for this plot.
|
|
1547
|
+
|
|
1548
|
+
Example usage::
|
|
1549
|
+
|
|
1550
|
+
>>> from tecplot.constant import PlotType, AxisMode
|
|
1551
|
+
>>> frame.plot_type = PlotType.XYLine
|
|
1552
|
+
>>> axes = frame.plot().axes
|
|
1553
|
+
>>> axes.axis_mode = AxisMode.XYDependent
|
|
1554
|
+
>>> axes.xy_ratio = 2
|
|
1555
|
+
"""
|
|
1556
|
+
return XYLineAxes(self)
|
|
1557
|
+
|
|
1558
|
+
@property
|
|
1559
|
+
def show_bars(self):
|
|
1560
|
+
"""`bool`: Enable bar chart drawing mode for this plot.
|
|
1561
|
+
|
|
1562
|
+
Example usage::
|
|
1563
|
+
|
|
1564
|
+
>>> plot.show_bars = True
|
|
1565
|
+
"""
|
|
1566
|
+
return self._get_style(bool, sv.SHOWBARCHARTS)
|
|
1567
|
+
|
|
1568
|
+
@show_bars.setter
|
|
1569
|
+
def show_bars(self, value):
|
|
1570
|
+
self._set_style(bool(value), sv.SHOWBARCHARTS)
|
|
1571
|
+
|
|
1572
|
+
@property
|
|
1573
|
+
def show_error_bars(self):
|
|
1574
|
+
"""`bool`: Enable error bars for this plot.
|
|
1575
|
+
|
|
1576
|
+
The variable to be used for error bars must be set first on at least
|
|
1577
|
+
one linemap within this plot::
|
|
1578
|
+
|
|
1579
|
+
>>> plot.linemap(0).error_bars.variable = dataset.variable('E')
|
|
1580
|
+
>>> plot.show_error_bars = True
|
|
1581
|
+
"""
|
|
1582
|
+
return self._get_style(bool, sv.SHOWERRORBARS)
|
|
1583
|
+
|
|
1584
|
+
@show_error_bars.setter
|
|
1585
|
+
def show_error_bars(self, value):
|
|
1586
|
+
self._set_style(bool(value), sv.SHOWERRORBARS)
|
|
1587
|
+
|
|
1588
|
+
@property
|
|
1589
|
+
def view(self):
|
|
1590
|
+
"""`XYLineView`: View control of the plot relative to the frame.
|
|
1591
|
+
|
|
1592
|
+
Example usage::
|
|
1593
|
+
|
|
1594
|
+
>>> plot.view.fit()
|
|
1595
|
+
"""
|
|
1596
|
+
return view.XYLineView(self)
|
|
1597
|
+
|
|
1598
|
+
@property
|
|
1599
|
+
def linking_between_frames(self):
|
|
1600
|
+
"""`XYLinePlotLinkingBetweenFrames`: Style linking between frames.
|
|
1601
|
+
|
|
1602
|
+
Example usage::
|
|
1603
|
+
|
|
1604
|
+
>>> plot.linking_between_frames.group = 1
|
|
1605
|
+
>>> plot.linking_between_frames.link_solution_time = True
|
|
1606
|
+
"""
|
|
1607
|
+
return linking.XYLinePlotLinkingBetweenFrames(self.frame)
|
|
1608
|
+
|
|
1609
|
+
|
|
1610
|
+
class PolarLinePlot(LinePlot):
|
|
1611
|
+
"""Polar plot with line data and associated style through linemaps.
|
|
1612
|
+
|
|
1613
|
+
.. code-block:: python
|
|
1614
|
+
:emphasize-lines: 16-22
|
|
1615
|
+
|
|
1616
|
+
import numpy as np
|
|
1617
|
+
import tecplot as tp
|
|
1618
|
+
from tecplot.constant import *
|
|
1619
|
+
|
|
1620
|
+
frame = tp.active_frame()
|
|
1621
|
+
|
|
1622
|
+
npoints = 300
|
|
1623
|
+
r = np.linspace(0, 2000, npoints)
|
|
1624
|
+
theta = np.linspace(0, 10, npoints)
|
|
1625
|
+
|
|
1626
|
+
dataset = frame.create_dataset('Data', ['R', 'Theta'])
|
|
1627
|
+
zone = dataset.add_ordered_zone('Zone', (300,))
|
|
1628
|
+
zone.values('R')[:] = r
|
|
1629
|
+
zone.values('Theta')[:] = theta
|
|
1630
|
+
|
|
1631
|
+
plot = frame.plot(PlotType.PolarLine)
|
|
1632
|
+
plot.activate()
|
|
1633
|
+
plot.axes.r_axis.max = r.max()
|
|
1634
|
+
plot.axes.theta_axis.mode = ThetaMode.Radians
|
|
1635
|
+
plot.delete_linemaps()
|
|
1636
|
+
lmap = plot.add_linemap('Linemap', zone, dataset.variable('R'),
|
|
1637
|
+
dataset.variable('Theta'))
|
|
1638
|
+
lmap.line.line_thickness = 0.8
|
|
1639
|
+
lmap.line.color = Color.Green
|
|
1640
|
+
|
|
1641
|
+
plot.view.fit()
|
|
1642
|
+
|
|
1643
|
+
tp.export.save_png('plot_polar.png', 600, supersample=3)
|
|
1644
|
+
|
|
1645
|
+
.. figure:: /_static/images/plot_polar.png
|
|
1646
|
+
:width: 300px
|
|
1647
|
+
:figwidth: 300px
|
|
1648
|
+
"""
|
|
1649
|
+
|
|
1650
|
+
def activate(self):
|
|
1651
|
+
"""Make this the active plot type on the parent frame.
|
|
1652
|
+
|
|
1653
|
+
Example usage::
|
|
1654
|
+
|
|
1655
|
+
>>> from tecplot.constant import PlotType
|
|
1656
|
+
>>> plot = frame.plot(PlotType.PolarLine)
|
|
1657
|
+
>>> plot.activate()
|
|
1658
|
+
"""
|
|
1659
|
+
self.frame.plot_type = PlotType.PolarLine
|
|
1660
|
+
|
|
1661
|
+
@property
|
|
1662
|
+
def axes(self):
|
|
1663
|
+
"""`PolarLineAxes`: Axes style control for this plot.
|
|
1664
|
+
|
|
1665
|
+
Example usage::
|
|
1666
|
+
|
|
1667
|
+
>>> from tecplot.constant import PlotType, ThetaMode
|
|
1668
|
+
>>> frame.plot_type = PlotType.PolarLine
|
|
1669
|
+
>>> axes = frame.plot().axes
|
|
1670
|
+
>>> axes.theta_mode = ThetaMode.Radians
|
|
1671
|
+
"""
|
|
1672
|
+
return PolarLineAxes(self)
|
|
1673
|
+
|
|
1674
|
+
@property
|
|
1675
|
+
def view(self):
|
|
1676
|
+
"""`PolarView`: View control of the plot relative to the frame.
|
|
1677
|
+
|
|
1678
|
+
Example usage::
|
|
1679
|
+
|
|
1680
|
+
>>> plot.view.fit()
|
|
1681
|
+
"""
|
|
1682
|
+
return view.PolarView(self)
|
|
1683
|
+
|
|
1684
|
+
def add_linemap(self, name=None, zone=None, r=None, theta=None, show=True):
|
|
1685
|
+
"""Add a linemap using the specified zone and variables.
|
|
1686
|
+
|
|
1687
|
+
Parameters:
|
|
1688
|
+
name (`str`): Name of the linemap which can be used for
|
|
1689
|
+
retrieving with `PolarLinePlot.linemap`. If `None`, then the
|
|
1690
|
+
linemap will not have a name. Default: `None`.
|
|
1691
|
+
zone (`Zone <data_access>`): The data to be used when drawing this
|
|
1692
|
+
linemap. If `None`, then |Tecplot Engine| will select a
|
|
1693
|
+
`Zone <data_access>`.
|
|
1694
|
+
Default: `None`.
|
|
1695
|
+
r (`Variable`): The ``r`` variable which must be from the same
|
|
1696
|
+
`Dataset <data.Dataset>` as ``theta`` and ``zone``. If `None`, then
|
|
1697
|
+
|Tecplot Engine| will select a variable. Default: `None`.
|
|
1698
|
+
theta (`Variable`): The ``theta`` variable which must be from the
|
|
1699
|
+
same `Dataset <data.Dataset>` as ``r`` and ``zone``. If `None`, then
|
|
1700
|
+
|Tecplot Engine| will select a variable. Default: `None`.
|
|
1701
|
+
show (`bool`, optional): Enable this linemap as soon as
|
|
1702
|
+
it's added. (default: `True`)
|
|
1703
|
+
|
|
1704
|
+
Returns:
|
|
1705
|
+
`PolarLinemap`
|
|
1706
|
+
|
|
1707
|
+
Example usage::
|
|
1708
|
+
|
|
1709
|
+
>>> lmap = plot.add_linemap('Line 1', dataset.zone('Zone'),
|
|
1710
|
+
... dataset.variable('R'),
|
|
1711
|
+
... dataset.variable('Theta'))
|
|
1712
|
+
>>> lmap.line.line_thickness = 0.8
|
|
1713
|
+
"""
|
|
1714
|
+
lmap = self._add_linemap(name, zone, show)
|
|
1715
|
+
if r is not None:
|
|
1716
|
+
lmap.r_variable = r
|
|
1717
|
+
if theta is not None:
|
|
1718
|
+
lmap.theta_variable = theta
|
|
1719
|
+
return lmap
|
|
1720
|
+
|
|
1721
|
+
def linemaps(self, *keys):
|
|
1722
|
+
"""`PolarLinemapCollection` by index or name.
|
|
1723
|
+
|
|
1724
|
+
Parameters:
|
|
1725
|
+
keys (`int`, `str` or `re.Pattern <re.compile>`): Zero-based
|
|
1726
|
+
index, case-insensitive `glob-style pattern string
|
|
1727
|
+
<fnmatch.fnmatch>` or a compiled `regex pattern instance
|
|
1728
|
+
<re.compile>` used to match the linemaps by name. A negative
|
|
1729
|
+
index is interpreted as counting from the end of the available
|
|
1730
|
+
linemaps.
|
|
1731
|
+
|
|
1732
|
+
Example usage, adjusting the line thickness for all lines in the plot::
|
|
1733
|
+
|
|
1734
|
+
>>> plot.linemaps().line.line_thickness = 1.4
|
|
1735
|
+
"""
|
|
1736
|
+
indices = self._linemap_indices(*keys)
|
|
1737
|
+
return linemap.PolarLinemapCollection(self, *indices)
|
|
1738
|
+
|
|
1739
|
+
def linemap(self, pattern):
|
|
1740
|
+
"""Returns a specific linemap within this plot.
|
|
1741
|
+
|
|
1742
|
+
Parameters:
|
|
1743
|
+
pattern (`int`, `str` or `re.Pattern <re.compile>`): Zero-based
|
|
1744
|
+
index, case-insensitive
|
|
1745
|
+
`glob-style pattern string <fnmatch.fnmatch>` or a compiled
|
|
1746
|
+
`regex pattern instance <re.compile>` used to match the
|
|
1747
|
+
linemaps by name. A negative index is interpreted as counting
|
|
1748
|
+
from the end of the available linemaps.
|
|
1749
|
+
|
|
1750
|
+
Returns:
|
|
1751
|
+
`PolarLinemap` corresponding to *pattern* or `None` if *pattern*
|
|
1752
|
+
was passed in as a `str` or `regex pattern instance <re.compile>`
|
|
1753
|
+
and no matching linemap was found.
|
|
1754
|
+
|
|
1755
|
+
.. note::
|
|
1756
|
+
|
|
1757
|
+
Plots can contain linemaps with identical names and only the first
|
|
1758
|
+
match found is returned. This is not guaranteed to be deterministic
|
|
1759
|
+
and care should be taken to have only linemaps with unique names
|
|
1760
|
+
when this feature is used.
|
|
1761
|
+
|
|
1762
|
+
Example usage::
|
|
1763
|
+
|
|
1764
|
+
>>> plot.linemap(0).error_bar.show = True
|
|
1765
|
+
"""
|
|
1766
|
+
try:
|
|
1767
|
+
return next(iter(self.linemaps(pattern)))
|
|
1768
|
+
except StopIteration:
|
|
1769
|
+
pass
|
|
1770
|
+
|
|
1771
|
+
@property
|
|
1772
|
+
def active_linemaps(self):
|
|
1773
|
+
"""`PolarLinemapCollection`: Active linemaps in this plot.
|
|
1774
|
+
|
|
1775
|
+
Example usage::
|
|
1776
|
+
|
|
1777
|
+
>>> plot.active_linemaps.show_symbols = True
|
|
1778
|
+
"""
|
|
1779
|
+
indices = self.active_linemap_indices
|
|
1780
|
+
return linemap.PolarLinemapCollection(self, *indices)
|
|
1781
|
+
|
|
1782
|
+
@property
|
|
1783
|
+
def linking_between_frames(self):
|
|
1784
|
+
"""`PolarPlotLinkingBetweenFrames`: Style linking between frames.
|
|
1785
|
+
|
|
1786
|
+
Example usage::
|
|
1787
|
+
|
|
1788
|
+
>>> plot.linking_between_frames.group = 1
|
|
1789
|
+
>>> plot.linking_between_frames.link_solution_time = True
|
|
1790
|
+
"""
|
|
1791
|
+
return linking.PolarPlotLinkingBetweenFrames(self.frame)
|