pytecplot 1.5.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pytecplot-1.5.2.dist-info/LICENSE.html +77 -0
- pytecplot-1.5.2.dist-info/METADATA +508 -0
- pytecplot-1.5.2.dist-info/RECORD +97 -0
- pytecplot-1.5.2.dist-info/WHEEL +5 -0
- pytecplot-1.5.2.dist-info/top_level.txt +1 -0
- tecplot/__init__.py +94 -0
- tecplot/annotation/__init__.py +7 -0
- tecplot/annotation/annotation.py +223 -0
- tecplot/annotation/geometry.py +369 -0
- tecplot/annotation/georeference.py +33 -0
- tecplot/annotation/image.py +185 -0
- tecplot/annotation/iter.py +105 -0
- tecplot/annotation/polyline.py +381 -0
- tecplot/annotation/text.py +744 -0
- tecplot/constant.py +401 -0
- tecplot/data/__init__.py +34 -0
- tecplot/data/array.py +645 -0
- tecplot/data/create.py +1 -0
- tecplot/data/dataset.py +1809 -0
- tecplot/data/extract.py +544 -0
- tecplot/data/face_neighbors.py +494 -0
- tecplot/data/facemap.py +814 -0
- tecplot/data/load.py +2075 -0
- tecplot/data/nodemap.py +577 -0
- tecplot/data/operate.py +928 -0
- tecplot/data/query.py +334 -0
- tecplot/data/save.py +343 -0
- tecplot/data/variable.py +280 -0
- tecplot/data/zone.py +841 -0
- tecplot/exception.py +201 -0
- tecplot/export/__init__.py +13 -0
- tecplot/export/animation.py +521 -0
- tecplot/export/export_setup.py +318 -0
- tecplot/export/image.py +577 -0
- tecplot/export/print_setup.py +218 -0
- tecplot/export/time_animation.py +607 -0
- tecplot/extension/__init__.py +14 -0
- tecplot/extension/ipython.py +68 -0
- tecplot/layout/__init__.py +20 -0
- tecplot/layout/frame.py +1285 -0
- tecplot/layout/layout.py +488 -0
- tecplot/layout/page.py +541 -0
- tecplot/legend/__init__.py +4 -0
- tecplot/legend/contour_legend.py +516 -0
- tecplot/legend/legend.py +141 -0
- tecplot/legend/line_legend.py +66 -0
- tecplot/legend/rgb_coloring_legend.py +291 -0
- tecplot/legend/scatter_legend.py +136 -0
- tecplot/macro.py +339 -0
- tecplot/plot/__init__.py +62 -0
- tecplot/plot/axes.py +881 -0
- tecplot/plot/axis.py +1350 -0
- tecplot/plot/blanking.py +584 -0
- tecplot/plot/contour.py +1302 -0
- tecplot/plot/effects.py +162 -0
- tecplot/plot/fieldmap.py +2159 -0
- tecplot/plot/grid.py +758 -0
- tecplot/plot/isosurface.py +1167 -0
- tecplot/plot/labels.py +338 -0
- tecplot/plot/linemap.py +1905 -0
- tecplot/plot/linking.py +489 -0
- tecplot/plot/plot.py +1791 -0
- tecplot/plot/rgb_coloring.py +281 -0
- tecplot/plot/scatter.py +396 -0
- tecplot/plot/slice.py +1544 -0
- tecplot/plot/streamtrace.py +1949 -0
- tecplot/plot/symbol.py +567 -0
- tecplot/plot/ticks.py +666 -0
- tecplot/plot/title.py +380 -0
- tecplot/plot/vector.py +679 -0
- tecplot/plot/view.py +868 -0
- tecplot/session/__init__.py +112 -0
- tecplot/session/aux_data.py +276 -0
- tecplot/session/config.py +92 -0
- tecplot/session/session.py +425 -0
- tecplot/session/state_changed.py +225 -0
- tecplot/session/style.py +504 -0
- tecplot/tecutil/__init__.py +16 -0
- tecplot/tecutil/arglist.py +230 -0
- tecplot/tecutil/captured_output.py +177 -0
- tecplot/tecutil/constant.py +1312 -0
- tecplot/tecutil/index_set.py +118 -0
- tecplot/tecutil/lock.py +36 -0
- tecplot/tecutil/message_pb2.py +39 -0
- tecplot/tecutil/preamble.py +54 -0
- tecplot/tecutil/stringlist.py +114 -0
- tecplot/tecutil/sv.py +1662 -0
- tecplot/tecutil/tecutil.py +12402 -0
- tecplot/tecutil/tecutil_client.py +627 -0
- tecplot/tecutil/tecutil_connector.py +937 -0
- tecplot/tecutil/tecutil_rpc.py +6845 -0
- tecplot/tecutil/util.py +332 -0
- tecplot/text/__init__.py +3 -0
- tecplot/text/font.py +224 -0
- tecplot/text/label_format.py +374 -0
- tecplot/text/textbox.py +106 -0
- tecplot/version.py +41 -0
tecplot/data/operate.py
ADDED
|
@@ -0,0 +1,928 @@
|
|
|
1
|
+
from collections.abc import Iterable
|
|
2
|
+
from contextlib import contextmanager
|
|
3
|
+
|
|
4
|
+
from ..tecutil import _tecutil
|
|
5
|
+
from ..constant import *
|
|
6
|
+
from ..exception import *
|
|
7
|
+
from .. import layout, tecutil
|
|
8
|
+
from ..tecutil import IndexSet, Index, flatten_args, sv, optional
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@tecutil.lock()
|
|
12
|
+
def execute_equation(equation, zones=None, i_range=None, j_range=None,
|
|
13
|
+
k_range=None, value_location=None, variable_data_type=None,
|
|
14
|
+
ignore_divide_by_zero=None):
|
|
15
|
+
"""The execute_equation function operates on a data set within the
|
|
16
|
+
|Tecplot Engine| using FORTRAN-like equations.
|
|
17
|
+
|
|
18
|
+
Parameters:
|
|
19
|
+
equation (`str`): String containing the equation.
|
|
20
|
+
Multiple equations can be processed by separating each equation
|
|
21
|
+
with a newline. See Section 20 - 1 "Data Alteration through
|
|
22
|
+
Equations" in the |Tecplot User's Manual| for more information on
|
|
23
|
+
using equations. Iterable container of `Zone <data_access>` objects
|
|
24
|
+
to operate on. May be a list, set, tuple, or any iterable
|
|
25
|
+
container. If `None`, the equation will be applied to all zones.
|
|
26
|
+
|
|
27
|
+
.. note:: In the equation string, variable names should be enclosed
|
|
28
|
+
in curly braces. For example, '{X} = {X} + 1'
|
|
29
|
+
|
|
30
|
+
zones: (Iterable container of `Zone <data_access>` objects, optional):
|
|
31
|
+
Iterable container of `Zone <data_access>` objects to operate on.
|
|
32
|
+
May be a list, set, tuple, or any iterable container. If `None`,
|
|
33
|
+
the equation will be applied to all zones.
|
|
34
|
+
i_range (`tuple` of `integers <int>`, optional):
|
|
35
|
+
Tuple of integers for I: (min, max, step). If `None`, then the
|
|
36
|
+
equation will operate on the entire range.
|
|
37
|
+
Not used for finite element nodal data.
|
|
38
|
+
j_range (`tuple` of `integers <int>`, optional):
|
|
39
|
+
Tuple of integers for J: (min, max, step). If `None`, then the
|
|
40
|
+
equation will operate on the entire range.
|
|
41
|
+
Not used for finite element nodal data.
|
|
42
|
+
k_range (`tuple` of `integers <int>`, optional):
|
|
43
|
+
Tuple of integers for K: (min, max, step). If `None`, then the
|
|
44
|
+
equation will operate on the entire range.
|
|
45
|
+
Not used for finite element nodal data.
|
|
46
|
+
value_location (`ValueLocation`, optional):
|
|
47
|
+
Variable `ValueLocation` for the variable on the left hand side.
|
|
48
|
+
This is used only if this variable is being created for the first
|
|
49
|
+
time.
|
|
50
|
+
If `None`, |Tecplot Engine| will choose the location for you.
|
|
51
|
+
variable_data_type (`FieldDataType`, optional):
|
|
52
|
+
Data type for the variable on the left hand side.
|
|
53
|
+
This is used only if this variable is being created for the first
|
|
54
|
+
time.
|
|
55
|
+
If `None`, |Tecplot Engine| will choose the type for you.
|
|
56
|
+
ignore_divide_by_zero (`bool`, optional):
|
|
57
|
+
`bool` value which instructs |Tecplot Engine| to ignore
|
|
58
|
+
divide by zero errors. The result is clamped
|
|
59
|
+
such that 0/0 is clamped to zero and (+/-N)/0
|
|
60
|
+
where N != 0 clamps to +/-maximum value for the given type.
|
|
61
|
+
|
|
62
|
+
.. warning:: Zero-based Indexing
|
|
63
|
+
|
|
64
|
+
It is important to know that all indexing in |PyTecplot| scripts are
|
|
65
|
+
zero-based. This is a departure from the macro language which is
|
|
66
|
+
one-based. This is to keep with the expectations when working in the
|
|
67
|
+
python language. However, |PyTecplot| does not modify strings that are
|
|
68
|
+
passed to the |Tecplot Engine|. This means that one-based indexing
|
|
69
|
+
should be used when running macro commands from python or when using
|
|
70
|
+
`execute_equation() <tecplot.data.operate.execute_equation>`.
|
|
71
|
+
|
|
72
|
+
Add one to variable 'X' for zones 'Rectangular' and 'Circular' for every
|
|
73
|
+
data point:
|
|
74
|
+
|
|
75
|
+
>>> dataset = tecplot.active_frame().dataset
|
|
76
|
+
>>> execute_equation('{X} = {X} + 1', zones=[dataset.zone('Rectangular'),
|
|
77
|
+
>>> dataset.zone('Circular')])
|
|
78
|
+
|
|
79
|
+
Create a new, double precision variable called DIST:
|
|
80
|
+
|
|
81
|
+
>>> execute_equation('{DIST} = SQRT({X}**2 + {Y}**2)',
|
|
82
|
+
... variable_data_type=FieldDataType.Double)
|
|
83
|
+
|
|
84
|
+
Set a variable called **P** to zero along the boundary of an IJ-ordered
|
|
85
|
+
zone:
|
|
86
|
+
|
|
87
|
+
>>> execute_equation('{P} = 0', i_range=(0, -1, 0), j_range=(0, -1, 0))
|
|
88
|
+
|
|
89
|
+
Using 1-based indexing in equations and 0-based indexing in parameters.
|
|
90
|
+
Zone 4 is subtracted from zone 3 and the result is placed in zone 2:
|
|
91
|
+
|
|
92
|
+
>>> execute_equation('{T} = {T}[3]-{T}[4]', zones=[ds.zone(1)])
|
|
93
|
+
"""
|
|
94
|
+
if __debug__:
|
|
95
|
+
if not isinstance(equation, str):
|
|
96
|
+
raise TecplotTypeError('Equation must be a string')
|
|
97
|
+
elif len(equation) == 0:
|
|
98
|
+
raise TecplotValueError('Equation can not be empty')
|
|
99
|
+
if not isinstance(value_location, (ValueLocation, type(None))):
|
|
100
|
+
msg = 'value_location must be a ValueLocation'
|
|
101
|
+
raise TecplotTypeError(msg)
|
|
102
|
+
if not isinstance(variable_data_type, (FieldDataType, type(None))):
|
|
103
|
+
msg = 'variable_data_type must be a FieldDataType'
|
|
104
|
+
raise TecplotTypeError(msg)
|
|
105
|
+
if not isinstance(ignore_divide_by_zero, (bool, type(None))):
|
|
106
|
+
raise TecplotTypeError('ignore_divide_by_zero must be a bool')
|
|
107
|
+
|
|
108
|
+
# Check that all zones belong to the active dataset
|
|
109
|
+
# (which is currently the only dataset option available)
|
|
110
|
+
if zones:
|
|
111
|
+
def dataset_uid(zone):
|
|
112
|
+
'''return the dataset uid if zone is a Zone object.'''
|
|
113
|
+
try:
|
|
114
|
+
return zone.dataset.uid
|
|
115
|
+
except AttributeError:
|
|
116
|
+
return None
|
|
117
|
+
|
|
118
|
+
if isinstance(zones, Iterable):
|
|
119
|
+
# converting generator to list to allow
|
|
120
|
+
# iterating over it more than once
|
|
121
|
+
zones = list(zones)
|
|
122
|
+
parent_ids = map(dataset_uid, zones)
|
|
123
|
+
else:
|
|
124
|
+
parent_ids = {dataset_uid(zones)}
|
|
125
|
+
parent_ids = set(filter(None, parent_ids))
|
|
126
|
+
|
|
127
|
+
active_id = layout.active_frame().dataset.uid
|
|
128
|
+
if parent_ids and parent_ids != {active_id}:
|
|
129
|
+
msg = 'All zones must have the same parent dataset'
|
|
130
|
+
raise TecplotValueError(msg)
|
|
131
|
+
|
|
132
|
+
with tecutil.ArgList() as arglist:
|
|
133
|
+
arglist[sv.EQUATION] = equation
|
|
134
|
+
with optional(IndexSet, zones) as zoneset:
|
|
135
|
+
arglist[sv.ZONESET] = zoneset
|
|
136
|
+
|
|
137
|
+
for dim, rng in zip(['I', 'J', 'K'], [i_range, j_range, k_range]):
|
|
138
|
+
if rng is not None:
|
|
139
|
+
rng = tecutil.IndexRange(*rng)
|
|
140
|
+
if rng.min is not None:
|
|
141
|
+
arglist[dim + 'MIN'] = Index(rng.min)
|
|
142
|
+
if rng.max is not None:
|
|
143
|
+
arglist[dim + 'MAX'] = Index(rng.max)
|
|
144
|
+
if rng.step is not None:
|
|
145
|
+
step = int(rng.step)
|
|
146
|
+
if step > 0:
|
|
147
|
+
arglist[dim + 'SKIP'] = step
|
|
148
|
+
elif step < 0:
|
|
149
|
+
msg = 'Negative step not supported.'
|
|
150
|
+
raise TecplotLogicError(msg)
|
|
151
|
+
|
|
152
|
+
arglist[sv.VALUELOCATION] = value_location
|
|
153
|
+
arglist[sv.VARDATATYPE] = variable_data_type
|
|
154
|
+
arglist[sv.IGNOREDIVIDEBYZERO] = ignore_divide_by_zero
|
|
155
|
+
|
|
156
|
+
if not _tecutil.DataAlterX(arglist):
|
|
157
|
+
raise TecplotSystemError()
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@contextmanager
|
|
161
|
+
def _interpolate_process_args(dest_zone, src_zones, variables, plot):
|
|
162
|
+
if plot is None:
|
|
163
|
+
plot = layout.active_frame().plot()
|
|
164
|
+
if isinstance(dest_zone, int):
|
|
165
|
+
dest_zone = plot.frame.dataset.zone(dest_zone)
|
|
166
|
+
if not isinstance(src_zones, (Iterable, type(None))):
|
|
167
|
+
src_zones = [src_zones]
|
|
168
|
+
if not isinstance(variables, (Iterable, type(None))):
|
|
169
|
+
variables = [variables]
|
|
170
|
+
|
|
171
|
+
if __debug__:
|
|
172
|
+
if plot.frame.dataset != dest_zone.dataset:
|
|
173
|
+
msg = 'Plot and destination zone do not share the same dataset.'
|
|
174
|
+
raise TecplotLogicError(msg)
|
|
175
|
+
if src_zones is not None:
|
|
176
|
+
def is_invalid_zone(z):
|
|
177
|
+
if isinstance(z, int):
|
|
178
|
+
return z >= plot.frame.dataset.num_zones
|
|
179
|
+
else:
|
|
180
|
+
return plot.frame.dataset != z.dataset
|
|
181
|
+
if any(map(is_invalid_zone, src_zones)):
|
|
182
|
+
msg = 'Source zones are not part of the same dataset.'
|
|
183
|
+
raise TecplotLogicError(msg)
|
|
184
|
+
if variables is not None:
|
|
185
|
+
def is_invalid_variable(v):
|
|
186
|
+
if isinstance(v, int):
|
|
187
|
+
return v >= plot.frame.dataset.num_variables
|
|
188
|
+
else:
|
|
189
|
+
return plot.frame.dataset != v.dataset
|
|
190
|
+
if any(map(is_invalid_variable, variables)):
|
|
191
|
+
msg = 'Variables are not part of the same dataset.'
|
|
192
|
+
raise TecplotLogicError(msg)
|
|
193
|
+
|
|
194
|
+
with plot.activated():
|
|
195
|
+
with optional(IndexSet, src_zones) as src:
|
|
196
|
+
with optional(IndexSet, variables) as varset:
|
|
197
|
+
dest = dest_zone.index + 1
|
|
198
|
+
yield src, dest, varset
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
@tecutil.lock()
|
|
202
|
+
def interpolate_linear(destination_zone, source_zones=None, variables=None,
|
|
203
|
+
fill_value=None, plot=None):
|
|
204
|
+
"""Linear interpolation onto a destination zone.
|
|
205
|
+
|
|
206
|
+
Parameters:
|
|
207
|
+
destination_zone (`zone <data_access>` or `int`): The
|
|
208
|
+
destination zone (or zone index) for interpolation.
|
|
209
|
+
source_zones (`zones <data_access>` or `integers <int>`, optional):
|
|
210
|
+
Zones (or zone indices) used to obtain the field values for
|
|
211
|
+
interpolation. By default, all zones except the *destination_zone*
|
|
212
|
+
will be used. All source zones must be FE-Tetra, FE-Brick or be
|
|
213
|
+
IJK-ordered when doing linear interpolation in 3D.
|
|
214
|
+
variables (`variables <Variable>` or `integers <int>`, optional):
|
|
215
|
+
Variables (or variable indices) to interpolate. By default, all
|
|
216
|
+
variables except those assigned to the axes will be used and is in
|
|
217
|
+
general dependent on the active plot type of the frame.
|
|
218
|
+
fill_value (`float`, optional): Constant value to which all points
|
|
219
|
+
outside the data field are set. By default, the values outside
|
|
220
|
+
the field are preserved.
|
|
221
|
+
plot (:ref:`plot`, optional): The plot to use when interpolating which
|
|
222
|
+
determines the dimensionality and spatial variables. By default,
|
|
223
|
+
the active plot on the active frame will be used.
|
|
224
|
+
|
|
225
|
+
.. note:: Cartesian 2D and 3D plots only.
|
|
226
|
+
|
|
227
|
+
This interpolation method relies on the coordinates, :math:`(x, y)` for
|
|
228
|
+
2D or :math:`(x, y, z)` for 3D, set for the active (or given) plot
|
|
229
|
+
which must be either Cartesian2D or Cartesian3D.
|
|
230
|
+
|
|
231
|
+
The following example loads a 2D dataset and uses interpolation to merge
|
|
232
|
+
information from two independent zones:
|
|
233
|
+
|
|
234
|
+
.. code-block:: python
|
|
235
|
+
|
|
236
|
+
import os
|
|
237
|
+
import numpy as np
|
|
238
|
+
import tecplot as tp
|
|
239
|
+
from tecplot.constant import *
|
|
240
|
+
|
|
241
|
+
# Use interpolation to merge information from two independent zones
|
|
242
|
+
examples_dir = tp.session.tecplot_examples_directory()
|
|
243
|
+
datafile = os.path.join(examples_dir, 'SimpleData', 'RainierElevation.plt')
|
|
244
|
+
dataset = tp.data.load_tecplot(datafile)
|
|
245
|
+
# Get list of source zones to use later
|
|
246
|
+
srczones = list(dataset.zones())
|
|
247
|
+
|
|
248
|
+
fr = tp.active_frame()
|
|
249
|
+
plot = fr.plot(PlotType.Cartesian2D)
|
|
250
|
+
plot.activate()
|
|
251
|
+
plot.show_contour = True
|
|
252
|
+
plot.show_edge = True
|
|
253
|
+
|
|
254
|
+
# Show two section of the plot independently
|
|
255
|
+
plot.contour(0).legend.show = False
|
|
256
|
+
plot.contour(1).legend.show = False
|
|
257
|
+
plot.contour(1).colormap_name = 'Diverging - Blue/Red'
|
|
258
|
+
for scrzone in srczones:
|
|
259
|
+
plot.fieldmap(scrzone).edge.line_thickness = 0.4
|
|
260
|
+
plot.fieldmap(0).contour.flood_contour_group = plot.contour(1)
|
|
261
|
+
|
|
262
|
+
# export image of original data
|
|
263
|
+
tp.export.save_png('interpolate_2d_source.png', 600, supersample=3)
|
|
264
|
+
|
|
265
|
+
# use the first zone as the source, and get the range of (x, y)
|
|
266
|
+
xvar = plot.axes.x_axis.variable
|
|
267
|
+
yvar = plot.axes.y_axis.variable
|
|
268
|
+
ymin, xmin = 99999,99999
|
|
269
|
+
ymax, xmax = -99999,-99999
|
|
270
|
+
for scrzone in srczones:
|
|
271
|
+
curxmin, curxmax = scrzone.values(xvar.index).minmax()
|
|
272
|
+
curymin, curymax = scrzone.values(yvar.index).minmax()
|
|
273
|
+
ymin = min(curymin,ymin)
|
|
274
|
+
ymax = max(curymax,ymax)
|
|
275
|
+
xmin = min(curxmin,xmin)
|
|
276
|
+
xmax = max(curxmax,xmax)
|
|
277
|
+
|
|
278
|
+
# create new zone with a coarse grid
|
|
279
|
+
# onto which we will interpolate from the source zone
|
|
280
|
+
xpoints = 40
|
|
281
|
+
ypoints = 40
|
|
282
|
+
newzone = dataset.add_ordered_zone('Interpolated', (xpoints, ypoints))
|
|
283
|
+
|
|
284
|
+
# setup the (x, y) positions of the new grid
|
|
285
|
+
xx = np.linspace(xmin, xmax, xpoints)
|
|
286
|
+
yy = np.linspace(ymin, ymax, ypoints)
|
|
287
|
+
YY, XX = np.meshgrid(yy, xx, indexing='ij')
|
|
288
|
+
newzone.values(xvar.index)[:] = XX.ravel()
|
|
289
|
+
newzone.values(yvar.index)[:] = YY.ravel()
|
|
290
|
+
|
|
291
|
+
# perform linear interpolation from the source to the new zone
|
|
292
|
+
tp.data.operate.interpolate_linear(newzone, source_zones=srczones)
|
|
293
|
+
|
|
294
|
+
# show the new zone's data, hide the source
|
|
295
|
+
plot.fieldmap(newzone).show = True
|
|
296
|
+
plot.fieldmap(newzone).contour.show = True
|
|
297
|
+
plot.fieldmap(newzone).contour.flood_contour_group = plot.contour(0)
|
|
298
|
+
plot.fieldmap(newzone).edge.show = True
|
|
299
|
+
plot.fieldmap(newzone).edge.line_thickness = .4
|
|
300
|
+
plot.fieldmap(newzone).edge.color = Color.Orange
|
|
301
|
+
|
|
302
|
+
for scrzone in srczones:
|
|
303
|
+
plot.fieldmap(scrzone).show = False
|
|
304
|
+
|
|
305
|
+
# export image of interpolated data
|
|
306
|
+
tp.export.save_png('interpolate_linear_2d_dest.png', 600, supersample=3)
|
|
307
|
+
|
|
308
|
+
.. figure:: /_static/images/interpolate_2d_source.png
|
|
309
|
+
:width: 300px
|
|
310
|
+
:figwidth: 300px
|
|
311
|
+
|
|
312
|
+
Source data.
|
|
313
|
+
|
|
314
|
+
.. figure:: /_static/images/interpolate_linear_2d_dest.png
|
|
315
|
+
:width: 300px
|
|
316
|
+
:figwidth: 300px
|
|
317
|
+
|
|
318
|
+
Interpolated data.
|
|
319
|
+
|
|
320
|
+
"""
|
|
321
|
+
with _interpolate_process_args(destination_zone, source_zones, variables,
|
|
322
|
+
plot) as (src, dest, varset):
|
|
323
|
+
if fill_value is None:
|
|
324
|
+
interp_const = 0.0
|
|
325
|
+
interp_mode = LinearInterpMode.DontChange
|
|
326
|
+
else:
|
|
327
|
+
interp_const = float(fill_value)
|
|
328
|
+
interp_mode = LinearInterpMode.SetToConst
|
|
329
|
+
if not _tecutil.LinearInterpolate(src, dest, varset, interp_const,
|
|
330
|
+
interp_mode.value):
|
|
331
|
+
raise TecplotSystemError()
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
@tecutil.lock()
|
|
335
|
+
def interpolate_kriging(destination_zone, source_zones=None, variables=None,
|
|
336
|
+
krig_range=0.3, zero_value=0.0, drift=Drift.Linear,
|
|
337
|
+
point_selection=PtSelection.OctantN, num_points=8,
|
|
338
|
+
plot=None):
|
|
339
|
+
"""Kriging interpolation onto a destination zone.
|
|
340
|
+
|
|
341
|
+
Parameters:
|
|
342
|
+
destination_zone (`zone <data_access>` or `int`): The
|
|
343
|
+
destination zone (or zone index) for interpolation.
|
|
344
|
+
source_zones (`zones <data_access>` or `integers <int>`, optional):
|
|
345
|
+
Zones (or zone indices) used to obtain the field values for
|
|
346
|
+
interpolation. By default, all zones except the *destination_zone*
|
|
347
|
+
will be used. All source zones must be FE-Tetra, FE-Brick or
|
|
348
|
+
IJK-ordered when doing kriging interpolation in 3D.
|
|
349
|
+
variables (`variables <Variable>` or `integers <int>`, optional):
|
|
350
|
+
Variables (or variable indices) to interpolate. By default, all
|
|
351
|
+
variables except those assigned to the axes will be used and is in
|
|
352
|
+
general dependent on the active plot type of the frame.
|
|
353
|
+
krig_range (`float`, optional): Distance beyond which source points
|
|
354
|
+
become insignificant. Must be between zero and one, inclusive.
|
|
355
|
+
(default: 0.3)
|
|
356
|
+
zero_value (`float`, optional): Semi-variance at each source data point
|
|
357
|
+
on a normalized scale from zero to one. (default: 0.0)
|
|
358
|
+
drift (`Drift`, optional): Overall trend for the data. Possible values:
|
|
359
|
+
`Drift.None_` no trend, `Drift.Linear` (default) linear trend,
|
|
360
|
+
`Drift.Quad` quadratic trend.
|
|
361
|
+
point_selection (`PtSelection`, optional): Method for determining which
|
|
362
|
+
source points to consider for each destination data point. Possible
|
|
363
|
+
values: `PtSelection.OctantN` (default) closest *num_points*
|
|
364
|
+
selected by coordinate-system octants, `PtSelection.NearestN`
|
|
365
|
+
closest *num_points* to the destination point, `PtSelection.All`
|
|
366
|
+
all points in the source zone.
|
|
367
|
+
num_points (`int`, optional): Number of source points to
|
|
368
|
+
consider for each destination data point if *point_selection* is
|
|
369
|
+
`PtSelection.OctantN` or `PtSelection.NearestN`. (default: 8)
|
|
370
|
+
plot (:ref:`plot`, optional): The plot to use when interpolating which
|
|
371
|
+
determines the dimensionality and spatial variables. By default,
|
|
372
|
+
the active plot on the active frame will be used.
|
|
373
|
+
|
|
374
|
+
.. note:: Cartesian 2D and 3D plots only.
|
|
375
|
+
|
|
376
|
+
This interpolation method relies on the coordinates, :math:`(x, y)` for
|
|
377
|
+
2D or :math:`(x, y, z)` for 3D, set for the active (or given) plot
|
|
378
|
+
which must be either Cartesian2D or Cartesian3D.
|
|
379
|
+
|
|
380
|
+
The following example loads a 2D dataset and interpolates the first zone to
|
|
381
|
+
a new one with a larger grid spacing:
|
|
382
|
+
|
|
383
|
+
.. code-block:: python
|
|
384
|
+
:emphasize-lines: 58-59
|
|
385
|
+
|
|
386
|
+
import os
|
|
387
|
+
import numpy as np
|
|
388
|
+
import tecplot as tp
|
|
389
|
+
from tecplot.constant import *
|
|
390
|
+
|
|
391
|
+
# Use interpolation to merge information from two independent zones
|
|
392
|
+
examples_dir = tp.session.tecplot_examples_directory()
|
|
393
|
+
datafile = os.path.join(examples_dir, 'SimpleData',
|
|
394
|
+
'RainierElevation.plt')
|
|
395
|
+
dataset = tp.data.load_tecplot(datafile)
|
|
396
|
+
# Get list of source zones to use later
|
|
397
|
+
srczones = list(dataset.zones())
|
|
398
|
+
|
|
399
|
+
fr = tp.active_frame()
|
|
400
|
+
plot = fr.plot(PlotType.Cartesian2D)
|
|
401
|
+
plot.activate()
|
|
402
|
+
plot.show_contour = True
|
|
403
|
+
plot.show_edge = True
|
|
404
|
+
|
|
405
|
+
# Show two section of the plot independently
|
|
406
|
+
plot.contour(0).legend.show = False
|
|
407
|
+
plot.contour(1).legend.show = False
|
|
408
|
+
plot.contour(1).colormap_name = 'Diverging - Blue/Red'
|
|
409
|
+
for scrzone in srczones:
|
|
410
|
+
plot.fieldmap(scrzone).edge.line_thickness = 0.4
|
|
411
|
+
plot.fieldmap(0).contour.flood_contour_group = plot.contour(1)
|
|
412
|
+
|
|
413
|
+
# export image of original data
|
|
414
|
+
tp.export.save_png('interpolate_2d_source.png', 600, supersample=3)
|
|
415
|
+
|
|
416
|
+
# use the first zone as the source, and get the range of (x, y)
|
|
417
|
+
xvar = plot.axes.x_axis.variable
|
|
418
|
+
yvar = plot.axes.y_axis.variable
|
|
419
|
+
ymin, xmin = 99999,99999
|
|
420
|
+
ymax, xmax = -99999,-99999
|
|
421
|
+
for scrzone in srczones:
|
|
422
|
+
curxmin, curxmax = scrzone.values(xvar.index).minmax()
|
|
423
|
+
curymin, curymax = scrzone.values(yvar.index).minmax()
|
|
424
|
+
ymin = min(curymin,ymin)
|
|
425
|
+
ymax = max(curymax,ymax)
|
|
426
|
+
xmin = min(curxmin,xmin)
|
|
427
|
+
xmax = max(curxmax,xmax)
|
|
428
|
+
|
|
429
|
+
# create new zone with a coarse grid
|
|
430
|
+
# onto which we will interpolate from the source zone
|
|
431
|
+
xpoints = 20
|
|
432
|
+
ypoints = 20
|
|
433
|
+
newzone = dataset.add_ordered_zone('Interpolated', (xpoints, ypoints))
|
|
434
|
+
|
|
435
|
+
# setup the (x, y) positions of the new grid
|
|
436
|
+
xx = np.linspace(xmin, xmax, xpoints)
|
|
437
|
+
yy = np.linspace(ymin, ymax, ypoints)
|
|
438
|
+
YY, XX = np.meshgrid(yy, xx, indexing='ij')
|
|
439
|
+
newzone.values(xvar.index)[:] = XX.ravel()
|
|
440
|
+
newzone.values(yvar.index)[:] = YY.ravel()
|
|
441
|
+
|
|
442
|
+
# perform linear interpolation from the source to the new zone
|
|
443
|
+
tp.data.operate.interpolate_kriging(newzone, source_zones=srczones,
|
|
444
|
+
drift=Drift.None_, num_points=1)
|
|
445
|
+
|
|
446
|
+
# show the new zone's data, hide the source
|
|
447
|
+
plot.fieldmap(newzone).show = True
|
|
448
|
+
plot.fieldmap(newzone).contour.show = True
|
|
449
|
+
plot.fieldmap(newzone).contour.flood_contour_group = plot.contour(0)
|
|
450
|
+
plot.fieldmap(newzone).edge.show = True
|
|
451
|
+
plot.fieldmap(newzone).edge.line_thickness = .4
|
|
452
|
+
plot.fieldmap(newzone).edge.color = Color.Orange
|
|
453
|
+
|
|
454
|
+
for scrzone in srczones:
|
|
455
|
+
plot.fieldmap(scrzone).show = False
|
|
456
|
+
|
|
457
|
+
# export image of interpolated data
|
|
458
|
+
tp.export.save_png('interpolate_krig_2d_dest.png', 600, supersample=3)
|
|
459
|
+
|
|
460
|
+
.. figure:: /_static/images/interpolate_2d_source.png
|
|
461
|
+
:width: 300px
|
|
462
|
+
:figwidth: 300px
|
|
463
|
+
|
|
464
|
+
Source data.
|
|
465
|
+
|
|
466
|
+
.. figure:: /_static/images/interpolate_krig_2d_dest.png
|
|
467
|
+
:width: 300px
|
|
468
|
+
:figwidth: 300px
|
|
469
|
+
|
|
470
|
+
Interpolated data.
|
|
471
|
+
"""
|
|
472
|
+
with _interpolate_process_args(destination_zone, source_zones, variables,
|
|
473
|
+
plot) as (src, dest, varset):
|
|
474
|
+
if not _tecutil.Krig(
|
|
475
|
+
src, dest, varset, krig_range, zero_value, Drift(drift).value,
|
|
476
|
+
PtSelection(point_selection).value, num_points):
|
|
477
|
+
raise TecplotSystemError()
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
@tecutil.lock()
|
|
481
|
+
def interpolate_inverse_distance(destination_zone, source_zones=None,
|
|
482
|
+
variables=None, exponent=3.5, min_radius=0.0,
|
|
483
|
+
point_selection=PtSelection.OctantN,
|
|
484
|
+
num_points=8, plot=None):
|
|
485
|
+
"""Inverse-Distance interpolation onto a destination zone.
|
|
486
|
+
|
|
487
|
+
Parameters:
|
|
488
|
+
destination_zone (`zone <data_access>` or `int`): The
|
|
489
|
+
destination zone (or zone index) for interpolation.
|
|
490
|
+
source_zones (`zones <data_access>` or `integers <int>`, optional):
|
|
491
|
+
Zones (or zone indices) used to obtain the field values for
|
|
492
|
+
interpolation. By default, all zones except the *destination_zone*
|
|
493
|
+
will be used. All source zones must be FE-Tetra, FE-Brick or be
|
|
494
|
+
IJK-ordered when doing linear interpolation in 3D.
|
|
495
|
+
variables (`variables <Variable>` or `integers <int>`, optional):
|
|
496
|
+
Variables (or variable indices) to interpolate. By default, all
|
|
497
|
+
variables except those assigned to the axes will be used and is in
|
|
498
|
+
general dependent on the active plot type of the frame.
|
|
499
|
+
exponent (`float`, optional): Exponent for the inverse-distance
|
|
500
|
+
weighting. (default: 3.5)
|
|
501
|
+
min_radius (`float`, optional): Minimum distance used for the
|
|
502
|
+
inverse-distance weighting. (default: 0.0)
|
|
503
|
+
point_selection (`PtSelection`, optional): Method for determining which
|
|
504
|
+
source points to consider for each destination data point. Possible
|
|
505
|
+
values: `PtSelection.OctantN` (default) closest *num_points*
|
|
506
|
+
selected by coordinate-system octants, `PtSelection.NearestN`
|
|
507
|
+
closest *num_points* to the destination point, `PtSelection.All`
|
|
508
|
+
all points in the source zone.
|
|
509
|
+
num_points (`int`, optional): Number of source points to
|
|
510
|
+
consider for each destination data point if *point_selection* is
|
|
511
|
+
`PtSelection.OctantN` or `PtSelection.NearestN`. (default: 8)
|
|
512
|
+
plot (:ref:`plot`, optional): The plot to use when interpolating which
|
|
513
|
+
determines the dimensionality and spatial variables. By default,
|
|
514
|
+
the active plot on the active frame will be used.
|
|
515
|
+
|
|
516
|
+
.. note:: Cartesian 2D and 3D plots only.
|
|
517
|
+
|
|
518
|
+
This interpolation method relies on the coordinates, :math:`(x, y)` for
|
|
519
|
+
2D or :math:`(x, y, z)` for 3D, set for the active (or given) plot
|
|
520
|
+
which must be either Cartesian2D or Cartesian3D.
|
|
521
|
+
|
|
522
|
+
The following example loads a 2D dataset and interpolates the first zone to
|
|
523
|
+
a new one with a larger grid spacing:
|
|
524
|
+
|
|
525
|
+
.. code-block:: python
|
|
526
|
+
:emphasize-lines: 57
|
|
527
|
+
|
|
528
|
+
import os
|
|
529
|
+
import numpy as np
|
|
530
|
+
import tecplot as tp
|
|
531
|
+
from tecplot.constant import *
|
|
532
|
+
|
|
533
|
+
# Use interpolation to merge information from two independent zones
|
|
534
|
+
examples_dir = tp.session.tecplot_examples_directory()
|
|
535
|
+
datafile = os.path.join(examples_dir, 'SimpleData', 'RainierElevation.plt')
|
|
536
|
+
dataset = tp.data.load_tecplot(datafile)
|
|
537
|
+
# Get list of source zones to use later
|
|
538
|
+
srczones = list(dataset.zones())
|
|
539
|
+
|
|
540
|
+
fr = tp.active_frame()
|
|
541
|
+
plot = fr.plot(PlotType.Cartesian2D)
|
|
542
|
+
plot.activate()
|
|
543
|
+
plot.show_contour = True
|
|
544
|
+
plot.show_edge = True
|
|
545
|
+
|
|
546
|
+
# Show two section of the plot independently
|
|
547
|
+
plot.contour(0).legend.show = False
|
|
548
|
+
plot.contour(1).legend.show = False
|
|
549
|
+
plot.contour(1).colormap_name = 'Diverging - Blue/Red'
|
|
550
|
+
for scrzone in srczones:
|
|
551
|
+
plot.fieldmap(scrzone).edge.line_thickness = 0.4
|
|
552
|
+
plot.fieldmap(0).contour.flood_contour_group = plot.contour(1)
|
|
553
|
+
|
|
554
|
+
# export image of original data
|
|
555
|
+
tp.export.save_png('interpolate_2d_source.png', 600, supersample=3)
|
|
556
|
+
|
|
557
|
+
# use the first zone as the source, and get the range of (x, y)
|
|
558
|
+
xvar = plot.axes.x_axis.variable
|
|
559
|
+
yvar = plot.axes.y_axis.variable
|
|
560
|
+
ymin, xmin = 99999,99999
|
|
561
|
+
ymax, xmax = -99999,-99999
|
|
562
|
+
for scrzone in srczones:
|
|
563
|
+
curxmin, curxmax = scrzone.values(xvar.index).minmax()
|
|
564
|
+
curymin, curymax = scrzone.values(yvar.index).minmax()
|
|
565
|
+
ymin = min(curymin,ymin)
|
|
566
|
+
ymax = max(curymax,ymax)
|
|
567
|
+
xmin = min(curxmin,xmin)
|
|
568
|
+
xmax = max(curxmax,xmax)
|
|
569
|
+
|
|
570
|
+
# create new zone with a coarse grid
|
|
571
|
+
# onto which we will interpolate from the source zone
|
|
572
|
+
xpoints = 40
|
|
573
|
+
ypoints = 40
|
|
574
|
+
newzone = dataset.add_ordered_zone('Interpolated', (xpoints, ypoints))
|
|
575
|
+
|
|
576
|
+
# setup the (x, y) positions of the new grid
|
|
577
|
+
xx = np.linspace(xmin, xmax, xpoints)
|
|
578
|
+
yy = np.linspace(ymin, ymax, ypoints)
|
|
579
|
+
YY, XX = np.meshgrid(yy, xx, indexing='ij')
|
|
580
|
+
newzone.values(xvar.index)[:] = XX.ravel()
|
|
581
|
+
newzone.values(yvar.index)[:] = YY.ravel()
|
|
582
|
+
|
|
583
|
+
# perform linear interpolation from the source to the new zone
|
|
584
|
+
tp.data.operate.interpolate_inverse_distance(newzone, source_zones=srczones)
|
|
585
|
+
|
|
586
|
+
# show the new zone's data, hide the source
|
|
587
|
+
plot.fieldmap(newzone).show = True
|
|
588
|
+
plot.fieldmap(newzone).contour.show = True
|
|
589
|
+
plot.fieldmap(newzone).contour.flood_contour_group = plot.contour(0)
|
|
590
|
+
plot.fieldmap(newzone).edge.show = True
|
|
591
|
+
plot.fieldmap(newzone).edge.line_thickness = .4
|
|
592
|
+
plot.fieldmap(newzone).edge.color = Color.Orange
|
|
593
|
+
|
|
594
|
+
for scrzone in srczones:
|
|
595
|
+
plot.fieldmap(scrzone).show = False
|
|
596
|
+
|
|
597
|
+
# export image of interpolated data
|
|
598
|
+
tp.export.save_png('interpolate_invdst_2d_dest.png', 600, supersample=3)
|
|
599
|
+
|
|
600
|
+
.. figure:: /_static/images/interpolate_2d_source.png
|
|
601
|
+
:width: 300px
|
|
602
|
+
:figwidth: 300px
|
|
603
|
+
|
|
604
|
+
Source data.
|
|
605
|
+
|
|
606
|
+
.. figure:: /_static/images/interpolate_invdst_2d_dest.png
|
|
607
|
+
:width: 300px
|
|
608
|
+
:figwidth: 300px
|
|
609
|
+
|
|
610
|
+
Interpolated data.
|
|
611
|
+
"""
|
|
612
|
+
with _interpolate_process_args(destination_zone, source_zones, variables,
|
|
613
|
+
plot) as (src, dest, varset):
|
|
614
|
+
if not _tecutil.InverseDistInterpolation(
|
|
615
|
+
src, dest, varset, exponent, min_radius,
|
|
616
|
+
PtSelection(point_selection).value, num_points):
|
|
617
|
+
raise TecplotSystemError()
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
@tecutil.lock()
|
|
621
|
+
def smooth(array, num_passes=1, weight=0.8,
|
|
622
|
+
boundary_condition=BoundaryCondition.Fixed, frame=None):
|
|
623
|
+
"""Smooth a field data `Array` in the dataset.
|
|
624
|
+
|
|
625
|
+
Parameters:
|
|
626
|
+
array (`Array`): The field data to smooth.
|
|
627
|
+
num_passes (`int`, optional): The number of smoothing passes to
|
|
628
|
+
perform. (default: 1)
|
|
629
|
+
weight (`float`, optional): The relaxation factor for each pass of
|
|
630
|
+
smoothing. Must be a number between zero and one exclusively.
|
|
631
|
+
Higher numbers indicate a greater smoothing effect. (default: 0.8)
|
|
632
|
+
boundary_condition (`BoundaryCondition`, optional): The boundary
|
|
633
|
+
condition by which to smooth. Possible values are
|
|
634
|
+
`BoundaryCondition.Fixed` (default),
|
|
635
|
+
`BoundaryCondition.ZeroGradient` and `BoundaryCondition.Zero2nd`.
|
|
636
|
+
frame (`Frame <layout.Frame>`, optional): The `Frame <layout.Frame>` that specifies the spatial
|
|
637
|
+
variables to smooth over via the active plot. By default, the frame
|
|
638
|
+
associated with the input `Array` object will be used.
|
|
639
|
+
|
|
640
|
+
The data will be smoothed over the spatial variables set by the plot and is
|
|
641
|
+
dependent on the active plot type of the associated `Frame <layout.Frame>` (`Cartesian2D`
|
|
642
|
+
or `Cartesian3D`). Example usage::
|
|
643
|
+
|
|
644
|
+
>>> tp.data.operate.smooth(dataset.zone('Zone').values('Pressure'))
|
|
645
|
+
"""
|
|
646
|
+
frame = frame or array.zone.dataset.frame
|
|
647
|
+
with frame.activated():
|
|
648
|
+
if not _tecutil.Smooth(array.zone.index + 1, array.variable.index + 1,
|
|
649
|
+
int(num_passes), float(weight),
|
|
650
|
+
BoundaryCondition(boundary_condition).value):
|
|
651
|
+
raise TecplotSystemError()
|
|
652
|
+
|
|
653
|
+
|
|
654
|
+
def _dataset(*objlists):
|
|
655
|
+
for objs in objlists:
|
|
656
|
+
if objs:
|
|
657
|
+
for obj in objs:
|
|
658
|
+
if obj and hasattr(obj, 'dataset'):
|
|
659
|
+
return obj.dataset
|
|
660
|
+
return layout.active_frame().dataset
|
|
661
|
+
|
|
662
|
+
|
|
663
|
+
@tecutil.lock()
|
|
664
|
+
def transform_polar_to_rectangular(r, theta, x=None, y=None,
|
|
665
|
+
angle_units=AngleUnits.Radians, zones=None):
|
|
666
|
+
"""Transform all points from polar to rectangular coordinates.
|
|
667
|
+
|
|
668
|
+
Parameters:
|
|
669
|
+
r (`Variable`): The radial input variable.
|
|
670
|
+
theta (`Variable`): The angular input variable in **angle_units** from
|
|
671
|
+
the :math:`x`-axis.
|
|
672
|
+
x (`Variable`, optional): The rectangular output :math:`x` variable. By
|
|
673
|
+
default, a new variable will be created. Both **x** and **y** must
|
|
674
|
+
be specified together as either existing variables or as `None`.
|
|
675
|
+
y (`Variable`, optional): The rectangular output :math:`y` variable. By
|
|
676
|
+
default, a new variable will be created. Both **x** and **y** must
|
|
677
|
+
be specified together as either existing variables or as `None`.
|
|
678
|
+
angle_units (`AngleUnits`, optional): The units of the angular
|
|
679
|
+
variables. This may be either `AngleUnits.Radians` (default) or
|
|
680
|
+
`AngleUnits.Degrees`.
|
|
681
|
+
zones (`list` of `Zones <data_access>`, optional): Specific zones to
|
|
682
|
+
transform. By default, all zones are transformed.
|
|
683
|
+
|
|
684
|
+
This example will create two new variables in the dataset corresponding to
|
|
685
|
+
the :math:`x` and :math:`y` equivalents of the :math:`r` and :math:`theta`
|
|
686
|
+
variables::
|
|
687
|
+
|
|
688
|
+
>>> dataset = tp.active_frame().dataset
|
|
689
|
+
>>> r = dataset.variable('R (m)')
|
|
690
|
+
>>> theta = dataset.variable('Theta (rad)')
|
|
691
|
+
>>> tp.data.operate.transform_polar_to_rectangular(r, theta)
|
|
692
|
+
>>> x, y = dataset.variable(-2), dataset.variable(-1)
|
|
693
|
+
|
|
694
|
+
.. warning:: **Source variables must have the same location as the
|
|
695
|
+
destination variables.**
|
|
696
|
+
|
|
697
|
+
The variables involved with this transformation must all be either
|
|
698
|
+
nodal or cell-centered.
|
|
699
|
+
"""
|
|
700
|
+
dataset = _dataset((r, theta, x, y), zones)
|
|
701
|
+
with tecutil.ArgList() as arglist:
|
|
702
|
+
arglist[sv.TRANSFORMATION] = Transform.PolarToRect
|
|
703
|
+
arglist[sv.RVAR] = dataset.variable(r).index
|
|
704
|
+
arglist[sv.THETAVAR] = dataset.variable(theta).index
|
|
705
|
+
if all(v is None for v in (x, y)):
|
|
706
|
+
arglist[sv.CREATENEWVARIABLES] = True
|
|
707
|
+
arglist[sv.XVAR] = 1
|
|
708
|
+
arglist[sv.YVAR] = 1
|
|
709
|
+
elif all(v is not None for v in (x, y)):
|
|
710
|
+
arglist[sv.CREATENEWVARIABLES] = False
|
|
711
|
+
arglist[sv.XVAR] = dataset.variable(x).index
|
|
712
|
+
arglist[sv.YVAR] = dataset.variable(y).index
|
|
713
|
+
else:
|
|
714
|
+
msg = 'All destination variables must be specified or None.'
|
|
715
|
+
raise TecplotLogicError(msg)
|
|
716
|
+
arglist[sv.ANGLESPEC] = AngleUnits(angle_units)
|
|
717
|
+
with tecutil.optional(tecutil.IndexSet, zones) as zones:
|
|
718
|
+
arglist[sv.ZONELIST] = zones
|
|
719
|
+
if not _tecutil.TransformCoordinatesX(arglist):
|
|
720
|
+
raise TecplotSystemError()
|
|
721
|
+
|
|
722
|
+
|
|
723
|
+
@tecutil.lock()
|
|
724
|
+
def transform_rectangular_to_polar(x, y, r=None, theta=None,
|
|
725
|
+
angle_units=AngleUnits.Radians, zones=None):
|
|
726
|
+
"""Transform all points from rectangular to polar coordinates.
|
|
727
|
+
|
|
728
|
+
Parameters:
|
|
729
|
+
x (`Variable`): The rectangular input :math:`x` variable.
|
|
730
|
+
y (`Variable`): The rectangular input :math:`y` variable.
|
|
731
|
+
r (`Variable`, optional): The radial output :math:`r` variable. By
|
|
732
|
+
default, a new variable will be created. Both **r** and **theta**
|
|
733
|
+
must be specified together as either existing variables or as
|
|
734
|
+
`None`.
|
|
735
|
+
theta (`Variable`, optional): The angular output :math:`theta`
|
|
736
|
+
variable. By default, a new variable will be created. Both **r**
|
|
737
|
+
and **theta** must be specified together as either existing
|
|
738
|
+
variables or as `None`.
|
|
739
|
+
angle_units (`AngleUnits`, optional): The units of the angular
|
|
740
|
+
variables. This may be either `AngleUnits.Radians` (default) or
|
|
741
|
+
`AngleUnits.Degrees`.
|
|
742
|
+
zones (`list` of `Zones <data_access>`, optional): Specific zones to
|
|
743
|
+
transform. By default, all zones are transformed.
|
|
744
|
+
|
|
745
|
+
This example will create two new variables in the dataset corresponding to
|
|
746
|
+
the :math:`r` and :math:`theta` equivalents of the :math:`x` and :math:`y`
|
|
747
|
+
variables::
|
|
748
|
+
|
|
749
|
+
>>> dataset = tp.active_frame().dataset
|
|
750
|
+
>>> x = dataset.variable('X (m)')
|
|
751
|
+
>>> y = dataset.variable('Y (m)')
|
|
752
|
+
>>> tp.data.operate.transform_rectangular_to_polar(x, y)
|
|
753
|
+
>>> theta, r = dataset.variable(-2), dataset.variable(-1)
|
|
754
|
+
|
|
755
|
+
.. warning:: **Source variables must have the same location as the
|
|
756
|
+
destination variables.**
|
|
757
|
+
|
|
758
|
+
The variables involved with this transformation must all be either
|
|
759
|
+
nodal or cell-centered.
|
|
760
|
+
"""
|
|
761
|
+
dataset = _dataset((x, y, r, theta), zones)
|
|
762
|
+
with tecutil.ArgList() as arglist:
|
|
763
|
+
arglist[sv.TRANSFORMATION] = Transform.RectToPolar
|
|
764
|
+
# (x, y) are switched in the SDK for this polar transformation
|
|
765
|
+
arglist[sv.XVAR] = dataset.variable(y).index
|
|
766
|
+
arglist[sv.YVAR] = dataset.variable(x).index
|
|
767
|
+
if all(v is None for v in (r, theta)):
|
|
768
|
+
arglist[sv.CREATENEWVARIABLES] = True
|
|
769
|
+
arglist[sv.RVAR] = 1
|
|
770
|
+
arglist[sv.THETAVAR] = 1
|
|
771
|
+
elif all(v is not None for v in (r, theta)):
|
|
772
|
+
arglist[sv.CREATENEWVARIABLES] = False
|
|
773
|
+
arglist[sv.RVAR] = dataset.variable(r).index
|
|
774
|
+
arglist[sv.THETAVAR] = dataset.variable(theta).index
|
|
775
|
+
else:
|
|
776
|
+
msg = 'All destination variables must be specified or None.'
|
|
777
|
+
raise TecplotLogicError(msg)
|
|
778
|
+
arglist[sv.ANGLESPEC] = AngleUnits(angle_units)
|
|
779
|
+
with tecutil.optional(tecutil.IndexSet, zones) as zones:
|
|
780
|
+
arglist[sv.ZONELIST] = zones
|
|
781
|
+
if not _tecutil.TransformCoordinatesX(arglist):
|
|
782
|
+
raise TecplotSystemError()
|
|
783
|
+
|
|
784
|
+
|
|
785
|
+
@tecutil.lock()
|
|
786
|
+
def transform_spherical_to_rectangular(r, theta, psi, x=None, y=None, z=None,
|
|
787
|
+
angle_units=AngleUnits.Radians, zones=None):
|
|
788
|
+
"""Transform all points from spherical to rectangular coordinates.
|
|
789
|
+
|
|
790
|
+
Parameters:
|
|
791
|
+
r (`Variable`): The radial input variable.
|
|
792
|
+
theta (`Variable`): The angular input variable in **angle_units** from
|
|
793
|
+
the :math:`x`-axis.
|
|
794
|
+
psi (`Variable`): The angular input variable in **angle_units** from
|
|
795
|
+
the :math:`z`-axis.
|
|
796
|
+
x (`Variable`, optional): The rectangular output :math:`x` variable. By
|
|
797
|
+
default, a new variable will be created. All of **x**, **y** and
|
|
798
|
+
**z** must be specified together as either existing variables or as
|
|
799
|
+
`None`.
|
|
800
|
+
y (`Variable`, optional): The rectangular output :math:`y` variable. By
|
|
801
|
+
default, a new variable will be created. All of **x**, **y** and
|
|
802
|
+
**z** must be specified together as either existing variables or as
|
|
803
|
+
`None`.
|
|
804
|
+
z (`Variable`, optional): The rectangular output :math:`z` variable. By
|
|
805
|
+
default, a new variable will be created. All of **x**, **y** and
|
|
806
|
+
**z** must be specified together as either existing variables or as
|
|
807
|
+
`None`.
|
|
808
|
+
angle_units (`AngleUnits`, optional): The units of the angular
|
|
809
|
+
variables. This may be either `AngleUnits.Radians` (default) or
|
|
810
|
+
`AngleUnits.Degrees`.
|
|
811
|
+
zones (`list` of `Zones <data_access>`, optional): Specific zones to
|
|
812
|
+
transform. By default, all zones are transformed.
|
|
813
|
+
|
|
814
|
+
This example will create three new variables in the dataset corresponding
|
|
815
|
+
to the :math:`(x, y, z)` equivalents of the :math:`(r, theta, psi)`
|
|
816
|
+
variables::
|
|
817
|
+
|
|
818
|
+
>>> dataset = tp.active_frame().dataset
|
|
819
|
+
>>> r = dataset.variable('R (m)')
|
|
820
|
+
>>> theta = dataset.variable('Theta (rad)')
|
|
821
|
+
>>> psi = dataset.variable('Psi (rad)')
|
|
822
|
+
>>> tp.data.operate.transform_spherical_to_rectangular(r, theta, psi)
|
|
823
|
+
>>> x = dataset.variable(-3)
|
|
824
|
+
>>> y = dataset.variable(-2)
|
|
825
|
+
>>> z = dataset.variable(-1)
|
|
826
|
+
|
|
827
|
+
.. warning:: **Source variables must have the same location as the
|
|
828
|
+
destination variables.**
|
|
829
|
+
|
|
830
|
+
The variables involved with this transformation must all be either
|
|
831
|
+
nodal or cell-centered.
|
|
832
|
+
"""
|
|
833
|
+
dataset = _dataset((r, theta, psi, x, y, z), zones)
|
|
834
|
+
with tecutil.ArgList() as arglist:
|
|
835
|
+
arglist[sv.TRANSFORMATION] = Transform.SphericalToRect
|
|
836
|
+
arglist[sv.RVAR] = dataset.variable(r).index
|
|
837
|
+
arglist[sv.THETAVAR] = dataset.variable(theta).index
|
|
838
|
+
arglist[sv.PSIVAR] = dataset.variable(psi).index
|
|
839
|
+
if all(v is None for v in (x, y, z)):
|
|
840
|
+
arglist[sv.CREATENEWVARIABLES] = True
|
|
841
|
+
arglist[sv.XVAR] = 1
|
|
842
|
+
arglist[sv.YVAR] = 1
|
|
843
|
+
arglist[sv.ZVAR] = 1
|
|
844
|
+
elif all(v is not None for v in (x, y, z)):
|
|
845
|
+
arglist[sv.CREATENEWVARIABLES] = False
|
|
846
|
+
arglist[sv.XVAR] = dataset.variable(x).index
|
|
847
|
+
arglist[sv.YVAR] = dataset.variable(y).index
|
|
848
|
+
arglist[sv.ZVAR] = dataset.variable(z).index
|
|
849
|
+
else:
|
|
850
|
+
msg = 'All destination variables must be specified or None.'
|
|
851
|
+
raise TecplotLogicError(msg)
|
|
852
|
+
arglist[sv.ANGLESPEC] = AngleUnits(angle_units)
|
|
853
|
+
with tecutil.optional(tecutil.IndexSet, zones) as zones:
|
|
854
|
+
arglist[sv.ZONELIST] = zones
|
|
855
|
+
if not _tecutil.TransformCoordinatesX(arglist):
|
|
856
|
+
raise TecplotSystemError()
|
|
857
|
+
|
|
858
|
+
|
|
859
|
+
@tecutil.lock()
|
|
860
|
+
def transform_rectangular_to_spherical(x, y, z, r=None, theta=None, psi=None,
|
|
861
|
+
angle_units=AngleUnits.Radians, zones=None):
|
|
862
|
+
"""Transform all points from rectangular to spherical coordinates.
|
|
863
|
+
|
|
864
|
+
Parameters:
|
|
865
|
+
x (`Variable`): The rectangular input :math:`x` variable.
|
|
866
|
+
y (`Variable`): The rectangular input :math:`y` variable.
|
|
867
|
+
z (`Variable`): The rectangular input :math:`z` variable.
|
|
868
|
+
r (`Variable`, optional): The radial output :math:`r` variable. By
|
|
869
|
+
default, a new variable will be created. All of **r**, **theta**
|
|
870
|
+
and **psi** must be specified together as either existing variables
|
|
871
|
+
or as `None`.
|
|
872
|
+
theta (`Variable`, optional): The angular output :math:`theta` variable
|
|
873
|
+
from the :math:`x`-axis. By default, a new variable will be
|
|
874
|
+
created. All of **r**, **theta** and **psi** must be specified
|
|
875
|
+
together as either existing variables or as `None`.
|
|
876
|
+
psi (`Variable`, optional): The angular output :math:`psi` variable
|
|
877
|
+
from the :math:`z`-axis. By default, a new variable will be
|
|
878
|
+
created. All of **r**, **theta** and **psi** must be specified
|
|
879
|
+
together as either existing variables or as `None`.
|
|
880
|
+
angle_units (`AngleUnits`, optional): The units of the angular
|
|
881
|
+
variables. This may be either `AngleUnits.Radians` (default) or
|
|
882
|
+
`AngleUnits.Degrees`.
|
|
883
|
+
zones (`list` of `Zones <data_access>`, optional): Specific zones to
|
|
884
|
+
transform. By default, all zones are transformed.
|
|
885
|
+
|
|
886
|
+
This example will create three new variables in the dataset corresponding
|
|
887
|
+
to the :math:`(r, theta, psi)` equivalents of the :math:`(x, y, z)`
|
|
888
|
+
variables::
|
|
889
|
+
|
|
890
|
+
>>> dataset = tp.active_frame().dataset
|
|
891
|
+
>>> x = dataset.variable('X (m)')
|
|
892
|
+
>>> y = dataset.variable('Y (m)')
|
|
893
|
+
>>> z = dataset.variable('Z (m)')
|
|
894
|
+
>>> tp.data.operate.transform_rectangular_to_spherical(x, y, z)
|
|
895
|
+
>>> theta = dataset.variable(-3)
|
|
896
|
+
>>> r = dataset.variable(-2)
|
|
897
|
+
>>> psi = dataset.variable(-1)
|
|
898
|
+
|
|
899
|
+
.. warning:: **Source variables must have the same location as the
|
|
900
|
+
destination variables.**
|
|
901
|
+
|
|
902
|
+
The variables involved with this transformation must all be either
|
|
903
|
+
nodal or cell-centered.
|
|
904
|
+
"""
|
|
905
|
+
dataset = _dataset((x, y, z, r, theta, psi), zones)
|
|
906
|
+
with tecutil.ArgList() as arglist:
|
|
907
|
+
arglist[sv.TRANSFORMATION] = Transform.RectToSpherical
|
|
908
|
+
arglist[sv.XVAR] = dataset.variable(x).index
|
|
909
|
+
arglist[sv.YVAR] = dataset.variable(y).index
|
|
910
|
+
arglist[sv.ZVAR] = dataset.variable(z).index
|
|
911
|
+
if all(v is None for v in (r, theta, psi)):
|
|
912
|
+
arglist[sv.CREATENEWVARIABLES] = True
|
|
913
|
+
arglist[sv.RVAR] = 1
|
|
914
|
+
arglist[sv.THETAVAR] = 1
|
|
915
|
+
arglist[sv.PSIVAR] = 1
|
|
916
|
+
elif all(v is not None for v in (r, theta, psi)):
|
|
917
|
+
arglist[sv.CREATENEWVARIABLES] = False
|
|
918
|
+
arglist[sv.RVAR] = dataset.variable(r).index
|
|
919
|
+
arglist[sv.THETAVAR] = dataset.variable(theta).index
|
|
920
|
+
arglist[sv.PSIVAR] = dataset.variable(psi).index
|
|
921
|
+
else:
|
|
922
|
+
msg = 'All destination variables must be specified or None.'
|
|
923
|
+
raise TecplotLogicError(msg)
|
|
924
|
+
arglist[sv.ANGLESPEC] = AngleUnits(angle_units)
|
|
925
|
+
with tecutil.optional(tecutil.IndexSet, zones) as zones:
|
|
926
|
+
arglist[sv.ZONELIST] = zones
|
|
927
|
+
if not _tecutil.TransformCoordinatesX(arglist):
|
|
928
|
+
raise TecplotSystemError()
|