Source code for tecplot.data.query

from builtins import str

from collections import namedtuple
from ctypes import byref, c_double, c_int32, c_int64

from ..tecutil import _tecutil
from ..constant import *
from ..exception import *
from .. import layout
from ..tecutil import Index, IndexSet, lock


[docs] @lock() def probe_at_position(x, y, z=None, nearest=False, starting_cell=None, starting_zone=None, zones=None, dataset=None, frame=None): """Returns field values at a point in space. .. note:: The position is taken according to the axis assignments of the `Frame <layout.Frame>` which may be any of the associated variables in the `Dataset <tecplot.data.Dataset>` and not necessarily ``(X, Y, Z)``. See: `Cartesian3DFieldAxis.variable`. Parameters: x,y,z (`float`, *z* is optional): position to probe for field values. nearest (`bool`): Returns the values at the nearest node to the given position. Probe position must be inside the volume of the data being queried, otherwise this will return `None`. starting_cell (3-`tuple` of `integers <int>`, optional): The ``(i,j,k)``-index of the cell to start looking for the given position. This must be used with ``starting_zone``. starting_zone (`Zone <data_access>`, optional): The first zone to start searching. This is required only when ``starting_cell`` is specified. zones (`list` of `Zones <data_access>`, optional): Limits the search to the given zones. `None` implies searching all zones. (default: `None`) dataset (`Dataset <tecplot.data.Dataset>`, optional): The `Dataset <tecplot.data.Dataset>` to probe. (defaults to the active `Dataset <tecplot.data.Dataset>`.) frame (`Frame <layout.Frame>`, optional): The `Frame <layout.Frame>` which determines the spatial variable assignment ``(X,Y,Z)``. (defaults to the active `Frame <layout.Frame>`.) Returns: `namedtuple <collections.namedtuple>`: ``(data, cell, zone)``: ``data`` (`list` of `floats <float>`) The values of each variable in the dataset at the given position. ``cell`` (3-`tuple` of `integers <int>`) ``(i,j,k)`` of the cell containing the given position. ``zone`` (`Zone <data_access>`) Zone containing the given position .. note:: Returns `None` if the position can't be probed. This method will return `None` if the position is outside the volume of the data being queried. This means one should capture the results in a single variable and test it against `None` before proceeding:: result = tp.data.query.probe_at_position(1.0, 2.0, 3.0) if result is None: print('probe failed.') else: data, cell, zone = result Additionally, with Tecplot 360 versions 2018 R1 and later, this function will raise an exception if Tecplot 360 was interrupted via the GUI during the probe operation. """ if __debug__: if frame and dataset and frame.dataset != dataset: msg = ('Dataset must be attached to the input Frame: {} != {}'. format(repr(frame.dataset), repr(dataset))) raise TecplotValueError(msg) if (starting_cell is None) ^ (starting_zone is None): msg = 'starting_cell option requires an associated starting_zone' raise TecplotLogicError(msg) if dataset is None: if frame is None: frame = layout.active_frame() dataset = frame.dataset elif frame is None: frame = dataset.frame with frame.activated(): if starting_cell is None: start_with_local_cell = False i, j, k = 0, 0, 0 starting_zone_index = 0 else: start_with_local_cell = True i, j, k = (x+1 for x in starting_cell) starting_zone_index = starting_zone.index allocd = [] if zones is not None: zones = IndexSet(*zones) allocd.append(zones) data = (max(3, dataset.num_variables)*c_double)() try: result = _tecutil.ProbeAtPosition( x, y, z or 0, i, j, k, IJKPlanes.Volume.value, starting_zone_index+1, start_with_local_cell, data, zones, z is not None, False, nearest) success, i, j, k, plane, zone_index = result except TecplotSystemError as e: if 'Assertion' in str(e): raise success = False if not success: if _tecutil.InterruptCheck(): raise TecplotInterruptError() return None cell = (Index(i-1), Index(j-1), Index(k-1)) zone_index = Index(zone_index-1) for a in allocd: a.dealloc() ProbeResult = namedtuple('ProbeResult', ['data', 'cell', 'zone']) return ProbeResult(data[:], cell, dataset.zone(zone_index))
[docs] @lock() def probe_on_surface(positions=((0,),(0,),(0,)), zones=None, variables=None, probe_nearest=ProbeNearest.Position, obey_blanking=True, num_nearest_nodes=20, tolerance=1e-5, dataset=None, frame=None): """Returns field values at points on a surface closest the points given. .. note:: The positions are processed according to the axis assignments of the `Frame <layout.Frame>` which may be any of the associated variables in the `Dataset <tecplot.data.Dataset>` and not necessarily (but usually) ``(X, Y, Z)``. See: `Cartesian3DFieldAxis.variable`. Parameters: positions (2D `float` array): Array of points to probe dimensioned by ``(3, N)`` where the first dimension corresponds to ``(x, y, z)``. A 1D `float` array is accepted for single point probes, however this should be avoided when probing several positions as the internal algorithm is optimized for probing many positions at once. zones (`list` of `Zones <data_access>`, optional): Limits the search to the given zones. `None` implies searching all active relevant surface zones including surfaces of ordered volume zones. To search FE or polygonal volume boundaries, include the volume zones in this list. (default: `None`) variables (`list` of `Variables <Variable>`, optional): The variables within the dataset to probe. `None` implies all variables. (default: `None`) probe_nearest (`ProbeNearest`, optional): Probe at the nodal location (`ProbeNearest.Node`) or interpolate to nearest location on the surface (`ProbeNearest.Position`, default). The return parameter **cells_or_nodes** will be cells if set to `ProbeNearest.Position` (default), or nodes if set to `ProbeNearest.Node`. obey_blanking (`bool`, optional): Do not search blanked cells according the frame's style settings. (default: `True`) num_nearest_nodes (`int`, optional): Only consider surface cells that contain one of the closest ``N`` nodes to the probed position. For highly varying surfaces, the nearest cell may or may not contain the nearest nodes to the probe position and so this value should be increased accordingly, however doing so increases the search-space linearly. (default: 20) tolerance (`float`, optional): The percentage of the longest cartesian ``(x, y, z)`` dimension subtended by the polygons of the surface. This is used in several parts of the algorithm to find the nearest position on the surface zones and should be increased when probing imprecise nodal position data. (default: 1e-5) dataset (`Dataset <tecplot.data.Dataset>`, optional): The `Dataset <tecplot.data.Dataset>` to probe. (defaults to the active `Dataset <tecplot.data.Dataset>`.) frame (`Frame <layout.Frame>`, optional): The `Frame <layout.Frame>` which determines the spatial variable assignment ``(X,Y,Z)``. (defaults to the active `Frame <layout.Frame>`.) Returns: `namedtuple <collections.namedtuple>`: ``(data, cells_or_nodes, planes, zone)``: ``data`` (`list` of `floats <float>`) Flattened `float` array which can be reshaped to ``(V, N)`` where ``V`` is the number of variables returned (either the number of variables in the dataset or the length of **variables** input parameter) and ``N`` is the number of points probed. ``cells_or_nodes`` (`list` of `integers <int>`) The index to the cells (or nodes if `ProbeNearest.Node` was passed in to **probe_nearest**) containing the returned positions. ``planes`` (`list` of `IJKPlanes`) For ordered zones, these are the plane-orientations of the cells for each probed position. ``zones`` (`list` of `Zones <data_access>`) Zones containing the given positions. .. versionadded:: 2018.1 Probe on surface requires Tecplot 360 2018 R1 or later. .. note:: The frame's plot type must be set to `PlotType.Cartesian3D` Probe on surface requires the spatial variables to be set according to the frame's style. This can be done by setting the plot type to `PlotType.Cartesian3D`. Example:: tp.active_frame().plot_type = tp.constant.PlotType.Cartesian3D For probing on 2D data, use `probe_at_position()`. .. note:: Linear zones will always return nearest nodal values. If linear zones, which are ignored by default, are included in the **zones** parameter, the resulting values on that zone will always be nodal and no interpolation on the position will be done. .. note:: Irregular or jaggged surfaces may behave poorly. For performance reasons, this algorithm has the potential to miss the closest position on highly varying surfaces. This can be addressed by first increasing **num_nearest_nodes** to search more of the zones and then by increasing the **tolerance** to allow for imprecise position data - skewed polygons for example. All nodes of each cell considered are checked for co-planarity. This check can be relaxed slightly by increasing the **tolerance** parameter. The nearest position calculation will then be made assuming the cells are planar and the resulting positions may be imprecise. Example usage: .. code-block:: python :emphasize-lines: 14,28 from os import path import numpy as np import tecplot as tp from tecplot.constant import PlotType examples = tp.session.tecplot_examples_directory() datafile = path.join(examples, 'SimpleData', 'F18.plt') ds = tp.data.load_tecplot(datafile) fr = tp.active_frame() fr.plot_type = PlotType.Cartesian3D # probe a single point res = tp.data.query.probe_on_surface((13.5, 4.0, 0.6 )) ''' The following line will print: (13.499723788684996, 3.9922783797612795, 0.49241572276992346, 0.0018958827755862578, 0.07313805429221854, 0.997276718375976, 0.06335166319722907) ''' print(res.data) # probe multiple points points = np.array([[13.5, 4.0, 0.6], # just above starboard wing [13.5, -4.0, 0.6]]) # just above port wing res = tp.data.query.probe_on_surface(points.transpose()) values = np.array(res.data).reshape((-1, len(points))).transpose() ''' The following will print the probed position and the result of the probe [ 13.5 4. 0.6] [ 1.34997238e+01 3.99227838e+00 4.92415723e-01 1.89588278e-03 7.31380543e-02 9.97276718e-01 6.33516632e-02] [ 13.5 -4. 0.6] [ 1.34997238e+01 -3.99227838e+00 4.92415723e-01 1.89588278e-03 7.31380543e-02 9.97276718e-01 6.33516632e-02] ''' for pt, v in zip(points, values): print(pt, v) """ if __debug__: if frame and dataset and frame.dataset != dataset: msg = ('Dataset must be attached to the input Frame: {} != {}'. format(repr(frame.dataset), repr(dataset))) raise TecplotValueError(msg) if dataset is None: if frame is None: frame = layout.active_frame() dataset = frame.dataset elif frame is None: frame = dataset.frame if not hasattr(positions[0], '__iter__'): positions = tuple(tuple([p]) for p in positions) nvariables = dataset.num_variables if variables is None else len(variables) with frame.activated(): n = max(len(p) for p in positions) m = n * nvariables x = (c_double * n)(*[float(p) for p in positions[0]]) y = (c_double * n)(*[float(p) for p in positions[1]]) z = (c_double * n)(*[float(p) for p in positions[2]]) v = (c_double * m)() cells_or_nodes = (c_int64 * n)() planes = (c_int32 * n)() zone_indices = (c_int32 * n)() zone_set = None if zones is None else IndexSet(zones) var_set = None if variables is None else IndexSet(variables) try: if not _tecutil.ProbeOnSurface(n, x, y, z, zone_set, var_set, ProbeNearest(probe_nearest).value, obey_blanking, num_nearest_nodes, tolerance, v, cells_or_nodes, planes, zone_indices): raise TecplotSystemError() finally: if zone_set is not None: zone_set.dealloc() if var_set is not None: var_set.dealloc() cells_or_nodes = tuple(cells_or_nodes) planes = tuple(map(IJKPlanes, planes)) zones = tuple(map(dataset.zone, zone_indices)) SurfaceProbeResult = namedtuple('SurfaceProbeResult', ['data', 'cells_or_nodes', 'planes', 'zones']) return SurfaceProbeResult(tuple(v), cells_or_nodes, planes, zones)