172{
173
176 ATH_MSG_WARNING(
"Model not loaded or Egamma pointer is null, returning cluster energy");
178 } else {
179 ATH_MSG_FATAL(
"Model not loaded or Egamma pointer is null, and useClusterIf0 is false, cannot proceed");
180 return 0.0f;
181 }
182 }
183
184
185 IegammaCellRecoveryTool::Info recoveryInfo;
186 bool recoverySucceeded = false;
189 ATH_MSG_WARNING(
"Cell Recovery Tool failed. Proceeding without recovered cells.");
190 } else {
191 recoverySucceeded = true;
192 }
193 }
194
195
197 std::unique_ptr<xAOD::Egamma> temp_eg;
198
200 auto array_layer_scales = std::array<double, 4>{1.0, 1.0, 1.0, 1.0};
201
203 ATH_MSG_DEBUG(
"Applying layer recalibration for GNN on data.");
204
205
206
209 temp_eg = std::make_unique<xAOD::Electron>();
210 temp_eg->makePrivateStore(*eg);
211 break;
212 }
215 temp_eg = std::make_unique<xAOD::Photon>();
216 temp_eg->makePrivateStore(*eg);
217 break;
218 }
219 default:
221 temp_eg = nullptr;
222 break;
223 }
224
225
226 if (temp_eg) {
229
230 clusterForTransformer = temp_eg->caloCluster();
231 }
232 }
233 else
234 {
235
237 ATH_MSG_DEBUG(
"Not using layer tool, Using raw layer energies as input to Transformer");
238 }
239
241 ATH_MSG_DEBUG(
"Applying extra layer scales for systematic studies, normally this is for MC events.");
243 ATH_MSG_WARNING(
"You are applying extra layer scales but the input is not MC! Are you sure this is intended?");
244 }
245
246 for (std::size_t i = 0;
i < 4; ++
i)
247 array_layer_scales[i] *= gei.
scaleEs[i];
248 }
249
250
251
252
253
257
258
259 std::vector<float> cells_E, cells_eta, cells_phi, cells_x, cells_y, cells_z;
260 std::vector<int> cells_layer;
261 std::vector<Identifier> included_cells;
262
263
264 double sum_cell_E_L0 = 0.0, sum_cell_E_L1 = 0.0, sum_cell_E_L2 = 0.0, sum_cell_E_L3 = 0.0, sum_cell_E_Gap = 0.0;
265
266
267 const CaloClusterCellLink* cellLinks = clus.
getCellLinks();
268 if (cellLinks) {
269 for (const CaloCell* cell : *cellLinks) {
270 if (!cell) continue;
271
272 int sampling =
cell->caloDDE()->getSampling();
273 double scale_factor = 1.0;
275
276 switch (sampling) {
277 case CaloCell_ID::PreSamplerB: case CaloCell_ID::PreSamplerE:
278 scale_factor = array_layer_scales[0];
layer_idx = 0;
break;
279 case CaloCell_ID::EMB1: case CaloCell_ID::EME1:
280 scale_factor = array_layer_scales[1];
layer_idx = 1;
break;
281 case CaloCell_ID::EMB2: case CaloCell_ID::EME2:
282 scale_factor = array_layer_scales[2];
layer_idx = 2;
283
285 included_cells.push_back(
cell->ID());
286 }
287 break;
288 case CaloCell_ID::EMB3: case CaloCell_ID::EME3:
289 scale_factor = array_layer_scales[3];
layer_idx = 3;
291 included_cells.push_back(
cell->ID());
292 }
293 break;
294 case CaloCell_ID::TileGap3:
295 scale_factor = 1.0;
layer_idx = 4;
break;
296 default: continue;
297 }
298
299 double final_E =
cell->e() * scale_factor;
300
301 cells_E.push_back(final_E);
302 cells_eta.push_back(
cell->eta());
303 cells_phi.push_back(
cell->phi());
304 cells_x.push_back(
cell->x());
305 cells_y.push_back(
cell->y());
306 cells_z.push_back(
cell->z());
307 cells_layer.push_back(layer_idx);
308
309
310 switch(layer_idx) {
311 case 0: sum_cell_E_L0 += final_E; break;
312 case 1: sum_cell_E_L1 += final_E; break;
313 case 2: sum_cell_E_L2 += final_E; break;
314 case 3: sum_cell_E_L3 += final_E; break;
315 case 4: sum_cell_E_Gap += final_E; break;
316 }
317 }
318 }
319
320
321
322 for (
const CaloCell* cell : recoveryInfo.
addedCells) {
323 if (!cell || !
cell->caloDDE())
continue;
324
325
326 if (std::find(included_cells.begin(), included_cells.end(),
cell->ID()) != included_cells.end()) {
327 ATH_MSG_DEBUG(
"Recovered cell " <<
cell->ID() <<
" already included in cluster. Skipping to avoid double counting.");
328 continue;
329 }
330 else {
332 }
333
334 int sampling =
cell->caloDDE()->getSampling();
335 double scale_factor = 1.0;
337
338 if (sampling == CaloCell_ID::EMB2 || sampling == CaloCell_ID::EME2) {
339 scale_factor = array_layer_scales[2];
layer_idx = 2;
340 } else if (sampling == CaloCell_ID::EMB3 || sampling == CaloCell_ID::EME3) {
341 scale_factor = array_layer_scales[3];
layer_idx = 3;
342 } else {
343
344 if (sampling == CaloCell_ID::PreSamplerB || sampling == CaloCell_ID::PreSamplerE) {
345 scale_factor = array_layer_scales[0];
layer_idx = 0;
346 } else if (sampling == CaloCell_ID::EMB1 || sampling == CaloCell_ID::EME1) {
347 scale_factor = array_layer_scales[1];
layer_idx = 1;
348 } else {
349 continue;
350 }
351 }
352
353 double final_E =
cell->e() * scale_factor;
354
355 cells_E.push_back(final_E);
356 cells_eta.push_back(
cell->eta());
357 cells_phi.push_back(
cell->phi());
358 cells_x.push_back(
cell->x());
359 cells_y.push_back(
cell->y());
360 cells_z.push_back(
cell->z());
361 cells_layer.push_back(layer_idx);
362
363 switch(layer_idx) {
364 case 0: sum_cell_E_L0 += final_E; break;
365 case 1: sum_cell_E_L1 += final_E; break;
366 case 2: sum_cell_E_L2 += final_E; break;
367 case 3: sum_cell_E_L3 += final_E; break;
368 case 4: sum_cell_E_Gap += final_E; break;
369 }
370 }
371
372
373 const size_t nCells = cells_E.size();
374 if (nCells == 0) return 0.0f;
375
376 double sum_cell_E_total = sum_cell_E_L0 + sum_cell_E_L1 + sum_cell_E_L2 + sum_cell_E_L3;
377 const double cluster_eta = clus.
eta();
378 const double cluster_phi = clus.
phi();
379
380 std::vector<float> cells_deta, cells_dphi, cells_eFrac;
381 cells_deta.reserve(nCells);
382 cells_dphi.reserve(nCells);
383 cells_eFrac.reserve(nCells);
384
385 for (
size_t i = 0;
i <
nCells; ++
i) {
386 float deta = cells_eta[
i] - cluster_eta;
387 float dphi = cells_phi[
i] - cluster_phi;
388 dphi = std::fmod(dphi + 3.0f *
M_PI, 2.0f *
M_PI) -
M_PI;
389
390 cells_deta.push_back(deta);
391 cells_dphi.push_back(dphi);
392
393 float eFrac_layer = 0.0f;
394 switch (cells_layer[i]) {
395 case 0: eFrac_layer = (sum_cell_E_L0 != 0) ? (cells_E[i] / sum_cell_E_L0) : 0.0f; break;
396 case 1: eFrac_layer = (sum_cell_E_L1 != 0) ? (cells_E[i] / sum_cell_E_L1) : 0.0f; break;
397 case 2: eFrac_layer = (sum_cell_E_L2 != 0) ? (cells_E[i] / sum_cell_E_L2) : 0.0f; break;
398 case 3: eFrac_layer = (sum_cell_E_L3 != 0) ? (cells_E[i] / sum_cell_E_L3) : 0.0f; break;
399 case 4: eFrac_layer = (sum_cell_E_Gap != 0) ? (cells_E[i] / sum_cell_E_Gap) : 0.0f; break;
400 }
401 cells_eFrac.push_back(eFrac_layer);
402 }
403
404
405 double ratio_L1_L2 = (sum_cell_E_L2 != 0) ? (sum_cell_E_L1 / sum_cell_E_L2) : 0.0;
406 double main_layers_sum = sum_cell_E_L1 + sum_cell_E_L2 + sum_cell_E_L3;
407 double ratio_L0_total = (main_layers_sum != 0) ? (sum_cell_E_L0 / main_layers_sum) : 0.0;
408 double ratio_Tile_total = (main_layers_sum != 0) ? (sum_cell_E_Gap / main_layers_sum) : 0.0;
409
410 std::map<std::string, FlavorTagInference::Inputs> gnn_input;
411
412
413 std::vector<float> cluster_feats = {
414 static_cast<float>(sum_cell_E_total),
415 static_cast<float>(sum_cell_E_L0),
416 static_cast<float>(sum_cell_E_L1),
417 static_cast<float>(sum_cell_E_L2),
418 static_cast<float>(sum_cell_E_L3),
419 static_cast<float>(sum_cell_E_Gap),
420 static_cast<float>(cluster_eta),
421 static_cast<float>(cluster_phi),
422 static_cast<float>(ratio_L1_L2),
423 static_cast<float>(ratio_L0_total),
424 static_cast<float>(ratio_Tile_total)
425 };
426
427
430 if (photon) {
431
432 float convR = 799.0f;
435 }
436
437
438 float convEtOverPt = 0.0f;
442 (raw_Es1 * array_layer_scales[1] + raw_Es2 * array_layer_scales[2] + raw_Es3 * array_layer_scales[3]) :
443 (raw_Es1 + raw_Es2 + raw_Es3));
445 convEtOverPt = std::max(0.0f, eacc / (std::cosh(cl_eta) * ptconv));
446 }
447 convEtOverPt = std::min(convEtOverPt, 2.0f);
448
449
450 float convPtRatio = 1.0f;
454 if ((pt1 + pt2) > 0.0f) {
455 convPtRatio = std::max(pt1, pt2) / (pt1 + pt2);
456 }
457 }
458
459
461
462 cluster_feats.push_back(convR);
463 cluster_feats.push_back(convEtOverPt);
464 cluster_feats.push_back(convPtRatio);
465 cluster_feats.push_back(conversionType);
466 } else {
467 cluster_feats.push_back(0.0f);
468 cluster_feats.push_back(0.0f);
469 cluster_feats.push_back(0.0f);
470 cluster_feats.push_back(0.0f);
471 }
472 }
473
474
476
477
478 std::vector<float> cell_feats_flat;
480 for (
size_t i = 0;
i <
nCells; ++
i) {
481 cell_feats_flat.push_back(cells_eFrac[i]);
482 cell_feats_flat.push_back(cells_deta[i]);
483 cell_feats_flat.push_back(cells_dphi[i]);
484 cell_feats_flat.push_back(cells_x[i]);
485 cell_feats_flat.push_back(cells_y[i]);
486 cell_feats_flat.push_back(cells_z[i]);
487 cell_feats_flat.push_back(static_cast<float>(cells_layer[i]));
488 }
490
491
492 auto [out_f, out_vc, out_vf] =
m_saltModel->runInference(gnn_input);
493
494 float el_gnn_score = 0.0f;
495 if (out_vf.empty() || out_vf.begin()->second.empty()) {
497 } else {
498 el_gnn_score = out_vf.begin()->second.front();
499 }
500
501
502 if (el_gnn_score == 0.0f) {
504 }
505
506 return el_gnn_score * static_cast<float>(sum_cell_E_total);
507}
#define ATH_MSG_WARNING(x)
const CaloClusterCellLink * getCellLinks() const
Get a pointer to the CaloClusterCellLink object (const version)
virtual double eta() const
The pseudorapidity ( ) of the particle.
virtual double e() const
The total energy of the particle.
float energyBE(const unsigned layer) const
Get the energy in one layer of the EM Calo.
virtual double phi() const
The azimuthal angle ( ) of the particle.
const xAOD::CaloCluster * caloCluster(size_t index=0) const
Pointer to the xAOD::CaloCluster/s that define the electron candidate.
std::pair< std::vector< float >, std::vector< int64_t > > Inputs
float compute_ptconv(const xAOD::Photon *ph)
This ptconv is the old one used by MVACalib.
float compute_pt2conv(const xAOD::Photon *ph)
float compute_cl_eta(const xAOD::CaloCluster &cluster)
float compute_pt1conv(const xAOD::Photon *ph)
ConversionType conversionType(const bool hasTrk1, const bool hasTrk2, const std::uint8_t nSiHits1, const std::uint8_t nSiHits2)
return the photon conversion type (see EgammaEnums)
std::size_t numberOfSiTracks(const xAOD::Photon *eg)
return the number of Si tracks in the conversion
float conversionRadius(const xAOD::Vertex *vx)
return the conversion radius or 9999.
EventInfo_v1 EventInfo
Definition of the latest event info version.
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
Photon_v1 Photon
Definition of the current "egamma version".
setRawEt setRawPhi nCells
std::array< float, 4 > scaleEs
const xAOD::EventInfo * eventInfo