Detector.hpp 11.5 KB
Newer Older
1
2
3
4
5
6
7
8
/** @file
 *  @brief Detector model class
 *  @copyright Copyright (c) 2017 CERN and the Corryvreckan authors.
 * This software is distributed under the terms of the MIT License, copied verbatim in the file "LICENSE.md".
 * In applying this license, CERN does not waive the privileges and immunities granted to it by virtue of its status as an
 * Intergovernmental Organization or submit itself to any jurisdiction.
 */

9
10
#ifndef CORRYVRECKAN_DETECTOR_H
#define CORRYVRECKAN_DETECTOR_H
11
12
13
14
15
16
17
18
19
20
21

#include <fstream>
#include <map>
#include <string>

#include <Math/DisplacementVector2D.h>
#include <Math/Vector2D.h>
#include <Math/Vector3D.h>
#include "Math/Transform3D.h"
#include "Math/Vector3D.h"

22
23
24
#include "core/config/Configuration.hpp"
#include "core/utils/ROOT.h"
#include "core/utils/log.h"
Simon Spannagel's avatar
Simon Spannagel committed
25
#include "objects/Track.hpp"
26
27

namespace corryvreckan {
28
    using namespace ROOT::Math;
Simon Spannagel's avatar
Simon Spannagel committed
29
30
31
32

    /**
     * @brief Role of the detector
     */
33
34
35
36
    enum class DetectorRole : int {
        NONE = 0x0,      ///< No specific detector role
        REFERENCE = 0x1, ///< Reference detector
        DUT = 0x2,       ///< Detector used as device under test
37
38
        AUXILIARY = 0x4, ///< Auxiliary device which should not participate in regular reconstruction but might provide
                         /// additional information
Simon Spannagel's avatar
Simon Spannagel committed
39
40
    };

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
    inline constexpr DetectorRole operator&(DetectorRole x, DetectorRole y) {
        return static_cast<DetectorRole>(static_cast<int>(x) & static_cast<int>(y));
    }

    inline constexpr DetectorRole operator|(DetectorRole x, DetectorRole y) {
        return static_cast<DetectorRole>(static_cast<int>(x) | static_cast<int>(y));
    }

    inline DetectorRole& operator&=(DetectorRole& x, DetectorRole y) {
        x = x & y;
        return x;
    }

    inline DetectorRole& operator|=(DetectorRole& x, DetectorRole y) {
        x = x | y;
        return x;
    }

Simon Spannagel's avatar
Simon Spannagel committed
59
60
61
    /**
     * @brief Detector representation in the reconstruction chain
     *
62
63
     * Contains the detector with all its properties such as type, name, position and orientation, pitch, spatial resolution
     * etc.
Simon Spannagel's avatar
Simon Spannagel committed
64
     */
65
66
    class Detector {
    public:
67
68
69
        /**
         * Delete default constructor
         */
70
        Detector() = delete;
71

72
73
74
75
76
        /**
         * @brief Constructs a detector in the geometry
         * @param config Configuration object describing the detector
         */
        Detector(const Configuration& config);
77

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
        /**
         * @brief Get type of the detector
         * @return Type of the detector model
         */
        std::string type() const;

        /**
         * @brief Get name of the detector
         * @return Detector name
         */
        std::string name() const;

        /**
         * @brief Check whether detector is registered as reference
         * @return Reference status
         */
94
        bool isReference() const;
95
96
97
98
99

        /**
         * @brief Check whether detector is registered as DUT
         * @return DUT status
         */
100
        bool isDUT() const;
101

102
103
104
105
106
107
        /**
         * @brief Check whether detector is registered as auxiliary device and should not parttake in the reconstruction
         * @return Auxiliary status
         */
        bool isAuxiliary() const;

108
109
110
111
        /**
         * @brief Retrieve configuration object from detector, containing all (potentially updated) parameters
         * @return Configuration object for this detector
         */
112
        Configuration getConfiguration() const;
113

114
115
116
117
118
119
120
121
122
123
        /**
         * @brief Get the total size of the active matrix, i.e. pitch * number of pixels in both dimensions
         * @return 2D vector with the dimensions of the pixle matrix in X and Y
         */
        XYVector size() const;

