ATLAS Offline Software
Loading...
Searching...
No Matches
NnClusterizationFactory.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5 #ifndef SICLUSTERIZATIONTOOL_NnClusterizationFactory_C
6 #define SICLUSTERIZATIONTOOL_NnClusterizationFactory_C
7
8 /******************************************************
9 @class NnClusterizationFactory
10 @author Giacinto Piacquadio (PH-ADE-ID)
11 Package : SiClusterizationTool
12 Created : January 2011
13 DESCRIPTION: Load neural networks used for clustering
14 and deal with:
15 1) estimate of number of particles
16 2) estimate of position of cluster / subclusters
17 3) estimate of error in all cases
18 (full PDF or just RMS)
19 ********************************************************/
20
21
22#include "GaudiKernel/ToolHandle.h"
23#include "GaudiKernel/ServiceHandle.h"
25
26
27//this is a typedef: no forward decl possible
38
39#include <RtypesCore.h> //Double_t
40#include <Eigen/Dense>
41#include <vector>
42#include <array>
43#include <string>
44#include <string_view>
45#include <regex>
46
47
48class TTrainedNetwork;
49class TH1;
50
51namespace lwt {
52 class NanReplacer;
53 class LightweightGraph;
54}
55
56namespace Trk {
57 class NeuralNetworkToHistoTool;
58 class Surface;
59}
60
61namespace InDetDD{
62 class SiLocalPosition;
63}
64
65namespace InDet {
66
67 class PixelCluster;
68
69 struct NNinput{
70 operator bool() const {
71 return !matrixOfToT.empty();
72 }
73 int sizeX = 0;
74 int sizeY = 0;
75 std::vector<std::vector<float> > matrixOfToT;
76 std::vector<float> vectorOfPitchesY;
77 std::vector<float> vectorOfPitchesX;
80 float phi = 0;
81 float theta = 0;
82 float etaModule = 0;
83 bool useTrackInfo = 0;
86 };
87
88 static const InterfaceID IID_NnClusterizationFactory("InDet::NnClusterizationFactory", 1, 0);
89
91
92 public:
93
95 static const InterfaceID& interfaceID() { return IID_NnClusterizationFactory; };
96
97 NnClusterizationFactory(const std::string& name,
98 const std::string& n, const IInterface* p);
100
101 virtual StatusCode initialize() override;
102 virtual StatusCode finalize() override { return StatusCode::SUCCESS; };
103
104 std::vector<double> estimateNumberOfParticles(const InDet::PixelCluster& pCluster,
105 Amg::Vector3D & beamSpotPosition) const;
106
107 std::vector<double> estimateNumberOfParticles(const InDet::PixelCluster& pCluster,
108 const Trk::Surface& pixelSurface,
109 const Trk::TrackParameters& trackParsAtSurface) const;
110
111 /* Public-facing method 1: no track parameters */
112 std::vector<Amg::Vector2D> estimatePositions(const InDet::PixelCluster& pCluster,
113 Amg::Vector3D & beamSpotPosition,
114 std::vector<Amg::MatrixX> & errors,
115 int numberSubClusters) const;
116
117 /* Public-facing method 1: with track parameters */
118 std::vector<Amg::Vector2D> estimatePositions(const InDet::PixelCluster& pCluster,
119 const Trk::Surface& pixelSurface,
120 const Trk::TrackParameters& trackParsAtSurface,
121 std::vector<Amg::MatrixX> & errors,
122 int numberSubClusters) const;
123
124 private:
125
126 // Handling lwtnn inputs
127 typedef std::vector<Eigen::VectorXd> InputVector;
128
129 /* Estimate number of particles for both with and w/o tracks */
130 /* Method 1: using older TTrainedNetworks */
131 std::vector<double> estimateNumberOfParticlesTTN(const TTrainedNetworkCollection &nn_collection,
132 const std::vector<double>& inputData) const;
133
134 /* Estimate number of particles for both with and w/o tracks */
135 /* Method 2: using lwtnn for more flexible interfacing with an ordered vector
136 * Vector order MUST match variable order. */
138
139 /* Estimate position for both with and w/o tracks */
140 /* Method 1: using older TTrainedNetworks */
141 std::vector<Amg::Vector2D> estimatePositionsTTN(
142 const TTrainedNetworkCollection &nn_collection,
143 const std::vector<double>& inputData,
144 const NNinput& input,
145 const InDet::PixelCluster& pCluster,
146 int numberSubClusters,
147 std::vector<Amg::MatrixX> & errors) const;
148
149 /* Estimate position for both with and w/o tracks */
150 /* Method 2: using lwtnn for more flexible interfacing with an ordered vector
151 * Vector order MUST match variable order. */
152 std::vector<Amg::Vector2D> estimatePositionsLWTNN(
154 NNinput& rawInput,
155 const InDet::PixelCluster& pCluster,
156 int numberSubClusters,
157 std::vector<Amg::MatrixX> & errors) const;
158
159 /* Estimate number of particles using ONNX */
160 std::vector<double> estimateNumberOfParticlesONNX(
161 const Eigen::VectorXd& input) const;
162
163 /* Estimate position using ONNX */
164 std::vector<Amg::Vector2D> estimatePositionsONNX(
165 const Eigen::VectorXd& input,
166 NNinput& rawInput,
167 const InDet::PixelCluster& pCluster,
168 int numberSubClusters,
169 std::vector<Amg::MatrixX>& errors) const;
170
171 // For error formatting in lwtnn cases
172 double correctedRMS(double posPixels, const std::vector<float>& pitches,
173 unsigned int size) const;
174
175 /* algorithmic component */
177 Amg::Vector3D & beamSpotPosition,
178 double & tanl) const;
179
180 void addTrackInfoToInput(NNinput& input,
181 const Trk::Surface& pixelSurface,
182 const Trk::TrackParameters& trackParsAtSurface,
183 const double tanl) const;
184
185
186 std::vector<double> assembleInputRunI(NNinput& input) const;
187
188
189 std::vector<double> assembleInputRunII(NNinput& input) const;
190
191 InputVector eigenInput(NNinput & input) const;
192
193 std::vector<Amg::Vector2D> getPositionsFromOutput(std::vector<double> & output,
194 const NNinput & input,
195 const InDet::PixelCluster& pCluster) const;
196
197
198 void getErrorMatrixFromOutput(std::vector<double>& outputX,
199 std::vector<double>& outputY,
200 std::vector<Amg::MatrixX>& errorMatrix,
201 int nParticles) const;
202
203
204 Gaudi::Property< std::vector<std::string> > m_nnOrder
205 {this, "NetworkOrder", {
206 "NumberParticles",
207 "ImpactPoints1P",
208 "ImpactPoints2P",
209 "ImpactPoints3P",
210 "ImpactPointErrorsX1",
211 "ImpactPointErrorsX2",
212 "ImpactPointErrorsX3",
213 "ImpactPointErrorsY1",
214 "ImpactPointErrorsY2",
215 "ImpactPointErrorsY3"},
216 "The order in which the networks will appear in the TTrainedNetworkCollection"};
217
223 static constexpr std::array<std::string_view, kNNetworkTypes> s_nnTypeNames{
224 "NumberParticlesNN",
225 "PositionNN",
226 "ErrorXNN",
227 "ErrorYNN" };
228 static constexpr std::array<unsigned int, kNNetworkTypes> m_nParticleGroup{0U,1U,1U,1U}; // unsigned int
229 static const std::array<std::regex, kNNetworkTypes> m_nnNames;
230
231 unsigned int m_nParticleNNId{};
232 std::vector< std::vector<unsigned int> > m_NNId{};
233
234
235 // Function to be called to assemble the inputs
237
238 //Calculate flat vector dimension, according to input
239 size_t calculateVectorDimension(const bool useTrackInfo) const;
240
241 // Function to be called to compute the output
242 using ReturnType = std::vector<Double_t>;
243 using InputType = std::vector<Double_t>;
244 //the following declares a member variable m_calculateOutput which is a function pointer
245 //to a member function of the TTrainedNetwork. Note to anyone brave enough to update this to C++17using std::function:
246 //TTrainedNetwork::calculateNormalized is overloaded so template resolution does not work trivially.
248
249 ToolHandle<ISiLorentzAngleTool> m_pixelLorentzAngleTool
250 {this, "PixelLorentzAngleTool", "SiLorentzAngleTool/PixelLorentzAngleTool", "Tool to retreive Lorentz angle of Pixel"};
251
253 {this, "PixelChargeCalibCondData", "PixelChargeCalibCondData", "Output key"};
254
256 {this, "NnCollectionReadKey", "PixelClusterNN", "The conditions store key for the pixel cluster NNs"};
257
259 {this, "NnCollectionWithTrackReadKey", "PixelClusterNNWithTrack",
260 "The conditions store key for the pixel cluster NNs which needs tracks as input"};
261
263 {this, "NnCollectionJSONReadKey", "PixelClusterNNJSON",
264 "The conditions key for the pixel cluster NNs configured via JSON file and accessed with lwtnn"};
265
266 // this is written into the JSON config "node_index"
267 // this can be found from the LWTNN GraphConfig object used to initalize the collection objects
268 // option size_t index = graph_config.outputs.at("output_node_name").node_index
269 //
270 Gaudi::Property< std::size_t > m_outputNodesPos1
271 {this, "OutputNodePos1", 7,
272 "Output node for the 1 position networks (LWTNN)"};
273
274 Gaudi::Property< std::vector<std::size_t> > m_outputNodesPos2
275 {this, "OutputNodePos2", { 10, 11 },
276 "List of output nodes for the 2 position network (LWTNN)"};
277
278 Gaudi::Property< std::vector<std::size_t> > m_outputNodesPos3
279 {this, "OutputNodePos3", { 13, 14, 15 },
280 "List of output nodes for the 3 position networks (LWTNN)"};
281
282 Gaudi::Property<unsigned int> m_maxSubClusters
283 {this, "MaxSubClusters", 3, "Maximum number of sub cluster supported by the networks." };
284
286 {this, "correctLorShiftBarrelWithoutTracks",0.,"Lorentz shift correction factor when evaluating NN without track input."};
287
288 Gaudi::Property<double> m_correctLorShiftBarrelWithTracks
289 {this, "correctLorShiftBarrelWithTracks",0.,"Lorentz shift correction factor when evaluating NN with track input."};
290
291 Gaudi::Property<bool> m_useToT
292 {this, "useToT",true,"Use Tot rather than charge." }; // @TODO toggle mode depending on whether a PxielCalibSvc is set ?
293
294 Gaudi::Property<bool> m_addIBL
295 {this, "addIBL", false, "Also apply to clusters in IBL." };
296
297 Gaudi::Property<bool> m_doRunI
298 {this, "doRunI", false, "Use runI style network (outputs are not normalised; add pitches; use charge if not m_useToT)"};
299
301 {this, "NnCollectionONNXReadKey", "",
302 "The conditions key for ONNX-based pixel cluster NNs"};
303
304 Gaudi::Property<bool> m_useONNX
305 {this, "useONNX", false, "Use ONNX models instead of LWTNN for NN inference."};
306
307 Gaudi::Property<bool> m_useTTrainedNetworks
308 {this, "useTTrainedNetworks", false, "Use earlier (release-21-like) neural networks stored in ROOT files and accessed via TTrainedNetowrk."};
309
310 Gaudi::Property<bool> m_useRecenteringNNWithouTracks
311 {this, "useRecenteringNNWithoutTracks",false,"Recenter x position when evaluating NN without track input."};
312
313 Gaudi::Property<bool> m_useRecenteringNNWithTracks
314 {this, "useRecenteringNNWithTracks",false,"Recenter x position when evaluating NN with track input."};
315
316 Gaudi::Property<bool> m_useXPitches
317 {this, "useXPitches", false,
318 "Also feed the phi-direction (X) pixel pitch vector as NN input "
319 "(ONNX only). Off by default so existing 60-input models are "
320 "unaffected; needs a (60 + sizeX)-input model when enabled."};
321
322 Gaudi::Property<unsigned int> m_sizeX
323 {this, "sizeX",7,"Size of pixel matrix along X"};
324
325 Gaudi::Property<unsigned int> m_sizeY
326 {this, "sizeY",7,"Size of pixel matrix along Y"};
327
328 };
329
330 }//end InDet namespace
331
332 #endif
Store pixel constant parameters in PixelModuleData.
size_t size() const
Number of registered mappings.
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Class to represent a position in the natural frame of a silicon sensor, for Pixel and SCT For Pixel: ...
std::vector< double > assembleInputRunII(NNinput &input) const
void addTrackInfoToInput(NNinput &input, const Trk::Surface &pixelSurface, const Trk::TrackParameters &trackParsAtSurface, const double tanl) const
Gaudi::Property< unsigned int > m_maxSubClusters
SG::ReadCondHandleKey< PixelChargeCalibCondData > m_chargeDataKey
std::vector< double > estimateNumberOfParticlesLWTNN(NnClusterizationFactory::InputVector &input) const
double correctedRMS(double posPixels, const std::vector< float > &pitches, unsigned int size) const
virtual StatusCode finalize() override
std::vector< Amg::Vector2D > estimatePositionsONNX(const Eigen::VectorXd &input, NNinput &rawInput, const InDet::PixelCluster &pCluster, int numberSubClusters, std::vector< Amg::MatrixX > &errors) const
Gaudi::Property< unsigned int > m_sizeX
ReturnType(::TTrainedNetwork::* m_calculateOutput)(const InputType &input) const
NNinput createInput(const InDet::PixelCluster &pCluster, Amg::Vector3D &beamSpotPosition, double &tanl) const
virtual StatusCode initialize() override
Gaudi::Property< double > m_correctLorShiftBarrelWithoutTracks
static const InterfaceID & interfaceID()
AlgTool interface methods.
Gaudi::Property< std::size_t > m_outputNodesPos1
Gaudi::Property< std::vector< std::size_t > > m_outputNodesPos2
ToolHandle< ISiLorentzAngleTool > m_pixelLorentzAngleTool
Gaudi::Property< std::vector< std::size_t > > m_outputNodesPos3
std::vector< Amg::Vector2D > estimatePositionsLWTNN(NnClusterizationFactory::InputVector &input, NNinput &rawInput, const InDet::PixelCluster &pCluster, int numberSubClusters, std::vector< Amg::MatrixX > &errors) const
SG::ReadCondHandleKey< OnnxNNCollection > m_readKeyONNX
std::vector< double > assembleInputRunI(NNinput &input) const
SG::ReadCondHandleKey< LWTNNCollection > m_readKeyJSON
std::vector< Amg::Vector2D > estimatePositions(const InDet::PixelCluster &pCluster, Amg::Vector3D &beamSpotPosition, std::vector< Amg::MatrixX > &errors, int numberSubClusters) const
Gaudi::Property< std::vector< std::string > > m_nnOrder
Gaudi::Property< double > m_correctLorShiftBarrelWithTracks
Gaudi::Property< bool > m_useTTrainedNetworks
std::vector< double > estimateNumberOfParticlesTTN(const TTrainedNetworkCollection &nn_collection, const std::vector< double > &inputData) const
static constexpr std::array< unsigned int, kNNetworkTypes > m_nParticleGroup
SG::ReadCondHandleKey< TTrainedNetworkCollection > m_readKeyWithoutTrack
std::vector< double >(InDet::NnClusterizationFactory::* m_assembleInput)(NNinput &input) const
std::vector< Eigen::VectorXd > InputVector
NnClusterizationFactory(const std::string &name, const std::string &n, const IInterface *p)
std::vector< Amg::Vector2D > estimatePositionsTTN(const TTrainedNetworkCollection &nn_collection, const std::vector< double > &inputData, const NNinput &input, const InDet::PixelCluster &pCluster, int numberSubClusters, std::vector< Amg::MatrixX > &errors) const
static const std::array< std::regex, kNNetworkTypes > m_nnNames
Gaudi::Property< bool > m_useRecenteringNNWithouTracks
static constexpr std::array< std::string_view, kNNetworkTypes > s_nnTypeNames
InputVector eigenInput(NNinput &input) const
void getErrorMatrixFromOutput(std::vector< double > &outputX, std::vector< double > &outputY, std::vector< Amg::MatrixX > &errorMatrix, int nParticles) const
Gaudi::Property< bool > m_useRecenteringNNWithTracks
std::vector< std::vector< unsigned int > > m_NNId
std::vector< Amg::Vector2D > getPositionsFromOutput(std::vector< double > &output, const NNinput &input, const InDet::PixelCluster &pCluster) const
size_t calculateVectorDimension(const bool useTrackInfo) const
Gaudi::Property< unsigned int > m_sizeY
SG::ReadCondHandleKey< TTrainedNetworkCollection > m_readKeyWithTrack
std::vector< double > estimateNumberOfParticlesONNX(const Eigen::VectorXd &input) const
std::vector< double > estimateNumberOfParticles(const InDet::PixelCluster &pCluster, Amg::Vector3D &beamSpotPosition) const
Abstract Base Class for tracking surfaces.
Definition Surface.h:79
Eigen::Matrix< double, 3, 1 > Vector3D
Message Stream Member.
Primary Vertex Finder.
static const InterfaceID IID_NnClusterizationFactory("InDet::NnClusterizationFactory", 1, 0)
Ensure that the ATLAS eigen extensions are properly loaded.
ParametersBase< TrackParametersDim, Charged > TrackParameters
int ClusterPixBarrelEC
layer index: as returned by PixelID::layer_disk
std::vector< float > vectorOfPitchesX
dimensions of pixels in mm along Y
float etaModule
polar incidence angle
std::vector< std::vector< float > > matrixOfToT
cluster span measured in pixels (seems unfilled)
float phi
global cluster location barrel vs endcap: as returned by: PixelID::barrel_ec
int columnWeightedPosition
flag to indicate if incidence angles (phi, theta) should be used in inference
int sizeY
cluster span measured in pixels (seems unfilled)
int ClusterPixLayer
same along X
bool useTrackInfo
module eta index as returned by PixelID:eta_module
int rowWeightedPosition
mean position along y
std::vector< float > vectorOfPitchesY
2D array of charges or ToTs (depending on filling tool configuration)
float theta
azimuthal incidence angle