LDMX Software
Classes | Public Types | Public Member Functions | Private Member Functions | Private Attributes | List of all members
ecal::EcalVetoProcessor Class Reference

Determines if event is vetoable using ECAL hit information. More...

#include <EcalVetoProcessor.h>

Classes

struct  HitData
 

Public Types

typedef std::pair< ldmx::EcalID, float > CellEnergyPair
 
typedef std::pair< float, float > XYCoords
 

Public Member Functions

 EcalVetoProcessor (const std::string &name, framework::Process &process)
 
void configure (framework::config::Parameters &parameters) override
 Configure the processor using the given user specified parameters.
 
void produce (framework::Event &event) override
 Process the event and put new data products into it.
 
- Public Member Functions inherited from framework::Producer
 Producer (const std::string &name, Process &process)
 Class constructor.
 
virtual void beforeNewRun (ldmx::RunHeader &header)
 Handle allowing producers to modify run headers before the run begins.
 
- Public Member Functions inherited from framework::EventProcessor
 EventProcessor (const std::string &name, Process &process)
 Class constructor.
 
virtual ~EventProcessor ()
 Class destructor.
 
virtual void onNewRun (const ldmx::RunHeader &runHeader)
 Callback for the EventProcessor to take any necessary action when the run being processed changes.
 
virtual void onFileOpen (EventFile &eventFile)
 Callback for the EventProcessor to take any necessary action when a new event input ROOT file is opened.
 
virtual void onFileClose (EventFile &eventFile)
 Callback for the EventProcessor to take any necessary action when a event input ROOT file is closed.
 
virtual void onProcessStart ()
 Callback for the EventProcessor to take any necessary action when the processing of events starts, such as creating histograms.
 
virtual void onProcessEnd ()
 Callback for the EventProcessor to take any necessary action when the processing of events finishes, such as calculating job-summary quantities.
 
template<class T >
const T & getCondition (const std::string &condition_name)
 Access a conditions object for the current event.
 
TDirectory * getHistoDirectory ()
 Access/create a directory in the histogram file for this event processor to create histograms and analysis tuples.
 
void setStorageHint (framework::StorageControl::Hint hint)
 Mark the current event as having the given storage control hint from this module.
 
void setStorageHint (framework::StorageControl::Hint hint, const std::string &purposeString)
 Mark the current event as having the given storage control hint from this module and the given purpose string.
 
int getLogFrequency () const
 Get the current logging frequency from the process.
 
int getRunNumber () const
 Get the run number from the process.
 
std::string getName () const
 Get the processor name.
 
void createHistograms (const std::vector< framework::config::Parameters > &histos)
 Internal function which is used to create histograms passed from the python configuration @parma histos vector of Parameters that configure histograms to create.
 

Private Member Functions

void clearProcessor ()
 
ldmx::EcalID GetShowerCentroidIDAndRMS (const std::vector< ldmx::EcalHit > &ecalRecHits, double &showerRMS)
 
void fillHitMap (const std::vector< ldmx::EcalHit > &ecalRecHits, std::map< ldmx::EcalID, float > &cellMap_)
 Function to load up empty vector of hit maps.
 
void fillIsolatedHitMap (const std::vector< ldmx::EcalHit > &ecalRecHits, ldmx::EcalID globalCentroid, std::map< ldmx::EcalID, float > &cellMap, std::map< ldmx::EcalID, float > &cellMapIso, bool doTight=false)
 
std::vector< XYCoords > getTrajectory (std::vector< double > momentum, std::vector< float > position)
 
void buildBDTFeatureVector (const ldmx::EcalVetoResult &result)
 
float distTwoLines (TVector3 v1, TVector3 v2, TVector3 w1, TVector3 w2)
 Returns the distance between the lines v and w, with v defined to pass through the points (v1,v2) (and similarly for w).
 
float distPtToLine (TVector3 h1, TVector3 p1, TVector3 p2)
 Return the minimum distance between the point h1 and the line passing through points p1 and p2.
 

Private Attributes

std::map< ldmx::EcalID, float > cellMap_
 
std::map< ldmx::EcalID, float > cellMapTightIso_
 
std::vector< float > ecalLayerEdepRaw_
 
std::vector< float > ecalLayerEdepReadout_
 
std::vector< float > ecalLayerTime_
 
std::vector< std::vector< double > > roc_range_values_
 
int nEcalLayers_ {0}
 
int nReadoutHits_ {0}
 
int deepestLayerHit_ {0}
 
double summedDet_ {0}
 
double summedTightIso_ {0}
 
double maxCellDep_ {0}
 
double showerRMS_ {0}
 
double xStd_ {0}
 
double yStd_ {0}
 
double avgLayerHit_ {0}
 
double stdLayerHit_ {0}
 
double ecalBackEnergy_ {0}
 
int nStraightTracks_ {0}
 Number of "straight" tracks found in the event.
 
int nLinregTracks_ {0}
 Number of "linreg" tracks found in the event.
 
int firstNearPhLayer_ {0}
 First ECal layer in which a hit is found near the photon.
 
int nNearPhHits_ {0}
 Number of hits near the photon trajectory.
 
float epAng_ {0}
 Angular separation between the projected photon and electron trajectories (currently unused)
 
float epSep_ {0}
 Distance between the projected photon and electron trajectories at the ECal face.
 
float epDot_ {0}
 Dot product of the photon and electron momenta unit vectors.
 
int photonTerritoryHits_ {0}
 Number of hits in the photon territory.
 
double bdtCutVal_ {0}
 
double beamEnergyMeV_ {0}
 
double linreg_radius_ {0}
 
bool verbose_ {false}
 
std::string bdtFileName_
 
std::string rocFileName_
 
std::vector< float > bdtFeatures_
 
std::string featureListName_
 
std::string rec_pass_name_
 
std::string rec_coll_name_
 
std::string collectionName_ {"EcalVeto"}
 Name of the collection which will containt the results.
 
std::unique_ptr< ldmx::Ort::ONNXRuntimert_
 
const ldmx::EcalGeometrygeometry_
 handle to current geometry (to share with member functions)
 

Additional Inherited Members

- Static Public Member Functions inherited from framework::EventProcessor
static void declare (const std::string &classname, int classtype, EventProcessorMaker *)
 Internal function which is part of the PluginFactory machinery.
 
- Static Public Attributes inherited from framework::Producer
static const int CLASSTYPE {1}
 Constant used to track EventProcessor types by the PluginFactory.
 
- Protected Member Functions inherited from framework::EventProcessor
void abortEvent ()
 Abort the event immediately.
 
- Protected Attributes inherited from framework::EventProcessor
HistogramHelper histograms_
 Interface class for making and filling histograms.
 
NtupleManagerntuple_ {NtupleManager::getInstance()}
 Manager for any ntuples.
 
logging::logger theLog_
 The logger for this EventProcessor.
 

Detailed Description

Determines if event is vetoable using ECAL hit information.

Definition at line 32 of file EcalVetoProcessor.h.

Member Typedef Documentation

◆ CellEnergyPair

typedef std::pair<ldmx::EcalID, float> ecal::EcalVetoProcessor::CellEnergyPair

Definition at line 34 of file EcalVetoProcessor.h.

◆ XYCoords

typedef std::pair<float, float> ecal::EcalVetoProcessor::XYCoords

Definition at line 36 of file EcalVetoProcessor.h.

Constructor & Destructor Documentation

◆ EcalVetoProcessor()

ecal::EcalVetoProcessor::EcalVetoProcessor ( const std::string &  name,
framework::Process process 
)
inline

Definition at line 38 of file EcalVetoProcessor.h.

39 : Producer(name, process) {}
Producer(const std::string &name, Process &process)
Class constructor.

◆ ~EcalVetoProcessor()

virtual ecal::EcalVetoProcessor::~EcalVetoProcessor ( )
inlinevirtual

Definition at line 41 of file EcalVetoProcessor.h.

41{}

Member Function Documentation

◆ buildBDTFeatureVector()

void ecal::EcalVetoProcessor::buildBDTFeatureVector ( const ldmx::EcalVetoResult result)
private

Electron RoC variables

Photon RoC variables

Outside RoC variables

Definition at line 30 of file EcalVetoProcessor.cxx.

31 {
32 // Base variables
33 bdtFeatures_.push_back(result.getNReadoutHits());
34 bdtFeatures_.push_back(result.getSummedDet());
35 bdtFeatures_.push_back(result.getSummedTightIso());
36 bdtFeatures_.push_back(result.getMaxCellDep());
37 bdtFeatures_.push_back(result.getShowerRMS());
38 bdtFeatures_.push_back(result.getXStd());
39 bdtFeatures_.push_back(result.getYStd());
40 bdtFeatures_.push_back(result.getAvgLayerHit());
41 bdtFeatures_.push_back(result.getStdLayerHit());
42 bdtFeatures_.push_back(result.getDeepestLayerHit());
43 bdtFeatures_.push_back(result.getEcalBackEnergy());
44 // MIP tracking
45 bdtFeatures_.push_back(result.getNStraightTracks());
46 // bdtFeatures_.push_back(result.getNLinregTracks());
47 bdtFeatures_.push_back(result.getFirstNearPhLayer());
48 bdtFeatures_.push_back(result.getNNearPhHits());
49 bdtFeatures_.push_back(result.getPhotonTerritoryHits());
50 bdtFeatures_.push_back(result.getEPSep());
51 bdtFeatures_.push_back(result.getEPDot());
52 // Longitudinal segment variables
53 bdtFeatures_.push_back(result.getEnergySeg()[0]);
54 bdtFeatures_.push_back(result.getXMeanSeg()[0]);
55 bdtFeatures_.push_back(result.getYMeanSeg()[0]);
56 bdtFeatures_.push_back(result.getLayerMeanSeg()[0]);
57 bdtFeatures_.push_back(result.getEnergySeg()[1]);
58 bdtFeatures_.push_back(result.getYMeanSeg()[2]);
60 bdtFeatures_.push_back(result.getEleContEnergy()[0][0]);
61 bdtFeatures_.push_back(result.getEleContEnergy()[1][0]);
62 bdtFeatures_.push_back(result.getEleContYMean()[0][0]);
63 bdtFeatures_.push_back(result.getEleContEnergy()[0][1]);
64 bdtFeatures_.push_back(result.getEleContEnergy()[1][1]);
65 bdtFeatures_.push_back(result.getEleContYMean()[0][1]);
67 bdtFeatures_.push_back(result.getPhContNHits()[0][0]);
68 bdtFeatures_.push_back(result.getPhContYMean()[0][0]);
69 bdtFeatures_.push_back(result.getPhContNHits()[0][1]);
71 bdtFeatures_.push_back(result.getOutContEnergy()[0][0]);
72 bdtFeatures_.push_back(result.getOutContEnergy()[1][0]);
73 bdtFeatures_.push_back(result.getOutContEnergy()[2][0]);
74 bdtFeatures_.push_back(result.getOutContNHits()[0][0]);
75 bdtFeatures_.push_back(result.getOutContXMean()[0][0]);
76 bdtFeatures_.push_back(result.getOutContYMean()[0][0]);
77 bdtFeatures_.push_back(result.getOutContYMean()[1][0]);
78 bdtFeatures_.push_back(result.getOutContYStd()[0][0]);
79 bdtFeatures_.push_back(result.getOutContEnergy()[0][1]);
80 bdtFeatures_.push_back(result.getOutContEnergy()[1][1]);
81 bdtFeatures_.push_back(result.getOutContEnergy()[2][1]);
82 bdtFeatures_.push_back(result.getOutContLayerMean()[0][1]);
83 bdtFeatures_.push_back(result.getOutContLayerStd()[0][1]);
84 bdtFeatures_.push_back(result.getOutContEnergy()[0][2]);
85 bdtFeatures_.push_back(result.getOutContLayerMean()[0][2]);
86}
int getNStraightTracks() const
Number of straight tracks found.

