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,614 @@
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
+ import argparse
24
+ from functools import partial
25
+ import glob
26
+ import json
27
+ import logging
28
+ import os
29
+ import pathlib
30
+ import sys
31
+ import time
32
+ from typing import Any, List, Optional
33
+ from urllib.parse import urlparse
34
+
35
+ import ansys.pyensight.core
36
+
37
+ original_stderr = sys.stderr
38
+ original_stdout = sys.stdout
39
+ sys.stderr = open(os.devnull, "w")
40
+ sys.stdout = open(os.devnull, "w")
41
+ try:
42
+ import ansys.pyensight.core.utils.dsg_server as dsg_server
43
+ import ansys.pyensight.core.utils.omniverse_dsg_server as ov_dsg_server
44
+ import ansys.pyensight.core.utils.omniverse_glb_server as ov_glb_server
45
+ except AttributeError as exc:
46
+ if "_ARRAY_API" not in str(exc):
47
+ raise exc
48
+ finally:
49
+ sys.stderr = original_stderr
50
+ sys.stdout = original_stdout
51
+
52
+
53
+ def str2bool_type(v: Any) -> bool:
54
+ """
55
+ This function is designed to be a 'type=' filter for an argparse entry returning a boolean.
56
+ It allows for additional, common alternative strings as booleans. These include 'yes','no',
57
+ 'true','false','t','f','y','n','1' and '0'. If the value does not meet the requirements,
58
+ the function will raise the argparse.ArgumentTypeError exception.
59
+ :param v: The (potential) boolean argument.
60
+ :return: The actual boolean value.
61
+ :raises: argparse.ArgumentTypeError
62
+ """
63
+ if isinstance(v, bool):
64
+ return v
65
+ if v.lower() in ("yes", "true", "t", "y", "1"):
66
+ return True
67
+ elif v.lower() in ("no", "false", "f", "n", "0"):
68
+ return False
69
+ else:
70
+ raise argparse.ArgumentTypeError("Boolean value expected.")
71
+
72
+
73
+ def int_range_type(
74
+ v: Any, min_value: int = 0, max_value: int = 100, allow: Optional[List[int]] = None
75
+ ) -> int:
76
+ """
77
+ This function is designed to be a 'type=' filter for an argparse entry returning an integer value within
78
+ a specified range. If the value does not meet the requirements, the function will raise the
79
+ argparse.ArgumentTypeError exception. This function is normally used with functools.partial to bind
80
+ the minimum and maximum values. For example: type=partial(int_range_type, min_value=0, max_value=65535)
81
+ :param v: The (potential) integer argument.
82
+ :param min_value: The minimum legal integer value.
83
+ :param max_value: The maximum legal integer value.
84
+ :param allow:A list of additional, legal values
85
+ :return: The validated integer value.
86
+ :raises: argparse.ArgumentTypeError
87
+ """
88
+ try:
89
+ value = int(v)
90
+ except ValueError:
91
+ raise argparse.ArgumentTypeError("Integer value expected.")
92
+ if allow is None:
93
+ allow = []
94
+ if (value >= min_value) and (value <= max_value):
95
+ return value
96
+ elif value in allow:
97
+ return value
98
+ else:
99
+ msg = f"Integer value is not in the range [{min_value},{max_value}]"
100
+ if allow:
101
+ msg += f" or in the list {allow}"
102
+ raise argparse.ArgumentTypeError(msg + ".")
103
+
104
+
105
+ class OmniverseGeometryServer(object):
106
+ def __init__(
107
+ self,
108
+ security_token: str = "",
109
+ destination: str = "",
110
+ temporal: bool = False,
111
+ vrmode: bool = False,
112
+ time_scale: float = 1.0,
113
+ normalize_geometry: bool = False,
114
+ dsg_uri: str = "",
115
+ monitor_directory: str = "",
116
+ line_width: float = 0.0,
117
+ grpc_use_tcp_sockets: bool = False,
118
+ grpc_allow_network_connections: bool = False,
119
+ grpc_disable_tls: bool = False,
120
+ disable_grpc_options: bool = False,
121
+ ) -> None:
122
+ self._dsg_uri = dsg_uri
123
+ self._destination = destination
124
+ self._security_token = security_token
125
+ if not self._security_token:
126
+ self._security_token = os.environ.get("ENSIGHT_SECURITY_TOKEN", "")
127
+ self._temporal = temporal
128
+ self._vrmode = vrmode
129
+ self._time_scale = time_scale
130
+ self._normalize_geometry = normalize_geometry
131
+ self._version = "unknown"
132
+ self._shutdown = False
133
+ self._server_process = None
134
+ self._status_filename: str = ""
135
+ self._monitor_directory: str = monitor_directory
136
+ self._line_width = line_width
137
+ self._grpc_allow_network_connections = grpc_allow_network_connections
138
+ self._grpc_disable_tls = grpc_disable_tls
139
+ self._grpc_use_tcp_sockets = grpc_use_tcp_sockets
140
+ self._disable_grpc_options = disable_grpc_options
141
+
142
+ @property
143
+ def monitor_directory(self) -> Optional[str]:
144
+ if self._monitor_directory:
145
+ return self._monitor_directory
146
+ # converts "" -> None
147
+ return None
148
+
149
+ @property
150
+ def pyensight_version(self) -> str:
151
+ """The ansys.pyensight.core version"""
152
+ return ansys.pyensight.core.VERSION
153
+
154
+ @property
155
+ def dsg_uri(self) -> str:
156
+ """The endpoint of a Dynamic Scene Graph service: grpc://{hostname}:{port}"""
157
+ return self._dsg_uri
158
+
159
+ @dsg_uri.setter
160
+ def dsg_uri(self, uri: str) -> None:
161
+ self._dsg_uri = uri
162
+
163
+ @property
164
+ def destination(self) -> str:
165
+ """The endpoint of an Omniverse Nucleus service: omniverse://{hostname}/{path}"""
166
+ return self._destination
167
+
168
+ @destination.setter
169
+ def destination(self, value: str) -> None:
170
+ self._destination = value
171
+
172
+ @property
173
+ def security_token(self) -> str:
174
+ """The security token of the DSG service instance."""
175
+ return self._security_token
176
+
177
+ @security_token.setter
178
+ def security_token(self, value: str) -> None:
179
+ self._security_token = value
180
+
181
+ @property
182
+ def temporal(self) -> bool:
183
+ """If True, the DSG update should include all timesteps."""
184
+ return self._temporal
185
+
186
+ @temporal.setter
187
+ def temporal(self, value: bool) -> None:
188
+ self._temporal = bool(value)
189
+
190
+ @property
191
+ def vrmode(self) -> bool:
192
+ """If True, the DSG update should not include camera transforms."""
193
+ return self._vrmode
194
+
195
+ @vrmode.setter
196
+ def vrmode(self, value: bool) -> None:
197
+ self._vrmode = bool(value)
198
+
199
+ @property
200
+ def normalize_geometry(self) -> bool:
201
+ """If True, the DSG geometry should be remapped into normalized space."""
202
+ return self._normalize_geometry
203
+
204
+ @normalize_geometry.setter
205
+ def normalize_geometry(self, val: bool) -> None:
206
+ self._normalize_geometry = val
207
+
208
+ @property
209
+ def time_scale(self) -> float:
210
+ """Value to multiply DSG time values by before passing to Omniverse"""
211
+ return self._time_scale
212
+
213
+ @time_scale.setter
214
+ def time_scale(self, value: float) -> None:
215
+ self._time_scale = value
216
+
217
+ @property
218
+ def line_width(self) -> float:
219
+ return self._line_width
220
+
221
+ @line_width.setter
222
+ def line_width(self, line_width: float) -> None:
223
+ self._line_width = line_width
224
+
225
+ def run_server(self, one_shot: bool = False) -> None:
226
+ """
227
+ Run a DSG to Omniverse server in process.
228
+
229
+ Note: this method does not return until the DSG connection is dropped or
230
+ self.stop_server() has been called.
231
+
232
+ Parameters
233
+ ----------
234
+ one_shot : bool
235
+ If True, only run the server to transfer a single scene and
236
+ then return.
237
+ """
238
+
239
+ # Build the Omniverse connection
240
+ omni_link = ov_dsg_server.OmniverseWrapper(
241
+ destination=self._destination, line_width=self.line_width
242
+ )
243
+ logging.info("Omniverse connection established.")
244
+
245
+ # parse the DSG URI
246
+ uds_path = None
247
+ port = None
248
+ host = None
249
+ if self.dsg_uri.endswith(".sock"):
250
+ # The path is a uds path
251
+ uds_path = self.dsg_uri.replace("unix:", "").replace(".sock", "")
252
+ else:
253
+ parsed = urlparse(self.dsg_uri)
254
+ port = parsed.port
255
+ host = parsed.hostname
256
+
257
+ # link it to a DSG session
258
+ update_handler = ov_dsg_server.OmniverseUpdateHandler(omni_link)
259
+ dsg_link = dsg_server.DSGSession(
260
+ port=port,
261
+ host=host,
262
+ vrmode=self.vrmode,
263
+ security_code=self.security_token,
264
+ verbose=1,
265
+ normalize_geometry=self.normalize_geometry,
266
+ time_scale=self.time_scale,
267
+ handler=update_handler,
268
+ uds_path=uds_path,
269
+ grpc_disable_tls=self._grpc_disable_tls,
270
+ grpc_allow_network_connections=self._grpc_allow_network_connections,
271
+ grpc_use_tcp_sockets=self._grpc_use_tcp_sockets,
272
+ disable_grpc_options=self._disable_grpc_options,
273
+ )
274
+
275
+ # Start the DSG link
276
+ logging.info(f"Making DSG connection to: {self.dsg_uri}")
277
+ err = dsg_link.start()
278
+ if err < 0:
279
+ logging.error("Omniverse connection failed.")
280
+ return
281
+
282
+ # Initial pull request
283
+ dsg_link.request_an_update(animation=self.temporal)
284
+
285
+ # until the link is dropped, continue
286
+ while not dsg_link.is_shutdown() and not self._shutdown:
287
+ # Reset the line width to the CLI default before each update
288
+ omni_link.line_width = self.line_width
289
+ dsg_link.handle_one_update()
290
+
291
+ if one_shot:
292
+ break
293
+
294
+ logging.info("Shutting down DSG connection")
295
+ dsg_link.end()
296
+ omni_link.shutdown()
297
+
298
+ def run_monitor(self):
299
+ """
300
+ Run monitor and upload GLB files to Omniverse in process. There are two cases:
301
+
302
+ 1) the "directory name" is actually a .glb file. In this case, simply push
303
+ the glb file contents to Omniverse.
304
+
305
+ 2) If a directory, then we periodically scan the directory for files named "*.upload".
306
+ If this file is found, there are two cases:
307
+
308
+ a) The file is empty. In this case, for a file named ABC.upload, the file
309
+ ABC.glb will be read and uploaded before both files are deleted.
310
+
311
+ b) The file contains valid json. In this case, the json object is parsed with
312
+ the following format (two glb files for the first timestep and one for the second):
313
+
314
+ {
315
+ "version": 1,
316
+ "destination": "",
317
+ "files": ["a.glb", "b.glb", "c.glb"],
318
+ "times": [0.0, 0.0, 1.0]
319
+ }
320
+
321
+ "times" is optional and defaults to [0*len("files")]. Once processed,
322
+ all the files referenced in the json and the json file itself are deleted.
323
+ "omniuri" is optional and defaults to the passed Omniverse path.
324
+
325
+ Note: In this mode, the method does not return until a "shutdown" file or
326
+ an error is encountered.
327
+
328
+ TODO: add "push" mechanism to trigger a DSG push from the connected session. This
329
+ can be done via the monitor mechanism and used by the Omniverse kit to implement
330
+ a "pull".
331
+ """
332
+ the_dir = self.monitor_directory
333
+ single_file_upload = False
334
+ if os.path.isfile(the_dir) and the_dir.lower().endswith(".glb"):
335
+ single_file_upload = True
336
+ else:
337
+ if not os.path.isdir(the_dir):
338
+ logging.error(f"The monitor directory {the_dir} does not exist.")
339
+ return
340
+
341
+ # Build the Omniverse connection
342
+ omni_link = ov_dsg_server.OmniverseWrapper(
343
+ destination=self._destination, line_width=self.line_width
344
+ )
345
+ logging.info("Omniverse connection established.")
346
+
347
+ # use an OmniverseUpdateHandler
348
+ update_handler = ov_dsg_server.OmniverseUpdateHandler(omni_link)
349
+
350
+ # Link it to the GLB file monitoring service
351
+ glb_link = ov_glb_server.GLBSession(verbose=1, handler=update_handler, vrmode=self.vrmode)
352
+ if single_file_upload:
353
+ start_time = time.time()
354
+ logging.info(f"Uploading file: {the_dir}.")
355
+ try:
356
+ glb_link.start_uploads([0.0, 0.0])
357
+ glb_link.upload_file(the_dir)
358
+ glb_link.end_uploads()
359
+ except Exception as error:
360
+ logging.error(f"Unable to upload file: {the_dir}: {error}")
361
+ logging.info(f"Uploaded in {(time.time() - start_time):.2f}")
362
+ else:
363
+ logging.info(f"Starting file monitoring for {the_dir}.")
364
+ the_dir_path = pathlib.Path(the_dir)
365
+ try:
366
+ stop_file = os.path.join(the_dir, "shutdown")
367
+ orig_destination = omni_link.destination
368
+ while not os.path.exists(stop_file):
369
+ loop_time = time.time()
370
+ files_to_remove = []
371
+ for filename in glob.glob(os.path.join(the_dir, "*.upload")):
372
+ # reset to the launch URI/directory
373
+ omni_link.destination = orig_destination
374
+ # Keep track of the files and time values
375
+ files_to_remove.append(filename)
376
+ files_to_process = []
377
+ file_timestamps = []
378
+ if os.path.getsize(filename) == 0:
379
+ # replace the ".upload" extension with ".glb"
380
+ glb_file = os.path.splitext(filename)[0] + ".glb"
381
+ if os.path.exists(glb_file):
382
+ files_to_process.append(glb_file)
383
+ file_timestamps.append(0.0)
384
+ files_to_remove.append(glb_file)
385
+ else:
386
+ # read the .upload file json content
387
+ try:
388
+ with open(filename, "r") as fp:
389
+ glb_info = json.load(fp)
390
+ except Exception:
391
+ logging.error(f"Unable to read file: {filename}")
392
+ continue
393
+ # if specified, set the URI/directory target
394
+ omni_link.destination = glb_info.get("destination", orig_destination)
395
+ # Get the GLB files to process
396
+ the_files = glb_info.get("files", [])
397
+ files_to_remove.extend(the_files)
398
+ # Times not used for now, but parse them anyway
399
+ the_times = glb_info.get("times", [0.0] * len(the_files))
400
+ file_timestamps.extend(the_times)
401
+ # Validate a few things
402
+ if len(the_files) != len(the_times):
403
+ logging.error(
404
+ f"Number of times and files are not the same in: {filename}"
405
+ )
406
+ continue
407
+ files_to_process.extend(the_files)
408
+ # manage time
409
+ timeline = sorted(set(file_timestamps))
410
+ if len(timeline) != 1:
411
+ logging.warning("Time values not currently supported.")
412
+ if len(files_to_process) > 1:
413
+ logging.warning("Multiple glb files not currently fully supported.")
414
+ # Reset the line width to the CLI default before each update
415
+ omni_link.line_width = self.line_width
416
+ # Upload the files
417
+ glb_link.start_uploads([timeline[0], timeline[-1]])
418
+ for glb_file, timestamp in zip(files_to_process, file_timestamps):
419
+ start_time = time.time()
420
+ logging.info(f"Uploading file: {glb_file} to {omni_link.destination}.")
421
+ try:
422
+ time_idx = timeline.index(timestamp) + 1
423
+ if time_idx == len(timeline):
424
+ time_idx -= 1
425
+ limits = [timestamp, timeline[time_idx]]
426
+ glb_link.upload_file(glb_file, timeline=limits)
427
+ except Exception as error:
428
+ logging.error(f"Unable to upload file: {glb_file}: {error}")
429
+ logging.info(f"Uploaded in {(time.time() - start_time):.2f}s")
430
+ glb_link.end_uploads()
431
+ for filename in files_to_remove:
432
+ try:
433
+ # Only delete the file if it is in the_dir_path
434
+ filename_path = pathlib.Path(filename)
435
+ if filename_path.is_relative_to(the_dir_path):
436
+ os.remove(filename)
437
+ except IOError:
438
+ pass
439
+ if time.time() - loop_time < 0.1:
440
+ time.sleep(0.25)
441
+ except Exception as error:
442
+ logging.error(f"Error encountered while monitoring: {error}")
443
+ logging.info("Stopping file monitoring.")
444
+ try:
445
+ os.remove(stop_file)
446
+ except IOError:
447
+ logging.error("Unable to remove 'shutdown' file.")
448
+
449
+ omni_link.shutdown()
450
+
451
+
452
+ if __name__ == "__main__":
453
+ parser = argparse.ArgumentParser(description="PyEnSight Omniverse Geometry Service")
454
+ parser.add_argument(
455
+ "destination", default="", type=str, help="The directory to save the USD scene graph into."
456
+ )
457
+ parser.add_argument(
458
+ "--verbose",
459
+ metavar="verbose_level",
460
+ default=0,
461
+ type=partial(int_range_type, min_value=0, max_value=3),
462
+ help="Enable logging information (0-3). Default: 0",
463
+ )
464
+ parser.add_argument(
465
+ "--log_file",
466
+ metavar="log_filename",
467
+ default="",
468
+ type=str,
469
+ help="Save logging output to the named log file instead of stdout.",
470
+ )
471
+ parser.add_argument(
472
+ "--dsg_uri",
473
+ default="grpc://127.0.0.1:5234",
474
+ type=str,
475
+ help="The URI of the EnSight Dynamic Scene Graph server. Default: grpc://127.0.0.1:5234",
476
+ )
477
+ parser.add_argument(
478
+ "--security_token",
479
+ metavar="token",
480
+ default="",
481
+ type=str,
482
+ help="Dynamic scene graph API security token. Default: none",
483
+ )
484
+ parser.add_argument(
485
+ "--monitor_directory",
486
+ metavar="glb_directory",
487
+ default="",
488
+ type=str,
489
+ help="Monitor specified directory for GLB files to be exported. Default: none",
490
+ )
491
+ parser.add_argument(
492
+ "--time_scale",
493
+ metavar="time_scale",
494
+ default=1.0,
495
+ type=float,
496
+ help="Scaling factor to be applied to input time values. Default: 1.0",
497
+ )
498
+ parser.add_argument(
499
+ "--normalize_geometry",
500
+ metavar="yes|no|true|false|1|0",
501
+ default=False,
502
+ type=str2bool_type,
503
+ help="Enable mapping of geometry to a normalized Cartesian space. Default: false",
504
+ )
505
+ parser.add_argument(
506
+ "--include_camera",
507
+ metavar="yes|no|true|false|1|0",
508
+ default=True,
509
+ type=str2bool_type,
510
+ help="Include the camera in the output USD scene graph. Default: true",
511
+ )
512
+ parser.add_argument(
513
+ "--temporal",
514
+ metavar="yes|no|true|false|1|0",
515
+ default=False,
516
+ type=str2bool_type,
517
+ help="Export a temporal scene graph. Default: false",
518
+ )
519
+ parser.add_argument(
520
+ "--oneshot",
521
+ metavar="yes|no|true|false|1|0",
522
+ default=False,
523
+ type=str2bool_type,
524
+ help="Convert a single geometry into USD and exit. Default: false",
525
+ )
526
+ line_default: Any = os.environ.get("ANSYS_OV_LINE_WIDTH", None)
527
+ if line_default is not None:
528
+ try:
529
+ line_default = float(line_default)
530
+ except ValueError:
531
+ line_default = None
532
+ parser.add_argument(
533
+ "--line_width",
534
+ metavar="line_width",
535
+ default=line_default,
536
+ type=float,
537
+ help=f"Width of lines: >0=absolute size. <0=fraction of diagonal. 0=none. Default: {line_default}",
538
+ )
539
+ parser.add_argument(
540
+ "--grpc_use_tcp_sockets",
541
+ metavar="yes|no|true|false|1|0",
542
+ default=False,
543
+ type=str2bool_type,
544
+ help="If using gRPC, and if True, then allow TCP Socket based connections instead of only local connections.",
545
+ )
546
+ parser.add_argument(
547
+ "--grpc_allow_network_connections",
548
+ metavar="yes|no|true|false|1|0",
549
+ default=False,
550
+ type=str2bool_type,
551
+ help="If using gRPC and using TCP Socket based connections, listen on all networks.",
552
+ )
553
+ parser.add_argument(
554
+ "--grpc_disable_tls",
555
+ metavar="yes|no|true|false|1|0",
556
+ default=False,
557
+ type=str2bool_type,
558
+ help="If using gRPC and using TCP Socket based connections, disable TLS.",
559
+ )
560
+ parser.add_argument(
561
+ "--disable_grpc_options",
562
+ metavar="yes|no|true|false|1|0",
563
+ default=False,
564
+ type=str2bool_type,
565
+ help="Disable all the gRPC options check and allow to run older versions of EnSight.",
566
+ )
567
+ # parse the command line
568
+ args = parser.parse_args()
569
+
570
+ # set up logging
571
+ level = logging.ERROR
572
+ if args.verbose == 1:
573
+ level = logging.WARN
574
+ elif args.verbose == 2:
575
+ level = logging.INFO
576
+ elif args.verbose == 3:
577
+ level = logging.DEBUG
578
+ log_args = dict(format="GeometryService:%(levelname)s:%(message)s", level=level)
579
+ if args.log_file:
580
+ log_args["filename"] = args.log_file
581
+ # start with a clean logging instance
582
+ while logging.root.hasHandlers():
583
+ logging.root.removeHandler(logging.root.handlers[0])
584
+ logging.basicConfig(**log_args) # type: ignore
585
+
586
+ # size of lines in data units or fraction of bounding box diagonal
587
+ line_width = 0.0
588
+ if args.line_width is not None:
589
+ line_width = args.line_width
590
+
591
+ # Build the server object
592
+ server = OmniverseGeometryServer(
593
+ destination=args.destination,
594
+ dsg_uri=args.dsg_uri,
595
+ security_token=args.security_token,
596
+ monitor_directory=args.monitor_directory,
597
+ time_scale=args.time_scale,
598
+ normalize_geometry=args.normalize_geometry,
599
+ vrmode=not args.include_camera,
600
+ temporal=args.temporal,
601
+ line_width=line_width,
602
+ grpc_disable_tls=args.grpc_disable_tls,
603
+ grpc_allow_network_connections=args.grpc_allow_network_connections,
604
+ grpc_use_tcp_sockets=args.grpc_use_tcp_sockets,
605
+ disable_grpc_options=args.disable_grpc_options,
606
+ )
607
+
608
+ # run the server
609
+ logging.info("Server startup.")
610
+ if server.monitor_directory:
611
+ server.run_monitor()
612
+ else:
613
+ server.run_server(one_shot=args.oneshot)
614
+ logging.info("Server shutdown.")