Examples¶
Hello World¶
A simple “Hello, World!” example that does the following:
- enables extremely verbose logging
- starts the Tecplot 360 EX engine
- add text to the active frame
- exports the frame to an image file
- releases the Tecplot 360 EX License
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.
import logging
import os
import sys
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
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)
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
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')
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.DEBUG)
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.variable('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.” The methods used in this example should be considered very low-level and in a “pre-alpha”/early stage in development:
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().dataset
ds.add_variable('x')
ds.add_variable('y')
ds.add_variable('z')
ds.add_variable('s')
sphere_zone = ds.add_ordered_zone(
'SphericalHarmonic({}, {}) Sphere'.format(m, n),
shape)
sphere_zone.variable('x')[:] = xx.ravel()
sphere_zone.variable('y')[:] = yy.ravel()
sphere_zone.variable('z')[:] = zz.ravel()
sphere_zone.variable('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.variable('x')[:] = (abs(ss)*xx).ravel()
shaped_zone.variable('y')[:] = (abs(ss)*yy).ravel()
shaped_zone.variable('z')[:] = (abs(ss)*zz).ravel()
shaped_zone.variable('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.show_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)
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 one or more zones. For complete information on the Tecplot Engine data alter syntax, see Chapter 21, Data Operations, in the Tecplot 360 User’s Manual.
import logging
import os
import sys
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
import tecplot
from tecplot.data.operate import execute_equation
from tecplot import active_frame
examples_dir = tecplot.session.tecplot_examples_directory()
infile = os.path.join(examples_dir, '3D', 'JetSurface.lay')
outfile = 'jet_surface.png'
tecplot.load_layout(infile)
current_dataset = active_frame().dataset # type: tecplot.data.dataset.Dataset
# alter variable 'Nj' for the the two wing zones in the dataset
# In this simple example, just multiply it by 10.
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(outfile, 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
# 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.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)