Skip to content

Commit

Permalink
docs: event streaming callback (#3546)
Browse files Browse the repository at this point in the history
* docs: event streaming callback

* docs: event streaming callback

* feat: optional last

* docs: move cheatsheet build to nightly
  • Loading branch information
mkundu1 authored Dec 3, 2024
1 parent 5a1c077 commit b556f1e
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 44 deletions.
17 changes: 1 addition & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,22 +115,6 @@ jobs:
restore-keys: |
Python-${{ runner.os }}-${{ matrix.python-version }}
- name: Install Quarto
uses: quarto-dev/quarto-actions/setup@v2
with:
tinytex: true

- name: Check Quarto Version
shell: bash
run: |
quarto --version
- name: "Install Poppler for PDF to PNG conversion"
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y poppler-utils
- name: Install pyfluent
run: make install

Expand Down Expand Up @@ -197,6 +181,7 @@ jobs:
make build-doc-source
env:
FLUENT_IMAGE_TAG: ${{ env.DOC_DEPLOYMENT_IMAGE_TAG }}
PYFLUENT_DOC_SKIP_CHEATSHEET: 1

- name: Zip HTML Documentation before upload
run: |
Expand Down
16 changes: 16 additions & 0 deletions .github/workflows/doc-build-dev-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,22 @@ jobs:
sudo apt update
sudo apt-get install pandoc libegl1 make xvfb libfontconfig1 libxrender1 libxkbcommon-x11-0 -y
- name: Install Quarto
uses: quarto-dev/quarto-actions/setup@v2
with:
tinytex: true

- name: Check Quarto Version
shell: bash
run: |
quarto --version
- name: "Install Poppler for PDF to PNG conversion"
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y poppler-utils
- name: Install pyfluent
run: make install

Expand Down
16 changes: 16 additions & 0 deletions .github/workflows/doc-build-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,22 @@ jobs:
sudo apt update
sudo apt-get install pandoc libegl1 make xvfb libfontconfig1 libxrender1 libxkbcommon-x11-0 -y
- name: Install Quarto
uses: quarto-dev/quarto-actions/setup@v2
with:
tinytex: true

- name: Check Quarto Version
shell: bash
run: |
quarto --version
- name: "Install Poppler for PDF to PNG conversion"
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y poppler-utils
- name: Install pyfluent
run: make install

Expand Down
13 changes: 6 additions & 7 deletions doc/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,7 @@

toggleprompt_offset_right = 35

skip_examples = int(os.getenv("PYFLUENT_SKIP_EXAMPLES_DOC", 0))
if skip_examples:
pass
else:
if os.getenv("PYFLUENT_DOC_SKIP_EXAMPLES") != "1":
extensions.append("sphinx_gallery.gen_gallery")

typehints_document_rtype = False
Expand Down Expand Up @@ -197,13 +194,15 @@ def _stop_fluent_container(gallery_conf, fname):
"navbar_end": ["version-switcher", "theme-switcher", "navbar-icon-links"],
"navigation_depth": -1,
"collapse_navigation": True,
"cheatsheet": {
}

if os.getenv("PYFLUENT_DOC_SKIP_CHEATSHEET") != "1":
html_theme_options["cheatsheet"] = {
"file": "cheatsheet/cheat_sheet.qmd",
"pages": ["index", "getting_started/index", "user_guide/index"],
"title": "PyFluent cheat sheet",
"version": __version__,
},
}
}

# -- Options for HTMLHelp output ---------------------------------------------

