Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ALICE3/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ o2physics_add_library(ALICE3Core
SOURCES TOFResoALICE3.cxx
TrackUtilities.cxx
DelphesO2TrackSmearer.cxx
TrackSmearerService.cxx
PUBLIC_LINK_LIBRARIES O2::Framework
O2Physics::AnalysisCore)

o2physics_target_root_dictionary(ALICE3Core
HEADERS TOFResoALICE3.h
TrackUtilities.h
DelphesO2TrackSmearer.h
TrackSmearerService.h
LINKDEF ALICE3CoreLinkDef.h)

o2physics_add_library(FastTracker
Expand Down
158 changes: 158 additions & 0 deletions ALICE3/Core/TrackSmearerService.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

/// \file TrackSmearerService.cxx
/// \brief Implementation for smearer service for the on-the-fly simulation
/// \author Jesper Karlsson Gumprecht <jesper.gumprecht@cern.ch>


#include "ALICE3/Core/TrackSmearerService.h"
#include <Framework/CommonServices.h>
#include <Framework/Plugins.h>
#include <Framework/ServiceHandle.h>
#include <Framework/ServiceSpec.h>

#include <string>
#include <TPDGCode.h>

#include <vector>

bool o2::upgrade::TrackSmearerImpl::mIsInit = false;
bool o2::upgrade::TrackSmearerImpl::mCleanLutWhenLoaded = true;

void o2::upgrade::TrackSmearerImpl::initSmearer(o2::ccdb::BasicCCDBManager* ccdb, bool cleanLutWhenLoaded)
{
if (mIsInit) {
LOG(fatal) << "TrackSmearerImpl already initialized, cannot re-initialize";
}

if (!ccdb) {
LOG(fatal) << "CCDB manager is not set, cannot initialize TrackSmearerImpl";
}

mIsInit = true;
mCcdb = ccdb;
mCcdb->setURL("http://alice-ccdb.cern.ch");
mCcdb->setTimestamp(-1);
mCleanLutWhenLoaded = cleanLutWhenLoaded;
}


std::vector<std::unique_ptr<o2::delphes::DelphesO2TrackSmearer>> o2::upgrade::TrackSmearerImpl::smearerContainer;
void o2::upgrade::TrackSmearerImpl::initCfg(int icfg, std::map<std::string, std::string> globalConfiguration)
{
smearerContainer.emplace_back(std::make_unique<o2::delphes::DelphesO2TrackSmearer>());
smearerContainer[icfg]->setCcdbManager(mCcdb);
smearerContainer[icfg]->setDownloadPath("./.ALICE3/");
smearerContainer[icfg]->setCleanupDownloadedFile(mCleanLutWhenLoaded);
for (const auto& entry : globalConfiguration) {
int pdg = 0;
if (entry.first.find("lut") != 0) {
continue;
}
if (entry.first.find("lutEl") != std::string::npos) {
pdg = kElectron;
} else if (entry.first.find("lutMu") != std::string::npos) {
pdg = kMuonMinus;
} else if (entry.first.find("lutPi") != std::string::npos) {
pdg = kPiPlus;
} else if (entry.first.find("lutKa") != std::string::npos) {
pdg = kKPlus;
} else if (entry.first.find("lutPr") != std::string::npos) {
pdg = kProton;
} else if (entry.first.find("lutDe") != std::string::npos) {
pdg = o2::constants::physics::kDeuteron;
} else if (entry.first.find("lutTr") != std::string::npos) {
pdg = o2::constants::physics::kTriton;
} else if (entry.first.find("lutHe3") != std::string::npos) {
pdg = o2::constants::physics::kHelium3;
} else if (entry.first.find("lutAl") != std::string::npos) {
pdg = o2::constants::physics::kAlpha;
}

std::string filename = entry.second;
if (pdg == 0) {
LOG(fatal) << "Unknown LUT entry " << entry.first << " for global configuration";
}
LOG(info) << "Loading LUT for pdg " << pdg << " for config " << icfg << " from provided file '" << filename << "'";
if (filename.empty()) {
LOG(warning) << "No LUT file passed for pdg " << pdg << ", skipping.";
}
// strip from leading/trailing spaces
filename.erase(0, filename.find_first_not_of(" "));
filename.erase(filename.find_last_not_of(" ") + 1);
if (filename.empty()) {
LOG(warning) << "No LUT file passed for pdg " << pdg << ", skipping.";
}
bool success = smearerContainer[icfg]->loadTable(pdg, filename.c_str());
if (!success) {
LOG(fatal) << "Having issue with loading the LUT " << pdg << " " << filename;
}
LOG(info) << "Successfully loaded LUT for pdg " << pdg;
}
}

o2::delphes::DelphesO2TrackSmearer* o2::upgrade::TrackSmearerImpl::getSmearer(int icfg)
{
if (icfg < 0 || icfg >= static_cast<int>(smearerContainer.size())) {
LOG(fatal) << "Configuration index " << icfg << " out of bounds";
return nullptr;
}
if (!smearerContainer[icfg]) {
LOG(fatal) << "nullptr entry in tracksmearer container";
return nullptr;
}
return smearerContainer[icfg].get();
}


void o2::upgrade::TrackSmearerImpl::setReady()
{
std::ofstream okFile(".TrackSmearerOK");
okFile.close();
LOG(info) << "Track smearer ready";
}

void o2::upgrade::TrackSmearerImpl::waitReady()
{
while (!std::ifstream(".TrackSmearerOK")) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}

struct TrackSmearerSupport : o2::framework::ServicePlugin {
o2::framework::ServiceSpec* create() final
{
return new o2::framework::ServiceSpec{
.name = "track-smearer",
.init = [](o2::framework::ServiceRegistryRef, o2::framework::DeviceState&, fair::mq::ProgOptions&) -> o2::framework::ServiceHandle {
auto* wrapper = new o2::upgrade::TrackSmearerContainer();
auto* ptr = new o2::upgrade::TrackSmearerImpl();
wrapper->setInstance(ptr);
return o2::framework::ServiceHandle{o2::framework::TypeIdHelpers::uniqueId<o2::upgrade::TrackSmearerContainer>(),
wrapper,
o2::framework::ServiceKind::Serial,
"database-pdg"};
},
.configure = o2::framework::CommonServices::noConfiguration(),
.exit = [](o2::framework::ServiceRegistryRef, void* service) {
auto* s = reinterpret_cast<o2::upgrade::TrackSmearerContainer*>(service);
delete s;
},
.kind = o2::framework::ServiceKind::Serial
};
}
};

DEFINE_DPL_PLUGINS_BEGIN
DEFINE_DPL_PLUGIN_INSTANCE(TrackSmearerSupport, CustomService);
DEFINE_DPL_PLUGINS_END

56 changes: 56 additions & 0 deletions ALICE3/Core/TrackSmearerService.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

/// \file TrackSmearerService.h
/// \brief Implementation for smearer service for the on-the-fly simulation
/// \author Jesper Karlsson Gumprecht <jesper.gumprecht@cern.ch>


#ifndef ALICE3_CORE_TRACKSMEARERSERVICE_H_
#define ALICE3_CORE_TRACKSMEARERSERVICE_H_

#include "ALICE3/Core/DelphesO2TrackSmearer.h"
#include "Framework/Plugins.h"
#include "CCDB/BasicCCDBManager.h"
#include "ALICE3/Core/FastTracker.h"

#include <string>
#include <vector>
#include <mutex>
#include <condition_variable>

namespace o2::upgrade {

struct TrackSmearerImpl {
static std::vector<std::unique_ptr<o2::delphes::DelphesO2TrackSmearer>> smearerContainer;
void initSmearer(o2::ccdb::BasicCCDBManager* ccdb, bool cleanLutWhenLoaded);
void initCfg(int icfg, std::map<std::string, std::string> globalConfiguration);
size_t size() { return smearerContainer.size(); }
void setReady();
void waitReady();
o2::delphes::DelphesO2TrackSmearer* getSmearer(int icfg = 0);


private:
static bool mIsInit;
static bool mCleanLutWhenLoaded;
o2::ccdb::BasicCCDBManager* mCcdb = nullptr;
};

struct TrackSmearerContainer : o2::framework::LoadableServicePlugin<TrackSmearerImpl> {
TrackSmearerContainer() : LoadableServicePlugin{"O2PhysicsALICE3Core:TrackSmearerSupport"}
{
}
};

} // namespace o2::upgrade

#endif // ALICE3_CORE_TRACKSMEARERSERVICE_H_
16 changes: 11 additions & 5 deletions ALICE3/TableProducer/OTF/onTheFlyDetectorGeometryProvider.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,32 @@
///

#include "ALICE3/Core/FastTracker.h"
#include "ALICE3/Core/TrackSmearerService.h"

#include <CCDB/BasicCCDBManager.h>
#include <Framework/AnalysisTask.h>
#include <Framework/HistogramRegistry.h>
#include <Framework/runDataProcessing.h>


#include <map>
#include <string>
#include <vector>

struct OnTheFlyDetectorGeometryProvider {
o2::framework::HistogramRegistry histos{"Histos", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject};
o2::framework::Configurable<bool> cleanLutWhenLoaded{"cleanLutWhenLoaded", true, "Flag to delete the local lut files after loading them into memory"};
o2::framework::Configurable<std::vector<std::string>> detectorConfiguration{"detectorConfiguration",
std::vector<std::string>{"$O2PHYSICS_ROOT/share/alice3/a3geometry_v3.ini"},
"Paths of the detector geometry configuration files"};
o2::framework::Service<o2::ccdb::BasicCCDBManager> ccdb;
o2::framework::Service<o2::upgrade::TrackSmearerContainer> smearerContainer;
void init(o2::framework::InitContext&)
{
if (std::ifstream(".TrackSmearerOK")) {
std::remove(".TrackSmearerOK");
}

ccdb->setURL("http://alice-ccdb.cern.ch");
ccdb->setTimestamp(-1);
o2::fastsim::GeometryContainer geometryContainer; // Checking that the geometry files can be accessed and loaded
Expand Down Expand Up @@ -70,13 +78,11 @@ struct OnTheFlyDetectorGeometryProvider {

// First we check that the magnetic field is consistent
const int nGeometries = geometryContainer.getNumberOfConfigurations();
const float mMagneticField = geometryContainer.getFloatValue(0, "global", "magneticfield");
smearerContainer->initSmearer(ccdb.operator->(), cleanLutWhenLoaded.value);
for (int icfg = 0; icfg < nGeometries; ++icfg) {
const float cfgBfield = geometryContainer.getFloatValue(icfg, "global", "magneticfield");
if (std::abs(cfgBfield - mMagneticField) > 1e-3) {
LOG(fatal) << "Inconsistent magnetic field values between configurations 0 and " << icfg << ": " << mMagneticField << " vs " << cfgBfield;
}
smearerContainer->initCfg(icfg, geometryContainer.getConfiguration(icfg, "global"));
}
smearerContainer->setReady();
LOG(info) << "Initialization completed";
}

Expand Down
66 changes: 6 additions & 60 deletions ALICE3/TableProducer/OTF/onTheFlyRichPid.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "Common/DataModel/TrackSelectionTables.h"

#include <CCDB/BasicCCDBManager.h>
#include "ALICE3/Core/TrackSmearerService.h"
#include <CCDB/CcdbApi.h>
#include <CommonConstants/GeomConstants.h>
#include <CommonConstants/MathConstants.h>
Expand Down Expand Up @@ -134,7 +135,7 @@ struct OnTheFlyRichPid {
o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE;

// Track smearer array, one per geometry
std::vector<std::unique_ptr<o2::delphes::DelphesO2TrackSmearer>> mSmearer;
Service<o2::upgrade::TrackSmearerContainer> smearerContainer;

// needed: random number generator for smearing
TRandom3 pRandomNumberGenerator;
Expand Down Expand Up @@ -290,65 +291,10 @@ struct OnTheFlyRichPid {
void init(o2::framework::InitContext& initContext)
{
mGeoContainer.init(initContext);

const int nGeometries = mGeoContainer.getNumberOfConfigurations();
smearerContainer->waitReady();
mMagneticField = mGeoContainer.getFloatValue(0, "global", "magneticfield");

pRandomNumberGenerator.SetSeed(0); // fully randomize

for (int icfg = 0; icfg < nGeometries; ++icfg) {
const std::string histPath = "Configuration_" + std::to_string(icfg) + "/";
mSmearer.emplace_back(std::make_unique<o2::delphes::DelphesO2TrackSmearer>());
mSmearer[icfg]->setCleanupDownloadedFile(cleanLutWhenLoaded.value);
mSmearer[icfg]->setCcdbManager(ccdb.operator->());
mSmearer[icfg]->setDownloadPath("./.ALICE3/RICHPID/");
std::map<std::string, std::string> globalConfiguration = mGeoContainer.getConfiguration(icfg, "global");
for (const auto& entry : globalConfiguration) {
int pdg = 0;
if (entry.first.find("lut") != 0) {
continue;
}
if (entry.first.find("lutEl") != std::string::npos) {
pdg = kElectron;
} else if (entry.first.find("lutMu") != std::string::npos) {
pdg = kMuonMinus;
} else if (entry.first.find("lutPi") != std::string::npos) {
pdg = kPiPlus;
} else if (entry.first.find("lutKa") != std::string::npos) {
pdg = kKPlus;
} else if (entry.first.find("lutPr") != std::string::npos) {
pdg = kProton;
} else if (entry.first.find("lutDe") != std::string::npos) {
pdg = o2::constants::physics::kDeuteron;
} else if (entry.first.find("lutTr") != std::string::npos) {
pdg = o2::constants::physics::kTriton;
} else if (entry.first.find("lutHe3") != std::string::npos) {
pdg = o2::constants::physics::kHelium3;
} else if (entry.first.find("lutAl") != std::string::npos) {
pdg = o2::constants::physics::kAlpha;
}

std::string filename = entry.second;
if (pdg == 0) {
LOG(fatal) << "Unknown LUT entry " << entry.first << " for global configuration";
}
LOG(info) << "Loading LUT for pdg " << pdg << " for config " << icfg << " from provided file '" << filename << "'";
if (filename.empty()) {
LOG(warning) << "No LUT file passed for pdg " << pdg << ", skipping.";
}
// strip from leading/trailing spaces
filename.erase(0, filename.find_first_not_of(" "));
filename.erase(filename.find_last_not_of(" ") + 1);
if (filename.empty()) {
LOG(warning) << "No LUT file passed for pdg " << pdg << ", skipping.";
}
bool success = mSmearer[icfg]->loadTable(pdg, filename.c_str());
if (!success) {
LOG(fatal) << "Having issue with loading the LUT " << pdg << " " << filename;
}
}
}

if (doQAplots) {
const AxisSpec axisMomentum{static_cast<int>(nBinsP), 0.0f, +20.0f, "#it{p} (GeV/#it{c})"};
const AxisSpec axisAngle{static_cast<int>(nBinsThetaRing), 0.0f, +0.30f, "Measured Cherenkov angle (rad)"};
Expand Down Expand Up @@ -870,9 +816,9 @@ struct OnTheFlyRichPid {
double ptResolution = transverseMomentum * transverseMomentum * std::sqrt(recoTrack.getSigma1Pt2());
double etaResolution = std::fabs(std::sin(2.0 * std::atan(std::exp(-recoTrack.getEta())))) * std::sqrt(recoTrack.getSigmaTgl2());
if (flagRICHLoadDelphesLUTs) {
if (mSmearer[collision.lutConfigId()]->hasTable(kParticlePdgs[ii])) {
ptResolution = mSmearer[collision.lutConfigId()]->getAbsPtRes(kParticlePdgs[ii], dNdEta, recoTrack.getEta(), transverseMomentum);
etaResolution = mSmearer[collision.lutConfigId()]->getAbsEtaRes(kParticlePdgs[ii], dNdEta, recoTrack.getEta(), transverseMomentum);
if (smearerContainer->getSmearer(collision.lutConfigId())->hasTable(kParticlePdgs[ii])) { // Only if the LUT for this particle was loaded
ptResolution = smearerContainer->getSmearer(collision.lutConfigId())->getAbsPtRes(kParticlePdgs[ii], dNdEta, recoTrack.getEta(), transverseMomentum);
etaResolution = smearerContainer->getSmearer(collision.lutConfigId())->getAbsEtaRes(kParticlePdgs[ii], dNdEta, recoTrack.getEta(), transverseMomentum);
}
}
// cout << endl << "Pt resolution: " << ptResolution << ", Eta resolution: " << etaResolution << endl << endl;
Expand Down
Loading
Loading