Examples¶
Hello World¶
A simple “Hello, World!” adds text to the active frame and exports the frame to an image file.
import tecplot
frame = tecplot.active_frame()
frame.add_text('Hello, World!', position=(36, 50), size=34)
tecplot.export.save_png('hello_world.png', 600)
Loading Layouts¶
Layouts can be loaded with the tecplot.load_layout()
method. This will accept
both lay
and lpk
(packaged) files. The exported image interprets the
image type by the extension you give it. See tecplot.export.save_png()
for
more details. Notice in this example, we turn on logging down to the DEBUG
level which is extremely verbose. This is useful for debugging the connection
between the script and Tecplot 360 EX.
import logging
import os
import sys
logging.basicConfig(stream=sys.stdout, level=logging.INFO)
import tecplot
examples_dir = tecplot.session.tecplot_examples_directory()
infile = os.path.join(examples_dir, '3D', 'JetSurface.lay')
tecplot.load_layout(infile)
tecplot.export.save_jpeg('jet_surface.jpeg', 600)
Extracting Slices¶
This script produces two images: a 3D view of the wing and a simplified pressure coefficient plot half-way down the wing:
import os
import sys
import logging
logging.basicConfig(stream=sys.stdout, level=logging.INFO)
import tecplot
examples_dir = tecplot.session.tecplot_examples_directory()
datafile = os.path.join(examples_dir, 'OneraM6wing', 'OneraM6_SU2_RANS.plt')
dataset = tecplot.data.load_tecplot(datafile)
frame = tecplot.active_frame()
frame.plot_type = tecplot.constant.PlotType.Cartesian3D
frame.plot().show_contour = True
# export image of wing
tecplot.export.save_png('wing.png', 600)
# extract an arbitrary slice from the surface data on the wing
extracted_slice = tecplot.data.extract.extract_slice(
origin=(0, 0.25, 0),
normal=(0, 1, 0),
slicesource=tecplot.constant.SliceSource.SurfaceZones,
dataset=dataset)
extracted_slice.name = 'Quarter-chord C_p'
# get x from slice
extracted_x = extracted_slice.values('x')
# copy of data as a numpy array
x = extracted_x.as_numpy_array()
# normalize x
xc = (x - x.min()) / (x.max() - x.min())
extracted_x[:] = xc
# switch plot type in current frame
frame.plot_type = tecplot.constant.PlotType.XYLine
plot = frame.plot()
# clear plot
plot.delete_linemaps()
# create line plot from extracted zone data
cp_linemap = plot.add_linemap(
name=extracted_slice.name,
zone=extracted_slice,
x=dataset.variable('x'),
y=dataset.variable('Pressure_Coefficient'))
# set style of linemap plot
cp_linemap.line.color = tecplot.constant.Color.Blue
cp_linemap.line.line_thickness = 0.8
cp_linemap.y_axis.reverse = True
# update axes limits to show data
plot.view.fit()
# export image of pressure coefficient as a function of x/c
tecplot.export.save_png('wing_pressure_coefficient.png', 600)
Numpy Integration¶
Note
Numpy, SciPy Required
This example requires both numpy and scipy installed. SciPy, in turn, requires a conforming linear algebra system such as OpenBLAS, LAPACK, ATLAS or MKL. It is recommended to use your operating system’s package manager to do this. Windows users and/or users that do not have root access to their machines might consider using Anaconda to setup a virtual environment where they can install python, numpy, scipy and all of its dependencies.
The spherical harmonic (n,m) = (5,4)
is calculated at unit radius. The magnitude is then used to create a 3D shape. The plot-style is modified and the following image is exported and the layout is saved in “packaged format.”
import logging as log
import numpy as np
from numpy import abs, pi, cos, sin
from scipy import special
log.basicConfig(level=log.INFO)
import tecplot as tp
from tecplot.session import set_style
from tecplot.constant import ColorMapDistribution
shape = (300, 300)
log.info('creating spherical harmonic data')
r = 0.3
phi = np.linspace(0, pi, shape[0])
theta = np.linspace(0, 2*pi, shape[1])
pphi, ttheta = np.meshgrid(phi, theta)
xx = r * sin(pphi) * cos(ttheta)
yy = r * sin(pphi) * sin(ttheta)
zz = r * cos(pphi)
n = 5
m = 4
ss = special.sph_harm(m, n, ttheta, pphi).real
ss /= ss.max()
log.info('creating tecplot dataset')
ds = tp.active_frame().create_dataset('Data', ['x','y','z','s'])
sphere_zone = ds.add_ordered_zone(
'SphericalHarmonic({}, {}) Sphere'.format(m, n),
shape)
sphere_zone.values('x')[:] = xx.ravel()
sphere_zone.values('y')[:] = yy.ravel()
sphere_zone.values('z')[:] = zz.ravel()
sphere_zone.values('s')[:] = ss.ravel()
tp.session.zones_added(sphere_zone)
log.info('creating shaped zone')
shaped_zone = ds.add_ordered_zone(
'SphericalHarmonic({}, {}) Shaped'.format(m, n),
shape)
shaped_zone.values('x')[:] = (abs(ss)*xx).ravel()
shaped_zone.values('y')[:] = (abs(ss)*yy).ravel()
shaped_zone.values('z')[:] = (abs(ss)*zz).ravel()
shaped_zone.values('s')[:] = ss.ravel()
log.info('state changed: zones added')
tp.session.zones_added(shaped_zone)
log.info('setting plot type to Cart3D')
tp.active_frame().plot_type = tp.constant.PlotType.Cartesian3D
plot = tp.active_frame().plot()
'''
The lines below are equivalent to the macro commands.
Notice that PyTecplot indexes universally from zero where the
macro indexes from one.
$!FIELDLAYERS SHOWCONTOUR = YES
$!FIELDLAYERS USETRANSLUCENCY = YES
$!FIELDMAP [1] EFFECTS { SURFACETRANSLUCENCY = 70 }
$!FIELDMAP [2] EFFECTS { SURFACETRANSLUCENCY = 30 }
$!GLOBALCONTOUR 1 COLORMAPFILTER { COLORMAPDISTRIBUTION = CONTINUOUS }
$!GLOBALCONTOUR 1 COLORMAPNAME = 'Sequential - Yellow/Green/Blue'
'''
plot.show_contour = True
plot.use_translucency = True
plot.fieldmap(sphere_zone).effects.surface_translucency = 70
plot.fieldmap(shaped_zone).effects.surface_translucency = 30
plot.contour(0).colormap_filter.distribution = ColorMapDistribution.Continuous
plot.contour(0).colormap_name = 'Sequential - Yellow/Green/Blue'
filename = 'spherical_harmonic_{}_{}'.format(m, n)
for axis in plot.axes:
axis.fit_range()
log.info('saving image')
tp.export.save_png(filename + '.png', 600)
log.info('saving packaged layout file')
tp.save_layout(filename + '.lpk', include_data=True)
log.info('releasing license')
Execute Equation¶
This example illustrates altering data through equations in four zones. For
complete information on the Tecplot Engine “data alter” syntax, see Chapter
21, Data Operations, in the Tecplot 360 User’s Manual. This script outputs
the original data followed by the same image where we’ve modified the scaling
of Nj
only on the wings.
import os
import tecplot
examples_dir = tecplot.session.tecplot_examples_directory()
infile = os.path.join(examples_dir, '3D', 'JetSurface.lay')
# Load a stylized layout where the contour variable is set to 'Nj'
tecplot.load_layout(infile)
current_dataset = tecplot.active_frame().dataset
# export original image
tecplot.export.save_png('jet_surface_orig.png', 600)
# alter variable 'Nj' for the the two wing zones in the dataset
# In this simple example, just multiply it by 10.
tecplot.data.operate.execute_equation('{Nj}={Nj}*10',
zones=[current_dataset.zone('right wing'),
current_dataset.zone('left wing')])
# The contour color of the wings in the exported image will now be
# red, since we have altered the 'Nj' variable by multiplying it by 10.
tecplot.export.save_png('jet_surface_altered.png', 600)
Line Plots¶
This example shows how to set the style for a plot of three lines. The y-axis label and legend labels are changed and the axes are adjusted to fit the data.
from os import path
import tecplot as tp
from tecplot.constant import PlotType, Color, LinePattern, AxisTitleMode
# load data from examples directory
examples_dir = tp.session.tecplot_examples_directory()
infile = path.join(examples_dir, 'XY', 'rainfall.plt')
dataset = tp.data.load_tecplot(infile)
# get handle to the active frame and set plot type to XY Line
frame = tp.active_frame()
frame.plot_type = PlotType.XYLine
plot = frame.plot()
# We will set the name, color and a few other properties
# for the first three linemaps in the dataset.
names = ['Seattle', 'Dallas', 'Miami']
colors = [Color.Blue, Color.DeepRed, Color.Khaki]
# loop over the linemaps, setting style for each
for lmap,name,color in zip(plot.linemaps(),names,colors):
lmap.show = True
lmap.name = name # This will be used in the legend
# Changing some line attributes
line = lmap.line
line.color = color
line.line_thickness = 1
line.line_pattern = LinePattern.LongDash
line.pattern_length = 2
# Set the y-axis label
plot.axes.y_axis(0).title.title_mode = AxisTitleMode.UseText
plot.axes.y_axis(0).title.text = 'Rainfall'
# Turn on legend
plot.legend.show = True
# Adjust the axes limits to show all the data
plot.view.fit()
# save image to file
tp.export.save_png('linemap.png', 600)
Creating Slices¶
This example illustrates reading a dataset then creating and showing arbitrary slices of the dataset. A primary slice, start, end, and 3 intermediate slices are shown.
from os import path
import tecplot as tp
from tecplot.constant import SliceSurface, ContourType
examples_dir = tp.session.tecplot_examples_directory()
datafile = path.join(examples_dir, '3D_Volume', 'ductflow.plt')
dataset = tp.data.load_tecplot(datafile)
plot = tp.active_frame().plot()
plot.contour(0).variable = dataset.variable('U(M/S)')
plot.show_slices = True
slice_0 = plot.slice(0)
slice_0.contour.show = True
slice_0.contour.contour_type = ContourType.Overlay # AKA "Both lines and flood"
slice_0.effects.use_translucency = True
slice_0.effects.surface_translucency = 30
slice_0.show_primary_slice = False
slice_0.show_start_and_end_slices = True
slice_0.show_intermediate_slices = True
slice_0.start_position = (-.21, .05, .025)
slice_0.end_position = (1.342, .95, .475)
slice_0.num_intermediate_slices = 2
tp.export.save_png('slice_example.png', 600)
Creating Iso-surfaces¶
This example illustrates reading a dataset, then creating and showing isosurfaces.
from os import path
import tecplot as tp
from tecplot.constant import LightingEffect, IsoSurfaceSelection
examples_dir = tp.session.tecplot_examples_directory()
datafile = path.join(examples_dir, '3D_Volume', 'ductflow.plt')
dataset = tp.data.load_tecplot(datafile)
plot = tp.active_frame().plot()
plot.contour(0).variable = dataset.variable('U(M/S)')
plot.show_isosurfaces = True
iso = plot.isosurface(0)
iso.isosurface_selection = IsoSurfaceSelection.ThreeSpecificValues
iso.isosurface_values = (135.674706817, 264.930212259, 394.185717702)
iso.shade.use_lighting_effect = True
iso.effects.lighting_effect = LightingEffect.Paneled
iso.contour.show = True
iso.effects.use_translucency = True
iso.effects.surface_translucency = 50
tp.export.save_png('isosurface_example.png', 600)
Wing Surface Slices¶
This example illustrates reading a dataset and showing surface slices with colored mesh on the Onera M6 Wing. Seven surface slices are shown, colored by the distance along the Y axis.
import tecplot
from tecplot.constant import *
import os
import numpy as np
examples_dir = tecplot.session.tecplot_examples_directory()
datafile = os.path.join(examples_dir, 'OneraM6wing', 'OneraM6_SU2_RANS.plt')
dataset = tecplot.data.load_tecplot(datafile)
frame = tecplot.active_frame()
plot = frame.plot()
# Turn on only the periodic slices (start, end and intermeidate)
# and set them to span the length of the wing
plot.show_slices = True
slices = plot.slice(0)
slices.slice_source = SliceSource.SurfaceZones
slices.orientation = SliceSurface.YPlanes
slices.show_primary_slice = False
slices.show_start_and_end_slices = True
slices.show_intermediate_slices = True
slices.num_intermediate_slices = 5
slices.start_position = (0, 0.02, 0)
slices.end_position = (0,1.19,0)
# Setup First Contour Group to color by the distance along the Y axis (Span)
cont = plot.contour(0)
cont.variable = frame.dataset.variable('y')
cont.levels.reset_levels(np.linspace(0,1.2,13))
cont.legend.show = False
# Color the Surface Slices by the contour, this must be done on the mesh
slices.contour.show = False
slices.mesh.show = True
slices.mesh.color = cont
slices.mesh.line_thickness = 0.6
slices.edge.show = False
# Turn translucency on globally
plot.use_translucency = True
tecplot.export.save_png("wing_slices.png",600)
Mach Iso-surfaces¶
This example illustrates using contour group properties to define multiple Iso-surfaces. In this case, multiple Mach values are shown as Iso-surfaces.
import tecplot
from tecplot.constant import *
import os
examples_dir = tecplot.session.tecplot_examples_directory()
datafile = os.path.join(examples_dir, 'OneraM6wing', 'OneraM6_SU2_RANS.plt')
ds = tecplot.data.load_tecplot(datafile)
frame = tecplot.active_frame()
plot = frame.plot()
# Set Isosurface to match Contour Levels of the first group.
iso = plot.isosurface(0)
iso.isosurface_selection = IsoSurfaceSelection.AllContourLevels
cont = plot.contour(0)
iso.definition_contour_group = cont
cont.colormap_name = 'Magma'
# Setup definition Isosurface layers
cont.variable = ds.variable('Mach')
cont.levels.reset_levels( [.95,1.0,1.1,1.4])
print(list(cont.levels))
# Turn on Translucency
iso.effects.use_translucency = True
iso.effects.surface_translucency = 80
# Turn on Isosurfaces
plot.show_isosurfaces = True
iso.show = True
cont.legend.show = False
tecplot.macro.execute_command("""$!THREEDVIEW
PSIANGLE = 65.777
THETAANGLE = 166.415
ALPHAANGLE = -1.05394
VIEWERPOSITION
{
X = -23.92541680486183
Y = 101.8931504712126
Z = 47.04269529295333
}
VIEWWIDTH = 1.3844""")
tecplot.export.save_png("wing_iso.png",width=600, supersample=4)
Exception Handling¶
It is the policy of the PyTecplot Python module to raise exceptions on any failure. It is the user’s job to catch them or otherwise prevent them by ensuring the Tecplot Engine is properly setup to the task you ask of it. Aside from exceptions raised by the underlying Python core libraries, PyTecplot may raise a subclass of TecplotError
, the most common being TecplotRuntimeError
.
import logging
import os
# turn on exceptionally verbose logging!!!
logging.basicConfig(level=logging.DEBUG)
import tecplot
from tecplot.exception import *
# Calling tecplot.session.acquire_license() is optional.
# If you do not call it, it will be called automatically for you
# the first time you call any |PyTecplot| API.
#
# acquire_license() may also be called manually. It will raise an exception
# if Tecplot cannot be initialized. The most common reason that
# Tecplot cannot be initialized is if a valid license is not found.
# If you call start yourself, you can catch and recover from the
# exception.
#
# Note that calling tecplot.session.stop() will release the license acquired
# when calling tecplot.session.|PyTecplot|().
#
# Also note that once tecplot.session.stop() is called, |Tecplot Engine|
# cannot be restarted again during the current python session.
#
try:
tecplot.session.acquire_license()
logging.info('License acquired, Tecplot Engine started.')
except TecplotLicenseError:
logging.exception('Missing or invalid license:')
except TecplotError:
logging.exception('Could not initialize pytecplot')
exit(1)
examples_dir = tecplot.session.tecplot_examples_directory()
infile = os.path.join(examples_dir, '3D', 'spaceship.lpk')
outfile = 'spaceship.png'
try:
logging.info('Opening layout file: ' + infile)
tecplot.load_layout(infile)
logging.info('Exporting Image: ' + outfile)
tecplot.export.save_png(outfile, 600)
logging.info('Finished, no errors')
except IOError:
logging.debug("I/O Error: Check disk space and permissions")
except TecplotSystemError:
logging.exception('Failed to export image: ' + outfile)
finally:
# tecplot.session.stop() may be called manually to shut down Tecplot and release
# the license.
# If tecplot.session.stop() is not called manually it will be called automatically
# when the script exits.
tecplot.session.stop()
logging.info('Done')