        /**
         * @brief Get pitch of a single pixel
         * @return Pitch of a pixel
         */
124
        XYVector pitch() const { return m_pitch; }
125
126

        /**
127
128
         * @brief Get intrinsic spatial resolution of the detector
         * @return Intrinsic spatial resolution in X and Y
129
         */
130
        XYVector getSpatialResolution() const { return m_spatial_resolution; }
Simon Spannagel's avatar
Simon Spannagel committed
131

132
133
134
135
        /**
         * @brief Get number of pixels in x and y
         * @return Number of two dimensional pixels
         */
136
        ROOT::Math::DisplacementVector2D<ROOT::Math::Cartesian2D<int>> nPixels() const { return m_nPixels; }
137
138
139

        /**
         * @brief Get detector time offset from global clock, can be used to correct for constant shifts or time of flight
140
         * @return Time offset of respective detector
141
         */
142
        double timeOffset() const { return m_timeOffset; }
143

144
        /**
145
146
         * @brief Get detector time resolution, used for timing cuts during clustering, track formation, etc.
         * @return Time resolutiom of respective detector
147
         */
148
        double getTimeResolution() const { return m_timeResolution; }
149

150
151
152
153
        /**
         * @brief Update detector position in the world
         * @param displacement Vector with three position coordinates
         */
154
        void displacement(XYZPoint displacement) { m_displacement = displacement; }
155
156
157
158
159

        /**
         * @brief Get position in the world
         * @return Global position in Cartesian coordinates
         */
160
        XYZPoint displacement() const { return m_displacement; }
161

162
163
164
165
        /**
         * @brief Get orientation in the world
         * @return Vector with three rotation angles
         */
166
        XYZVector rotation() const { return m_orientation; }
167
168
169
170
171

        /**
         * @brief Update detector orientation in the world
         * @param rotation Vector with three rotation angles
         */
172
        void rotation(XYZVector rotation) { m_orientation = rotation; }
173

174
175
176
177
        /**
         * @brief Get normal vector to sensor surface
         * @return Normal vector to sensor surface
         */
178
        PositionVector3D<Cartesian3D<double>> normal() const { return m_normal; };
179

180
181
182
183
        /**
         * @brief Get path of the file with pixel mask information
         * @return Path of the pixel mask file
         */
184
        std::string maskFile() const { return m_maskfile; }
185
186
187
188
189
190

        /**
         * @brief Mark a detector channel as masked
         * @param chX X coordinate of the pixel to be masked
         * @param chY Y coordinate of the pixel to be masked
         */
191
        void maskChannel(int chX, int chY);
192
193
194
195
196
197
198

        /**
         * @brief Check if a detector channel is masked
         * @param chX X coordinate of the pixel to check
         * @param chY Y coordinate of the pixel to check
         * @return    Mask status of the pixel in question
         */
199
        bool masked(int chX, int chY) const;
200

201
202
203
        /**
         * @brief Update coordinate transformations based on currently configured position and orientation values
         */
204
205
206
        void update();

        // Function to get global intercept with a track
207
        PositionVector3D<Cartesian3D<double>> getIntercept(const Track* track) const;
208
        // Function to get local intercept with a track
209
        PositionVector3D<Cartesian3D<double>> getLocalIntercept(const Track* track) const;
210
211

        // Function to check if a track intercepts with a plane
212
        bool hasIntercept(const Track* track, double pixelTolerance = 0.) const;
213
214

        // Function to check if a track goes through/near a masked pixel
215
        bool hitMasked(Track* track, int tolerance = 0.) const;
216
217

