Skip to content

Detectors¤

BaseDetector

dLux.detectors.BaseDetector ¤

Bases: Base

Abstract base class for detector models.

Concrete detectors implement model(...) to transform input PSFs into detector-space outputs.

UML

UML

Source code in dLux/detectors.py
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class BaseDetector(zdx.Base):
    """
    Abstract base class for detector models.

    Concrete detectors implement `model(...)` to transform input PSFs into
    detector-space outputs.

    ??? abstract "UML"
        ![UML](../../assets/uml/BaseDetector.png)
    """

    @abstractmethod
    def __call__(
        self: BaseDetector, psf: PSF, return_psf: bool = False
    ) -> Array | PSF:  # pragma: no cover
        pass

    def model(
        self: LayeredDetector,
        psf: PSF,
        return_psf: bool = False,
    ) -> Array | PSF:
        """
        Backwards compatibility method that invokes __call__.

        Delegates to the __call__ method.
        """
        return self(psf, return_psf)

model(psf, return_psf=False) ¤

Backwards compatibility method that invokes call.

Delegates to the call method.

Source code in dLux/detectors.py
34
35
36
37
38
39
40
41
42
43
44
def model(
    self: LayeredDetector,
    psf: PSF,
    return_psf: bool = False,
) -> Array | PSF:
    """
    Backwards compatibility method that invokes __call__.

    Delegates to the __call__ method.
    """
    return self(psf, return_psf)
LayeredDetector

dLux.detectors.LayeredDetector ¤

Bases: BaseDetector

Applies a series of detector layers to an input PSF.

UML

UML

Attributes:

Name Type Description
layers OrderedDict

A series of DetectorLayer transformations to apply to the input PSF.

Source code in dLux/detectors.py
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
class LayeredDetector(BaseDetector):
    """
    Applies a series of detector layers to an input PSF.

    ??? abstract "UML"
        ![UML](../../assets/uml/LayeredDetector.png)

    Attributes
    ----------
    layers: OrderedDict
        A series of `DetectorLayer` transformations to apply to the input PSF.
    """

    layers: OrderedDict

    def __init__(
        self: LayeredDetector,
        layers: list[DetectorLayer | tuple[str, DetectorLayer]],
    ):
        """
        Parameters
        ----------
        layers : list[DetectorLayer | tuple[str, DetectorLayer]]
            A list of DetectorLayer objects to apply to the input PSF. List entries
            can be tuples of (key, layer) to specify a key, else the key is taken as
            the class name of the layer.
        """
        self.layers = dlu.list2dictionary(layers, True, DetectorLayer)
        super().__init__()

    def __getattr__(self: LayeredDetector, key: str) -> Any:
        """
        Raises the individual layers via their keys.

        Parameters
        ----------
        key : str
            The key of the item to be searched for in the layers dictionary.

        Returns
        -------
        item : Any
            The item corresponding to the supplied key in the layers
            dictionary.
        """
        if key in self.layers.keys():
            return self.layers[key]
        for layer in list(self.layers.values()):
            if hasattr(layer, key):
                return getattr(layer, key)
        raise dlu.helpers.missing_attribute_error(
            self,
            key,
            list(self.layers.keys()),
        )

    def __call__(
        self: LayeredDetector,
        psf: PSF,
        return_psf: bool = False,
    ) -> Array | PSF:
        """
        Applies the detector layers to the input PSF.

        Parameters
        ----------
        psf : PSF
            The input PSF to be transformed.
        return_psf : bool = False
            Should the PSF object be returned instead of the PSF array?

        Returns
        -------
        result : Array | PSF
            If `return_psf` is False, returns the PSF array.
            If `return_psf` is True, returns the PSF object.
        """
        for _, layer in self.layers.items():
            psf = layer(psf)
        if return_psf:
            return psf
        return psf.data

    def insert_layer(
        self: LayeredDetector,
        layer: DetectorLayer | tuple[str, DetectorLayer],
        index: int,
    ) -> LayeredDetector:
        """
        Inserts a layer into the layers dictionary at a specified index. This function
        calls the list2dictionary function to ensure all keys remain unique. Note that
        this can result in some keys being modified if they are duplicates. The input
        'layer' can be a tuple of (key, layer) to specify a key, else the key is taken
        as the class name of the layer.

        Parameters
        ----------
        layer : DetectorLayer | tuple[str, DetectorLayer]
            The layer to be inserted.
        index : int
            The index at which to insert the layer.

        Returns
        -------
        detector : LayeredDetector
            The updated detector.
        """
        return self.set(
            "layers",
            dlu.insert_layer(self.layers, layer, index, DetectorLayer),
        )

    def remove_layer(self: LayeredDetector, key: str) -> LayeredDetector:
        """
        Removes a layer from the layers dictionary, specified by its key.

        Parameters
        ----------
        key : str
            The key of the layer to be removed.

        Returns
        -------
        detector : LayeredDetector
            The updated detector.
        """
        return self.set("layers", dlu.remove_layer(self.layers, key))

