@File : descriptors.py @Time : 2026/03/25 11:57:22 @Author : Alejandro Marrero (amarrerd@ull.edu.es) @Version : 1.0 @Contact : amarrerd@ull.edu.es @License : (C)Copyright 2026, Alejandro Marrero @Desc : None

DescriptorFn

Bases: Protocol

Defines the Protocol that all descriptable functions must follow

Source code in digneapy/core/_descriptors.py
25
26
27
28
29
30
31
32
33
34
35
class DescriptorFn(Protocol):
    """Defines the Protocol that all descriptable functions must follow"""

    def __call__(
        self,
        population: np.ndarray | Sequence[Instance],
        scores: Optional[np.ndarray],
        domain: Optional[Domain],
        *args,
        **kwargs,
    ) -> np.ndarray: ...

DescriptorPipeline

Pipeline to transform descriptors with several models

Source code in digneapy/core/_descriptors.py
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
class DescriptorPipeline:
    """Pipeline to transform descriptors with several models"""

    def __init__(self, key: DescriptorKey, *transformers: Transformer):
        if not isinstance(key, str) or key not in descriptors_registry:
            raise KeyError(
                f"Unknown descriptor key {key}. Registered keys are: {descriptors_registry.keys()}"
            )
        if any(not isinstance(t, Transformer) for t in transformers):
            raise TypeError(
                f"All transformers must implement the Transformer Protocol. Got: {transformers}"
            )
        self._key = key
        self._transformers = tuple(transformers)

    def __call__(
        self,
        population: np.ndarray | Sequence[Instance],
        scores: Optional[np.ndarray] = None,
        domain: Optional[Domain] = None,
        *args,
        **kwargs,
    ) -> np.ndarray:
        descriptors = descriptors_registry[self._key](
            population, scores, domain, *args, **kwargs
        )
        for transfomer in self._transformers:
            descriptors = transfomer(descriptors)
        return descriptors

    def __repr__(self) -> str:
        steps = [self._key] + [
            getattr(t, "__name__", repr(t)) for t in self._transformers
        ]
        return f"DescriptorPipeline({' -> '.join(steps)})"

register_descriptor(key)

Registers a new descriptor strategy

Parameters:
  • key (str) –

    Key to store the strategy

Returns:
Source code in digneapy/core/_descriptors.py
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
def register_descriptor(key: str) -> Callable[[DescriptorFn], DescriptorFn]:
    """Registers a new descriptor strategy

    Args:
        key (str): Key to store the strategy

    Returns:
        Callable[[DescriptorFn], DescriptorFn]: Newly registered strategy
    """

    def decorator(fn: DescriptorFn) -> DescriptorFn:
        @wraps(fn)
        def wrapper(
            population: np.ndarray | Sequence[Instance],
            scores: Optional[np.ndarray],
            domain: Optional[Domain],
            *args,
            **kwargs,
        ) -> np.ndarray:
            return fn(population, scores, domain, *args, **kwargs)

        descriptors_registry[key] = wrapper
        return wrapper

    return decorator