References ldmx::EcalVetoResult::getNStraightTracks().

Referenced by produce().

◆ clearProcessor()

void ecal::EcalVetoProcessor::clearProcessor ( )
private

Definition at line 138 of file EcalVetoProcessor.cxx.

138 {
139 cellMap_.clear();
140 cellMapTightIso_.clear();
141 bdtFeatures_.clear();
142
143 nReadoutHits_ = 0;
144 summedDet_ = 0;
145 summedTightIso_ = 0;
146 maxCellDep_ = 0;
147 showerRMS_ = 0;
148 xStd_ = 0;
149 yStd_ = 0;
150 avgLayerHit_ = 0;
151 stdLayerHit_ = 0;
152 deepestLayerHit_ = 0;
153 ecalBackEnergy_ = 0;
154 // MIP tracking
156 nLinregTracks_ = 0;
158 nNearPhHits_ = 0;
159 epAng_ = 0;
160 epSep_ = 0;
161 epDot_ = 0;
163
164 std::fill(ecalLayerEdepRaw_.begin(), ecalLayerEdepRaw_.end(), 0);
165 std::fill(ecalLayerEdepReadout_.begin(), ecalLayerEdepReadout_.end(), 0);
166 std::fill(ecalLayerTime_.begin(), ecalLayerTime_.end(), 0);
167}
float epSep_
Distance between the projected photon and electron trajectories at the ECal face.
int photonTerritoryHits_
Number of hits in the photon territory.
float epAng_
Angular separation between the projected photon and electron trajectories (currently unused)
int nStraightTracks_
Number of "straight" tracks found in the event.
int nLinregTracks_
Number of "linreg" tracks found in the event.
int firstNearPhLayer_
First ECal layer in which a hit is found near the photon.
float epDot_
Dot product of the photon and electron momenta unit vectors.
int nNearPhHits_
Number of hits near the photon trajectory.

◆ configure()

void ecal::EcalVetoProcessor::configure ( framework::config::Parameters parameters)
overridevirtual

Configure the processor using the given user specified parameters.

Parameters
parametersSet of parameters used to configure this processor.

Reimplemented from framework::EventProcessor.

Definition at line 88 of file EcalVetoProcessor.cxx.

