Skip to content

Commit 7fceb1f

Browse files
authored
chore: Update optional dependencies. (#564)
Update optional dependencies.
1 parent cf53021 commit 7fceb1f

File tree

7 files changed

+113
-71
lines changed

7 files changed

+113
-71
lines changed

README.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,19 @@ Install the latest release from `PyPI
6464
6565
pip install ansys-fluent-visualization
6666
67+
There are optional dependencies depending on the desired usage mode.
68+
To run the plotter in interactive mode, install with:
69+
70+
.. code:: console
71+
72+
pip install ansys-fluent-visualization[interactive]
73+
74+
For interactive mode with graphics displayed in a single Qt window using multiple tabs, install with:
75+
76+
.. code:: console
77+
78+
pip install ansys-fluent-visualization[single-window]
79+
6780
Alternatively, install the latest release from `GitHub
6881
<https://github.com/ansys/pyfluent-visualization>`_ with:
6982

pyproject.toml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,12 @@ importlib-metadata = {version = "^4.0", python = "<3.9"}
2828
ansys-fluent-core = "~=0.34.0"
2929
pyvista = ">=0.44.0"
3030
matplotlib = ">=3.6.0"
31-
pyvistaqt = "~=0.11.1"
32-
pyside6 = "~=6.8.1"
33-
imageio= ">=2.36.1"
31+
pyvistaqt = { version = "~=0.11.1", optional = true }
32+
pyside6 = { version = "~=6.8.1", optional = true }
33+
34+
[tool.poetry.extras]
35+
interactive = ["pyvistaqt"]
36+
single-window = ["pyvistaqt", "pyside6"]
3437

3538
[tool.poetry.urls]
3639
"Documentation" = "https://visualization.fluent.docs.pyansys.com/"

src/ansys/fluent/visualization/graphics/graphics_windows.py

Lines changed: 13 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,6 @@
2121
# SOFTWARE.
2222

2323
"""A wrapper to improve the user interface of graphics."""
24-
from PySide6.QtWidgets import (
25-
QApplication,
26-
QMainWindow,
27-
QTabWidget,
28-
QVBoxLayout,
29-
QWidget,
30-
)
31-
3224
import ansys.fluent.visualization as pyviz
3325
from ansys.fluent.visualization.graphics import graphics_windows_manager
3426

@@ -61,6 +53,19 @@ def __init__(
6153
except AttributeError:
6254
self.plotter = None
6355
if pyviz.config.single_window:
56+
try:
57+
from PySide6.QtWidgets import QApplication
58+
59+
from ansys.fluent.visualization.graphics.single_qt_windows import (
60+
MainWindow,
61+
)
62+
except ModuleNotFoundError as ex:
63+
raise ModuleNotFoundError(
64+
"Missing dependencies, "
65+
"use 'pip install ansys-fluent-visualization[single-window]' "
66+
"to install them."
67+
) from ex
68+
6469
global _qt_window
6570
if not _qt_window:
6671
QApplication.instance() or QApplication()
@@ -176,42 +181,3 @@ def close(
176181
graphics_windows_manager.close_windows(
177182
windows_id=[self.window_id], session_id=session_id
178183
)
179-
180-
181-
# Define the main window
182-
class MainWindow(QMainWindow):
183-
def __init__(self):
184-
super().__init__()
185-
self.setWindowTitle("PyFluent Visualization Plots")
186-
screen = QApplication.primaryScreen().availableGeometry()
187-
width = int(screen.width() * 0.75)
188-
height = int(screen.height() * 0.75)
189-
self.setGeometry(
190-
(screen.width() - width) // 2, # Center X
191-
(screen.height() - height) // 2, # Center Y
192-
width,
193-
height,
194-
)
195-
self.tabs = QTabWidget()
196-
self.setCentralWidget(self.tabs)
197-
self.tabs.setMovable(True)
198-
self.plotters = []
199-
200-
def _add_tab(self, plotter, title="-"):
201-
tab = QWidget()
202-
layout = QVBoxLayout()
203-
204-
self.plotters.append(plotter)
205-
layout.addWidget(plotter.interactor)
206-
tab.setLayout(layout)
207-
208-
# Add tabs with PyVista BackgroundPlotters
209-
self.tabs.addTab(tab, f"PyViz ({title})")
210-
211-
def closeEvent(self, event):
212-
"""Ensure proper cleanup of plotter instances on window close."""
213-
for plotter in self.plotters:
214-
plotter.close() # Properly close each PyVista plotter
215-
event.accept()
216-
global _qt_window
217-
_qt_window = None

src/ansys/fluent/visualization/graphics/graphics_windows_manager.py

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from enum import Enum
2626
import itertools
2727
import threading
28-
from typing import Dict, List, Optional, Union
28+
from typing import Dict, List, Optional
2929

3030
import numpy as np
3131
import pyvista as pv
@@ -36,12 +36,6 @@
3636
PlotDefn,
3737
)
3838
from ansys.fluent.interface.post_objects.singleton_meta import AbstractSingletonMeta
39-
40-
try:
41-
from pyvistaqt import BackgroundPlotter
42-
except ModuleNotFoundError:
43-
BackgroundPlotter = None
44-
4539
import ansys.fluent.visualization as pyviz
4640
from ansys.fluent.visualization.post_data_extractor import (
4741
FieldDataExtractor,
@@ -691,7 +685,7 @@ def get_window(self, window_id: str) -> GraphicsWindow:
691685
with self._condition:
692686
return self._post_windows.get(window_id, None)
693687

694-
def get_plotter(self, window_id: str) -> Union[BackgroundPlotter, pv.Plotter]:
688+
def get_plotter(self, window_id: str):
695689
"""Get the PyVista plotter.
696690
697691
Parameters
@@ -701,8 +695,7 @@ def get_plotter(self, window_id: str) -> Union[BackgroundPlotter, pv.Plotter]:
701695
702696
Returns
703697
-------
704-
Union[BackgroundPlotter, pv.Plotter]
705-
PyVista plotter.
698+
Plotter.
706699
"""
707700
with self._condition:
708701
return self._post_windows[window_id].renderer.plotter

src/ansys/fluent/visualization/graphics/pyvista/renderer.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,12 @@
2828

2929
try:
3030
from pyvistaqt import BackgroundPlotter
31-
except ModuleNotFoundError:
32-
BackgroundPlotter = None
31+
except ModuleNotFoundError as ex:
32+
if pyviz.config.interactive:
33+
raise ModuleNotFoundError(
34+
"Missing dependencies, "
35+
"use 'pip install ansys-fluent-visualization[interactive]' to install them."
36+
) from ex
3337

3438
from ansys.fluent.visualization.base.renderer import AbstractRenderer
3539

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Copyright (C) 2022 - 2025 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+
"""Module defining qt single window to add graphics."""
23+
24+
from PySide6.QtWidgets import (
25+
QApplication,
26+
QMainWindow,
27+
QTabWidget,
28+
QVBoxLayout,
29+
QWidget,
30+
)
31+
32+
33+
# Define the main window
34+
class MainWindow(QMainWindow):
35+
def __init__(self):
36+
super().__init__()
37+
self.setWindowTitle("PyFluent Visualization Plots")
38+
screen = QApplication.primaryScreen().availableGeometry()
39+
width = int(screen.width() * 0.75)
40+
height = int(screen.height() * 0.75)
41+
self.setGeometry(
42+
(screen.width() - width) // 2, # Center X
43+
(screen.height() - height) // 2, # Center Y
44+
width,
45+
height,
46+
)
47+
self.tabs = QTabWidget()
48+
self.setCentralWidget(self.tabs)
49+
self.tabs.setMovable(True)
50+
self.plotters = []
51+
52+
def _add_tab(self, plotter, title="-"):
53+
tab = QWidget()
54+
layout = QVBoxLayout()
55+
56+
self.plotters.append(plotter)
57+
if plotter:
58+
layout.addWidget(plotter.interactor)
59+
tab.setLayout(layout)
60+
61+
# Add tabs with PyVista BackgroundPlotters
62+
self.tabs.addTab(tab, f"PyViz ({title})")
63+
64+
def closeEvent(self, event):
65+
"""Ensure proper cleanup of plotter instances on window close."""
66+
for plotter in self.plotters:
67+
plotter.close() # Properly close each PyVista plotter
68+
event.accept()
69+
global _qt_window
70+
_qt_window = None

tests/test_visualization.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656
XYPlot,
5757
config,
5858
)
59+
60+
config.interactive = False
5961
from ansys.fluent.visualization.graphics.graphics_windows_manager import (
6062
GraphicsWindow as TGraphicsWindow,
6163
)
@@ -93,7 +95,6 @@ def test_visualization_calls_render_correctly_with_single_mesh(
9395
new_solver_session_with_exhaust_case_and_data,
9496
):
9597
with patch.object(Renderer, "render") as mock_render:
96-
config.interactive = False
9798
solver = new_solver_session_with_exhaust_case_and_data
9899
mesh_surfaces_list = [
99100
"in1",
@@ -152,7 +153,6 @@ def test_visualization_calls_render_correctly_with_dual_mesh(
152153
new_solver_session_with_exhaust_case_and_data,
153154
):
154155
with patch.object(Renderer, "render") as mock_render:
155-
config.interactive = False
156156
solver = new_solver_session_with_exhaust_case_and_data
157157
mesh_surfaces_list = [
158158
"in1",
@@ -209,7 +209,6 @@ def test_visualization_calls_render_correctly_with_plane_and_iso_surface(
209209
new_solver_session_with_exhaust_case_and_data,
210210
):
211211
with patch.object(Renderer, "render") as mock_render:
212-
config.interactive = False
213212
solver = new_solver_session_with_exhaust_case_and_data
214213
TGraphicsWindow.show_graphics = lambda win_id: None
215214

@@ -264,7 +263,6 @@ def test_visualization_calls_render_correctly_with_contour(
264263
new_solver_session_with_exhaust_case_and_data,
265264
):
266265
with patch.object(Renderer, "render") as mock_render:
267-
config.interactive = False
268266
solver = new_solver_session_with_exhaust_case_and_data
269267
TGraphicsWindow.show_graphics = lambda win_id: None
270268
contour = Contour(
@@ -301,7 +299,6 @@ def test_visualization_calls_render_correctly_with_vector(
301299
new_solver_session_with_exhaust_case_and_data,
302300
):
303301
with patch.object(Renderer, "render") as mock_render:
304-
config.interactive = False
305302
solver = new_solver_session_with_exhaust_case_and_data
306303
TGraphicsWindow.show_graphics = lambda win_id: None
307304
velocity_vector = Vector(
@@ -334,7 +331,6 @@ def test_visualization_calls_render_correctly_with_pathlines(
334331
new_solver_session_with_exhaust_case_and_data,
335332
):
336333
with patch.object(Renderer, "render") as mock_render:
337-
config.interactive = False
338334
solver = new_solver_session_with_exhaust_case_and_data
339335
TGraphicsWindow.show_graphics = lambda win_id: None
340336
pathlines = Pathline(solver=solver)
@@ -366,7 +362,6 @@ def test_visualization_calls_render_correctly_with_xy_plot_pyvista(
366362
new_solver_session_with_exhaust_case_and_data,
367363
):
368364
with patch.object(Plotter, "render") as mock_render:
369-
config.interactive = False
370365
solver = new_solver_session_with_exhaust_case_and_data
371366
TPlotterWindow._show_plot = lambda win_id: None
372367
xy_plot_object = XYPlot(
@@ -396,7 +391,6 @@ def test_visualization_calls_render_correctly_with_xy_plot_matplotlib(
396391
new_solver_session_with_exhaust_case_and_data,
397392
):
398393
with patch.object(MatPlotter, "render") as mock_render:
399-
config.interactive = False
400394
solver = new_solver_session_with_exhaust_case_and_data
401395
TPlotterWindow._show_plot = lambda win_id: None
402396
xy_plot_object = XYPlot(
@@ -426,7 +420,6 @@ def test_visualization_calls_render_correctly_with_monitor_plot(
426420
new_solver_session_with_exhaust_case_and_data,
427421
):
428422
with patch.object(Plotter, "render") as mock_render:
429-
config.interactive = False
430423
solver = new_solver_session_with_exhaust_case_and_data
431424
TPlotterWindow._show_plot = lambda win_id: None
432425
residual = Monitor(solver=solver)

0 commit comments

Comments
 (0)