__call__(psf, return_psf=False) ¤

Applies the detector layers to the input PSF.

Parameters:

Name Type Description Default
psf PSF

The input PSF to be transformed.

required
return_psf bool = False

Should the PSF object be returned instead of the PSF array?

False

Returns:

Name Type Description
result Array | PSF

If return_psf is False, returns the PSF array. If return_psf is True, returns the PSF object.

Source code in dLux/detectors.py
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
def __call__(
    self: LayeredDetector,
    psf: PSF,
    return_psf: bool = False,
) -> Array | PSF:
    """
    Applies the detector layers to the input PSF.

    Parameters
    ----------
    psf : PSF
        The input PSF to be transformed.
    return_psf : bool = False
        Should the PSF object be returned instead of the PSF array?

    Returns
    -------
    result : Array | PSF
        If `return_psf` is False, returns the PSF array.
        If `return_psf` is True, returns the PSF object.
    """
    for _, layer in self.layers.items():
        psf = layer(psf)
    if return_psf:
        return psf
    return psf.data

__getattr__(key) ¤

Raises the individual layers via their keys.

Parameters:

Name Type Description Default
key str

The key of the item to be searched for in the layers dictionary.

required

Returns:

Name Type Description
item Any

The item corresponding to the supplied key in the layers dictionary.

Source code in dLux/detectors.py
 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
def __getattr__(self: LayeredDetector, key: str) -> Any:
    """
    Raises the individual layers via their keys.

    Parameters
    ----------
    key : str
        The key of the item to be searched for in the layers dictionary.

    Returns
    -------
    item : Any
        The item corresponding to the supplied key in the layers
        dictionary.
    """
    if key in self.layers.keys():
        return self.layers[key]
    for layer in list(self.layers.values()):
        if hasattr(layer, key):
            return getattr(layer, key)
    raise dlu.helpers.missing_attribute_error(
        self,
        key,
        list(self.layers.keys()),
    )

__init__(layers) ¤

Parameters:

Name Type Description Default
layers list[DetectorLayer | tuple[str, DetectorLayer]]

A list of DetectorLayer objects to apply to the input PSF. List entries can be tuples of (key, layer) to specify a key, else the key is taken as the class name of the layer.

required
Source code in dLux/detectors.py
62
63
64
65
66
67
68
69
70
71
72
73
74
75
def __init__(
    self: LayeredDetector,
    layers: list[DetectorLayer | tuple[str, DetectorLayer]],
):
    """
    Parameters
    ----------
    layers : list[DetectorLayer | tuple[str, DetectorLayer]]
        A list of DetectorLayer objects to apply to the input PSF. List entries
        can be tuples of (key, layer) to specify a key, else the key is taken as
        the class name of the layer.
    """
    self.layers = dlu.list2dictionary(layers, True, DetectorLayer)
    super().__init__()

insert_layer(layer, index) ¤

Inserts a layer into the layers dictionary at a specified index. This function calls the list2dictionary function to ensure all keys remain unique. Note that this can result in some keys being modified if they are duplicates. The input 'layer' can be a tuple of (key, layer) to specify a key, else the key is taken as the class name of the layer.

Parameters:

Name Type Description Default
layer DetectorLayer | tuple[str, DetectorLayer]

The layer to be inserted.

required
index int

The index at which to insert the layer.

required

Returns:

Name Type Description
detector LayeredDetector

The updated detector.

Source code in dLux/detectors.py
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
def insert_layer(
    self: LayeredDetector,
    layer: DetectorLayer | tuple[str, DetectorLayer],
    index: int,
) -> LayeredDetector:
    """
    Inserts a layer into the layers dictionary at a specified index. This function
    calls the list2dictionary function to ensure all keys remain unique. Note that
    this can result in some keys being modified if they are duplicates. The input
    'layer' can be a tuple of (key, layer) to specify a key, else the key is taken
    as the class name of the layer.

    Parameters
    ----------
    layer : DetectorLayer | tuple[str, DetectorLayer]
        The layer to be inserted.
    index : int
        The index at which to insert the layer.

    Returns
    -------
    detector : LayeredDetector
        The updated detector.
    """
    return self.set(
        "layers",
        dlu.insert_layer(self.layers, layer, index, DetectorLayer),
    )

remove_layer(key) ¤

Removes a layer from the layers dictionary, specified by its key.

Parameters:

Name Type Description Default
key str

The key of the layer to be removed.

required

Returns:

Name Type Description
detector LayeredDetector

The updated detector.

Source code in dLux/detectors.py
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
def remove_layer(self: LayeredDetector, key: str) -> LayeredDetector:
    """
    Removes a layer from the layers dictionary, specified by its key.

    Parameters
    ----------
    key : str
        The key of the layer to be removed.

    Returns
    -------
    detector : LayeredDetector
        The updated detector.
    """
    return self.set("layers", dlu.remove_layer(self.layers, key))