        // Functions to get row and column from local position
218
219
        double getRow(PositionVector3D<Cartesian3D<double>> localPosition) const;
        double getColumn(PositionVector3D<Cartesian3D<double>> localPosition) const;
220

221
222
        // Function to get local position from column (x) and row (y) coordinates
        PositionVector3D<Cartesian3D<double>> getLocalPosition(double column, double row) const;
223

224
225
        /**
         * Transformation from local (sensor) coordinates to in-pixel coordinates
226
227
         * @param  column Column address ranging from int_column-0.5*pitch to int_column+0.5*pitch
         * @param  row Row address ranging from int_column-0.5*pitch to int_column+0.5*pitch
228
229
         * @return               Position within a single pixel cell, given in units of length
         */
230
        XYVector inPixel(const double column, const double row) const;
231

232
233
        /**
         * Transformation from local (sensor) coordinates to in-pixel coordinates
234
         * @param  localPosition Local position on the sensor
235
236
         * @return               Position within a single pixel cell, given in units of length
         */
237
        XYVector inPixel(PositionVector3D<Cartesian3D<double>> localPosition) const;
238

239
240
241
242
243
        /**
         * @brief Transform local coordinates of this detector into global coordinates
         * @param  local Local coordinates in the reference frame of this detector
         * @return       Global coordinates
         */
244
        XYZPoint localToGlobal(XYZPoint local) const { return m_localToGlobal * local; };
245
246
247
248
249
250

        /**
         * @brief Transform global coordinates into detector-local coordinates
         * @param  global Global coordinates
         * @return        Local coordinates in the reference frame of this detector
         */
251
        XYZPoint globalToLocal(XYZPoint global) const { return m_globalToLocal * global; };
252

253
254
255
256
257
        /**
         * @brief Check whether given track is within the detector's region-of-interest
         * @param  track The track to be checked
         * @return       Boolean indicating cluster affiliation with region-of-interest
         */
258
        bool isWithinROI(const Track* track) const;
259
260
261
262
263
264

        /**
         * @brief Check whether given cluster is within the detector's region-of-interest
         * @param  cluster The cluster to be checked
         * @return         Boolean indicating cluster affiliation with region-of-interest
         */
265
        bool isWithinROI(Cluster* cluster) const;
266

Lennart Huth's avatar
Lennart Huth committed
267
        /**
268
         * @brief Return the thickness of the senosr assembly layer (sensor+support) in fractions of radiation length
Lennart Huth's avatar
Lennart Huth committed
269
         * @return thickness in fractions of radiation length
Lennart Huth's avatar
Lennart Huth committed
270
         */
271
        double materialBudget() const { return m_materialBudget; }
Lennart Huth's avatar
Lennart Huth committed
272

273
    private:
274
        // Roles of the detector
Simon Spannagel's avatar
Simon Spannagel committed
275
276
        DetectorRole m_role;

277
278
279
        // Initialize coordinate transformations
        void initialise();

280
281
282
283
        // Functions to set and check channel masking
        void setMaskFile(std::string file);
        void processMaskFile();

284
285
286
        // Detector information
        std::string m_detectorType;
        std::string m_detectorName;
287
        XYVector m_pitch{};
288
        XYVector m_spatial_resolution{};
289
        ROOT::Math::DisplacementVector2D<ROOT::Math::Cartesian2D<int>> m_nPixels{};
290
        double m_timeOffset;
291
        double m_timeResolution;
292
        double m_materialBudget;
293

294
        std::vector<std::vector<int>> m_roi{};
295
296
297
        static int winding_number(std::pair<int, int> probe, std::vector<std::vector<int>> polygon);
        inline static int isLeft(std::pair<int, int> pt0, std::pair<int, int> pt1, std::pair<int, int> pt2);

298
        // Displacement and rotation in x,y,z
299
        ROOT::Math::XYZPoint m_displacement;
300
        ROOT::Math::XYZVector m_orientation;
301
        std::string m_orientation_mode;
302
303

        // Transforms from local to global and back
304
305
        Transform3D m_localToGlobal;
        Transform3D m_globalToLocal;
306
307
308
309
310
311
312
313

        // Normal to the detector surface and point on the surface
        PositionVector3D<Cartesian3D<double>> m_normal;
        PositionVector3D<Cartesian3D<double>> m_origin;

        // List of masked channels
        std::map<int, bool> m_masked;
        std::string m_maskfile;
314
        std::string m_maskfile_name;
315
    };
316
} // namespace corryvreckan
317

318
#endif // CORRYVRECKAN_DETECTOR_H