ansys-pyensight-core 0.11.0__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 (37) hide show
  1. ansys/pyensight/core/__init__.py +41 -0
  2. ansys/pyensight/core/common.py +341 -0
  3. ansys/pyensight/core/deep_pixel_view.html +98 -0
  4. ansys/pyensight/core/dockerlauncher.py +1124 -0
  5. ansys/pyensight/core/dvs.py +872 -0
  6. ansys/pyensight/core/enscontext.py +345 -0
  7. ansys/pyensight/core/enshell_grpc.py +641 -0
  8. ansys/pyensight/core/ensight_grpc.py +874 -0
  9. ansys/pyensight/core/ensobj.py +515 -0
  10. ansys/pyensight/core/launch_ensight.py +296 -0
  11. ansys/pyensight/core/launcher.py +388 -0
  12. ansys/pyensight/core/libuserd.py +2110 -0
  13. ansys/pyensight/core/listobj.py +280 -0
  14. ansys/pyensight/core/locallauncher.py +579 -0
  15. ansys/pyensight/core/py.typed +0 -0
  16. ansys/pyensight/core/renderable.py +880 -0
  17. ansys/pyensight/core/session.py +1923 -0
  18. ansys/pyensight/core/sgeo_poll.html +24 -0
  19. ansys/pyensight/core/utils/__init__.py +21 -0
  20. ansys/pyensight/core/utils/adr.py +111 -0
  21. ansys/pyensight/core/utils/dsg_server.py +1220 -0
  22. ansys/pyensight/core/utils/export.py +606 -0
  23. ansys/pyensight/core/utils/omniverse.py +769 -0
  24. ansys/pyensight/core/utils/omniverse_cli.py +614 -0
  25. ansys/pyensight/core/utils/omniverse_dsg_server.py +1196 -0
  26. ansys/pyensight/core/utils/omniverse_glb_server.py +848 -0
  27. ansys/pyensight/core/utils/parts.py +1221 -0
  28. ansys/pyensight/core/utils/query.py +487 -0
  29. ansys/pyensight/core/utils/readers.py +300 -0
  30. ansys/pyensight/core/utils/resources/Materials/000_sky.exr +0 -0
  31. ansys/pyensight/core/utils/support.py +128 -0
  32. ansys/pyensight/core/utils/variables.py +2019 -0
  33. ansys/pyensight/core/utils/views.py +674 -0
  34. ansys_pyensight_core-0.11.0.dist-info/METADATA +309 -0
  35. ansys_pyensight_core-0.11.0.dist-info/RECORD +37 -0
  36. ansys_pyensight_core-0.11.0.dist-info/WHEEL +4 -0
  37. ansys_pyensight_core-0.11.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,487 @@
