Skip to content

Commit b18a2ea

Browse files
authored
Blocking post display. (#256)
1 parent 29dc2cc commit b18a2ea

File tree

11 files changed

+207
-42
lines changed

11 files changed

+207
-42
lines changed

ansys/fluent/core/session.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ def __init__(
116116
self,
117117
ip: str = None,
118118
port: int = None,
119+
password: str = None,
119120
channel: grpc.Channel = None,
120121
cleanup_on_exit: bool = True,
121122
):
@@ -133,6 +134,8 @@ def __init__(
133134
Port to connect to existing Fluent instance. Used only
134135
when ``channel`` is ``None``. Defaults value can be set by
135136
the environment variable ``PYFLUENT_FLUENT_PORT=<port>``.
137+
password : str, optional
138+
Password to connect to existing Fluent instance.
136139
channel : grpc.Channel, optional
137140
Grpc channel to use to connect to existing Fluent instance.
138141
ip and port arguments will be ignored when channel is
@@ -154,7 +157,9 @@ def __init__(
154157
"The port to connect to Fluent session is not provided."
155158
)
156159
self._channel = grpc.insecure_channel(f"{ip}:{port}")
157-
self._metadata: List[Tuple[str, str]] = []
160+
self._metadata: List[Tuple[str, str]] = (
161+
[("password", password)] if password else []
162+
)
158163
self._id = f"session-{next(Session._id_iter)}"
159164
self._settings_root = None
160165

@@ -229,8 +234,12 @@ def create_from_server_info_file(
229234
Session instance
230235
"""
231236
ip, port, password = _parse_server_info_file(server_info_filepath)
232-
session = Session(ip=ip, port=port, cleanup_on_exit=cleanup_on_exit)
233-
session._metadata.append(("password", password))
237+
session = Session(
238+
ip=ip,
239+
port=port,
240+
password=password,
241+
cleanup_on_exit=cleanup_on_exit,
242+
)
234243
return session
235244

236245
@property

ansys/fluent/post/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,5 +84,4 @@ def _update_vtk_version():
8484

8585
if import_errors:
8686
raise ImportError("\n".join(import_errors))
87-
88-
import ansys.fluent.post.pyvista as pyvista # noqa: F401
87+
from ansys.fluent.post._config import get_config, set_config # noqa: F401

ansys/fluent/post/_config.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""Global configuration state for post."""
2+
import threading
3+
4+
_global_config = {
5+
"blocking": False,
6+
}
7+
_threadlocal = threading.local()
8+
9+
10+
def _get_threadlocal_config():
11+
if not hasattr(_threadlocal, "global_config"):
12+
_threadlocal.global_config = _global_config.copy()
13+
return _threadlocal.global_config
14+
15+
16+
def get_config() -> dict:
17+
"""
18+
Retrieve post configuration.
19+
20+
Returns
21+
-------
22+
config : dict
23+
Keys are parameter names that can be passed to :func:`set_config`.
24+
"""
25+
return _get_threadlocal_config().copy()
26+
27+
28+
def set_config(blocking: bool = False):
29+
"""
30+
Set post configuration.
31+
32+
Parameters
33+
----------
34+
blocking : bool, default=False
35+
If True, then graphics/plot display will block the current thread.
36+
"""
37+
local_config = _get_threadlocal_config()
38+
local_config["blocking"] = blocking

ansys/fluent/post/matplotlib/matplot_objects.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,7 @@ def __init__(self, session, local_surfaces_provider=None):
3333
else:
3434
self.__dict__ = session_state
3535
self._local_surfaces_provider = (
36-
lambda: local_surfaces_provider
37-
if local_surfaces_provider
38-
else self.Surfaces
39-
if hasattr(self, "Surfaces")
40-
else []
36+
lambda: local_surfaces_provider or getattr(self, "Surfaces", [])
4137
)
4238

4339
def _init_module(self, obj, mod):

ansys/fluent/post/matplotlib/matplot_windows_manager.py

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
from typing import List, Optional, Union
55

66
import numpy as np
7+
78
from ansys.fluent.core.session import Session
89
from ansys.fluent.core.utils.generic import AbstractSingletonMeta, in_notebook
10+
from ansys.fluent.post import get_config
911
from ansys.fluent.post.matplotlib.plotter_defns import Plotter, ProcessPlotter
1012
from ansys.fluent.post.post_object_defns import GraphicsDefn, PlotDefn
1113
from ansys.fluent.post.post_windows_manager import (
@@ -40,6 +42,9 @@ def plot(self, data):
4042
def set_properties(self, properties):
4143
self.plot_pipe.send({"properties": properties})
4244

45+
def save_graphic(self, name: str):
46+
self.plot_pipe.send({"save_graphic": name})
47+
4348
def is_closed(self):
4449
if self._closed:
4550
return True
@@ -82,15 +87,13 @@ def __init__(self, id: str, post_object: Union[GraphicsDefn, PlotDefn]):
8287
self.animate: bool = False
8388
self.close: bool = False
8489
self.refresh: bool = False
85-
if in_notebook():
86-
self.plotter()
8790

8891
def plot(self):
8992
"""Draw plot."""
9093
if not self.post_object:
9194
return
9295
xy_data = self._get_xy_plot_data()
93-
if in_notebook():
96+
if in_notebook() or get_config()["blocking"]:
9497
self.plotter.set_properties(self.properties)
9598
else:
9699
try:
@@ -106,7 +109,7 @@ def plot(self):
106109
def _get_plotter(self):
107110
return (
108111
Plotter(self.id)
109-
if in_notebook()
112+
if in_notebook() or get_config()["blocking"]
110113
else _ProcessPlotterHandle(self.id)
111114
)
112115

@@ -244,6 +247,31 @@ def plot(
244247
window.post_object = object
245248
window.plot()
246249

250+
def save_graphic(
251+
self,
252+
window_id: str,
253+
format: str,
254+
) -> None:
255+
"""
256+
Save graphics.
257+
258+
Parameters
259+
----------
260+
window_id : str
261+
Window id for which graphic should be saved.
262+
format : str
263+
Graphic format. Supported formats are eps, jpeg, jpg,
264+
pdf, pgf, png, ps, raw, rgba, svg, svgz, tif and tiff.
265+
266+
Raises
267+
------
268+
ValueError
269+
If window does not support specified format.
270+
"""
271+
window = self._post_windows.get(window_id)
272+
if window:
273+
window.plotter.save_graphic(f"{window_id}.{format}")
274+
247275
def refresh_windows(
248276
self,
249277
session_id: Optional[str] = "",
@@ -332,7 +360,10 @@ def _open_window(
332360
if (
333361
window
334362
and not window.plotter.is_closed()
335-
and (not in_notebook() or window.refresh)
363+
and (
364+
not (in_notebook() or get_config()["blocking"])
365+
or window.refresh
366+
)
336367
):
337368
window.refresh = False
338369
else:

ansys/fluent/post/matplotlib/plotter_defns.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ def __init__(
5050
self._max_x = None
5151
self._data = {}
5252
self._closed = False
53+
self._visible = False
5354
if not remote_process:
5455
self.fig = plt.figure(num=self._window_id)
5556
self.ax = self.fig.add_subplot(111)
@@ -98,6 +99,9 @@ def plot(self, data: dict) -> None:
9899
self.ax.set_ylim(
99100
self._min_y - y_range * 0.2, self._max_y + y_range * 0.2
100101
)
102+
if not self._visible:
103+
self._visible = True
104+
plt.show()
101105

102106
def close(self):
103107
"""Close window."""
@@ -108,6 +112,17 @@ def is_closed(self):
108112
"""Check if window is closed."""
109113
return self._closed
110114

115+
def save_graphic(self, file_name: str):
116+
"""
117+
Save graphics.
118+
119+
Parameters
120+
----------
121+
file_name : str
122+
File name to save graphic.
123+
"""
124+
plt.savefig(file_name)
125+
111126
def set_properties(self, properties: dict):
112127
"""
113128
Set plot properties.
@@ -131,6 +146,7 @@ def set_properties(self, properties: dict):
131146
def __call__(self):
132147
"""Reset and show plot."""
133148
self._reset()
149+
self._visible = True
134150
plt.show()
135151

136152
# private methods
@@ -193,6 +209,9 @@ def _call_back(self):
193209
if "properties" in data:
194210
properties = data["properties"]
195211
self.set_properties(properties)
212+
elif "save_graphic" in data:
213+
name = data["save_graphic"]
214+
self.save_graphic(name)
196215
else:
197216
self.plot(data)
198217
self.fig.canvas.draw()
@@ -209,4 +228,5 @@ def __call__(self, pipe):
209228
timer = self.fig.canvas.new_timer(interval=10)
210229
timer.add_callback(self._call_back)
211230
timer.start()
231+
self._visible = True
212232
plt.show()

ansys/fluent/post/post_windows_manager.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,29 @@ def plot(
8383
"""
8484
pass
8585

86+
@abstractmethod
87+
def save_graphic(
88+
self,
89+
window_id: str,
90+
format: str,
91+
) -> None:
92+
"""
93+
Save graphics.
94+
95+
Parameters
96+
----------
97+
window_id : str
98+
Window id for which graphic should be saved.
99+
format : str
100+
Graphic format.
101+
102+
Raises
103+
------
104+
ValueError
105+
If window does not support specified format.
106+
"""
107+
pass
108+
86109
@abstractmethod
87110
def refresh_windows(
88111
self,

ansys/fluent/post/pyvista/pyvista_objects.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,7 @@ def __init__(self, session, local_surfaces_provider=None):
4545
else:
4646
self.__dict__ = session_state
4747
self._local_surfaces_provider = (
48-
lambda: local_surfaces_provider
49-
if local_surfaces_provider
50-
else self.Surfaces
51-
if hasattr(self, "Surfaces")
52-
else []
48+
lambda: local_surfaces_provider or getattr(self, "Surfaces", [])
5349
)
5450

5551
def _init_module(self, obj, mod):

ansys/fluent/post/pyvista/pyvista_windows_manager.py

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
from ansys.fluent.core.session import Session
1111
from ansys.fluent.core.utils.generic import AbstractSingletonMeta, in_notebook
12+
from ansys.fluent.post import get_config
1213
from ansys.fluent.post.post_object_defns import GraphicsDefn, PlotDefn
1314
from ansys.fluent.post.post_windows_manager import (
1415
PostWindow,
@@ -33,16 +34,16 @@ def __init__(self, id: str, post_object: Union[GraphicsDefn, PlotDefn]):
3334
self.post_object: Union[GraphicsDefn, PlotDefn] = post_object
3435
self.id: str = id
3536
self.plotter: Union[BackgroundPlotter, pv.Plotter] = (
36-
pv.Plotter()
37-
if in_notebook()
37+
pv.Plotter(title=f"PyFluent ({self.id})")
38+
if in_notebook() or get_config()["blocking"]
3839
else BackgroundPlotter(title=f"PyFluent ({self.id})")
3940
)
4041
self.animate: bool = False
4142
self.close: bool = False
4243
self.refresh: bool = False
4344
self.update: bool = False
45+
self._visible: bool = False
4446
self._init_properties()
45-
self.plotter.show()
4647

4748
def plot(self):
4849
"""Plot graphics."""
@@ -64,6 +65,9 @@ def plot(self):
6465
if self.animate:
6566
plotter.write_frame()
6667
plotter.camera = camera.copy()
68+
if not self._visible:
69+
plotter.show()
70+
self._visible = True
6771

6872
# private methods
6973

@@ -415,7 +419,7 @@ def open_window(self, window_id: Optional[str] = None) -> str:
415419
with self._condition:
416420
if not window_id:
417421
window_id = self._get_unique_window_id()
418-
if in_notebook():
422+
if in_notebook() or get_config()["blocking"]:
419423
self._open_window_notebook(window_id)
420424
else:
421425
self._open_and_plot_console(None, window_id)
@@ -473,11 +477,36 @@ def plot(
473477
with self._condition:
474478
if not window_id:
475479
window_id = self._get_unique_window_id()
476-
if in_notebook():
480+
if in_notebook() or get_config()["blocking"]:
477481
self._plot_notebook(object, window_id)
478482
else:
479483
self._open_and_plot_console(object, window_id)
480484

485+
def save_graphic(
486+
self,
487+
window_id: str,
488+
format: str,
489+
) -> None:
490+
"""
491+
Save graphics.
492+
493+
Parameters
494+
----------
495+
window_id : str
496+
Window id for which graphic should be saved.
497+
format : str
498+
Graphic format. Supported formats are svg, eps, ps, pdf and tex.
499+
500+
Raises
501+
------
502+
ValueError
503+
If window does not support specified format.
504+
"""
505+
with self._condition:
506+
window = self._post_windows.get(window_id)
507+
if window:
508+
window.plotter.save_graphic(f"{window_id}.{format}")
509+
481510
def refresh_windows(
482511
self,
483512
session_id: Optional[str] = "",
@@ -561,7 +590,7 @@ def close_windows(
561590
for window_id in windows_id:
562591
window = self._post_windows.get(window_id)
563592
if window:
564-
if in_notebook():
593+
if in_notebook() or get_config()["blocking"]:
565594
window.plotter.close()
566595
window.close = True
567596

0 commit comments

Comments
 (0)