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
tecplot/plot/view.py ADDED
@@ -0,0 +1,868 @@
1
+ from builtins import super
2
+
3
+ import itertools
4
+ import math
5
+
6
+ from ..tecutil import _tecutil
7
+ from ..constant import *
8
+ from ..exception import *
9
+ from .. import constant, session, tecutil, version
10
+ from ..tecutil import lock, lock_attributes, sv
11
+
12
+
13
+ @lock_attributes
14
+ class View(session.Style):
15
+ """View of plot within the frame."""
16
+ def __init__(self, plot, *svargs):
17
+ self.plot = plot
18
+ super().__init__(svargs, uniqueid=plot.frame.uid)
19
+
20
+ @lock()
21
+ def _view_action(self, action, consider_blanking=None):
22
+ """Internal implementation for all view actions which take a single
23
+ consider_blanking parameter."""
24
+ with self.plot.frame.activated():
25
+ with tecutil.ArgList() as arglist:
26
+ arglist[sv.VIEWOP] = action
27
+ arglist[sv.CONSIDERBLANKING] = consider_blanking
28
+ if not _tecutil.ViewX(arglist):
29
+ raise TecplotSystemError()
30
+
31
+ @property
32
+ def magnification(self):
33
+ """`float`: Magnification for the data being plotted.
34
+
35
+ The ``magnification`` value is a decimal percent and must be greater
36
+ than 0. A ``magnification`` size of 1.0 (100%) will size the plot so
37
+ that it can fit within the grid area. The following example will scale
38
+ the view to ten percent of the size at which the data would fit the
39
+ full frame::
40
+
41
+ >>> view.magnification = 0.10
42
+ """
43
+ with self.plot.frame.activated():
44
+ success, result = _tecutil.ViewGetMagnification()
45
+ if not success:
46
+ raise TecplotSystemError()
47
+ return result
48
+
49
+ @magnification.setter
50
+ @lock()
51
+ def magnification(self, value):
52
+ with self.plot.frame.activated():
53
+ if not _tecutil.ViewSetMagnification(float(value)):
54
+ raise TecplotSystemError()
55
+
56
+ @lock()
57
+ def translate(self, x=0.0, y=0.0):
58
+ """Shift the data being plotted in the X and/or Y direction.
59
+
60
+ .. note:: The amount translated is in frame units.
61
+
62
+ Parameters:
63
+ x (`float`, optional): Amount to shift in the X direction
64
+ as a percentage of the frame width. Positive values shift right,
65
+ negative values shift left. (default: 0.0)
66
+ y (`float`, optional): Amount to shift in the Y direction
67
+ as a percentage of the frame height. Positive values shift up,
68
+ negative values shift down. (default: 0.0)
69
+
70
+ Translate the view 10 percent of the frame width to the right::
71
+
72
+ >>> view.translate(x=10)
73
+
74
+ Translate the view 5 percent of the frame width to the right,
75
+ 20 of the frame height down::
76
+
77
+ >>> view.translate(x=5, y=-20)
78
+ """
79
+ with self.plot.frame.activated():
80
+ if not _tecutil.ViewTranslate(float(x), float(y)):
81
+ raise TecplotSystemError()
82
+
83
+ @lock()
84
+ def zoom(self, xmin, ymin, xmax, ymax):
85
+ """Zoom the view to a rectangular region of the plot.
86
+
87
+ Change the view by "zooming" into the data. Ranges on the axes are
88
+ adjusted to view the region defined by the rectangle with corners at
89
+ (``xmin``, ``ymin``) and (``xmax``, ``ymax``).
90
+
91
+ .. note:: All position values are defined in units of the X- and
92
+ Y- axis (that is, grid coordinates).
93
+
94
+ Parameters:
95
+ xmin: (`float`) X min corner of the rectangle to be viewed.
96
+ ymin: (`float`) Y min corner of the rectangle to be viewed.
97
+ xmax: (`float`) X max corner of the rectangle to be viewed.
98
+ ymax: (`float`) Y max corner of the rectangle to be viewed.
99
+
100
+ Zoom so the rectangular region with corners at ``(1, 0)`` and ``(7,
101
+ 9)`` is in view::
102
+
103
+ >>> view.zoom(1, 7, 0, 9)
104
+ """
105
+ with self.plot.frame.activated():
106
+ if not _tecutil.ViewZoom(float(xmin), float(ymin),
107
+ float(xmax), float(ymax)):
108
+ raise TecplotSystemError()
109
+
110
+
111
+ class Cartesian2DView(View):
112
+ def adjust_to_nice(self):
113
+ """Shifts axes to make axis-line values "nice"
114
+
115
+ Modifies the axis range to fit the minimum and maximum of the
116
+ variable assigned to that axis, then snaps the major tick marks to
117
+ the ends of the axis. If axis dependency is not independent,
118
+ this may affect the range on another axis.
119
+
120
+ In other words, given an existing range of values RMin, RMax and an
121
+ initial delta, D (such as axis ranges with grid spacing or
122
+ contour levels), determine a new delta (ND) that:
123
+
124
+ * Is 1,2, or 5 times 10 to some power that is the "best"
125
+ alternative to D.
126
+ * Produces new range min and max values that are some multiple of ND
127
+ that are nearest the original RMin and RMax
128
+
129
+ Axes are shifted without changing the extents of the window.
130
+ """
131
+ self._view_action(constant.View.MakeCurrentViewNice)
132
+
133
+ def fit_to_nice(self):
134
+ """Set axis range to begin/end on major axis increments.
135
+
136
+ Changes the view to make the extents of the frame neatly hold the
137
+ plot with integer values for axis labels.
138
+ """
139
+ self._view_action(constant.View.NiceFit)
140
+
141
+
142
+ class FieldView(View):
143
+ def fit(self, consider_blanking=True):
144
+ """Fit the data being plotted within the axis grid area.
145
+
146
+ .. note:: This also takes into consideration text and geometries that
147
+ are plotted using the grid coordinate system.
148
+
149
+ Parameters:
150
+ consider_blanking (`Boolean <bool>`, optional): If `True` and
151
+ blanking is enabled, the resulting view excludes blanked cells
152
+ at the edges of the plot. If 'False`, then
153
+ the resulting view will ignore blanked cells at the edges of the
154
+ plot. (default: `True`)
155
+ """
156
+ self._view_action(constant.View.Fit, consider_blanking)
157
+
158
+ def fit_data(self, consider_blanking=True):
159
+ """Fit data zones or line mappings within the grid area.
160
+
161
+ Parameters:
162
+ consider_blanking (`Boolean <bool>`, optional): If `True` and
163
+ blanking is enabled, the resulting view excludes blanked cells
164
+ at the edges of the plot. If 'False`, then
165
+ the resulting view will ignore blanked cells at the edges of the
166
+ plot. (default: `True`)
167
+
168
+ .. note:: This does not take into consideration text and geometries that
169
+ are plotted using the grid coordinate system.
170
+ """
171
+ self._view_action(constant.View.DataFit, consider_blanking)
172
+
173
+ def center(self, consider_blanking=True):
174
+ """Center the data within the axis grid area.
175
+
176
+ Parameters:
177
+ consider_blanking (`Boolean <bool>`, optional): If `True` and
178
+ blanking is enabled, the resulting view excludes blanked cells
179
+ at the edges of the plot. If 'False`, then
180
+ the resulting view will ignore blanked cells at the edges of the
181
+ plot. (default: `True`)
182
+ """
183
+ self._view_action(constant.View.Center, consider_blanking)
184
+
185
+
186
+ class LineView(View):
187
+ def fit(self):
188
+ """Fit the data being plotted within the axis grid area.
189
+
190
+ .. note:: This also takes into consideration text and geometries that
191
+ are plotted using the grid coordinate system.
192
+ """
193
+ self._view_action(constant.View.Fit)
194
+
195
+ def fit_data(self):
196
+ """Fit data zones or line mappings within the grid area.
197
+
198
+ .. note:: This does not take into consideration text and geometries
199
+ that are plotted using the grid coordinate system.
200
+ """
201
+ self._view_action(constant.View.DataFit)
202
+
203
+ def center(self):
204
+ """Center the data within the axis grid area.
205
+
206
+ Raises:
207
+ `TecplotSystemError`: View could not be centered.
208
+ """
209
+ self._view_action(constant.View.Center)
210
+
211
+ @property
212
+ def extents(self):
213
+ """`tuple`: Viewport extents in data units.
214
+
215
+ Extents are represented by the `tuple`: ``(x1, y1, x2, y2)`` and
216
+ setting this effectively zooms the view of the data within the
217
+ viewport. The values ``(x1, y1)`` and ``(x2, y2)`` are the lower-left
218
+ and upper-right edges respectively and are in data units. The following
219
+ example will set the bottom and left edges of the viewport to the value
220
+ of ``-3`` and the top and right edges to the value of 5::
221
+
222
+ >>> plot.view.extents = -3, -3, 5, 5
223
+ """
224
+ return session.RectPosition(self, sv.VIEWPORTPOSITION)
225
+
226
+ @extents.setter
227
+ def extents(self, values):
228
+ session.RectPosition(self, sv.VIEWPORTPOSITION)[:] = values
229
+
230
+
231
+ class XYLineView(LineView, Cartesian2DView):
232
+ """Adjust the way XY Line data is displayed.
233
+
234
+ .. code-block:: python
235
+ :emphasize-lines: 20
236
+
237
+ import os
238
+ import tecplot
239
+ from tecplot.constant import *
240
+
241
+ examples_dir = tecplot.session.tecplot_examples_directory()
242
+ datafile = os.path.join(examples_dir, 'SimpleData', 'Rainfall.dat')
243
+ dataset = tecplot.data.load_tecplot(datafile)
244
+
245
+ frame = tecplot.active_frame()
246
+ plot = frame.plot()
247
+ frame.plot_type = tecplot.constant.PlotType.XYLine
248
+
249
+ for i in range(3):
250
+ plot.linemap(i).show = True
251
+ plot.linemap(i).line.line_thickness = .4
252
+
253
+ y_axis = plot.axes.y_axis(0)
254
+ y_axis.title.title_mode = AxisTitleMode.UseText
255
+ y_axis.title.text = 'Rainfall (in)'
256
+ plot.view.fit_to_nice()
257
+
258
+ tecplot.export.save_png('view_line.png', 600, supersample=3)
259
+
260
+ .. figure:: /_static/images/view_line.png
261
+ :width: 300px
262
+ :figwidth: 300px
263
+ """
264
+ def __init__(self, plot):
265
+ super().__init__(plot, sv.XYLINEAXIS)
266
+
267
+
268
+ class Cartesian2DFieldView(FieldView, Cartesian2DView):
269
+ """Adjust the way cartesian 2D data is displayed.
270
+
271
+ .. code-block:: python
272
+ :emphasize-lines: 16
273
+
274
+ from os import path
275
+ import tecplot as tp
276
+ from tecplot.constant import PlotType
277
+
278
+ examples_dir = tp.session.tecplot_examples_directory()
279
+ infile = path.join(examples_dir, 'SimpleData', 'HeatExchanger.plt')
280
+ dataset = tp.data.load_tecplot(infile)
281
+
282
+ frame = tp.active_frame()
283
+ plot = frame.plot(PlotType.Cartesian2D)
284
+ plot.activate()
285
+ plot.show_contour = True
286
+ plot.contour(0).variable = dataset.variable('P(N)')
287
+ plot.contour(0).colormap_name = 'Sequential - Yellow/Green/Blue'
288
+
289
+ plot.view.fit_to_nice()
290
+
291
+ # ensure consistent output between interactive (connected) and batch
292
+ plot.contour(0).levels.reset_to_nice()
293
+
294
+ tp.export.save_png('view_2D.png', 600, supersample=3)
295
+
296
+ .. figure:: /_static/images/view_2D.png
297
+ :width: 300px
298
+ :figwidth: 300px
299
+ """
300
+ def fit_to_nice(self, consider_blanking=True):
301
+ """Set axis range to begin/end on major axis increments.
302
+
303
+ Changes the view to make the extents of the frame neatly hold the
304
+ plot with integer values for axis labels.
305
+
306
+ Parameters:
307
+ consider_blanking (`Boolean <bool>`, optional): If `True` and
308
+ blanking is enabled, the resulting view excludes blanked cells
309
+ at the edges of the plot. If 'False`, then
310
+ the resulting view will ignore blanked cells at the edges of the
311
+ plot. (default: `True`)
312
+ """
313
+ self._view_action(constant.View.NiceFit, consider_blanking)
314
+
315
+
316
+ class Cartesian3DView(FieldView):
317
+ """Adjust the way cartesian 3D data is displayed.
318
+
319
+ .. code-block:: python
320
+ :emphasize-lines: 9-13
321
+
322
+ import tecplot
323
+ import os
324
+ from tecplot.constant import *
325
+ examples_dir = tecplot.session.tecplot_examples_directory()
326
+ infile = os.path.join(examples_dir, 'SimpleData', 'F18.plt')
327
+ ds = tecplot.data.load_tecplot(infile)
328
+ plot = tecplot.active_frame().plot(PlotType.Cartesian3D)
329
+ plot.activate()
330
+ plot.view.width = 17.5
331
+ plot.view.alpha = 0
332
+ plot.view.theta = 125
333
+ plot.view.psi = 65
334
+ plot.view.position = (-100, 80, 65)
335
+
336
+ tecplot.export.save_jpeg('view_3D.jpeg', 600, supersample=3)
337
+
338
+ .. figure:: /_static/images/view_3D.jpeg
339
+ :width: 300px
340
+ :figwidth: 300px
341
+ """
342
+ def __init__(self, plot):
343
+ super().__init__(plot, sv.THREEDVIEW)
344
+
345
+ @lock()
346
+ def rotate_to_angles(self, psi, theta, alpha):
347
+ """Rotate the plot to specific angles.
348
+
349
+ Parameters:
350
+ psi: (`float`): Tilt, in degrees, of the eye origin ray away from
351
+ the Z-axis.
352
+ theta: (`float`): Rotation, in degrees, of the eye origin ray about
353
+ the Z-axis.
354
+ alpha: (`float`): Twist, in degrees, about the eye origin ray.
355
+ """
356
+ _tecutil.RotateToSpecificAngles(float(psi), float(theta), float(alpha))
357
+
358
+ @lock()
359
+ def _rotate(self, angle, normal, origin):
360
+ rotate_axis = RotateAxis.AboutVector
361
+ for i, j in itertools.combinations([0, 1, 2], 2):
362
+ if normal[i] == 0 and normal[j] == 0:
363
+ a = ({0, 1, 2} - {i, j}).pop()
364
+ rotate_axis = {0: RotateAxis.X,
365
+ 1: RotateAxis.Y,
366
+ 2: RotateAxis.Z}[a]
367
+ if normal[a] < 0:
368
+ angle = -1 * angle
369
+ break
370
+ if not _tecutil.ViewRotate3D(rotate_axis.value, angle, normal[0],
371
+ normal[1], normal[2],
372
+ RotateOriginLocation(origin).value):
373
+ raise TecplotSystemError()
374
+
375
+ @property
376
+ def rotation_origin(self):
377
+ """`tuple`: Center of rotation for `rotate_axes` and `rotate_viewer`.
378
+
379
+ Example of rotating 30 degrees about the :math:`y`-axis and around the
380
+ data-position :math:`(x, y, z) = (1, 2, 3)`::
381
+
382
+ >>> plot.view.rotation_origin = (1, 2, 3)
383
+ >>> plot.view.rotate_axes(30, (0, 1, 0))
384
+ """
385
+ style = session.Style(sv.GLOBALTHREED, uniqueid=self.plot.frame.uid)
386
+ return session.XYZ(style, sv.ROTATEORIGIN)
387
+
388
+ @rotation_origin.setter
389
+ def rotation_origin(self, values):
390
+ style = session.Style(sv.GLOBALTHREED, uniqueid=self.plot.frame.uid)
391
+ session.XYZ(style, sv.ROTATEORIGIN)[:] = values
392
+
393
+ def rotate_axes(self, angle, normal=(0, 0, 1)):
394
+ """Adjust the view so the axes are rotated about some normal vector.
395
+
396
+ This effectively rotates the axes around the axes origin about some
397
+ **normal** using the right-hand rule by the specified **angle** in
398
+ degrees. The rotation is performed about the position:
399
+ `Cartesian3DView.rotation_origin`.
400
+
401
+ Parameters:
402
+ angle (`float`): The angle in degrees to rotate.
403
+ normal (`tuple`, optional): The direction vector :math:`(x, y, z)`
404
+ around which the rotation will be done.
405
+ (default: ``(0, 0, 1)``)
406
+
407
+ Example of rotating 30 degrees about the :math:`x`-axis and around the
408
+ data's origin::
409
+
410
+ >>> plot.view.rotation_origin = (0, 0, 0)
411
+ >>> plot.view.rotate_axes(30, (1, 0, 0))
412
+ """
413
+ return self._rotate(angle, normal, RotateOriginLocation.DefinedOrigin)
414
+
415
+ def rotate_viewer(self, angle, normal=(0, 0, 1)):
416
+ """Rotate the camera or viewer about some normal vector.
417
+
418
+ This rotates the viewer about some **normal** using the right-hand rule
419
+ by the specified **angle** in degrees. The rotation is performed about
420
+ the position: `Cartesian3DView.rotation_origin`.
421
+
422
+ Parameters:
423
+ angle (`float`): The angle in degrees to rotate.
424
+ normal (`tuple`, optional): The direction vector :math:`(x, y, z)`
425
+ around which the rotation will be done.
426
+ (default: ``(0, 0, 1)``)
427
+
428
+ Example of rotating 2 degrees about the :math:`x`-axis and around the
429
+ data's origin::
430
+
431
+ >>> plot.view.rotation_origin = (0, 0, 0)
432
+ >>> plot.view.rotate_viewer(2, (1, 0, 0))
433
+ """
434
+ return self._rotate(angle, normal, RotateOriginLocation.Viewer)
435
+
436
+ def fit_surfaces(self, consider_blanking=True):
437
+ """Fit 3D plot surfaces to the grid area.
438
+
439
+ Parameters:
440
+ consider_blanking (`bool`, optional): If `True` and blanking is
441
+ enabled, the resulting view excludes blanked cells at the edges
442
+ of the plot. If 'False`, then the resulting view will ignore
443
+ blanked cells at the edges of the plot. (default: `True`)
444
+
445
+ .. note:: 3D volume zones are excluded when `surfaces_to_plot` is
446
+ `SurfacesToPlot.None_`.
447
+ """
448
+ self._view_action(constant.View.FitSurfaces, consider_blanking)
449
+
450
+ @property
451
+ def _draw_in_perspective(self):
452
+ # DRAWINPERSPECTIVE is deprecated, but we use it privately for backward
453
+ # compatibility if PROJECTION is not available.
454
+ return self._get_style(bool, sv.DRAWINPERSPECTIVE)
455
+
456
+ @property
457
+ def field_of_view(self):
458
+ """`float`: Amount of the plot which is displayed.
459
+
460
+ Get or set the amount of the plot (in terms of spherical arc) in front
461
+ of the viewer that may be seen.
462
+
463
+ .. warning:: ``field_of_view`` cannot be set if `projection`
464
+ is `Projection.Orthographic`.
465
+
466
+ Example usage::
467
+
468
+ >>> from tecplot.constant import Projection
469
+ >>> plot.view.projection = Projection.Perspective
470
+ >>> plot.view.field_of_view = 9.6
471
+ """
472
+ return self._get_style(float, sv.FIELDOFVIEW)
473
+
474
+ @field_of_view.setter
475
+ def field_of_view(self, value):
476
+ if __debug__:
477
+ if not self._draw_in_perspective:
478
+ raise TecplotValueError('Cannot set field_of_view if not '
479
+ 'using perspective.')
480
+ self._set_style(float(value), sv.FIELDOFVIEW)
481
+
482
+ @property
483
+ def projection(self):
484
+ """`Projection`: Projection type (`Perspective` or `Orthographic`).
485
+
486
+ When set to `Perspective`, Tecplot 360 draws the plot in perspective.
487
+ When set to `Orthographic`, the plot is drawn with orthographic
488
+ projection where the shape of the object does not change with distance.
489
+
490
+ .. note:: Requires Tecplot version 2017.2 or later.
491
+
492
+ Example usage::
493
+
494
+ >>> from tecplot.constant import Projection
495
+ >>> plot.view.projection = Projection.Orthographic
496
+ """
497
+ return self._get_style(Projection, sv.PROJECTION)
498
+
499
+ @projection.setter
500
+ def projection(self, value):
501
+ self._set_style(Projection(value), sv.PROJECTION)
502
+
503
+ @property
504
+ def psi(self):
505
+ """`float`: Eye origin view Psi angle in degrees.
506
+
507
+ The Psi angle is the tilt of the eye origin ray away from the Z-axis::
508
+
509
+ >>> plot.view.psi = 90.0
510
+ """
511
+ return self._get_style(float, sv.PSIANGLE)
512
+
513
+ @psi.setter
514
+ def psi(self, angle):
515
+ self._set_style(math.fmod(float(angle), 360.0), sv.PSIANGLE)
516
+
517
+ @property
518
+ def theta(self):
519
+ """`float`: Eye origin view Theta angle in degrees.
520
+
521
+ The Theta angle is the rotation of the eye origin ray about the
522
+ Z-axis::
523
+
524
+ >>> plot.view.theta = 24.3
525
+ """
526
+ return self._get_style(float, sv.THETAANGLE)
527
+
528
+ @theta.setter
529
+ def theta(self, angle):
530
+ self._set_style(math.fmod(float(angle), 360.0), sv.THETAANGLE)
531
+
532
+ @property
533
+ def alpha(self):
534
+ """`float`: Eye origin view Alpha angle in degrees.
535
+
536
+ The Alpha angle is the twist about the eye origin ray::
537
+
538
+ >>> plot.view.alpha = 95.0
539
+ """
540
+ return self._get_style(float, sv.ALPHAANGLE)
541
+
542
+ @alpha.setter
543
+ def alpha(self, angle):
544
+ self._set_style(math.fmod(float(angle), 360.0), sv.ALPHAANGLE)
545
+
546
+ @property
547
+ def position(self):
548
+ """`tuple`: 3D viewer position.
549
+
550
+ The viewer position is the viewer's relation to the image::
551
+
552
+ >>> plot.view.position
553
+ (1.25, 3.2, 0.74)
554
+ >>> plot.view.position.x
555
+ 1.25
556
+ >>> plot.view.position = (2.5, 0.0, 1.0)
557
+ >>> plot.view.position.y
558
+ 0.0
559
+ >>> plot.view.position.z
560
+ 1.0
561
+
562
+ .. seealso:: `distance`
563
+ """
564
+ return session.XYZ(self, sv.VIEWERPOSITION)
565
+
566
+ @position.setter
567
+ def position(self, pos):
568
+ session.XYZ(self, sv.VIEWERPOSITION)[:] = pos
569
+
570
+ @property
571
+ def width(self):
572
+ """`float`: 3D view width.
573
+
574
+ The 3D view width is the amount of the plot (in X-axis units) in front
575
+ of the viewer that may be seen.
576
+
577
+ .. warning:: `width` cannot be set if `projection` is `Perspective`.
578
+
579
+ Example usage::
580
+
581
+ >>> plot.view.width = 1.5
582
+ """
583
+ return self._get_style(float, sv.VIEWWIDTH)
584
+
585
+ @width.setter
586
+ def width(self, value):
587
+ if __debug__:
588
+ if self._draw_in_perspective:
589
+ raise TecplotValueError('view width cannot be set if drawing '
590
+ 'in perspective.')
591
+ self._set_style(float(value), sv.VIEWWIDTH)
592
+
593
+ @property
594
+ def distance(self):
595
+ """`float`: Get or set the view distance.
596
+
597
+ The view distance is the distance from the viewer to the plane that is
598
+ parallel to the screen and passes through the 3-D rotation origin.
599
+
600
+ .. note:: Changing this value will also change the viewer `position`.
601
+
602
+ .. seealso:: `position`
603
+
604
+ Example usage::
605
+
606
+ >>> plot.view.distance
607
+ 13.5
608
+ >>> plot.view.distance = 10.0
609
+ >>> plot.view.distance
610
+ 10.0
611
+ """
612
+ return _tecutil.ThreeDViewGetDistanceToRotateOriginPlane()
613
+
614
+ @distance.setter
615
+ @lock()
616
+ def distance(self, value):
617
+ if not _tecutil.Set3DEyeDistance(float(value)):
618
+ raise TecplotSystemError()
619
+
620
+
621
+ class PolarView(LineView):
622
+ """Adjust the way polar data is displayed.
623
+
624
+ .. code-block:: python
625
+ :emphasize-lines: 27
626
+
627
+ import numpy as np
628
+ import tecplot as tp
629
+ from tecplot.constant import PlotType, ThetaMode
630
+
631
+ frame = tp.active_frame()
632
+
633
+ npoints = 300
634
+ r = np.linspace(0, 2000, npoints)
635
+ theta = np.linspace(0, 10, npoints)
636
+
637
+ dataset = frame.create_dataset('Data', ['R', 'Theta'])
638
+ zone = dataset.add_ordered_zone('Zone', (300,))
639
+ zone.values('R')[:] = r
640
+ zone.values('Theta')[:] = theta
641
+
642
+ plot = frame.plot(PlotType.PolarLine)
643
+ plot.activate()
644
+
645
+ plot.axes.r_axis.max = np.max(r)
646
+ plot.axes.theta_axis.mode = ThetaMode.Radians
647
+
648
+ plot.delete_linemaps()
649
+ lmap = plot.add_linemap('Linemap', zone, dataset.variable('R'),
650
+ dataset.variable('Theta'))
651
+ lmap.line.line_thickness = 0.8
652
+
653
+ plot.view.fit()
654
+
655
+ tp.export.save_png('view_polar.png', 600, supersample=3)
656
+
657
+ .. figure:: /_static/images/view_polar.png
658
+ :width: 300px
659
+ :figwidth: 300px
660
+ """
661
+ def __init__(self, plot):
662
+ super().__init__(plot, sv.POLARVIEW)
663
+
664
+ @property
665
+ def extents(self):
666
+ """`tuple`: Viewport extents in radial data units.
667
+
668
+ Extents are represented by the `tuple`: ``(x1, y1, x2, y2)`` and
669
+ setting this effectively zooms the view of the data within the
670
+ viewport. The values ``(x1, y1)`` and ``(x2, y2)`` are the lower-left
671
+ and upper-right edges respectively and are in radial (data) units. The
672
+ following example will set the bottom and left edges of the viewport to
673
+ the radial value of ``-3`` and the top and right edges to the radial
674
+ value of 5::
675
+
676
+ >>> plot.view.extents = -3, -3, 5, 5
677
+ """
678
+ return session.RectPosition(self, sv.EXTENTS)
679
+
680
+ @extents.setter
681
+ def extents(self, values):
682
+ session.RectPosition(self, sv.EXTENTS)[:] = values
683
+
684
+
685
+ @lock_attributes
686
+ class ReadOnlyViewport(session.Style):
687
+ def __init__(self, axes):
688
+ kw = dict(uniqueid=axes.plot.frame.uid)
689
+ super().__init__(*axes._sv, **kw)
690
+
691
+ @property
692
+ def bottom(self):
693
+ """`float` in percentage of frame height from the bottom of frame
694
+
695
+ Example usage::
696
+
697
+ >>> print(plot.axes.viewport.bottom)
698
+ 10.0
699
+ """
700
+ return self._get_style(float, sv.VIEWPORTPOSITION, sv.Y1)
701
+
702
+ @property
703
+ def left(self):
704
+ """`float` in percentage of frame width from the left of the frame.
705
+
706
+ Example usage::
707
+
708
+ >>> print(plot.axes.viewport.left)
709
+ 10.0
710
+ """
711
+ return self._get_style(float, sv.VIEWPORTPOSITION, sv.X1)
712
+
713
+ @property
714
+ def right(self):
715
+ """`float` in percentage of frame width from the left of the frame.
716
+
717
+ Example usage::
718
+
719
+ >>> print(plot.axes.viewport.right)
720
+ 90.0
721
+ """
722
+ return self._get_style(float, sv.VIEWPORTPOSITION, sv.X2)
723
+
724
+ @property
725
+ def top(self):
726
+ """`float` in percentage of frame height from the bottom of the frame.
727
+
728
+ Example usage::
729
+
730
+ >>> print(plot.axes.viewport.top)
731
+ 90.0
732
+ """
733
+ return self._get_style(float, sv.VIEWPORTPOSITION, sv.Y2)
734
+
735
+
736
+ class Viewport(ReadOnlyViewport):
737
+ bottom = ReadOnlyViewport.bottom
738
+ left = ReadOnlyViewport.left
739
+ right = ReadOnlyViewport.right
740
+ top = ReadOnlyViewport.top
741
+
742
+ @bottom.setter
743
+ def bottom(self, value):
744
+ self._set_style(float(value), sv.VIEWPORTPOSITION, sv.Y1)
745
+
746
+ @left.setter
747
+ def left(self, value):
748
+ self._set_style(float(value), sv.VIEWPORTPOSITION, sv.X1)
749
+
750
+ @right.setter
751
+ def right(self, value):
752
+ self._set_style(float(value), sv.VIEWPORTPOSITION, sv.X2)
753
+
754
+ @top.setter
755
+ def top(self, value):
756
+ self._set_style(float(value), sv.VIEWPORTPOSITION, sv.Y2)
757
+
758
+
759
+ class Cartesian2DViewport(Viewport):
760
+ @property
761
+ def nice_fit_buffer(self):
762
+ """`float`: Tolerance for viewport/frame fit niceness.
763
+
764
+ Example usage::
765
+
766
+ >>> plot.axes.viewport.nice_fit_buffer = 20
767
+ """
768
+ return self._get_style(float, sv.VIEWPORTNICEFITBUFFER)
769
+
770
+ @nice_fit_buffer.setter
771
+ def nice_fit_buffer(self, value):
772
+ self._set_style(float(value), sv.VIEWPORTNICEFITBUFFER)
773
+
774
+ @property
775
+ def top_snap_target(self):
776
+ """`float`: Target value for top when being adjusted or dragged.
777
+
778
+ Example usage::
779
+
780
+ >>> plot.axes.viewport.top_snap_target = 90
781
+ """
782
+ return self._get_style(float, sv.VIEWPORTTOPSNAPTARGET)
783
+
784
+ @top_snap_target.setter
785
+ def top_snap_target(self, value):
786
+ self._set_style(float(value), sv.VIEWPORTTOPSNAPTARGET)
787
+
788
+ @property
789
+ def top_snap_tolerance(self):
790
+ """`float`: Tolerance for snapping to target value for top.
791
+
792
+ Example usage::
793
+
794
+ >>> plot.axes.viewport.top_snap_tolerance = 8
795
+ """
796
+ return self._get_style(float, sv.VIEWPORTTOPSNAPTOLERANCE)
797
+
798
+ @top_snap_tolerance.setter
799
+ def top_snap_tolerance(self, value):
800
+ self._set_style(float(value), sv.VIEWPORTTOPSNAPTOLERANCE)
801
+
802
+
803
+ class PolarViewport(Viewport):
804
+ @property
805
+ def fill_color(self):
806
+ """`Color`: Background fill color of the entire viewport.
807
+
808
+ Example usage::
809
+
810
+ >>> from tecplot.constant import Color
811
+ >>> plot.axes.viewport.fill_color = Color.Blue
812
+ """
813
+ if self._get_style(bool, sv.VIEWPORTSTYLE, sv.ISFILLED):
814
+ return self._get_style(Color, sv.VIEWPORTSTYLE, sv.FILLCOLOR)
815
+
816
+ @fill_color.setter
817
+ def fill_color(self, value):
818
+ if value is None:
819
+ self._set_style(False, sv.VIEWPORTSTYLE, sv.ISFILLED)
820
+ else:
821
+ self._set_style(True, sv.VIEWPORTSTYLE, sv.ISFILLED)
822
+ self._set_style(Color(value), sv.VIEWPORTSTYLE, sv.FILLCOLOR)
823
+
824
+ @property
825
+ def show_border(self):
826
+ """`bool`: Draw a border line around the viewport.
827
+
828
+ Example usage::
829
+
830
+ >>> plot.axes.viewport.show_border = True
831
+ """
832
+ return self._get_style(bool, sv.VIEWPORTSTYLE, sv.DRAWBORDER)
833
+
834
+ @show_border.setter
835
+ def show_border(self, value):
836
+ self._set_style(bool(value), sv.VIEWPORTSTYLE, sv.DRAWBORDER)
837
+
838
+ @property
839
+ def border_thickness(self):
840
+ """`float`: Border line thickness around the viewport.
841
+
842
+ Example usage::
843
+
844
+ >>> plot.axes.viewport.show_border = True
845
+ >>> plot.axes.viewport.border_thickness = 0.8
846
+ """
847
+ return self._get_style(float, sv.VIEWPORTSTYLE, sv.LINETHICKNESS)
848
+
849
+ @border_thickness.setter
850
+ def border_thickness(self, value):
851
+ self._set_style(float(value), sv.VIEWPORTSTYLE, sv.LINETHICKNESS)
852
+
853
+ @property
854
+ def border_color(self):
855
+ """`Color`: Border line color around the viewport.
856
+
857
+ Example usage::
858
+
859
+ >>> from tecplot.constant import Color
860
+ >>> plot.axes.viewport.show_border = True
861
+ >>> plot.axes.viewport.border_thickness = 0.8
862
+ >>> plot.axes.viewport.border_color = Color.Red
863
+ """
864
+ return self._get_style(Color, sv.VIEWPORTSTYLE, sv.COLOR)
865
+
866
+ @border_color.setter
867
+ def border_color(self, value):
868
+ self._set_style(Color(value), sv.VIEWPORTSTYLE, sv.COLOR)