ansys-pyensight-core 0.9.0__tar.gz → 0.9.2__tar.gz
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.
Potentially problematic release.
This version of ansys-pyensight-core might be problematic. Click here for more details.
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/PKG-INFO +2 -2
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/pyproject.toml +2 -2
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/ensight_grpc.py +302 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/renderable.py +6 -1
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/session.py +3 -1
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/utils/dsg_server.py +16 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/utils/omniverse.py +218 -76
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/utils/omniverse_cli.py +19 -11
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/utils/omniverse_dsg_server.py +108 -44
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/utils/omniverse_glb_server.py +172 -24
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/LICENSE +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/README.rst +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/__init__.py +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/common.py +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/deep_pixel_view.html +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/dockerlauncher.py +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/enscontext.py +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/enshell_grpc.py +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/ensobj.py +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/launch_ensight.py +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/launcher.py +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/libuserd.py +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/listobj.py +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/locallauncher.py +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/py.typed +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/sgeo_poll.html +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/utils/__init__.py +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/utils/adr.py +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/utils/export.py +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/utils/parts.py +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/utils/query.py +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/utils/readers.py +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/utils/resources/Materials/000_sky.exr +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/utils/support.py +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/utils/variables.py +0 -0
- {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/utils/views.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: ansys-pyensight-core
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.2
|
|
4
4
|
Summary: A python wrapper for Ansys EnSight
|
|
5
5
|
Author-email: "ANSYS, Inc." <pyansys.core@ansys.com>
|
|
6
6
|
Maintainer-email: "ANSYS, Inc." <pyansys.core@ansys.com>
|
|
@@ -20,7 +20,7 @@ Requires-Dist: ansys-api-pyensight==0.4.2
|
|
|
20
20
|
Requires-Dist: requests>=2.28.2
|
|
21
21
|
Requires-Dist: docker>=6.1.0
|
|
22
22
|
Requires-Dist: urllib3<3.0.0
|
|
23
|
-
Requires-Dist: numpy>=1.21.0,<
|
|
23
|
+
Requires-Dist: numpy>=1.21.0,<3
|
|
24
24
|
Requires-Dist: Pillow>=9.3.0
|
|
25
25
|
Requires-Dist: pypng>=0.0.20
|
|
26
26
|
Requires-Dist: psutil>=5.9.2
|
|
@@ -6,7 +6,7 @@ build-backend = "flit_core.buildapi"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "ansys-pyensight-core"
|
|
9
|
-
version = "0.9.
|
|
9
|
+
version = "0.9.2"
|
|
10
10
|
description = "A python wrapper for Ansys EnSight"
|
|
11
11
|
readme = "README.rst"
|
|
12
12
|
requires-python = ">=3.9,<4"
|
|
@@ -31,7 +31,7 @@ dependencies = [
|
|
|
31
31
|
"requests>=2.28.2",
|
|
32
32
|
"docker>=6.1.0",
|
|
33
33
|
"urllib3<3.0.0",
|
|
34
|
-
"numpy>=1.21.0,<
|
|
34
|
+
"numpy>=1.21.0,<3",
|
|
35
35
|
"Pillow>=9.3.0",
|
|
36
36
|
"pypng>=0.0.20",
|
|
37
37
|
"psutil>=5.9.2",
|
{ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/ensight_grpc.py
RENAMED
|
@@ -4,6 +4,11 @@ This package defines the EnSightGRPC class which provides a simpler
|
|
|
4
4
|
interface to the EnSight gRPC interface, including event streams.
|
|
5
5
|
|
|
6
6
|
"""
|
|
7
|
+
from concurrent import futures
|
|
8
|
+
import os
|
|
9
|
+
import platform
|
|
10
|
+
import sys
|
|
11
|
+
import tempfile
|
|
7
12
|
import threading
|
|
8
13
|
from typing import Any, Callable, List, Optional, Tuple, Union
|
|
9
14
|
import uuid
|
|
@@ -47,6 +52,14 @@ class EnSightGRPC(object):
|
|
|
47
52
|
# Callback for events (self._events not used)
|
|
48
53
|
self._event_callback: Optional[Callable] = None
|
|
49
54
|
self._prefix: Optional[str] = None
|
|
55
|
+
self._shmem_module = None
|
|
56
|
+
self._shmem_filename: Optional[str] = None
|
|
57
|
+
self._shmem_client = None
|
|
58
|
+
self._image_stream = None
|
|
59
|
+
self._image_thread = None
|
|
60
|
+
self._image = None
|
|
61
|
+
self._image_number = 0
|
|
62
|
+
self._sub_service = None
|
|
50
63
|
|
|
51
64
|
@property
|
|
52
65
|
def host(self) -> str:
|
|
@@ -120,6 +133,12 @@ class EnSightGRPC(object):
|
|
|
120
133
|
if self._channel:
|
|
121
134
|
self._channel.close()
|
|
122
135
|
self._channel = None
|
|
136
|
+
if self._shmem_client:
|
|
137
|
+
if self._shmem_module:
|
|
138
|
+
self._shmem_module.stream_destroy(self._shmem_client)
|
|
139
|
+
else:
|
|
140
|
+
self.command("ensight_grpc_shmem.stream_destroy(enscl._shmem_client)")
|
|
141
|
+
self._shmem_client = None
|
|
123
142
|
|
|
124
143
|
def is_connected(self) -> bool:
|
|
125
144
|
"""Check to see if the gRPC connection is live
|
|
@@ -430,3 +449,286 @@ class EnSightGRPC(object):
|
|
|
430
449
|
# signal that the gRPC connection has broken
|
|
431
450
|
self._event_stream = None
|
|
432
451
|
self._event_thread = None
|
|
452
|
+
|
|
453
|
+
def _attempt_shared_mem_import(self):
|
|
454
|
+
try:
|
|
455
|
+
import ensight_grpc_shmem
|
|
456
|
+
|
|
457
|
+
self._shmem_module = ensight_grpc_shmem
|
|
458
|
+
except ModuleNotFoundError:
|
|
459
|
+
try:
|
|
460
|
+
self.command("import enve", do_eval=False)
|
|
461
|
+
cei_home = eval(self.command("enve.home()"))
|
|
462
|
+
self.command("import ceiversion", do_eval=False)
|
|
463
|
+
cei_version = eval(self.command("ceiversion.version_suffix"))
|
|
464
|
+
self.command("import sys", do_eval=False)
|
|
465
|
+
py_version = eval(self.command("sys.version_info[:3]"))
|
|
466
|
+
is_win = True if "Win" in platform.system() else False
|
|
467
|
+
plat = "win64" if is_win else "linux_2.6_64"
|
|
468
|
+
_lib = "DLLs" if is_win else f"lib/python{py_version[0]}.{py_version[1]}"
|
|
469
|
+
dll_loc = os.path.join(
|
|
470
|
+
cei_home,
|
|
471
|
+
f"apex{cei_version}",
|
|
472
|
+
"machines",
|
|
473
|
+
plat,
|
|
474
|
+
f"Python-{py_version[0]}.{py_version[1]}.{py_version[2]}",
|
|
475
|
+
_lib,
|
|
476
|
+
)
|
|
477
|
+
if os.path.exists(dll_loc):
|
|
478
|
+
sys.path.append(dll_loc)
|
|
479
|
+
import ensight_grpc_shmem
|
|
480
|
+
|
|
481
|
+
self._shmem_module = ensight_grpc_shmem
|
|
482
|
+
except ModuleNotFoundError:
|
|
483
|
+
pass
|
|
484
|
+
|
|
485
|
+
@classmethod
|
|
486
|
+
def _find_filename(cls, size=1024 * 1024 * 25):
|
|
487
|
+
"""Create a file on disk to support shared memory transport.
|
|
488
|
+
|
|
489
|
+
A file, 25MB in size, will be created using the pid of the current
|
|
490
|
+
process to generate the filename. It will be located in a temporary
|
|
491
|
+
directory.
|
|
492
|
+
"""
|
|
493
|
+
tempdir = tempfile.mkdtemp(prefix="pyensight_shmem")
|
|
494
|
+
for i in range(100):
|
|
495
|
+
filename = os.path.join(tempdir, "shmem_{}.bin".format(os.getpid() + i))
|
|
496
|
+
if not os.path.exists(filename):
|
|
497
|
+
try:
|
|
498
|
+
tmp = open(filename, "wb")
|
|
499
|
+
tmp.write(b"\0" * size) # 25MB
|
|
500
|
+
tmp.close()
|
|
501
|
+
return filename
|
|
502
|
+
except Exception:
|
|
503
|
+
pass
|
|
504
|
+
return None
|
|
505
|
+
|
|
506
|
+
def get_image(self):
|
|
507
|
+
"""Retrieve the current EnSight image.
|
|
508
|
+
|
|
509
|
+
When any of the image streaming systems is enabled, Python threads will receive the
|
|
510
|
+
most recent image and store them in this instance. The frame stored in this instance
|
|
511
|
+
can be accessed by calling this method
|
|
512
|
+
|
|
513
|
+
Returns
|
|
514
|
+
-------
|
|
515
|
+
(tuple):
|
|
516
|
+
A tuple containing a dictionary defining the image binary
|
|
517
|
+
(pixels=bytearray, width=w, height=h) and the image frame number.
|
|
518
|
+
"""
|
|
519
|
+
return self._image, self._image_number
|
|
520
|
+
|
|
521
|
+
def _start_sub_service(self):
|
|
522
|
+
"""Start a gRPC client service.
|
|
523
|
+
When the client calls one subscribe_events() or subscribe_images() with the
|
|
524
|
+
connection set to GRPC, the interface requires the client to start a gRPC server
|
|
525
|
+
that EnSight will call back to with event/image messages. This method starts
|
|
526
|
+
such a gRPC server."""
|
|
527
|
+
try:
|
|
528
|
+
if self._sub_service is not None:
|
|
529
|
+
return
|
|
530
|
+
self._sub_service = _EnSightSubServicer(parent=self)
|
|
531
|
+
self._sub_service.start()
|
|
532
|
+
except Exception:
|
|
533
|
+
self._sub_service = None
|
|
534
|
+
|
|
535
|
+
def subscribe_images(self, flip_vertical=False, use_shmem=True):
|
|
536
|
+
"""Subscribe to an image stream.
|
|
537
|
+
|
|
538
|
+
This methond makes a EnSightService::SubscribeImages() gRPC call. If
|
|
539
|
+
use_shmem is False, the transport system will be made over gRPC. It causes
|
|
540
|
+
EnSight to make a reverse gRPC connection over with gRPC calls with the
|
|
541
|
+
various images will be made. If use_shmem is True (the default), the \ref shmem will be used.
|
|
542
|
+
|
|
543
|
+
Parameters
|
|
544
|
+
---------
|
|
545
|
+
flip_vertical: bool
|
|
546
|
+
If True, the image pixels will be flipped over the X axis
|
|
547
|
+
use_shmem: bool
|
|
548
|
+
If True, use the shared memory transport, otherwise use reverse gRPC"""
|
|
549
|
+
self.connect()
|
|
550
|
+
if use_shmem:
|
|
551
|
+
try:
|
|
552
|
+
# we need a shared memory file
|
|
553
|
+
self._shmem_filename = self._find_filename()
|
|
554
|
+
if self._shmem_filename is not None:
|
|
555
|
+
conn_type = ensight_pb2.SubscribeImageOptions.SHARED_MEM
|
|
556
|
+
options = dict(filename=self._shmem_filename)
|
|
557
|
+
image_options = ensight_pb2.SubscribeImageOptions(
|
|
558
|
+
prefix=self.prefix(),
|
|
559
|
+
type=conn_type,
|
|
560
|
+
options=options,
|
|
561
|
+
flip_vertical=flip_vertical,
|
|
562
|
+
chunk=False,
|
|
563
|
+
)
|
|
564
|
+
_ = self._stub.SubscribeImages(image_options, metadata=self._metadata())
|
|
565
|
+
# start the local server
|
|
566
|
+
if not self._shmem_module:
|
|
567
|
+
self._attempt_shared_mem_import()
|
|
568
|
+
if self._shmem_module:
|
|
569
|
+
self._shmem_client = self._shmem_module.stream_create(self._shmem_filename)
|
|
570
|
+
else:
|
|
571
|
+
self.command("import ensight_grpc_shmem", do_eval=False)
|
|
572
|
+
to_send = self._shmem_filename.replace("\\", "\\\\")
|
|
573
|
+
self.command(
|
|
574
|
+
f"enscl._shmem_client = ensight_grpc_shmem.stream_create('{to_send}')",
|
|
575
|
+
do_eval=False,
|
|
576
|
+
)
|
|
577
|
+
if self.command("enscl._shmem_client is not None"):
|
|
578
|
+
self._shmem_client = True
|
|
579
|
+
|
|
580
|
+
# turn on the polling thread
|
|
581
|
+
self._image_thread = threading.Thread(target=self._poll_images)
|
|
582
|
+
self._image_thread.daemon = True
|
|
583
|
+
self._image_thread.start()
|
|
584
|
+
return
|
|
585
|
+
except Exception as e:
|
|
586
|
+
print("Unable to subscribe to an image stream via shared memory: {}".format(str(e)))
|
|
587
|
+
|
|
588
|
+
self._start_sub_service()
|
|
589
|
+
conn_type = ensight_pb2.SubscribeImageOptions.GRPC
|
|
590
|
+
options = {}
|
|
591
|
+
if self._sub_service:
|
|
592
|
+
options = dict(uri=self._sub_service._uri)
|
|
593
|
+
image_options = ensight_pb2.SubscribeImageOptions(
|
|
594
|
+
prefix=self.prefix(),
|
|
595
|
+
type=conn_type,
|
|
596
|
+
options=options,
|
|
597
|
+
flip_vertical=flip_vertical,
|
|
598
|
+
chunk=True,
|
|
599
|
+
)
|
|
600
|
+
_ = self._stub.SubscribeImages(image_options, metadata=self._metadata())
|
|
601
|
+
|
|
602
|
+
def image_stream_enable(self, flip_vertical=False):
|
|
603
|
+
"""Enable a simple gRPC-based image stream from EnSight.
|
|
604
|
+
|
|
605
|
+
This method makes a EnSightService::GetImageStream() gRPC call into EnSight, returning
|
|
606
|
+
an ensightservice::ImageReply stream. The method creates a thread to hold this
|
|
607
|
+
stream open and read new image frames from it. The thread places the read images
|
|
608
|
+
in this object. An external application can retrieve the most recent one using
|
|
609
|
+
get_image().
|
|
610
|
+
|
|
611
|
+
Parameters
|
|
612
|
+
----------
|
|
613
|
+
flip_vertical: bool
|
|
614
|
+
If True, the image will be flipped over the X axis before being sent from EnSight."""
|
|
615
|
+
if self._image_stream is not None:
|
|
616
|
+
return
|
|
617
|
+
self.connect()
|
|
618
|
+
self._image_stream = self._stub.GetImageStream(
|
|
619
|
+
ensight_pb2.ImageStreamRequest(flip_vertical=flip_vertical, chunk=True),
|
|
620
|
+
metadata=self._metadata(),
|
|
621
|
+
)
|
|
622
|
+
self._image_thread = threading.Thread(target=self._poll_images)
|
|
623
|
+
self._image_thread.daemon = True
|
|
624
|
+
self._image_thread.start()
|
|
625
|
+
|
|
626
|
+
def _put_image(self, the_image):
|
|
627
|
+
"""Store an image on this instance.
|
|
628
|
+
|
|
629
|
+
This method is used by threads to store the latest image they receive
|
|
630
|
+
so it can be accessed by get_image.
|
|
631
|
+
"""
|
|
632
|
+
self._image = the_image
|
|
633
|
+
self._image_number += 1
|
|
634
|
+
|
|
635
|
+
def image_stream_is_enabled(self):
|
|
636
|
+
"""Check to see if the image stream is enabled.
|
|
637
|
+
|
|
638
|
+
If an image stream has been successfully established via image_stream_enable(),
|
|
639
|
+
then this function returns True.
|
|
640
|
+
|
|
641
|
+
Returns
|
|
642
|
+
-------
|
|
643
|
+
(bool):
|
|
644
|
+
True if a ensightservice::ImageReply steam is active
|
|
645
|
+
"""
|
|
646
|
+
return self._image_stream is not None
|
|
647
|
+
|
|
648
|
+
def _poll_images(self):
|
|
649
|
+
"""Handle image streams.
|
|
650
|
+
|
|
651
|
+
This method is called by a Python thread to read imagery via the shared memory
|
|
652
|
+
transport system or the the ensightservice::ImageReply stream.
|
|
653
|
+
"""
|
|
654
|
+
try:
|
|
655
|
+
while self._stub is not None:
|
|
656
|
+
if self._shmem_client:
|
|
657
|
+
if self._shmem_module:
|
|
658
|
+
img = self._shmem_module.stream_lock(self._shmem_client)
|
|
659
|
+
else:
|
|
660
|
+
img = self.command("ensight_grpc_shmem.stream_lock(enscl._shmem_client)")
|
|
661
|
+
if type(img) is dict:
|
|
662
|
+
the_image = dict(
|
|
663
|
+
pixels=img["pixeldata"], width=img["width"], height=img["height"]
|
|
664
|
+
)
|
|
665
|
+
self._put_image(the_image)
|
|
666
|
+
if self._shmem_module:
|
|
667
|
+
self._shmem_module.stream_unlock(self._shmem_client)
|
|
668
|
+
else:
|
|
669
|
+
self.command(
|
|
670
|
+
"ensight_grpc_shmem.stream_unlock(enscl._shmem_client)",
|
|
671
|
+
do_eval=False,
|
|
672
|
+
)
|
|
673
|
+
|
|
674
|
+
if self._image_stream is not None:
|
|
675
|
+
img = self._image_stream.next()
|
|
676
|
+
buffer = img.pixels
|
|
677
|
+
|
|
678
|
+
while not img.final:
|
|
679
|
+
img = self._image_stream.next()
|
|
680
|
+
buffer += img.pixels
|
|
681
|
+
|
|
682
|
+
the_image = dict(pixels=buffer, width=img.width, height=img.height)
|
|
683
|
+
self._put_image(the_image)
|
|
684
|
+
except Exception:
|
|
685
|
+
# signal that the gRPC connection has broken
|
|
686
|
+
self._image_stream = None
|
|
687
|
+
self._image_thread = None
|
|
688
|
+
self._image = None
|
|
689
|
+
|
|
690
|
+
|
|
691
|
+
class _EnSightSubServicer(ensight_pb2_grpc.EnSightSubscriptionServicer):
|
|
692
|
+
"""Internal class handling reverse subscription connections.
|
|
693
|
+
The EnSight gRPC interface has a mechanism for reversing the gRPC
|
|
694
|
+
streams called Subscriptions. Image and event streams can be
|
|
695
|
+
subscribed to. In this mode, the client application starts a
|
|
696
|
+
gRPC server that implements the EnSightSubscription protocol.
|
|
697
|
+
EnSight will connect back to the client using this protocol and
|
|
698
|
+
send images/events back to the client as regular (non-stream)
|
|
699
|
+
rpc calls. This can be useful in situations where it is difficult
|
|
700
|
+
keep a long-running stream alive.
|
|
701
|
+
The EnSightSubServicer class implements a gRPC server for the client application.
|
|
702
|
+
"""
|
|
703
|
+
|
|
704
|
+
def __init__(self, parent: Optional["EnSightGRPC"] = None):
|
|
705
|
+
self._server: Optional["grpc.Server"] = None
|
|
706
|
+
self._uri: str = ""
|
|
707
|
+
self._parent = parent
|
|
708
|
+
|
|
709
|
+
def PublishEvent(self, request: Any, context: Any) -> "ensight_pb2.GenericResponse":
|
|
710
|
+
"""Publish an event to the remote server."""
|
|
711
|
+
if self._parent is not None:
|
|
712
|
+
self._parent._put_event(request)
|
|
713
|
+
return ensight_pb2.GenericResponse(str="Event Published")
|
|
714
|
+
|
|
715
|
+
def PublishImage(self, request_iterator: Any, context: Any) -> "ensight_pb2.GenericResponse":
|
|
716
|
+
"""Publish a single image (possibly in chucks) to the remote server."""
|
|
717
|
+
img: Any = request_iterator.next()
|
|
718
|
+
buffer = img.pixels
|
|
719
|
+
while not img.final:
|
|
720
|
+
img = request_iterator.next()
|
|
721
|
+
buffer += img.pixels
|
|
722
|
+
the_image = dict(pixels=buffer, width=img.width, height=img.height)
|
|
723
|
+
if self._parent is not None:
|
|
724
|
+
self._parent._put_image(the_image)
|
|
725
|
+
return ensight_pb2.GenericResponse(str="Image Published")
|
|
726
|
+
|
|
727
|
+
def start(self):
|
|
728
|
+
"""Start the gRPC server to be used for the EnSight Subscription Service."""
|
|
729
|
+
self._server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
|
|
730
|
+
ensight_pb2_grpc.add_EnSightSubscriptionServicer_to_server(self, self._server)
|
|
731
|
+
# Start the server on localhost with a random port
|
|
732
|
+
port = self._server.add_insecure_port("localhost:0")
|
|
733
|
+
self._uri = "localhost:" + str(port)
|
|
734
|
+
self._server.start()
|
{ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/renderable.py
RENAMED
|
@@ -557,7 +557,11 @@ class RenderableVNC(Renderable):
|
|
|
557
557
|
"""Generates an ansys-nexus-viewer component that can be used to connect to the EnSight VNC remote image renderer."""
|
|
558
558
|
|
|
559
559
|
def __init__(self, *args, **kwargs) -> None:
|
|
560
|
+
ui = kwargs.get("ui")
|
|
561
|
+
if kwargs.get("ui"):
|
|
562
|
+
kwargs.pop("ui")
|
|
560
563
|
super().__init__(*args, **kwargs)
|
|
564
|
+
self._ui = ui
|
|
561
565
|
self._generate_url()
|
|
562
566
|
self._rendertype = "remote"
|
|
563
567
|
self.update()
|
|
@@ -585,6 +589,7 @@ class RenderableVNC(Renderable):
|
|
|
585
589
|
"""
|
|
586
590
|
optional_query = self._get_query_parameters_str()
|
|
587
591
|
version = _get_ansysnexus_version(self._session._cei_suffix)
|
|
592
|
+
ui = "simple" if not self._ui else self._ui
|
|
588
593
|
if int(self._session._cei_suffix) < 242: # pragma: no cover
|
|
589
594
|
version = ""
|
|
590
595
|
self._update_2023R2_or_less() # pragma: no cover
|
|
@@ -604,7 +609,7 @@ class RenderableVNC(Renderable):
|
|
|
604
609
|
query_args = f', "extra_query_args":"{optional_query[1:]}"' # pragma: no cover
|
|
605
610
|
|
|
606
611
|
attributes = ' renderer="envnc"'
|
|
607
|
-
attributes +=
|
|
612
|
+
attributes += f" ui={ui}"
|
|
608
613
|
attributes += ' active="true"'
|
|
609
614
|
attributes += (
|
|
610
615
|
" renderer_options='"
|
{ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.2}/src/ansys/pyensight/core/session.py
RENAMED
|
@@ -838,6 +838,7 @@ class Session:
|
|
|
838
838
|
aa: int = 4,
|
|
839
839
|
fps: float = 30.0,
|
|
840
840
|
num_frames: Optional[int] = None,
|
|
841
|
+
ui: Optional[str] = "simple",
|
|
841
842
|
) -> "renderable.Renderable":
|
|
842
843
|
"""Capture the current EnSight scene or otherwise make it available for
|
|
843
844
|
display in a web browser.
|
|
@@ -898,7 +899,7 @@ class Session:
|
|
|
898
899
|
if self._html_port is None:
|
|
899
900
|
raise RuntimeError("No websocketserver has been associated with this Session")
|
|
900
901
|
|
|
901
|
-
kwargs = dict(
|
|
902
|
+
kwargs: Dict[str, Union[float, int, None, str]] = dict(
|
|
902
903
|
height=height, width=width, temporal=temporal, aa=aa, fps=fps, num_frames=num_frames
|
|
903
904
|
)
|
|
904
905
|
if self._jupyter_notebook: # pragma: no cover
|
|
@@ -924,6 +925,7 @@ class Session:
|
|
|
924
925
|
else:
|
|
925
926
|
render = RenderableSGEO(self, **kwargs)
|
|
926
927
|
elif what == "remote":
|
|
928
|
+
kwargs["ui"] = ui
|
|
927
929
|
render = RenderableVNC(self, **kwargs)
|
|
928
930
|
elif what == "remote_scene":
|
|
929
931
|
render = RenderableEVSN(self, **kwargs)
|
|
@@ -685,6 +685,9 @@ class DSGSession(object):
|
|
|
685
685
|
self._dsg_queue: Optional[queue.SimpleQueue] = None # Outgoing messages to EnSight
|
|
686
686
|
self._shutdown = False
|
|
687
687
|
self._dsg = None
|
|
688
|
+
# Prevent the protobuffer queue from growing w/o limits. The payload chunking is
|
|
689
|
+
# around 4MB, so 200 buffers would be a bit less than 1GB.
|
|
690
|
+
self._max_dsg_queue_size = int(os.environ.get("ANSYS_OV_SERVER_MAX_GRPC_QUEUE_SIZE", "200"))
|
|
688
691
|
self._normalize_geometry = normalize_geometry
|
|
689
692
|
self._vrmode = vrmode
|
|
690
693
|
self._time_scale = time_scale
|
|
@@ -711,6 +714,14 @@ class DSGSession(object):
|
|
|
711
714
|
def mesh_block_count(self) -> int:
|
|
712
715
|
return self._mesh_block_count
|
|
713
716
|
|
|
717
|
+
@property
|
|
718
|
+
def max_dsg_queue_size(self) -> int:
|
|
719
|
+
return self._max_dsg_queue_size
|
|
720
|
+
|
|
721
|
+
@max_dsg_queue_size.setter
|
|
722
|
+
def max_dsg_queue_size(self, value: int) -> None:
|
|
723
|
+
self._max_dsg_queue_size = value
|
|
724
|
+
|
|
714
725
|
@property
|
|
715
726
|
def vrmode(self) -> bool:
|
|
716
727
|
return self._vrmode
|
|
@@ -891,6 +902,11 @@ class DSGSession(object):
|
|
|
891
902
|
while not self._shutdown:
|
|
892
903
|
try:
|
|
893
904
|
self._message_queue.put(next(self._dsg)) # type:ignore
|
|
905
|
+
# if the queue is getting too deep, wait a bit to avoid holding too
|
|
906
|
+
# many messages (filling up memory)
|
|
907
|
+
if self.max_dsg_queue_size:
|
|
908
|
+
while self._message_queue.qsize() >= self.max_dsg_queue_size:
|
|
909
|
+
time.sleep(0.001)
|
|
894
910
|
except Exception:
|
|
895
911
|
self._shutdown = True
|
|
896
912
|
self.log("DSG connection broken, calling exit")
|