pytecplot 1.5.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. pytecplot-1.5.2.dist-info/LICENSE.html +77 -0
  2. pytecplot-1.5.2.dist-info/METADATA +508 -0
  3. pytecplot-1.5.2.dist-info/RECORD +97 -0
  4. pytecplot-1.5.2.dist-info/WHEEL +5 -0
  5. pytecplot-1.5.2.dist-info/top_level.txt +1 -0
  6. tecplot/__init__.py +94 -0
  7. tecplot/annotation/__init__.py +7 -0
  8. tecplot/annotation/annotation.py +223 -0
  9. tecplot/annotation/geometry.py +369 -0
  10. tecplot/annotation/georeference.py +33 -0
  11. tecplot/annotation/image.py +185 -0
  12. tecplot/annotation/iter.py +105 -0
  13. tecplot/annotation/polyline.py +381 -0
  14. tecplot/annotation/text.py +744 -0
  15. tecplot/constant.py +401 -0
  16. tecplot/data/__init__.py +34 -0
  17. tecplot/data/array.py +645 -0
  18. tecplot/data/create.py +1 -0
  19. tecplot/data/dataset.py +1809 -0
  20. tecplot/data/extract.py +544 -0
  21. tecplot/data/face_neighbors.py +494 -0
  22. tecplot/data/facemap.py +814 -0
  23. tecplot/data/load.py +2075 -0
  24. tecplot/data/nodemap.py +577 -0
  25. tecplot/data/operate.py +928 -0
  26. tecplot/data/query.py +334 -0
  27. tecplot/data/save.py +343 -0
  28. tecplot/data/variable.py +280 -0
  29. tecplot/data/zone.py +841 -0
  30. tecplot/exception.py +201 -0
  31. tecplot/export/__init__.py +13 -0
  32. tecplot/export/animation.py +521 -0
  33. tecplot/export/export_setup.py +318 -0
  34. tecplot/export/image.py +577 -0
  35. tecplot/export/print_setup.py +218 -0
  36. tecplot/export/time_animation.py +607 -0
  37. tecplot/extension/__init__.py +14 -0
  38. tecplot/extension/ipython.py +68 -0
  39. tecplot/layout/__init__.py +20 -0
  40. tecplot/layout/frame.py +1285 -0
  41. tecplot/layout/layout.py +488 -0
  42. tecplot/layout/page.py +541 -0
  43. tecplot/legend/__init__.py +4 -0
  44. tecplot/legend/contour_legend.py +516 -0
  45. tecplot/legend/legend.py +141 -0
  46. tecplot/legend/line_legend.py +66 -0
  47. tecplot/legend/rgb_coloring_legend.py +291 -0
  48. tecplot/legend/scatter_legend.py +136 -0
  49. tecplot/macro.py +339 -0
  50. tecplot/plot/__init__.py +62 -0
  51. tecplot/plot/axes.py +881 -0
  52. tecplot/plot/axis.py +1350 -0
  53. tecplot/plot/blanking.py +584 -0
  54. tecplot/plot/contour.py +1302 -0
  55. tecplot/plot/effects.py +162 -0
  56. tecplot/plot/fieldmap.py +2159 -0
  57. tecplot/plot/grid.py +758 -0
  58. tecplot/plot/isosurface.py +1167 -0
  59. tecplot/plot/labels.py +338 -0
  60. tecplot/plot/linemap.py +1905 -0
  61. tecplot/plot/linking.py +489 -0
  62. tecplot/plot/plot.py +1791 -0
  63. tecplot/plot/rgb_coloring.py +281 -0
  64. tecplot/plot/scatter.py +396 -0
  65. tecplot/plot/slice.py +1544 -0
  66. tecplot/plot/streamtrace.py +1949 -0
  67. tecplot/plot/symbol.py +567 -0
  68. tecplot/plot/ticks.py +666 -0
  69. tecplot/plot/title.py +380 -0
  70. tecplot/plot/vector.py +679 -0
  71. tecplot/plot/view.py +868 -0
  72. tecplot/session/__init__.py +112 -0
  73. tecplot/session/aux_data.py +276 -0
  74. tecplot/session/config.py +92 -0
  75. tecplot/session/session.py +425 -0
  76. tecplot/session/state_changed.py +225 -0
  77. tecplot/session/style.py +504 -0
  78. tecplot/tecutil/__init__.py +16 -0
  79. tecplot/tecutil/arglist.py +230 -0
  80. tecplot/tecutil/captured_output.py +177 -0
  81. tecplot/tecutil/constant.py +1312 -0
  82. tecplot/tecutil/index_set.py +118 -0
  83. tecplot/tecutil/lock.py +36 -0
  84. tecplot/tecutil/message_pb2.py +39 -0
  85. tecplot/tecutil/preamble.py +54 -0
  86. tecplot/tecutil/stringlist.py +114 -0
  87. tecplot/tecutil/sv.py +1662 -0
  88. tecplot/tecutil/tecutil.py +12402 -0
  89. tecplot/tecutil/tecutil_client.py +627 -0
  90. tecplot/tecutil/tecutil_connector.py +937 -0
  91. tecplot/tecutil/tecutil_rpc.py +6845 -0
  92. tecplot/tecutil/util.py +332 -0
  93. tecplot/text/__init__.py +3 -0
  94. tecplot/text/font.py +224 -0
  95. tecplot/text/label_format.py +374 -0
  96. tecplot/text/textbox.py +106 -0
  97. tecplot/version.py +41 -0
