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,300 @@
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
+ """Readers module.
24
+
25
+ This module contains utilities to do readers specific operations.
26
+ """
27
+ import os
28
+ import re
29
+ from threading import Thread
30
+ import time
31
+ from types import ModuleType
32
+ from typing import Optional, Tuple, Union
33
+ import uuid
34
+
35
+ try:
36
+ import ensight
37
+ except ImportError:
38
+ from ansys.api.pyensight import ensight_api
39
+
40
+
41
+ class Readers:
42
+ """A namespace to access the interfaces of specific readers"""
43
+
44
+ def __init__(self, interface: Union["ensight_api.ensight", "ensight"]):
45
+ self._ensight = interface
46
+ self._dvs = DVS(self._ensight)
47
+
48
+ @property
49
+ def dvs(self) -> "DVS":
50
+ """The ensight interface"""
51
+ return self._dvs
52
+
53
+
54
+ class DVS:
55
+ """A namespace to access specific DVS interfaces"""
56
+
57
+ def __init__(self, interface: Union["ensight_api.ensight", "ensight"]):
58
+ self._ensight: Union["ensight_api.ensight", "ensight"] = interface
59
+ self._dvs_port: Optional[int] = None
60
+
61
+ MONITOR_NEW_TIMESTEPS_STAY_AT_CURRENT = "stay_at_current"
62
+ MONITOR_NEW_TIMESTEPS_JUMP_TO_END = "jump_to_end"
63
+
64
+ def _launch_live_dvs_242_cmd(
65
+ self,
66
+ tmp_name: str,
67
+ port: int = 0,
68
+ secret_key: Optional[str] = None,
69
+ monitor_new_timesteps: str = MONITOR_NEW_TIMESTEPS_STAY_AT_CURRENT,
70
+ ):
71
+ """Launch a live DVS session from PyEnSight for EnSight 242 and onward"""
72
+ indent = " "
73
+ cmd = "import re\n"
74
+ cmd += "def dvs_callback():\n"
75
+ cmd += f'{indent}command_string = f"set_server_port={port}"\n'
76
+ if secret_key is not None:
77
+ secret_string = f'{indent}command_string += f"&set_secret_key='
78
+ secret_string += secret_key + '"\n'
79
+ cmd += secret_string
80
+ tmp_name = tmp_name.replace("\\", "\\\\")
81
+ cmd += f"{indent}reply = ensight.objs.core.CURRENTCASE[0].client_command(command_string)\n"
82
+ cmd += f"{indent}dvs_port_string = ensight.objs.core.CURRENTCASE[0].client_command('get_server_port')\n"
83
+ cmd += (
84
+ f"{indent}dvs_port = int(re.search(r':([0-9]{{4,5}})', dvs_port_string).groups(1)[0])\n"
85
+ )
86
+ cmd += f"{indent}with open('{tmp_name}', 'w') as temp_file:\n"
87
+ cmd += f"{2*indent}temp_file.write(str(dvs_port))\n"
88
+ cmd += f"{indent}return True\n\n"
89
+ cmd += "reply = ensight.objs.core.CURRENTCASE[0].client_command_callback(dvs_callback)\n"
90
+ if monitor_new_timesteps:
91
+ cmd += f'ensight.solution_time.monitor_for_new_steps("{monitor_new_timesteps}")\n'
92
+ cmd += 'ensight.part.elt_representation("3D_feature_2D_full")\n'
93
+ cmd += 'ensight.data.format("DVS")\n'
94
+ cmd += 'err = ensight.data.replace("notexisting.dvs")\n'
95
+ return cmd
96
+
97
+ def _launch_live_dvs_241_cmd(
98
+ self,
99
+ port: int = 0,
100
+ secret_key: Optional[str] = None,
101
+ monitor_new_timesteps: str = MONITOR_NEW_TIMESTEPS_STAY_AT_CURRENT,
102
+ ):
103
+ """Launch a live DVS session from PyEnSight for EnSight 241"""
104
+ if port == 0:
105
+ ports = self._ensight._session.find_remote_unused_ports(1)
106
+ if ports:
107
+ self._dvs_port = ports[0]
108
+ port = ports[0]
109
+ indent = " "
110
+ cmd = "import os\n"
111
+ cmd += f"try:\n{indent}os.remove('remote.dvs')\n"
112
+ cmd += f"except (FileNotFoundError, OSError):\n{indent}pass\n"
113
+ cmd += "path = os.path.join(os.getcwd(), 'remote.dvs')\n"
114
+ cmd += "with open(path, 'w') as dvsfile:\n"
115
+ cmd += f"{indent}dvsfile.write('#!DVS_CASE 1.0\\n')\n"
116
+ cmd += f"{indent}dvsfile.write(f'SERVER_PORT_BASE={port}\\n')\n"
117
+ cmd += f"{indent}dvsfile.write('SERVER_PORT_MULT=1\\n')\n"
118
+ if secret_key:
119
+ cmd += f"{indent}dvsfile.write(f'SERVER_SECURITY_SECRET={secret_key}\\n')\n"
120
+ cmd += f'ensight.solution_time.monitor_for_new_steps("{monitor_new_timesteps}")\n'
121
+ cmd += 'ensight.part.elt_representation("3D_feature_2D_full")\n'
122
+ cmd += 'ensight.data.format("DVS")\n'
123
+ cmd += "ensight.data.replace(path)\n"
124
+ return cmd
125
+
126
+ def _find_dvs_port(self, tmp_name: Optional[str] = None):
127
+ """Find the dvs port allocated from the input temporary name"""
128
+ if not tmp_name:
129
+ raise RuntimeError("Temporary name for dvs port file not available")
130
+ try_local = True
131
+ if self._ensight._session._launcher:
132
+ if hasattr(self._ensight._session._launcher, "_enshell"):
133
+ try_local = False
134
+ log_content = self._ensight._session._launcher.enshell_log_contents()
135
+ dvs_port_match = re.search(r"\(0.0.0.0\):([0-9]{4,5})\n", log_content)
136
+ if dvs_port_match:
137
+ self._dvs_port = int(str(dvs_port_match.groups(1)[0]).strip())
138
+ if try_local:
139
+ try:
140
+ with open(tmp_name) as dvs_port_file:
141
+ self._dvs_port = int(dvs_port_file.read().strip())
142
+ except Exception:
143
+ raise RuntimeError("Cannot retrieve DVS Port")
144
+
145
+ @staticmethod
146
+ def _launch_dvs_callback_in_ensight(
147
+ port: int,
148
+ filename: Optional[str],
149
+ secret_key: Optional[str],
150
+ monitor_new_timesteps: str = MONITOR_NEW_TIMESTEPS_STAY_AT_CURRENT,
151
+ ) -> None: # pragma: no cover
152
+ """Launch a live DVS session in EnSight"""
153
+ from ceiversion import ensight_suffix # pylint: disable=import-outside-toplevel
154
+
155
+ if int(ensight_suffix) < 242:
156
+ from cei import find_unused_ports # pylint: disable=import-outside-toplevel
157
+
158
+ if port == 0:
159
+ ports = find_unused_ports(1)
160
+ if ports:
161
+ port = ports[0]
162
+ try:
163
+ os.remove("remote.dvs")
164
+ except (FileNotFoundError, OSError):
165
+ pass
166
+ path = os.path.join(os.getcwd(), "remote.dvs")
167
+ with open(path, "w") as dvsfile:
168
+ dvsfile.write("#!DVS_CASE 1.0\n")
169
+ dvsfile.write(f"SERVER_PORT_BASE={port}\n")
170
+ dvsfile.write("SERVER_PORT_MULT=1\n")
171
+ if secret_key is not None:
172
+ dvsfile.write(f"SERVER_SECURITY_SECRET={secret_key}\n")
173
+ if filename:
174
+ try:
175
+ with open(filename, "w") as dvs_port_file:
176
+ dvs_port_file.write(str(port))
177
+ except Exception:
178
+ raise RuntimeError(f"Couldn't write allocated DVS port to {filename}")
179
+ ensight.part.elt_representation("3D_feature_2D_full")
180
+ ensight.solution_time.monitor_for_new_steps(f"{monitor_new_timesteps}")
181
+ ensight.data.format("DVS")
182
+ ensight.data.replace(path)
183
+ else:
184
+
185
+ def dvs_callback():
186
+ command_string = f"set_server_port={port}"
187
+ if secret_key is not None:
188
+ command_string += f"&set_secret_key={secret_key}"
189
+ ensight.objs.core.CURRENTCASE[0].client_command(command_string)
190
+ dvs_port_string = ensight.objs.core.CURRENTCASE[0].client_command("get_server_port")
191
+ dvs_port_match = re.search(r":([0-9]{4,5})", dvs_port_string)
192
+ dvs_port = None
193
+ if dvs_port_match:
194
+ dvs_port = int(dvs_port_match.groups(1)[0])
195
+ if not dvs_port:
196
+ raise RuntimeError("DVS couldn't allocate a port")
197
+ if filename:
198
+ try:
199
+ with open(filename, "w") as dvs_port_file:
200
+ dvs_port_file.write(str(dvs_port))
201
+ except Exception:
202
+ raise RuntimeError(f"Couldn't write allocated DVS port to {filename}")
203
+ return True
204
+
205
+ ensight.objs.core.CURRENTCASE[0].client_command_callback(dvs_callback)
206
+ ensight.solution_time.monitor_for_new_steps(f"{monitor_new_timesteps}")
207
+ ensight.part.elt_representation("3D_feature_2D_full")
208
+ ensight.data.format("DVS")
209
+ ensight.data.replace("notexisting.dvs")
210
+
211
+ def launch_live_dvs(
212
+ self,
213
+ port: int = 0,
214
+ secret_key: Optional[str] = None,
215
+ monitor_new_timesteps: str = MONITOR_NEW_TIMESTEPS_STAY_AT_CURRENT,
216
+ start_thread: bool = True,
217
+ filename: Optional[str] = None,
218
+ ) -> Tuple[Optional[Thread], Optional[int]]:
219
+ """To provide an interface to launch an in-situ EnSight DVS session.
220
+ If in PyEnSight, the function will return a thread which will launch the DVS reader
221
+ in EnSight, hence the DVS servers, and will also return the port allocated by DVS, to
222
+ cover the case the port 0 was asked for.
223
+ If instead the function will be used directly in EnSight via the utils interface, since
224
+ the reader launch will block the interpreter waiting for new data, the port cannot be returned
225
+ and cannot be printed up until the first update happens.
226
+ So, if you need to access the port number in a script and you cannot check the EnSight console,
227
+ please supply a filename to store the dvs port into.
228
+
229
+ Parameters
230
+ ----------
231
+ port: int
232
+ the port number where the first DVS server will be started. In case of a
233
+ SOS EnSight session, on the following server the DVS servers will be started on the
234
+ next port, e.g. if the first server starts at port 50055, the second will start
235
+ at port 50056 and so on
236
+ secret_key: str
237
+ an optional secret key to pass in case the DVS clients have been started with a secret key
238
+ for the underlying gRPC connections. An empty string can be provided if needed
239
+ monitor_new_timesteps: str
240
+ set the way EnSight will monitor for new timesteps. Defaults to MONITOR_NEW_TIMESTEPS_STAY_AT_CURRENT.
241
+ The allowed values are MONITOR_NEW_TIMESTEPS_STAY_AT_CURRENT
242
+ and MONITOR_NEW_TIMESTEPS_JUMP_TO_END
243
+ start_thread: bool
244
+ True if the thread to be returned needs to be started already. Default is True
245
+ filename: str
246
+ An optional path to store the port number in. It will be used only if the utils is being
247
+ called directly in EnSight.
248
+
249
+ Returns
250
+ -------
251
+ Thread:
252
+ a python Thread which holds the dvs load
253
+ """
254
+
255
+ def load_dvs():
256
+ self._ensight._session.cmd(cmd, do_eval=False)
257
+
258
+ if monitor_new_timesteps not in [
259
+ self.MONITOR_NEW_TIMESTEPS_JUMP_TO_END,
260
+ self.MONITOR_NEW_TIMESTEPS_STAY_AT_CURRENT,
261
+ ]:
262
+ raise RuntimeError(
263
+ f"{monitor_new_timesteps} value not allowed for an in-situ DVS session"
264
+ )
265
+ if not isinstance(self._ensight, ModuleType): # pragma: no cover
266
+ self._ensight._session.ensight_version_check("2024 R1")
267
+ else:
268
+ self._launch_dvs_callback_in_ensight(
269
+ port=port,
270
+ secret_key=secret_key,
271
+ monitor_new_timesteps=monitor_new_timesteps,
272
+ filename=filename,
273
+ )
274
+ return None, None
275
+ cmd = ""
276
+ path = None
277
+ if int(self._ensight._session.cei_suffix) < 242:
278
+ cmd = self._launch_live_dvs_241_cmd(
279
+ port=port, secret_key=secret_key, monitor_new_timesteps=monitor_new_timesteps
280
+ )
281
+ else:
282
+ tmp_name = str(uuid.uuid4())
283
+ path = os.path.join(self._ensight._session._launcher.session_directory, tmp_name)
284
+ cmd = self._launch_live_dvs_242_cmd(
285
+ port=port,
286
+ secret_key=secret_key,
287
+ monitor_new_timesteps=monitor_new_timesteps,
288
+ tmp_name=path,
289
+ )
290
+ t = Thread(target=load_dvs)
291
+ if start_thread:
292
+ t.start()
293
+ start = time.time()
294
+ while not self._dvs_port and time.time() - start < 60:
295
+ try:
296
+ self._find_dvs_port(path)
297
+ except Exception:
298
+ pass
299
+ time.sleep(0.5)
300
+ return t, self._dvs_port
@@ -0,0 +1,128 @@
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, ContextManager, Union
24
+
25
+ if TYPE_CHECKING:
26
+ try:
27
+ import ensight
28
+ except ImportError:
29
+ from ansys.api.pyensight import ensight_api
30
+
31
+
32
+ class Support:
33
+ """Provides the ``ensight.utils.support`` interface.
34
+
35
+ This class provides a collection of general utility functions and objects
36
+ that can be used to simplify various issues that come up when using EnSight
37
+ and PyEnSight.
38
+
39
+ This class is instantiated as ``ensight.utils.support`` in EnSight Python
40
+ and as ``Session.ensight.utils.support`` in PyEnSight. The constructor is
41
+ passed the interface, which serves as the ``ensight`` module for either
42
+ case. As a result, the methods can be accessed as ``ensight.utils.support.*``
43
+ in EnSight Python or ``session.ensight.utils.support.*`` in PyEnSight.
44
+
45
+ Parameters
46
+ ----------
47
+ interface :
48
+ Entity that provides the ``ensight`` namespace. In the case of
49
+ EnSight Python, the ``ensight`` module is passed. In the case
50
+ of PyEnSight, ``Session.ensight`` is passed.
51
+ """
52
+
53
+ def __init__(self, interface: Union["ensight_api.ensight", "ensight"]):
54
+ self._ensight = interface
55
+
56
+ def scoped_name(self, obj: Any, native_exceptions: bool = False) -> ContextManager:
57
+ """Allow for the use of ``with`` to shorten APIs.
58
+
59
+ In the EnSight and PyEnsight APIs, the interfaces can become lengthy.
60
+ This class makes it possible to shorten APIs for modules, classes,
61
+ and namespaces. The native_exceptions keyword can be used to enable
62
+ exceptions for EnSight native Python API. By default, an invalid
63
+ native API call like ``ensight.part.select_begin(-9999)`` will return
64
+ -1. If native_exceptions is True, a Python exception will be thrown.
65
+ The scope of this operational change parallels the scoped_name()
66
+ instance.
67
+
68
+ Parameters
69
+ ----------
70
+ obj: Any
71
+ The object for which to generate a simplified namespace.
72
+ native_exceptions: bool
73
+ If True, then EnSight native Python API exceptions are enabled.
74
+ The default is False.
75
+
76
+ Returns
77
+ -------
78
+ The passed object wrapped in a context manager that can be used as a
79
+ simplified namespace.
80
+
81
+ Examples
82
+ --------
83
+ >>> sn = s.ensight.utils.support.scoped_name
84
+ >>> with sn(s.ensight.objs.core) as core, sn(s.ensight.objs.enums) as enums:
85
+ >>> print(core.PARTS.find(True, enums.VISIBLE))
86
+
87
+ >>> sn = ensight.utils.support.scoped_name
88
+ >>> with sn(ensight.objs.core) as core, sn(ensight.objs.enums) as enums:
89
+ >>> print(core.PARTS.find(True, enums.VISIBLE))
90
+
91
+ >>> sn = ensight.utils.support.scoped_name
92
+ >>> with sn(ensight.part, native_exceptions=True) as part:
93
+ >>> part.select_begin(-9999)
94
+ """
95
+ return ScopedName(self._ensight, obj, native_exceptions=native_exceptions)
96
+
97
+
98
+ class ScopedName:
99
+ """Allow for the use of ``with`` to shorten APIs.
100
+
101
+ In the EnSight and PyEnsight APIs, the interfaces can become lengthy.
102
+ This class makes it possible to shorten APIs for modules, classes,
103
+ and namespaces.
104
+ """
105
+
106
+ def __init__(
107
+ self,
108
+ interface: Union["ensight_api.ensight", "ensight"],
109
+ obj: Any,
110
+ native_exceptions: bool = False,
111
+ ):
112
+ self._obj = obj
113
+ self._ensight = interface
114
+ self._old_raise = None
115
+ if native_exceptions:
116
+ # if we are being asked to enable exceptions, record what to restore it to
117
+ self._old_raise = self._ensight.query("SENDMESG_RAISE")
118
+
119
+ def __enter__(self) -> Any:
120
+ if self._old_raise is not None:
121
+ # if a restore value is set, enable them
122
+ self._ensight.sendmesgoptions(exception=1)
123
+ return self._obj
124
+
125
+ def __exit__(self, exc_type, exc_value, exc_trace):
126
+ if self._old_raise is not None:
127
+ # if the restore value is set, restore it here
128
+ self._ensight.sendmesgoptions(exception=self._old_raise)