Source code for tecplot.data.dataset

from builtins import super

import ctypes
import logging
import re

from collections import namedtuple
from fnmatch import fnmatch
from functools import reduce
from keyword import iskeyword
from six import string_types
from textwrap import dedent

from ..tecutil import (_tecutil, ArgList, Index, IndexSet, flatten_args,
                       log_setattr)
from .. import layout
from ..constant import *
from ..exception import *
from ..tecutil import lock
from ..tecutil import sv

log = logging.getLogger(__name__)


# noinspection PyShadowingNames
@log_setattr
[docs]class Array(ctypes.c_void_p): """Low-level accessor for underlying data within a `Dataset`.""" def __init__(self, dataset, zone, variable): self.dataset = dataset self.zone = zone self.variable = variable super().__init__(self._native_reference) @property @lock() def _native_reference(self): return _tecutil.DataValueGetReadableNativeRefByUniqueID( self.dataset.uid, self.zone.index + 1, self.variable.index + 1) def __eq__(self, other): return ctypes.addressof(self) == ctypes.addressof(other) def __len__(self): return self.shape[0] @property def size(self): return _tecutil.DataValueGetCountByRef(self) @property def shape(self): """(i,j,k) shape""" return self.zone.shape @property def c_type(self): _ctypes = { FieldDataType.Float: ctypes.c_float, FieldDataType.Double: ctypes.c_double, FieldDataType.Int32: ctypes.c_int, FieldDataType.Int16: ctypes.c_int16, FieldDataType.Byte: ctypes.c_int8} return _ctypes[self.data_type] @property def data_type(self): return _tecutil.DataValueGetRefType(self) @property def data(self): _tecutil.handle.tecUtilDataValueGetWritableRawPtrByRef.restype = \ ctypes.POINTER(self.c_type) return _tecutil.DataValueGetWritableRawPtrByRef(self) @lock()
[docs] def copy(self, offset=0, size=None): size = self.size if size is None else size arr = (self.c_type * size)() _tecutil.DataValueArrayGetByRef(self, offset + 1, size, arr) return arr
def _slice_range(self, s): start = s.start or 0 stop = s.stop or self.size step = s.step or 1 return range(start, stop, step) def __getitem__(self, i): if isinstance(i, slice): data = self.data return [data[ii] for ii in self._slice_range(i)] else: return self.data[i] def __setitem__(self, i, val): if isinstance(i, slice): data = self.data for ii in self._slice_range(i): data[ii] = val[ii] else: self.data[i] = val def __iter__(self): self.current_index = -1 self.current_length = self.size return self def __next__(self): self.current_index += 1 if self.current_index < self.current_length: return self.__getitem__(self.current_index) else: del self.current_index del self.current_length raise StopIteration() @property def minmax(self): return _tecutil.DataValueGetMinMaxByRef(self)
[docs] def min(self): return self.minmax[0]
[docs] def max(self): return self.minmax[1]
# noinspection PyShadowingNames @log_setattr
[docs]class Zone(object): """Key value for a data array within a `Dataset`. Parameters: uid (`integer <int>`): This must be a *valid* unique ID number pointing internally to a `Zone` object in the given `Dataset`. dataset (`Dataset`): A `Dataset` to which this `Zone` is contained. `Zones <Zone>` can be identified (uniquely) by the index with their parent `Dataset` or (non-uniquely) by name. In general, a `Variable` must be selected to access the underlying data array. """ def __init__(self, uid, dataset): self.uid = uid self.dataset = dataset # string representations def __str__(self): """Brief string representation. Returns: `string <str>`: Brief representation of this `Zone`, showing a list of associated `Variables <Variable>`. Example:: >>> rect_zone = dataset.zone('Rectangular zone') >>> print(rect_zone) Zone: Rectangular zone Variables: ['x', 'y', 'z'] """ fmt = 'Zone: {}\n Variables: [{}]' vnames = ["'{}'".format(v.name) for v in self.dataset.variables()] return fmt.format(self.name, ','.join(vnames)) def __repr__(self): """Executable string representation. Returns: `string <str>`: Internal representation of this `Zone`. The string returned can be executed to generate a clone of this `Zone` object:: >>> rectzone = dataset.zone('Rectangular zone') >>> print(repr(rectzone)) Zone(uid=31, Dataset(uid=21, frame=Frame(uid=11, page=Page(uid=1))) >>> exec('rectzone_clone = '+repr(rectzone)) >>> rectzone_clone Zone(uid=31, Dataset(uid=21, frame=Frame(uid=11, page=Page(uid=1))) >>> rectzone == rectzone_clone True """ return 'Zone(uid={uid}, dataset={dataset})'.format( uid=self.uid, dataset=repr(self.dataset)) def __eq__(self, other): """Checks for equality in the |Tecplot Engine|. Returns: `bool`: `True` if the unique ID numbers are the same for both `Zones <Zone>`. """ return self.uid == other.uid @property def index(self): """Zero-based position within the parent `Dataset`. :type: `Index` """ return Index(_tecutil.ZoneGetNumByUniqueID(self.uid) - 1) @property def strand(self): """Returns the StrandID. :type: `Index` """ return Index(_tecutil.ZoneGetStrandID(self.index + 1) - 1) @strand.setter @lock() def strand(self, value): _tecutil.ZoneSetStrandID(self.index + 1, value + 1) @property def solution_time(self): """Returns the solution time. :type: `float` """ return _tecutil.ZoneGetSolutionTime(self.index + 1) @solution_time.setter @lock() def solution_time(self, value): _tecutil.ZoneSetSolutionTime(self.index + 1, value) @property def type(self): """Returns the zone type. :type: `ZoneType` """ return _tecutil.ZoneGetType(self.index + 1) @property def name(self): """Returns or sets the name. :type: `string <str>` Raises: `TecplotSystemError` """ res, zname = _tecutil.ZoneGetNameByDataSetID(self.dataset.uid, self.index + 1) if not res: TecplotSystemError() return zname @name.setter @lock() def name(self, name): _tecutil.ZoneRenameByDataSetID(self.dataset.uid, self.index + 1, name) @property def num_variables(self): """Number of `Variables <Variable>` in the parent `Dataset`. :type: `integer <int>` """ return self.dataset.num_variables
[docs] def variable(self, pattern): """Returns an `Array` by index or string pattern. Parameters: pattern (`integer <int>` or `string <str>`): Zero-based index or `glob-style pattern <fnmatch.fnmatch>` in which case, the first match is returned. The `Variable.name` attribute is used to match the *pattern* to the desired `Array` though this is not necessarily unique:: >>> ds = frame.dataset >>> print(ds) Dataset: Zones: ['Rectangular zone'] Variables: ['x', 'y', 'z'] >>> zone = ds.zone('Rectangular zone') >>> x = zone.variable('x') >>> x == zone.variable(0) True """ return Array(self.dataset, self, self.dataset.variable(pattern))
[docs] def variables(self, pattern=None): """Yields all `Arrays <Array>` matching a *pattern*.""" for variable in self.dataset.variables(pattern): yield Array(self.dataset, self, variable)
[docs] def copy(self): """duplicate this `Zone` in its currently held parent `Dataset`.""" return self.dataset.copy_zones(self)[0]
@property def num_points(self): """Number of elements in the associated data array.""" if self.type is ZoneType.Ordered: return reduce(lambda x, y: x * y, self.shape, 1) else: return self.shape[0] @property def shape(self): """The shape of the associated data arrays. Returns: `tuple`(`int`): ``(i,j,k)`` for ordered data or ``(len,)`` for unordered data. """ return _tecutil.ZoneGetIJKByUniqueID(self.dataset.uid, self.index + 1)
# noinspection PyShadowingNames @log_setattr
[docs]class Variable(object): """Key value for a data array within a `Dataset`. Parameters: uid (`integer <int>`): This must be a *valid* unique ID number pointing internally to a `Variable` object in the given `Dataset`. dataset (`Dataset`): A `Dataset` to which this `Variable` is contained. `Variables <Variable>` can be identified (uniquely) by the index with their parent `Dataset` or (non-uniquely) by name. In general, a `Zone` must be selected to access the underlying data array. """ def __init__(self, uid, dataset): self.uid = uid self.dataset = dataset # string representations def __str__(self): """Brief string representation. Returns: `string <str>`: Brief representation of this `Variable`, showing `Zones <Zone>`. Example:: >>> x = dataset.variable('x') >>> print(x) Variable: x Zones: ['Rectangular zone'] """ fmt = 'Variable: {}\n Zones: [{}]' znames = ["'{}'".format(z.name) for z in self.dataset.zones()] return fmt.format(self.name, ','.join(znames)) def __repr__(self): """Executable string representation. Returns: `string <str>`: Internal representation of this `Variable`. The string returned can be executed to generate a clone of this `Variable` object:: >>> x = dataset.variable('x') >>> print(repr(x)) Variable(uid=41, Dataset(uid=21, frame=Frame(uid=11, page=Page(uid=1))) >>> exec('x_clone = '+repr(x)) >>> x_clone Variable(uid=41, Dataset(uid=21, frame=Frame(uid=11, page=Page(uid=1))) >>> x == x_clone True """ return 'Variable(uid={uid}, dataset={dataset})'.format( uid=self.uid, dataset=repr(self.dataset)) def __eq__(self, other): """Checks for equality in the |Tecplot Engine|. Returns: `bool`: `True` if the unique ID numbers are the same for both `Variables <Variable>`. """ return self.uid == other.uid @property def index(self): """Zero-based position within the parent `Dataset`. :type: `Index` """ return Index(_tecutil.VarGetNumByUniqueID(self.uid) - 1) @property def name(self): """Returns or sets the name. :type: `string <str>` Raises: `TecplotSystemError` """ res, var_name = _tecutil.VarGetNameByDataSetID(self.dataset.uid, self.index + 1) if not res: TecplotSystemError() return var_name @name.setter @lock() def name(self, name): _tecutil.VarRenameByDataSetID(self.dataset.uid, self.index + 1, name) @property def num_zones(self): """Number of `Zones <Zone>` in the parent `Dataset`. :type: `integer <int>` """ return self.dataset.num_zones
[docs] def zone(self, pattern): """Returns `Array` by index or string pattern. Parameters: pattern (`integer <int>` or `string <str>`): Zero-based index or `glob-style pattern <fnmatch.fnmatch>` in which case, the first match is returned. The `Zone.name` attribute is used to match the *pattern* to the desired `Array` though this is not necessarily unique:: >>> ds = frame.dataset >>> print(ds) Dataset: Zones: ['Rectangular zone'] Variables: ['x', 'y', 'z'] >>> x = ds.variable('x') >>> rectzone = x.zone('Rectangular zone') >>> rectzone == x.zone(0) True """ return Array(self.dataset, self.dataset.zone(pattern), self)
[docs] def zones(self, pattern=None): """Yields all `Arrays <Array>` matching a *pattern*.""" for zone in self.dataset.zones(pattern): yield Array(self.dataset, zone, self)
# noinspection PyShadowingNames @log_setattr
[docs]class Dataset(object): """A matrix of `Zones <Zone>` and `Variables <Variable>`. Parameters: uid (`integer <int>`): This must be a *valid* unique ID number pointing internally to a `Dataset` object. frame (`Frame`): A `Frame` to which this `Dataset` is attached. This is the primary data-holding object within the Tecplot Engine. A `Dataset` can be shared among several `Frames <Frame>`, though any particular `Dataset` object will have a handle to at least one of them. Any modification of a shared `Dataset` will be reflected in all `Frames <Frame>` that use it. Though a `Dataset` is usually attached to a `Frame` and the plot style associated with that, it can be thought of as independent from any style or plotting representation. Each `Dataset` consists of a list of `Variables <Variable>` which are used by one or more of a list of `Zones <Zone>`. The `Variable` determines the data type while the `Zone` determines the layout such as shape and ordered vs unordered. The actual data are found at the intersection of a `Zone` and `Variable` and the resulting object is an `Array`. The data array can be obtained using either path:: >>> # These two lines obtain the same object "x" >>> x = dataset.zone('My Zone').variable('X') >>> x = dataset.variable('X').zone('My Zone') A `Dataset` is the object returned by most data-loading operation in |PyTecplot|:: >>> dataset = tecplot.data.load_tecplot('my_data.plt') Under `Dataset`, there are a number methods to create and delete `zones <Zone>` and `variables <Variable>`. """ def __init__(self, uid, frame): self.uid = uid self.frame = frame def __repr__(self): """Executable string representation. Returns: `string <str>`: Internal representation of this `Dataset`. The string returned can be executed to generate a clone of this `Dataset` object:: >>> dataset = frame.dataset >>> print(repr(dataset)) Dataset(uid=21, frame=Frame(uid=11, page=Page(uid=1))) >>> exec('dataset_clone = '+repr(dataset)) >>> dataset_clone Dataset(uid=21, frame=Frame(uid=11, page=Page(uid=1))) >>> dataset == dataset_clone True """ return 'Dataset(uid={uid}, frame={frame})'.format( uid=self.uid, frame=repr(self.frame)) def __str__(self): """Brief string representation. Returns: `string <str>`: Brief representation of this `Dataset`, showing `Zones <Zone>` and `Variables <Variable>`. Example:: >>> dataset = frame.dataset >>> print(dataset) Dataset: Zones: ['Rectangular zone'] Variables: ['x', 'y', 'z'] """ fmt = 'Dataset:\n Zones: [{}]\n Variables: [{}]' return fmt.format( ','.join("'{}'".format(z.name) for z in self.zones()), ','.join("'{}'".format(v.name) for v in self.variables())) def __eq__(self, other): """Checks for equality in the |Tecplot Engine|. Returns: `bool`: `True` if the unique ID numbers are the same for both `Datasets <Dataset>`. This can be useful for determining if two `Frames <Frame>` are holding on to the same `Dataset`:: >>> frame1.dataset == frame2.dataset True """ return self.uid == other.uid def __ne__(self, other): return not self.__eq__(other) def __contains__(self, obj): if obj.dataset == self: if isinstance(obj, Variable) and obj == self.variable(obj.index): return True elif isinstance(obj, Zone) and obj == self.zone(obj.index): return True return False @property def title(self): """Title of this `Dataset`. :type: `string <str>` Raises: `TecplotSystemError` Example usage:: >>> dataset.title = 'My Data' """ try: return _tecutil.DataSetGetInfoByUniqueID(self.uid)[0] except AttributeError: with self.frame.activated(): return _tecutil.DataSetGetInfo()[1] @title.setter @lock() def title(self, title): try: if not _tecutil.DataSetSetTitleByUniqueID(self.uid, title): raise TecplotSystemError() except AttributeError: with self.frame.activated(): if not _tecutil.DataSetSetTitle(name): raise TecplotSystemError() @property def num_zones(self): """Number of `Zones <Zone>` in this `Dataset`. :type: `integer <int>` Example usage:: >>> for i in range(dataset.num_zones): ... zone = dataset.zone(i) """ return _tecutil.DataSetGetNumZonesByUniqueID(self.uid)
[docs] def zone(self, pattern): """Returns `Zone` by index or string pattern. Parameters: pattern (`integer <int>` or `string <str>`): Zero-based index or `glob-style pattern <fnmatch.fnmatch>` in which case, the first match is returned. Raises: `TecplotIndexError` The `Zone.name` attribute is used to match the *pattern* to the desired `Zone` though this is not necessarily unique:: >>> ds = frame.dataset >>> print(ds) Dataset: Zones: ['Rectangular zone'] Variables: ['x', 'y', 'z'] >>> rectzone = ds.zone('Rectangular zone') >>> rectzone == ds.zone(0) True """ if isinstance(pattern, string_types): return next(self.zones(pattern)) else: if pattern < 0: pattern += self.num_zones if 0 <= pattern < self.num_zones: with self.frame.activated(): if _tecutil.ZoneIsEnabled(pattern + 1): return Zone(_tecutil.ZoneGetUniqueIDByDataSetID( self.uid, pattern + 1), self) raise TecplotIndexError
[docs] def zones(self, pattern=None): """Yields all `Zones <Zone>` matching a *pattern*. Parameters: pattern (`string <str>` pattern, optional): `glob-style pattern <fnmatch.fnmatch>` used to match zone names or `None` which will return all zones. (default: `None`) Example usage:: >>> for zone in dataset.zones('A*'): ... x_array = zone.variable('X') """ for i in range(self.num_zones): try: zone = self.zone(i) if pattern is None or fnmatch(zone.name, pattern): yield zone except TecplotIndexError: # zone not enabled pass
@property def num_variables(self): """Number of `Variables <Variable>` in this `Dataset`. :type: `integer <int>` Example usage:: >>> for i in range(dataset.num_variables): ... variable = dataset.variable(i) """ return _tecutil.DataSetGetNumVarsByUniqueID(self.uid)
[docs] def variable(self, pattern): """Returns the `Variable` by index or string pattern. Parameters: pattern (`integer <int>` or `string <str>`): Zero-based index or `glob-style pattern <fnmatch.fnmatch>` in which case, the first match is returned. Raises: `TecplotIndexError` The `Variable.name` attribute is used to match the *pattern* to the desired `Variable` though this is not necessarily unique:: >>> ds = frame.dataset >>> print(ds) Dataset: Zones: ['Rectangular zone'] Variables: ['x', 'y', 'z'] >>> x = ds.variable('x') >>> x == ds.variable(0) True """ if isinstance(pattern, string_types): return next(self.variables(pattern)) else: if pattern < 0: pattern += self.num_variables if 0 <= pattern < self.num_variables: if _tecutil.VarIsEnabledByDataSetID(self.uid, pattern + 1): return Variable(_tecutil.VarGetUniqueIDByDataSetID( self.uid, pattern + 1), self) raise TecplotIndexError
[docs] def variables(self, pattern=None): """Yields all `Variables <Variable>` matching a *pattern*. Parameters: pattern (`string <str>` pattern, optional): `glob-style pattern <fnmatch.fnmatch>` used to match variable names or `None` which will return all variables. (default: `None`) Example usage:: >>> for variable in dataset.variables('A*'): ... array = variable.zone('My Zone') """ for i in range(self.num_variables): try: variable = self.variable(i) if pattern is None or fnmatch(variable.name, pattern): yield variable except TecplotIndexError: # variable not enabled pass
# noinspection PyPep8Naming @property def VariablesNamedTuple(self): """A `collections.namedtuple` object using variable names. .. note:: The variable names are transformed to be unique, valid identifiers suitable for use as the key-list for a `collections.namedtuple`. This means that all invalid characters such as spaces and dashes are converted to underscores, leading numbers and Python keywords are prepended by underscores and duplicate variable names are indexed starting with zero. Examples: This example shows how one can use this n-tuple type with the result from a call to `tecplot.data.query.probe_at_position`:: >>> from os import path >>> import tecplot as tp >>> examples_dir = tp.session.tecplot_examples_directory() >>> datafile = path.join(examples_dir,'3D_Volume','jetflow.plt') >>> dataset = tp.data.load_tecplot(datafile) >>> result = tp.data.query.probe_at_position(0,0.1,0.3) >>> data = dataset.VariablesNamedTuple(*result.data) >>> msg = '(RHO, E) = ({:.2f}, {:.2f})' >>> print(msg.format(data.RHO, data.E)) (RHO, E) = (1.17, 252930.37) """ names = [] name_count = {} for v in self.variables(): # sub invalid characters with underscores name = re.sub('\W|^(?=\d)', '_', v.name) # prepend Python keywords with underscore if iskeyword(name): name = '_' + name if name in name_count: name_count[name] += 1 name = '{}{}'.format(name, name_count[name]) else: name_count[name] = 0 names.append(name) return namedtuple('DatasetVariables', names) @lock()
[docs] def copy_zones(self, *zones): """Copies `Zones <Zone>` within this `Dataset`. Parameters: zones (`Zone`, optional): Specific `zones <Zone>` to copy. Returns: `list` of the newly created `Zones <Zone>`. Example usage:: >>> zones = dataset.copy_zones() """ num_zones = self.num_zones with IndexSet(*zones) as zoneset: with ArgList(SOURCEZONES=zoneset) as arglist: if __debug__: log.debug('Zone copy:\n' + str(arglist)) _tecutil.ZoneCopyX(arglist) return [self.zone(i) for i in range(num_zones, self.num_zones)]
@lock()
[docs] def add_variable(self, name, dtypes=None, locations=None): """Add a single `Variable` to the active `Dataset`. Parameters: name (`string <str>`): The name of the new `Variable`. This does not have to be unique. dtypes (`FieldDataType` or `list` of `FieldDataType`, optional): Data types of this `Variable` for each `Zone` in the currently active `Dataset`. Options are: `FieldDataType.Float`, `Double <FieldDataType.Double>`, `Int32`, `Int16`, `Byte` and `Bit`. If a single value, this will be duplicated for all `Zones <Zone>`. (default: `None`) locations (`ValueLocation` or `list` of `ValueLocation`, optional): Point locations of this `Variable` for each `Zone` in the currently active `Dataset`. Options are: `Nodal` and `CellCentered`. If a single value, this will be duplicated for all `Zones <Zone>`. (default: `None`) Raises: `TecplotSystemError` """ assert len(name) <= 128, 'Variable names are limited to 128 characters' with self.frame.activated(): dataset = self.frame.dataset new_variable_index = dataset.num_variables with ArgList(NAME=name) as arglist: if dtypes is not None: if not hasattr(dtypes, '__iter__'): dtypes = [dtypes] * dataset.num_zones arglist['VARDATATYPE'] = dtypes if locations is not None: if not hasattr(locations, '__iter__'): locations = [locations] * dataset.num_zones arglist['VALUELOCATION'] = locations if __debug__: msg = 'new variable: ' + name for k, v in arglist.items(): msg += '\n {} = {}'.format(k, v) log.debug(msg) if not _tecutil.DataSetAddVarX(arglist): raise TecplotSystemError() return dataset.variable(new_variable_index)
@lock()
[docs] def add_zone(self, zone_type, name, shape, dtypes=None, locations=None, **kwargs): """Add a single `Zone` to this `Dataset`. Parameters: zone_type (`ZoneType`): The type of `Zone` to be created. Possible values are: `Ordered`, `FETriangle`, `FEQuad`, `FETetra`, `FEBrick`, `FELineSeg`, `FEPolyhedron` and `FEPolygon`. name (`string <str>`): Name of the new `Zone`. This does not have to be unique. shape (`integer <int>` or `list` of `integers <int>`): Specifies the length and dimension (up to three) of the new `Zone`. A 1D `Zone` is assumed if a single `int` is given. This is **(i, j, k)** for ordered `Zones <Zone>`, **(num_points, num_elements)** for finite-element `Zones <Zone>` and **(num_points, num_elements, num_faces)** for polytope `Zones <Zone>` where the number of faces is known. dtypes (`FieldDataType`, `list` of `FieldDataType`, optional): Data types of this `Zone` for each `Variable` in the currently active `Dataset`. Options are: `FieldDataType.Float`, `Double <FieldDataType.Double>`, `Int32`, `Int16`, `Byte` and `Bit`. If a single value, this will be duplicated for all `Variables <Variable>`. If `None` then the type of the first `Variable`, defaulting to `FieldDataType.Float`, is used for all. (default: `None`) locations (`ValueLocation`, `list` of `ValueLocation`, optional): Point locations of this `Zone` for each `Variable` in the currently active `Dataset`. Options are: `Nodal` and `CellCentered`. If a single value, this will be duplicated for all `Variables <Variable>`. If `None` then the type of the first `Variable`, defaulting to `Nodal`, is used for all. (default: `None`) parent_zone (`Zone`, optional): A parent `Zone` to be used when generating surface-restricted streamtraces. solution_time (`float`, optional): (default: 0) strand_id (`integer <int>`, optional): Associate this new `Zone` with a particular strand. Raises: `TecplotSystemError` """ if __debug__: if self.num_variables == 0: errmsg = dedent('''\ Can not create a zone on a dataset with no variables. Add at least one variable to this dataset before creating any zones.''') raise TecplotLogicError(errmsg) kwargs = {k.replace('_', '').upper(): v for k, v in kwargs.items()} with self.frame.activated(): dataset = self.frame.dataset new_zone_index = dataset.num_zones with ArgList(ZONETYPE=zone_type, NAME=name) as arglist: # convert shape to (imax, jmax, kmax) if not hasattr(shape, '__iter__'): shape = [shape] for k, v in zip([sv.IMAX, sv.JMAX, sv.KMAX], shape): arglist[k] = v # expand data types and locations to length of num_variables for key, val in zip([sv.VARDATATYPE, sv.VALUELOCATION], [dtypes, locations]): if val is not None: if not hasattr(val, '__iter__'): val = [val] * dataset.num_variables arglist[key] = val # ensure floating-point params are floats float_args = [sv.SOLUTIONTIME] for a in float_args: if a in kwargs: kwargs[a] = float(kwargs[a]) # convert objects to indexes index_args = [sv.ZONE, sv.CONNECTSHAREZONE] for a in index_args: if a in kwargs: kwargs[a] = kwargs[a].index + 1 arglist.update(**kwargs) if __debug__: shp = '({})'.format(','.join(str(s) for s in shape)) msg = 'new dataset shape: ' + shp for k, v in arglist.items(): msg += '\n {} = {}'.format(k, v) log.debug(msg) if not _tecutil.DataSetAddZoneX(arglist): raise TecplotSystemError() return dataset.zone(new_zone_index)
[docs] def add_ordered_zone(self, name, shape, dtypes=None, locs=None, **kwargs): return self.add_zone(ZoneType.Ordered, name, shape, dtypes, locs, **kwargs)
[docs] def add_fe_zone(self, zone_type, name, num_points, num_elements, dtypes=None, locs=None, **kwargs): assert zone_type in [ZoneType.FETriangle, ZoneType.FEQuad, ZoneType.FETetra, ZoneType.FEBrick, ZoneType.FELineSeg] return self.add_zone(zone_type, name, (num_points, num_elements), dtypes, locs, **kwargs)
[docs] def add_poly_zone(self, name, zone_type, num_points, num_elements, num_faces, **kwargs): assert zone_type in [ZoneType.FEPolyhedron, ZoneType.FEPolygon] return self.add_zone(zone_type, name, (num_points, num_elements, num_faces), dtypes, locs, **kwargs)
@lock()
[docs] def delete_variables(self, *variables): """Remove `Variables <Variable>` from this `Dataset`. Parameters: *variables (`Variable` or index `integer <int>`): Variables to remove from this dataset. .. code-block:: python :emphasize-lines: 3 >>> print([v.name for v in dataset.variables()]) ['X','Y','Z'] >>> dataset.delete_variables(dataset.variable('Z')) >>> print([v.name for v in dataset.variables()]) ['X','Y'] Notes: Multiple `Variables <Variable>` can be deleted at once, though the last `Variable` can not be deleted. This command deletes all but the first `Variable` in the `Dataset` (usually ``X``):: >>> # Try to delete all variables: >>> dataset.delete_variables(dataset.variables()) >>> # Dataset requires at least one variable to >>> # exist, so it leaves the first one: >>> print([v.name for v in dataset.variables()]) ['X'] """ variables = flatten_args(*variables) with self.frame.activated(): with IndexSet(*variables) as vlist: _tecutil.DataSetDeleteVar(vlist)
@lock()
[docs] def delete_zones(self, *zones): """Remove `Zones <Zone>` from this `Dataset`. Parameters: *zones (`Zone` or index `integer <int>`): Zones to remove from this dataset. .. code-block:: python :emphasize-lines: 3 >>> print([z.name for z in dataset.zones()]) ['Zone 1', 'Zone 2'] >>> dataset.delete_zones(dataset.zone('Zone 2')) >>> print([z.name for z in dataset.zones()]) ['Zone 1'] Notes: Multiple `Zones <Zone>` can be deleted at once, though the last `Zone` can not be deleted. This command deletes all but the first `Zone` in the `Dataset`:: dataset.delete_zones(dataset.zones()) """ zones = flatten_args(*zones) with self.frame.activated(): with IndexSet(*zones) as zlist: _tecutil.DataSetDeleteZone(zlist)
@property @lock() def dataset(frame): """`Dataset` attached to this `Frame`. Returns: `Dataset`: The object holding onto the data associated with this `Frame`. If no `Dataset` has been created for this `Frame`, a new one is created and returned. """ with frame.activated(): if not _tecutil.DataSetIsAvailableForFrame(frame.uid): frame.create_dataset(frame.name + ' Dataset') return Dataset(_tecutil.DataSetGetUniqueID(), frame) @property def has_dataset(frame): """Checks to see if the `Frame` as an attached `Dataset` Returns: `bool`: `True` if the `Frame` has a `Dataset` """ with frame.activated(): return _tecutil.DataSetIsAvailableForFrame(frame.uid) layout.Frame.dataset = dataset layout.Frame.has_dataset = has_dataset