27#include "TStopwatch.h"
63 std::copy(origin.begin(), origin.end(), std::back_inserter(
target));
68 target.mergeAtBack(origin);
76 targetbr->ResetAddress();
77 targetbr->DropBaskets(
"all");
80void writeToBranchHelper<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>(TTree&
tree,
86 accum->clear_andfreememory();
90 targetbr->ResetAddress();
91 targetbr->DropBaskets(
"all");
96 std::stringstream branchnamestreamleft;
98 return branchnamestreamleft.str();
103 std::stringstream branchnamestreamright;
104 branchnamestreamright <<
"TPCHitsShiftedSector" << sector;
105 return branchnamestreamright.str();
118 LOG(info) <<
"Initializing TPC digitization";
123 auto triggeredMode = ic.
options().
get<
bool>(
"TPCtriggered");
124 mRecalcDistortions = !(ic.
options().
get<
bool>(
"do-not-recalculate-distortions"));
125 const int nthreadsDist = ic.
options().
get<
int>(
"n-threads-distortions");
127 mUseCalibrationsFromCCDB = ic.
options().
get<
bool>(
"TPCuseCCDB");
128 mMeanLumiDistortions = ic.
options().
get<
float>(
"meanLumiDistortions");
129 mMeanLumiDistortionsDerivative = ic.
options().
get<
float>(
"meanLumiDistortionsDerivative");
131 LOG(info) <<
"TPC calibrations from CCDB: " << mUseCalibrationsFromCCDB;
141 if (mInternalWriter) {
150 std::stringstream tmp;
151 tmp <<
"tpc_driftime_digits_lane" << mLaneId <<
".root";
152 if (std::filesystem::exists(tmp.str())) {
153 std::filesystem::remove(tmp.str());
159 if (!mInternalROOTFlushFile) {
160 std::stringstream tmp;
161 tmp <<
"tpc_driftime_digits_lane" << mLaneId <<
".root";
162 mInternalROOTFlushFile =
new TFile(tmp.str().c_str(),
"UPDATE");
163 std::stringstream trname;
165 mInternalROOTFlushTTree =
new TTree(trname.str().c_str(),
"o2sim");
168 std::stringstream brname;
169 brname <<
"TPCDigit_" << mSector;
176 std::stringstream brname;
177 brname <<
"TPCDigitMCTruth_" << mSector;
184 std::stringstream brname;
185 brname <<
"TPCCommonMode_" << mSector;
198 LOGP(info,
"Updating distortion map");
200 if (mMeanLumiDistortions >= 0) {
205 LOGP(info,
"Updating reference distortion map");
207 if (mMeanLumiDistortionsDerivative >= 0) {
212 LOGP(info,
"TPC gas param updated");
216 LOGP(info,
"TPC GEM param updated");
223 LOG(info) <<
"Processing TPC digitization";
227 cdb.setUseDefaults(!mUseCalibrationsFromCCDB);
232 if (mDistortionType) {
234 if (mDistortionType == 2) {
237 if (mRecalcDistortions) {
245 LOGP(info,
"Updating TPC fast transform map with new VDrift factor of {} wrt reference {} and DriftTimeOffset correction {} wrt {} from source {}",
246 vd.corrFact, vd.refVDrift, vd.timeOffsetCorr, vd.refTimeOffset, mTPCVDriftHelper.
getSourceName());
252 if (std::filesystem::exists(
"ThresholdMap.root")) {
253 LOG(info) <<
"TPC: Using zero suppression map from 'ThresholdMap.root'";
254 cdb.setThresholdMapFromFile(
"ThresholdMap.root");
257 if (std::filesystem::exists(
"GainMap.root")) {
258 LOG(info) <<
"TPC: Using gain map from 'GainMap.root'";
259 cdb.setGainMapFromFile(
"GainMap.root");
263 for (
auto const& inputref : it) {
264 if (inputref.spec->lifetime == o2::framework::Lifetime::Condition) {
268 if (mInternalWriter) {
269 mInternalROOTFlushTTree->SetEntries(mFlushCounter);
270 mInternalROOTFlushFile->Write(
"", TObject::kOverwrite);
271 mInternalROOTFlushFile->Close();
273 delete mInternalROOTFlushFile;
274 mInternalROOTFlushFile =
nullptr;
289 auto& irecords = context->getEventRecords();
290 LOG(info) <<
"TPC: Processing " << irecords.size() <<
" collisions";
291 if (irecords.size() == 0) {
294 auto const* dh = DataRefUtils::getHeader<o2::header::DataHeader*>(inputref);
301 <<
" to GRPUpdater from channel " << dh->subSpecification;
307 auto const* sectorHeader = DataRefUtils::getHeader<TPCSectorHeader*>(inputref);
308 if (sectorHeader ==
nullptr) {
309 LOG(error) <<
"TPC: Sector header missing, skipping processing";
312 auto sector = sectorHeader->sector();
314 mListOfSectors.push_back(sector);
315 LOG(info) <<
"TPC: Processing sector " << sector;
317 uint64_t activeSectors = 0;
318 activeSectors = sectorHeader->activeSectors;
321 auto makeDigitBuffer = [
this, sector, &pc, activeSectors, &dh]() {
324 if (mInternalWriter) {
325 using ContainerType = std::decay_t<
decltype(pc.
outputs().
make<std::vector<o2::tpc::Digit>>(
Output{
"",
"", 0}))>*;
326 return ContainerType(
nullptr);
333 auto snapshotCommonMode = [
this, sector, &pc, activeSectors, &dh](std::vector<o2::tpc::CommonMode>
const& commonMode) {
336 if (!mInternalWriter) {
339 const_cast<std::vector<o2::tpc::CommonMode>&
>(commonMode));
347 if (!mInternalWriter) {
349 labels.flatten_to(sharedlabels);
354 auto snapshotEvents = [
this, sector, &pc, activeSectors, &dh](
const std::vector<DigiGroupRef>& events) {
357 if (!mInternalWriter) {
358 LOG(info) <<
"TPC: Send TRIGGERS for sector " << sector <<
" channel " << dh->subSpecification <<
" | size " << events.size();
360 const_cast<std::vector<DigiGroupRef>&
>(events));
364 auto digitsAccum = makeDigitBuffer();
366 std::vector<CommonMode> commonModeAccum;
367 std::vector<DigiGroupRef> eventAccum;
372 throw std::runtime_error(
"Legacy control information is not expected any more");
379 throw std::runtime_error(
"Digitizer can only work on single sectors");
385 auto& eventParts = context->getEventParts();
387 auto flushDigitsAndLabels = [
this, digitsAccum, &labelAccum, &commonModeAccum](
bool finalFlush =
false) {
393 mDigitizer.
flush(mDigits, mLabels, mCommonMode, finalFlush);
394 LOG(info) <<
"TPC: Flushed " << mDigits.size() <<
" digits, " << mLabels.
getNElements() <<
" labels and " << mCommonMode.size() <<
" common mode entries";
396 if (mInternalWriter) {
401 std::copy(mDigits.begin(), mDigits.end(), std::back_inserter(*digitsAccum));
405 std::copy(mCommonMode.begin(), mCommonMode.end(), std::back_inserter(commonModeAccum));
407 mDigitCounter += mDigits.size();
414 mDigitizer.
setStartTime(irecords[0].getTimeNS() / 1000.f);
422 for (
int collID = 0; collID < irecords.size(); ++collID) {
423 const double eventTime = irecords[collID].getTimeNS() / 1000.f;
424 LOG(info) <<
"TPC: Event time " << eventTime <<
" us";
429 size_t startSize = mDigitCounter;
433 for (
auto& part : eventParts[collID]) {
434 const int eventID = part.entryID;
435 const int sourceID = part.sourceID;
438 std::vector<o2::tpc::HitGroup> hitsLeft;
439 std::vector<o2::tpc::HitGroup> hitsRight;
440 context->retrieveHits(mSimChains,
getBranchNameLeft(sector).c_str(), part.sourceID, part.entryID, &hitsLeft);
441 context->retrieveHits(mSimChains,
getBranchNameRight(sector).c_str(), part.sourceID, part.entryID, &hitsRight);
442 LOG(
debug) <<
"TPC: Found " << hitsLeft.size() <<
" hit groups left and " << hitsRight.size() <<
" hit groups right in collision " << collID <<
" eventID " << part.entryID;
444 mDigitizer.
process(hitsLeft, eventID, sourceID);
445 mDigitizer.
process(hitsRight, eventID, sourceID);
447 flushDigitsAndLabels();
450 eventAccum.emplace_back(startSize, mDigits.size());
457 LOG(info) <<
"TPC: Final flush";
458 flushDigitsAndLabels(
true);
459 eventAccum.emplace_back(0, mDigitCounter);
462 if (!mInternalWriter) {
464 snapshotEvents(eventAccum);
466 snapshotCommonMode(commonModeAccum);
467 snapshotLabels(labelAccum);
471 LOG(info) <<
"TPC: Digitization took " << timer.CpuTime() <<
"s";
477 std::vector<TChain*> mSimChains;
478 std::vector<o2::tpc::Digit> mDigits;
480 std::vector<o2::tpc::CommonMode> mCommonMode;
481 std::vector<int> mListOfSectors;
482 TFile* mInternalROOTFlushFile =
nullptr;
483 TTree* mInternalROOTFlushTTree =
nullptr;
484 size_t mDigitCounter = 0;
485 size_t mFlushCounter = 0;
488 bool mWriteGRP =
false;
489 bool mWithMCTruth =
true;
490 bool mInternalWriter =
false;
491 bool mUseCalibrationsFromCCDB =
false;
492 int mDistortionType = 0;
493 float mMeanLumiDistortions = -1;
494 float mMeanLumiDistortionsDerivative = -1;
495 bool mRecalcDistortions =
false;
505 std::stringstream
id;
506 id <<
"TPCDigitizer" << channel;
508 std::vector<OutputSpec> outputs;
510 if (!internalwriter) {
511 outputs.emplace_back(
"TPC",
"DIGITS",
static_cast<SubSpecificationType>(channel), Lifetime::Timeframe);
512 outputs.emplace_back(
"TPC",
"DIGTRIGGERS",
static_cast<SubSpecificationType>(channel), Lifetime::Timeframe);
514 outputs.emplace_back(
"TPC",
"DIGITSMCTR",
static_cast<SubSpecificationType>(channel), Lifetime::Timeframe);
516 outputs.emplace_back(
"TPC",
"COMMONMODE",
static_cast<SubSpecificationType>(channel), Lifetime::Timeframe);
519 outputs.emplace_back(
"TPC",
"ROMode", 0, Lifetime::Timeframe);
520 LOG(
debug) <<
"TPC: Channel " << channel <<
" will supply ROMode";
523 std::vector<InputSpec> inputs{
InputSpec{
"collisioncontext",
"SIM",
"COLLISIONCONTEXT",
static_cast<SubSpecificationType>(channel), Lifetime::Timeframe}};
528 AlgorithmSpec{adaptFromTask<TPCDPLDigitizerTask>(internalwriter, distortionType)},
530 {
"TPCtriggered", VariantType::Bool,
false, {
"Impose triggered RO mode (default: continuous)"}},
531 {
"TPCuseCCDB", VariantType::Bool,
false, {
"true: load calibrations from CCDB; false: use random calibratoins"}},
532 {
"meanLumiDistortions", VariantType::Float, -1.f, {
"override lumi of distortion object if >=0"}},
533 {
"meanLumiDistortionsDerivative", VariantType::Float, -1.f, {
"override lumi of derivative distortion object if >=0"}},
534 {
"do-not-recalculate-distortions", VariantType::Bool,
false, {
"Do not recalculate the distortions"}},
535 {
"n-threads-distortions", VariantType::Int, 4, {
"Number of threads used for the calculation of the distortions"}},
547 pipelineTemplate[0].
name =
"TPCDigitizer";
549 pipelineTemplate, nLanes, [
size = sectors.size()]() { return size; }, [§ors](
size_t index) { return sectors[index]; });
555 if (distortionType) {
558 if (distortionType == 2) {
563 pipelines[0].outputs.emplace_back(
"TPC",
"ROMode", 0, Lifetime::Timeframe);
Definition of the base digitizer task class.
Definition of the Detector class.
Simple interface to the CDB manager.
A const (ready only) version of MCTruthContainer.
o2::framework::DataAllocator::SubSpecificationType SubSpecificationType
Header of the General Run Parameters object.
A special IO container - splitting a given vector to enable ROOT IO.
Definition of the parameter class for the GEM stack.
Class to refer to the 1st entry and N elements of some group in the continuous container.
This class contains the algorithms for calculation the distortions and corrections.
Definition of the ALICE TPC digitizer.
Helper class to extract VDrift from different sources.
static const DigiParams & Instance()
T get(const char *key) const
void snapshot(const Output &spec, T const &object)
o2::header::DataHeader::SubSpecificationType SubSpecificationType
decltype(auto) make(const Output &spec, Args... args)
bool isAllowed(Output const &query)
check if a certain output is allowed
ServiceRegistryRef services()
ConfigParamRegistry const & options()
DataAllocator & outputs()
The data allocator is used to allocate memory for the output data.
InputRecord & inputs()
The inputs associated with this processing context.
bool initSimChains(o2::detectors::DetID detid, std::vector< TChain * > &simchains) const
static CDBInterface & instance()
void setMeanLumiDistortions(float meanLumi)
void setUseSCDistortions(const SCDistortionType &distortionType, const TH3 *hisInitialSCDensity)
void setMeanLumiDistortionsDerivative(float meanLumi)
void setDistortionScaleType(int distortionScaleType)
void flush(std::vector< o2::tpc::Digit > &digits, o2::dataformats::MCTruthContainer< o2::MCCompLabel > &labels, std::vector< o2::tpc::CommonMode > &commonModeOutput, bool finalFlush=false)
void setSector(Sector sec)
void setOutputDigitTimeOffset(double offset)
Set mOutputDigitTimeOffset.
void setSCDistortionsDerivative(SC *spaceCharge)
void setLumiScaleFactor()
void setStartTime(double time)
void recalculateDistortions()
in case of scaled distortions, the distortions can be recalculated to ensure consistent distortions a...
void setContinuousReadout(bool isContinuous)
void process(const std::vector< o2::tpc::HitGroup > &hits, const int eventID, const int sourceID=0)
void setEventTime(double time)
void setTDriftOffset(float t)
bool isContinuousReadout()
static Sector getLeft(const Sector s)
static void setNThreads(const int nThreads)
set the number of threads used for some of the calculations
void initDigitizerTask(framework::InitContext &ic) override
void run(framework::ProcessingContext &pc)
void process(framework::ProcessingContext &pc, framework::DataRef const &inputref)
TPCDPLDigitizerTask(bool internalwriter, int distortionType)
void finaliseCCDB(framework::ConcreteDataMatcher &matcher, void *obj)
static void requestCCDBInputs(std::vector< o2::framework::InputSpec > &inputs, bool laser=true, bool itstpcTgl=true)
void extractCCDBInputs(o2::framework::ProcessingContext &pc, bool laser=true, bool itstpcTgl=true)
const VDriftCorrFact & getVDriftObject() const
bool accountCCDBInputs(const o2::framework::ConcreteDataMatcher &matcher, void *obj)
static std::string_view getSourceName(Source s)
GLuint const GLchar * name
constexpr o2::header::DataOrigin gDataOriginTPC
TBranch * getOrMakeBranch(TTree &tree, const char *brname, T *ptr)
Defining PrimaryVertex explicitly as messageable.
WorkflowSpec parallelPipeline(const WorkflowSpec &specs, size_t nPipelines, std::function< size_t()> getNumberOfSubspecs, std::function< size_t(size_t)> getSubSpec)
std::vector< ConfigParamSpec > ccdbParamSpec(std::string const &path, int runDependent, std::vector< CCDBMetadata > metadata={}, int qrate=0)
std::vector< DataProcessorSpec > WorkflowSpec
std::vector< ConfigParamSpec > Options
header::DataHeader::SubSpecificationType SubSpecificationType
std::string getBranchNameLeft(int sector)
const std::unordered_map< CDBType, const std::string > CDBTypeMap
Storage name in CCDB for each calibration and parameter type.
void writeToBranchHelper(TTree &tree, const char *name, T *accum)
o2::framework::DataProcessorSpec getTPCDigitizerSpec(int channel, bool writeGRP, bool mctruth, bool internalwriter, int distortionType)
void copyHelper(T const &origin, R &target)
@ ParGas
Parameter for Gas.
@ DistortionMapDerivMC
derivative distortions for MC used in the digitizer for scaling
@ DistortionMapMC
full distortions (static + IR dependant) for MC used in the digitizer
std::string getBranchNameRight(int sector)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
class listing possible services
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))