27#include "TStopwatch.h"
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.parts()) {
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();
294 LOG(info) <<
"TPC: Processing " << irecords.size() <<
" collisions";
295 auto const* dh = DataRefUtils::getHeader<o2::header::DataHeader*>(inputref);
302 <<
" to GRPUpdater from channel " << dh->subSpecification;
308 auto const* sectorHeader = DataRefUtils::getHeader<TPCSectorHeader*>(inputref);
309 if (sectorHeader ==
nullptr) {
310 LOG(error) <<
"TPC: Sector header missing, skipping processing";
313 auto sector = sectorHeader->sector();
315 mListOfSectors.push_back(sector);
316 LOG(info) <<
"TPC: Processing sector " << sector;
318 uint64_t activeSectors = 0;
319 activeSectors = sectorHeader->activeSectors;
322 auto makeDigitBuffer = [
this, sector, &pc, activeSectors, &dh]() {
325 if (mInternalWriter) {
326 using ContainerType = std::decay_t<
decltype(pc.
outputs().
make<std::vector<o2::tpc::Digit>>(
Output{
"",
"", 0}))>*;
327 return ContainerType(
nullptr);
334 auto snapshotCommonMode = [
this, sector, &pc, activeSectors, &dh](std::vector<o2::tpc::CommonMode>
const& commonMode) {
337 if (!mInternalWriter) {
340 const_cast<std::vector<o2::tpc::CommonMode>&
>(commonMode));
348 if (!mInternalWriter) {
350 labels.flatten_to(sharedlabels);
355 auto snapshotEvents = [
this, sector, &pc, activeSectors, &dh](
const std::vector<DigiGroupRef>& events) {
358 if (!mInternalWriter) {
359 LOG(info) <<
"TPC: Send TRIGGERS for sector " << sector <<
" channel " << dh->subSpecification <<
" | size " << events.size();
361 const_cast<std::vector<DigiGroupRef>&
>(events));
365 auto digitsAccum = makeDigitBuffer();
367 std::vector<CommonMode> commonModeAccum;
368 std::vector<DigiGroupRef> eventAccum;
373 throw std::runtime_error(
"Legacy control information is not expected any more");
380 throw std::runtime_error(
"Digitizer can only work on single sectors");
386 auto& eventParts = context->getEventParts();
388 auto flushDigitsAndLabels = [
this, digitsAccum, &labelAccum, &commonModeAccum](
bool finalFlush =
false) {
394 mDigitizer.
flush(mDigits, mLabels, mCommonMode, finalFlush);
395 LOG(info) <<
"TPC: Flushed " << mDigits.size() <<
" digits, " << mLabels.
getNElements() <<
" labels and " << mCommonMode.size() <<
" common mode entries";
397 if (mInternalWriter) {
402 std::copy(mDigits.begin(), mDigits.end(), std::back_inserter(*digitsAccum));
406 std::copy(mCommonMode.begin(), mCommonMode.end(), std::back_inserter(commonModeAccum));
408 mDigitCounter += mDigits.size();
415 if (!irecords.empty()) {
416 mDigitizer.
setStartTime(irecords[0].getTimeNS() / 1000.f);
425 for (
int collID = 0; collID < irecords.size(); ++collID) {
426 const double eventTime = irecords[collID].getTimeNS() / 1000.f;
427 LOG(info) <<
"TPC: Event time " << eventTime <<
" us";
432 size_t startSize = mDigitCounter;
436 for (
auto& part : eventParts[collID]) {
437 const int eventID = part.entryID;
438 const int sourceID = part.sourceID;
441 std::vector<o2::tpc::HitGroup> hitsLeft;
442 std::vector<o2::tpc::HitGroup> hitsRight;
443 context->retrieveHits(mSimChains,
getBranchNameLeft(sector).c_str(), part.sourceID, part.entryID, &hitsLeft);
444 context->retrieveHits(mSimChains,
getBranchNameRight(sector).c_str(), part.sourceID, part.entryID, &hitsRight);
445 LOG(
debug) <<
"TPC: Found " << hitsLeft.size() <<
" hit groups left and " << hitsRight.size() <<
" hit groups right in collision " << collID <<
" eventID " << part.entryID;
447 mDigitizer.
process(hitsLeft, eventID, sourceID);
448 mDigitizer.
process(hitsRight, eventID, sourceID);
450 flushDigitsAndLabels();
453 eventAccum.emplace_back(startSize, mDigits.size());
460 LOG(info) <<
"TPC: Final flush";
461 flushDigitsAndLabels(
true);
462 eventAccum.emplace_back(0, mDigitCounter);
465 if (!mInternalWriter) {
467 snapshotEvents(eventAccum);
469 snapshotCommonMode(commonModeAccum);
470 snapshotLabels(labelAccum);
474 LOG(info) <<
"TPC: Digitization took " << timer.CpuTime() <<
"s";
480 std::vector<TChain*> mSimChains;
481 std::vector<o2::tpc::Digit> mDigits;
483 std::vector<o2::tpc::CommonMode> mCommonMode;
484 std::vector<int> mListOfSectors;
485 TFile* mInternalROOTFlushFile =
nullptr;
486 TTree* mInternalROOTFlushTTree =
nullptr;
487 size_t mDigitCounter = 0;
488 size_t mFlushCounter = 0;
491 bool mWriteGRP =
false;
492 bool mWithMCTruth =
true;
493 bool mInternalWriter =
false;
494 bool mUseCalibrationsFromCCDB =
false;
495 int mDistortionType = 0;
496 float mMeanLumiDistortions = -1;
497 float mMeanLumiDistortionsDerivative = -1;
498 bool mRecalcDistortions =
false;
508 std::stringstream
id;
509 id <<
"TPCDigitizer" << channel;
511 std::vector<OutputSpec> outputs;
513 if (!internalwriter) {
514 outputs.emplace_back(
"TPC",
"DIGITS",
static_cast<SubSpecificationType>(channel), Lifetime::Timeframe);
515 outputs.emplace_back(
"TPC",
"DIGTRIGGERS",
static_cast<SubSpecificationType>(channel), Lifetime::Timeframe);
517 outputs.emplace_back(
"TPC",
"DIGITSMCTR",
static_cast<SubSpecificationType>(channel), Lifetime::Timeframe);
519 outputs.emplace_back(
"TPC",
"COMMONMODE",
static_cast<SubSpecificationType>(channel), Lifetime::Timeframe);
522 outputs.emplace_back(
"TPC",
"ROMode", 0, Lifetime::Timeframe);
523 LOG(
debug) <<
"TPC: Channel " << channel <<
" will supply ROMode";
526 std::vector<InputSpec> inputs{
InputSpec{
"collisioncontext",
"SIM",
"COLLISIONCONTEXT",
static_cast<SubSpecificationType>(channel), Lifetime::Timeframe}};
531 AlgorithmSpec{adaptFromTask<TPCDPLDigitizerTask>(internalwriter, distortionType)},
533 {
"TPCtriggered", VariantType::Bool,
false, {
"Impose triggered RO mode (default: continuous)"}},
534 {
"TPCuseCCDB", VariantType::Bool,
false, {
"true: load calibrations from CCDB; false: use random calibratoins"}},
535 {
"meanLumiDistortions", VariantType::Float, -1.f, {
"override lumi of distortion object if >=0"}},
536 {
"meanLumiDistortionsDerivative", VariantType::Float, -1.f, {
"override lumi of derivative distortion object if >=0"}},
537 {
"do-not-recalculate-distortions", VariantType::Bool,
false, {
"Do not recalculate the distortions"}},
538 {
"n-threads-distortions", VariantType::Int, 4, {
"Number of threads used for the calculation of the distortions"}},
550 pipelineTemplate[0].
name =
"TPCDigitizer";
552 pipelineTemplate, nLanes, [
size = sectors.size()]() { return size; }, [§ors](
size_t index) { return sectors[index]; });
558 if (distortionType) {
561 if (distortionType == 2) {
566 pipelines[0].outputs.emplace_back(
"TPC",
"ROMode", 0, Lifetime::Timeframe);
header::DataOrigin origin
std::vector< std::string > labels
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 ITS Vertex 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()))