88 {
89 verbose_ = parameters.getParameter<bool>("verbose");
90 featureListName_ = parameters.getParameter<std::string>("feature_list_name");
91 // Load BDT ONNX file
92 rt_ = std::make_unique<ldmx::Ort::ONNXRuntime>(
93 parameters.getParameter<std::string>("bdt_file"));
94
95 // Read in arrays holding 68% containment radius per layer
96 // for different bins in momentum/angle
97 rocFileName_ = parameters.getParameter<std::string>("roc_file");
98 if (!std::ifstream(rocFileName_).good()) {
99 EXCEPTION_RAISE(
100 "EcalVetoProcessor",
101 "The specified RoC file '" + rocFileName_ + "' does not exist!");
102 } else {
103 std::ifstream rocfile(rocFileName_);
104 std::string line, value;
105
106 // Extract the first line in the file
107 std::getline(rocfile, line);
108 std::vector<double> values;
109
110 // Read data, line by line
111 while (std::getline(rocfile, line)) {
112 std::stringstream ss(line);
113 values.clear();
114 while (std::getline(ss, value, ',')) {
115 double f_value = (value != "") ? std::stof(value) : -1.0;
116 values.push_back(f_value);
117 }
118 roc_range_values_.push_back(values);
119 }
120 }
121
122 nEcalLayers_ = parameters.getParameter<int>("num_ecal_layers");
123
124 bdtCutVal_ = parameters.getParameter<double>("disc_cut");
125 ecalLayerEdepRaw_.resize(nEcalLayers_, 0);
126 ecalLayerEdepReadout_.resize(nEcalLayers_, 0);
127 ecalLayerTime_.resize(nEcalLayers_, 0);
128
129 beamEnergyMeV_ = parameters.getParameter<double>("beam_energy");
130 linreg_radius_ = parameters.getParameter<double>("linreg_radius");
131
132 // Set the collection name as defined in the configuration
133 collectionName_ = parameters.getParameter<std::string>("collection_name");
134 rec_pass_name_ = parameters.getParameter<std::string>("rec_pass_name");
135 rec_coll_name_ = parameters.getParameter<std::string>("rec_coll_name");
136}
std::string collectionName_
Name of the collection which will containt the results.
T getParameter(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:89

References collectionName_, and framework::config::Parameters::getParameter().

◆ distPtToLine()

float ecal::EcalVetoProcessor::distPtToLine ( TVector3  h1,
TVector3  p1,
TVector3  p2 
)
private

Return the minimum distance between the point h1 and the line passing through points p1 and p2.

Parameters
[in]h1Point to find the distance to
[in]p1An arbitrary point on the line
[in]p2A second, distinct point on the line
Returns
Minimum distance between h1 and the line

Definition at line 1273 of file EcalVetoProcessor.cxx.

1273 {
1274 return ((h1 - p1).Cross(h1 - p2)).Mag() / (p1 - p2).Mag();
1275}

Referenced by produce().

◆ distTwoLines()

float ecal::EcalVetoProcessor::distTwoLines ( TVector3  v1,
TVector3  v2,
TVector3  w1,
TVector3  w2 
)
private

Returns the distance between the lines v and w, with v defined to pass through the points (v1,v2) (and similarly for w).

Parameters
[in]v1An arbitrary point on line v
[in]v2A second, distinct point on line v
[in]w1An arbitrary point on line w
[in]w2A second, distinct point on line w
Returns
Closest distance of approach of lines u and v

Definition at line 1260 of file EcalVetoProcessor.cxx.

1261 {
1262 TVector3 e1 = v1 - v2;
1263 TVector3 e2 = w1 - w2;
1264 TVector3 crs = e1.Cross(e2);
1265 if (crs.Mag() == 0) {
1266 return 100.0; // arbitrary large number; edge case that shouldn't cause
1267 // problems.
1268 } else {
1269 return std::abs(crs.Dot(v1 - w1) / crs.Mag());
1270 }
1271}

Referenced by produce().

◆ fillHitMap()

void ecal::EcalVetoProcessor::fillHitMap ( const std::vector< ldmx::EcalHit > &  ecalRecHits,
std::map< ldmx::EcalID, float > &  cellMap_ 
)
private

Function to load up empty vector of hit maps.

Definition at line 1191 of file EcalVetoProcessor.cxx.

1193 {
1194 for (const ldmx::EcalHit &hit : ecalRecHits) {
1195 ldmx::EcalID id(hit.getID());
1196 cellMap.emplace(id, hit.getEnergy());
1197 }
1198}
Stores reconstructed hit information from the ECAL.
Definition EcalHit.h:19
Extension of DetectorID providing access to ECal layers and cell numbers in a hex grid.
Definition EcalID.h:20

Referenced by produce().

◆ fillIsolatedHitMap()

void ecal::EcalVetoProcessor::fillIsolatedHitMap ( const std::vector< ldmx::EcalHit > &  ecalRecHits,
ldmx::EcalID  globalCentroid,
std::map< ldmx::EcalID, float > &  cellMap,
std::map< ldmx::EcalID, float > &  cellMapIso,
bool  doTight = false 
)
private

Definition at line 1200 of file EcalVetoProcessor.cxx.

1203 {
1204 for (const ldmx::EcalHit &hit : ecalRecHits) {
1205 auto isolatedHit = std::make_pair(true, ldmx::EcalID());
1206 ldmx::EcalID id(hit.getID());
1207 if (doTight) {
1208 // Disregard hits that are on the centroid.
1209 if (id == globalCentroid) continue;
1210
1211 // Skip hits that are on centroid inner ring
1212 if (geometry_->isNN(globalCentroid, id)) {
1213 continue;
1214 }
1215 }
1216
1217 // Skip hits that have a readout neighbor
1218 // Get neighboring cell id's and try to look them up in the full cell map
1219 // (constant speed algo.)
1220 // these ideas are only cell/module (must ignore layer)
1221 std::vector<ldmx::EcalID> cellNbrIds = geometry_->getNN(id);
1222
1223 for (int k = 0; k < cellNbrIds.size(); k++) {
1224 // update neighbor ID to the current layer
1225 cellNbrIds[k] = ldmx::EcalID(id.layer(), cellNbrIds[k].module(),
1226 cellNbrIds[k].cell());
1227 // look in cell hit map to see if it is there
1228 if (cellMap.find(cellNbrIds[k]) != cellMap.end()) {
1229 isolatedHit = std::make_pair(false, cellNbrIds[k]);
1230 break;
1231 }
1232 }
1233 if (!isolatedHit.first) {
1234 continue;
1235 }
1236 // Insert isolated hit
1237 cellMapIso.emplace(id, hit.getEnergy());
1238 }
1239}
const ldmx::EcalGeometry * geometry_
handle to current geometry (to share with member functions)
std::vector< EcalID > getNN(EcalID id) const
Get the Nearest Neighbors of the input ID.
bool isNN(EcalID centroid, EcalID probe) const
Check if the probe id is one of the nearest neightbors of the centroid id.

◆ GetShowerCentroidIDAndRMS()

ldmx::EcalID ecal::EcalVetoProcessor::GetShowerCentroidIDAndRMS ( const std::vector< ldmx::EcalHit > &  ecalRecHits,
double &  showerRMS 
)
private

Definition at line 1144 of file EcalVetoProcessor.cxx.

1145 {
1146 auto wgtCentroidCoords = std::make_pair<float, float>(0., 0.);
1147 float sumEdep = 0;
1148 ldmx::EcalID returnCellId;
1149
1150 // Calculate Energy Weighted Centroid
1151 for (const ldmx::EcalHit &hit : ecalRecHits) {
1152 ldmx::EcalID id(hit.getID());
1153 CellEnergyPair cell_energy_pair = std::make_pair(id, hit.getEnergy());
1154 auto [x, y, z] = geometry_->getPosition(id);
1155 XYCoords centroidCoords = std::make_pair(x, y);
1156 wgtCentroidCoords.first = wgtCentroidCoords.first +
1157 centroidCoords.first * cell_energy_pair.second;
1158 wgtCentroidCoords.second = wgtCentroidCoords.second +
1159 centroidCoords.second * cell_energy_pair.second;
1160 sumEdep += cell_energy_pair.second;
1161 }
1162 wgtCentroidCoords.first = (sumEdep > 1E-6) ? wgtCentroidCoords.first / sumEdep
1163 : wgtCentroidCoords.first;
1164 wgtCentroidCoords.second = (sumEdep > 1E-6)
1165 ? wgtCentroidCoords.second / sumEdep
1166 : wgtCentroidCoords.second;
1167 // Find Nearest Cell to Centroid
1168 float maxDist = 1e6;
1169 for (const ldmx::EcalHit &hit : ecalRecHits) {
1170 auto [x, y, z] = geometry_->getPosition(hit.getID());
1171 XYCoords centroidCoords = std::make_pair(x, y);
1172
1173 float deltaR =
1174 pow(pow((centroidCoords.first - wgtCentroidCoords.first), 2) +
1175 pow((centroidCoords.second - wgtCentroidCoords.second), 2),
1176 .5);
1177 showerRMS += deltaR * hit.getEnergy();
1178 if (deltaR < maxDist) {
1179 maxDist = deltaR;
1180 returnCellId = ldmx::EcalID(hit.getID());
1181 }
1182 }
1183 if (sumEdep > 0) showerRMS = showerRMS / sumEdep;
1184 // flatten
1185 return ldmx::EcalID(0, returnCellId.module(), returnCellId.cell());
1186}
std::tuple< double, double, double > getPosition(EcalID id) const
Get a cell's position from its ID number.
int cell() const
Get the value of the cell field from the ID.
Definition EcalID.h:111
int module() const
Get the value of the module field from the ID.
Definition EcalID.h:87

◆ getTrajectory()

std::vector< std::pair< float, float > > ecal::EcalVetoProcessor::getTrajectory ( std::vector< double >  momentum,
std::vector< float >  position 
)
private

Definition at line 1243 of file EcalVetoProcessor.cxx.

1244 {
1245 std::vector<XYCoords> positions;
1246 for (int iLayer = 0; iLayer < nEcalLayers_; iLayer++) {
1247 float posX =
1248 position[0] + (momentum[0] / momentum[2]) *
1249 (geometry_->getZPosition(iLayer) - position[2]);
1250 float posY =
1251 position[1] + (momentum[1] / momentum[2]) *
1252 (geometry_->getZPosition(iLayer) - position[2]);
1253 positions.push_back(std::make_pair(posX, posY));
1254 }
1255 return positions;
1256}
double getZPosition(int layer) const
Get the z-coordinate given the layer id.

◆ produce()

void ecal::EcalVetoProcessor::produce ( framework::Event event)
overridevirtual

Process the event and put new data products into it.

Parameters
eventThe Event to process.

Implements framework::Producer.

Definition at line 169 of file EcalVetoProcessor.cxx.

169 {
170 // Get the Ecal Geometry
171 geometry_ = &getCondition<ldmx::EcalGeometry>(
172 ldmx::EcalGeometry::CONDITIONS_OBJECT_NAME);
173
175
176 clearProcessor();
177
178 // Get the collection of Ecal scoring plane hits. If it doesn't exist,
179 // don't bother adding any truth tracking information.
180
181 std::vector<double> recoilP;
182 std::vector<float> recoilPos;
183 std::vector<double> recoilPAtTarget;
184 std::vector<float> recoilPosAtTarget;
185
186 if (verbose_) {
187 ldmx_log(debug) << " Loop through all of the sim particles and find the "
188 "recoil electron";
189 }
190
191 if (event.exists("EcalScoringPlaneHits")) {
192 //
193 // Loop through all of the sim particles and find the recoil electron.
194 //
195
196 // Get the collection of simulated particles from the event
197 auto particleMap{event.getMap<int, ldmx::SimParticle>("SimParticles")};
198
199 // Search for the recoil electron
200 auto [recoilTrackID, recoilElectron] = Analysis::getRecoil(particleMap);
201
202 // Find ECAL SP hit for recoil electron
203 auto ecalSpHits{
204 event.getCollection<ldmx::SimTrackerHit>("EcalScoringPlaneHits")};
205 float pmax = 0;
206 for (ldmx::SimTrackerHit &spHit : ecalSpHits) {
207 ldmx::SimSpecialID hit_id(spHit.getID());
208 if (hit_id.plane() != 31 || spHit.getMomentum()[2] <= 0) continue;
209
210 if (spHit.getTrackID() == recoilTrackID) {
211 if (sqrt(pow(spHit.getMomentum()[0], 2) +
212 pow(spHit.getMomentum()[1], 2) +
213 pow(spHit.getMomentum()[2], 2)) > pmax) {
214 recoilP = spHit.getMomentum();
215 recoilPos = spHit.getPosition();
216 pmax = sqrt(pow(recoilP[0], 2) + pow(recoilP[1], 2) +
217 pow(recoilP[2], 2));
218 }
219 }
220 }
221
222 // Find target SP hit for recoil electron
223 if (event.exists("TargetScoringPlaneHits")) {
224 std::vector<ldmx::SimTrackerHit> targetSpHits =
225 event.getCollection<ldmx::SimTrackerHit>("TargetScoringPlaneHits");
226 pmax = 0;
227 for (ldmx::SimTrackerHit &spHit : targetSpHits) {
228 ldmx::SimSpecialID hit_id(spHit.getID());
229 if (hit_id.plane() != 1 || spHit.getMomentum()[2] <= 0) continue;
230
231 if (spHit.getTrackID() == recoilTrackID) {
232 if (sqrt(pow(spHit.getMomentum()[0], 2) +
233 pow(spHit.getMomentum()[1], 2) +
234 pow(spHit.getMomentum()[2], 2)) > pmax) {
235 recoilPAtTarget = spHit.getMomentum();
236 recoilPosAtTarget = spHit.getPosition();
237 pmax =
238 sqrt(pow(recoilPAtTarget[0], 2) + pow(recoilPAtTarget[1], 2) +
239 pow(recoilPAtTarget[2], 2));
240 }
241 }
242 }
243 }
244 }
245
246 if (verbose_) {
247 ldmx_log(debug) << " Get projected trajectories for electron and photon";
248 }
249 // Get projected trajectories for electron and photon
250 std::vector<XYCoords> ele_trajectory, photon_trajectory;
251 if (recoilP.size() > 0) {
252 ele_trajectory = getTrajectory(recoilP, recoilPos);
253 std::vector<double> pvec = recoilPAtTarget.size()
254 ? recoilPAtTarget
255 : std::vector<double>{0.0, 0.0, 0.0};
256 std::vector<float> posvec = recoilPosAtTarget.size()
257 ? recoilPosAtTarget
258 : std::vector<float>{0.0, 0.0, 0.0};
259 photon_trajectory =
260 getTrajectory({-pvec[0], -pvec[1], beamEnergyMeV_ - pvec[2]}, posvec);
261 }
262
263 float recoilPMag =
264 recoilP.size()
265 ? sqrt(pow(recoilP[0], 2) + pow(recoilP[1], 2) + pow(recoilP[2], 2))
266 : -1.0;
267 float recoilTheta =
268 recoilPMag > 0 ? acos(recoilP[2] / recoilPMag) * 180.0 / M_PI : -1.0;
269
270 if (verbose_) {
271 ldmx_log(debug) << " Build Radii of containment (ROC)";
272 }
273 // Use the appropriate containment radii for the recoil electron
274 std::vector<double> roc_values_bin0(roc_range_values_[0].begin() + 4,
275 roc_range_values_[0].end());
276 std::vector<double> ele_radii = roc_values_bin0;
277 double theta_min, theta_max, p_min, p_max;
278 bool inrange;
279
280 for (int i = 0; i < roc_range_values_.size(); i++) {
281 theta_min = roc_range_values_[i][0];
282 theta_max = roc_range_values_[i][1];
283 p_min = roc_range_values_[i][2];
284 p_max = roc_range_values_[i][3];
285 inrange = true;
286
287 if (theta_min != -1.0) {
288 inrange = inrange && (recoilTheta >= theta_min);
289 }
290 if (theta_max != -1.0) {
291 inrange = inrange && (recoilTheta < theta_max);
292 }
293 if (p_min != -1.0) {
294 inrange = inrange && (recoilPMag >= p_min);
295 }
296 if (p_max != -1.0) {
297 inrange = inrange && (recoilPMag < p_max);
298 }
299 if (inrange) {
300 std::vector<double> roc_values_bini(roc_range_values_[i].begin() + 4,
301 roc_range_values_[i].end());
302 ele_radii = roc_values_bini;
303 }
304 }
305 // Use default RoC bin for photon
306 std::vector<double> photon_radii = roc_values_bin0;
307
308 // Get the collection of digitized Ecal hits from the event.
309 const std::vector<ldmx::EcalHit> ecalRecHits =
310 event.getCollection<ldmx::EcalHit>(rec_coll_name_, rec_pass_name_);
311
312 ldmx::EcalID globalCentroid =
313 GetShowerCentroidIDAndRMS(ecalRecHits, showerRMS_);
314 /* ~~ Fill the hit map ~~ O(n) */
315 fillHitMap(ecalRecHits, cellMap_);
316 bool doTight = true;
317 /* ~~ Fill the isolated hit maps ~~ O(n) */
318 fillIsolatedHitMap(ecalRecHits, globalCentroid, cellMap_, cellMapTightIso_,
319 doTight);
320
321 // Loop over the hits from the event to calculate the rest of the important
322 // quantities
323
324 float wavgLayerHit = 0;
325 float xMean = 0;
326 float yMean = 0;
327
328 // Containment variables
329 unsigned int nregions = 5;
330 std::vector<float> electronContainmentEnergy(nregions, 0.0);
331 std::vector<float> photonContainmentEnergy(nregions, 0.0);
332 std::vector<float> outsideContainmentEnergy(nregions, 0.0);
333 std::vector<int> outsideContainmentNHits(nregions, 0);
334 std::vector<float> outsideContainmentXmean(nregions, 0.0);
335 std::vector<float> outsideContainmentYmean(nregions, 0.0);
336 std::vector<float> outsideContainmentXstd(nregions, 0.0);
337 std::vector<float> outsideContainmentYstd(nregions, 0.0);
338 // Longitudinal segmentation
339 std::vector<int> segLayers = {0, 6, 17, 34};
340 unsigned int nsegments = segLayers.size() - 1;
341 std::vector<float> energySeg(nsegments, 0.0);
342 std::vector<float> xMeanSeg(nsegments, 0.0);
343 std::vector<float> xStdSeg(nsegments, 0.0);
344 std::vector<float> yMeanSeg(nsegments, 0.0);
345 std::vector<float> yStdSeg(nsegments, 0.0);
346 std::vector<float> layerMeanSeg(nsegments, 0.0);
347 std::vector<float> layerStdSeg(nsegments, 0.0);
348 std::vector<std::vector<float>> eContEnergy(
349 nregions, std::vector<float>(nsegments, 0.0));
350 std::vector<std::vector<float>> eContXMean(
351 nregions, std::vector<float>(nsegments, 0.0));
352 std::vector<std::vector<float>> eContYMean(
353 nregions, std::vector<float>(nsegments, 0.0));
354 std::vector<std::vector<float>> gContEnergy(
355 nregions, std::vector<float>(nsegments, 0.0));
356 std::vector<std::vector<int>> gContNHits(nregions,
357 std::vector<int>(nsegments, 0));
358 std::vector<std::vector<float>> gContXMean(
359 nregions, std::vector<float>(nsegments, 0.0));
360 std::vector<std::vector<float>> gContYMean(
361 nregions, std::vector<float>(nsegments, 0.0));
362 std::vector<std::vector<float>> oContEnergy(
363 nregions, std::vector<float>(nsegments, 0.0));
364 std::vector<std::vector<int>> oContNHits(nregions,
365 std::vector<int>(nsegments, 0));
366 std::vector<std::vector<float>> oContXMean(
367 nregions, std::vector<float>(nsegments, 0.0));
368 std::vector<std::vector<float>> oContYMean(
369 nregions, std::vector<float>(nsegments, 0.0));
370 std::vector<std::vector<float>> oContXStd(nregions,
371 std::vector<float>(nsegments, 0.0));
372 std::vector<std::vector<float>> oContYStd(nregions,
373 std::vector<float>(nsegments, 0.0));
374 std::vector<std::vector<float>> oContLayerMean(
375 nregions, std::vector<float>(nsegments, 0.0));
376 std::vector<std::vector<float>> oContLayerStd(
377 nregions, std::vector<float>(nsegments, 0.0));
378
379 // MIP tracking: vector of hits to be used in the MIP tracking algorithm. All
380 // hits inside the electron ROC (or all hits in the ECal if the event is
381 // missing an electron) will be included.
382 std::vector<HitData> trackingHitList;
383
384 if (verbose_) {
385 ldmx_log(debug)
386 << " Loop over the hits from the event to calculate the BDT features";
387 }
388
389 for (const ldmx::EcalHit &hit : ecalRecHits) {
390 // Layer-wise quantities
391 ldmx::EcalID id(hit.getID());
392 ecalLayerEdepRaw_[id.layer()] =
393 ecalLayerEdepRaw_[id.layer()] + hit.getEnergy();
394 if (id.layer() >= 20) ecalBackEnergy_ += hit.getEnergy();
395 if (maxCellDep_ < hit.getEnergy()) maxCellDep_ = hit.getEnergy();
396 if (hit.getEnergy() > 0) {
397 nReadoutHits_++;
398 ecalLayerEdepReadout_[id.layer()] += hit.getEnergy();
399 ecalLayerTime_[id.layer()] += (hit.getEnergy()) * hit.getTime();
400 auto [x, y, z] = geometry_->getPosition(id);
401 xMean += x * hit.getEnergy();
402 yMean += y * hit.getEnergy();
403 avgLayerHit_ += id.layer();
404 wavgLayerHit += id.layer() * hit.getEnergy();
405 if (deepestLayerHit_ < id.layer()) {
406 deepestLayerHit_ = id.layer();
407 }
408 XYCoords xy_pair = std::make_pair(x, y);
409 float distance_ele_trajectory =
410 ele_trajectory.size()
411 ? sqrt(
412 pow((xy_pair.first - ele_trajectory[id.layer()].first), 2) +
413 pow((xy_pair.second - ele_trajectory[id.layer()].second),
414 2))
415 : -1.0;
416 float distance_photon_trajectory =
417 photon_trajectory.size()
418 ? sqrt(
419 pow((xy_pair.first - photon_trajectory[id.layer()].first),
420 2) +
421 pow((xy_pair.second - photon_trajectory[id.layer()].second),
422 2))
423 : -1.0;
424
425 // Decide which longitudinal segment the hit is in and add to sums
426 for (unsigned int iseg = 0; iseg < nsegments; iseg++) {
427 if (id.layer() >= segLayers[iseg] &&
428 id.layer() <= segLayers[iseg + 1] - 1) {
429 energySeg[iseg] += hit.getEnergy();
430 xMeanSeg[iseg] += xy_pair.first * hit.getEnergy();
431 yMeanSeg[iseg] += xy_pair.second * hit.getEnergy();
432 layerMeanSeg[iseg] += id.layer() * hit.getEnergy();
433
434 // Decide which containment region the hit is in and add to sums
435 for (unsigned int ireg = 0; ireg < nregions; ireg++) {
436 if (distance_ele_trajectory >= ireg * ele_radii[id.layer()] &&
437 distance_ele_trajectory < (ireg + 1) * ele_radii[id.layer()]) {
438 eContEnergy[ireg][iseg] += hit.getEnergy();
439 eContXMean[ireg][iseg] += xy_pair.first * hit.getEnergy();
440 eContYMean[ireg][iseg] += xy_pair.second * hit.getEnergy();
441 }
442 if (distance_photon_trajectory >= ireg * photon_radii[id.layer()] &&
443 distance_photon_trajectory <
444 (ireg + 1) * photon_radii[id.layer()]) {
445 gContEnergy[ireg][iseg] += hit.getEnergy();
446 gContNHits[ireg][iseg] += 1;
447 gContXMean[ireg][iseg] += xy_pair.first * hit.getEnergy();
448 gContYMean[ireg][iseg] += xy_pair.second * hit.getEnergy();
449 }
450 if (distance_ele_trajectory > (ireg + 1) * ele_radii[id.layer()] &&
451 distance_photon_trajectory >
452 (ireg + 1) * photon_radii[id.layer()]) {
453 oContEnergy[ireg][iseg] += hit.getEnergy();
454 oContNHits[ireg][iseg] += 1;
455 oContXMean[ireg][iseg] += xy_pair.first * hit.getEnergy();
456 oContYMean[ireg][iseg] += xy_pair.second * hit.getEnergy();
457 oContLayerMean[ireg][iseg] += id.layer() * hit.getEnergy();
458 }
459 }
460 }
461 }
462
463 // Decide which containment region the hit is in and add to sums
464 for (unsigned int ireg = 0; ireg < nregions; ireg++) {
465 if (distance_ele_trajectory >= ireg * ele_radii[id.layer()] &&
466 distance_ele_trajectory < (ireg + 1) * ele_radii[id.layer()])
467 electronContainmentEnergy[ireg] += hit.getEnergy();
468 if (distance_photon_trajectory >= ireg * photon_radii[id.layer()] &&
469 distance_photon_trajectory < (ireg + 1) * photon_radii[id.layer()])
470 photonContainmentEnergy[ireg] += hit.getEnergy();
471 if (distance_ele_trajectory > (ireg + 1) * ele_radii[id.layer()] &&
472 distance_photon_trajectory >
473 (ireg + 1) * photon_radii[id.layer()]) {
474 outsideContainmentEnergy[ireg] += hit.getEnergy();
475 outsideContainmentNHits[ireg] += 1;
476 outsideContainmentXmean[ireg] += xy_pair.first * hit.getEnergy();
477 outsideContainmentYmean[ireg] += xy_pair.second * hit.getEnergy();
478 }
479 }
480
481 // MIP tracking: Decide whether hit should be added to trackingHitList
482 // If inside e- RoC or if etraj is missing, use the hit for tracking:
483 if (distance_ele_trajectory >= ele_radii[id.layer()] ||
484 distance_ele_trajectory == -1.0) {
485 HitData hd;
486 hd.pos = TVector3(xy_pair.first, xy_pair.second,
487 geometry_->getZPosition(id.layer()));
488 hd.layer = id.layer();
489 trackingHitList.push_back(hd);
490 }
491 }
492 } // end loop over rechits
493
494 for (const auto &[id, energy] : cellMapTightIso_) {
495 if (energy > 0) summedTightIso_ += energy;
496 }
497
498 for (int iLayer = 0; iLayer < ecalLayerEdepReadout_.size(); iLayer++) {
499 ecalLayerTime_[iLayer] =
500 ecalLayerTime_[iLayer] / ecalLayerEdepReadout_[iLayer];
501 summedDet_ += ecalLayerEdepReadout_[iLayer];
502 }
503
504 if (nReadoutHits_ > 0) {
505 avgLayerHit_ /= nReadoutHits_;
506 wavgLayerHit /= summedDet_;
507 xMean /= summedDet_;
508 yMean /= summedDet_;
509 } else {
510 wavgLayerHit = 0;
511 avgLayerHit_ = 0;
512 xMean = 0;
513 yMean = 0;
514 }
515
516 // If necessary, quotient out the total energy from the means
517 for (unsigned int iseg = 0; iseg < nsegments; iseg++) {
518 if (energySeg[iseg] > 0) {
519 xMeanSeg[iseg] /= energySeg[iseg];
520 yMeanSeg[iseg] /= energySeg[iseg];
521 layerMeanSeg[iseg] /= energySeg[iseg];
522 }
523 for (unsigned int ireg = 0; ireg < nregions; ireg++) {
524 if (eContEnergy[ireg][iseg] > 0) {
525 eContXMean[ireg][iseg] /= eContEnergy[ireg][iseg];
526 eContYMean[ireg][iseg] /= eContEnergy[ireg][iseg];
527 }
528 if (gContEnergy[ireg][iseg] > 0) {
529 gContXMean[ireg][iseg] /= gContEnergy[ireg][iseg];
530 gContYMean[ireg][iseg] /= gContEnergy[ireg][iseg];
531 }
532 if (oContEnergy[ireg][iseg] > 0) {
533 oContXMean[ireg][iseg] /= oContEnergy[ireg][iseg];
534 oContYMean[ireg][iseg] /= oContEnergy[ireg][iseg];
535 oContLayerMean[ireg][iseg] /= oContEnergy[ireg][iseg];
536 }
537 }
538 }
539
540 for (unsigned int ireg = 0; ireg < nregions; ireg++) {
541 if (outsideContainmentEnergy[ireg] > 0) {
542 outsideContainmentXmean[ireg] /= outsideContainmentEnergy[ireg];
543 outsideContainmentYmean[ireg] /= outsideContainmentEnergy[ireg];
544 }
545 }
546
547 // Loop over hits a second time to find the standard deviations.
548 for (const ldmx::EcalHit &hit : ecalRecHits) {
549 ldmx::EcalID id(hit.getID());
550 auto [x, y, z] = geometry_->getPosition(id);
551 if (hit.getEnergy() > 0) {
552 xStd_ += pow((x - xMean), 2) * hit.getEnergy();
553 yStd_ += pow((y - yMean), 2) * hit.getEnergy();
554 stdLayerHit_ += pow((id.layer() - wavgLayerHit), 2) * hit.getEnergy();
555 }
556 XYCoords xy_pair = std::make_pair(x, y);
557 float distance_ele_trajectory =
558 ele_trajectory.size()
559 ? sqrt(pow((xy_pair.first - ele_trajectory[id.layer()].first), 2) +
560 pow((xy_pair.second - ele_trajectory[id.layer()].second), 2))
561 : -1.0;
562 float distance_photon_trajectory =
563 photon_trajectory.size()
564 ? sqrt(pow((xy_pair.first - photon_trajectory[id.layer()].first),
565 2) +
566 pow((xy_pair.second - photon_trajectory[id.layer()].second),
567 2))
568 : -1.0;
569
570 for (unsigned int iseg = 0; iseg < nsegments; iseg++) {
571 if (id.layer() >= segLayers[iseg] &&
572 id.layer() <= segLayers[iseg + 1] - 1) {
573 xStdSeg[iseg] +=
574 pow((xy_pair.first - xMeanSeg[iseg]), 2) * hit.getEnergy();
575 yStdSeg[iseg] +=
576 pow((xy_pair.second - yMeanSeg[iseg]), 2) * hit.getEnergy();
577 layerStdSeg[iseg] +=
578 pow((id.layer() - layerMeanSeg[iseg]), 2) * hit.getEnergy();
579
580 for (unsigned int ireg = 0; ireg < nregions; ireg++) {
581 if (distance_ele_trajectory > (ireg + 1) * ele_radii[id.layer()] &&
582 distance_photon_trajectory >
583 (ireg + 1) * photon_radii[id.layer()]) {
584 oContXStd[ireg][iseg] +=
585 pow((xy_pair.first - oContXMean[ireg][iseg]), 2) *
586 hit.getEnergy();
587 oContYStd[ireg][iseg] +=
588 pow((xy_pair.second - oContYMean[ireg][iseg]), 2) *
589 hit.getEnergy();
590 oContLayerStd[ireg][iseg] +=
591 pow((id.layer() - oContLayerMean[ireg][iseg]), 2) *
592 hit.getEnergy();
593 }
594 }
595 }
596 }
597
598 for (unsigned int ireg = 0; ireg < nregions; ireg++) {
599 if (distance_ele_trajectory > (ireg + 1) * ele_radii[id.layer()] &&
600 distance_photon_trajectory > (ireg + 1) * photon_radii[id.layer()]) {
601 outsideContainmentXstd[ireg] +=
602 pow((xy_pair.first - outsideContainmentXmean[ireg]), 2) *
603 hit.getEnergy();
604 outsideContainmentYstd[ireg] +=
605 pow((xy_pair.second - outsideContainmentYmean[ireg]), 2) *
606 hit.getEnergy();
607 }
608 }
609 } // end loop over rechits (2nd time)
610
611 if (nReadoutHits_ > 0) {
612 xStd_ = sqrt(xStd_ / summedDet_);
613 yStd_ = sqrt(yStd_ / summedDet_);
614 stdLayerHit_ = sqrt(stdLayerHit_ / summedDet_);
615 } else {
616 xStd_ = 0;
617 yStd_ = 0;
618 stdLayerHit_ = 0;
619 }
620
621 // Quotient out the total energies from the standard deviations if possible
622 // and take root
623 for (unsigned int iseg = 0; iseg < nsegments; iseg++) {
624 if (energySeg[iseg] > 0) {
625 xStdSeg[iseg] = sqrt(xStdSeg[iseg] / energySeg[iseg]);
626 yStdSeg[iseg] = sqrt(yStdSeg[iseg] / energySeg[iseg]);
627 layerStdSeg[iseg] = sqrt(layerStdSeg[iseg] / energySeg[iseg]);
628 }
629 for (unsigned int ireg = 0; ireg < nregions; ireg++) {
630 if (oContEnergy[ireg][iseg] > 0) {
631 oContXStd[ireg][iseg] =
632 sqrt(oContXStd[ireg][iseg] / oContEnergy[ireg][iseg]);
633 oContYStd[ireg][iseg] =
634 sqrt(oContYStd[ireg][iseg] / oContEnergy[ireg][iseg]);
635 oContLayerStd[ireg][iseg] =
636 sqrt(oContLayerStd[ireg][iseg] / oContEnergy[ireg][iseg]);
637 }
638 }
639 }
640
641 for (unsigned int ireg = 0; ireg < nregions; ireg++) {
642 if (outsideContainmentEnergy[ireg] > 0) {
643 outsideContainmentXstd[ireg] =
644 sqrt(outsideContainmentXstd[ireg] / outsideContainmentEnergy[ireg]);
645 outsideContainmentYstd[ireg] =
646 sqrt(outsideContainmentYstd[ireg] / outsideContainmentEnergy[ireg]);
647 }
648 }
649
650 if (verbose_) {
651 ldmx_log(debug) << " Find out if the recoil electron is fiducial";
652 }
653
654 // Find the location of the recoil electron
655 // Ecal face is not where the first layer starts,
656 // defined in DetDescr/python/EcalGeometry.py
657 const float dz_from_face{7.932};
658 float drifted_recoil_x{-9999.};
659 float drifted_recoil_y{-9999.};
660 if (recoilP.size() > 0) {
661 drifted_recoil_x =
662 (dz_from_face * (recoilP[0] / recoilP[2])) + recoilPos[0];
663 drifted_recoil_y =
664 (dz_from_face * (recoilP[1] / recoilP[2])) + recoilPos[1];
665 }
666 const int recoil_layer_index = 0;
667
668 // Check if it's fiducial
669 bool inside{false};
670 // At module level
671 const auto ecalID = geometry_->getID(drifted_recoil_x, drifted_recoil_y,
672 recoil_layer_index, true);
673 if (!ecalID.null()) {
674 // If fiducial at module level, check at cell level
675 const auto cellID =
676 geometry_->getID(drifted_recoil_x, drifted_recoil_y, recoil_layer_index,
677 ecalID.getModuleID(), true);
678 if (!cellID.null()) {
679 inside = true;
680 }
681 }
682
683 if (!inside) {
684 ldmx_log(info) << "This event is non-fiducial in ECAL";
685 }
686
687 // ------------------------------------------------------
688 // MIP tracking starts here
689
690 /* Goal: Calculate
691 * nStraightTracks (self-explanatory),
692 * nLinregTracks (tracks found by linreg algorithm),
693 */
694
695 // Find epAng and epSep, and prepare EP trajectory vectors:
696 TVector3 e_traj_start;
697 TVector3 e_traj_end;
698 TVector3 p_traj_start;
699 TVector3 p_traj_end;
700 if (ele_trajectory.size() > 0 && photon_trajectory.size() > 0) {
701 // Create TVector3s marking the start and endpoints of each projected
702 // trajectory
703 e_traj_start.SetXYZ(ele_trajectory[0].first, ele_trajectory[0].second,
705 e_traj_end.SetXYZ(ele_trajectory[(nEcalLayers_ - 1)].first,
706 ele_trajectory[(nEcalLayers_ - 1)].second,
707 geometry_->getZPosition((nEcalLayers_ - 1)));
708 p_traj_start.SetXYZ(photon_trajectory[0].first, photon_trajectory[0].second,
710 p_traj_end.SetXYZ(photon_trajectory[(nEcalLayers_ - 1)].first,
711 photon_trajectory[(nEcalLayers_ - 1)].second,
712 geometry_->getZPosition((nEcalLayers_ - 1)));
713
714 TVector3 evec = e_traj_end - e_traj_start;
715 TVector3 e_norm = evec.Unit();
716 TVector3 pvec = p_traj_end - p_traj_start;
717 TVector3 p_norm = pvec.Unit();
718 epDot_ = e_norm.Dot(p_norm);
719 epAng_ = acos(epDot_) * 180.0 / M_PI;
720 epSep_ = sqrt(pow(e_traj_start.X() - p_traj_start.X(), 2) +
721 pow(e_traj_start.Y() - p_traj_start.Y(), 2));
722 } else {
723 // Electron trajectory is missing, so all hits in the Ecal are fair game.
724 // Pick e/ptraj so that they won't restrict the tracking algorithm (place
725 // them far outside the ECal).
726 e_traj_start = TVector3(999, 999, geometry_->getZPosition(0)); // 0);
727 e_traj_end = TVector3(
728 999, 999, geometry_->getZPosition((nEcalLayers_ - 1))); // 999);
729 p_traj_start = TVector3(1000, 1000, geometry_->getZPosition(0)); // 0);
730 p_traj_end = TVector3(
731 1000, 1000, geometry_->getZPosition((nEcalLayers_ - 1))); // 1000);
732 /*ensures event will not be vetoed by angle/separation cut */
733 epAng_ = 999.;
734 epSep_ = 999.;
735 epDot_ = 999.;
736 }
737
738 // Near photon step: Find the first layer of the ECal where a hit near the
739 // projected photon trajectory is found Currently unusued pending further
740 // study; performance has dropped between v9 and v12. Currently used in
741 // segmipBDT
742 firstNearPhLayer_ = nEcalLayers_ - 1;
743
744 if (photon_trajectory.size() !=
745 0) { // If no photon trajectory, leave this at the default (ECal back)
746 for (std::vector<HitData>::iterator it = trackingHitList.begin();
747 it != trackingHitList.end(); ++it) {
748 float ehDist =
749 sqrt(pow((*it).pos.X() - photon_trajectory[(*it).layer].first, 2) +
750 pow((*it).pos.Y() - photon_trajectory[(*it).layer].second, 2));
751 if (ehDist < 8.7) {
752 nNearPhHits_++;
753 if ((*it).layer < firstNearPhLayer_) {
754 firstNearPhLayer_ = (*it).layer;
755 }
756 }
757 }
758 }
759
760 // Territories limited to trackingHitList
761 TVector3 gToe = (e_traj_start - p_traj_start).Unit();
762 TVector3 origin = p_traj_start + 0.5 * 8.7 * gToe;
763 if (ele_trajectory.size() > 0) {
764 for (auto &hitData : trackingHitList) {
765 TVector3 hitPos = hitData.pos;
766 TVector3 hitPrime = hitPos - origin;
767 if (hitPrime.Dot(gToe) <= 0) {
769 }
770 }
771 } else {
772 photonTerritoryHits_ = nReadoutHits_;
773 }
774
775 // ------------------------------------------------------
776 // Find straight MIP tracks:
777
778 std::sort(trackingHitList.begin(), trackingHitList.end(),
779 [](HitData ha, HitData hb) { return ha.layer > hb.layer; });
780 // For merging tracks: Need to keep track of existing tracks
781 // Candidate tracks to merge in will always be in front of the current track
782 // (lower z), so only store the last hit 3-layer vector: each track = vector
783 // of 3-tuples (xy+layer).
784 std::vector<std::vector<HitData>> track_list;
785
786 // print trackingHitList
787 if (verbose_) {
788 ldmx_log(debug) << "====== Tracking hit list (original) length "
789 << trackingHitList.size() << " ======";
790 for (int i = 0; i < trackingHitList.size(); i++) {
791 std::cout << "[" << trackingHitList[i].pos.X() << ", "
792 << trackingHitList[i].pos.Y() << ", "
793 << trackingHitList[i].layer << "], ";
794 }
795 std::cout << std::endl;
796 ldmx_log(debug) << "====== END OF Tracking hit list ======";
797 }
798
799 // in v14 minR is 4.17 mm
800 // while maxR is 4.81 mm
801 float cellWidth = 2 * geometry_->getCellMaxR();
802 for (int iHit = 0; iHit < trackingHitList.size(); iHit++) {
803 // list of hit numbers in track (34 = maximum theoretical length)
804 int track[34];
805 int currenthit{iHit};
806 int trackLen{1};
807
808 track[0] = iHit;
809
810 // Search for hits to add to the track:
811 // repeatedly find hits in the front two layers with same x & y positions
812 // but since v14 the odd layers are offset, so we allow half a cellWidth
813 // deviation and then add to track until no more hits are found
814 int jHit = iHit;
815 while (jHit < trackingHitList.size()) {
816 if ((trackingHitList[jHit].layer ==
817 trackingHitList[currenthit].layer - 1 ||
818 trackingHitList[jHit].layer ==
819 trackingHitList[currenthit].layer - 2) &&
820 abs(trackingHitList[jHit].pos.X() -
821 trackingHitList[currenthit].pos.X()) <= 0.5 * cellWidth &&
822 abs(trackingHitList[jHit].pos.Y() -
823 trackingHitList[currenthit].pos.Y()) <= 0.5 * cellWidth) {
824 track[trackLen] = jHit;
825 trackLen++;
826 currenthit = jHit;
827 }
828 jHit++;
829 }
830
831 // Confirm that the track is valid:
832 if (trackLen < 2) continue; // Track must contain at least 2 hits
833 float closest_e = distTwoLines(trackingHitList[track[0]].pos,
834 trackingHitList[track[trackLen - 1]].pos,
835 e_traj_start, e_traj_end);
836 float closest_p = distTwoLines(trackingHitList[track[0]].pos,
837 trackingHitList[track[trackLen - 1]].pos,
838 p_traj_start, p_traj_end);
839 // Make sure that the track is near the photon trajectory and away from the
840 // electron trajectory Details of these constraints may be revised
841 if (closest_p > cellWidth and closest_e < 2 * cellWidth) continue;
842 if (trackLen < 4 and closest_e > closest_p) continue;
843 if (verbose_) {
844 ldmx_log(debug) << "====== After rejection for MIP tracking ======";
845 ldmx_log(debug) << "current hit: [" << trackingHitList[iHit].pos.X()
846 << ", " << trackingHitList[iHit].pos.Y() << ", "
847 << trackingHitList[iHit].layer << "]";
848
849 for (int k = 0; k < trackLen; k++) {
850 ldmx_log(debug) << "track[" << k << "] position = ["
851 << trackingHitList[track[k]].pos.X() << ", "
852 << trackingHitList[track[k]].pos.Y() << ", "
853 << trackingHitList[track[k]].layer << "]";
854 }
855 }
856
857 // if track found, increment nStraightTracks and remove all hits in track
858 // from future consideration
859 if (trackLen >= 2) {
860 std::vector<HitData> temp_track_list;
861 int n_remove = 0;
862 for (int kHit = 0; kHit < trackLen; kHit++) {
863 temp_track_list.push_back(trackingHitList[track[kHit] - n_remove]);
864 trackingHitList.erase(trackingHitList.begin() + track[kHit] - n_remove);
865 n_remove++;
866 }
867 // print trackingHitList
868 if (verbose_) {
869 ldmx_log(debug) << "====== Tracking hit list (after erase) length "
870 << trackingHitList.size() << " ======";
871 for (int i = 0; i < trackingHitList.size(); i++) {
872 std::cout << "[" << trackingHitList[i].pos.X() << ", "
873 << trackingHitList[i].pos.Y() << ", "
874 << trackingHitList[i].layer << "] ";
875 }
876 std::cout << std::endl;
877 ldmx_log(debug) << "====== END OF Tracking hit list ======";
878 }
879
880 track_list.push_back(temp_track_list);
881 // The *current* hit will have been removed, so iHit is currently pointing
882 // to the next hit. Decrement iHit so no hits will get skipped by iHit++
883 iHit--;
884 }
885 }
886
887 ldmx_log(debug) << "Straight tracks found (before merge): "
888 << track_list.size();
889 if (verbose_) {
890 for (int iTrack = 0; iTrack < track_list.size(); iTrack++) {
891 ldmx_log(debug) << "Track " << iTrack << ":";
892 for (int iHit = 0; iHit < track_list[iTrack].size(); iHit++) {
893 std::cout << " Hit " << iHit << ": ["
894 << track_list[iTrack][iHit].pos.X() << ", "
895 << track_list[iTrack][iHit].pos.Y() << ", "
896 << track_list[iTrack][iHit].layer << "]" << std::endl;
897 }
898 std::cout << std::endl;
899 }
900 }
901
902 // Optional addition: Merge nearby straight tracks. Not necessary for veto.
903 // Criteria: consider tail of track. Merge if head of next track is 1/2
904 // layers behind, within 1 cell of xy position.
905 ldmx_log(debug) << "Beginning track merging using " << track_list.size()
906 << " tracks";
907
908 for (int track_i = 0; track_i < track_list.size(); track_i++) {
909 // for each track, check the remainder of the track list for compatible
910 // tracks
911 std::vector<HitData> base_track = track_list[track_i];
912 HitData tail_hitdata = base_track.back(); // xylayer of last hit in track
913 if (verbose_) ldmx_log(debug) << " Considering track " << track_i;
914 for (int track_j = track_i + 1; track_j < track_list.size(); track_j++) {
915 std::vector<HitData> checking_track = track_list[track_j];
916 HitData head_hitdata = checking_track.front();
917 // if 1-2 layers behind, and xy within one cell...
918 if ((head_hitdata.layer == tail_hitdata.layer + 1 ||
919 head_hitdata.layer == tail_hitdata.layer + 2) &&
920 pow(pow(head_hitdata.pos.X() - tail_hitdata.pos.X(), 2) +
921 pow(head_hitdata.pos.Y() - tail_hitdata.pos.Y(), 2),
922 0.5) <= cellWidth) {
923 // ...then append the second track to the first one and delete it
924 // NOTE: TO ADD: (trackingHitList[iHit].pos -
925 // trackingHitList[jHit].pos).Mag()
926 if (verbose_) {
927 ldmx_log(debug) << " ** Compatible track found at index "
928 << track_j;
929 ldmx_log(debug) << " Tail xylayer: " << head_hitdata.pos.X()
930 << "," << head_hitdata.pos.Y() << ","
931 << head_hitdata.layer;
932 ldmx_log(debug) << " Head xylayer: " << tail_hitdata.pos.X()
933 << "," << tail_hitdata.pos.Y() << ","
934 << tail_hitdata.layer;
935 }
936 for (int hit_k = 0; hit_k < checking_track.size(); hit_k++) {
937 base_track.push_back(track_list[track_j][hit_k]);
938 }
939 track_list[track_i] = base_track;
940 track_list.erase(track_list.begin() + track_j);
941 break;
942 }
943 }
944 }
945 nStraightTracks_ = track_list.size();
946 // print the track list
947 ldmx_log(debug) << "Straight tracks found (after merge): "
949 for (int track_i = 0; track_i < track_list.size(); track_i++) {
950 ldmx_log(debug) << "Track " << track_i << ":";
951 for (int hit_i = 0; hit_i < track_list[track_i].size(); hit_i++) {
952 ldmx_log(debug) << " Hit " << hit_i << ": ["
953 << track_list[track_i][hit_i].pos.X() << ", "
954 << track_list[track_i][hit_i].pos.Y() << ", "
955 << track_list[track_i][hit_i].layer << "]";
956 }
957 }
958
959 // ------------------------------------------------------
960 // Linreg tracking:
961 ldmx_log(debug) << "Finding linreg tracks from a total of "
962 << trackingHitList.size() << " hits using a radius of "
963 << linreg_radius_ << " mm";
964
965 for (int iHit = 0; iHit < trackingHitList.size(); iHit++) {
966 // Hits being considered at a given time
967 std::vector<int> hitsInRegion;
968 TMatrixD Vm(3, 3);
969 TMatrixD hdt(3, 3);
970 TVector3 slopeVec;
971 TVector3 hmean;
972 TVector3 hpoint;
973 float r_corr_best{0.0};
974 // Temp array having 3 potential hits
975 int hitNums[3];
976 // From the above which are passing the correlation reqs
977 int bestHitNums[3];
978
979 hitsInRegion.push_back(iHit);
980 // Find all hits within 2 cells of the primary hit:
981 for (int jHit = 0; jHit < trackingHitList.size(); jHit++) {
982 // Dont try to put hits on the same layer to the lin-reg track
983 if (trackingHitList[iHit].pos(2) == trackingHitList[jHit].pos(2)) {
984 continue;
985 }
986 float dstToHit =
987 (trackingHitList[iHit].pos - trackingHitList[jHit].pos).Mag();
988 // This distance optimized to give the best significance
989 // it used to be 2*cellWidth, i.e. 4.81 mm
990 // note, the layers in the back have a separation of 22.3
991 if (dstToHit <= 2 * linreg_radius_) {
992 hitsInRegion.push_back(jHit);
993 }
994 }
995 // Found a track that passed the lin-reg reqs
996 bool bestLinRegFound{false};
997 if (verbose_) {
998 ldmx_log(debug) << "There are " << hitsInRegion.size()
999 << " hits within a radius of " << linreg_radius_ << " mm";
1000 }
1001 // Look at combinations of hits within the region (do not consider the same
1002 // combination twice):
1003 hitNums[0] = iHit;
1004 for (int jHitInReg = 1; jHitInReg < hitsInRegion.size() - 1; jHitInReg++) {
1005 // We require (exactly) 3 hits for the lin-reg track building
1006 if (hitsInRegion.size() < 3) break;
1007 hitNums[1] = hitsInRegion[jHitInReg];
1008 for (int kHitReg = jHitInReg + 1; kHitReg < hitsInRegion.size();
1009 kHitReg++) {
1010 hitNums[2] = hitsInRegion[kHitReg];
1011 for (int hInd = 0; hInd < 3; hInd++) {
1012 // hmean = geometric mean, subtract off from hits to improve SVD
1013 // performance
1014 hmean(hInd) = (trackingHitList[hitNums[0]].pos(hInd) +
1015 trackingHitList[hitNums[1]].pos(hInd) +
1016 trackingHitList[hitNums[2]].pos(hInd)) /
1017 3.0;
1018 }
1019 for (int hInd = 0; hInd < 3; hInd++) {
1020 for (int lInd = 0; lInd < 3; lInd++) {
1021 hdt(hInd, lInd) =
1022 trackingHitList[hitNums[hInd]].pos(lInd) - hmean(lInd);
1023 }
1024 }
1025
1026 // Perform "linreg" on selected points
1027 // Calculate the determinant of the matrix
1028 double determinant =
1029 hdt(0, 0) * (hdt(1, 1) * hdt(2, 2) - hdt(1, 2) * hdt(2, 1)) -
1030 hdt(0, 1) * (hdt(1, 0) * hdt(2, 2) - hdt(1, 2) * hdt(2, 0)) +
1031 hdt(0, 2) * (hdt(1, 0) * hdt(2, 1) - hdt(1, 1) * hdt(2, 0));
1032 // Exit early if the matrix is singular (i.e. det = 0)
1033 if (determinant == 0) continue;
1034 // Perform matrix decomposition with SVD
1035 TDecompSVD svdObj(hdt);
1036 bool decomposed = svdObj.Decompose();
1037 if (!decomposed) continue;
1038
1039 // First col of V matrix is the slope of the best-fit line
1040 Vm = svdObj.GetV();
1041 for (int hInd = 0; hInd < 3; hInd++) {
1042 slopeVec(hInd) = Vm[0][hInd];
1043 }
1044 // hmean, hpoint are points on the best-fit line
1045 hpoint = slopeVec + hmean;
1046 // linreg complete: Now have best-fit line for 3 hits under
1047 // consideration Check whether the track is valid: r^2 must be high,
1048 // and the track must plausibly originate from the photon
1049 float closest_e = distTwoLines(hmean, hpoint, e_traj_start, e_traj_end);
1050 float closest_p = distTwoLines(hmean, hpoint, p_traj_start, p_traj_end);
1051 // Projected track must be close to the photon; details may change after
1052 // future study.
1053 if (closest_p > cellWidth or closest_e < 1.5 * cellWidth) continue;
1054 // find r^2
1055 // ~variance
1056 float vrnc = (trackingHitList[hitNums[0]].pos - hmean).Mag() +
1057 (trackingHitList[hitNums[1]].pos - hmean).Mag() +
1058 (trackingHitList[hitNums[2]].pos - hmean).Mag();
1059 // sum of |errors|
1060 float sumerr =
1061 distPtToLine(trackingHitList[hitNums[0]].pos, hmean, hpoint) +
1062 distPtToLine(trackingHitList[hitNums[1]].pos, hmean, hpoint) +
1063 distPtToLine(trackingHitList[hitNums[2]].pos, hmean, hpoint);
1064 float r_corr = 1 - sumerr / vrnc;
1065 // Check whether r^2 exceeds a low minimum r_corr: "Fake" tracks are
1066 // still much more common in background, so making the algorithm
1067 // oversensitive doesn't lower performance significantly
1068 if (r_corr > r_corr_best and r_corr > .6) {
1069 r_corr_best = r_corr;
1070 // Only looking for 3-hit tracks currently
1071 bestLinRegFound = true;
1072 for (int k = 0; k < 3; k++) {
1073 bestHitNums[k] = hitNums[k];
1074 }
1075 }
1076 } // end loop on hits in the region
1077 } // end 2nd loop on hits in the region
1078
1079 // Continue early if not hits on track
1080 if (!bestLinRegFound) continue;
1081 // Otherwise increase the number of lin-reg tracks
1083 ldmx_log(debug) << " Lin-reg track " << nLinregTracks_;
1084 for (int finalHitIndx = 0; finalHitIndx < 3; finalHitIndx++) {
1085 ldmx_log(debug) << " Hit " << finalHitIndx << " ["
1086 << trackingHitList[bestHitNums[finalHitIndx]].pos(0)
1087 << ", "
1088 << trackingHitList[bestHitNums[finalHitIndx]].pos(1)
1089 << ", "
1090 << trackingHitList[bestHitNums[finalHitIndx]].pos(2)
1091 << "] ";
1092 }
1093
1094 // Exclude all hits in a found track from further consideration:
1095 for (int lHit = 0; lHit < 3; lHit++) {
1096 trackingHitList.erase(trackingHitList.begin() + bestHitNums[lHit]);
1097 }
1098 iHit--;
1099 } // end loop on all hits
1100
1101 ldmx_log(info) << " MIP tracking completed; found " << nStraightTracks_
1102 << " straight tracks and " << nLinregTracks_
1103 << " lin-reg tracks";
1104
1105 result.setVariables(
1106 nReadoutHits_, deepestLayerHit_, summedDet_, summedTightIso_, maxCellDep_,
1107 showerRMS_, xStd_, yStd_, avgLayerHit_, stdLayerHit_, ecalBackEnergy_,
1109 photonTerritoryHits_, epAng_, epSep_, epDot_, electronContainmentEnergy,
1110 photonContainmentEnergy, outsideContainmentEnergy,
1111 outsideContainmentNHits, outsideContainmentXstd, outsideContainmentYstd,
1112 energySeg, xMeanSeg, yMeanSeg, xStdSeg, yStdSeg, layerMeanSeg,
1113 layerStdSeg, eContEnergy, eContXMean, eContYMean, gContEnergy, gContNHits,
1114 gContXMean, gContYMean, oContEnergy, oContNHits, oContXMean, oContYMean,
1115 oContXStd, oContYStd, oContLayerMean, oContLayerStd,
1116 ecalLayerEdepReadout_, recoilP, recoilPos);
1117
1118 buildBDTFeatureVector(result);
1119 ldmx::Ort::FloatArrays inputs({bdtFeatures_});
1120 float pred = rt_->run({featureListName_}, inputs, {"probabilities"})[0].at(1);
1121 // Other considerations were (nLinregTracks_ == 0) && (firstNearPhLayer_ >=
1122 // 6)
1123 // && (epAng_ > 3.0 && epAng_ < 900 || epSep_ > 10.0 && epSep_ < 900)
1124 bool passesTrackingVeto = (nStraightTracks_ < 3);
1125 result.setVetoResult(pred > bdtCutVal_ && passesTrackingVeto);
1126 result.setDiscValue(pred);
1127 ldmx_log(debug) << " The pred > bdtCutVal = " << (pred > bdtCutVal_);
1128
1129 // Persist in the event if the recoil ele is fiducial
1130 result.setFiducial(inside);
1131
1132 // If the event passes the veto, keep it. Otherwise,
1133 // drop the event.
1134 if (result.passesVeto()) {
1136 } else {
1138 }
1139
1140 event.add(collectionName_, result);
1141}
std::tuple< int, const ldmx::SimParticle * > getRecoil(const std::map< int, ldmx::SimParticle > &particleMap)
Find and return the sim particle associated with the recoil electron.
float distTwoLines(TVector3 v1, TVector3 v2, TVector3 w1, TVector3 w2)
Returns the distance between the lines v and w, with v defined to pass through the points (v1,...
void buildBDTFeatureVector(const ldmx::EcalVetoResult &result)
float distPtToLine(TVector3 h1, TVector3 p1, TVector3 p2)
Return the minimum distance between the point h1 and the line passing through points p1 and p2.
void fillHitMap(const std::vector< ldmx::EcalHit > &ecalRecHits, std::map< ldmx::EcalID, float > &cellMap_)
Function to load up empty vector of hit maps.
void setStorageHint(framework::StorageControl::Hint hint)
Mark the current event as having the given storage control hint from this module.
bool exists(const std::string &name, const std::string &passName="", bool unique=true) const
Check for the existence of an object or collection with the given name and pass name in the event.
Definition Event.cxx:92
EcalID getID(double x, double y, double z, bool fallible=false) const
Get a cell's ID number from its position.
double getCellMaxR() const
Get the center-to-corner radius of the cell hexagons.
void setVariables(int nReadoutHits, int deepestLayerHit, float summedDet, float summedTightIso, float maxCellDep, float showerRMS, float xStd, float yStd, float avgLayerHit, float stdLayerHit, float ecalBackEnergy, int nStraightTracks, int nLinregTracks, int firstNearPhLayer, int nNearPhHits, int photonTerritoryHits, float epAng, float epSep, float epDot, std::vector< float > electronContainmentEnergy, std::vector< float > photonContainmentEnergy, std::vector< float > outsideContainmentEnergy, std::vector< int > outsideContainmentNHits, std::vector< float > outsideContainmentXStd, std::vector< float > outsideContainmentYStd, std::vector< float > energySeg, std::vector< float > xMeanSeg, std::vector< float > yMeanSeg, std::vector< float > xStdSeg, std::vector< float > yStdSeg, std::vector< float > layerMeanSeg, std::vector< float > layerStdSeg, std::vector< std::vector< float > > eContEnergy, std::vector< std::vector< float > > eContXMean, std::vector< std::vector< float > > eContYMean, std::vector< std::vector< float > > gContEnergy, std::vector< std::vector< int > > gContNHits, std::vector< std::vector< float > > gContXMean, std::vector< std::vector< float > > gContYMean, std::vector< std::vector< float > > oContEnergy, std::vector< std::vector< int > > oContNHits, std::vector< std::vector< float > > oContXMean, std::vector< std::vector< float > > oContYMean, std::vector< std::vector< float > > oContXStd, std::vector< std::vector< float > > oContYStd, std::vector< std::vector< float > > oContLayerMean, std::vector< std::vector< float > > oContLayerStd, std::vector< float > EcalLayerEdepReadout, std::vector< double > recoilP, std::vector< float > recoilPos)
Set the sim particle and 'is findable' flag.
bool passesVeto() const
Checks if the event passes the Ecal veto.
Class representing a simulated particle.
Definition SimParticle.h:23
Implements detector ids for special simulation-derived hits like scoring planes.
Represents a simulated tracker hit in the simulation.
constexpr StorageControl::Hint hint_shouldKeep
storage control hint alias for backwards compatibility
constexpr StorageControl::Hint hint_shouldDrop
storage control hint alias for backwards compatibility

References buildBDTFeatureVector(), collectionName_, distPtToLine(), distTwoLines(), epAng_, epDot_, epSep_, framework::Event::exists(), fillHitMap(), firstNearPhLayer_, geometry_, ldmx::EcalGeometry::getCellMaxR(), ldmx::EcalGeometry::getID(), ldmx::EcalGeometry::getPosition(), ldmx::EcalGeometry::getZPosition(), framework::hint_shouldDrop, framework::hint_shouldKeep, nLinregTracks_, nNearPhHits_, nStraightTracks_, ldmx::EcalVetoResult::passesVeto(), photonTerritoryHits_, ldmx::SimSpecialID::plane(), framework::EventProcessor::setStorageHint(), and ldmx::EcalVetoResult::setVariables().

Member Data Documentation

◆ avgLayerHit_

double ecal::EcalVetoProcessor::avgLayerHit_ {0}
private

Definition at line 125 of file EcalVetoProcessor.h.

125{0};

◆ bdtCutVal_

double ecal::EcalVetoProcessor::bdtCutVal_ {0}
private

Definition at line 148 of file EcalVetoProcessor.h.

148{0};

◆ bdtFeatures_

std::vector<float> ecal::EcalVetoProcessor::bdtFeatures_
private

Definition at line 157 of file EcalVetoProcessor.h.

◆ bdtFileName_

std::string ecal::EcalVetoProcessor::bdtFileName_
private

Definition at line 155 of file EcalVetoProcessor.h.

◆ beamEnergyMeV_

double ecal::EcalVetoProcessor::beamEnergyMeV_ {0}
private

Definition at line 150 of file EcalVetoProcessor.h.

150{0};

◆ cellMap_

std::map<ldmx::EcalID, float> ecal::EcalVetoProcessor::cellMap_
private

Definition at line 106 of file EcalVetoProcessor.h.

◆ cellMapTightIso_

std::map<ldmx::EcalID, float> ecal::EcalVetoProcessor::cellMapTightIso_
private

Definition at line 107 of file EcalVetoProcessor.h.

◆ collectionName_

std::string ecal::EcalVetoProcessor::collectionName_ {"EcalVeto"}
private

Name of the collection which will containt the results.

Definition at line 164 of file EcalVetoProcessor.h.

164{"EcalVeto"};

Referenced by configure(), and produce().

◆ deepestLayerHit_

int ecal::EcalVetoProcessor::deepestLayerHit_ {0}
private

Definition at line 117 of file EcalVetoProcessor.h.

117{0};

◆ ecalBackEnergy_

double ecal::EcalVetoProcessor::ecalBackEnergy_ {0}
private

Definition at line 127 of file EcalVetoProcessor.h.

127{0};

◆ ecalLayerEdepRaw_

std::vector<float> ecal::EcalVetoProcessor::ecalLayerEdepRaw_
private

Definition at line 109 of file EcalVetoProcessor.h.

◆ ecalLayerEdepReadout_

std::vector<float> ecal::EcalVetoProcessor::ecalLayerEdepReadout_
private

Definition at line 110 of file EcalVetoProcessor.h.

◆ ecalLayerTime_

std::vector<float> ecal::EcalVetoProcessor::ecalLayerTime_
private

Definition at line 111 of file EcalVetoProcessor.h.

◆ epAng_

float ecal::EcalVetoProcessor::epAng_ {0}
private

Angular separation between the projected photon and electron trajectories (currently unused)

Definition at line 139 of file EcalVetoProcessor.h.

139{0};

Referenced by produce().

◆ epDot_

float ecal::EcalVetoProcessor::epDot_ {0}
private

Dot product of the photon and electron momenta unit vectors.

Definition at line 144 of file EcalVetoProcessor.h.

144{0};

Referenced by produce().

◆ epSep_

float ecal::EcalVetoProcessor::epSep_ {0}
private

Distance between the projected photon and electron trajectories at the ECal face.

Definition at line 142 of file EcalVetoProcessor.h.

142{0};

Referenced by produce().

◆ featureListName_

std::string ecal::EcalVetoProcessor::featureListName_
private

Definition at line 158 of file EcalVetoProcessor.h.

◆ firstNearPhLayer_

int ecal::EcalVetoProcessor::firstNearPhLayer_ {0}
private

First ECal layer in which a hit is found near the photon.

Definition at line 134 of file EcalVetoProcessor.h.

134{0};

Referenced by produce().

◆ geometry_

const ldmx::EcalGeometry* ecal::EcalVetoProcessor::geometry_
private

handle to current geometry (to share with member functions)

Definition at line 169 of file EcalVetoProcessor.h.

Referenced by produce().

◆ linreg_radius_

double ecal::EcalVetoProcessor::linreg_radius_ {0}
private

Definition at line 151 of file EcalVetoProcessor.h.

151{0};

◆ maxCellDep_

double ecal::EcalVetoProcessor::maxCellDep_ {0}
private

Definition at line 121 of file EcalVetoProcessor.h.

121{0};

◆ nEcalLayers_

int ecal::EcalVetoProcessor::nEcalLayers_ {0}
private

Definition at line 115 of file EcalVetoProcessor.h.

115{0};

◆ nLinregTracks_

int ecal::EcalVetoProcessor::nLinregTracks_ {0}
private

Number of "linreg" tracks found in the event.

Definition at line 132 of file EcalVetoProcessor.h.

132{0};

Referenced by produce().

◆ nNearPhHits_

int ecal::EcalVetoProcessor::nNearPhHits_ {0}
private

Number of hits near the photon trajectory.

Definition at line 136 of file EcalVetoProcessor.h.

136{0};

Referenced by produce().

◆ nReadoutHits_

int ecal::EcalVetoProcessor::nReadoutHits_ {0}
private

Definition at line 116 of file EcalVetoProcessor.h.

116{0};

◆ nStraightTracks_

int ecal::EcalVetoProcessor::nStraightTracks_ {0}
private

Number of "straight" tracks found in the event.

Definition at line 130 of file EcalVetoProcessor.h.

130{0};

Referenced by produce().

◆ photonTerritoryHits_

int ecal::EcalVetoProcessor::photonTerritoryHits_ {0}
private

Number of hits in the photon territory.

Definition at line 146 of file EcalVetoProcessor.h.

146{0};

Referenced by produce().

◆ rec_coll_name_

std::string ecal::EcalVetoProcessor::rec_coll_name_
private

Definition at line 161 of file EcalVetoProcessor.h.

◆ rec_pass_name_

std::string ecal::EcalVetoProcessor::rec_pass_name_
private

Definition at line 160 of file EcalVetoProcessor.h.

◆ roc_range_values_

std::vector<std::vector<double> > ecal::EcalVetoProcessor::roc_range_values_
private

Definition at line 113 of file EcalVetoProcessor.h.

◆ rocFileName_

std::string ecal::EcalVetoProcessor::rocFileName_
private

Definition at line 156 of file EcalVetoProcessor.h.

◆ rt_

std::unique_ptr<ldmx::Ort::ONNXRuntime> ecal::EcalVetoProcessor::rt_
private

Definition at line 166 of file EcalVetoProcessor.h.

◆ showerRMS_

double ecal::EcalVetoProcessor::showerRMS_ {0}
private

Definition at line 122 of file EcalVetoProcessor.h.

122{0};

◆ stdLayerHit_

double ecal::EcalVetoProcessor::stdLayerHit_ {0}
private

Definition at line 126 of file EcalVetoProcessor.h.

126{0};

◆ summedDet_

double ecal::EcalVetoProcessor::summedDet_ {0}
private

Definition at line 119 of file EcalVetoProcessor.h.

119{0};

◆ summedTightIso_

double ecal::EcalVetoProcessor::summedTightIso_ {0}
private

Definition at line 120 of file EcalVetoProcessor.h.

120{0};

◆ verbose_

bool ecal::EcalVetoProcessor::verbose_ {false}
private

Definition at line 153 of file EcalVetoProcessor.h.

153{false};

◆ xStd_

double ecal::EcalVetoProcessor::xStd_ {0}
private

Definition at line 123 of file EcalVetoProcessor.h.

123{0};

◆ yStd_

double ecal::EcalVetoProcessor::yStd_ {0}
private

Definition at line 124 of file EcalVetoProcessor.h.

124{0};

The documentation for this class was generated from the following files: