diff --git a/Common/Tools/PID/pidTPCModule.h b/Common/Tools/PID/pidTPCModule.h index 1c6a35048f7..7ceb7504881 100644 --- a/Common/Tools/PID/pidTPCModule.h +++ b/Common/Tools/PID/pidTPCModule.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -91,7 +92,8 @@ struct pidTPCConfigurables : o2::framework::ConfigurableGroup { // Parameters for loading network from a file / downloading the file o2::framework::Configurable useNetworkCorrection{"useNetworkCorrection", 0, "(bool) Wether or not to use the network correction for the TPC dE/dx signal"}; o2::framework::Configurable autofetchNetworks{"autofetchNetworks", 1, "(bool) Automatically fetches networks from CCDB for the correct run number"}; - o2::framework::Configurable skipTPCOnly{"skipTPCOnly", false, "Flag to skip TPC only tracks (faster but affects the analyses that use TPC only tracks)"}; + o2::framework::Configurable skipTPCOnly{"skipTPCOnly", -1, "Flag to skip TPC only tracks (faster but affects the analyses that use TPC only tracks). 0: do not skip, 1: skip, -1: check if needed by specific tasks"}; + o2::framework::Configurable> devicesRequiringTPCOnlyPID{"devicesRequiringTPCOnlyPID", std::vector{"photon-conversion-builder"}, "List of device names of tasks requiring TPC-only tracks to have TPC PID calculated"}; o2::framework::Configurable networkPathLocally{"networkPathLocally", "network.onnx", "(std::string) Path to the local .onnx file. If autofetching is enabled, then this is where the files will be downloaded"}; o2::framework::Configurable networkPathCCDB{"networkPathCCDB", "Analysis/PID/TPC/ML", "Path on CCDB"}; o2::framework::Configurable enableNetworkOptimizations{"enableNetworkOptimizations", 1, "(bool) If the neural network correction is used, this enables GraphOptimizationLevel::ORT_ENABLE_EXTENDED in the ONNX session"}; @@ -244,6 +246,59 @@ class pidTPCModule LOGF(info, "***************************************************"); } + if (pidTPCopts.skipTPCOnly.value == -1) { + LOGF(info, "***************************************************"); + LOGF(info, " the skipTPConly flag has a value of -1! "); + LOGF(info, " ---> autodetecting TPC-only track necessity now "); + LOGF(info, "***************************************************"); + // print list of devices that are being checked for + for (std::size_t devIdx{0}; devIdx < pidTPCopts.devicesRequiringTPCOnlyPID->size(); devIdx++) { + LOGF(info, "Will search for #%i device requiring TPC PID for TPC only: %s", devIdx, pidTPCopts.devicesRequiringTPCOnlyPID->at(devIdx)); + } + LOGF(info, "***************************************************"); + + // assume that TPC tracks are not needed, but check if tasks + // requiring them are present in the chain + pidTPCopts.skipTPCOnly.value = 1; + + // loop over devices in this execution + auto& workflows = context.services().template get(); + for (o2::framework::DeviceSpec const& device : workflows.devices) { + // Look for propagation service + if (device.name.compare("propagation-service") == 0) { + LOGF(info, " ---> propagation service detected, checking if photons enabled..."); + for (auto const& option : device.options) { + // check for photon generation enabled or not + if (option.name.compare("v0BuilderOpts.generatePhotonCandidates") == 0) { + if (option.defaultValue.get()) { + LOGF(info, " ---> propagation service: photons enabled, will calculate TPC PID for TPC only tracks."); + pidTPCopts.skipTPCOnly.value = 0; + } else { + LOGF(info, " ---> propagation service: photons disabled, TPC PID not required for TPC-only tracks"); + } + } + } + } + + // Check 2: specific tasks that require TPC PID based on configurable + for (std::size_t devIdx{0}; devIdx < pidTPCopts.devicesRequiringTPCOnlyPID->size(); devIdx++) { + if (device.name.compare(pidTPCopts.devicesRequiringTPCOnlyPID->at(devIdx)) == 0) { + LOGF(info, " ---> %s detected! ", pidTPCopts.devicesRequiringTPCOnlyPID->at(devIdx)); + LOGF(info, " ---> enabling TPC only track TPC PID calculations now."); + pidTPCopts.skipTPCOnly.value = 0; + } + } + } + + if (pidTPCopts.skipTPCOnly.value == 1) { + LOGF(info, "***************************************************"); + LOGF(info, "No need for TPC only information detected. Will not generate Nsigma for TPC only tracks"); + LOGF(info, "If this is unexpected behaviour and a necessity was not identified, please add the"); + LOGF(info, "corresponding task to the list 'devicesRequiringTPCOnlyPID' in pidTPCModule::Init()"); + } + LOGF(info, "***************************************************"); + } + // initialize PID response response = new o2::pid::tpc::Response(); @@ -330,12 +385,16 @@ class pidTPCModule LOG(info) << "Successfully retrieved TPC PID object from CCDB for timestamp " << time << ", period " << headers["LPMProductionTag"] << ", recoPass " << headers["RecoPassName"]; metadata["RecoPassName"] = headers["RecoPassName"]; // Force pass number for NN request to match retrieved BB o2::parameters::GRPLHCIFData* grpo = ccdb->template getForTimeStamp(pidTPCopts.cfgPathGrpLhcIf.value, time); - LOG(info) << " collision type::" << CollisionSystemType::getCollisionTypeFromGrp(grpo); - collsys = CollisionSystemType::getCollisionTypeFromGrp(grpo); - if (collsys == CollisionSystemType::kCollSyspp) { - irSource = std::string("T0VTX"); + if (grpo) { + LOG(info) << " collision type::" << CollisionSystemType::getCollisionTypeFromGrp(grpo); + collsys = CollisionSystemType::getCollisionTypeFromGrp(grpo); + if (collsys == CollisionSystemType::kCollSyspp) { + irSource = std::string("T0VTX"); + } else { + irSource = std::string("ZNC hadronic"); + } } else { - irSource = std::string("ZNC hadronic"); + LOGF(info, "No grpo object found. irSource will remain undefined."); } response->PrintAll(); } @@ -412,12 +471,16 @@ class pidTPCModule LOG(info) << "Successfully retrieved TPC PID object from CCDB for timestamp " << bc.timestamp() << ", period " << headers["LPMProductionTag"] << ", recoPass " << headers["RecoPassName"]; metadata["RecoPassName"] = headers["RecoPassName"]; // Force pass number for NN request to match retrieved BB o2::parameters::GRPLHCIFData* grpo = ccdb->template getForTimeStamp(pidTPCopts.cfgPathGrpLhcIf.value, bc.timestamp()); - LOG(info) << "Collision type::" << CollisionSystemType::getCollisionTypeFromGrp(grpo); - collsys = CollisionSystemType::getCollisionTypeFromGrp(grpo); - if (collsys == CollisionSystemType::kCollSyspp) { - irSource = std::string("T0VTX"); + if (grpo) { + LOG(info) << "Collision type::" << CollisionSystemType::getCollisionTypeFromGrp(grpo); + collsys = CollisionSystemType::getCollisionTypeFromGrp(grpo); + if (collsys == CollisionSystemType::kCollSyspp) { + irSource = std::string("T0VTX"); + } else { + irSource = std::string("ZNC hadronic"); + } } else { - irSource = std::string("ZNC hadronic"); + LOGF(info, "No grpo object found. irSource will remain undefined."); } response->PrintAll(); } @@ -458,11 +521,19 @@ class pidTPCModule size_t i = 0; for (const auto& collision : collisions) { const auto& bc = collision.template bc_as(); - hadronicRateForCollision[i] = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource) * 1.e-3; + if (irSource.compare("") != 0) { + hadronicRateForCollision[i] = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource) * 1.e-3; + } else { + hadronicRateForCollision[i] = 0.0f; + } i++; } auto bc = bcs.begin(); - hadronicRateBegin = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource) * 1.e-3; // kHz + if (irSource.compare("") != 0) { + hadronicRateBegin = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource) * 1.e-3; // kHz + } else { + hadronicRateBegin = 0.0f; + } // Filling a std::vector to be evaluated by the network // Evaluation on single tracks brings huge overhead: Thus evaluation is done on one large vector @@ -685,11 +756,19 @@ class pidTPCModule size_t i = 0; for (const auto& collision : cols) { const auto& bc = collision.template bc_as(); - hadronicRateForCollision[i] = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource) * 1.e-3; + if (irSource.compare("") != 0) { + hadronicRateForCollision[i] = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource) * 1.e-3; + } else { + hadronicRateForCollision[i] = 0.0f; + } i++; } auto bc = bcs.begin(); - hadronicRateBegin = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource) * 1.e-3; // kHz + if (irSource.compare("") != 0) { + hadronicRateBegin = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource) * 1.e-3; // kHz + } else { + hadronicRateBegin = 0.0f; + } } for (auto const& trk : tracks) { @@ -797,12 +876,16 @@ class pidTPCModule } LOG(info) << "Successfully retrieved TPC PID object from CCDB for timestamp " << bc.timestamp() << ", period " << headers["LPMProductionTag"] << ", recoPass " << headers["RecoPassName"]; o2::parameters::GRPLHCIFData* grpo = ccdb->template getForTimeStamp(pidTPCopts.cfgPathGrpLhcIf.value, bc.timestamp()); - LOG(info) << "Collisions type::" << CollisionSystemType::getCollisionTypeFromGrp(grpo); - collsys = CollisionSystemType::getCollisionTypeFromGrp(grpo); - if (collsys == CollisionSystemType::kCollSyspp) { - irSource = std::string("T0VTX"); + if (grpo) { + LOG(info) << "Collisions type::" << CollisionSystemType::getCollisionTypeFromGrp(grpo); + collsys = CollisionSystemType::getCollisionTypeFromGrp(grpo); + if (collsys == CollisionSystemType::kCollSyspp) { + irSource = std::string("T0VTX"); + } else { + irSource = std::string("ZNC hadronic"); + } } else { - irSource = std::string("ZNC hadronic"); + LOGF(info, "No grpo object found. irSource will remain undefined."); } response->PrintAll(); }