Source code for tecplot.data.extract
import ctypes
from ..tecutil import _tecutil
from ..constant import *
from ..exception import *
from .. import layout, tecutil, version
from ..tecutil import sv
[docs]@tecutil.lock()
def extract_line(points, num_points=None, frame=None, dataset=None):
"""Create new zone from a line in the dataset.
Parameters:
points (``2D numeric array``): The points defining the line in two or
three dimensions. This array must be of the shape *(N, D)* where
*N* is the number points and *D* is the number of dimensions. That
is, it must take the form ``[(x0, y0, z0), (x1, y1, z1) ...]``.
Points that do not lie within the dataset volume will be removed
from the resulting zone.
num_points (`int`, optional): The number of points to evenly
distribute along the polyline. (default: length of *points* or *N*)
frame (`Frame`, optional): A `Frame` that holds the `Dataset` to
operate on which must match *dataset* if given. (default: currently
active `Frame`)
dataset (`Dataset`, optional): The `Dataset` to operate on which must
be attached to *frame* if given. (default: currently active
`Dataset`)
Returns:
A 1D `OrderedZone` representing a line through the data. Points outside
of the dataset will be removed from the extracted zone resulting in
fewer points than input.
.. warning::
Line extraction is only available when the plot type is set to
`Cartesian2D` or `Cartesian3D`::
>>> from tecplot.constant import PlotType
>>> frame.plot_type = PlotType.Cartesian3D
This example shows how to extract a zone along a line, overlaying the
result in a new frame:
.. code-block:: python
:emphasize-lines: 26
import numpy as np
from os import path
import tecplot as tp
from tecplot.constant import *
examples_dir = tp.session.tecplot_examples_directory()
datafile = path.join(examples_dir, 'SimpleData', 'VortexShedding.plt')
dataset = tp.data.load_tecplot(datafile)
frame = tp.active_frame()
frame.activate()
plot = frame.plot()
plot.contour(0).variable = dataset.variable("P(N/M2)")
plot.show_contour = True
plot.contour(0).levels.reset(num_levels=11)
plot.contour(0).colormap_name = 'Sequential - Yellow/Green/Blue'
plot.axes.y_axis.min = -0.01
plot.axes.y_axis.max = 0.01
plot.axes.x_axis.min = -0.005
plot.axes.x_axis.max = 0.015
xx = np.linspace(0, 0.01, 100)
yy = np.zeros(100)
line = tp.data.extract.extract_line(zip(xx, yy))
plot.show_mesh = True
plot.fieldmap(0).mesh.show = False
frame = tp.active_page().add_frame()
frame.position = (3.0, 0.5)
frame.height = 2
frame.width = 4
plot = tp.active_frame().plot(PlotType.XYLine)
plot.activate()
plot.delete_linemaps()
lmap = plot.add_linemap('data', line, x=dataset.variable('P(N/M2)'),
y=dataset.variable('T(K)'))
lmap.line.line_thickness = 2.0
plot.axes.x_axis(0).title.font.size = 10
plot.axes.y_axis(0).title.font.size = 10
plot.axes.viewport.left = 20
plot.axes.viewport.bottom = 20
plot.view.fit()
tp.export.save_png("extract_line.png", region=ExportRegion.AllFrames,
width=600, supersample=3)
.. figure:: /_static/images/extract_line.png
:width: 300px
:figwidth: 300px
"""
if dataset is None:
if frame is None:
frame = layout.active_frame()
dataset = frame.dataset
elif frame is None:
frame = dataset.frame
if __debug__:
if frame.plot_type not in [PlotType.Cartesian2D, PlotType.Cartesian3D]:
msg = 'must be in a cartesian plot type to extract a line'
raise TecplotLogicError(msg)
if dataset != frame.dataset:
msg = 'dataset is not attached to given frame'
raise TecplotLogicError(msg)
new_zone_index = dataset.num_zones
try:
_ = points[0]
except TypeError:
points = list(points)
ndim = len(points[0])
if num_points is None:
num_points = len(points)
n = len(points)
xx = (ctypes.c_double * n)(*(float(p[0]) for p in points))
yy = (ctypes.c_double * n)(*(float(p[1]) for p in points))
zz = (ctypes.c_double * n)(*([0.]*len(xx)
if ndim < 3
else (float(p[2]) for p in points)))
extract_through_volume = ndim == 3
only_points_on_line = num_points == len(points)
include_distance = False
to_file = False
filename = None
try:
if not _tecutil.ExtractFromPolyline(xx, yy, zz, len(xx),
extract_through_volume,
only_points_on_line,
include_distance, num_points,
to_file, filename):
raise TecplotSystemError()
except TecplotLogicError as e:
# If some of the points are outside of the data, the zone
# is still extracted and this exception is not technically
# an error. A different message is generated if all of the
# points are outside of the data which is re-raised.
if 'Probe Position is outside of the data' not in str(e):
raise
return dataset.zone(new_zone_index)
[docs]@tecutil.lock()
def extract_slice(origin=(0, 0, 0), normal=(0, 0, 1), source=None,
mode=ExtractMode.SingleZone, copy_cell_centers=None,
assign_strand_ids=None,
transient_mode=TransientOperationMode.SingleSolutionTime,
frame=None, dataset=None, **kw):
"""Create new zone from a plane in the dataset.
Parameters:
origin (array of three `floats <float>`): Point in space,
:math:`(x, y, z)`, that lies on the slice plane.
normal (array of three `floats <float>`): Vector direction,
:math:`(x, y, z)`, indicating the normal of the slice plane.
source (`SliceSource`): Source zone types to consider when extracting
the slice. Possible values: `SliceSource.LinearZones`,
`SliceSource.SurfaceZones`, `SliceSource.SurfacesOfVolumeZones`,
`SliceSource.VolumeZones` (default).
mode (`ExtractMode`): Controls how many zones are created. Possible
values are: `ExtractMode.SingleZone` (default),
`ExtractMode.OneZonePerConnectedRegion` and
`ExtractMode.OneZonePerSourceZone`.
copy_cell_centers (`bool`): If `True`, cell-center
values will be copied when possible to the extracted slice plane.
Cell-centers are copied when a variable is cell-centered for all
the source zones through which the slice passes. Otherwise,
extracted planes use node-centered data, which is calculated by
interpolation. (default: `False`)
assign_strand_ids (`bool`): Automatically assign strand IDs
to the data extracted from transient sources. This is only
available if *multiple_zones* is `False`. (default: `True`)
transient_mode (`TransientOperationMode`): Determines which solution
times are used to extract slices when transient data is available
in the dataset. Possible values are
`TransientOperationMode.SingleSolutionTime` (default) or
`TransientOperationMode.AllSolutionTimes`.
frame (`Frame`, optional): A `Frame` that holds the `Dataset` to
operate on which must match *dataset* if given. (default: currently
active `Frame`)
dataset (`Dataset`, optional): The `Dataset` to operate on which must
be attached to *frame* if given. (default: currently active
`Dataset`)
Returns:
One or a `list` of `Zones <data_access>` representing a planar slice.
.. warning::
Slicing is only available when the plot type is set to 3D::
>>> from tecplot.constant import PlotType
>>> frame.plot_type = PlotType.Cartesian3D
.. note::
The extracted zone is returned if **mode** is `ExtractMode.SingleZone`
and **transient_mode** is `TransientOperationMode.SingleSolutionTime`,
otherwise a `generator <https://docs.python.org/3/reference/expressions.html#generator-expressions>`_
of the extracted zones.
.. seealso:: `tecplot.plot.SliceGroup.extract()`
This example shows extracting a slice zone from the surface a wing:
.. code-block:: python
:emphasize-lines: 16-20
import os
import tecplot as tp
from tecplot.constant import PlotType, SliceSource
examples_dir = tp.session.tecplot_examples_directory()
datafile = os.path.join(examples_dir, 'OneraM6wing',
'OneraM6_SU2_RANS.plt')
dataset = tp.data.load_tecplot(datafile)
frame = tp.active_frame()
frame.plot_type = PlotType.Cartesian3D
# set active plot to 3D and extract
# an arbitrary slice from the surface
# data on the wing
extracted_slice = tp.data.extract.extract_slice(
origin=(0, 0.25, 0),
normal=(0, 1, 0),
source=SliceSource.SurfaceZones,
dataset=dataset)
# switch plot type in current frame, clear plot
plot = frame.plot(PlotType.XYLine)
plot.activate()
plot.delete_linemaps()
# create line plot from extracted zone data
cp_linemap = plot.add_linemap(
name='Quarter-chord C_p',
zone=extracted_slice,
x=dataset.variable('x'),
y=dataset.variable('Pressure_Coefficient'))
# set style of linemap plot and
# update axes limits to show data
cp_linemap.line.color = tp.constant.Color.Blue
cp_linemap.line.line_thickness = 0.8
cp_linemap.y_axis.reverse = True
plot.view.fit()
# export image of pressure coefficient as a function of x
tp.export.save_png('wing_slice_pressure_coeff.png', 600, supersample=3)
.. figure:: /_static/images/wing_slice_pressure_coeff.png
:width: 300px
:figwidth: 300px
"""
if 'multiple_zones' in kw:
tecutil.api_changed('''\
"multiple_zones" has been removed, please use "mode" instead.''',
'0.13', '2018 R2')
if dataset is None:
if frame is None:
frame = layout.active_frame()
dataset = frame.dataset
elif frame is None:
frame = dataset.frame
mode = ExtractMode(mode)
transient_mode = TransientOperationMode(transient_mode)
if __debug__:
if frame.dataset != dataset:
raise TecplotLogicError('Dataset is not attached to frame.')
if frame.plot_type is not PlotType.Cartesian3D:
msg = 'Plot Type must be Cartesian3D to create a slice.'
raise TecplotLogicError(msg)
if mode != ExtractMode.SingleZone:
if version.sdk_version_info < (2017, 3):
msg = '"mode" parameter not supported.'
raise TecplotOutOfDateEngineError((2017, 3), msg)
if transient_mode != TransientOperationMode.SingleSolutionTime:
if version.sdk_version_info < (2019, 1):
msg = 'Slice over all solution times not supported'
raise TecplotOutOfDateEngineError((2019, 1), msg)
with frame.activated():
nzones = dataset.num_zones
with tecutil.ArgList() as arglist:
arglist[sv.ORIGINX] = float(origin[0])
arglist[sv.ORIGINY] = float(origin[1])
arglist[sv.ORIGINZ] = float(origin[2])
arglist[sv.NORMALX] = float(normal[0])
arglist[sv.NORMALY] = float(normal[1])
arglist[sv.NORMALZ] = float(normal[2])
if source is not None:
arglist[sv.SLICESOURCE] = SliceSource(source)
if mode != ExtractMode.SingleZone:
arglist[sv.EXTRACTMODE] = mode
arglist[sv.COPYCELLCENTEREDVALUES] = copy_cell_centers
if assign_strand_ids is not None:
arglist[sv.AUTOSTRANDTRANSIENTDATA] = bool(assign_strand_ids)
if transient_mode != TransientOperationMode.SingleSolutionTime:
arglist[sv.TRANSIENTOPERATIONMODE] = transient_mode
if not _tecutil.CreateSliceZoneFromPlneX(arglist):
raise TecplotSystemError()
if dataset.num_zones == nzones:
raise TecplotLogicError('No zones found when extracting slice')
if (
mode == ExtractMode.SingleZone and
transient_mode == TransientOperationMode.SingleSolutionTime
):
return dataset.zone(nzones)
else:
return (dataset.zone(i) for i in range(nzones, dataset.num_zones))
@tecutil.lock()
def extract_zones_from_connected_regions(zones):
with tecutil.IndexSet(zones) as zone_set:
if not _tecutil.ExtractZonesFromConnectedRegions(zone_set):
raise TecplotSystemError()