22#include "TMVA/Reader.h"
34 float largestWeight = 0;
36 for (
const auto *vtx : *vertices) {
38 const auto& trkLinks=vtx->trackParticleLinks();
39 const size_t nTrackLinks=trkLinks.size();
40 for (
unsigned i=0;i<nTrackLinks;++i) {
42 if( vtx->trackWeights()[i] > largestWeight ){
43 vtxWithLargestWeight = vtx;
50 return vtxWithLargestWeight;
90 int nVars,
const std::vector<std::vector<float>>& input_data,
91 const std::shared_ptr<Ort::Session>& sessionHandle,
92 std::vector<int64_t> input_node_dims,
93 std::vector<const char*> input_node_names,
94 std::vector<const char*> output_node_names)
const {
98 const std::vector<std::vector<float>>& input_tensor_values_ = input_data;
101 size_t input_tensor_size = nVars;
102 std::vector<float> input_tensor_values(nVars);
103 input_tensor_values = input_tensor_values_[0];
107 Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);
109 Ort::Value input_tensor = Ort::Value::CreateTensor<float>(
110 memory_info, input_tensor_values.data(), input_tensor_size,
111 input_node_dims.data(), input_node_dims.size());
114 assert(input_tensor.IsTensor());
118 for (
const auto*
name : input_node_names) {
121 for (
const auto*
name : output_node_names) {
125 for (
auto dim : input_node_dims) {
131 auto output_tensors =
132 sessionHandle->Run(Ort::RunOptions{
nullptr}, input_node_names.data(),
133 &input_tensor, input_node_names.size(),
134 output_node_names.data(), output_node_names.size());
137 assert(output_tensors.size() == 1 && output_tensors.front().IsTensor());
141 float* floatarr = output_tensors[0].GetTensorMutableData<
float>();
143 int arrSize =
sizeof(*floatarr) /
sizeof(floatarr[0]);
150 std::tuple<std::vector<int64_t>, std::vector<const char*>>
152 const std::shared_ptr<Ort::Session>& sessionHandle,
153 Ort::AllocatorWithDefaultOptions& allocator) {
155 std::vector<int64_t> input_node_dims;
156 size_t num_input_nodes = sessionHandle->GetInputCount();
157 std::vector<const char*> input_node_names(num_input_nodes);
160 for( std::size_t i = 0; i < num_input_nodes; i++ ) {
162 char* input_name = sessionHandle->GetInputNameAllocated(i, allocator).release();
164 input_node_names[i] = input_name;
167 Ort::TypeInfo type_info = sessionHandle->GetInputTypeInfo(i);
168 auto tensor_info = type_info.GetTensorTypeAndShapeInfo();
169 ONNXTensorElementDataType
type = tensor_info.GetElementType();
173 input_node_dims = tensor_info.GetShape();
174 ATH_MSG_DEBUG(
"Input "<<i<<
" : num_dims= "<<input_node_dims.size());
175 for (std::size_t j = 0; j < input_node_dims.size(); j++){
176 if(input_node_dims[j]<0){input_node_dims[j] =1;}
177 ATH_MSG_DEBUG(
"Input"<<i<<
" : dim "<<j<<
"= "<<input_node_dims[j]);
180 return std::make_tuple(input_node_dims, input_node_names);
184 std::tuple<std::vector<int64_t>, std::vector<const char*>>
186 const std::shared_ptr<Ort::Session>& sessionHandle,
187 Ort::AllocatorWithDefaultOptions& allocator) {
189 std::vector<int64_t> output_node_dims;
190 size_t num_output_nodes = sessionHandle->GetOutputCount();
191 std::vector<const char*> output_node_names(num_output_nodes);
194 for( std::size_t i = 0; i < num_output_nodes; i++ ) {
196 char* output_name = sessionHandle->GetOutputNameAllocated(i, allocator).release();
198 output_node_names[i] = output_name;
200 Ort::TypeInfo type_info = sessionHandle->GetOutputTypeInfo(i);
201 auto tensor_info = type_info.GetTensorTypeAndShapeInfo();
202 ONNXTensorElementDataType
type = tensor_info.GetElementType();
206 output_node_dims = tensor_info.GetShape();
207 ATH_MSG_DEBUG(
"Output "<<i<<
" : num_dims= "<<output_node_dims.size());
208 for (std::size_t j = 0; j < output_node_dims.size(); j++){
209 if(output_node_dims[j]<0){output_node_dims[j] =1;}
210 ATH_MSG_DEBUG(
"Output"<<i<<
" : dim "<<j<<
"= "<<output_node_dims[j]);
213 return std::make_tuple(output_node_dims, output_node_names);
217 std::tuple<std::shared_ptr<Ort::Session>, Ort::AllocatorWithDefaultOptions>
219 const std::string& modelFilePath) {
225 Ort::SessionOptions sessionOptions;
226 sessionOptions.SetIntraOpNumThreads( 1 );
227 sessionOptions.SetGraphOptimizationLevel( ORT_ENABLE_BASIC );
229 Ort::AllocatorWithDefaultOptions allocator;
231 std::shared_ptr<Ort::Session> sessionHandle = std::make_shared<Ort::Session>( env, modelFileName.c_str(), sessionOptions );
233 ATH_MSG_INFO(
"Created the ONNX Runtime session for model file = " << modelFileName);
234 return std::make_tuple(sessionHandle, allocator);
240 ATH_MSG_INFO(
"Initializing PhotonVertexSelectionTool...");
247 std::vector<std::string> var_names = {
248 "deltaZ := TMath::Min(abs(PrimaryVerticesAuxDyn.z-zCommon)/zCommonError,20)",
249 "deltaPhi := abs(deltaPhi(PrimaryVerticesAuxDyn.phi,egamma_phi))" ,
250 "logSumpt := log10(PrimaryVerticesAuxDyn.sumPt)" ,
251 "logSumpt2 := log10(PrimaryVerticesAuxDyn.sumPt2)"
253 auto *mva1 =
new TMVA::Reader(var_names,
"!Silent:Color");
255 m_mva1 = std::unique_ptr<TMVA::Reader>( mva1 );
257 auto mva2 = std::make_unique<TMVA::Reader>(var_names,
"!Silent:Color");
259 m_mva2 = std::unique_ptr<TMVA::Reader>( std::move(mva2) );
263 ATH_MSG_INFO(
"ONNX Runtime version: " << Ort::GetVersionString());
266 Ort::ThreadingOptions tp_options;
267 tp_options.SetGlobalIntraOpNumThreads(1);
268 tp_options.SetGlobalInterOpNumThreads(1);
271 m_env = std::make_unique< Ort::Env >(
274 "PhotonVertexSelectionTool");
300#ifndef XAOD_STANDALONE
305 return StatusCode::SUCCESS;
315 return StatusCode::SUCCESS;
322 const EventContext& ctx = Gaudi::Hive::currentContext();
361 deltaZ(*vertex) = std::abs((zCommon.first - vertex->z())/zCommon.second);
366 if(failType!=
nullptr)
368 return StatusCode::SUCCESS;
372 std::vector<std::pair<const xAOD::Vertex*, float>>
379 std::vector<std::pair<const xAOD::Vertex*, float> > vertexMLP;
382 if (
getVertexImp( egammas, vertex, ignoreConv, noDecorate, vertexMLP, vtxCase, failType ).isSuccess()) {
385 if(vtxCasePtr!=
nullptr)
386 *vtxCasePtr = vtxCase;
387 if(failTypePtr!=
nullptr)
388 *failTypePtr = failType;
396 bool ignoreConv)
const
398 std::vector<std::pair<const xAOD::Vertex*, float> > vertexMLP;
401 return getVertexImp( egammas, prime_vertex, ignoreConv,
false, vertexMLP, vtxcase, failType );
409 std::vector<std::pair<const xAOD::Vertex*, float>>& vertexMLP,
420 return StatusCode::FAILURE;
424 if (!ignoreConv && photons) {
426 if (prime_vertex !=
nullptr) {
429 vertexMLP.emplace_back(prime_vertex, 0.);
430 return StatusCode::SUCCESS;
435 ATH_MSG_VERBOSE(
"Returning hardest vertex. Fail detected (type="<< fail <<
")");
438 vertexMLP.emplace_back(prime_vertex, 10.);
439 return StatusCode::SUCCESS;
448 bool isConverted =
false;
452 if (!ignoreConv && photons) {
453 for (
const auto *
photon: *photons) {
457 return StatusCode::FAILURE;
469 TMVA::Reader *tmva_reader =
new TMVA::Reader();
473 tmva_reader =
m_mva1.get();
477 tmva_reader =
m_mva2.get();
491 std::vector<float> ONNXInputVector;
492 std::vector<std::vector<float>> onnx_input_tensor_values;
493 std::vector<float> TMVAInputVector;
495 float mlp = 0.0, mlp_max = -99999.0;
496 float doSkipByZSigmaScore = -9999.0;
498 float thresGoodVtxScore;
500 else{thresGoodVtxScore = mlp_max;}
506 onnx_input_tensor_values.clear();
509 float sumPt, sumPt2,
deltaPhi, deltaZ;
510 float log10_sumPt, log10_sumPt2;
512 sumPt = (sumPtA)(*vertex);
513 sumPt2 = (sumPt2A)(*vertex);
515 deltaZ = (deltaZA)(*vertex);
517 " sumPt2: " << sumPt2 <<
519 " deltaZ: " << deltaZ);
524 TMVAMethod =
"MLP method";
525 log10_sumPt =
static_cast<float>(log10(sumPt));
526 log10_sumPt2 =
static_cast<float>(log10(sumPt2));
527 TMVAInputVector = {deltaZ,
deltaPhi,log10_sumPt,log10_sumPt2};
533 ONNXInputVector = {sumPt2, sumPt,
deltaPhi, deltaZ};
534 for (
long unsigned int i = 0; i < ONNXInputVector.size(); i++) {
539 if (ONNXInputVector[i] != 0 && std::isinf(ONNXInputVector[i]) !=
true && std::isnan(ONNXInputVector[i]) !=
true){
540 ONNXInputVector[i] = log(std::abs(ONNXInputVector[i]));
543 ONNXInputVector[i] = log(std::abs(0.00000001));
546 onnx_input_tensor_values.push_back(ONNXInputVector);
551 mlp = tmva_reader->EvaluateMVA(TMVAInputVector, TMVAMethod);
566 " log(abs(sumPt2)): " << sumPt2 <<
568 " log(abs(deltaZ)): " << deltaZ);
569 ATH_MSG_VERBOSE(
"ONNX output, isConverted = " << isConverted <<
", mlp=" << mlp);
575 if ((isConverted && deltaZ > 15) || (!isConverted && deltaZ > 10)) {
576 mlp = doSkipByZSigmaScore;
581 vertexMLP.emplace_back(vertex, mlp);
586 prime_vertex = vertex;
593 if (mlp_max <= thresGoodVtxScore) {
594 ATH_MSG_DEBUG(
"No good vertex candidates from pointing, returning hardest vertex.");
601 ATH_MSG_VERBOSE(
"getVertex case "<< (
int)vtxCase <<
" exit code "<< (
int)fail);
602 return StatusCode::SUCCESS;
607 const std::pair<const xAOD::Vertex*, float> &b)
608 {
return a.second > b.second; }
613 if (photons ==
nullptr) {
614 ATH_MSG_WARNING(
"Passed nullptr photon container, returning nullptr vertex from getPrimaryVertexFromConv");
618 std::vector<const xAOD::Vertex*> vertices;
619 const xAOD::Vertex *conversionVertex =
nullptr, *primary =
nullptr;
621 size_t NumberOfTracks = 0;
627 for (
const auto *
photon: *photons) {
628 conversionVertex =
photon->vertex();
629 if (conversionVertex ==
nullptr)
continue;
632 for (
size_t i = 0; i < NumberOfTracks; ++i) {
635 if (gsfTp ==
nullptr)
continue;
640 if (tp ==
nullptr)
continue;
643 if (primary ==
nullptr)
continue;
647 if (std::find(vertices.begin(), vertices.end(), primary) == vertices.end()) {
648 vertices.push_back(primary);
655 if (!vertices.empty()) {
656 if (vertices.size() > 1)
657 ATH_MSG_WARNING(
"Photons associated to different vertices! Returning lead photon association.");
667 TLorentzVector v, v1;
675 cluster =
egamma->caloCluster();
676 if (cluster ==
nullptr) {
677 ATH_MSG_WARNING(
"No cluster associated to egamma, not adding to 4-vector.");
#define ATH_CHECK
Evaluate an expression and check for errors.
bool isValid() const
Test to see if the link can be dereferenced.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
std::enable_if_t< std::is_void_v< std::result_of_t< decltype(&T::renounce)(T)> > &&!std::is_base_of_v< SG::VarHandleKeyArray, T > &&std::is_base_of_v< Gaudi::DataHandle, T >, void > renounce(T &h)
bool msgLvl(const MSG::Level lvl) const
virtual double e() const
energy
Handle class for adding a decoration to an object.
bool isAvailable()
Test to see if this variable exists in the store, for the referenced object.
float phiBE(const unsigned layer) const
Get the phi in one layer of the EM Calo.
float etaBE(const unsigned layer) const
Get the eta in one layer of the EM Calo.
size_t nTrackParticles() const
Get the number of tracks associated with this vertex.
const TrackParticle * trackParticle(size_t i) const
Get the pointer to a given track that was used in vertex reco.
const std::vector< float > & trackWeights() const
Get all the track weights.
Select isolated Photons, Electrons and Muons.
const xAOD::Vertex * getVertexFromTrack(const xAOD::TrackParticle *track, const xAOD::VertexContainer *vertices)
std::string decorKeyFromKey(const std::string &key, const std::string &deflt)
Extract the decoration part of key.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
const xAOD::TrackParticle * getOriginalTrackParticleFromGSF(const xAOD::TrackParticle *trkPar)
Helper function for getting the "Original" Track Particle (i.e before GSF) via the GSF Track Particle...
const xAOD::Vertex * getHardestVertex(const xAOD::VertexContainer *vertices)
Return vertex with highest sum pT^2.
float getVertexSumPt(const xAOD::Vertex *vertex, int power=1, bool useAux=true)
Loop over track particles associated with vertex and return scalar sum of pT^power in GeV (from auxda...
TLorentzVector getVertexMomentum(const xAOD::Vertex *vertex, bool useAux=true, const std::string &derivationPrefix="")
Return vector sum of tracks associated with vertex (from auxdata if available and useAux = true).
bool passConvSelection(const xAOD::Photon *photon, float convPtCut=2e3)
Check if photon is converted, and tracks have Si hits and pass selection.
std::pair< float, float > getZCommonAndError(const xAOD::EventInfo *eventInfo, const xAOD::EgammaContainer *egammas, float convPtCut=2e3)
Return zCommon and zCommonError.
PhotonContainer_v1 PhotonContainer
Definition of the current "photon container version".
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
setSAddress setEtaMS setDirPhiMS setDirZMS setBarrelRadius setEndcapAlpha setEndcapRadius setInterceptInner setEtaMap setEtaBin setIsTgcFailure setDeltaPt deltaPhi
TrackParticle_v1 TrackParticle
Reference the current persistent version:
VertexContainer_v1 VertexContainer
Definition of the current "Vertex container version".
Vertex_v1 Vertex
Define the latest version of the vertex class.
Egamma_v1 Egamma
Definition of the current "egamma version".
EgammaContainer_v1 EgammaContainer
Definition of the current "egamma container version".