plaid.containers.sample ======================= .. py:module:: plaid.containers.sample .. autoapi-nested-parse:: Implementation of the `Sample` container. Attributes ---------- .. autoapisummary:: plaid.containers.sample.Self plaid.containers.sample.CGNS_WORKER plaid.containers.sample.FEATURES_METHODS Classes ------- .. autoapisummary:: plaid.containers.sample.Sample Module Contents --------------- .. py:data:: Self .. py:data:: CGNS_WORKER .. py:data:: FEATURES_METHODS :value: ['set_default_base', 'set_default_zone_base', 'get_base_assignment', 'get_zone_assignment',... .. py:class:: Sample(/, **data: Any) Bases: :py:obj:`pydantic.BaseModel` Represents a single sample. It contains data and information related to a single observation or measurement within a dataset. By default, the sample is empty but: - You can provide a path to a folder containing the sample data, and it will be loaded during initialization. - You can provide `SampleFeatures` and `SampleFeatures` instances to initialize the sample with existing data. The default `SampleFeatures` instance is initialized with `data=None` (i.e., no mesh data). Create a new model by parsing and validating input data from keyword arguments. Raises [`ValidationError`][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model. `self` is explicitly positional-only to allow `self` as a field name. .. py:attribute:: model_config Configuration for the model, should be a dictionary conforming to [`ConfigDict`][pydantic.config.ConfigDict]. .. py:attribute:: path :type: Optional[Union[str, pathlib.Path]] :value: None .. py:attribute:: features :type: Optional[plaid.containers.features.SampleFeatures] :value: None .. py:method:: model_post_init(_context: Any) -> None Post-initialization processing for the Sample model. .. py:method:: copy() -> Self Create a deep copy of the current `Sample` instance. Usage of `model_copy(deep=True)` from Pydantic to ensure all internal data is deeply copied. :returns: A new `Sample` instance with all internal data (scalars, fields, meshes, etc.) deeply copied to ensure full isolation from the original. .. note:: This operation may be memory-intensive for large samples. .. py:method:: get_scalar(name: str) -> Optional[plaid.types.Scalar] Retrieve a scalar value associated with the given name. :param name: The name of the scalar value to retrieve. :type name: str :returns: The scalar value associated with the given name, or None if the name is not found. :rtype: Scalar or None .. py:method:: add_scalar(name: str, value: plaid.types.Scalar) -> None Add a scalar value to a dictionary. :param name: The name of the scalar value. :type name: str :param value: The scalar value to add or update in the dictionary. :type value: Scalar .. py:method:: del_scalar(name: str) -> plaid.types.Scalar Delete a scalar value from the dictionary. :param name: The name of the scalar value to be deleted. :type name: str :raises KeyError: Raised when there is no scalar / there is no scalar with the provided name. :returns: The value of the deleted scalar. :rtype: Scalar .. py:method:: get_scalar_names() -> list[str] Get a set of scalar names available in the object. :returns: A set containing the names of the available scalars. :rtype: list[str] .. py:method:: del_all_fields() -> Self Delete alls field from sample, while keeping geometrical info. :returns: The sample with deleted fields :rtype: Sample .. py:method:: get_all_features_identifiers() -> list[plaid.containers.feature_identifier.FeatureIdentifier] Get all features identifiers from the sample. :returns: A list of dictionaries containing the identifiers of all features in the sample. :rtype: list[FeatureIdentifier] .. py:method:: get_all_features_identifiers_by_type(feature_type: str) -> list[plaid.containers.feature_identifier.FeatureIdentifier] Get all features identifiers of a given type from the sample. :param feature_type: Type of features to return :type feature_type: str :returns: A list of dictionaries containing the identifiers of a given type of all features in the sample. :rtype: list[FeatureIdentifier] .. py:method:: get_feature_by_path(path: str, time: Optional[int] = None) -> plaid.types.Feature Retrieve a feature value from the sample's CGNS mesh using a CGNS-style path. :param path: CGNS node path relative to the mesh root (for example "BaseName/ZoneName/GridCoordinates/CoordinateX" or "BaseName/ZoneName/Solution/FieldName"). :type path: str :param time: Time selection for the mesh. If an integer, it is interpreted via the SampleFeatures time-assignment logic (see SampleFeatures.get_time_assignment). If None, the default time assignment is used. Defaults to None. :type time: Optional[int], optional :returns: The value stored at the given CGNS path. This may be a numpy array, a scalar, or None if the node has no value. :rtype: Feature .. note:: - This is a thin wrapper around CGNS.PAT.cgnsutils.getValueByPath and Sample.get_mesh(time). Callers should handle a returned None when the path or value does not exist. - For field-like features, prefer using Sample.get_field which applies additional validation and selection logic. .. py:method:: get_feature_from_string_identifier(feature_string_identifier: str) -> plaid.types.Feature Retrieve a specific feature from its encoded string identifier. The `feature_string_identifier` must follow the format: ":://.../" Supported feature types: - "scalar": expects 1 detail → `scalars.get(name)` - "field": up to 5 details → `get_field(name, base_name, zone_name, location, time)` - "nodes": up to 3 details → `get_nodes(base_name, zone_name, time)` :param feature_string_identifier: Structured identifier of the feature. :type feature_string_identifier: str :returns: The retrieved feature object. :rtype: Feature :raises AssertionError: If `feature_type` is unknown. .. warning:: - If "time" is present in a field/nodes identifier, it is cast to float. - `name` is required for scalar and field features. - The order of the details must be respected. One cannot specify a detail in the feature_string_identifier string without specified the previous ones. .. py:method:: get_feature_from_identifier(feature_identifier: plaid.containers.feature_identifier.FeatureIdentifier) -> plaid.types.Feature Retrieve a feature object based on a structured identifier dictionary. The `feature_identifier` must include a `"type"` key specifying the feature kind: - `"scalar"` → calls `scalars.get(name)` - `"field"` → calls `get_field(name, base_name, zone_name, location, time)` - `"nodes"` → calls `get_nodes(base_name, zone_name, time)` Required keys: - `"type"`: one of `"scalar"`, `"field"`, or `"nodes"` - `"name"`: required for all types except `"nodes"` Optional keys depending on type: - `"base_name"`, `"zone_name"`, `"location"`, `"time"`: used in `"field"` and `"nodes"` Any omitted optional keys will rely on the default values mechanics of the class. :param feature_identifier ( dict[str: Union[str, float]]): A dictionary encoding the feature type and its relevant parameters. :returns: The corresponding feature instance retrieved via the appropriate accessor. :rtype: Feature .. py:method:: get_features_from_identifiers(feature_identifiers: list[plaid.containers.feature_identifier.FeatureIdentifier]) -> list[plaid.types.Feature] Retrieve features based on a list of structured identifier dictionaries. Elements of `feature_identifiers` must include a `"type"` key specifying the feature kind: - `"scalar"` → calls `scalars.get(name)` - `"field"` → calls `get_field(name, base_name, zone_name, location, time)` - `"nodes"` → calls `get_nodes(base_name, zone_name, time)` Required keys: - `"type"`: one of `"scalar"`, `"field"`, or `"nodes"` - `"name"`: required for all types except `"nodes"` Optional keys depending on type: - `"base_name"`, `"zone_name"`, `"location"`, `"time"`: used in `"field"` and `"nodes"` Any omitted optional keys will rely on the default values mechanics of the class. :param feature_identifiers: A dictionary encoding the feature type and its relevant parameters. :type feature_identifiers: list[FeatureIdentifier] :returns: List of corresponding feature instance retrieved via the appropriate accessor. :rtype: list[Feature] .. py:method:: add_feature(feature_identifier: plaid.containers.feature_identifier.FeatureIdentifier, feature: plaid.types.Feature) -> Self Add a feature to current sample. This method applies updates to scalars, fields, or nodes using feature identifiers, and corresponding feature data. :param feature_identifier: A feature identifier. :type feature_identifier: dict :param feature: A feature corresponding to the identifiers. :type feature: Feature :returns: The updated sample :rtype: Self :raises AssertionError: If types are inconsistent or identifiers contain unexpected keys. .. py:method:: del_feature(feature_identifier: plaid.containers.feature_identifier.FeatureIdentifier) -> Self Remove a feature from current sample. This method applies updates to scalars, time series, fields, or nodes using feature identifiers. :param feature_identifier: A feature identifier. :type feature_identifier: dict :returns: The updated sample :rtype: Self :raises AssertionError: If types are inconsistent or identifiers contain unexpected keys. .. py:method:: update_features_from_identifier(feature_identifiers: dict[int, Union[plaid.containers.feature_identifier.FeatureIdentifier, list[plaid.containers.feature_identifier.FeatureIdentifier]]], features: Union[plaid.types.Feature, list[plaid.types.Feature]], in_place: bool = False) -> Self Update one or several features of the sample by their identifier(s). This method applies updates to scalars, fields, or nodes using feature identifiers, and corresponding feature data. When `in_place=False`, a deep copy of the sample is created before applying updates, ensuring full isolation from the original. :param feature_identifiers: One or more feature identifiers. :type feature_identifiers: FeatureIdentifier or list of FeatureIdentifier :param features: One or more features corresponding to the identifiers. :type features: dict of Feature or list of Feature :param in_place: If True, modifies the current sample in place. If False, returns a deep copy with updated features. :type in_place: bool, optional :returns: The updated sample (either the current instance or a new copy). :rtype: Self :raises AssertionError: If types are inconsistent or identifiers contain unexpected keys. .. py:method:: extract_sample_from_identifier(feature_identifiers: Union[plaid.containers.feature_identifier.FeatureIdentifier, list[plaid.containers.feature_identifier.FeatureIdentifier]]) -> Self Extract features of the sample by their identifier(s) and return a new sample containing these features. This method applies updates to scalars, fields, or nodes using feature identifiers :param feature_identifiers: One or more feature identifiers. :type feature_identifiers: dict or list of dict :returns: New sample containing the provided feature identifiers :rtype: Self :raises AssertionError: If types are inconsistent or identifiers contain unexpected keys. .. py:method:: from_features_identifier(feature_identifiers: Union[plaid.containers.feature_identifier.FeatureIdentifier, list[plaid.containers.feature_identifier.FeatureIdentifier]]) -> Self DEPRECATED: Use :meth:`Dataset.extract_sample_from_identifier` instead. .. py:method:: merge_features(sample: Self, in_place: bool = False) -> Self Merge features from another sample into the current sample. This method applies updates to scalars, fields, or nodes using features from another sample. When `in_place=False`, a deep copy of the sample is created before applying updates, ensuring full isolation from the original. :param sample: The sample from which features will be merged. :type sample: Sample :param in_place: If True, modifies the current sample in place. If False, returns a deep copy with updated features. :type in_place: bool, optional :returns: The updated sample (either the current instance or a new copy). :rtype: Self .. py:method:: save(path: Union[str, pathlib.Path], overwrite: bool = False, memory_safe: bool = False) -> None DEPRECATED: use :meth:`Dataset.save_to_dir` instead. .. py:method:: save_to_dir(path: Union[str, pathlib.Path], overwrite: bool = False, memory_safe: bool = False) -> None Save the Sample in directory `path`. :param path: relative or absolute directory path. :type path: Union[str,Path] :param overwrite: target directory overwritten if True. :type overwrite: bool :param memory_safe: use pyCGNS save in a subprocess (requires an additional pickle of the sample) if True. :type memory_safe: bool .. py:method:: load_from_dir(path: Union[str, pathlib.Path]) -> Self :classmethod: Load the Sample from directory `path`. This is a class method, you don't need to instantiate a `Sample` first. :param path: Relative or absolute directory path. :type path: Union[str,Path] :returns: Sample .. rubric:: Example .. code-block:: python from plaid import Sample sample = Sample.load_from_dir(dir_path) print(sample) >>> Sample(2 scalars, 1 timestamp, 5 fields) .. note:: It calls :meth:`Sample.load` method during execution. .. py:method:: load(path: Union[str, pathlib.Path]) -> None Load the Sample from directory `path`. :param path: Relative or absolute directory path. :type path: Union[str,Path] :raises FileNotFoundError: Triggered if the provided directory does not exist. :raises FileExistsError: Triggered if the provided path is a file instead of a directory. .. rubric:: Example .. code-block:: python from plaid import Sample sample = Sample() sample.load(path) print(sample) >>> Sample(3 scalars, 1 timestamp, 3 fields) .. py:method:: summarize() -> str Provide detailed summary of the Sample content, showing feature names and mesh information. This provides more detailed information than the __repr__ method, including the name of each feature. :returns: A detailed string representation of the sample content. :rtype: str .. rubric:: Example .. code-block:: bash Sample Summary: ================================================== Scalars (8): - Pr: 0.9729006564945664 - Q: 0.2671142611487964 - Tr: 0.9983394202616822 - angle_in: 45.5066666666667 - angle_out: 61.89519547386746 - eth_is: 0.21238326882538008 - mach_out: 0.81003 - power: 0.0019118127462776008 Meshes (1 timestamps): Time: 0.0 Base: Base_2_2 Nodes (36421) Tags (6): Intrado (122), Extrado (122), Inflow (121), Outflow (121), Periodic_1 (120), Periodic_2 (238) Fields (7): ro, sdf, rou, nut, mach, roe, rov Elements (36000) QUAD_4 (36000) Base: Base_1_2 Nodes (244) Fields (1): M_iso Elements (242) BAR_2 (242) .. py:method:: check_completeness() -> str Check the completeness of features in this sample. :returns: A report on feature completeness. :rtype: str .. rubric:: Example .. code-block:: bash Sample Completeness Check: ============================== Has scalars: True Has meshes: True Total unique fields: 8 Field names: M_iso, mach, nut, ro, roe, rou, rov, sdf