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.
- ansys/pyensight/core/__init__.py +41 -0
- ansys/pyensight/core/common.py +341 -0
- ansys/pyensight/core/deep_pixel_view.html +98 -0
- ansys/pyensight/core/dockerlauncher.py +1124 -0
- ansys/pyensight/core/dvs.py +872 -0
- ansys/pyensight/core/enscontext.py +345 -0
- ansys/pyensight/core/enshell_grpc.py +641 -0
- ansys/pyensight/core/ensight_grpc.py +874 -0
- ansys/pyensight/core/ensobj.py +515 -0
- ansys/pyensight/core/launch_ensight.py +296 -0
- ansys/pyensight/core/launcher.py +388 -0
- ansys/pyensight/core/libuserd.py +2110 -0
- ansys/pyensight/core/listobj.py +280 -0
- ansys/pyensight/core/locallauncher.py +579 -0
- ansys/pyensight/core/py.typed +0 -0
- ansys/pyensight/core/renderable.py +880 -0
- ansys/pyensight/core/session.py +1923 -0
- ansys/pyensight/core/sgeo_poll.html +24 -0
- ansys/pyensight/core/utils/__init__.py +21 -0
- ansys/pyensight/core/utils/adr.py +111 -0
- ansys/pyensight/core/utils/dsg_server.py +1220 -0
- ansys/pyensight/core/utils/export.py +606 -0
- ansys/pyensight/core/utils/omniverse.py +769 -0
- ansys/pyensight/core/utils/omniverse_cli.py +614 -0
- ansys/pyensight/core/utils/omniverse_dsg_server.py +1196 -0
- ansys/pyensight/core/utils/omniverse_glb_server.py +848 -0
- ansys/pyensight/core/utils/parts.py +1221 -0
- ansys/pyensight/core/utils/query.py +487 -0
- ansys/pyensight/core/utils/readers.py +300 -0
- ansys/pyensight/core/utils/resources/Materials/000_sky.exr +0 -0
- ansys/pyensight/core/utils/support.py +128 -0
- ansys/pyensight/core/utils/variables.py +2019 -0
- ansys/pyensight/core/utils/views.py +674 -0
- ansys_pyensight_core-0.11.0.dist-info/METADATA +309 -0
- ansys_pyensight_core-0.11.0.dist-info/RECORD +37 -0
- ansys_pyensight_core-0.11.0.dist-info/WHEEL +4 -0
- ansys_pyensight_core-0.11.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,345 @@
|
|
|
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
|
+
"""EnsContext module
|
|
24
|
+
|
|
25
|
+
Interface to objects that contain a representation of an EnSight session state.
|
|
26
|
+
Three types of content are supported:
|
|
27
|
+
|
|
28
|
+
#. Full context: a complete EnSight context file.
|
|
29
|
+
#. Simple context: an EnSight context file without any data loading reference.
|
|
30
|
+
|
|
31
|
+
"""
|
|
32
|
+
import base64
|
|
33
|
+
import io
|
|
34
|
+
import os
|
|
35
|
+
import tempfile
|
|
36
|
+
from typing import Any, Optional, Union
|
|
37
|
+
import warnings
|
|
38
|
+
import zipfile
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class EnsContext:
|
|
42
|
+
"""A saved EnSight session state
|
|
43
|
+
|
|
44
|
+
This object allows for the generation and application of the
|
|
45
|
+
EnSight "state". The object may store a EnSight "context",
|
|
46
|
+
or a "data-less context" representation. The object can
|
|
47
|
+
save() and load() the context to/from disk.
|
|
48
|
+
|
|
49
|
+
Parameters
|
|
50
|
+
----------
|
|
51
|
+
filename : str, optional
|
|
52
|
+
If specified, "load()" the named context file after
|
|
53
|
+
creating the object instance.
|
|
54
|
+
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
_UNKNOWN: int = 0
|
|
58
|
+
_FULL_CONTEXT: int = 1
|
|
59
|
+
_SIMPLE_CONTEXT: int = 2
|
|
60
|
+
|
|
61
|
+
def __init__(self, filename: Optional[str] = None) -> None:
|
|
62
|
+
"""Initialized EnsContext."""
|
|
63
|
+
self._type: int = self._UNKNOWN
|
|
64
|
+
self._buffer: io.BytesIO = io.BytesIO()
|
|
65
|
+
if filename is not None:
|
|
66
|
+
self.load(filename)
|
|
67
|
+
|
|
68
|
+
def _set_type(self, names: list) -> None:
|
|
69
|
+
"""Update the 'type' of the context
|
|
70
|
+
|
|
71
|
+
Look though the file files stored in the zip file. Look for the special
|
|
72
|
+
embedded "type" files and set the object type accordingly.
|
|
73
|
+
|
|
74
|
+
Parameters
|
|
75
|
+
----------
|
|
76
|
+
names: list
|
|
77
|
+
A list of filenames in the zip file.
|
|
78
|
+
|
|
79
|
+
"""
|
|
80
|
+
self._type = self._UNKNOWN
|
|
81
|
+
if "fullcontext.txt" in names:
|
|
82
|
+
self._type = self._FULL_CONTEXT
|
|
83
|
+
elif "simplecontext.txt" in names:
|
|
84
|
+
self._type = self._SIMPLE_CONTEXT
|
|
85
|
+
|
|
86
|
+
def load(self, filename: str) -> None:
|
|
87
|
+
"""Read a context from a local zip file
|
|
88
|
+
|
|
89
|
+
Given the name of a context file, read it into memory and make it available
|
|
90
|
+
for use by the PyEnSight Session methods.
|
|
91
|
+
|
|
92
|
+
Parameters
|
|
93
|
+
----------
|
|
94
|
+
filename: str
|
|
95
|
+
The name of the file to read.
|
|
96
|
+
|
|
97
|
+
"""
|
|
98
|
+
if not zipfile.is_zipfile(filename):
|
|
99
|
+
raise RuntimeError(f"'{filename}' is not a saved context file.")
|
|
100
|
+
with open(filename, "rb") as f:
|
|
101
|
+
data = f.read()
|
|
102
|
+
self._from_data(data)
|
|
103
|
+
|
|
104
|
+
def _from_data(self, data: Union[bytes, str]) -> None:
|
|
105
|
+
"""Read a context from a blob or string
|
|
106
|
+
|
|
107
|
+
Given a context file in the form of a bytes object or a
|
|
108
|
+
the same bytes object encoded into a string using base64
|
|
109
|
+
encoding.
|
|
110
|
+
|
|
111
|
+
Parameters
|
|
112
|
+
----------
|
|
113
|
+
data: Union[bytes, str]
|
|
114
|
+
A bytes or string object of the contents of a
|
|
115
|
+
context zip file.
|
|
116
|
+
|
|
117
|
+
"""
|
|
118
|
+
if type(data) != bytes:
|
|
119
|
+
data = base64.b64decode(data)
|
|
120
|
+
self._buffer = io.BytesIO(data)
|
|
121
|
+
the_file = zipfile.ZipFile(self._buffer, "r")
|
|
122
|
+
self._set_type(the_file.namelist())
|
|
123
|
+
|
|
124
|
+
def save(self, filename: str) -> None:
|
|
125
|
+
"""Save the context information to a file
|
|
126
|
+
|
|
127
|
+
Save the current context to disk.
|
|
128
|
+
|
|
129
|
+
Parameters
|
|
130
|
+
----------
|
|
131
|
+
filename: str
|
|
132
|
+
Name of the file to save.
|
|
133
|
+
|
|
134
|
+
"""
|
|
135
|
+
data = self._buffer.getvalue()
|
|
136
|
+
if len(data) < 1: # pragma: no cover
|
|
137
|
+
raise RuntimeError("No context data to save") # pragma: no cover
|
|
138
|
+
with open(filename, "wb") as fp:
|
|
139
|
+
fp.write(data)
|
|
140
|
+
|
|
141
|
+
def _data(self, b64: bool = False) -> Union[bytes, str]:
|
|
142
|
+
"""Return a representation of the context file as a string or bytes object
|
|
143
|
+
|
|
144
|
+
Either a bytes object or a string (base64 encoded bytes object)
|
|
145
|
+
representation of the current context file is returned.
|
|
146
|
+
|
|
147
|
+
Parameters
|
|
148
|
+
----------
|
|
149
|
+
b64: bool
|
|
150
|
+
If True, return the bytes representation encoded into a string
|
|
151
|
+
object using base64 encoding. By default, false.
|
|
152
|
+
|
|
153
|
+
Returns
|
|
154
|
+
-------
|
|
155
|
+
Union[bytes, str]
|
|
156
|
+
A bytes object or a string object.
|
|
157
|
+
|
|
158
|
+
"""
|
|
159
|
+
data = self._buffer.getvalue()
|
|
160
|
+
if b64: # pragma: no cover
|
|
161
|
+
return base64.b64encode(data).decode("ascii")
|
|
162
|
+
return data # pragma: no cover
|
|
163
|
+
|
|
164
|
+
def _build_from_directory(self, pathname: str) -> None:
|
|
165
|
+
"""Create a zip object from the contents of a directory
|
|
166
|
+
|
|
167
|
+
Given a directory name, generate an in-memory zip file
|
|
168
|
+
containing all the files in the directory. A bytes/string
|
|
169
|
+
representation (suitable for use by from_zip_data()) can be
|
|
170
|
+
obtained using the data() method, following a from_directory
|
|
171
|
+
call.
|
|
172
|
+
|
|
173
|
+
Parameters
|
|
174
|
+
----------
|
|
175
|
+
pathname: str
|
|
176
|
+
The directory of filenames to be placed in the context
|
|
177
|
+
file.
|
|
178
|
+
"""
|
|
179
|
+
self._buffer = io.BytesIO()
|
|
180
|
+
the_file = zipfile.ZipFile(self._buffer, "w", compression=zipfile.ZIP_DEFLATED)
|
|
181
|
+
for folder_name, _, file_names in os.walk(pathname):
|
|
182
|
+
for filename in file_names:
|
|
183
|
+
file_pathname = os.path.join(folder_name, filename)
|
|
184
|
+
the_file.write(file_pathname, os.path.basename(file_pathname))
|
|
185
|
+
self._set_type(the_file.namelist())
|
|
186
|
+
the_file.close()
|
|
187
|
+
|
|
188
|
+
@staticmethod
|
|
189
|
+
def _fix_context_file(ctx_file: str) -> None:
|
|
190
|
+
"""Clean up a context file
|
|
191
|
+
|
|
192
|
+
Currently, there is a bug in the single case context file saving code
|
|
193
|
+
that puts information that cannot be recalled independently of other
|
|
194
|
+
cases in the .ctx file. Remove that information and rewrite the file.
|
|
195
|
+
|
|
196
|
+
Parameters
|
|
197
|
+
----------
|
|
198
|
+
ctx_file: str
|
|
199
|
+
The name of the context file to process.
|
|
200
|
+
"""
|
|
201
|
+
try:
|
|
202
|
+
with open(ctx_file, "rb") as f:
|
|
203
|
+
ctx = f.read()
|
|
204
|
+
try:
|
|
205
|
+
# Remove the Object MetaData block units, we do not want to restore them
|
|
206
|
+
# as they could change.
|
|
207
|
+
# These are the lines we need to remove:
|
|
208
|
+
# ensight.objs.core.VARIABLES.find('Pressure',
|
|
209
|
+
# attr="DESCRIPTION")[0].setmetatag('CFD_VAR','')
|
|
210
|
+
# ensight.objs.core.CURRENTCASE[0].setmetatag('ENS_UNITS_LABEL',2.000000)
|
|
211
|
+
# ensight.objs.core.CURRENTCASE[0].setmetatag('ENS_UNITS_DIMS',1.000000)
|
|
212
|
+
# ensight.objs.core.CURRENTCASE[0].setmetatag('ENS_UNITS_LABEL_TIME','s')
|
|
213
|
+
# ensight.objs.core.CURRENTCASE[0].setmetatag('ENS_UNITS_SYSTEM',1.000000)
|
|
214
|
+
# ensight.objs.core.CURRENTCASE[0].setmetatag('ENS_UNITS_SYSTEM_NAME','SI')
|
|
215
|
+
start = ctx.index(b"# Object MetaData commands")
|
|
216
|
+
end = ctx.index(b"# End Object MetaData commands")
|
|
217
|
+
if (start >= 0) and (end >= 0): # pragma: no cover
|
|
218
|
+
saved_lines = list()
|
|
219
|
+
for line in ctx[start:end].split(b"\n"):
|
|
220
|
+
skip = b".setmetatag('CFD_VAR'" in line
|
|
221
|
+
skip = skip or (b".setmetatag('ENS_UNITS_LABEL'" in line)
|
|
222
|
+
skip = skip or (b".setmetatag('ENS_UNITS_DIMS'" in line)
|
|
223
|
+
skip = skip or (b".setmetatag('ENS_UNITS_LABEL_TIME'" in line)
|
|
224
|
+
skip = skip or (b".setmetatag('ENS_UNITS_SYSTEM'" in line)
|
|
225
|
+
skip = skip or (b".setmetatag('ENS_UNITS_SYSTEM_NAME'" in line)
|
|
226
|
+
skip = skip and line.startswith(b"ensight.objs.core.")
|
|
227
|
+
if skip:
|
|
228
|
+
continue
|
|
229
|
+
saved_lines.append(line)
|
|
230
|
+
ctx = ctx[:start] + b"\n".join(saved_lines) + ctx[end:]
|
|
231
|
+
except ValueError: # pragma: no cover
|
|
232
|
+
warnings.warn("Note: Object Metadata block not found") # pragma: no cover
|
|
233
|
+
try:
|
|
234
|
+
# remove the Textures block (as the textures are not in the project)
|
|
235
|
+
start = ctx.index(b"# Textures")
|
|
236
|
+
end = ctx.index(b"# Attributes To Restore Viewport Defaults") # pragma: no cover
|
|
237
|
+
if (start >= 0) and (end >= 0): # pragma: no cover
|
|
238
|
+
ctx = ctx[:start] + ctx[end:] # pragma: no cover
|
|
239
|
+
except ValueError:
|
|
240
|
+
warnings.warn("Note: Object Metadata block not found")
|
|
241
|
+
# rewrite the file
|
|
242
|
+
with open(ctx_file, "wb") as f:
|
|
243
|
+
f.write(ctx)
|
|
244
|
+
except Exception as e:
|
|
245
|
+
warnings.warn("Unable to filter out undesired context file content: {}".format(e))
|
|
246
|
+
|
|
247
|
+
def _restore_context(self, ensight: Any) -> None:
|
|
248
|
+
"""Restore a context from the state in this object
|
|
249
|
+
|
|
250
|
+
Unpack the zip contents to disk (temporary directory) and perform a context restore on
|
|
251
|
+
the contents.
|
|
252
|
+
|
|
253
|
+
Parameters
|
|
254
|
+
----------
|
|
255
|
+
ensight : Any
|
|
256
|
+
The EnSight interface to use to make the actual native API commands.
|
|
257
|
+
|
|
258
|
+
"""
|
|
259
|
+
with tempfile.TemporaryDirectory() as tempdirname:
|
|
260
|
+
the_file = zipfile.ZipFile(self._buffer, "r")
|
|
261
|
+
the_file.extractall(path=tempdirname)
|
|
262
|
+
if self._type in (self._SIMPLE_CONTEXT, self._FULL_CONTEXT): # pragma: no cover
|
|
263
|
+
_ = ensight.file.context_restore_rescale("OFF") # pragma: no cover
|
|
264
|
+
_ = ensight.file.restore_context(
|
|
265
|
+
os.path.join(tempdirname, "context.ctx")
|
|
266
|
+
) # pragma: no cover
|
|
267
|
+
|
|
268
|
+
def _capture_context(
|
|
269
|
+
self, ensight: Any, context: int = _SIMPLE_CONTEXT, all_cases: bool = True
|
|
270
|
+
) -> None:
|
|
271
|
+
"""Capture the current state
|
|
272
|
+
|
|
273
|
+
Cause the EnSight interface to save a context into a temporary directory.
|
|
274
|
+
Zip up the directory contents (along with a "type" marking file) into the
|
|
275
|
+
zip object inside of this state instance.
|
|
276
|
+
|
|
277
|
+
Parameters
|
|
278
|
+
----------
|
|
279
|
+
ensight : Any
|
|
280
|
+
The EnSight interface to use to make the actual native API commands.
|
|
281
|
+
context : int, optional
|
|
282
|
+
The type of context to save. By default, _SIMPLE_CONTEXT.
|
|
283
|
+
all_cases : bool, optional
|
|
284
|
+
By default, save all cases. If all_cases is set to False, only
|
|
285
|
+
the current case will be saved. By default, True.
|
|
286
|
+
|
|
287
|
+
"""
|
|
288
|
+
with tempfile.TemporaryDirectory() as tempdirname:
|
|
289
|
+
# Save a context
|
|
290
|
+
which = "current_case"
|
|
291
|
+
if all_cases: # pragma: no cover
|
|
292
|
+
which = "all_cases"
|
|
293
|
+
_ = ensight.file.save_context_type(which)
|
|
294
|
+
_ = ensight.file.save_context(os.path.join(tempdirname, "context.ctx"))
|
|
295
|
+
if context == self._SIMPLE_CONTEXT:
|
|
296
|
+
# remove sections that cause problems
|
|
297
|
+
with open(os.path.join(tempdirname, "simplecontext.txt"), "w") as fp:
|
|
298
|
+
fp.write("simplecontext")
|
|
299
|
+
self._fix_context_file(os.path.join(tempdirname, "context.ctx"))
|
|
300
|
+
elif context == self._FULL_CONTEXT: # pragma: no cover
|
|
301
|
+
with open(os.path.join(tempdirname, "fullcontext.txt"), "w") as fp:
|
|
302
|
+
fp.write("fullcontext")
|
|
303
|
+
self._build_from_directory(tempdirname)
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def _capture_context(ensight: Any, full: bool) -> Any:
|
|
307
|
+
"""Private interface called by PyEnSight
|
|
308
|
+
|
|
309
|
+
API that makes it simpler to capture a context from a PyEnSight session.
|
|
310
|
+
|
|
311
|
+
Parameters
|
|
312
|
+
----------
|
|
313
|
+
ensight: Any
|
|
314
|
+
EnSight session interface
|
|
315
|
+
full: bool
|
|
316
|
+
True if a "full context" should be saved.
|
|
317
|
+
Returns
|
|
318
|
+
-------
|
|
319
|
+
Any
|
|
320
|
+
A base64 representation of the context.
|
|
321
|
+
|
|
322
|
+
"""
|
|
323
|
+
tmp = EnsContext()
|
|
324
|
+
mode = EnsContext._SIMPLE_CONTEXT
|
|
325
|
+
if full:
|
|
326
|
+
mode = EnsContext._FULL_CONTEXT
|
|
327
|
+
tmp._capture_context(ensight, context=mode)
|
|
328
|
+
return tmp._data(b64=True)
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
def _restore_context(ensight: Any, data: str) -> None:
|
|
332
|
+
"""Private interface called by PyEnSight
|
|
333
|
+
|
|
334
|
+
API that makes it simpler to restore a context from a PyEnSight session.
|
|
335
|
+
|
|
336
|
+
Parameters
|
|
337
|
+
----------
|
|
338
|
+
ensight: Any
|
|
339
|
+
EnSight session interface
|
|
340
|
+
data: str
|
|
341
|
+
A base64 representation of the context.
|
|
342
|
+
"""
|
|
343
|
+
tmp = EnsContext()
|
|
344
|
+
tmp._from_data(data)
|
|
345
|
+
tmp._restore_context(ensight)
|