Source code for mammos_entity.operations

r"""Entities operations."""

from __future__ import annotations

import warnings
from typing import TYPE_CHECKING

import mammos_units as u
import numpy as np

from mammos_entity._entity import Entity

if TYPE_CHECKING:
    import mammos_units
    import numpy.typing

    import mammos_entity


[docs] def concat_flat( *elements: mammos_entity.Entity | mammos_units.Quantity | numpy.typing.ArrayLike, unit: mammos_units.Unit | str | None = None, description: str | None = None, ) -> mammos_entity.Entity: r"""Concatenate objects into a unique flat Entity. At least one of the inputs must be an Entity with a `ontology_label`. The unit of the first Entity is accepted unless the optional argument `unit` is defined. Arrays are flattened according to :py:func:`numpy.flatten` in ``order="C"``. Args: *elements: object arguments to be concatenated. unit: If specified, all values are converted to this unit. description: If specified, this description string is assigned to the resulting entity. If not specified, all unique descriptions from the input entities are collected and concatenated (separated by \|). The order of the collected descriptions might change. Examples: >>> import mammos_entity as me >>> import mammos_units as u >>> Ms = me.Ms([500, 600], "kA/m") >>> me.operations.concat_flat(Ms, 0.3, 700000 * u.A / u.m, unit="MA/m", description="Merge XRD and literature values") Entity(ontology_label='SpontaneousMagnetization', value=array([0.5, 0.6, 0.3, 0.7]), unit='MA / m', description='Merge XRD and literature values') """ # noqa: E501 _elements = [] _descriptions = set() for e in elements: if isinstance(e, list | tuple): _elements.extend(e) else: _elements.append(e) first_unit = None ontology_labels = [] for e in _elements: if isinstance(e, Entity): if not first_unit: first_unit = e.unit ontology_labels.append(e.ontology_label) if e.description: _descriptions.add(e.description) if not ontology_labels: raise ValueError("At least one Entity is required.") elif len(set(ontology_labels)) > 1: raise ValueError("Entities with different ontology labels are not supported.") unit = u.Unit(unit) if unit is not None else first_unit values = [] for e in _elements: if isinstance(e, Entity): values.append(e.q.flatten().to(unit)) elif isinstance(e, u.Quantity): values.append(e.flatten().to(unit)) else: values.append(np.asarray(e).flatten() * unit) if description is None: if len(_descriptions) > 1: warnings.warn( "concat_flat was called without specifying a description input. " "The descriptions from all entities are collected and concatenated " "into a single string.", stacklevel=1, ) description = "|".join(_descriptions) return Entity( ontology_labels[0], np.concatenate(values), unit, description=description )