Expand Down
6 changes: 4 additions & 2 deletions doc/source/contributing/environment_variables.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ Following is a list of environment variables that can be set to control various
- Specifies the path inside the container where the host path is mounted while starting a Fluent container in :func:`launch_fluent() <ansys.fluent.core.launcher.launcher.launch_fluent>`.
* - PYFLUENT_FLUENT_DEBUG
- Starts Fluent in debug mode while launching Fluent in :func:`launch_fluent() <ansys.fluent.core.launcher.launcher.launch_fluent>`.
* - PYFLUENT_DOC_SKIP_CHEATSHEET:
- Skips the generation of cheatsheet.
* - PYFLUENT_DOC_SKIP_EXAMPLES
- Skips the generation of examples documentation.
* - PYFLUENT_FLUENT_IP
- Specifies the IP address of the Fluent server in :func:`connect_to_fluent() <ansys.fluent.core.launcher.launcher.connect_to_fluent>`.
* - PYFLUENT_FLUENT_PORT
Expand All @@ -47,8 +51,6 @@ Following is a list of environment variables that can be set to control various
- Shows the Fluent GUI while launching Fluent in :func:`launch_fluent() <ansys.fluent.core.launcher.launcher.launch_fluent>`.
* - PYFLUENT_SKIP_API_UPGRADE_ADVICE
- Disables printing of TUI to settings API upgrade advice.
* - PYFLUENT_SKIP_EXAMPLES_DOC
- Skips the generation of examples documentation.
* - PYFLUENT_TIMEOUT_FORCE_EXIT
- Enables force exit while exiting a Fluent session and specifies the timeout in seconds.
* - PYFLUENT_WATCHDOG_DEBUG
Expand Down
21 changes: 14 additions & 7 deletions doc/source/user_guide/events.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,27 @@ The following code triggers a callback at the end of every iteration.

.. code-block:: python
>>> from ansys.fluent.core import SolverEvent
>>> from ansys.fluent.core import SolverEvent, IterationEndedEventInfo
>>>
>>> def on_iteration_ended(session, event_info):
>>> def on_iteration_ended(session, event_info: IterationEndedEventInfo):
>>> print("Iteration ended. Index = ", event_info.index)
>>>
>>> callback_id = solver.events.register_callback(SolverEvent.ITERATION_ENDED, on_iteration_ended)
>>>
The general signature of the callback function is ``cb(session, event_info, <additional arguments>)``, where ``session`` is the session instance
and ``event_info`` instance holds information about the event. The event information classes for each event are documented in the
API reference of the :obj:`~ansys.fluent.core.streaming_services.events_streaming` module. See the callback function
``on_case_loaded_with_args()`` in the below examples for an example of how to pass additional arguments to the callback
function.


Examples
--------

.. code-block:: python
>>> from ansys.fluent.core import MeshingEvent, SolverEvent
>>> from ansys.fluent.core import CaseLoadedEventInfo, DataLoadedEventInfo, SolutionInitializedEventInfo, IterationEndedEventInfo
>>> from ansys.fluent.core.utils.event_loop import execute_in_event_loop_threadsafe
>>> from ansys.fluent.visualization.matplotlib import matplot_windows_manager
>>> from ansys.fluent.visualization.pyvista import pyvista_windows_manager
Expand All @@ -48,26 +55,26 @@ Examples
>>> contour2.surfaces_list = ["symmetry"]
>>>
>>> @execute_in_event_loop_threadsafe
>>> def auto_refersh_call_back_iteration(session, event_info):
>>> def auto_refersh_call_back_iteration(session, event_info: IterationEndedEventInfo):
>>> if event_info.index % 5 == 0:
>>> pyvista_windows_manager.refresh_windows(session.id, ["contour-1", "contour-2"])
>>> matplot_windows_manager.refresh_windows("", ["residual"])
>>>
>>> callback_itr_id = solver.events.register_callback(SolverEvent.ITERATION_ENDED, auto_refersh_call_back_iteration)
>>>
>>> @execute_in_event_loop_threadsafe
>>> def initialize_call_back(session, event_info):
>>> def initialize_call_back(session, event_info: SolutionInitializedEventInfo | DataLoadedEventInfo):
>>> pyvista_windows_manager.refresh_windows(session.id, ["contour-1", "contour-2"])
>>> matplot_windows_manager.refresh_windows("", ["residual"])
>>>
>>> callback_init_id = solver.events.register_callback(SolverEvent.SOLUTION_INITIALIZED, initialize_call_back)
>>>
>>> callback_data_read_id = solver.events.register_callback(SolverEvent.DATA_LOADED, initialize_call_back)
>>>
>>> def on_case_loaded(session, event_info):
>>> def on_case_loaded(session, event_info: CaseLoadedEventInfo):
>>> print("Case loaded. Index = ", event_info.index)
>>>
>>> def on_case_loaded_with_args(x, y, session, event_info):
>>> def on_case_loaded_with_args(session, event_info: CaseLoadedEventInfo, x, y):
>>> print(f"Case loaded with {x}, {y}. Index = ", event_info.index)
>>>
>>> callback = meshing.events.register_callback(MeshingEvent.CASE_LOADED, on_case_loaded)
Expand Down
39 changes: 28 additions & 11 deletions src/ansys/fluent/core/streaming_services/events_streaming.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from ansys.fluent.core.warnings import PyFluentDeprecationWarning