1
+ # Copyright (C) 2022 - 2026 ANSYS, Inc. and/or its affiliates.
2
+ # SPDX-License-Identifier: MIT
3
+ #
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ from typing import TYPE_CHECKING, Any, List, Optional, Union
24
+
25
+ if TYPE_CHECKING:
26
+ try:
27
+ import ensight
28
+ from ensight.objs import ENS_QUERY # type: ignore
29
+ except ImportError:
30
+ from ansys.api.pyensight import ensight_api
31
+ from ansys.api.pyensight.ens_query import ENS_QUERY
32
+
33
+
34
+ class Query:
35
+ """Provides the ``ensight.utils.query`` interface.
36
+
37
+ The methods in this class implement simplified interfaces to common
38
+ query-orientated operations, such as creating a temporal or temporal query.
39
+
40
+ This class is instantiated as ``ensight.utils.query`` in EnSight Python
41
+ and as ``Session.ensight.utils.query`` in PyEnSight. The constructor is
42
+ passed the interface, which serves as the ``ensight`` module for either
43
+ case. As a result, the methods can be accessed as ``ensight.utils.query.create_distance()``
44
+ in EnSight Python or ``session.ensight.utils.query.create_distance()`` in PyEnSight.
45
+
46
+ Parameters
47
+ ----------
48
+ interface :
49
+ Entity that provides the ``ensight`` namespace. In the case of
50
+ EnSight Python, the ``ensight`` module is passed. In the case
51
+ of PyEnSight, ``Session.ensight`` is passed.
52
+ """
53
+
54
+ def __init__(self, interface: Union["ensight_api.ensight", "ensight"]):
55
+ self._ensight = interface
56
+
57
+ DISTANCE_PART1D: str = "1d_part"
58
+ DISTANCE_LINE: str = "line_tool"
59
+ DISTANCE_SPLINE: str = "spline"
60
+
61
+ DIST_TYPE_LENGTH: str = "arc_length"
62
+ DIST_TYPE_LENGTH_X: str = "x_arc_length"
63
+ DIST_TYPE_LENGTH_Y: str = "y_arc_length"
64
+ DIST_TYPE_LENGTH_Z: str = "z_arc_length"
65
+ DIST_TYPE_ORIGIN: str = "from_origin"
66
+ DIST_TYPE_ORIGIN_X: str = "x_from_origin"
67
+ DIST_TYPE_ORIGIN_Y: str = "y_from_origin"
68
+ DIST_TYPE_ORIGIN_Z: str = "z_from_origin"
69
+
70
+ DIST_SEG_ACCUMULATION: str = "accumulation"
71
+ DIST_SEG_RESET_EACH: str = "reset_each"
72
+
73
+ def create_distance(
74
+ self,
75
+ name: str,
76
+ query_type: str,
77
+ part_list: List[Any],
78
+ variable1: Any,
79
+ variable2: Optional[Any] = None,
80
+ num_samples: int = 20,
81
+ point1: Optional[List[float]] = None,
82
+ point2: Optional[List[float]] = None,
83
+ distance_type: str = DIST_TYPE_LENGTH,
84
+ segments_by: str = DIST_SEG_ACCUMULATION,
85
+ spline_name: Optional[str] = None,
86
+ new_plotter: bool = False,
87
+ ) -> "ENS_QUERY":
88
+ """Create an EnSight query over a distance object.
89
+
90
+ Create an EnSight distance query using the passed parameters. Return
91
+ the newly generated ``ENS_QUERY`` object.
92
+
93
+ Parameters
94
+ ----------
95
+ name : str
96
+ Name for the query.
97
+ query_type : str
98
+ Type of the query. This table describes the options:
99
+
100
+ ================== ========================================
101
+ Name Query type
102
+ ================== ========================================
103
+ DISTANCE_PART1D Samples along the points of a 1D part
104
+ DISTANCE_LINE Samples along the length of a line
105
+ DISTANCE_SPLINE Samples along the length of a spline
106
+ ================== ========================================
107
+
108
+
109
+ part_list: list
110
+ List of parts to use as the source for the query. Part numbers,
111
+ part names, and part objects are supported.
112
+ variable1 :
113
+ Variable to sample as the "y" value.
114
+ variable2 : optional
115
+ Variable to sample as the "x" value. The default is ``None``,
116
+ in which case the "x" value is the distance along the sampling
117
+ domain.
118
+ num_samples : int, optional
119
+ For a spline or line query, the number of samples to use along
120
+ the length of the spline or line. The default is ``20``.
121
+ point1 : list[float], optional
122
+ For a line query, the ``x,y,z`` location of the start of the line.
123
+ The default is ``None``.
124
+ point2: : list[float], optional
125
+ For a line query, the x,y,z location of the end of the line.
126
+ The default is ``None``.
127
+ distance_type : str, optional
128
+ For a query over a distance (no second variable), how to compute
129
+ distance. The default is ``"arc_length"``, in which case
130
+ ``DIST-TYPE_LENGTH_X`` is used. This table describes
131
+ the options:
132
+
133
+ =================== =========================================
134
+ Name Query type
135
+ =================== =========================================
136
+ DIST_TYPE_LENGTH Length along path
137
+ DIST_TYPE_LENGTH_X X component along path
138
+ DIST_TYPE_LENGTH_Y Y component along path
139
+ DIST_TYPE_LENGTH_Z Z component along path
140
+ DIST_TYPE_ORIGIN Distance from the origin
141
+ DIST_TYPE_ORIGIN_X X component of distance from the origin
142
+ DIST_TYPE_ORIGIN_Y Y component of distance from the origin
143
+ DIST_TYPE_ORIGIN_Z Z component of distance from the origin
144
+ =================== =========================================
145
+
146
+
147
+ segments_by : str, optional
148
+ For a 1D part query, how to compute distance for the
149
+ segments of the 1D part. The default is ``"accumulation"``,
150
+ in which case ``DIST_SEG_ACCUMULATION`` is used.
151
+ This table describes the options:
152
+
153
+ ====================== ==========================================
154
+ Name Segment handling
155
+ ====================== ==========================================
156
+ DIST_SEG_ACCUMULATION Accumulate distance over segments
157
+ DIST_SEG_RESET_EACH Reset the distance value for each segment
158
+ ====================== ==========================================
159
+
160
+
161
+ spline_name : str, optional
162
+ For a spline query, the name of the spline to sample along. The
163
+ default is ``None``.
164
+ new_plotter : bool, optional
165
+ Whether to add the query to a newly created plotter. The default is
166
+ ``False``.
167
+
168
+ Returns
169
+ -------
170
+ ENS_QUERY
171
+ ``ENS_QUERY`` instance on success or raises an exception on error.
172
+
173
+ Examples
174
+ --------
175
+ >>> s = LocalLauncher().start()
176
+ >>> s.load_data(f"{s.cei_home}/ensight{s.cei_suffix}/data/cube/cube.case")
177
+ >>> parts = s.ensight.objs.core.PARTS["Computational mesh"]
178
+ >>> pnt1 = [-1.0, 0.5, 1.0]
179
+ >>> pnt2 = [2.0, 0.5, 1.0]
180
+ >>> query = s.ensight.utils.query.create_distance("Temperature vs Distance",
181
+ >>> s.ensight.utils.query.DISTANCE_LINE, parts, "temperature",
182
+ >>> point1=pnt1, point2=pnt2, new_plotter=True)
183
+
184
+ """
185
+ if query_type not in [
186
+ self.DISTANCE_PART1D,
187
+ self.DISTANCE_LINE,
188
+ self.DISTANCE_SPLINE,
189
+ ]: # pragma: no cover
190
+ raise RuntimeError(f"Invalid query type: {query_type} specified.") # pragma: no cover
191
+
192
+ var1 = self._get_variable(variable1)
193
+ var2 = self._get_variable(variable2, "DISTANCE")
194
+
195
+ if query_type == self.DISTANCE_LINE:
196
+ if (point1 is None) or (point2 is None): # pragma: no cover
197
+ raise RuntimeError("Both point1 and point2 must be specified.") # pragma: no cover
198
+ self._create_query_core_begin(name, part_list)
199
+ self._ensight.query_ent_var.number_of_sample_pts(num_samples)
200
+ self._ensight.query_ent_var.constrain("line_tool")
201
+ self._ensight.query_ent_var.line_loc(1, *point1)
202
+ self._ensight.query_ent_var.line_loc(2, *point2)
203
+
204
+ elif query_type == self.DISTANCE_PART1D: # pragma: no cover
205
+ self._create_query_core_begin(name, part_list, single=True)
206
+ self._ensight.query_ent_var.constrain("1d_part")
207
+ self._ensight.query_ent_var.multiple_segments_by(segments_by)
208
+
209
+ elif query_type == self.DISTANCE_SPLINE: # pragma: no cover
210
+ if spline_name is None:
211
+ raise RuntimeError("A spline_name must be specified.")
212
+ self._create_query_core_begin(name, part_list)
213
+ self._ensight.query_ent_var.number_of_sample_pts(num_samples)
214
+ self._ensight.query_ent_var.constrain("spline")
215
+ self._ensight.query_ent_var.spline_name(spline_name)
216
+
217
+ self._ensight.query_ent_var.distance(distance_type)
218
+ self._ensight.query_ent_var.variable_1(var1)
219
+ self._ensight.query_ent_var.generate_over("distance")
220
+ self._ensight.query_ent_var.variable_2(var2)
221
+
222
+ query = self._create_query_core_end()
223
+ if new_plotter:
224
+ plot = self._ensight.objs.core.DEFAULTPLOT[0].createplotter()
225
+ query.addtoplot(plot)
226
+ return query
227
+
228
+ TEMPORAL_NODE: str = "node"
229
+ TEMPORAL_ELEMENT: str = "element"
230
+ TEMPORAL_IJK: str = "ijk"
231
+ TEMPORAL_XYZ: str = "cursor"
232
+ TEMPORAL_MINIMUM: str = "min"
233
+ TEMPORAL_MAXIMUM: str = "max"
234
+
235
+ def create_temporal(
236
+ self,
237
+ name: str,
238
+ query_type: str,
239
+ part_list: List[Any],
240
+ variable1: Any,
241
+ variable2: Optional[Any] = None,
242
+ start_time: Optional[float] = None,
243
+ end_time: Optional[float] = None,
244
+ num_samples: Optional[int] = None,
245
+ node_id: Optional[int] = None,
246
+ element_id: Optional[int] = None,
247
+ xyz: Optional[List[float]] = None,
248
+ ijk: Optional[List[int]] = None,
249
+ new_plotter: bool = False,
250
+ ) -> "ENS_QUERY":
251
+ """Create an EnSight query over time.
252
+
253
+ Parameters
254
+ ----------
255
+ name : str
256
+ Name for the query.
257
+ query_type:
258
+ Type of the query. Descriptions of options follow.
259
+
260
+ ================= =========================================================
261
+ Name Query type
262
+ ================= =========================================================
263
+ TEMPORAL_NODE At a node number over time
264
+ TEMPORAL_ELEMENT At an element number over time
265
+ TEMPORAL_IJK At an ijk element over time
266
+ TEMPORAL_XYZ At some x,y,z location over time
267
+ TEMPORAL_MINIMUM Minimum value on the selected parts at each point in time
268
+ TEMPORAL_MAXIMUM Maximum value on the selected parts at each point in time
269
+ ================= =========================================================
270
+
271
+
272
+ part_list : list
273
+ List of parts to use as the source for the query.
274
+ variable1 :
275
+ Variable to sample as the "y" value.
276
+ variable2 : optional
277
+ Variable to sample as the "x" value. The default is ``None``, in which
278
+ case the "x" value is the distance along the sampling domain.
279
+ start_time : float, optional
280
+ Simulation time to start sampling at. The default is ``None``, in which
281
+ case the first timestep, ``ENS_GLOBALS.SOLUTIONTIME_LIMITS[0]``, is used.
282
+ end_time : float, optional
283
+ The simulation time to end sampling at. The default is ``None``, in which
284
+ case the last timestep, ``ENS_GLOBALS.SOLUTIONTIME_LIMITS[1]``, is used.
285
+ num_samples : int, optional
286
+ Number of samples to take along the selected timestep range. The default
287
+ is ``None``, in which case the number of defined timesteps,
288
+ ``ENS_GLOBALS.TIMESTEP_LIMITS[1] - ENS_GLOBALS.TIMESTEP_LIMITS[0] + 1``,
289
+ is used.
290
+ node_id : int, optional
291
+ For a ``TEMPORAL_NODE`` query, the ID of the node to query. The default is
292
+ ``None``.
293
+ element_id : int, optional
294
+ For a ``TEMPORAL_ELEMENT`` query, the ID of the element to query. The
295
+ default is ``None``.
296
+ xyz : list[float], optional
297
+ For a ``TEMPORRAL_XYZ`` query, the ``[x,y,z]`` location in data space
298
+ to query. The default is ``None``.
299
+ ijk : list[int], optional
300
+ For a ``TEMPORAL_IJK`` query, the ``[i,j,k]`` value for the structured
301
+ mesh node to query. The default is ``None``.
302
+ new_plotter : bool, optional
303
+ Whether to add the query to a newly created plotter. The default is
304
+ ``False``.
305
+
306
+ Returns
307
+ -------
308
+ ENS_QUERY
309
+ ````ENS_QUERY`` instance on success or raises an exception on error.
310
+
311
+ Examples
312
+ --------
313
+ >>> s = LocalLauncher().start()
314
+ >>> s.load_data(f"{s.cei_home}/ensight{s.cei_suffix}/data/guard_rail/crash.case")
315
+ >>> parts = s.ensight.objs.core.PARTS
316
+ >>> s.ensight.utils.query.create_temporal("Maximum plastic",
317
+ >>> s.ensight.utils.query.TEMPORAL_MAXIMUM, parts, "plastic", new_plotter=True)
318
+
319
+ """
320
+ if query_type not in [ # pragma: no cover
321
+ self.TEMPORAL_NODE,
322
+ self.TEMPORAL_ELEMENT,
323
+ self.TEMPORAL_IJK,
324
+ self.TEMPORAL_XYZ,
325
+ self.TEMPORAL_MINIMUM,
326
+ self.TEMPORAL_MAXIMUM,
327
+ ]:
328
+ raise RuntimeError(f"Invalid query type: {query_type} specified.") # pragma: no cover
329
+
330
+ var1 = self._get_variable(variable1)
331
+ var2 = self._get_variable(variable2, "TIME")
332
+
333
+ # default the time range
334
+ if start_time is None: # pragma: no cover
335
+ start_time = self._ensight.objs.core.SOLUTIONTIME_LIMITS[0]
336
+ if end_time is None: # pragma: no cover
337
+ end_time = self._ensight.objs.core.SOLUTIONTIME_LIMITS[1]
338
+
339
+ # default the number of timesteps
340
+ if num_samples is None: # pragma: no cover
341
+ num_samples = (
342
+ self._ensight.objs.core.TIMESTEP_LIMITS[1]
343
+ - self._ensight.objs.core.TIMESTEP_LIMITS[0]
344
+ + 1
345
+ )
346
+
347
+ if query_type == self.TEMPORAL_NODE:
348
+ if node_id is None: # pragma: no cover
349
+ raise RuntimeError("node_id must be specified.") # pragma: no cover
350
+ self._create_query_core_begin(name, part_list)
351
+ self._ensight.query_ent_var.constrain("node")
352
+ self._ensight.query_ent_var.node_id(node_id)
353
+
354
+ elif query_type == self.TEMPORAL_ELEMENT:
355
+ if element_id is None: # pragma: no cover
356
+ raise RuntimeError("element_id must be specified.") # pragma: no cover
357
+ self._create_query_core_begin(name, part_list)
358
+ self._ensight.query_ent_var.constrain("element")
359
+ self._ensight.query_ent_var.elem_id(element_id)
360
+
361
+ elif query_type == self.TEMPORAL_XYZ:
362
+ if xyz is None: # pragma: no cover
363
+ raise RuntimeError("xyz must be specified.") # pragma: no cover
364
+ self._create_query_core_begin(name, part_list)
365
+ self._ensight.query_ent_var.constrain("cursor")
366
+ self._ensight.query_ent_var.cursor_loc(*xyz)
367
+
368
+ elif query_type == self.TEMPORAL_IJK:
369
+ if ijk is None: # pragma: no cover
370
+ raise RuntimeError("ijk must be specified.") # pragma: no cover
371
+ self._create_query_core_begin(name, part_list) # pragma: no cover
372
+ self._ensight.query_ent_var.constrain("ijk") # pragma: no cover
373
+ self._ensight.query_ent_var.ijk(*ijk) # pragma: no cover
374
+
375
+ elif query_type == self.TEMPORAL_MINIMUM:
376
+ self._create_query_core_begin(name, part_list)
377
+ self._ensight.query_ent_var.constrain("min")
378
+
379
+ elif query_type == self.TEMPORAL_MAXIMUM: # pragma: no cover
380
+ self._create_query_core_begin(name, part_list)
381
+ self._ensight.query_ent_var.constrain("max")
382
+
383
+ self._ensight.query_ent_var.number_of_sample_pts(num_samples)
384
+ self._ensight.query_ent_var.begin_simtime(start_time)
385
+ self._ensight.query_ent_var.end_simtime(end_time)
386
+ self._ensight.query_ent_var.sample_by("value")
387
+ self._ensight.query_ent_var.update_with_newtimesteps("ON")
388
+ self._ensight.query_ent_var.variable_1(var1)
389
+ self._ensight.query_ent_var.generate_over("time")
390
+ self._ensight.query_ent_var.variable_2(var2)
391
+
392
+ query = self._create_query_core_end()
393
+ if new_plotter:
394
+ plot = self._ensight.objs.core.DEFAULTPLOT[0].createplotter()
395
+ query.addtoplot(plot)
396
+ return query
397
+
398
+ def _create_query_core_end(self) -> "ENS_QUERY":
399
+ """Complete a query operation.
400
+
401
+ Execute the "end()" and "query()" calls to finalize the query. Return the latest
402
+ ENS_QUERY object.
403
+
404
+ Returns
405
+ -------
406
+ "ENS_QUERY"
407
+ The last created ENS_QUERY object or raise an exception if query creation fails.
408
+
409
+ """
410
+ nextid = self._ensight.objs.next_id()
411
+ self._ensight.query_ent_var.end()
412
+ self._ensight.query_ent_var.query()
413
+ error_msg = None
414
+ try:
415
+ query = max(self._ensight.objs.core.QUERIES)
416
+ # no new id allocated
417
+ if query.__OBJID__ < nextid: # pragma: no cover
418
+ error_msg = "Unable to create the specified query." # pragma: no cover
419
+ except ValueError: # pragma: no cover
420
+ error_msg = "Unable to create the specified query." # pragma: no cover
421
+ if error_msg: # pragma: no cover
422
+ raise RuntimeError(error_msg) # pragma: no cover
423
+ return query
424
+
425
+ def _create_query_core_begin(self, name: str, parts: Optional[List[int]], single=False) -> None:
426
+ """Common query setup
427
+
428
+ Make the common calls for all queries. Select the appropriate source parts, set the
429
+ query name and "generated" type.
430
+
431
+ Parameters
432
+ ----------
433
+ name : str
434
+ The name for the query.
435
+ parts : List
436
+ The list of source parts for the query.
437
+ single : bool
438
+ If true, then this is a 1D part query and emit the appropriate output. Otherwise,
439
+ ensure that the proper parts are selected. (Default value = False)
440
+
441
+ """
442
+ part_list = []
443
+ if parts: # pragma: no cover
444
+ for p in parts:
445
+ if type(p) == str: # pragma: no cover
446
+ part_list.append(
447
+ self._ensight.objs.core.PARTS[p][0].PARTNUMBER
448
+ ) # pragma: no cover
449
+ elif type(p) == int: # pragma: no cover
450
+ part_list.append(p) # pragma: no cover
451
+ else:
452
+ if hasattr(p, "PARTNUMBER"): # pragma: no cover
453
+ part_list.append(p.PARTNUMBER)
454
+ if not single:
455
+ self._ensight.part.select_begin(part_list)
456
+ self._ensight.query_ent_var.begin()
457
+ self._ensight.query_ent_var.description(name)
458
+ self._ensight.query_ent_var.query_type("generated")
459
+ if single:
460
+ self._ensight.query_ent_var.part_id(part_list[0])
461
+
462
+ def _get_variable(self, v: Any, default: Optional[str] = None) -> Optional[str]:
463
+ """Convert a generic argument into a variable name string
464
+
465
+ Convert a generic object into a variable name. Valid inputs
466
+ include a string or an ENS_VARIABLE object.
467
+
468
+ Parameters
469
+ ----------
470
+ v: Any
471
+ The object to be converted into a variable name.
472
+ default: str, optional
473
+ The value to return if the input variable is None.
474
+
475
+ Returns
476
+ -------
477
+ The string name of the variable or None.
478
+
479
+ """
480
+ if v is None:
481
+ return default
482
+ elif type(v) is str:
483
+ if v not in self._ensight.objs.core.VARIABLES.get_attr("DESCRIPTION"):
484
+ raise ValueError("The variable supplied does not exist.")
485
+ return v
486
+ else:
487
+ return v.DESCRIPTION