@@ -0,0 +1,332 @@
1
+ import collections
2
+ import contextlib
3
+ import ctypes
4
+ import inspect
5
+ import logging
6
+ import os
7
+ import re
8
+ import tempfile
9
+ import textwrap
10
+ import warnings
11
+
12
+ from collections.abc import Iterable
13
+ from ctypes import cast, c_int, POINTER
14
+
15
+ from ..exception import *
16
+ from ..constant import Color
17
+
18
+ log = logging.getLogger(__name__)
19
+
20
+ maxint64 = 2**(64 - 1) - 1
21
+ minint64 = -maxint64 - 1
22
+ maxuint64 = 2**64 - 1
23
+
24
+ IndexRange = collections.namedtuple('IndexRange', 'min max step')
25
+ IndexRange.__new__.__defaults__ = (None, None, None)
26
+
27
+ class Index(int):
28
+ """Position identifier type.
29
+
30
+ This type is used internally to represent a position in a list. It is
31
+ used to indicate that a change between zero-based indexing and one-based
32
+ indexing must occur at the TecUtil boundary.
33
+
34
+ This type can be treated exactly like a Python native `int` and is only
35
+ meaningful internally to the tecplot Python module.
36
+ """
37
+
38
+ XY = collections.namedtuple('XY', ('x', 'y'))
39
+ XY.__new__.__defaults__ = (None, None)
40
+
41
+ XYZ = collections.namedtuple('XYZ', ('x', 'y', 'z'))
42
+ XYZ.__new__.__defaults__ = (None, None, None)
43
+
44
+ def flatten_args(*args):
45
+ flatargs = []
46
+ for a in args:
47
+ if isinstance(a, Iterable) and not isinstance(a, str):
48
+ flatargs += list(a)
49
+ else:
50
+ flatargs.append(a)
51
+ return tuple(flatargs)
52
+
53
+
54
+ def array_to_enums(array_pointer, array_size, enum_type):
55
+ indexes = cast(array_pointer, POINTER(c_int))
56
+ return tuple(enum_type(indexes[i]) for i in range(array_size))
57
+
58
+
59
+ def inherited_property(cls):
60
+ def _copy_property(prop):
61
+ attr = getattr(cls, prop.__name__)
62
+ return property(attr.fget, attr.fset, attr.fdel, prop.__doc__)
63
+ return _copy_property
64
+
65
+
66
+ def lock_attributes(cls):
67
+ """
68
+ As a decorator of a class, this ensures that no new attributes are created
69
+ after __init__() is called.
70
+ """
71
+ if __debug__:
72
+ def _setattr(self, name, value):
73
+ if not name.startswith('_') and name not in dir(self):
74
+ stacknames = [f[0].f_code.co_name for f in inspect.stack()[:3]]
75
+ if '__init__' not in stacknames:
76
+ msg = 'No attribute: {}.{}'
77
+ classname = self.__class__.__name__
78
+ raise TecplotAttributeError(msg.format(classname, name))
79
+ return super(cls, self).__setattr__(name, value)
80
+ cls.__setattr__ = _setattr
81
+ return cls
82
+
83
+
84
+ _VarInfo = collections.namedtuple('_VarInfo', ('types', 'values', 'names'))
85
+
86
+
87
+ def check_arglist_argtypes(function_name, *args):
88
+ for arg in args:
89
+ vinfo = _VarInfo(*arg)
90
+ for name, value in zip(vinfo.names, vinfo.values):
91
+ if value is not None:
92
+ if not isinstance(value, tuple(vinfo.types)):
93
+ errfmt = '{}: Type of parameter {} must be one of: {}'
94
+ types = ', '.join(t.__name__ for t in vinfo.types)
95
+ errmsg = errfmt.format(function_name, name, types)
96
+ raise TecplotTypeError(errmsg)
97
+
98
+
99
+ def color_spec(color, plot=None):
100
+ """
101
+ color_spec(Color.Blue, plot) --> Color.Blue
102
+ color_spec(Color.MultiColor, plot) --> plot.contour(0)
103
+ color_spec(Color.MultiColor2, plot) --> plot.contour(1)
104
+ color_spec(Color.Blue) --> Color.Blue
105
+ color_spec(plot.contour(0)) --> Color.MultiColor
106
+ color_spec(plot.contour(1)) --> Color.MultiColor2
107
+
108
+ color_spec(plot.rgb_coloring) --> Color.RGBColor
109
+ color_spec(Color.RGBColor, plot) --> plot.rgb_coloring
110
+ """
111
+ if isinstance(color, Iterable):
112
+ return tuple([color_spec(c, plot) for c in color])
113
+ color_spec._indexes = {
114
+ Color.RGBColor: Index(Color.RGBColor.value),
115
+ Color.MultiColor: Index(0),
116
+ Color.MultiColor2: Index(1),
117
+ Color.MultiColor3: Index(2),
118
+ Color.MultiColor4: Index(3),
119
+ Color.MultiColor5: Index(4),
120
+ Color.MultiColor6: Index(5),
121
+ Color.MultiColor7: Index(6),
122
+ Color.MultiColor8: Index(7)}
123
+ color_spec._multicolors = {v: k for k, v in color_spec._indexes.items()}
124
+ try:
125
+ if plot:
126
+ if color == Color.RGBColor:
127
+ return plot.rgb_coloring
128
+ else:
129
+ return plot.contour(color_spec._indexes[Color(color)])
130
+ else:
131
+ return color_spec._multicolors[Index(color.index)]
132
+ except (AttributeError, KeyError):
133
+ return Color(color)
134
+
135
+
136
+ def filled_slice(slice_, maxlen):
137
+ """Convert start, stop, step in slice to real integers.
138
+
139
+ None and negative values are converted to actual default values depending
140
+ on the maxlen given.
141
+ """
142
+ if slice_.start is None:
143
+ start = 0
144
+ elif slice_.start < 0:
145
+ start = maxlen + slice_.start
146
+ else:
147
+ start = slice_.start
148
+ start = min(max(start, 0), maxlen)
149
+
150
+ if slice_.stop is None:
151
+ stop = maxlen
152
+ elif slice_.stop < 0:
153
+ stop = maxlen + slice_.stop
154
+ else:
155
+ stop = slice_.stop
156
+ stop = min(max(stop, 0), maxlen)
157
+
158
+ if slice_.step is None:
159
+ step = 1
160
+ else:
161
+ step = min(max(slice_.step, 1), maxlen)
162
+
163
+ return slice(start, stop, step)
164
+
165
+
166
+ def array_to_str(arr, maxlen=10):
167
+ try:
168
+ itr = iter(arr)
169
+ item = next(itr)
170
+ ret = '[' + str(item)
171
+ for i, item in enumerate(itr, start=2):
172
+ if i > maxlen:
173
+ ret += ' ...'
174
+ break
175
+ ret += ', {}'.format(item)
176
+ return ret + ']'
177
+ except StopIteration:
178
+ return '[]'
179
+ except TypeError:
180
+ return str(arr)
181
+
182
+
183
+ class ListWrapper(object):
184
+ """Converts a list to a wrapped paragraph of items.
185
+
186
+ Unlike textwrap.TextWrapper, items in the list are not broken over
187
+ multiple lines even if they contain spaces.
188
+ """
189
+ def __init__(self, initial_indent='', subsequent_indent=' ',
190
+ initial_width=70, subsequent_width=70, delim=',',
191
+ prefix='', suffix=''):
192
+ assert (len(prefix) + len(initial_indent)) < initial_width
193
+ assert (len(suffix) + len(subsequent_indent)) < subsequent_width
194
+ self.initial_indent = initial_indent
195
+ self.subsequent_indent = subsequent_indent
196
+ self.initial_width = initial_width
197
+ self.subsequent_width = subsequent_width
198
+ self.delim = delim
199
+ self.prefix = prefix
200
+ self.suffix = suffix
201
+
202
+ def wrap(self, str_list):
203
+ ret = []
204
+ max_space = self.subsequent_width - len(self.subsequent_indent)
205
+
206
+ line = "{}{}".format(self.prefix, self.initial_indent)
207
+
208
+ itr = iter(str_list)
209
+ try:
210
+ item = next(itr)
211
+ line += "'{}'".format(item)
212
+ except StopIteration:
213
+ pass # no items in list
214
+
215
+ space_left = self.initial_width - len(line)
216
+
217
+ for item in itr:
218
+ s = "{} '{}'".format(self.delim, str(item))
219
+ if len(s) < space_left or max_space <= space_left:
220
+ line += s
221
+ space_left -= len(s)
222
+ else:
223
+ ret.append(line + self.delim)
224
+ line = "{}'{}'".format(self.subsequent_indent, item)
225
+ space_left = self.subsequent_width - len(line)
226
+
227
+ if len(self.suffix) <= space_left:
228
+ ret.append(line + self.suffix)
229
+ else:
230
+ ret.append(line)
231
+ ret.append("{}{}".format(self.subsequent_indent, self.suffix))
232
+ return ret
233
+
234
+ def fill(self, str_list):
235
+ return '\n'.join(self.wrap(str_list))
236
+
237
+
238
+ @contextlib.contextmanager
239
+ def optional(cls, args):
240
+ """Context for optional arguments that can be None.
241
+
242
+ In this example, variables is an optional parameter. If not `None`, then
243
+ ``varset`` will be the result of ``IndexSet(*variables)``, if `None`, then
244
+ ``varset`` will be `None`::
245
+
246
+ def fn(variables=None):
247
+ with optional(IndexSet, variables) as varset:
248
+ _tecutil.Fn(varset)
249
+
250
+ The ``cls`` parameter must be a class and must have the ``__enter__`` and
251
+ ``__exit__`` methods implemented.
252
+ """
253
+ if args is None:
254
+ yield None
255
+ else:
256
+ with cls(*flatten_args(args)) as obj:
257
+ yield obj
258
+
259
+
260
+ def split_macro(source):
261
+ """Split macro code into a list of commands."""
262
+ comments = re.compile(r'(?<!\\)(\".*?\"|\'.*?\')|(#[^\r\n]*$)', re.MULTILINE)
263
+ pattern = re.compile(r'(\$!.*?)(?=\$!)|(\$!.*)', re.MULTILINE | re.DOTALL)
264
+ source = comments.sub(lambda m: m.group(1) or '', source)
265
+ for match in pattern.finditer(source):
266
+ yield (match.group(1) or match.group(2)).strip()
267
+
268
+
269
+ def normalize_path(nodepath):
270
+ """Convert relative paths to absolute and normalize.
271
+
272
+ Always use Python's current working directory to convert to absolute paths.
273
+ However, relative paths are disallowed when connected to a non-local
274
+ instance of the TecUtil Server.
275
+ """
276
+ if nodepath is not None:
277
+ nodepath = str(nodepath)
278
+ from tecplot.tecutil import _tecutil_connector
279
+ if _tecutil_connector.connected:
280
+ if _tecutil_connector.client.host not in ['localhost', '127.0.0.1']:
281
+ if not os.path.isabs(nodepath):
282
+ msg = 'paths must be absolute when connected to Tecplot 360'
283
+ raise TecplotLogicError(msg)
284
+ return os.path.abspath(nodepath)
285
+
286
+
287
+ @contextlib.contextmanager
288
+ def temporary_closed_file(suffix=None):
289
+ """A named temporary file that has been created and closed.
290
+
291
+ The file will be removed on exit of the context.
292
+ """
293
+ ftmp = tempfile.NamedTemporaryFile(suffix=suffix, delete=False)
294
+ try:
295
+ ftmp.close()
296
+ yield ftmp.name
297
+ finally:
298
+ try:
299
+ os.remove(ftmp.name)
300
+ except OSError as e:
301
+ msg = 'Temp file I/O error: {}'.format(e)
302
+ warnings.warn(msg)
303
+
304
+
305
+ def api_changed(msg, version_changed, sdk_version_changed, warning=False):
306
+ msg = textwrap.dedent('''\
307
+ PyTecplot API Change (version {})
308
+ Tecplot 360 version: {}
309
+ {}
310
+ ''').format(version_changed, sdk_version_changed, textwrap.fill(msg))
311
+ if warning:
312
+ if __debug__:
313
+ msg += 'Please update your code as the legacy interface will\n' \
314
+ + 'be removed in the next major release of PyTecplot.'
315
+ warnings.warn(msg, TecplotFutureWarning)
316
+ else:
317
+ raise TecplotInterfaceChangeError(msg)
318
+
319
+
320
+ def api_moved(old, new, version_changed, sdk_version_changed, warning=False):
321
+ msg = textwrap.dedent('''\
322
+ PyTecplot API Change (version {})
323
+ Tecplot 360 version: {}
324
+ {} has been moved to {}
325
+ ''').format(version_changed, sdk_version_changed, old, new)
326
+ if warning:
327
+ if __debug__:
328
+ msg += 'Please update your code as the legacy interface will\n' \
329
+ + 'be removed in the next major release of PyTecplot.'
330
+ warnings.warn(msg, TecplotFutureWarning)
331
+ else:
332
+ raise TecplotInterfaceChangeError(msg)
@@ -0,0 +1,3 @@
1
+ from .font import BaseFont, Font, LegendFont
2
+ from .textbox import TextBox
3
+ from .label_format import LabelFormat
tecplot/text/font.py ADDED
@@ -0,0 +1,224 @@
1
+ from builtins import str, super
2
+
3
+ from ..exception import *
4
+ from .. import constant, session
5
+ from ..tecutil import sv
6
+
7
+
8
+ class Font(session.Style):
9
+ """Style of text objects such as titles and labels.
10
+
11
+ This class controls the typeface and size of various text objects found
12
+ in plots and axes:
13
+
14
+ .. code-block:: python
15
+ :emphasize-lines: 26-30
16
+
17
+ from os import path
18
+ import tecplot as tp
19
+ from tecplot.constant import PlotType, Units, AxisTitleMode
20
+
21
+ examples_dir = tp.session.tecplot_examples_directory()
22
+ infile = path.join(examples_dir, 'OneraM6wing', 'OneraM6_SU2_RANS.plt')
23
+ dataset = tp.data.load_tecplot(infile)
24
+
25
+ frame = tp.active_frame()
26
+ plot = frame.plot(PlotType.Cartesian2D)
27
+ plot.activate()
28
+
29
+ plot.show_contour = True
30
+
31
+ xaxis = plot.axes.x_axis
32
+ xaxis.title.title_mode = AxisTitleMode.UseText
33
+ xaxis.title.text = 'Longitudinal (m)'
34
+ xaxis.min, xaxis.max = 0, 1.2
35
+
36
+ yaxis = plot.axes.y_axis
37
+ yaxis.title.title_mode = AxisTitleMode.UseText
38
+ yaxis.title.text = 'Transverse (m)'
39
+ yaxis.min, yaxis.max = 0, 1.3
40
+
41
+ for ax in [xaxis, yaxis]:
42
+ ax.title.font.typeface = 'Times'
43
+ ax.title.font.bold = False
44
+ ax.title.font.italic = True
45
+ ax.title.font.size_units = Units.Frame
46
+ ax.title.font.size = 7
47
+
48
+ # ensure consistent output between interactive (connected) and batch
49
+ plot.contour(0).levels.reset_to_nice()
50
+
51
+ tp.export.save_png('font.png', 600, supersample=3)
52
+
53
+ .. figure:: /_static/images/font.png
54
+ :width: 300px
55
+ :figwidth: 300px
56
+ """
57
+ def __init__(self, parent, sv_textshape=sv.TEXTSHAPE):
58
+ self.parent = parent
59
+ super().__init__(parent._sv, sv_textshape, **parent._kw)
60
+
61
+ @property
62
+ def bold(self):
63
+ """`bool`: Use the bold version of the current typeface.
64
+
65
+ Example::
66
+
67
+ >>> axis.title.font.bold = True
68
+ """
69
+ return self._get_style(bool, sv.ISBOLD)
70
+
71
+ @bold.setter
72
+ def bold(self, value):
73
+ self._set_style(bool(value), sv.ISBOLD)
74
+
75
+ @property
76
+ def italic(self):
77
+ """`bool`: Use the italic version of the current typeface.
78
+
79
+ Example::
80
+
81
+ >>> axis.title.font.italic = True
82
+ """
83
+ return self._get_style(bool, sv.ISITALIC)
84
+
85
+ @italic.setter
86
+ def italic(self, value):
87
+ self._set_style(bool(value), sv.ISITALIC)
88
+
89
+ @property
90
+ def size(self):
91
+ """`float`: Height of the font. in units of `Font.size_units`.
92
+
93
+ Example usage::
94
+
95
+ >>> axis.title.font.size = 10
96
+ """
97
+ return self._get_style(float, sv.HEIGHT)
98
+
99
+ @size.setter
100
+ def size(self, value):
101
+ self._set_style(float(value), sv.HEIGHT)
102
+
103
+ @property
104
+ def size_units(self):
105
+ """`constant.Units`: Used by the size attribute.
106
+
107
+ Possible values: `Units.Point`, `Units.Frame` (percentage of frame
108
+ height). This example sets the axis title to 10% of the frame height::
109
+
110
+ >>> from tecplot.constant import Units
111
+ >>> axis.title.font.size_units = Units.Frame
112
+ >>> axis.title.font.size = 10
113
+ """
114
+ return self._get_style(constant.Units, sv.SIZEUNITS)
115
+
116
+ @size_units.setter
117
+ def size_units(self, value):
118
+ size = self.size
119
+ self._set_style(constant.Units(value), sv.SIZEUNITS)
120
+ self.size = size
121
+
122
+ @property
123
+ def typeface(self):
124
+ """`str`: Specific font (or typeface) to use for text.
125
+
126
+ This can be any font installed on the current system. If the font is
127
+ not found, Times or Helvetica will be used when rendering the text.
128
+ Example usage::
129
+
130
+ >>> axis.title.font.typeface = 'Times'
131
+ """
132
+ return self._get_style(str, sv.FONTFAMILY)
133
+
134
+ @typeface.setter
135
+ def typeface(self, value):
136
+ self._set_style(str(value), sv.FONTFAMILY)
137
+
138
+
139
+ class BaseFont(session.Style):
140
+ """Plot-level or scatter font style fall-back settings.
141
+
142
+ .. note::
143
+ Base fonts are accessible directly from line plots
144
+ (`XYLinePlot.base_font`, `PolarLinePlot.base_font`)::
145
+
146
+ >>> frame.plot(PlotType.XYLine).base_font
147
+
148
+ and the scatter style of field plots (`Scatter.base_font`)::
149
+
150
+ >>> frame.plot(PlotType.Cartesian3D).scatter.base_font
151
+ """
152
+ @property
153
+ def typeface(self):
154
+ """`str`: Specific font (or typeface) to use for text.
155
+
156
+ This can be any font installed on the current system. If the font is
157
+ not found, Times or Helvetica will be used when rendering the text.
158
+ Example usage::
159
+
160
+ >>> line_plot.base_font.typeface = 'Times'
161
+ >>> field_plot.scatter.base_font.typeface = 'Times'
162
+ """
163
+ return self._get_style(str, sv.BASEFONTFAMILY)
164
+
165
+ @typeface.setter
166
+ def typeface(self, value):
167
+ self._set_style(str(value), sv.BASEFONTFAMILY)
168
+
169
+ @property
170
+ def bold(self):
171
+ """`bool`: Use the bold version of the current typeface.
172
+
173
+ Example::
174
+
175
+ >>> line_plot.base_font.bold = True
176
+ >>> field_plot.scatter.base_font.bold = True
177
+ """
178
+ return self._get_style(bool, sv.BASEFONTISBOLD)
179
+
180
+ @bold.setter
181
+ def bold(self, value):
182
+ self._set_style(bool(value), sv.BASEFONTISBOLD)
183
+
184
+ @property
185
+ def italic(self):
186
+ """`bool`: Use the italic version of the current typeface.
187
+
188
+ Example::
189
+
190
+ >>> line_plot.base_font.italic = True
191
+ >>> field_plot.scatter.base_font.italic = True
192
+ """
193
+ return self._get_style(bool, sv.BASEFONTISITALIC)
194
+
195
+ @italic.setter
196
+ def italic(self, value):
197
+ self._set_style(bool(value), sv.BASEFONTISITALIC)
198
+
199
+
200
+ class LegendFont(Font):
201
+ """`LegendFont` is a font that restricts the setting of size_units."""
202
+
203
+ @property
204
+ def size_units(self):
205
+ """`Units <constant.Units>`: Units used by the size attribute.
206
+
207
+ Possible values: `Units.Point`, `Units.Frame` (percentage of frame
208
+ height). This example sets the axis title to 10% of the frame height::
209
+
210
+ >>> legend.font.size_units = Units.Frame
211
+ >>> legend.font.size = 10
212
+ """
213
+ return self._get_style(constant.Units, sv.SIZEUNITS)
214
+
215
+ @size_units.setter
216
+ def size_units(self, value):
217
+ value = constant.Units(value)
218
+ if __debug__:
219
+ if value not in (constant.Units.Frame, constant.Units.Point):
220
+ msg = '''\
221
+ Legend font size units must be one of:
222
+ Units.Frame, Units.Point'''
223
+ raise TecplotValueError(msg)
224
+ self._set_style(value, sv.SIZEUNITS)