File indexing completed on 2024-04-06 12:27:47
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include "FWCore/Framework/interface/stream/EDProducer.h"
0011 #include "RecoTauTag/RecoTau/interface/DeepTauIdBase.h"
0012 #include "FWCore/Utilities/interface/isFinite.h"
0013
0014 namespace deep_tau {
0015 class DeepTauCache {
0016 public:
0017 using GraphPtr = std::shared_ptr<tensorflow::GraphDef>;
0018
0019 DeepTauCache(const std::map<std::string, std::string>& graph_names, bool mem_mapped) {
0020 for (const auto& graph_entry : graph_names) {
0021
0022 tensorflow::Options options{tensorflow::Backend::cpu};
0023
0024 const std::string& entry_name = graph_entry.first;
0025 const std::string& graph_file = graph_entry.second;
0026 if (mem_mapped) {
0027 memmappedEnv_[entry_name] = std::make_unique<tensorflow::MemmappedEnv>(tensorflow::Env::Default());
0028 const tensorflow::Status mmap_status = memmappedEnv_.at(entry_name)->InitializeFromFile(graph_file);
0029 if (!mmap_status.ok()) {
0030 throw cms::Exception("DeepTauCache: unable to initalize memmapped environment for ")
0031 << graph_file << ". \n"
0032 << mmap_status.ToString();
0033 }
0034
0035 graphs_[entry_name] = std::make_unique<tensorflow::GraphDef>();
0036 const tensorflow::Status load_graph_status =
0037 ReadBinaryProto(memmappedEnv_.at(entry_name).get(),
0038 tensorflow::MemmappedFileSystem::kMemmappedPackageDefaultGraphDef,
0039 graphs_.at(entry_name).get());
0040 if (!load_graph_status.ok())
0041 throw cms::Exception("DeepTauCache: unable to load graph from ") << graph_file << ". \n"
0042 << load_graph_status.ToString();
0043
0044 options.getSessionOptions().config.mutable_graph_options()->mutable_optimizer_options()->set_opt_level(
0045 ::tensorflow::OptimizerOptions::L0);
0046 options.getSessionOptions().env = memmappedEnv_.at(entry_name).get();
0047
0048 sessions_[entry_name] = tensorflow::createSession(graphs_.at(entry_name).get(), options);
0049
0050 } else {
0051 graphs_[entry_name].reset(tensorflow::loadGraphDef(graph_file));
0052 sessions_[entry_name] = tensorflow::createSession(graphs_.at(entry_name).get(), options);
0053 }
0054 }
0055 };
0056 ~DeepTauCache() {
0057 for (auto& session_entry : sessions_)
0058 tensorflow::closeSession(session_entry.second);
0059 }
0060
0061
0062
0063 tensorflow::Session& getSession(const std::string& name = "") const { return *sessions_.at(name); }
0064 const tensorflow::GraphDef& getGraph(const std::string& name = "") const { return *graphs_.at(name); }
0065
0066 private:
0067 std::map<std::string, GraphPtr> graphs_;
0068 std::map<std::string, tensorflow::Session*> sessions_;
0069 std::map<std::string, std::unique_ptr<tensorflow::MemmappedEnv>> memmappedEnv_;
0070 };
0071 }
0072
0073 class DeepTauIdWrapper : public edm::stream::EDProducer<edm::GlobalCache<deep_tau::DeepTauCache>> {
0074 public:
0075 DeepTauIdWrapper(const edm::ParameterSet& cfg) {}
0076 };
0077
0078 class DeepTauId : public DeepTauIdBase<DeepTauIdWrapper> {
0079 public:
0080 static void fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0081 edm::ParameterSetDescription desc;
0082 fillDescriptionsHelper(desc);
0083 desc.add<std::vector<std::string>>("graph_file",
0084 {"RecoTauTag/TrainingFiles/data/DeepTauId/deepTau_2017v2p6_e6.pb"});
0085 descriptions.add("DeepTau", desc);
0086 }
0087
0088 public:
0089 explicit DeepTauId(const edm::ParameterSet& cfg, const deep_tau::DeepTauCache* cache)
0090 : DeepTauIdBase<DeepTauIdWrapper>(cfg), cache_(cache) {
0091 if (version_ == 2) {
0092 using namespace dnn_inputs_v2;
0093 if (sub_version_ == 1) {
0094 tauBlockTensor_ = std::make_unique<tensorflow::Tensor>(
0095 tensorflow::DT_FLOAT, tensorflow::TensorShape{1, TauBlockInputs::NumberOfInputs});
0096 } else if (sub_version_ == 5) {
0097 tauBlockTensor_ = std::make_unique<tensorflow::Tensor>(
0098 tensorflow::DT_FLOAT,
0099 tensorflow::TensorShape{1,
0100 static_cast<int>(TauBlockInputs::NumberOfInputs) -
0101 static_cast<int>(TauBlockInputs::varsToDrop.size())});
0102 }
0103
0104 for (size_t n = 0; n < 2; ++n) {
0105 const bool is_inner = n == 0;
0106 const auto n_cells = is_inner ? number_of_inner_cell : number_of_outer_cell;
0107 eGammaTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
0108 tensorflow::DT_FLOAT, tensorflow::TensorShape{1, 1, 1, EgammaBlockInputs::NumberOfInputs});
0109 muonTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
0110 tensorflow::DT_FLOAT, tensorflow::TensorShape{1, 1, 1, MuonBlockInputs::NumberOfInputs});
0111 hadronsTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
0112 tensorflow::DT_FLOAT, tensorflow::TensorShape{1, 1, 1, HadronBlockInputs::NumberOfInputs});
0113 convTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
0114 tensorflow::DT_FLOAT, tensorflow::TensorShape{1, n_cells, n_cells, number_of_conv_features});
0115 zeroOutputTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
0116 tensorflow::DT_FLOAT, tensorflow::TensorShape{1, 1, 1, number_of_conv_features});
0117
0118 eGammaTensor_[is_inner]->flat<float>().setZero();
0119 muonTensor_[is_inner]->flat<float>().setZero();
0120 hadronsTensor_[is_inner]->flat<float>().setZero();
0121
0122 setCellConvFeatures(*zeroOutputTensor_[is_inner], getPartialPredictions(is_inner), 0, 0, 0);
0123 }
0124 }
0125 }
0126
0127 void produce(edm::Event& event, const edm::EventSetup& es) override {
0128 edm::Handle<TauCollection> taus;
0129 event.getByToken(tausToken_, taus);
0130
0131
0132 if (taus->empty()) {
0133 const tensorflow::Tensor emptyPrediction(tensorflow::DT_FLOAT, {0, deep_tau::NumberOfOutputs});
0134 createOutputs(event, emptyPrediction, taus);
0135 return;
0136 }
0137
0138 loadPrediscriminants(event, taus);
0139
0140 const tensorflow::Tensor& pred = getPredictions(event, taus);
0141 createOutputs(event, pred, taus);
0142 }
0143
0144 static std::unique_ptr<deep_tau::DeepTauCache> initializeGlobalCache(const edm::ParameterSet& cfg) {
0145 const auto graph_name_vector = cfg.getParameter<std::vector<std::string>>("graph_file");
0146 std::map<std::string, std::string> graph_names;
0147 for (const auto& entry : graph_name_vector) {
0148 const size_t sep_pos = entry.find(':');
0149 std::string entry_name, graph_file;
0150 if (sep_pos != std::string::npos) {
0151 entry_name = entry.substr(0, sep_pos);
0152 graph_file = entry.substr(sep_pos + 1);
0153 } else {
0154 entry_name = "";
0155 graph_file = entry;
0156 }
0157 graph_file = edm::FileInPath(graph_file).fullPath();
0158 if (graph_names.count(entry_name))
0159 throw cms::Exception("DeepTauCache") << "Duplicated graph entries";
0160 graph_names[entry_name] = graph_file;
0161 }
0162 bool mem_mapped = cfg.getParameter<bool>("mem_mapped");
0163 return std::make_unique<deep_tau::DeepTauCache>(graph_names, mem_mapped);
0164 }
0165
0166 static void globalEndJob(const deep_tau::DeepTauCache* cache_) {}
0167
0168 private:
0169 inline void checkInputs(const tensorflow::Tensor& inputs,
0170 const std::string& block_name,
0171 int n_inputs,
0172 const CellGrid* grid = nullptr) const {
0173 if (debug_level >= 1) {
0174 std::cout << "<checkInputs>: block_name = " << block_name << std::endl;
0175 if (block_name == "input_tau") {
0176 for (int input_index = 0; input_index < n_inputs; ++input_index) {
0177 float input = inputs.matrix<float>()(0, input_index);
0178 if (edm::isNotFinite(input)) {
0179 throw cms::Exception("DeepTauId")
0180 << "in the " << block_name
0181 << ", input is not finite, i.e. infinite or NaN, for input_index = " << input_index;
0182 }
0183 if (debug_level >= 2) {
0184 std::cout << block_name << "[var = " << input_index << "] = " << std::setprecision(5) << std::fixed << input
0185 << std::endl;
0186 }
0187 }
0188 } else {
0189 assert(grid);
0190 int n_eta, n_phi;
0191 if (block_name.find("input_inner") != std::string::npos) {
0192 n_eta = 5;
0193 n_phi = 5;
0194 } else if (block_name.find("input_outer") != std::string::npos) {
0195 n_eta = 10;
0196 n_phi = 10;
0197 } else
0198 assert(0);
0199 int eta_phi_index = 0;
0200 for (int eta = -n_eta; eta <= n_eta; ++eta) {
0201 for (int phi = -n_phi; phi <= n_phi; ++phi) {
0202 const CellIndex cell_index{eta, phi};
0203 const auto cell_iter = grid->find(cell_index);
0204 if (cell_iter != grid->end()) {
0205 for (int input_index = 0; input_index < n_inputs; ++input_index) {
0206 float input = inputs.tensor<float, 4>()(eta_phi_index, 0, 0, input_index);
0207 if (edm::isNotFinite(input)) {
0208 throw cms::Exception("DeepTauId")
0209 << "in the " << block_name << ", input is not finite, i.e. infinite or NaN, for eta = " << eta
0210 << ", phi = " << phi << ", input_index = " << input_index;
0211 }
0212 if (debug_level >= 2) {
0213 std::cout << block_name << "[eta = " << eta << "][phi = " << phi << "][var = " << input_index
0214 << "] = " << std::setprecision(5) << std::fixed << input << std::endl;
0215 }
0216 }
0217 eta_phi_index += 1;
0218 }
0219 }
0220 }
0221 }
0222 }
0223 }
0224
0225 inline void saveInputs(const tensorflow::Tensor& inputs,
0226 const std::string& block_name,
0227 int n_inputs,
0228 const CellGrid* grid = nullptr) {
0229 if (debug_level >= 1) {
0230 std::cout << "<saveInputs>: block_name = " << block_name << std::endl;
0231 }
0232 if (!is_first_block_)
0233 (*json_file_) << ", ";
0234 (*json_file_) << "\"" << block_name << "\": [";
0235 if (block_name == "input_tau") {
0236 for (int input_index = 0; input_index < n_inputs; ++input_index) {
0237 float input = inputs.matrix<float>()(0, input_index);
0238 if (input_index != 0)
0239 (*json_file_) << ", ";
0240 (*json_file_) << input;
0241 }
0242 } else {
0243 assert(grid);
0244 int n_eta, n_phi;
0245 if (block_name.find("input_inner") != std::string::npos) {
0246 n_eta = 5;
0247 n_phi = 5;
0248 } else if (block_name.find("input_outer") != std::string::npos) {
0249 n_eta = 10;
0250 n_phi = 10;
0251 } else
0252 assert(0);
0253 int eta_phi_index = 0;
0254 for (int eta = -n_eta; eta <= n_eta; ++eta) {
0255 if (eta != -n_eta)
0256 (*json_file_) << ", ";
0257 (*json_file_) << "[";
0258 for (int phi = -n_phi; phi <= n_phi; ++phi) {
0259 if (phi != -n_phi)
0260 (*json_file_) << ", ";
0261 (*json_file_) << "[";
0262 const CellIndex cell_index{eta, phi};
0263 const auto cell_iter = grid->find(cell_index);
0264 for (int input_index = 0; input_index < n_inputs; ++input_index) {
0265 float input = 0.;
0266 if (cell_iter != grid->end()) {
0267 input = inputs.tensor<float, 4>()(eta_phi_index, 0, 0, input_index);
0268 }
0269 if (input_index != 0)
0270 (*json_file_) << ", ";
0271 (*json_file_) << input;
0272 }
0273 if (cell_iter != grid->end()) {
0274 eta_phi_index += 1;
0275 }
0276 (*json_file_) << "]";
0277 }
0278 (*json_file_) << "]";
0279 }
0280 }
0281 (*json_file_) << "]";
0282 is_first_block_ = false;
0283 }
0284
0285 private:
0286 tensorflow::Tensor getPredictions(edm::Event& event, edm::Handle<TauCollection> taus) {
0287
0288 const std::vector<pat::Electron> electron_collection_default;
0289 const std::vector<pat::Muon> muon_collection_default;
0290 const reco::TauDiscriminatorContainer basicTauDiscriminators_default;
0291 const reco::TauDiscriminatorContainer basicTauDiscriminatorsdR03_default;
0292 const edm::AssociationVector<reco::PFTauRefProd, std::vector<reco::PFTauTransverseImpactParameterRef>>
0293 pfTauTransverseImpactParameters_default;
0294
0295 const std::vector<pat::Electron>* electron_collection;
0296 const std::vector<pat::Muon>* muon_collection;
0297 const reco::TauDiscriminatorContainer* basicTauDiscriminators;
0298 const reco::TauDiscriminatorContainer* basicTauDiscriminatorsdR03;
0299 const edm::AssociationVector<reco::PFTauRefProd, std::vector<reco::PFTauTransverseImpactParameterRef>>*
0300 pfTauTransverseImpactParameters;
0301
0302 if (!is_online_) {
0303 electron_collection = &event.get(electrons_token_);
0304 muon_collection = &event.get(muons_token_);
0305 pfTauTransverseImpactParameters = &pfTauTransverseImpactParameters_default;
0306 basicTauDiscriminators = &basicTauDiscriminators_default;
0307 basicTauDiscriminatorsdR03 = &basicTauDiscriminatorsdR03_default;
0308 } else {
0309 electron_collection = &electron_collection_default;
0310 muon_collection = &muon_collection_default;
0311 pfTauTransverseImpactParameters = &event.get(pfTauTransverseImpactParameters_token_);
0312 basicTauDiscriminators = &event.get(basicTauDiscriminators_inputToken_);
0313 basicTauDiscriminatorsdR03 = &event.get(basicTauDiscriminatorsdR03_inputToken_);
0314
0315
0316 if (!discrIndicesMapped_) {
0317 basicDiscrIndexMap_ =
0318 matchDiscriminatorIndices(event, basicTauDiscriminators_inputToken_, requiredBasicDiscriminators_);
0319 basicDiscrdR03IndexMap_ =
0320 matchDiscriminatorIndices(event, basicTauDiscriminatorsdR03_inputToken_, requiredBasicDiscriminatorsdR03_);
0321 discrIndicesMapped_ = true;
0322 }
0323 }
0324
0325 TauFunc tauIDs = {basicTauDiscriminators,
0326 basicTauDiscriminatorsdR03,
0327 pfTauTransverseImpactParameters,
0328 basicDiscrIndexMap_,
0329 basicDiscrdR03IndexMap_};
0330
0331 edm::Handle<edm::View<reco::Candidate>> pfCands;
0332 event.getByToken(pfcandToken_, pfCands);
0333
0334 edm::Handle<reco::VertexCollection> vertices;
0335 event.getByToken(vtxToken_, vertices);
0336
0337 edm::Handle<double> rho;
0338 event.getByToken(rho_token_, rho);
0339
0340 auto const& eventnr = event.id().event();
0341
0342 tensorflow::Tensor predictions(tensorflow::DT_FLOAT, {static_cast<int>(taus->size()), deep_tau::NumberOfOutputs});
0343
0344 for (size_t tau_index = 0; tau_index < taus->size(); ++tau_index) {
0345 const edm::RefToBase<reco::BaseTau> tauRef = taus->refAt(tau_index);
0346
0347 std::vector<tensorflow::Tensor> pred_vector;
0348
0349 bool passesPrediscriminants;
0350 if (is_online_) {
0351 passesPrediscriminants = tauIDs.passPrediscriminants<std::vector<TauDiscInfo<reco::PFTauDiscriminator>>>(
0352 recoPrediscriminants_, andPrediscriminants_, tauRef);
0353 } else {
0354 passesPrediscriminants = tauIDs.passPrediscriminants<std::vector<TauDiscInfo<pat::PATTauDiscriminator>>>(
0355 patPrediscriminants_, andPrediscriminants_, tauRef);
0356 }
0357
0358 if (passesPrediscriminants) {
0359 if (version_ == 2) {
0360 if (is_online_) {
0361 getPredictionsV2<reco::PFCandidate, reco::PFTau>(taus->at(tau_index),
0362 tau_index,
0363 tauRef,
0364 electron_collection,
0365 muon_collection,
0366 *pfCands,
0367 vertices->at(0),
0368 *rho,
0369 eventnr,
0370 pred_vector,
0371 tauIDs);
0372 } else
0373 getPredictionsV2<pat::PackedCandidate, pat::Tau>(taus->at(tau_index),
0374 tau_index,
0375 tauRef,
0376 electron_collection,
0377 muon_collection,
0378 *pfCands,
0379 vertices->at(0),
0380 *rho,
0381 eventnr,
0382 pred_vector,
0383 tauIDs);
0384 } else {
0385 throw cms::Exception("DeepTauId") << "version " << version_ << " is not supported.";
0386 }
0387
0388 for (int k = 0; k < deep_tau::NumberOfOutputs; ++k) {
0389 const float pred = pred_vector[0].flat<float>()(k);
0390 if (!(pred >= 0 && pred <= 1))
0391 throw cms::Exception("DeepTauId")
0392 << "invalid prediction = " << pred << " for tau_index = " << tau_index << ", pred_index = " << k;
0393 predictions.matrix<float>()(tau_index, k) = pred;
0394 }
0395 } else {
0396
0397
0398
0399
0400
0401 for (int k = 0; k < deep_tau::NumberOfOutputs; ++k) {
0402 predictions.matrix<float>()(tau_index, k) = (k == 2) ? -1.f : 2.f;
0403 }
0404 }
0405 }
0406 return predictions;
0407 }
0408
0409 template <typename CandidateCastType, typename TauCastType>
0410 void getPredictionsV2(TauCollection::const_reference& tau,
0411 const size_t tau_index,
0412 const edm::RefToBase<reco::BaseTau> tau_ref,
0413 const std::vector<pat::Electron>* electrons,
0414 const std::vector<pat::Muon>* muons,
0415 const edm::View<reco::Candidate>& pfCands,
0416 const reco::Vertex& pv,
0417 double rho,
0418 const edm::EventNumber_t& eventnr,
0419 std::vector<tensorflow::Tensor>& pred_vector,
0420 TauFunc tau_funcs) {
0421 using namespace dnn_inputs_v2;
0422 if (debug_level >= 2) {
0423 std::cout << "<DeepTauId::getPredictionsV2 (moduleLabel = " << moduleDescription().moduleLabel()
0424 << ")>:" << std::endl;
0425 std::cout << " tau: pT = " << tau.pt() << ", eta = " << tau.eta() << ", phi = " << tau.phi()
0426 << ", eventnr = " << eventnr << std::endl;
0427 }
0428 CellGrid inner_grid(number_of_inner_cell, number_of_inner_cell, 0.02, 0.02, disable_CellIndex_workaround_);
0429 CellGrid outer_grid(number_of_outer_cell, number_of_outer_cell, 0.05, 0.05, disable_CellIndex_workaround_);
0430 fillGrids(dynamic_cast<const TauCastType&>(tau), *electrons, inner_grid, outer_grid);
0431 fillGrids(dynamic_cast<const TauCastType&>(tau), *muons, inner_grid, outer_grid);
0432 fillGrids(dynamic_cast<const TauCastType&>(tau), pfCands, inner_grid, outer_grid);
0433
0434 tauBlockTensor_->flat<float>().setZero();
0435 createTauBlockInputs<CandidateCastType>(
0436 dynamic_cast<const TauCastType&>(tau), tau_index, tau_ref, pv, rho, tau_funcs, *tauBlockTensor_);
0437 checkInputs(*tauBlockTensor_, "input_tau", static_cast<int>(tauBlockTensor_->shape().dim_size(1)));
0438 createConvFeatures<CandidateCastType>(dynamic_cast<const TauCastType&>(tau),
0439 tau_index,
0440 tau_ref,
0441 pv,
0442 rho,
0443 electrons,
0444 muons,
0445 pfCands,
0446 inner_grid,
0447 tau_funcs,
0448 true);
0449 checkInputs(*eGammaTensor_[true], "input_inner_egamma", EgammaBlockInputs::NumberOfInputs, &inner_grid);
0450 checkInputs(*muonTensor_[true], "input_inner_muon", MuonBlockInputs::NumberOfInputs, &inner_grid);
0451 checkInputs(*hadronsTensor_[true], "input_inner_hadrons", HadronBlockInputs::NumberOfInputs, &inner_grid);
0452 createConvFeatures<CandidateCastType>(dynamic_cast<const TauCastType&>(tau),
0453 tau_index,
0454 tau_ref,
0455 pv,
0456 rho,
0457 electrons,
0458 muons,
0459 pfCands,
0460 outer_grid,
0461 tau_funcs,
0462 false);
0463 checkInputs(*eGammaTensor_[false], "input_outer_egamma", EgammaBlockInputs::NumberOfInputs, &outer_grid);
0464 checkInputs(*muonTensor_[false], "input_outer_muon", MuonBlockInputs::NumberOfInputs, &outer_grid);
0465 checkInputs(*hadronsTensor_[false], "input_outer_hadrons", HadronBlockInputs::NumberOfInputs, &outer_grid);
0466
0467 if (save_inputs_) {
0468 std::string json_file_name = "DeepTauId_" + std::to_string(eventnr) + "_" + std::to_string(tau_index) + ".json";
0469 json_file_ = new std::ofstream(json_file_name.data());
0470 is_first_block_ = true;
0471 (*json_file_) << "{";
0472 saveInputs(*tauBlockTensor_, "input_tau", static_cast<int>(tauBlockTensor_->shape().dim_size(1)));
0473 saveInputs(*eGammaTensor_[true], "input_inner_egamma", EgammaBlockInputs::NumberOfInputs, &inner_grid);
0474 saveInputs(*muonTensor_[true], "input_inner_muon", MuonBlockInputs::NumberOfInputs, &inner_grid);
0475 saveInputs(*hadronsTensor_[true], "input_inner_hadrons", HadronBlockInputs::NumberOfInputs, &inner_grid);
0476 saveInputs(*eGammaTensor_[false], "input_outer_egamma", EgammaBlockInputs::NumberOfInputs, &outer_grid);
0477 saveInputs(*muonTensor_[false], "input_outer_muon", MuonBlockInputs::NumberOfInputs, &outer_grid);
0478 saveInputs(*hadronsTensor_[false], "input_outer_hadrons", HadronBlockInputs::NumberOfInputs, &outer_grid);
0479 (*json_file_) << "}";
0480 delete json_file_;
0481 ++file_counter_;
0482 }
0483
0484 tensorflow::run(&(cache_->getSession("core")),
0485 {{"input_tau", *tauBlockTensor_},
0486 {"input_inner", *convTensor_.at(true)},
0487 {"input_outer", *convTensor_.at(false)}},
0488 {"main_output/Softmax"},
0489 &pred_vector);
0490 if (debug_level >= 1) {
0491 std::cout << "output = { ";
0492 for (int idx = 0; idx < deep_tau::NumberOfOutputs; ++idx) {
0493 if (idx > 0)
0494 std::cout << ", ";
0495 std::string label;
0496 if (idx == 0)
0497 label = "e";
0498 else if (idx == 1)
0499 label = "mu";
0500 else if (idx == 2)
0501 label = "tau";
0502 else if (idx == 3)
0503 label = "jet";
0504 else
0505 assert(0);
0506 std::cout << label << " = " << pred_vector[0].flat<float>()(idx);
0507 }
0508 std::cout << " }" << std::endl;
0509 }
0510 }
0511
0512 tensorflow::Tensor getPartialPredictions(bool is_inner) {
0513 std::vector<tensorflow::Tensor> pred_vector;
0514 if (is_inner) {
0515 tensorflow::run(&(cache_->getSession("inner")),
0516 {
0517 {"input_inner_egamma", *eGammaTensor_.at(is_inner)},
0518 {"input_inner_muon", *muonTensor_.at(is_inner)},
0519 {"input_inner_hadrons", *hadronsTensor_.at(is_inner)},
0520 },
0521 {"inner_all_dropout_4/Identity"},
0522 &pred_vector);
0523 } else {
0524 tensorflow::run(&(cache_->getSession("outer")),
0525 {
0526 {"input_outer_egamma", *eGammaTensor_.at(is_inner)},
0527 {"input_outer_muon", *muonTensor_.at(is_inner)},
0528 {"input_outer_hadrons", *hadronsTensor_.at(is_inner)},
0529 },
0530 {"outer_all_dropout_4/Identity"},
0531 &pred_vector);
0532 }
0533
0534 return pred_vector.at(0);
0535 }
0536
0537 template <typename CandidateCastType, typename TauCastType>
0538 void createConvFeatures(const TauCastType& tau,
0539 const size_t tau_index,
0540 const edm::RefToBase<reco::BaseTau> tau_ref,
0541 const reco::Vertex& pv,
0542 double rho,
0543 const std::vector<pat::Electron>* electrons,
0544 const std::vector<pat::Muon>* muons,
0545 const edm::View<reco::Candidate>& pfCands,
0546 const CellGrid& grid,
0547 TauFunc tau_funcs,
0548 bool is_inner) {
0549 if (debug_level >= 2) {
0550 std::cout << "<DeepTauId::createConvFeatures (is_inner = " << is_inner << ")>:" << std::endl;
0551 std::cout << "number of valid cells = " << grid.num_valid_cells() << std::endl;
0552 }
0553
0554 const size_t n_valid_cells = grid.num_valid_cells();
0555 tensorflow::Tensor predTensor;
0556 tensorflow::Tensor& convTensor = *convTensor_.at(is_inner);
0557
0558
0559
0560 if (n_valid_cells > 0) {
0561 eGammaTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
0562 tensorflow::DT_FLOAT,
0563 tensorflow::TensorShape{
0564 (long long int)grid.num_valid_cells(), 1, 1, dnn_inputs_v2::EgammaBlockInputs::NumberOfInputs});
0565 muonTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
0566 tensorflow::DT_FLOAT,
0567 tensorflow::TensorShape{
0568 (long long int)grid.num_valid_cells(), 1, 1, dnn_inputs_v2::MuonBlockInputs::NumberOfInputs});
0569 hadronsTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
0570 tensorflow::DT_FLOAT,
0571 tensorflow::TensorShape{
0572 (long long int)grid.num_valid_cells(), 1, 1, dnn_inputs_v2::HadronBlockInputs::NumberOfInputs});
0573
0574 eGammaTensor_[is_inner]->flat<float>().setZero();
0575 muonTensor_[is_inner]->flat<float>().setZero();
0576 hadronsTensor_[is_inner]->flat<float>().setZero();
0577
0578 unsigned idx = 0;
0579 for (int eta = -grid.maxEtaIndex(); eta <= grid.maxEtaIndex(); ++eta) {
0580 for (int phi = -grid.maxPhiIndex(); phi <= grid.maxPhiIndex(); ++phi) {
0581 if (debug_level >= 2) {
0582 std::cout << "processing ( eta = " << eta << ", phi = " << phi << " )" << std::endl;
0583 }
0584 const CellIndex cell_index{eta, phi};
0585 const auto cell_iter = grid.find(cell_index);
0586 if (cell_iter != grid.end()) {
0587 if (debug_level >= 2) {
0588 std::cout << " creating inputs for ( eta = " << eta << ", phi = " << phi << " ): idx = " << idx
0589 << std::endl;
0590 }
0591 const Cell& cell = cell_iter->second;
0592 createEgammaBlockInputs<CandidateCastType>(idx,
0593 tau,
0594 tau_index,
0595 tau_ref,
0596 pv,
0597 rho,
0598 electrons,
0599 pfCands,
0600 cell,
0601 tau_funcs,
0602 is_inner,
0603 *eGammaTensor_[is_inner]);
0604 createMuonBlockInputs<CandidateCastType>(
0605 idx, tau, tau_index, tau_ref, pv, rho, muons, pfCands, cell, tau_funcs, is_inner, *muonTensor_[is_inner]);
0606 createHadronsBlockInputs<CandidateCastType>(
0607 idx, tau, tau_index, tau_ref, pv, rho, pfCands, cell, tau_funcs, is_inner, *hadronsTensor_[is_inner]);
0608 idx += 1;
0609 } else {
0610 if (debug_level >= 2) {
0611 std::cout << " skipping creation of inputs, because ( eta = " << eta << ", phi = " << phi
0612 << " ) is not in the grid !!" << std::endl;
0613 }
0614 }
0615 }
0616 }
0617
0618 predTensor = getPartialPredictions(is_inner);
0619 }
0620
0621 unsigned idx = 0;
0622 for (int eta = -grid.maxEtaIndex(); eta <= grid.maxEtaIndex(); ++eta) {
0623 for (int phi = -grid.maxPhiIndex(); phi <= grid.maxPhiIndex(); ++phi) {
0624 const CellIndex cell_index{eta, phi};
0625 const int eta_index = grid.getEtaTensorIndex(cell_index);
0626 const int phi_index = grid.getPhiTensorIndex(cell_index);
0627
0628 const auto cell_iter = grid.find(cell_index);
0629 if (cell_iter != grid.end()) {
0630 setCellConvFeatures(convTensor, predTensor, idx, eta_index, phi_index);
0631 idx += 1;
0632 } else {
0633 setCellConvFeatures(convTensor, *zeroOutputTensor_[is_inner], 0, eta_index, phi_index);
0634 }
0635 }
0636 }
0637 }
0638
0639 void setCellConvFeatures(tensorflow::Tensor& convTensor,
0640 const tensorflow::Tensor& features,
0641 unsigned batch_idx,
0642 int eta_index,
0643 int phi_index) {
0644 for (int n = 0; n < dnn_inputs_v2::number_of_conv_features; ++n) {
0645 convTensor.tensor<float, 4>()(0, eta_index, phi_index, n) = features.tensor<float, 4>()(batch_idx, 0, 0, n);
0646 }
0647 }
0648
0649 private:
0650 const deep_tau::DeepTauCache* cache_;
0651
0652 std::unique_ptr<tensorflow::Tensor> tauBlockTensor_;
0653 std::array<std::unique_ptr<tensorflow::Tensor>, 2> eGammaTensor_, muonTensor_, hadronsTensor_, convTensor_,
0654 zeroOutputTensor_;
0655 };
0656
0657 #include "FWCore/Framework/interface/MakerMacros.h"
0658 DEFINE_FWK_MODULE(DeepTauId);