From d90b67e3f944794cd2e2032a51eb216b774081fb Mon Sep 17 00:00:00 2001 From: Paul Profizi <100710998+PProfizi@users.noreply.github.com> Date: Thu, 11 Dec 2025 10:15:21 +0100 Subject: [PATCH 1/4] doc: expose the `label_space` class in the API reference --- doc/source/conf.py | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index 35f0b64975c..8903d0c15ff 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -98,7 +98,6 @@ "*/operators/build.py", "*/operators/specification.py", "*/vtk_helper.py", - "*/label_space.py", "*/examples/python_plugins/*", "*/examples/examples.py", "*/gate/*", From 57a63c498c5da33e9bab1ddff7fbda4d4386fafe Mon Sep 17 00:00:00 2001 From: PProfizi Date: Thu, 11 Dec 2025 14:17:04 +0100 Subject: [PATCH 2/4] Improve the module documentation --- src/ansys/dpf/core/label_space.py | 103 ++++++++++++++++++++++++++---- 1 file changed, 90 insertions(+), 13 deletions(-) diff --git a/src/ansys/dpf/core/label_space.py b/src/ansys/dpf/core/label_space.py index ea38180c02a..3ccddd0ab23 100644 --- a/src/ansys/dpf/core/label_space.py +++ b/src/ansys/dpf/core/label_space.py @@ -20,12 +20,36 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -"""Internal Usage.""" +# -*- coding: utf-8 -*- + +""" +LabelSpace. + +LabelSpace is a key component for managing entries in DPF collections such as FieldsContainer and ScopingsContainer. + +It provides a mapping between label names and values, +allowing users to organize, filter, and retrieve data based on metadata +such as time steps, zones, element types, and more. + +Typical usage: +- FieldsContainer: Each field is indexed by a LabelSpace, enabling access by time, zone, etc. +- ScopingsContainer: Each scoping is indexed by a LabelSpace, allowing management of multiple selections. + +LabelSpace enables advanced data organization and querying in DPF workflows. + +""" + +from __future__ import annotations import traceback -from typing import Dict +from typing import TYPE_CHECKING import warnings +if TYPE_CHECKING: # pragma: no cover + from collections.abc import Generator + + from ansys.dpf.core.server import AnyServerType + from ansys.dpf.core import server as server_module from ansys.dpf.gate import ( data_processing_capi, @@ -38,7 +62,37 @@ class LabelSpace: """A class representing a label space, which allows storage and management of key-value pairs (labels).""" - def __init__(self, label_space=None, obj=None, server=None): + def __init__( + self, + label_space: dict[str, int] | LabelSpace | None = None, + obj: object = None, + server: AnyServerType = None, + ) -> None: + """ + Initialize a LabelSpace instance. + + Parameters + ---------- + label_space: + Dictionary of label names and values, another LabelSpace instance, or an internal label space object. + If a dictionary is provided, it will be used to fill the label space. + obj: + Internal object used for advanced initialization (rarely needed by users). + server: + DPF server instance to associate with this label space. + + Examples + -------- + >>> # Create a LabelSpace from a dictionary + >>> ls = LabelSpace(label_space={"time": 1, "zone": 2}) + >>> print(dict(ls)) + {'time': 1, 'zone': 2} + + >>> # Create a LabelSpace from another LabelSpace + >>> ls2 = LabelSpace(label_space=ls) + >>> print(dict(ls2)) + {'time': 1, 'zone': 2} + """ # ############################ # step 1: get server self._server = server_module.get_or_create_server( @@ -55,7 +109,7 @@ def __init__(self, label_space=None, obj=None, server=None): # step4: if object exists, take the instance, else create it if label_space is not None and not isinstance(label_space, dict): - self._internal_obj = label_space + self._internal_obj = label_space._internal_obj else: self._internal_obj = self._api.label_space_new_for_object(obj) if isinstance(label_space, dict): @@ -70,7 +124,7 @@ def _data_processing_core_api(self): core_api.init_data_processing_environment(self) return core_api - def fill(self, label_space: Dict[str, int]): + def fill(self, label_space: dict[str, int]) -> None: """ Fill the label space with the provided dictionary of labels. @@ -79,15 +133,17 @@ def fill(self, label_space: Dict[str, int]): label_space : dict A dictionary where keys are labels (str) and values are indices (int) to be added to the label space. - Returns - ------- - None - This method does not return anything, it modifies the internal label space. + Examples + -------- + >>> label_space = LabelSpace() + >>> label_space.fill({"time": 1, "node": 42}) + >>> print(dict(label_space)) + {'time': 1, 'node': 42} """ for key, index in label_space.items(): self._api.label_space_add_data(self, key, index) - def __str__(self): + def __str__(self) -> str: """ Return a string representation of the LabelSpace instance. @@ -95,10 +151,16 @@ def __str__(self): ------- str A string representation of the label space, formatted as a dictionary. + + Examples + -------- + >>> label_space = LabelSpace(label_space={"time": 1, "node": 42}) + >>> print(str(label_space)) + "{'time': 1, 'node': 42}" """ return str(dict(self)) - def __iter__(self): + def __iter__(self) -> Generator[tuple[str, int], None, None]: """ Iterate over the labels in the label space, yielding (key, value) pairs. @@ -106,6 +168,14 @@ def __iter__(self): ------ tuple A tuple of (key, value) for each label in the label space. + + Examples + -------- + >>> label_space = LabelSpace(label_space={"time": 1, "node": 42}) + >>> for key, value in label_space: + ... print(key, value) + time 1 + node 42 """ yield from [ ( @@ -115,7 +185,7 @@ def __iter__(self): for i in range(self._api.label_space_get_size(self)) ] - def __dict__(self): + def __dict__(self) -> dict[str, int]: """ Return a dictionary representation of the LabelSpace instance. @@ -123,6 +193,13 @@ def __dict__(self): ------- dict A dictionary where keys are label names (str) and values are label indices (int). + + Examples + -------- + >>> label_space = LabelSpace(label_space={"time": 1, "node": 42}) + >>> d = label_space.__dict__() + >>> print(d) + {'time': 1, 'node': 42} """ if isinstance(self._internal_obj, dict): return self._internal_obj @@ -134,7 +211,7 @@ def __dict__(self): ) return out - def __del__(self): + def __del__(self) -> None: """ Destructor for cleaning up the label space resources. From 70799dbe51e72de0e76e003077b88b632be4dd43 Mon Sep 17 00:00:00 2001 From: Paul Profizi <100710998+PProfizi@users.noreply.github.com> Date: Thu, 11 Dec 2025 17:28:57 +0100 Subject: [PATCH 3/4] Apply suggestions from code review --- src/ansys/dpf/core/label_space.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ansys/dpf/core/label_space.py b/src/ansys/dpf/core/label_space.py index 3ccddd0ab23..05645440a98 100644 --- a/src/ansys/dpf/core/label_space.py +++ b/src/ansys/dpf/core/label_space.py @@ -109,7 +109,7 @@ def __init__( # step4: if object exists, take the instance, else create it if label_space is not None and not isinstance(label_space, dict): - self._internal_obj = label_space._internal_obj + self._internal_obj = label_space else: self._internal_obj = self._api.label_space_new_for_object(obj) if isinstance(label_space, dict): From 54fae4777c1582606fda366038e49c8c1771dd8c Mon Sep 17 00:00:00 2001 From: Paul Profizi <100710998+PProfizi@users.noreply.github.com> Date: Thu, 11 Dec 2025 17:30:26 +0100 Subject: [PATCH 4/4] Update label_space.py --- src/ansys/dpf/core/label_space.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ansys/dpf/core/label_space.py b/src/ansys/dpf/core/label_space.py index 05645440a98..2c3e4de9d35 100644 --- a/src/ansys/dpf/core/label_space.py +++ b/src/ansys/dpf/core/label_space.py @@ -109,7 +109,10 @@ def __init__( # step4: if object exists, take the instance, else create it if label_space is not None and not isinstance(label_space, dict): - self._internal_obj = label_space + if isinstance(label_space, LabelSpace): + self._internal_obj = label_space._internal_obj + else: + self._internal_obj = label_space else: self._internal_obj = self._api.label_space_new_for_object(obj) if isinstance(label_space, dict):