__all__ = [
"EventsManager",
"Event",
"SolverEvent",
"MeshingEvent",
Expand Down Expand Up @@ -128,6 +129,7 @@ def __getattr__(self, name):
@dataclass
class TimestepStartedEventInfo(EventInfoBase, event=SolverEvent.TIMESTEP_STARTED):
"""Information about the event triggered when a timestep is started.
Attributes
----------
index : int
Expand All @@ -143,6 +145,7 @@ class TimestepStartedEventInfo(EventInfoBase, event=SolverEvent.TIMESTEP_STARTED
@dataclass
class TimestepEndedEventInfo(EventInfoBase, event=SolverEvent.TIMESTEP_ENDED):
"""Information about the event triggered when a timestep is ended.
Attributes
----------
index : int
Expand All @@ -158,6 +161,7 @@ class TimestepEndedEventInfo(EventInfoBase, event=SolverEvent.TIMESTEP_ENDED):
@dataclass
class IterationEndedEventInfo(EventInfoBase, event=SolverEvent.ITERATION_ENDED):
"""Information about the event triggered when an iteration is ended.
Attributes
----------
index : int
Expand Down Expand Up @@ -190,6 +194,7 @@ class CalculationsResumedEventInfo(
@dataclass
class AboutToLoadCaseEventInfo(EventInfoBase, event=SolverEvent.ABOUT_TO_LOAD_CASE):
"""Information about the event triggered just before a case file is loaded.
Attributes
----------
case_file_name : str
Expand All @@ -202,6 +207,7 @@ class AboutToLoadCaseEventInfo(EventInfoBase, event=SolverEvent.ABOUT_TO_LOAD_CA
@dataclass
class CaseLoadedEventInfo(EventInfoBase, event=SolverEvent.CASE_LOADED):
"""Information about the event triggered after a case file is loaded.
Attributes
----------
case_file_name : str
Expand All @@ -214,6 +220,7 @@ class CaseLoadedEventInfo(EventInfoBase, event=SolverEvent.CASE_LOADED):
@dataclass
class AboutToLoadDataEventInfo(EventInfoBase, event=SolverEvent.ABOUT_TO_LOAD_DATA):
"""Information about the event triggered just before a data file is loaded.
Attributes
----------
data_file_name : str
Expand All @@ -226,6 +233,7 @@ class AboutToLoadDataEventInfo(EventInfoBase, event=SolverEvent.ABOUT_TO_LOAD_DA
@dataclass
class DataLoadedEventInfo(EventInfoBase, event=SolverEvent.DATA_LOADED):
"""Information about the event triggered after a data file is loaded.
Attributes
----------
data_file_name : str
Expand All @@ -252,6 +260,7 @@ class ReportDefinitionUpdatedEventInfo(
EventInfoBase, event=SolverEvent.REPORT_DEFINITION_UPDATED
):
"""Information about the event triggered when a report definition is updated.
Attributes
----------
report_name : str
Expand All @@ -266,6 +275,7 @@ class ReportPlotSetUpdatedEventInfo(
EventInfoBase, event=SolverEvent.REPORT_PLOT_SET_UPDATED
):
"""Information about the event triggered when a report plot set is updated.
Attributes
----------
plot_set_name : str
Expand All @@ -288,6 +298,7 @@ class SettingsClearedEventInfo(EventInfoBase, event=SolverEvent.SETTINGS_CLEARED
@dataclass
class SolutionPausedEventInfo(EventInfoBase, event=SolverEvent.SOLUTION_PAUSED):
"""Information about the event triggered when solution is paused.
Attributes
----------
level : str
Expand All @@ -303,6 +314,7 @@ class SolutionPausedEventInfo(EventInfoBase, event=SolverEvent.SOLUTION_PAUSED):
@dataclass
class ProgressUpdatedEventInfo(EventInfoBase, event=SolverEvent.PROGRESS_UPDATED):
"""Information about the event triggered when progress is updated.
Attributes
----------
message : str
Expand All @@ -320,6 +332,7 @@ class SolverTimeEstimateUpdatedEventInfo(
EventInfoBase, event=SolverEvent.SOLVER_TIME_ESTIMATE_UPDATED
):
"""Information about the event triggered when solver time estimate is updated.
Attributes
----------
hours : float
Expand All @@ -338,6 +351,7 @@ class SolverTimeEstimateUpdatedEventInfo(
@dataclass
class FatalErrorEventInfo(EventInfoBase, event=SolverEvent.FATAL_ERROR):
"""Information about the event triggered when a fatal error occurs.
Attributes
----------
message : str
Expand Down Expand Up @@ -428,23 +442,26 @@ def _process_streaming(

@staticmethod
def _make_callback_to_call(callback: Callable, args, kwargs):
old_style = "session_id" in inspect.signature(callback).parameters
if old_style:
params = inspect.signature(callback).parameters
if "session_id" in params:
warnings.warn(
"Update event callback function signatures"
" substituting 'session' for 'session_id'.",
PyFluentDeprecationWarning,
)
fn = partial(callback, *args, **kwargs)
return (
(
lambda session, event_info: fn(
session_id=session.id, event_info=event_info
)
return lambda session, event_info: callback(
*args, session_id=session.id, event_info=event_info, **kwargs
)
else:
positional_args = [
p
for p in params
if p not in kwargs and p not in ("session", "event_info")
]
kwargs.update(dict(zip(positional_args, args)))
return lambda session, event_info: callback(
session=session, event_info=event_info, **kwargs
)
if old_style
else fn
)

def register_callback(
self,
Expand Down
13 changes: 12 additions & 1 deletion tests/test_events_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ def on_case_loaded(session, event_info):

on_case_loaded.loaded = False

def on_case_loaded_with_args(x, y, session, event_info):
def on_case_loaded_with_args_optional_first(x, y, session, event_info):
on_case_loaded_with_args_optional_first.state = dict(x=x, y=y)

on_case_loaded_with_args_optional_first.state = None

def on_case_loaded_with_args(session, event_info, x, y):
on_case_loaded_with_args.state = dict(x=x, y=y)

on_case_loaded_with_args.state = None
Expand All @@ -43,6 +48,10 @@ def on_case_loaded_with_args(x, y, session, event_info):

solver.events.register_callback(SolverEvent.CASE_LOADED, on_case_loaded)

solver.events.register_callback(
SolverEvent.CASE_LOADED, on_case_loaded_with_args_optional_first, 12, y=42
)

solver.events.register_callback(
SolverEvent.CASE_LOADED, on_case_loaded_with_args, 12, y=42
)
Expand All @@ -54,6 +63,7 @@ def on_case_loaded_with_args(x, y, session, event_info):
assert not on_case_loaded_old.loaded
assert not on_case_loaded.loaded
assert not on_case_loaded_old_with_args.state
assert not on_case_loaded_with_args_optional_first.state
assert not on_case_loaded_with_args.state

try:
Expand All @@ -64,6 +74,7 @@ def on_case_loaded_with_args(x, y, session, event_info):
assert on_case_loaded_old.loaded
assert on_case_loaded.loaded
assert on_case_loaded_old_with_args.state == dict(x=12, y=42)
assert on_case_loaded_with_args_optional_first.state == dict(x=12, y=42)
assert on_case_loaded_with_args.state == dict(x=12, y=42)


Expand Down

0 comments on commit b556f1e

Please sign in to comment.