From 81c688904133c9ea0ec17e67341c90ed176aaad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Tue, 17 Mar 2026 08:31:06 +0100 Subject: [PATCH 01/16] TOF digitiser --- .../Upgrades/ALICE3/IOTOF/CMakeLists.txt | 1 + .../ALICE3/IOTOF/simulation/CMakeLists.txt | 2 + .../IOTOFSimulation/DPLDigitizerParam.h | 69 +++++++++ .../simulation/src/DPLDigitizerParam.cxx | 22 +++ .../ALICE3/IOTOF/workflow/CMakeLists.txt | 25 ++++ .../include/IOTOFWorkflow/DigitReaderSpec.h | 67 +++++++++ .../include/IOTOFWorkflow/DigitWriterSpec.h | 26 ++++ .../IOTOF/workflow/src/DigitReaderSpec.cxx | 132 ++++++++++++++++++ .../IOTOF/workflow/src/DigitWriterSpec.cxx | 110 +++++++++++++++ .../workflow/src/iotof-reco-workflow.cxx | 82 +++++++++++ Steer/DigitizerWorkflow/CMakeLists.txt | 6 +- .../src/IOTOFDigitizerSpec.cxx | 93 ++++++++++++ .../src/IOTOFDigitizerSpec.h | 22 +++ .../src/SimpleDigitizerWorkflow.cxx | 9 ++ 14 files changed, 665 insertions(+), 1 deletion(-) create mode 100644 Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h create mode 100644 Detectors/Upgrades/ALICE3/IOTOF/simulation/src/DPLDigitizerParam.cxx create mode 100644 Detectors/Upgrades/ALICE3/IOTOF/workflow/CMakeLists.txt create mode 100644 Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/DigitReaderSpec.h create mode 100644 Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/DigitWriterSpec.h create mode 100644 Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitReaderSpec.cxx create mode 100644 Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitWriterSpec.cxx create mode 100644 Detectors/Upgrades/ALICE3/IOTOF/workflow/src/iotof-reco-workflow.cxx create mode 100644 Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx create mode 100644 Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.h diff --git a/Detectors/Upgrades/ALICE3/IOTOF/CMakeLists.txt b/Detectors/Upgrades/ALICE3/IOTOF/CMakeLists.txt index 04288f205d8f4..587c11fdb04cc 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/CMakeLists.txt +++ b/Detectors/Upgrades/ALICE3/IOTOF/CMakeLists.txt @@ -12,4 +12,5 @@ add_subdirectory(base) add_subdirectory(simulation) add_subdirectory(DataFormatsIOTOF) +# add_subdirectory(workflow) add_subdirectory(macros) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/CMakeLists.txt b/Detectors/Upgrades/ALICE3/IOTOF/simulation/CMakeLists.txt index 25d623c0047a9..ae9b0ed29e63d 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/CMakeLists.txt +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/CMakeLists.txt @@ -13,6 +13,7 @@ o2_add_library(IOTOFSimulation SOURCES src/Layer.cxx src/Detector.cxx src/Digitizer.cxx + src/DPLDigitizerParam.cxx # src/IOTOFServices.cxx src/Segmentation.cxx PUBLIC_LINK_LIBRARIES O2::IOTOFBase @@ -23,6 +24,7 @@ o2_target_root_dictionary(IOTOFSimulation HEADERS include/IOTOFSimulation/Detector.h include/IOTOFSimulation/Layer.h include/IOTOFSimulation/Digitizer.h + include/IOTOFSimulation/DPLDigitizerParam.h # include/IOTOFSimulation/IOTOFServices.h include/IOTOFSimulation/Segmentation.h ) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h new file mode 100644 index 0000000000000..db68b9670d272 --- /dev/null +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h @@ -0,0 +1,69 @@ +// 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. + +#ifndef ALICEO2_TRKDPLDIGITIZERPARAM_H_ +#define ALICEO2_TRKDPLDIGITIZERPARAM_H_ + +#include "DetectorsCommonDataFormats/DetID.h" +#include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/ConfigurableParamHelper.h" +#include + +namespace o2 +{ +namespace trk +{ +template +struct DPLDigitizerParam : public o2::conf::ConfigurableParamHelper> { + static_assert(N == o2::detectors::DetID::TF3, "only DetID::TF3 is allowed"); + + static constexpr std::string_view getParamName() + { + return N == o2::detectors::DetID::TF3 ? ParamName[0] : ParamName[1]; + } + + bool continuous = true; ///< flag for continuous simulation + float noisePerPixel = DEFNoisePerPixel(); ///< ALPIDE Noise per channel + float strobeFlatTop = 20.; ///< strobe shape flat top + float strobeMaxRiseTime = 0.; ///< strobe max rise time + float strobeQRiseTime0 = 0.; ///< q @ which strobe rise time is 0 + + double timeOffset = 0.; ///< time offset (in seconds!) to calculate ROFrame from hit time + int chargeThreshold = 75; ///< charge threshold in Nelectrons + int minChargeToAccount = 7; ///< minimum charge contribution to account + int nSimSteps = 475; ///< number of steps in response simulation + float energyToNElectrons = 1. / 3.6e-9; // conversion of eloss to Nelectrons + + float Vbb = 0.0; ///< back bias absolute value for MFT (in Volt) + float IBVbb = 0.0; ///< back bias absolute value for ITS Inner Barrel (in Volt) + float OBVbb = 0.0; ///< back bias absolute value for ITS Outter Barrel (in Volt) + + std::string noiseFilePath{}; ///< optional noise masks file path. FIXME to be removed once switch to CCDBFetcher + + // boilerplate stuff + make principal key + O2ParamDef(DPLDigitizerParam, getParamName().data()); + + private: + static constexpr float DEFNoisePerPixel() + { + return N == o2::detectors::DetID::TF3 ? 1e-7 : 1e-8; // ITS/MFT values here!! + } + + static constexpr std::string_view ParamName[2] = {"TRKDigitizerParam", "FT3DigitizerParam"}; +}; + +template +DPLDigitizerParam DPLDigitizerParam::sInstance; + +} // namespace trk +} // namespace o2 + +#endif diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/DPLDigitizerParam.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/DPLDigitizerParam.cxx new file mode 100644 index 0000000000000..3bb48a2b49fb6 --- /dev/null +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/DPLDigitizerParam.cxx @@ -0,0 +1,22 @@ +// 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. + +#include "IOTOFSimulation/DPLDigitizerParam.h" + +namespace o2 +{ +namespace iotof +{ +// this makes sure that the constructor of the parameters is statically called +// so that these params are part of the parameter database +static auto& sDigitizerParamTF3 = o2::trk::DPLDigitizerParam::Instance(); +} // namespace iotof +} // namespace o2 diff --git a/Detectors/Upgrades/ALICE3/IOTOF/workflow/CMakeLists.txt b/Detectors/Upgrades/ALICE3/IOTOF/workflow/CMakeLists.txt new file mode 100644 index 0000000000000..496b473427974 --- /dev/null +++ b/Detectors/Upgrades/ALICE3/IOTOF/workflow/CMakeLists.txt @@ -0,0 +1,25 @@ +# 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. + +o2_add_library(IOTOFWorkflow + TARGETVARNAME targetName + SOURCES src/DigitReaderSpec.cxx + # src/DigitWriterSpec.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + O2::DataFormatsIOTOF + ) + +o2_add_executable(reco-workflow + SOURCES src/iotof-reco-workflow.cxx + COMPONENT_NAME alice3-iotof + PUBLIC_LINK_LIBRARIES O2::IOTOFWorkflow + O2::IOTOFSimulation + ) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/DigitReaderSpec.h b/Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/DigitReaderSpec.h new file mode 100644 index 0000000000000..2a51639b931fc --- /dev/null +++ b/Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/DigitReaderSpec.h @@ -0,0 +1,67 @@ +// 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. + +#ifndef O2_IOTOF_DIGITREADER +#define O2_IOTOF_DIGITREADER + +#include "TFile.h" +#include "TTree.h" +#include "DataFormatsIOTOF/Digit.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include "Headers/DataHeader.h" +#include "DataFormatsITSMFT/ROFRecord.h" +#include "DetectorsCommonDataFormats/DetID.h" + +namespace o2::iotof +{ + +class TF3DigitReader : public o2::framework::Task +{ + public: + TF3DigitReader() = delete; + TF3DigitReader(o2::detectors::DetID id, bool useMC, bool useCalib); + ~TF3DigitReader() override = default; + void init(o2::framework::InitContext& ic) final; + void run(o2::framework::ProcessingContext& pc) final; + + protected: + void connectTree(const std::string& filename); + + std::vector mDigits, *mDigitsPtr = &mDigits; + o2::header::DataOrigin mOrigin = o2::header::gDataOriginInvalid; + + std::unique_ptr mFile; + std::unique_ptr mTree; + + bool mUseMC = true; // use MC truth + bool mUseCalib = true; // send calib data + + std::string mDetName = ""; + std::string mDetNameLC = ""; + std::string mFileName = ""; + std::string mDigTreeName = "o2sim"; + std::string mDigitBranchName = "Digit"; + std::string mDigROFBranchName = "DigitROF"; + std::string mCalibBranchName = "Calib"; + + std::string mDigtMCTruthBranchName = "DigitMCTruth"; + std::string mDigtMC2ROFBranchName = "DigitMC2ROF"; + // static constexpr o2::detectors::DetID mDetID = o2::header::gDataOriginTF3; +}; + +/// create a processor spec +/// read ITS/MFT Digit data from a root file +o2::framework::DataProcessorSpec getIOTOFDigitReaderSpec(bool useMC = true, bool useCalib = false, std::string defname = "iotofdigits.root"); + +} // namespace o2::iotof + +#endif /* O2_IOTOF_DigitREADER */ diff --git a/Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/DigitWriterSpec.h b/Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/DigitWriterSpec.h new file mode 100644 index 0000000000000..9c37d4318bb0f --- /dev/null +++ b/Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/DigitWriterSpec.h @@ -0,0 +1,26 @@ +// 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. + +#ifndef STEER_TRKDIGITWRITER_H_ +#define STEER_TRKDIGITWRITER_H_ + +#include "Framework/DataProcessorSpec.h" + +namespace o2 +{ +namespace trk +{ + +o2::framework::DataProcessorSpec getTRKDigitWriterSpec(bool mctruth = true, bool dec = false, bool calib = false); +} // namespace trk +} // end namespace o2 + +#endif /* STEER_TRKDIGITWRITER_H_ */ diff --git a/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitReaderSpec.cxx b/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitReaderSpec.cxx new file mode 100644 index 0000000000000..8ab51235d32b6 --- /dev/null +++ b/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitReaderSpec.cxx @@ -0,0 +1,132 @@ +// 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. + +#include + +#include "TTree.h" + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/Logger.h" +#include "IOTOFWorkflow/DigitReaderSpec.h" +#include "SimulationDataFormat/MCCompLabel.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" +#include "SimulationDataFormat/IOMCTruthContainerView.h" + +namespace o2::iotof +{ + +TF3DigitReader::TF3DigitReader(o2::detectors::DetID id, bool useMC, bool useCalib) +{ + assert(id == o2::detectors::DetID::TRK); + mDetNameLC = mDetName = id.getName(); + mDigTreeName = "o2sim"; + + mDigitBranchName = mDetName + mDigitBranchName; + mDigROFBranchName = mDetName + mDigROFBranchName; + mCalibBranchName = mDetName + mCalibBranchName; + + mDigtMCTruthBranchName = mDetName + mDigtMCTruthBranchName; + mDigtMC2ROFBranchName = mDetName + mDigtMC2ROFBranchName; + + mUseMC = useMC; + mUseCalib = useCalib; + std::transform(mDetNameLC.begin(), mDetNameLC.end(), mDetNameLC.begin(), ::tolower); +} + +void TF3DigitReader::init(o2::framework::InitContext& ic) +{ + mFileName = ic.options().get((mDetNameLC + "-digit-infile").c_str()); + connectTree(mFileName); +} + +void TF3DigitReader::run(o2::framework::ProcessingContext& pc) +{ + auto ent = mTree->GetReadEntry() + 1; + assert(ent < mTree->GetEntries()); // this should not happen + + o2::dataformats::IOMCTruthContainerView* plabels = nullptr; + if (mUseMC) { + mTree->SetBranchAddress(mDigtMCTruthBranchName.c_str(), &plabels); + } + mTree->GetEntry(ent); + LOG(info) << mDetName << "TF3DigitReader pushes " << mDigROFRec.size() << " ROFRecords, " + << mDigits.size() << " digits at entry " << ent; + + // This is a very ugly way of providing DataDescription, which anyway does not need to contain detector name. + // To be fixed once the names-definition class is ready + pc.outputs().snapshot(Output{mOrigin, "DIGITSROF", 0}, mDigROFRec); + pc.outputs().snapshot(Output{mOrigin, "DIGITS", 0}, mDigits); + if (mUseCalib) { + pc.outputs().snapshot(Output{mOrigin, "GBTCALIB", 0}, mCalib); + } + + if (mUseMC) { + auto& sharedlabels = pc.outputs().make>(Output{mOrigin, "DIGITSMCTR", 0}); + plabels->copyandflatten(sharedlabels); + delete plabels; + pc.outputs().snapshot(Output{mOrigin, "DIGITSMC2ROF", 0}, mDigMC2ROFs); + } + + if (mTree->GetReadEntry() + 1 >= mTree->GetEntries()) { + pc.services().get().endOfStream(); + pc.services().get().readyToQuit(QuitRequest::Me); + } +} + +void TF3DigitReader::connectTree(const std::string& filename) +{ + mTree.reset(nullptr); // in case it was already loaded + mFile.reset(TFile::Open(filename.c_str())); + assert(mFile && !mFile->IsZombie()); + mTree.reset((TTree*)mFile->Get(mDigTreeName.c_str())); + assert(mTree); + + mTree->SetBranchAddress(mDigROFBranchName.c_str(), &mDigROFRecPtr); + mTree->SetBranchAddress(mDigitBranchName.c_str(), &mDigitsPtr); + if (mUseCalib) { + if (!mTree->GetBranch(mCalibBranchName.c_str())) { + throw std::runtime_error("GBT calibration data requested but not found in the tree"); + } + mTree->SetBranchAddress(mCalibBranchName.c_str(), &mCalibPtr); + } + if (mUseMC) { + if (!mTree->GetBranch(mDigtMC2ROFBranchName.c_str()) || !mTree->GetBranch(mDigtMCTruthBranchName.c_str())) { + throw std::runtime_error("MC data requested but not found in the tree"); + } + mTree->SetBranchAddress(mDigtMC2ROFBranchName.c_str(), &mDigMC2ROFsPtr); + } + LOG(info) << "Loaded tree from " << filename << " with " << mTree->GetEntries() << " entries"; +} + +DataProcessorSpec getTRKDigitReaderSpec(bool useMC, bool useCalib, std::string defname) +{ + std::vector outputSpec; + outputSpec.emplace_back("TRK", "DIGITS", 0, Lifetime::Timeframe); + outputSpec.emplace_back("TRK", "DIGITSROF", 0, Lifetime::Timeframe); + if (useCalib) { + outputSpec.emplace_back("TRK", "GBTCALIB", 0, Lifetime::Timeframe); + } + if (useMC) { + outputSpec.emplace_back("TRK", "DIGITSMCTR", 0, Lifetime::Timeframe); + outputSpec.emplace_back("TRK", "DIGITSMC2ROF", 0, Lifetime::Timeframe); + } + + return DataProcessorSpec{ + "iotof-digit-reader", + Inputs{}, + outputSpec, + AlgorithmSpec{adaptFromTask(useMC, useCalib)}, + Options{ + {"iotof-digit-infile", VariantType::String, defname, {"Name of the input digit file"}}}}; +} + +} // namespace o2::iotof diff --git a/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitWriterSpec.cxx b/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitWriterSpec.cxx new file mode 100644 index 0000000000000..2a743551adddb --- /dev/null +++ b/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitWriterSpec.cxx @@ -0,0 +1,110 @@ +// 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. + +/// @brief Processor spec for a ROOT file writer for ITSMFT digits + +#include "TRKWorkflow/DigitWriterSpec.h" +#include "DPLUtils/MakeRootTreeWriterSpec.h" +#include "DataFormatsITSMFT/Digit.h" +#include "DataFormatsITSMFT/GBTCalibData.h" +#include "Headers/DataHeader.h" +#include "DetectorsCommonDataFormats/DetID.h" +#include "DataFormatsITSMFT/ROFRecord.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" +#include "SimulationDataFormat/IOMCTruthContainerView.h" +#include "SimulationDataFormat/MCCompLabel.h" +#include +#include +#include + +using namespace o2::framework; +using SubSpecificationType = o2::framework::DataAllocator::SubSpecificationType; + +namespace o2 +{ +namespace trk +{ + +template +using BranchDefinition = MakeRootTreeWriterSpec::BranchDefinition; +using MCCont = o2::dataformats::ConstMCTruthContainer; + +/// create the processor spec +/// describing a processor receiving digits for ITS/MFT and writing them to file +DataProcessorSpec getDigitWriterSpec(bool mctruth, bool dec, bool calib, o2::header::DataOrigin detOrig, o2::detectors::DetID detId) +{ + std::string detStr = o2::detectors::DetID::getName(detId); + std::string detStrL = dec ? "o2_" : ""; // for decoded digits prepend by o2 + detStrL += detStr; + std::transform(detStrL.begin(), detStrL.end(), detStrL.begin(), ::tolower); + auto logger = [](std::vector const& inDigits) { + LOG(info) << "RECEIVED DIGITS SIZE " << inDigits.size(); + }; + + // the callback to be set as hook for custom action when the writer is closed + auto finishWriting = [](TFile* outputfile, TTree* outputtree) { + const auto* brArr = outputtree->GetListOfBranches(); + int64_t nent = 0; + for (const auto* brc : *brArr) { + int64_t n = ((const TBranch*)brc)->GetEntries(); + if (nent && (nent != n)) { + LOG(error) << "Branches have different number of entries"; + } + nent = n; + } + outputtree->SetEntries(nent); + outputtree->Write("", TObject::kOverwrite); + outputfile->Close(); + }; + + // handler for labels + // This is necessary since we can't store the original label buffer in a ROOT entry -- as is -- if it exceeds a certain size. + // We therefore convert it to a special split class. + auto fillLabels = [](TBranch& branch, std::vector const& labelbuffer, DataRef const& /*ref*/) { + o2::dataformats::ConstMCTruthContainerView labels(labelbuffer); + LOG(info) << "WRITING " << labels.getNElements() << " LABELS "; + + o2::dataformats::IOMCTruthContainerView outputcontainer; + auto ptr = &outputcontainer; + auto br = framework::RootTreeWriter::remapBranch(branch, &ptr); + outputcontainer.adopt(labelbuffer); + br->Fill(); + br->ResetAddress(); + }; + + return MakeRootTreeWriterSpec((detStr + "DigitWriter" + (dec ? "_dec" : "")).c_str(), + (detStrL + "digits.root").c_str(), + MakeRootTreeWriterSpec::TreeAttributes{"o2sim", "Digits tree"}, + MakeRootTreeWriterSpec::CustomClose(finishWriting), + // in case of labels we first read them as std::vector and process them correctly in the fillLabels hook + BranchDefinition>{InputSpec{"digitsMCTR", detOrig, "DIGITSMCTR", 0}, + (detStr + "DigitMCTruth").c_str(), + (mctruth ? 1 : 0), fillLabels}, + BranchDefinition>{InputSpec{"digitsMC2ROF", detOrig, "DIGITSMC2ROF", 0}, + (detStr + "DigitMC2ROF").c_str(), + (mctruth ? 1 : 0)}, + BranchDefinition>{InputSpec{"digits", detOrig, "DIGITS", 0}, + (detStr + "Digit").c_str(), + logger}, + BranchDefinition>{InputSpec{"calib", detOrig, "GBTCALIB", 0}, + (detStr + "Calib").c_str(), + (calib ? 1 : 0)}, + BranchDefinition>{InputSpec{"digitsROF", detOrig, "DIGITSROF", 0}, + (detStr + "DigitROF").c_str()})(); +} + +DataProcessorSpec getTRKDigitWriterSpec(bool mctruth, bool dec, bool calib) +{ + return getDigitWriterSpec(mctruth, dec, calib, o2::header::gDataOriginTRK, o2::detectors::DetID::TRK); +} + +} // end namespace trk +} // end namespace o2 diff --git a/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/iotof-reco-workflow.cxx b/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/iotof-reco-workflow.cxx new file mode 100644 index 0000000000000..079b9670051d4 --- /dev/null +++ b/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/iotof-reco-workflow.cxx @@ -0,0 +1,82 @@ +// 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. + +// 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. + +// #include "TRKWorkflow/RecoWorkflow.h" +// #include "CommonUtils/ConfigurableParam.h" +// #include "ITStracking/TrackingConfigParam.h" +// #include "ITStracking/Configuration.h" + +#include "Framework/CallbacksPolicy.h" +#include "Framework/ConfigContext.h" +#include "Framework/CompletionPolicyHelpers.h" + +// #include + +using namespace o2::framework; + +void customize(std::vector& policies) +{ + // o2::raw::HBFUtilsInitializer::addNewTimeSliceCallback(policies); +} + +void customize(std::vector& policies) +{ + // ordered policies for the writers + policies.push_back(CompletionPolicyHelpers::consumeWhenAllOrdered(".*(?:TF3|iotof).*[W,w]riter.*")); +} + +void customize(std::vector& workflowOptions) +{ + // option allowing to set parameters + std::vector options{ + {"digits-from-upstream", VariantType::Bool, false, {"digits will be provided from upstream, skip digits reader"}}, + {"clusters-from-upstream", VariantType::Bool, false, {"clusters will be provided from upstream, skip clusterizer"}}, + {"disable-root-output", VariantType::Bool, false, {"do not write output root files"}}, + {"disable-mc", VariantType::Bool, false, {"disable MC propagation even if available"}}, + {"tracking-from-hits-config", VariantType::String, "", {"JSON file with tracking from hits configuration"}}, + {"disable-tracking", VariantType::Bool, false, {"disable tracking step"}}, + {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}, + {"use-gpu-workflow", VariantType::Bool, false, {"use GPU workflow (default: false)"}}, + {"gpu-device", VariantType::Int, 1, {"use gpu device: CPU=1,CUDA=2,HIP=3 (default: CPU)"}}}; + std::swap(workflowOptions, options); +} + +#include "Framework/runDataProcessing.h" +#include "Framework/Logger.h" + +o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& configcontext) +{ + // Update the (declared) parameters if changed from the command line + auto useMC = !configcontext.options().get("disable-mc"); + auto hitRecoConfig = configcontext.options().get("tracking-from-hits-config"); + auto useGpuWF = configcontext.options().get("use-gpu-workflow"); + auto gpuDevice = static_cast(configcontext.options().get("gpu-device")); + auto extDigits = configcontext.options().get("digits-from-upstream"); + auto extClusters = configcontext.options().get("clusters-from-upstream"); + auto disableRootOutput = configcontext.options().get("disable-root-output"); + o2::conf::ConfigurableParam::updateFromString(configcontext.options().get("configKeyValues")); + + // write the configuration used for the reco workflow + o2::conf::ConfigurableParam::writeINI("o2itsrecoflow_configuration.ini"); + + return o2::iotof::reco_workflow::getWorkflow(useMC, hitRecoConfig, extDigits, extClusters, disableRootOutput, useGpuWF, gpuDevice); +} diff --git a/Steer/DigitizerWorkflow/CMakeLists.txt b/Steer/DigitizerWorkflow/CMakeLists.txt index 10e8dc2b13995..3cbd05dd1d644 100644 --- a/Steer/DigitizerWorkflow/CMakeLists.txt +++ b/Steer/DigitizerWorkflow/CMakeLists.txt @@ -29,6 +29,7 @@ o2_add_executable(digitizer-workflow src/TOFDigitizerSpec.cxx $<$:src/ITS3DigitizerSpec.cxx> $<$:src/TRKDigitizerSpec.cxx> + $<$:src/IOTOFDigitizerSpec.cxx> PUBLIC_LINK_LIBRARIES O2::Framework O2::Steer O2::CommonConstants @@ -69,7 +70,10 @@ o2_add_executable(digitizer-workflow $<$:O2::ITS3Simulation> $<$:O2::ITS3Workflow> $<$:O2::TRKSimulation> - $<$:O2::TRKWorkflow>) + $<$:O2::TRKWorkflow> + $<$:O2::IOTOFSimulation> + # $<$:O2::IOTOFWorkflow> + ) o2_add_executable(mctruth-testworkflow diff --git a/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx new file mode 100644 index 0000000000000..96ad5823e3c1d --- /dev/null +++ b/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx @@ -0,0 +1,93 @@ +// 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. + +#include "IOTOFDigitizerSpec.h" +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/CCDBParamSpec.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/DataRefUtils.h" +#include "Framework/Lifetime.h" +#include "Framework/Task.h" +#include "Steer/HitProcessingManager.h" +#include "DataFormatsITSMFT/Digit.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" +#include "DetectorsBase/BaseDPLDigitizer.h" +#include "DetectorsRaw/HBFUtils.h" +#include "DetectorsCommonDataFormats/DetID.h" +#include "DetectorsCommonDataFormats/SimTraits.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsITSMFT/ROFRecord.h" +#include "IOTOFSimulation/Digitizer.h" +#include "Headers/DataHeader.h" + +#include +#include + +#include +#include +#include + +namespace o2::iotof +{ + +class IOTOFDPLDigitizerTask : o2::base::BaseDPLDigitizer +{ + public: + using BaseDPLDigitizer::init; + + IOTOFDPLDigitizerTask(bool mctruth = true) : BaseDPLDigitizer(o2::base::InitServices::FIELD | o2::base::InitServices::GEOM), + mWithMCTruth(mctruth) {} + + void initDigitizerTask(framework::InitContext& ic) override + { + } + + void run(framework::ProcessingContext& pc) + { + } + + private: + bool mWithMCTruth{true}; +}; + +std::vector makeOutChannels(o2::header::DataOrigin detOrig, bool mctruth) +{ + std::vector outputs; + for (uint32_t iLayer = 0; iLayer < 3; ++iLayer) { + outputs.emplace_back(detOrig, "DIGITS", iLayer, o2::framework::Lifetime::Timeframe); + outputs.emplace_back(detOrig, "DIGITSROF", iLayer, o2::framework::Lifetime::Timeframe); + if (mctruth) { + outputs.emplace_back(detOrig, "DIGITSMC2ROF", iLayer, o2::framework::Lifetime::Timeframe); + outputs.emplace_back(detOrig, "DIGITSMCTR", iLayer, o2::framework::Lifetime::Timeframe); + } + } + outputs.emplace_back(detOrig, "ROMode", 0, o2::framework::Lifetime::Timeframe); + return outputs; +} + +o2::framework::DataProcessorSpec getIOTOFDigitizerSpec(int channel, bool mctruth) +{ + std::vector inputs; + inputs.emplace_back("collisioncontext", "SIM", "COLLISIONCONTEXT", static_cast(channel), o2::framework::Lifetime::Timeframe); + inputs.emplace_back("IOTOF_aptsresp", "TF3", "APTSRESP", 0, o2::framework::Lifetime::Condition, o2::framework::ccdbParamSpec("IT3/Calib/APTSResponse")); + + const std::string detStr = o2::detectors::DetID::getName(o2::detectors::DetID::TF3); + return o2::framework::DataProcessorSpec{detStr + "Digitizer", + inputs, + makeOutChannels(o2::header::gDataOriginTF3, mctruth), + o2::framework::AlgorithmSpec{o2::framework::adaptFromTask(mctruth)}, + o2::framework::Options{ + {"disable-qed", o2::framework::VariantType::Bool, false, {"disable QED handling"}}, + {"local-response-file", o2::framework::VariantType::String, "", {"use response file saved locally at this path/filename"}}}}; +} + +} // namespace o2::iotof diff --git a/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.h b/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.h new file mode 100644 index 0000000000000..cebc698e4ec41 --- /dev/null +++ b/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.h @@ -0,0 +1,22 @@ +// 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. + +#ifndef STEER_DIGITIZERWORKFLOW_IOTOFDIGITIZER_H_ +#define STEER_DIGITIZERWORKFLOW_IOTOFDIGITIZER_H_ + +#include "Framework/DataProcessorSpec.h" + +namespace o2::iotof +{ +o2::framework::DataProcessorSpec getIOTOFDigitizerSpec(int channel, bool mctruth = true); +} // namespace o2::iotof + +#endif diff --git a/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx b/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx index 3b7bf3088a8f9..c9ec327b4ae73 100644 --- a/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx +++ b/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx @@ -665,6 +665,15 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) // connect the ALICE 3 TRK digit writer specs.emplace_back(o2::trk::getTRKDigitWriterSpec(mctruth)); } + + // the ALICE 3 IOTOF part + // if (isEnabled(o2::detectors::DetID::TF3)) { + // detList.emplace_back(o2::detectors::DetID::TF3); + // // connect the ALICE 3 IOTOF digitization + // specs.emplace_back(o2::iotof::getIOTOFDigitizerSpec(fanoutsize++, mctruth)); + // // connect the ALICE 3 IOTOF digit writer + // specs.emplace_back(o2::iotof::getIOTOFDigitWriterSpec(mctruth)); + // } #endif // the MFT part From dc9d98715fb3c95ce0a761a309817591cc81bb1e Mon Sep 17 00:00:00 2001 From: maciacco Date: Mon, 18 May 2026 15:48:38 +0200 Subject: [PATCH 02/16] fix digitizer workflow skeleton (use correct namespaces and tree columns) --- .../Upgrades/ALICE3/IOTOF/CMakeLists.txt | 2 +- .../IOTOFSimulation/DPLDigitizerParam.h | 14 +++++------ .../simulation/src/DPLDigitizerParam.cxx | 2 +- .../ALICE3/IOTOF/workflow/CMakeLists.txt | 16 +++++++------ .../include/IOTOFWorkflow/DigitReaderSpec.h | 4 +++- .../include/IOTOFWorkflow/DigitWriterSpec.h | 12 +++++----- .../IOTOF/workflow/src/DigitReaderSpec.cxx | 24 ++++++++++--------- .../IOTOF/workflow/src/DigitWriterSpec.cxx | 16 ++++++------- Steer/DigitizerWorkflow/CMakeLists.txt | 2 +- .../src/IOTOFDigitizerSpec.cxx | 1 + .../src/SimpleDigitizerWorkflow.cxx | 18 ++++++++------ 11 files changed, 61 insertions(+), 50 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/CMakeLists.txt b/Detectors/Upgrades/ALICE3/IOTOF/CMakeLists.txt index 587c11fdb04cc..a9964670a99c1 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/CMakeLists.txt +++ b/Detectors/Upgrades/ALICE3/IOTOF/CMakeLists.txt @@ -12,5 +12,5 @@ add_subdirectory(base) add_subdirectory(simulation) add_subdirectory(DataFormatsIOTOF) -# add_subdirectory(workflow) +add_subdirectory(workflow) add_subdirectory(macros) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h index db68b9670d272..5e4313a64dd5b 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h @@ -9,8 +9,8 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef ALICEO2_TRKDPLDIGITIZERPARAM_H_ -#define ALICEO2_TRKDPLDIGITIZERPARAM_H_ +#ifndef ALICEO2_TF3DPLDIGITIZERPARAM_H_ +#define ALICEO2_TF3DPLDIGITIZERPARAM_H_ #include "DetectorsCommonDataFormats/DetID.h" #include "CommonUtils/ConfigurableParam.h" @@ -19,7 +19,7 @@ namespace o2 { -namespace trk +namespace iotof { template struct DPLDigitizerParam : public o2::conf::ConfigurableParamHelper> { @@ -27,7 +27,7 @@ struct DPLDigitizerParam : public o2::conf::ConfigurableParamHelper DPLDigitizerParam DPLDigitizerParam::sInstance; -} // namespace trk +} // namespace iotof } // namespace o2 #endif diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/DPLDigitizerParam.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/DPLDigitizerParam.cxx index 3bb48a2b49fb6..c5fc19430174e 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/DPLDigitizerParam.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/DPLDigitizerParam.cxx @@ -17,6 +17,6 @@ namespace iotof { // this makes sure that the constructor of the parameters is statically called // so that these params are part of the parameter database -static auto& sDigitizerParamTF3 = o2::trk::DPLDigitizerParam::Instance(); +static auto& sDigitizerParamTF3 = o2::iotof::DPLDigitizerParam::Instance(); } // namespace iotof } // namespace o2 diff --git a/Detectors/Upgrades/ALICE3/IOTOF/workflow/CMakeLists.txt b/Detectors/Upgrades/ALICE3/IOTOF/workflow/CMakeLists.txt index 496b473427974..c0310603d915c 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/workflow/CMakeLists.txt +++ b/Detectors/Upgrades/ALICE3/IOTOF/workflow/CMakeLists.txt @@ -12,14 +12,16 @@ o2_add_library(IOTOFWorkflow TARGETVARNAME targetName SOURCES src/DigitReaderSpec.cxx - # src/DigitWriterSpec.cxx + src/DigitWriterSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DataFormatsIOTOF + O2::DataFormatsITSMFT + O2::DPLUtils ) -o2_add_executable(reco-workflow - SOURCES src/iotof-reco-workflow.cxx - COMPONENT_NAME alice3-iotof - PUBLIC_LINK_LIBRARIES O2::IOTOFWorkflow - O2::IOTOFSimulation - ) +#o2_add_executable(reco-workflow +# SOURCES src/iotof-reco-workflow.cxx +# COMPONENT_NAME alice3-iotof +# PUBLIC_LINK_LIBRARIES O2::IOTOFWorkflow +# O2::IOTOFSimulation +# ) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/DigitReaderSpec.h b/Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/DigitReaderSpec.h index 2a51639b931fc..1c56c1c1644af 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/DigitReaderSpec.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/DigitReaderSpec.h @@ -37,7 +37,9 @@ class TF3DigitReader : public o2::framework::Task void connectTree(const std::string& filename); std::vector mDigits, *mDigitsPtr = &mDigits; - o2::header::DataOrigin mOrigin = o2::header::gDataOriginInvalid; + std::vector*> mDigROFRec, *mDigROFRecPtr = &mDigROFRec; + std::vector*> mDigMC2ROFs, *mDigMC2ROFsPtr = &mDigMC2ROFs; + o2::header::DataOrigin mOrigin = o2::header::gDataOriginTF3; std::unique_ptr mFile; std::unique_ptr mTree; diff --git a/Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/DigitWriterSpec.h b/Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/DigitWriterSpec.h index 9c37d4318bb0f..7fff4fd000c2d 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/DigitWriterSpec.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/DigitWriterSpec.h @@ -9,18 +9,18 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef STEER_TRKDIGITWRITER_H_ -#define STEER_TRKDIGITWRITER_H_ +#ifndef STEER_TF3DIGITWRITER_H_ +#define STEER_TF3DIGITWRITER_H_ #include "Framework/DataProcessorSpec.h" namespace o2 { -namespace trk +namespace iotof { -o2::framework::DataProcessorSpec getTRKDigitWriterSpec(bool mctruth = true, bool dec = false, bool calib = false); -} // namespace trk +o2::framework::DataProcessorSpec getIOTOFDigitWriterSpec(bool mctruth = true, bool dec = false, bool calib = false); +} // namespace iotof } // end namespace o2 -#endif /* STEER_TRKDIGITWRITER_H_ */ +#endif /* STEER_TF3DIGITWRITER_H_ */ diff --git a/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitReaderSpec.cxx b/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitReaderSpec.cxx index 8ab51235d32b6..99582712ab090 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitReaderSpec.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitReaderSpec.cxx @@ -21,12 +21,14 @@ #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/IOMCTruthContainerView.h" +using namespace o2::framework; + namespace o2::iotof { TF3DigitReader::TF3DigitReader(o2::detectors::DetID id, bool useMC, bool useCalib) { - assert(id == o2::detectors::DetID::TRK); + assert(id == o2::detectors::DetID::TF3); mDetNameLC = mDetName = id.getName(); mDigTreeName = "o2sim"; @@ -66,7 +68,7 @@ void TF3DigitReader::run(o2::framework::ProcessingContext& pc) pc.outputs().snapshot(Output{mOrigin, "DIGITSROF", 0}, mDigROFRec); pc.outputs().snapshot(Output{mOrigin, "DIGITS", 0}, mDigits); if (mUseCalib) { - pc.outputs().snapshot(Output{mOrigin, "GBTCALIB", 0}, mCalib); + // pc.outputs().snapshot(Output{mOrigin, "GBTCALIB", 0}, mCalib); } if (mUseMC) { @@ -96,10 +98,10 @@ void TF3DigitReader::connectTree(const std::string& filename) if (!mTree->GetBranch(mCalibBranchName.c_str())) { throw std::runtime_error("GBT calibration data requested but not found in the tree"); } - mTree->SetBranchAddress(mCalibBranchName.c_str(), &mCalibPtr); + // mTree->SetBranchAddress(mCalibBranchName.c_str(), &mCalibPtr); } if (mUseMC) { - if (!mTree->GetBranch(mDigtMC2ROFBranchName.c_str()) || !mTree->GetBranch(mDigtMCTruthBranchName.c_str())) { + if (!mTree->GetBranch(mDigtMCTruthBranchName.c_str())) { throw std::runtime_error("MC data requested but not found in the tree"); } mTree->SetBranchAddress(mDigtMC2ROFBranchName.c_str(), &mDigMC2ROFsPtr); @@ -107,24 +109,24 @@ void TF3DigitReader::connectTree(const std::string& filename) LOG(info) << "Loaded tree from " << filename << " with " << mTree->GetEntries() << " entries"; } -DataProcessorSpec getTRKDigitReaderSpec(bool useMC, bool useCalib, std::string defname) +DataProcessorSpec getIOTOFDigitReaderSpec(bool useMC, bool useCalib, std::string defname) { std::vector outputSpec; - outputSpec.emplace_back("TRK", "DIGITS", 0, Lifetime::Timeframe); - outputSpec.emplace_back("TRK", "DIGITSROF", 0, Lifetime::Timeframe); + outputSpec.emplace_back("TF3", "DIGITS", 0, Lifetime::Timeframe); + outputSpec.emplace_back("TF3", "DIGITSROF", 0, Lifetime::Timeframe); if (useCalib) { - outputSpec.emplace_back("TRK", "GBTCALIB", 0, Lifetime::Timeframe); + // outputSpec.emplace_back("TF3", "GBTCALIB", 0, Lifetime::Timeframe); } if (useMC) { - outputSpec.emplace_back("TRK", "DIGITSMCTR", 0, Lifetime::Timeframe); - outputSpec.emplace_back("TRK", "DIGITSMC2ROF", 0, Lifetime::Timeframe); + outputSpec.emplace_back("TF3", "DIGITSMCTR", 0, Lifetime::Timeframe); + outputSpec.emplace_back("TF3", "DIGITSMC2ROF", 0, Lifetime::Timeframe); } return DataProcessorSpec{ "iotof-digit-reader", Inputs{}, outputSpec, - AlgorithmSpec{adaptFromTask(useMC, useCalib)}, + AlgorithmSpec{adaptFromTask(o2::detectors::DetID::TF3, useMC, useCalib)}, Options{ {"iotof-digit-infile", VariantType::String, defname, {"Name of the input digit file"}}}}; } diff --git a/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitWriterSpec.cxx b/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitWriterSpec.cxx index 2a743551adddb..e15352899c7dc 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitWriterSpec.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitWriterSpec.cxx @@ -11,7 +11,7 @@ /// @brief Processor spec for a ROOT file writer for ITSMFT digits -#include "TRKWorkflow/DigitWriterSpec.h" +#include "IOTOFWorkflow/DigitWriterSpec.h" #include "DPLUtils/MakeRootTreeWriterSpec.h" #include "DataFormatsITSMFT/Digit.h" #include "DataFormatsITSMFT/GBTCalibData.h" @@ -30,7 +30,7 @@ using SubSpecificationType = o2::framework::DataAllocator::SubSpecificationType; namespace o2 { -namespace trk +namespace iotof { template @@ -94,17 +94,17 @@ DataProcessorSpec getDigitWriterSpec(bool mctruth, bool dec, bool calib, o2::hea BranchDefinition>{InputSpec{"digits", detOrig, "DIGITS", 0}, (detStr + "Digit").c_str(), logger}, - BranchDefinition>{InputSpec{"calib", detOrig, "GBTCALIB", 0}, - (detStr + "Calib").c_str(), - (calib ? 1 : 0)}, + // BranchDefinition>{InputSpec{"calib", detOrig, "GBTCALIB", 0}, + // (detStr + "Calib").c_str(), + // (calib ? 1 : 0)}, BranchDefinition>{InputSpec{"digitsROF", detOrig, "DIGITSROF", 0}, (detStr + "DigitROF").c_str()})(); } -DataProcessorSpec getTRKDigitWriterSpec(bool mctruth, bool dec, bool calib) +DataProcessorSpec getIOTOFDigitWriterSpec(bool mctruth, bool dec, bool calib) { - return getDigitWriterSpec(mctruth, dec, calib, o2::header::gDataOriginTRK, o2::detectors::DetID::TRK); + return getDigitWriterSpec(mctruth, dec, calib, o2::header::gDataOriginTF3, o2::detectors::DetID::TF3); } -} // end namespace trk +} // end namespace iotof } // end namespace o2 diff --git a/Steer/DigitizerWorkflow/CMakeLists.txt b/Steer/DigitizerWorkflow/CMakeLists.txt index 3cbd05dd1d644..9a4ac7c7fb8f4 100644 --- a/Steer/DigitizerWorkflow/CMakeLists.txt +++ b/Steer/DigitizerWorkflow/CMakeLists.txt @@ -72,7 +72,7 @@ o2_add_executable(digitizer-workflow $<$:O2::TRKSimulation> $<$:O2::TRKWorkflow> $<$:O2::IOTOFSimulation> - # $<$:O2::IOTOFWorkflow> + $<$:O2::IOTOFWorkflow> ) diff --git a/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx index 96ad5823e3c1d..a7df0afa6c367 100644 --- a/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx @@ -53,6 +53,7 @@ class IOTOFDPLDigitizerTask : o2::base::BaseDPLDigitizer void run(framework::ProcessingContext& pc) { + LOG(info) << "Ciao"; } private: diff --git a/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx b/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx index c9ec327b4ae73..bcc9a4ecddc37 100644 --- a/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx +++ b/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx @@ -49,6 +49,10 @@ // for alice 3 TRK #include "TRKDigitizerSpec.h" #include "TRKWorkflow/DigitWriterSpec.h" + +// for alice 3 TF3 +#include "IOTOFDigitizerSpec.h" +#include "IOTOFWorkflow/DigitWriterSpec.h" #endif // for TOF @@ -667,13 +671,13 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) } // the ALICE 3 IOTOF part - // if (isEnabled(o2::detectors::DetID::TF3)) { - // detList.emplace_back(o2::detectors::DetID::TF3); - // // connect the ALICE 3 IOTOF digitization - // specs.emplace_back(o2::iotof::getIOTOFDigitizerSpec(fanoutsize++, mctruth)); - // // connect the ALICE 3 IOTOF digit writer - // specs.emplace_back(o2::iotof::getIOTOFDigitWriterSpec(mctruth)); - // } + if (isEnabled(o2::detectors::DetID::TF3)) { + detList.emplace_back(o2::detectors::DetID::TF3); + // connect the ALICE 3 IOTOF digitization + specs.emplace_back(o2::iotof::getIOTOFDigitizerSpec(fanoutsize++, mctruth)); + // connect the ALICE 3 IOTOF digit writer + specs.emplace_back(o2::iotof::getIOTOFDigitWriterSpec(mctruth)); + } #endif // the MFT part From 214815724d1511bed25ea6d4c8c3fdbdc0dc512d Mon Sep 17 00:00:00 2001 From: maciacco Date: Mon, 18 May 2026 17:10:22 +0200 Subject: [PATCH 03/16] fix issue in chip configuration (complex types cannot be used in configurables) + fix dictionary creation --- .../base/include/IOTOFBase/IOTOFBaseParam.h | 37 +++++++++++++++++-- .../ALICE3/IOTOF/base/src/IOTOFBaseParam.cxx | 4 +- .../simulation/src/IOTOFSimulationLinkDef.h | 11 ++++++ .../IOTOF/simulation/src/Segmentation.cxx | 7 ++-- 4 files changed, 52 insertions(+), 7 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h b/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h index c4cf5fd8844a8..6caca9514fa16 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h @@ -15,6 +15,7 @@ #include "CommonUtils/ConfigurableParam.h" #include "CommonUtils/ConfigurableParamHelper.h" + namespace o2 { namespace iotof @@ -38,6 +39,39 @@ struct ChipSpecifics { float SensorSizeRows() const { return ActiveMatrixSizeRows() + PassiveEdgeTop + PassiveEdgeReadOut; } }; +struct ITOFChipSpecifics : ChipSpecifics { + ITOFChipSpecifics() + { + NCols = 258; + NRows = 271; + PitchCol = 250.00e-4; + PitchRow = 100.00e-4; + SensorLayerThicknessEff = 50.e-4; + SensorLayerThickness = 50.e-4; + } +}; + +struct OTOFChipSpecifics : ChipSpecifics { + OTOFChipSpecifics() + { + NCols = 251; + NRows = 487; + PitchCol = 250.00e-4; + PitchRow = 100.00e-4; + PassiveEdgeSide = 106.48e-4; + SensorLayerThicknessEff = 50.e-4; + SensorLayerThickness = 50.e-4; + } +}; + +struct ITOFChipSpecificParam : public o2::conf::ConfigurableParamPromoter { + O2ParamDef(ITOFChipSpecificParam, "ITOFChipSpecific"); +}; + +struct OTOFChipSpecificParam : public o2::conf::ConfigurableParamPromoter { + O2ParamDef(OTOFChipSpecificParam, "OTOFChipSpecific"); +}; + struct IOTOFBaseParam : public o2::conf::ConfigurableParamHelper { bool enableInnerTOF = true; // Enable Inner TOF layer bool enableOuterTOF = true; // Enable Outer TOF layer @@ -49,9 +83,6 @@ struct IOTOFBaseParam : public o2::conf::ConfigurableParamHelper float x2x0 = 0.02f; // thickness expressed in radiation length, for all layers for the moment float sensorThickness = 0.0050f; // thickness of the sensor in cm, for all layers for the moment, the default is set to 50 microns - ChipSpecifics iTofChipSpecifics{258, 271, 250.00e-4, 100.00e-4, 0.00f, 0.00e-4, 0.00e-4, 50.e-4, 50.e-4}; - ChipSpecifics oTofChipSpecifics{251, 487, 250.00e-4, 100.00e-4, 0.00f, 0.00e-4, 106.48e-4, 50.e-4, 50.e-4}; - O2ParamDef(IOTOFBaseParam, "IOTOFBase"); }; diff --git a/Detectors/Upgrades/ALICE3/IOTOF/base/src/IOTOFBaseParam.cxx b/Detectors/Upgrades/ALICE3/IOTOF/base/src/IOTOFBaseParam.cxx index 22488b2cc9e14..f6799f41e3786 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/base/src/IOTOFBaseParam.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/base/src/IOTOFBaseParam.cxx @@ -11,4 +11,6 @@ #include "IOTOFBase/IOTOFBaseParam.h" -O2ParamImpl(o2::iotof::IOTOFBaseParam); \ No newline at end of file +O2ParamImpl(o2::iotof::IOTOFBaseParam); +O2ParamImpl(o2::iotof::ITOFChipSpecificParam); +O2ParamImpl(o2::iotof::OTOFChipSpecificParam); diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/IOTOFSimulationLinkDef.h b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/IOTOFSimulationLinkDef.h index f6f45ba5cda5f..96ed6fe04c846 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/IOTOFSimulationLinkDef.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/IOTOFSimulationLinkDef.h @@ -22,4 +22,15 @@ #pragma link C++ class o2::iotof::Detector + ; #pragma link C++ class o2::base::DetImpl < o2::iotof::Detector> + ; +#pragma link C++ class o2::iotof::DPLDigitizerParam < o2::detectors::DetID::TF3 > + ; +#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::iotof::DPLDigitizerParam < o2::detectors::DetID::TF3>> + ; + +#pragma link C++ class o2::iotof::ChipSpecifics + ; +#pragma link C++ class o2::iotof::ITOFChipSpecifics + ; +#pragma link C++ class o2::iotof::OTOFChipSpecifics + ; +#pragma link C++ class o2::iotof::ITOFChipSpecificParam + ; +#pragma link C++ class o2::conf::ConfigurableParamPromoter < o2::iotof::ITOFChipSpecificParam , o2::iotof::ITOFChipSpecifics > + ; +#pragma link C++ class o2::iotof::OTOFChipSpecificParam + ; +#pragma link C++ class o2::conf::ConfigurableParamPromoter < o2::iotof::OTOFChipSpecificParam , o2::iotof::OTOFChipSpecifics > + ; + #endif diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Segmentation.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Segmentation.cxx index bbfb60234210d..ea03b3d317cdc 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Segmentation.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Segmentation.cxx @@ -37,9 +37,10 @@ Segmentation::Segmentation() if (sInstance) { printf("Invalid use of public constructor: o2::iotof::Segmentation instance exists\n"); } else { - auto& iotofPars = IOTOFBaseParam::Instance(); - const ChipSpecifics& mITofChipPars = iotofPars.iTofChipSpecifics; - const ChipSpecifics& mOTofChipPars = iotofPars.oTofChipSpecifics; + auto& itofPars = ITOFChipSpecificParam::Instance(); + auto& otofPars = OTOFChipSpecificParam::Instance(); + const ChipSpecifics mITofChipPars(itofPars.NCols, itofPars.NRows, itofPars.PitchCol, itofPars.PitchRow, itofPars.PassiveEdgeReadOut, itofPars.PassiveEdgeTop, itofPars.PassiveEdgeSide, itofPars.SensorLayerThicknessEff, itofPars.SensorLayerThickness); + const ChipSpecifics mOTofChipPars(otofPars.NCols, otofPars.NRows, otofPars.PitchCol, otofPars.PitchRow, otofPars.PassiveEdgeReadOut, otofPars.PassiveEdgeTop, otofPars.PassiveEdgeSide, otofPars.SensorLayerThicknessEff, otofPars.SensorLayerThickness); configChip(mITofChipPars, 0 /* subDetectorID for iTOF */); configChip(mOTofChipPars, 1 /* subDetectorID for oTOF */); From 557b717423aeb46c5a9d984bee6b70a64c93109d Mon Sep 17 00:00:00 2001 From: maciacco Date: Mon, 18 May 2026 17:25:13 +0200 Subject: [PATCH 04/16] remove debug print --- Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx index a7df0afa6c367..96ad5823e3c1d 100644 --- a/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx @@ -53,7 +53,6 @@ class IOTOFDPLDigitizerTask : o2::base::BaseDPLDigitizer void run(framework::ProcessingContext& pc) { - LOG(info) << "Ciao"; } private: From 34e6113abe9a625c5a8bb13de0eece0e6fa0f34b Mon Sep 17 00:00:00 2001 From: maciacco Date: Mon, 18 May 2026 21:40:28 +0200 Subject: [PATCH 05/16] add first information to digitizer spec and test reader --- .../src/IOTOFDigitizerSpec.cxx | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx index 96ad5823e3c1d..b3d5ba417e35d 100644 --- a/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx @@ -36,6 +36,8 @@ #include #include +using namespace o2::framework; + namespace o2::iotof { @@ -49,14 +51,100 @@ class IOTOFDPLDigitizerTask : o2::base::BaseDPLDigitizer void initDigitizerTask(framework::InitContext& ic) override { + mDisableQED = ic.options().get("disable-qed"); + mDigits.resize(mLayers); + mROFRecords.resize(mLayers); + mROFRecordsAccum.resize(mLayers); + mLabels.resize(mLayers); + mLabelsAccum.resize(mLayers); } void run(framework::ProcessingContext& pc) { + if (mFinished) { + return; + } + mFirstOrbitTF = pc.services().get().firstTForbit; + const o2::InteractionRecord firstIR(0, mFirstOrbitTF); + + // read collision context from input + auto context = pc.inputs().get("collisioncontext"); + context->initSimChains(mID, mSimChains); + const bool withQED = context->isQEDProvided() && !mDisableQED; + auto& timesview = context->getEventRecords(); + LOG(info) << "GOT " << timesview.size() << " COLLISION TIMES"; + LOG(info) << "SIMCHAINS " << mSimChains.size(); + + // if there is nothing to do ... return + if (timesview.empty()) { + return; + } + + TStopwatch timer; + timer.Start(); + LOG(info) << " CALLING TF3 DIGITIZATION "; + + auto& eventParts = context->getEventParts(withQED); + uint64_t nDigits{0}; + for (uint32_t iLayer = 0; iLayer < static_cast(mLayers); ++iLayer) { + mDigits[iLayer].clear(); + // mROFRecords[iLayer].clear(); + // mROFRecordsAccum[iLayer].clear(); + if (mWithMCTruth) { + // mLabels[iLayer].clear(); + // mLabelsAccum[iLayer].clear(); + // mMC2ROFRecordsAccum[iLayer].clear(); + } + + mDigitizer.setDigits(&mDigits[iLayer]); + // mDigitizer.setROFRecords(&mROFRecords[iLayer]); + // mDigitizer.setMCLabels(&mLabels[iLayer]); + + for (int collID = 0; collID < timesview.size(); ++collID) { + for (const auto& part : eventParts[collID]) { + + // get the hits for this event and this source + mHits.clear(); + context->retrieveHits(mSimChains, o2::detectors::SimTraits::DETECTORBRANCHNAMES[mID][0].c_str(), part.sourceID, part.entryID, &mHits); + + if (mHits.size() > 0) { + LOG(debug) << "For collision " << collID << " eventID " << part.entryID << " found " << mHits.size() << " hits "; + // mDigitizer.process(&mHits, part.entryID, part.sourceID, layer); // call actual digitization procedure + } + } + } + + } + + timer.Stop(); + LOG(info) << "Digitization took " << timer.CpuTime() << "s"; + LOG(info) << "Produced " << nDigits << " digits"; + + // we should be only called once; tell DPL that this process is ready to exit + pc.services().get().readyToQuit(QuitRequest::Me); + + mFinished = true; } private: + bool mDisableQED = false; bool mWithMCTruth{true}; + bool mFinished{false}; + int mLayers{2}; + unsigned long mFirstOrbitTF = 0x0; + const o2::detectors::DetID mID{o2::detectors::DetID::TF3}; + const o2::header::DataOrigin mOrigin{o2::header::gDataOriginTF3}; + o2::iotof::Digitizer mDigitizer{}; + std::vector> mDigits{}; + std::vector> mROFRecords{}; + std::vector> mROFRecordsAccum{}; + std::vector mHits{}; + std::vector* mHitsP{&mHits}; + std::vector> mLabels{}; + std::vector> mLabelsAccum{}; + std::vector> mMC2ROFRecordsAccum{}; + std::vector mSimChains{}; + o2::parameters::GRPObject::ROMode mROMode = o2::parameters::GRPObject::PRESENT; // readout mode }; std::vector makeOutChannels(o2::header::DataOrigin detOrig, bool mctruth) From e85b558c53d585a586418ed864390a343aecf8a9 Mon Sep 17 00:00:00 2001 From: maciacco Date: Tue, 19 May 2026 11:47:29 +0200 Subject: [PATCH 06/16] add first element in workflow enabling digit processing --- .../src/IOTOFDigitizerSpec.cxx | 101 ++++++++++-------- 1 file changed, 59 insertions(+), 42 deletions(-) diff --git a/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx index b3d5ba417e35d..7932221151c53 100644 --- a/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx @@ -28,6 +28,7 @@ #include "DataFormatsITSMFT/ROFRecord.h" #include "IOTOFSimulation/Digitizer.h" #include "Headers/DataHeader.h" +#include "IOTOFBase/GeometryTGeo.h" #include #include @@ -52,11 +53,11 @@ class IOTOFDPLDigitizerTask : o2::base::BaseDPLDigitizer void initDigitizerTask(framework::InitContext& ic) override { mDisableQED = ic.options().get("disable-qed"); - mDigits.resize(mLayers); - mROFRecords.resize(mLayers); - mROFRecordsAccum.resize(mLayers); - mLabels.resize(mLayers); - mLabelsAccum.resize(mLayers); + auto geom = GeometryTGeo::Instance(); + geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)); // make sure L2G matrices are loaded + mDigitizer.setGeometry(geom); + mDigitizer.setChargeThreshold(-1000.f); + mDigitizer.init(); } void run(framework::ProcessingContext& pc) @@ -84,38 +85,60 @@ class IOTOFDPLDigitizerTask : o2::base::BaseDPLDigitizer timer.Start(); LOG(info) << " CALLING TF3 DIGITIZATION "; - auto& eventParts = context->getEventParts(withQED); uint64_t nDigits{0}; - for (uint32_t iLayer = 0; iLayer < static_cast(mLayers); ++iLayer) { - mDigits[iLayer].clear(); - // mROFRecords[iLayer].clear(); - // mROFRecordsAccum[iLayer].clear(); - if (mWithMCTruth) { - // mLabels[iLayer].clear(); - // mLabelsAccum[iLayer].clear(); - // mMC2ROFRecordsAccum[iLayer].clear(); - } - - mDigitizer.setDigits(&mDigits[iLayer]); - // mDigitizer.setROFRecords(&mROFRecords[iLayer]); - // mDigitizer.setMCLabels(&mLabels[iLayer]); - for (int collID = 0; collID < timesview.size(); ++collID) { - for (const auto& part : eventParts[collID]) { - - // get the hits for this event and this source - mHits.clear(); - context->retrieveHits(mSimChains, o2::detectors::SimTraits::DETECTORBRANCHNAMES[mID][0].c_str(), part.sourceID, part.entryID, &mHits); + mDigitizer.setDigits(&mDigits); + mDigitizer.setROFRecords(&mROFRecords); + if (mWithMCTruth) { + mDigitizer.setMCLabels(&mLabels); + } - if (mHits.size() > 0) { - LOG(debug) << "For collision " << collID << " eventID " << part.entryID << " found " << mHits.size() << " hits "; - // mDigitizer.process(&mHits, part.entryID, part.sourceID, layer); // call actual digitization procedure + auto& eventParts = context->getEventParts(withQED); + // loop over all composite collisions given from context + // (aka loop over all the interaction records) + // o2::InteractionTimeRecord firstorbit(o2::InteractionRecord(0, o2::raw::HBFUtils::Instance().orbitFirstSampled), 0.0); + for (int collID = 0; collID < timesview.size(); ++collID) { + o2::InteractionTimeRecord orbit(timesview[collID]); + // orbit += firstorbit + mDigitizer.setEventTime(orbit); + + // for each collision, loop over the constituents event and source IDs + // (background signal merging is basically taking place here) + for (const auto& part : eventParts[collID]) { + + // get the hits for this event and this source + mHits.clear(); + context->retrieveHits(mSimChains, o2::detectors::SimTraits::DETECTORBRANCHNAMES[mID][0].c_str(), part.sourceID, part.entryID, &mHits); + + if (mHits.size() > 0) { + mDigits.clear(); + if (mWithMCTruth) { + mLabels.clear(); } + + LOG(debug) << "For collision " << collID << " eventID " << part.entryID << " found " << mHits.size() << " hits "; + mDigitizer.process(&mHits, part.entryID, part.sourceID); // call actual digitization procedure } } + } + if (mDigitizer.isContinuous()) { + mDigits.clear(); + if (mWithMCTruth) { + mLabels.clear(); + } + mDigitizer.fillOutputContainer(); + } + // here we have all digits and we can send them to consumer (aka snapshot it onto output) + pc.outputs().snapshot(Output{mOrigin, "DIGITS", 0}, mDigits); + pc.outputs().snapshot(Output{mOrigin, "DIGITSROF"}, mROFRecords); + if (mWithMCTruth) { + // } + LOG(info) << mID.getName() << ": Sending ROMode= " << mROMode << " to GRPUpdater"; + pc.outputs().snapshot(Output{mOrigin, "ROMode", 0}, mROMode); + timer.Stop(); LOG(info) << "Digitization took " << timer.CpuTime() << "s"; LOG(info) << "Produced " << nDigits << " digits"; @@ -130,19 +153,15 @@ class IOTOFDPLDigitizerTask : o2::base::BaseDPLDigitizer bool mDisableQED = false; bool mWithMCTruth{true}; bool mFinished{false}; - int mLayers{2}; unsigned long mFirstOrbitTF = 0x0; const o2::detectors::DetID mID{o2::detectors::DetID::TF3}; const o2::header::DataOrigin mOrigin{o2::header::gDataOriginTF3}; o2::iotof::Digitizer mDigitizer{}; - std::vector> mDigits{}; - std::vector> mROFRecords{}; - std::vector> mROFRecordsAccum{}; + std::vector mDigits{}; + std::vector mROFRecords{}; std::vector mHits{}; std::vector* mHitsP{&mHits}; - std::vector> mLabels{}; - std::vector> mLabelsAccum{}; - std::vector> mMC2ROFRecordsAccum{}; + o2::dataformats::MCTruthContainer mLabels{}; std::vector mSimChains{}; o2::parameters::GRPObject::ROMode mROMode = o2::parameters::GRPObject::PRESENT; // readout mode }; @@ -150,13 +169,11 @@ class IOTOFDPLDigitizerTask : o2::base::BaseDPLDigitizer std::vector makeOutChannels(o2::header::DataOrigin detOrig, bool mctruth) { std::vector outputs; - for (uint32_t iLayer = 0; iLayer < 3; ++iLayer) { - outputs.emplace_back(detOrig, "DIGITS", iLayer, o2::framework::Lifetime::Timeframe); - outputs.emplace_back(detOrig, "DIGITSROF", iLayer, o2::framework::Lifetime::Timeframe); - if (mctruth) { - outputs.emplace_back(detOrig, "DIGITSMC2ROF", iLayer, o2::framework::Lifetime::Timeframe); - outputs.emplace_back(detOrig, "DIGITSMCTR", iLayer, o2::framework::Lifetime::Timeframe); - } + outputs.emplace_back(detOrig, "DIGITS", o2::framework::Lifetime::Timeframe); + outputs.emplace_back(detOrig, "DIGITSROF", o2::framework::Lifetime::Timeframe); + if (mctruth) { + outputs.emplace_back(detOrig, "DIGITSMC2ROF", o2::framework::Lifetime::Timeframe); + outputs.emplace_back(detOrig, "DIGITSMCTR", o2::framework::Lifetime::Timeframe); } outputs.emplace_back(detOrig, "ROMode", 0, o2::framework::Lifetime::Timeframe); return outputs; From 8c47460f6243e465919c0a2ad191acbc2b9c88e3 Mon Sep 17 00:00:00 2001 From: GiorgioAlbertoLucia Date: Fri, 22 May 2026 18:03:59 +0200 Subject: [PATCH 07/16] developing digitizer, added chips --- .../include/DataFormatsIOTOF/Digit.h | 5 ++++ .../base/include/IOTOFBase/GeometryTGeo.h | 4 +++ .../ALICE3/IOTOF/base/src/GeometryTGeo.cxx | 2 ++ .../ALICE3/IOTOF/simulation/src/Digitizer.cxx | 2 +- .../IOTOF/workflow/src/DigitWriterSpec.cxx | 25 ++++++++++--------- .../src/IOTOFDigitizerSpec.cxx | 20 +++++++++------ 6 files changed, 38 insertions(+), 20 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h b/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h index 19b5dc3bcd72b..a64049f16a73c 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h @@ -37,6 +37,11 @@ class Digit : public o2::itsmft::Digit // Getters double getTime() const { return mTime; } + static UInt_t getOrderingKey(UShort_t chipindex, UShort_t row, UShort_t col) + { + return (static_cast(chipindex) << 16) | (static_cast(row) << 8) | static_cast(col); + } + private: double mTime = 0.; ///< Measured time (ns) ClassDefNV(Digit, 1); diff --git a/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/GeometryTGeo.h b/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/GeometryTGeo.h index b998619684b28..af447007dd7e4 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/GeometryTGeo.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/GeometryTGeo.h @@ -33,6 +33,7 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache static const char* getIOTOFVolPattern() { return sIOTOFVolumeName.c_str(); } // Inner TOF + const int getITOFNumberOfChips() { return mNumberOfChipsIOTOF[0]; } static const char* getITOFLayerPattern() { return sITOFLayerName.c_str(); } static const char* getITOFStavePattern() { return sITOFStaveName.c_str(); } static const char* getITOFModulePattern() { return sITOFModuleName.c_str(); } @@ -40,6 +41,7 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache static const char* getITOFSensorPattern() { return sITOFSensorName.c_str(); } // Outer TOF + const int getOTOFNumberOfChips() { return mNumberOfChipsIOTOF[1]; } static const char* getOTOFLayerPattern() { return sOTOFLayerName.c_str(); } static const char* getOTOFStavePattern() { return sOTOFStaveName.c_str(); } static const char* getOTOFModulePattern() { return sOTOFModuleName.c_str(); } @@ -47,11 +49,13 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache static const char* getOTOFSensorPattern() { return sOTOFSensorName.c_str(); } // Forward TOF + const int getFTOFNumberOfChips() { return mNumberOfChipsFTOF; } static const char* getFTOFLayerPattern() { return sFTOFLayerName.c_str(); } static const char* getFTOFChipPattern() { return sFTOFChipName.c_str(); } static const char* getFTOFSensorPattern() { return sFTOFSensorName.c_str(); } // Backward TOF + const int getBTOFNumberOfChips() { return mNumberOfChipsBTOF; } static const char* getBTOFLayerPattern() { return sBTOFLayerName.c_str(); } static const char* getBTOFChipPattern() { return sBTOFChipName.c_str(); } static const char* getBTOFSensorPattern() { return sBTOFSensorName.c_str(); } diff --git a/Detectors/Upgrades/ALICE3/IOTOF/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/ALICE3/IOTOF/base/src/GeometryTGeo.cxx index eb209931207e3..e36da46d4c78e 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/base/src/GeometryTGeo.cxx @@ -273,6 +273,8 @@ void GeometryTGeo::fillMatrixCache(int mask) return; } + LOG(debug) << "Filling matrix cache for " << getName() << " with mask " << mask; + if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)) && !getCacheL2G().isFilled()) { // Matrices for Local (Sensor!!! rather than the full chip) to Global frame transformation LOG(info) << "Loading " << getName() << " L2G matrices from TGeo; there are " << mSize << " matrices"; diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx index 8e5e74dd1f0ca..2f708a85da75d 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx @@ -107,7 +107,7 @@ void Digitizer::processHit(const o2::itsmft::Hit& hit, int evID, int srcID) uint16_t chipIndex = static_cast(detID); if (detID > mGeometry->getSize() || mGeometry->getSize() < 1) { - LOG(debug) << "Invalid detector ID: " << detID; + LOG(debug) << "Invalid detector ID: " << detID << ", geometry size: " << mGeometry->getSize(); return; // invalid detector ID } const auto& matrix = mGeometry->getMatrixL2G(hit.GetDetectorID()); diff --git a/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitWriterSpec.cxx b/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitWriterSpec.cxx index e15352899c7dc..8d7bca00e78ff 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitWriterSpec.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitWriterSpec.cxx @@ -13,7 +13,7 @@ #include "IOTOFWorkflow/DigitWriterSpec.h" #include "DPLUtils/MakeRootTreeWriterSpec.h" -#include "DataFormatsITSMFT/Digit.h" +#include "DataFormatsIOTOF/Digit.h" #include "DataFormatsITSMFT/GBTCalibData.h" #include "Headers/DataHeader.h" #include "DetectorsCommonDataFormats/DetID.h" @@ -45,7 +45,7 @@ DataProcessorSpec getDigitWriterSpec(bool mctruth, bool dec, bool calib, o2::hea std::string detStrL = dec ? "o2_" : ""; // for decoded digits prepend by o2 detStrL += detStr; std::transform(detStrL.begin(), detStrL.end(), detStrL.begin(), ::tolower); - auto logger = [](std::vector const& inDigits) { + auto logger = [](std::vector const& inDigits) { LOG(info) << "RECEIVED DIGITS SIZE " << inDigits.size(); }; @@ -85,20 +85,21 @@ DataProcessorSpec getDigitWriterSpec(bool mctruth, bool dec, bool calib, o2::hea MakeRootTreeWriterSpec::TreeAttributes{"o2sim", "Digits tree"}, MakeRootTreeWriterSpec::CustomClose(finishWriting), // in case of labels we first read them as std::vector and process them correctly in the fillLabels hook - BranchDefinition>{InputSpec{"digitsMCTR", detOrig, "DIGITSMCTR", 0}, - (detStr + "DigitMCTruth").c_str(), - (mctruth ? 1 : 0), fillLabels}, - BranchDefinition>{InputSpec{"digitsMC2ROF", detOrig, "DIGITSMC2ROF", 0}, - (detStr + "DigitMC2ROF").c_str(), - (mctruth ? 1 : 0)}, - BranchDefinition>{InputSpec{"digits", detOrig, "DIGITS", 0}, + //BranchDefinition>{InputSpec{"digitsMCTR", detOrig, "DIGITSMCTR", 0}, + // (detStr + "DigitMCTruth").c_str(), + // (mctruth ? 1 : 0), fillLabels}, + //BranchDefinition>{InputSpec{"digitsMC2ROF", detOrig, "DIGITSMC2ROF", 0}, + // (detStr + "DigitMC2ROF").c_str(), + // (mctruth ? 1 : 0)}, + BranchDefinition>{InputSpec{"digits", detOrig, "DIGITS", 0}, (detStr + "Digit").c_str(), - logger}, + logger} //, // BranchDefinition>{InputSpec{"calib", detOrig, "GBTCALIB", 0}, // (detStr + "Calib").c_str(), // (calib ? 1 : 0)}, - BranchDefinition>{InputSpec{"digitsROF", detOrig, "DIGITSROF", 0}, - (detStr + "DigitROF").c_str()})(); + //BranchDefinition>{InputSpec{"digitsROF", detOrig, "DIGITSROF", 0}, + // (detStr + "DigitROF").c_str()} + )(); } DataProcessorSpec getIOTOFDigitWriterSpec(bool mctruth, bool dec, bool calib) diff --git a/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx index 7932221151c53..ab647d6b7618a 100644 --- a/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx @@ -29,6 +29,7 @@ #include "IOTOFSimulation/Digitizer.h" #include "Headers/DataHeader.h" #include "IOTOFBase/GeometryTGeo.h" +#include "IOTOFBase/IOTOFBaseParam.h" #include #include @@ -53,8 +54,10 @@ class IOTOFDPLDigitizerTask : o2::base::BaseDPLDigitizer void initDigitizerTask(framework::InitContext& ic) override { mDisableQED = ic.options().get("disable-qed"); + auto geom = GeometryTGeo::Instance(); geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)); // make sure L2G matrices are loaded + mDigitizer.setGeometry(geom); mDigitizer.setChargeThreshold(-1000.f); mDigitizer.init(); @@ -85,8 +88,6 @@ class IOTOFDPLDigitizerTask : o2::base::BaseDPLDigitizer timer.Start(); LOG(info) << " CALLING TF3 DIGITIZATION "; - uint64_t nDigits{0}; - mDigitizer.setDigits(&mDigits); mDigitizer.setROFRecords(&mROFRecords); if (mWithMCTruth) { @@ -111,7 +112,7 @@ class IOTOFDPLDigitizerTask : o2::base::BaseDPLDigitizer context->retrieveHits(mSimChains, o2::detectors::SimTraits::DETECTORBRANCHNAMES[mID][0].c_str(), part.sourceID, part.entryID, &mHits); if (mHits.size() > 0) { - mDigits.clear(); + //mDigits.clear(); if (mWithMCTruth) { mLabels.clear(); } @@ -122,26 +123,31 @@ class IOTOFDPLDigitizerTask : o2::base::BaseDPLDigitizer } } if (mDigitizer.isContinuous()) { - mDigits.clear(); + //mDigits.clear(); if (mWithMCTruth) { mLabels.clear(); } mDigitizer.fillOutputContainer(); } + for (int iDigit = 0; iDigit < mDigits.size(); iDigit++) { + mROFRecords.emplace_back(); + } + // here we have all digits and we can send them to consumer (aka snapshot it onto output) + + LOG(debug) << "Digitization finished with " << mDigits.size() << " digits and " << mROFRecords.size() << " ROF records"; pc.outputs().snapshot(Output{mOrigin, "DIGITS", 0}, mDigits); - pc.outputs().snapshot(Output{mOrigin, "DIGITSROF"}, mROFRecords); + //pc.outputs().snapshot(Output{mOrigin, "DIGITSROF", 0}, mROFRecords); if (mWithMCTruth) { // } LOG(info) << mID.getName() << ": Sending ROMode= " << mROMode << " to GRPUpdater"; - pc.outputs().snapshot(Output{mOrigin, "ROMode", 0}, mROMode); + //pc.outputs().snapshot(Output{mOrigin, "ROMode", 0}, mROMode); timer.Stop(); LOG(info) << "Digitization took " << timer.CpuTime() << "s"; - LOG(info) << "Produced " << nDigits << " digits"; // we should be only called once; tell DPL that this process is ready to exit pc.services().get().readyToQuit(QuitRequest::Me); From 71b45ac12a61047e477f02ffe949951cab804aa6 Mon Sep 17 00:00:00 2001 From: maciacco Date: Mon, 25 May 2026 17:34:16 +0200 Subject: [PATCH 08/16] remove default constructor + fix compilation of digit and vector --- .../IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h | 1 - .../IOTOF/DataFormatsIOTOF/src/DataFormatsIOTOFLinkDef.h | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h b/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h index a64049f16a73c..e865289184a00 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h @@ -26,7 +26,6 @@ namespace o2::iotof class Digit : public o2::itsmft::Digit { public: - Digit() = default; ~Digit() = default; Digit(UShort_t chipindex = 0, UShort_t row = 0, UShort_t col = 0, Int_t charge = 0, double time = 0.) : o2::itsmft::Digit(chipindex, row, col, charge), mTime(time) {}; diff --git a/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/src/DataFormatsIOTOFLinkDef.h b/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/src/DataFormatsIOTOFLinkDef.h index 8a167df4d6c7b..f4e2c6eb76445 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/src/DataFormatsIOTOFLinkDef.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/src/DataFormatsIOTOFLinkDef.h @@ -16,5 +16,6 @@ #pragma link off all functions; #pragma link C++ class o2::iotof::Digit + ; -// #pragma link C++ class std::vector < o2::iotof::Digit> + ; +#pragma link C++ class std::vector < o2::iotof::Digit> + ; + #endif From c2fb078ec73a735aa8acbd6a78b96dc37eec54e8 Mon Sep 17 00:00:00 2001 From: GiorgioAlbertoLucia Date: Tue, 26 May 2026 15:02:40 +0200 Subject: [PATCH 09/16] commit 1: all forseen branches available in the TF3 tree. Still preliminary approach to fill the Digits in the Digitizer class --- .../IOTOF/workflow/src/DigitWriterSpec.cxx | 17 ++++++------ .../src/IOTOFDigitizerSpec.cxx | 26 ++++++++----------- 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitWriterSpec.cxx b/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitWriterSpec.cxx index 8d7bca00e78ff..649495caed5df 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitWriterSpec.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitWriterSpec.cxx @@ -85,21 +85,20 @@ DataProcessorSpec getDigitWriterSpec(bool mctruth, bool dec, bool calib, o2::hea MakeRootTreeWriterSpec::TreeAttributes{"o2sim", "Digits tree"}, MakeRootTreeWriterSpec::CustomClose(finishWriting), // in case of labels we first read them as std::vector and process them correctly in the fillLabels hook - //BranchDefinition>{InputSpec{"digitsMCTR", detOrig, "DIGITSMCTR", 0}, + // BranchDefinition>{InputSpec{"digitsMCTR", detOrig, "DIGITSMCTR", 0}, // (detStr + "DigitMCTruth").c_str(), // (mctruth ? 1 : 0), fillLabels}, - //BranchDefinition>{InputSpec{"digitsMC2ROF", detOrig, "DIGITSMC2ROF", 0}, - // (detStr + "DigitMC2ROF").c_str(), - // (mctruth ? 1 : 0)}, + BranchDefinition>{InputSpec{"digitsMC2ROF", detOrig, "DIGITSMC2ROF", 0}, + (detStr + "DigitMC2ROF").c_str(), + (mctruth ? 1 : 0)}, BranchDefinition>{InputSpec{"digits", detOrig, "DIGITS", 0}, - (detStr + "Digit").c_str(), - logger} //, + (detStr + "Digit").c_str(), + logger}, // BranchDefinition>{InputSpec{"calib", detOrig, "GBTCALIB", 0}, // (detStr + "Calib").c_str(), // (calib ? 1 : 0)}, - //BranchDefinition>{InputSpec{"digitsROF", detOrig, "DIGITSROF", 0}, - // (detStr + "DigitROF").c_str()} - )(); + BranchDefinition>{InputSpec{"digitsROF", detOrig, "DIGITSROF", 0}, + (detStr + "DigitROF").c_str()})(); } DataProcessorSpec getIOTOFDigitWriterSpec(bool mctruth, bool dec, bool calib) diff --git a/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx index ab647d6b7618a..8b6a27319e25b 100644 --- a/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx @@ -54,7 +54,7 @@ class IOTOFDPLDigitizerTask : o2::base::BaseDPLDigitizer void initDigitizerTask(framework::InitContext& ic) override { mDisableQED = ic.options().get("disable-qed"); - + auto geom = GeometryTGeo::Instance(); geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)); // make sure L2G matrices are loaded @@ -112,9 +112,9 @@ class IOTOFDPLDigitizerTask : o2::base::BaseDPLDigitizer context->retrieveHits(mSimChains, o2::detectors::SimTraits::DETECTORBRANCHNAMES[mID][0].c_str(), part.sourceID, part.entryID, &mHits); if (mHits.size() > 0) { - //mDigits.clear(); + // mDigits.clear(); if (mWithMCTruth) { - mLabels.clear(); + // mLabels.clear(); } LOG(debug) << "For collision " << collID << " eventID " << part.entryID << " found " << mHits.size() << " hits "; @@ -123,29 +123,25 @@ class IOTOFDPLDigitizerTask : o2::base::BaseDPLDigitizer } } if (mDigitizer.isContinuous()) { - //mDigits.clear(); + // mDigits.clear(); if (mWithMCTruth) { - mLabels.clear(); + // mLabels.clear(); } mDigitizer.fillOutputContainer(); } - for (int iDigit = 0; iDigit < mDigits.size(); iDigit++) { - mROFRecords.emplace_back(); - } - // here we have all digits and we can send them to consumer (aka snapshot it onto output) - LOG(debug) << "Digitization finished with " << mDigits.size() << " digits and " << mROFRecords.size() << " ROF records"; pc.outputs().snapshot(Output{mOrigin, "DIGITS", 0}, mDigits); - //pc.outputs().snapshot(Output{mOrigin, "DIGITSROF", 0}, mROFRecords); + pc.outputs().snapshot(Output{mOrigin, "DIGITSROF", 0}, mROFRecords); if (mWithMCTruth) { - // + pc.outputs().make>(Output{mOrigin, "DIGITSMCTR", 0}); + // write dummy MC2ROF vector to keep writer/readers backward compatible + // NOTE: Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx also uses dummy MC2ROF + static std::vector dummyMC2ROF; + pc.outputs().snapshot(Output{mOrigin, "DIGITSMC2ROF", 0}, dummyMC2ROF); } - LOG(info) << mID.getName() << ": Sending ROMode= " << mROMode << " to GRPUpdater"; - //pc.outputs().snapshot(Output{mOrigin, "ROMode", 0}, mROMode); - timer.Stop(); LOG(info) << "Digitization took " << timer.CpuTime() << "s"; From 1a866c4f43ca2f80b4da92460e1d199281d8215a Mon Sep 17 00:00:00 2001 From: GiorgioAlbertoLucia Date: Tue, 26 May 2026 15:23:29 +0200 Subject: [PATCH 10/16] I forgor (one of the branches) --- .../ALICE3/IOTOF/workflow/src/DigitWriterSpec.cxx | 6 +++--- Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx | 8 +++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitWriterSpec.cxx b/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitWriterSpec.cxx index 649495caed5df..5a145e966781e 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitWriterSpec.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitWriterSpec.cxx @@ -85,9 +85,9 @@ DataProcessorSpec getDigitWriterSpec(bool mctruth, bool dec, bool calib, o2::hea MakeRootTreeWriterSpec::TreeAttributes{"o2sim", "Digits tree"}, MakeRootTreeWriterSpec::CustomClose(finishWriting), // in case of labels we first read them as std::vector and process them correctly in the fillLabels hook - // BranchDefinition>{InputSpec{"digitsMCTR", detOrig, "DIGITSMCTR", 0}, - // (detStr + "DigitMCTruth").c_str(), - // (mctruth ? 1 : 0), fillLabels}, + BranchDefinition>{InputSpec{"digitsMCTR", detOrig, "DIGITSMCTR", 0}, + (detStr + "DigitMCTruth").c_str(), + (mctruth ? 1 : 0), fillLabels}, BranchDefinition>{InputSpec{"digitsMC2ROF", detOrig, "DIGITSMC2ROF", 0}, (detStr + "DigitMC2ROF").c_str(), (mctruth ? 1 : 0)}, diff --git a/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx index 8b6a27319e25b..00e0d18691f04 100644 --- a/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx @@ -135,7 +135,12 @@ class IOTOFDPLDigitizerTask : o2::base::BaseDPLDigitizer pc.outputs().snapshot(Output{mOrigin, "DIGITS", 0}, mDigits); pc.outputs().snapshot(Output{mOrigin, "DIGITSROF", 0}, mROFRecords); if (mWithMCTruth) { - pc.outputs().make>(Output{mOrigin, "DIGITSMCTR", 0}); + auto& sharedlabels = pc.outputs().make>(Output{mOrigin, "DIGITSMCTR", 0}); + mLabelsAccum.flatten_to(sharedlabels); + // free space of existing label containers + mLabels.clear_andfreememory(); + mLabelsAccum.clear_andfreememory(); + // write dummy MC2ROF vector to keep writer/readers backward compatible // NOTE: Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx also uses dummy MC2ROF static std::vector dummyMC2ROF; @@ -164,6 +169,7 @@ class IOTOFDPLDigitizerTask : o2::base::BaseDPLDigitizer std::vector mHits{}; std::vector* mHitsP{&mHits}; o2::dataformats::MCTruthContainer mLabels{}; + o2::dataformats::MCTruthContainer mLabelsAccum{}; std::vector mSimChains{}; o2::parameters::GRPObject::ROMode mROMode = o2::parameters::GRPObject::PRESENT; // readout mode }; From fb06b06edfe4121efa96824ad36c4fb6c37cb6a2 Mon Sep 17 00:00:00 2001 From: maciacco Date: Wed, 27 May 2026 22:51:21 +0200 Subject: [PATCH 11/16] add tracking matrix cache --- .../base/include/IOTOFBase/GeometryTGeo.h | 28 ++++++++ .../ALICE3/IOTOF/base/src/GeometryTGeo.cxx | 71 ++++++++++++++++++- 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/GeometryTGeo.h b/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/GeometryTGeo.h index af447007dd7e4..8aaa9c5e31bb8 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/GeometryTGeo.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/GeometryTGeo.h @@ -23,6 +23,7 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache { public: using DetMatrixCache::getMatrixL2G; + using DetMatrixCache::getMatrixT2L; GeometryTGeo(bool build = false, int loadTrans = 0); void Build(int loadTrans); @@ -94,8 +95,31 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache /// for a given chip 'index' by querying the TGeoManager TGeoHMatrix* extractMatrixSensor(int index) const; + // sensor ref X and alpha + void extractSensorXAlpha(int, float&, float&); + + // create matrix for tracking to local frame for IOTOF + TGeoHMatrix& createT2LMatrix(int); + TString getMatrixPath(int index) const; + // cache for tracking frames + void defineSensors(); + bool isTrackingFrameCached() const { return !mCacheRefX.empty(); } + void fillTrackingFramesCache(); + + float getSensorRefAlpha(int chipId) const + { + const int local = chipId; + return mCacheRefAlpha[local]; + } + + float getSensorX(int chipId) const + { + const int local = chipId; + return mCacheRefX[local]; + } + protected: // Determine the number of active parts in the geometry int extractNumberOfStavesIOTOF(int lay) const; @@ -145,6 +169,10 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache // Backward TOF int mNumberOfChipsBTOF; + std::vector sensors; + std::vector mCacheRefX; /// cache for X of IOTOF + std::vector mCacheRefAlpha; /// cache for sensor ref alpha IOTOF + private: static std::unique_ptr sInstance; }; diff --git a/Detectors/Upgrades/ALICE3/IOTOF/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/ALICE3/IOTOF/base/src/GeometryTGeo.cxx index e36da46d4c78e..edaeb1e848d06 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/base/src/GeometryTGeo.cxx @@ -12,6 +12,7 @@ #include #include #include +#include namespace o2 { @@ -261,8 +262,31 @@ void GeometryTGeo::Build(int loadTrans) LOG(info) << "numberOfChipsITOF = " << mNumberOfChipsIOTOF[0] << ", numberOfChipsOTOF = " << mNumberOfChipsIOTOF[1] << ", numberOfChips = " << numberOfChips << ", mNumberOfChipesPerStaveITOF" << mNumberOfChipsPerStaveIOTOF[0]; setSize(numberOfChips); + defineSensors(); + fillTrackingFramesCache(); fillMatrixCache(loadTrans); - // fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)); +// fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)); +} + +void GeometryTGeo::defineSensors() +{ + for (int i = 0; i < mSize; i++) { + sensors.push_back(i); + } +} + +void GeometryTGeo::fillTrackingFramesCache() +{ + // fill for every sensor of IOTOF its tracking frame parameters + if (!isTrackingFrameCached() && !sensors.empty()) { + size_t newSize = sensors.size(); + mCacheRefX.resize(newSize); + mCacheRefAlpha.resize(newSize); + for (int i = 0; i < newSize; i++) { + int sensorId = sensors[i]; + extractSensorXAlpha(sensorId, mCacheRefX[i], mCacheRefAlpha[i]); + } + } } void GeometryTGeo::fillMatrixCache(int mask) @@ -286,6 +310,51 @@ void GeometryTGeo::fillMatrixCache(int mask) cacheL2G.setMatrix(o2::math_utils::Transform3D(*hm), i); } } + + // build T2L matrices for IOTOF + if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L)) && !getCacheT2L().isFilled()) { + LOGP(info, "Loading {} T2L matrices from TGeo for IOTOF", getName()); + if (sensors.size()) { + int m_Size = sensors.size(); + auto& cacheT2L = getCacheT2L(); + cacheT2L.setSize(m_Size); + for (int i = 0; i < m_Size; i++) { + int sensorID = sensors[i]; + TGeoHMatrix& hm = createT2LMatrix(sensorID); + cacheT2L.setMatrix(Mat3D(hm), i); + } + } + } +} + +void GeometryTGeo::extractSensorXAlpha(int chipID, float& x, float& alp) +{ + double locA[3] = {-100., 0., 0.}, locB[3] = {100., 0., 0.}, gloA[3], gloB[3]; + double xp{0}, yp{0}; + + const TGeoHMatrix* matL2G = extractMatrixSensor(chipID); + matL2G->LocalToMaster(locA, gloA); + matL2G->LocalToMaster(locB, gloB); + double dx = gloB[0] - gloA[0], dy = gloB[1] - gloA[1]; + double t = (gloB[0] * dx + gloB[1] * dy) / (dx * dx + dy * dy); + xp = gloB[0] - dx * t; + yp = gloB[1] - dy * t; + + alp = std::atan2(yp, xp); + x = std::hypot(xp, yp); + o2::math_utils::bringTo02Pi(alp); +} + +TGeoHMatrix& GeometryTGeo::createT2LMatrix(int chipID) +{ + static TGeoHMatrix t2l; + t2l.Clear(); + float alpha = getSensorRefAlpha(chipID); + t2l.RotateZ(alpha * TMath::RadToDeg()); + const TGeoHMatrix* matL2G = extractMatrixSensor(chipID); + const TGeoHMatrix& matL2Gi = matL2G->Inverse(); + t2l.MultiplyLeft(&matL2Gi); + return t2l; } GeometryTGeo* GeometryTGeo::Instance() From d800da6510e484ede876867e6852458d262e7bf7 Mon Sep 17 00:00:00 2001 From: GiorgioAlbertoLucia Date: Wed, 27 May 2026 19:03:40 +0200 Subject: [PATCH 12/16] commit 2: updated digitisation at the chip level (still need to figure out the proper way to clean up the extra digits) --- .../include/DataFormatsIOTOF/Digit.h | 27 +++- .../src/DataFormatsIOTOFLinkDef.h | 6 + .../ALICE3/IOTOF/simulation/CMakeLists.txt | 53 ++++---- .../simulation/include/IOTOFSimulation/Chip.h | 98 ++++++++++++++ .../include/IOTOFSimulation/Digitizer.h | 34 ++++- .../ALICE3/IOTOF/simulation/src/Chip.cxx | 39 ++++++ .../ALICE3/IOTOF/simulation/src/Digitizer.cxx | 124 ++++++++++++++---- .../simulation/src/IOTOFSimulationLinkDef.h | 7 +- .../src/IOTOFDigitizerSpec.cxx | 11 +- 9 files changed, 342 insertions(+), 57 deletions(-) create mode 100644 Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Chip.h create mode 100644 Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Chip.cxx diff --git a/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h b/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h index e865289184a00..1e526716972d5 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h @@ -19,6 +19,7 @@ #ifndef ALICEO2_IOTOF_DIGIT_H #define ALICEO2_IOTOF_DIGIT_H +#include "SimulationDataFormat/MCCompLabel.h" #include "DataFormatsITSMFT/Digit.h" namespace o2::iotof @@ -28,7 +29,7 @@ class Digit : public o2::itsmft::Digit public: ~Digit() = default; Digit(UShort_t chipindex = 0, UShort_t row = 0, UShort_t col = 0, Int_t charge = 0, double time = 0.) - : o2::itsmft::Digit(chipindex, row, col, charge), mTime(time) {}; + : o2::itsmft::Digit(chipindex, row, col, charge), mTime(time){}; // Setters void setTime(double time) { mTime = time; } @@ -46,5 +47,29 @@ class Digit : public o2::itsmft::Digit ClassDefNV(Digit, 1); }; +// McLabelRef is used to store the MC label of the hit contributing to a digit, and eventually link to extra contributions to the same pixel +struct McLabelRef { + o2::MCCompLabel mLabel; ///< hit label + int mNext = -1; ///< eventual next contribution to the same pixel + McLabelRef(o2::MCCompLabel label = 0, int next = -1) : mLabel(label), mNext(next) {} + + ClassDefNV(McLabelRef, 1); +}; + +class LabeledDigit : public Digit +{ + public: + LabeledDigit(UShort_t chipindex = 0, UShort_t row = 0, UShort_t col = 0, Int_t charge = 0, double time = 0., + o2::MCCompLabel label = 0) + : Digit(chipindex, row, col, charge, time), mLabel(label) {} + + void setLabel(McLabelRef label) { mLabel = label; } + McLabelRef getLabel() const { return mLabel; } + + private: + McLabelRef mLabel; ///< label of the hit contributing to the digit, and eventually reference to extra contributions to the same pixel + ClassDefNV(LabeledDigit, 1); +}; + } // namespace o2::iotof #endif // ALICEO2_IOTOF_DIGIT_H diff --git a/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/src/DataFormatsIOTOFLinkDef.h b/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/src/DataFormatsIOTOFLinkDef.h index f4e2c6eb76445..3f629289cf842 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/src/DataFormatsIOTOFLinkDef.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/src/DataFormatsIOTOFLinkDef.h @@ -18,4 +18,10 @@ #pragma link C++ class o2::iotof::Digit + ; #pragma link C++ class std::vector < o2::iotof::Digit> + ; +#pragma link C++ class o2::iotof::McLabelRef + ; +#pragma link C++ class std::vector < o2::iotof::McLabelRef> + ; + +#pragma link C++ class o2::iotof::LabeledDigit + ; +#pragma link C++ class std::vector < o2::iotof::LabeledDigit> + ; + #endif diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/CMakeLists.txt b/Detectors/Upgrades/ALICE3/IOTOF/simulation/CMakeLists.txt index ae9b0ed29e63d..e0dae7c563ad3 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/CMakeLists.txt +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/CMakeLists.txt @@ -1,30 +1,35 @@ -# 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. +#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". +#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 +#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. o2_add_library(IOTOFSimulation - SOURCES src/Layer.cxx - src/Detector.cxx - src/Digitizer.cxx - src/DPLDigitizerParam.cxx - # src/IOTOFServices.cxx - src/Segmentation.cxx - PUBLIC_LINK_LIBRARIES O2::IOTOFBase - O2::DataFormatsIOTOF - O2::ITSMFTSimulation) + SOURCES src / + Layer.cxx + src / + Chip.cxx + src / + Detector.cxx + src / + Digitizer.cxx + src / + DPLDigitizerParam.cxx +#src / IOTOFServices.cxx + src / + Segmentation.cxx + PUBLIC_LINK_LIBRARIES O2::IOTOFBase + O2::DataFormatsIOTOF + O2::ITSMFTSimulation) -o2_target_root_dictionary(IOTOFSimulation - HEADERS include/IOTOFSimulation/Detector.h - include/IOTOFSimulation/Layer.h - include/IOTOFSimulation/Digitizer.h - include/IOTOFSimulation/DPLDigitizerParam.h - # include/IOTOFSimulation/IOTOFServices.h - include/IOTOFSimulation/Segmentation.h - ) + o2_target_root_dictionary(IOTOFSimulation + HEADERS include / + IOTOFSimulation / Detector.h include / IOTOFSimulation / Chip.h include / IOTOFSimulation / Layer.h include / IOTOFSimulation / Digitizer.h include / IOTOFSimulation / DPLDigitizerParam.h +#include / IOTOFSimulation / IOTOFServices.h + include / + IOTOFSimulation / Segmentation.h) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Chip.h b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Chip.h new file mode 100644 index 0000000000000..43729682d06dc --- /dev/null +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Chip.h @@ -0,0 +1,98 @@ +// 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. + +// +// TOF Chip class: it will be used to store the digits at TOF that +// fall in the same Chip +// + +//////////////////////////////////// +// To put in O2/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/Chip.h + +#ifndef ALICEO2_IOTOF_CHIP_H_ +#define ALICEO2_IOTOF_CHIP_H_ + +#include +#include +#include +#include +#include +#include +#include "MathUtils/Cartesian.h" + +namespace o2::iotof +{ + +/// @class Chip +/// @brief Container for similated points connected to a given TOF Chip +/// This will be used in order to allow a more efficient clusterization +/// that can happen only between digits that belong to the same Chip +/// + +class Chip +{ + + public: + /// Default constructor + Chip() = default; + + /// Destructor + ~Chip() = default; + + /// Main constructor + /// @param Chipindex Index of the Chip + /// @param mat Transformation matrix + Chip(Int_t index); + + /// Copy constructor + /// @param ref Reference for the copy + Chip(const Chip& ref) = default; + + /// Empties the point container + /// @param option unused + void clear() { mDigits.clear(); } + + std::map& getDigits() { return mDigits; } + bool isEmpty() const { return mDigits.empty(); } + + void setChipIndex(Int_t index) { mChipIndex = index; } + Int_t getChipIndex() const { return mChipIndex; } + + void disable(bool disable) { mDisabled = disable; } + bool isDisabled() const { return mDisabled; } + + /// Get the number of point assigned to the chip + /// @return Number of points assigned to the chip + Int_t getNumberOfDigits() const { return mDigits.size(); } + + /// reset points container + o2::iotof::LabeledDigit* findDigit(ULong64_t key); + + void addDigit(UShort_t row, UShort_t col, Int_t charge, double time); + + protected: + Int_t mChipIndex = -1; ///< Chip ID + bool mDisabled = false; ///< Flag to indicate if the chip is disabled (e.g. due to dead channels) + std::map mDigits; ///< Map of fired digits, possibly in multiple frames + + ClassDefNV(Chip, 1); +}; + +inline o2::iotof::LabeledDigit* Chip::findDigit(ULong64_t key) +{ + // finds the digit corresponding to global key + auto digitentry = mDigits.find(key); + return digitentry != mDigits.end() ? &(digitentry->second) : nullptr; +} + +} // namespace o2::iotof + +#endif /* defined(ALICEO2_IOTOF_CHIP_H_) */ \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Digitizer.h b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Digitizer.h index aae989248f07e..a0c55f62eb3a4 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Digitizer.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Digitizer.h @@ -19,9 +19,16 @@ #ifndef ALICEO2_IOTOF_DIGITIZER_H #define ALICEO2_IOTOF_DIGITIZER_H +#include +#include +#include + +#include "Rtypes.h" // for Digitizer::Class +#include "TObject.h" // for TObject + #include "ITSMFTSimulation/Hit.h" -#include "DataFormatsITSMFT/Digit.h" #include "DataFormatsIOTOF/Digit.h" +#include "IOTOFSimulation/Chip.h" #include "DataFormatsITSMFT/ROFRecord.h" #include "CommonDataFormat/InteractionRecord.h" #include "SimulationDataFormat/MCCompLabel.h" @@ -40,7 +47,7 @@ namespace o2::iotof /// - Converting energy loss to charge /// - Applying charge threshold /// - Managing readout frames (ROF) -class Digitizer +class Digitizer : public TObject { public: void setDigits(std::vector* dig) { mDigits = dig; } @@ -81,6 +88,10 @@ class Digitizer /// Process a single hit void processHit(const o2::itsmft::Hit& hit, int evID, int srcID); + /// Register digits in a given chip + void registerDigits(Chip& chip, uint32_t roFrame, float timeInitROF, int nROF, + uint16_t row, uint16_t col, int nElectrons, o2::MCCompLabel& label); + /// Apply time smearing to simulate detector resolution double smearTime(double time) const; @@ -90,10 +101,27 @@ class Digitizer /// Check if the hit passes efficiency cut bool isEfficient() const; + std::vector* getExtraLabelBuffer(uint32_t roFrame) + { + // if (mROFrameMin > roFrame) { + // return nullptr; // nothing to do + // } + // int index = roFrame - mROFrameMin; + + int index = roFrame; + while (index >= int(mExtraLabelBuffer.size())) { + mExtraLabelBuffer.emplace_back(std::make_unique>()); + } + return mExtraLabelBuffer[index].get(); + } + static constexpr float sec2ns = 1e9f; ///< seconds to nanoseconds conversion const o2::iotof::GeometryTGeo* mGeometry = nullptr; ///< IOTOF geometry + std::vector mChips; //! Chips in the detector, indexed by chip ID + std::deque>> mExtraLabelBuffer; //! buffer for multiple mc labels to the same pixel + std::vector* mDigits = nullptr; //! output digits std::vector* mROFRecords = nullptr; //! output ROF records o2::dataformats::MCTruthContainer* mMCLabels = nullptr; //! output labels @@ -108,6 +136,8 @@ class Digitizer float mEnergyToCharge = 3.6e-9f; ///< energy loss to electrons conversion (3.6 eV per e-h pair in Si) static o2::iotof::Segmentation* sSegmentation; ///< IOTOF segmentation instance (singleton) + + ClassDefNV(Digitizer, 1); }; } // namespace o2::iotof diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Chip.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Chip.cxx new file mode 100644 index 0000000000000..3b737d35ac359 --- /dev/null +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Chip.cxx @@ -0,0 +1,39 @@ +// 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. + +// +// Chip.cxx: structure to store the TOF digits in Chips - useful +// for clusterization purposes +// ALICEO2 +// +#include +#include + +#include +#include + +#include "IOTOFSimulation/Chip.h" + +using namespace o2::iotof; + +ClassImp(o2::iotof::Chip); + +//_______________________________________________________________________ +Chip::Chip(Int_t index) + : mChipIndex(index) +{ +} +//_______________________________________________________________________ +void Chip::addDigit(UShort_t row, UShort_t col, Int_t charge, double time) +{ + ULong64_t key = Digit::getOrderingKey(mChipIndex, row, col); + mDigits.emplace(std::make_pair(key, LabeledDigit(mChipIndex, row, col, charge, time))); +} diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx index 2f708a85da75d..9e11e8e981ad4 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx @@ -34,6 +34,22 @@ o2::iotof::Segmentation* Digitizer::sSegmentation = nullptr; //_______________________________________________________________________ void Digitizer::init() { + const int numberOfChips = mGeometry->getSize(); + mChips.resize(numberOfChips); + for (int i = numberOfChips; i--;) { + mChips[i].setChipIndex(i); + /// Noise map to be implemented + /// if (mNoiseMap) { + /// mChips[i].setNoiseMap(mNoiseMap); + /// } + + /// Dead channel map to be implemented + /// if (mDeadChanMap) { + /// mChips[i].disable(mDeadChanMap->isFullChipMasked(i)); + /// mChips[i].setDeadChanMap(mDeadChanMap); + /// } + } + LOG(info) << "Initializing IOTOF digitizer"; LOG(info) << " Time resolution: " << mTimeResolution * 1e3 << " ps"; LOG(info) << " Charge threshold: " << mChargeThreshold << " electrons"; @@ -67,6 +83,7 @@ void Digitizer::process(const std::vector* hits, int evID, int // In triggered mode, flush output after each event if (!mContinuous) { + LOG(debug) << "Inner flushing for non-continuous mode"; fillOutputContainer(); } } @@ -83,7 +100,12 @@ void Digitizer::processHit(const o2::itsmft::Hit& hit, int evID, int srcID) } // Get detector element ID - int detID = hit.GetDetectorID(); + int chipID = hit.GetDetectorID(); + auto& chip = mChips[chipID]; + if (chip.isDisabled()) { + LOG(debug) << "Hit rejected because chip " << chipID << " is disabled"; + return; + } // Convert energy loss to charge (number of electrons) float energyLoss = hit.GetEnergyLoss(); // in GeV @@ -104,10 +126,10 @@ void Digitizer::processHit(const o2::itsmft::Hit& hit, int evID, int srcID) // For now, use simple row/col mapping from detector ID // TODO: Implement proper segmentation when geometry is finalized - uint16_t chipIndex = static_cast(detID); + uint16_t chipIndex = static_cast(chipID); - if (detID > mGeometry->getSize() || mGeometry->getSize() < 1) { - LOG(debug) << "Invalid detector ID: " << detID << ", geometry size: " << mGeometry->getSize(); + if (chipID > mGeometry->getSize() || mGeometry->getSize() < 1) { + LOG(debug) << "Invalid detector ID: " << chipID << ", geometry size: " << mGeometry->getSize(); return; // invalid detector ID } const auto& matrix = mGeometry->getMatrixL2G(hit.GetDetectorID()); @@ -118,23 +140,19 @@ void Digitizer::processHit(const o2::itsmft::Hit& hit, int evID, int srcID) int row = 0; // Will be determined from start hit position int col = 0; // Will be determined from start hit position - if (!sSegmentation->localToDetector(xyzPositionStart.X(), xyzPositionStart.Z(), row, col, mGeometry->getIOTOFLayer(detID))) { - LOG(debug) << "Hit position out of bounds for detector ID " << detID; + if (!sSegmentation->localToDetector(xyzPositionStart.X(), xyzPositionStart.Z(), row, col, mGeometry->getIOTOFLayer(chipID))) { + LOG(debug) << "Hit position out of bounds for detector ID " << chipID; return; // hit is outside the active area } // Create the digit with time information int digID = mDigits->size(); - mDigits->emplace_back(chipIndex, static_cast(row), static_cast(col), charge, smearedTime); - - LOG(debug) << "Created digit #" << digID << " chip=" << chipIndex - << " charge=" << charge << " time=" << smearedTime << " ns"; + o2::MCCompLabel label(hit.GetTrackID(), evID, srcID, false); + const int roFrameAbs = 0; // For now, we can set this to 0 or calculate based on time if needed + const int timeInitROF = 0; // For now, we can set this to 0 or calculate based on time if needed + const int nROF = 1; // For now, we can assume the signal is contained in one ROF, this can be extended to multiple ROFs based on the time - // Add MC truth label - if (mMCLabels) { - o2::MCCompLabel lbl(hit.GetTrackID(), evID, srcID, false); - mMCLabels->addElement(digID, lbl); - } + registerDigits(chip, roFrameAbs, timeInitROF, nROF, static_cast(row), static_cast(col), charge, label); } //_______________________________________________________________________ @@ -166,14 +184,74 @@ bool Digitizer::isEfficient() const //_______________________________________________________________________ void Digitizer::fillOutputContainer() { - // Create ROF record for the current event - if (mROFRecords && mDigits && !mDigits->empty()) { - o2::itsmft::ROFRecord rof; - rof.setFirstEntry(0); - rof.setNEntries(mDigits->size()); - rof.setBCData(mEventTime); - mROFRecords->push_back(rof); - LOG(debug) << "Created ROF record with " << mDigits->size() << " digits"; + LOG(info) << "Filling output container with digits from chips"; + LOG(debug) << "Number of chips: " << mChips.size(); + + o2::itsmft::ROFRecord rof; + rof.setFirstEntry(mDigits->size()); // index of the first digit + + auto& extraLabelBuffer = *(mExtraLabelBuffer.front().get()); // buffer for extra labels + for (auto& chip : mChips) { + + if (chip.isDisabled()) { + continue; + } + + /// chip.addNoise(...); // to be implemented + + if (chip.isEmpty()) { + continue; + } + + auto& chipDigits = chip.getDigits(); + for (const auto& [key, digit] : chipDigits) { + + /// Charge threshold not implemented yet + /// if (digit.getCharge() < mChargeThreshold) { + /// continue; // skip digits below threshold + /// } + + int digitID = mDigits->size(); + mDigits->emplace_back(digit.getChipIndex(), digit.getRow(), digit.getColumn(), digit.getCharge(), digit.getTime()); + mMCLabels->addElement(digitID, digit.getLabel().mLabel); + auto labelRef = digit.getLabel(); + + while (labelRef.mNext >= 0) { + labelRef = extraLabelBuffer[labelRef.mNext]; + mMCLabels->addElement(digitID, labelRef.mLabel); + } + } + chipDigits.clear(); // clear chip digits after copying to output + } + + rof.setNEntries(mDigits->size() - rof.getFirstEntry()); // number of digits + rof.setBCData(mEventTime); + mROFRecords->push_back(rof); + LOG(debug) << "Created ROF record with " << mDigits->size() << " digits"; + + // extraLabelBuffer.clear(); // clear buffer for extra labels + // mExtraLabelBuffer.emplace_back(mExtraLabelBuffer.front().release()); // move current buffer to the end + // mExtraLabelBuffer.pop_front(); +} + +void Digitizer::registerDigits(Chip& chip, uint32_t roFrame, float timeInitROF, int nROF, + uint16_t row, uint16_t col, int nElectrons, o2::MCCompLabel& label) +{ + + auto key = o2::iotof::Digit::getOrderingKey(roFrame, row, col); + o2::iotof::LabeledDigit* existingDigit = chip.findDigit(key); + if (!existingDigit) { + // No existing digit, create a new one + chip.addDigit(row, col, nElectrons, timeInitROF); // Last one should really just be time + } else { + // Digit already exists, update charge and labels + const int storedCharge = existingDigit->getCharge(); + existingDigit->setCharge(storedCharge + nElectrons); + if (existingDigit->getLabel().mLabel == label) { + return; // don't store the same label twice + } + std::vector* extra = getExtraLabelBuffer(roFrame); + extra->emplace_back(label); } } diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/IOTOFSimulationLinkDef.h b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/IOTOFSimulationLinkDef.h index 96ed6fe04c846..6d507e2c112c2 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/IOTOFSimulationLinkDef.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/IOTOFSimulationLinkDef.h @@ -22,15 +22,16 @@ #pragma link C++ class o2::iotof::Detector + ; #pragma link C++ class o2::base::DetImpl < o2::iotof::Detector> + ; -#pragma link C++ class o2::iotof::DPLDigitizerParam < o2::detectors::DetID::TF3 > + ; +#pragma link C++ class o2::iotof::Digitizer + ; +#pragma link C++ class o2::iotof::DPLDigitizerParam < o2::detectors::DetID::TF3> + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::iotof::DPLDigitizerParam < o2::detectors::DetID::TF3>> + ; #pragma link C++ class o2::iotof::ChipSpecifics + ; #pragma link C++ class o2::iotof::ITOFChipSpecifics + ; #pragma link C++ class o2::iotof::OTOFChipSpecifics + ; #pragma link C++ class o2::iotof::ITOFChipSpecificParam + ; -#pragma link C++ class o2::conf::ConfigurableParamPromoter < o2::iotof::ITOFChipSpecificParam , o2::iotof::ITOFChipSpecifics > + ; +#pragma link C++ class o2::conf::ConfigurableParamPromoter < o2::iotof::ITOFChipSpecificParam, o2::iotof::ITOFChipSpecifics> + ; #pragma link C++ class o2::iotof::OTOFChipSpecificParam + ; -#pragma link C++ class o2::conf::ConfigurableParamPromoter < o2::iotof::OTOFChipSpecificParam , o2::iotof::OTOFChipSpecifics > + ; +#pragma link C++ class o2::conf::ConfigurableParamPromoter < o2::iotof::OTOFChipSpecificParam, o2::iotof::OTOFChipSpecifics> + ; #endif diff --git a/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx index 00e0d18691f04..11dd371c1de04 100644 --- a/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/IOTOFDigitizerSpec.cxx @@ -112,9 +112,9 @@ class IOTOFDPLDigitizerTask : o2::base::BaseDPLDigitizer context->retrieveHits(mSimChains, o2::detectors::SimTraits::DETECTORBRANCHNAMES[mID][0].c_str(), part.sourceID, part.entryID, &mHits); if (mHits.size() > 0) { - // mDigits.clear(); + mDigits.clear(); if (mWithMCTruth) { - // mLabels.clear(); + mLabels.clear(); } LOG(debug) << "For collision " << collID << " eventID " << part.entryID << " found " << mHits.size() << " hits "; @@ -123,11 +123,14 @@ class IOTOFDPLDigitizerTask : o2::base::BaseDPLDigitizer } } if (mDigitizer.isContinuous()) { - // mDigits.clear(); + LOG(debug) << "Number of digits before final flush: " << mDigits.size(); + mDigits.clear(); if (mWithMCTruth) { - // mLabels.clear(); + mLabels.clear(); } + LOG(debug) << "Final flushing for continuous mode"; mDigitizer.fillOutputContainer(); + LOG(debug) << "Number of digits after final flush: " << mDigits.size(); } // here we have all digits and we can send them to consumer (aka snapshot it onto output) From f28379bc5b429255641da5f2bba4d40b272691dd Mon Sep 17 00:00:00 2001 From: Giorgio Alberto Lucia <87222843+GiorgioAlbertoLucia@users.noreply.github.com> Date: Thu, 28 May 2026 09:56:32 +0200 Subject: [PATCH 13/16] clang-format does not know how to handle CMakeLists apparently --- .../ALICE3/IOTOF/simulation/CMakeLists.txt | 40 +++++++++---------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/CMakeLists.txt b/Detectors/Upgrades/ALICE3/IOTOF/simulation/CMakeLists.txt index e0dae7c563ad3..63aaab105d9c7 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/CMakeLists.txt +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/CMakeLists.txt @@ -10,26 +10,22 @@ # or submit itself to any jurisdiction. o2_add_library(IOTOFSimulation - SOURCES src / - Layer.cxx - src / - Chip.cxx - src / - Detector.cxx - src / - Digitizer.cxx - src / - DPLDigitizerParam.cxx -#src / IOTOFServices.cxx - src / - Segmentation.cxx - PUBLIC_LINK_LIBRARIES O2::IOTOFBase - O2::DataFormatsIOTOF - O2::ITSMFTSimulation) + SOURCES src/Layer.cxx + src/Chip.cxx + src/Detector.cxx + src/Digitizer.cxx + src/DPLDigitizerParam.cxx + #src/IOTOFServices.cxx + src/Segmentation.cxx + PUBLIC_LINK_LIBRARIES O2::IOTOFBase + O2::DataFormatsIOTOF + O2::ITSMFTSimulation) - o2_target_root_dictionary(IOTOFSimulation - HEADERS include / - IOTOFSimulation / Detector.h include / IOTOFSimulation / Chip.h include / IOTOFSimulation / Layer.h include / IOTOFSimulation / Digitizer.h include / IOTOFSimulation / DPLDigitizerParam.h -#include / IOTOFSimulation / IOTOFServices.h - include / - IOTOFSimulation / Segmentation.h) +o2_target_root_dictionary(IOTOFSimulation + HEADERS include/IOTOFSimulation/Detector.h + include/IOTOFSimulation/Chip.h + include/IOTOFSimulation/Layer.h + include/IOTOFSimulation/Digitizer.h + include/IOTOFSimulation/DPLDigitizerParam.h + #include/IOTOFSimulation/IOTOFServices.h + include/IOTOFSimulation/Segmentation.h) From 51c194e57591500453bdecbc473cd1fce4cee868 Mon Sep 17 00:00:00 2001 From: maciacco Date: Thu, 28 May 2026 12:14:29 +0200 Subject: [PATCH 14/16] add first skeleton of reco workflow for iotof --- .../ALICE3/IOTOF/workflow/CMakeLists.txt | 13 +++--- .../include/IOTOFWorkflow/RecoWorkflow.h | 32 ++++++++++++++ .../IOTOF/workflow/src/RecoWorkflow.cxx | 43 +++++++++++++++++++ .../workflow/src/iotof-reco-workflow.cxx | 25 +++++------ 4 files changed, 95 insertions(+), 18 deletions(-) create mode 100644 Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/RecoWorkflow.h create mode 100644 Detectors/Upgrades/ALICE3/IOTOF/workflow/src/RecoWorkflow.cxx diff --git a/Detectors/Upgrades/ALICE3/IOTOF/workflow/CMakeLists.txt b/Detectors/Upgrades/ALICE3/IOTOF/workflow/CMakeLists.txt index c0310603d915c..73ae6edd15cf4 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/workflow/CMakeLists.txt +++ b/Detectors/Upgrades/ALICE3/IOTOF/workflow/CMakeLists.txt @@ -13,15 +13,16 @@ o2_add_library(IOTOFWorkflow TARGETVARNAME targetName SOURCES src/DigitReaderSpec.cxx src/DigitWriterSpec.cxx + src/RecoWorkflow.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DataFormatsIOTOF O2::DataFormatsITSMFT O2::DPLUtils ) -#o2_add_executable(reco-workflow -# SOURCES src/iotof-reco-workflow.cxx -# COMPONENT_NAME alice3-iotof -# PUBLIC_LINK_LIBRARIES O2::IOTOFWorkflow -# O2::IOTOFSimulation -# ) +o2_add_executable(reco-workflow + SOURCES src/iotof-reco-workflow.cxx + COMPONENT_NAME alice3-iotof + PUBLIC_LINK_LIBRARIES O2::IOTOFWorkflow + O2::IOTOFSimulation + ) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/RecoWorkflow.h b/Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/RecoWorkflow.h new file mode 100644 index 0000000000000..6310ec6348a8e --- /dev/null +++ b/Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/RecoWorkflow.h @@ -0,0 +1,32 @@ +// 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. + +#ifndef O2_TF3_RECOWORKFLOW_H +#define O2_TF3_RECOWORKFLOW_H + +#include "Framework/WorkflowSpec.h" +#include + +namespace o2::iotof +{ +namespace reco_workflow +{ + +o2::framework::WorkflowSpec getWorkflow(bool useMC, + // const std::string& hitRecoConfig, + bool upstreamDigits = false, + bool upstreamClusters = false, + bool disableRootOutput = false); +} + +} // namespace o2::iotof + +#endif diff --git a/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/RecoWorkflow.cxx b/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/RecoWorkflow.cxx new file mode 100644 index 0000000000000..b9be173842d7d --- /dev/null +++ b/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/RecoWorkflow.cxx @@ -0,0 +1,43 @@ +// 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. + +#include "IOTOFWorkflow/RecoWorkflow.h" +#include "IOTOFWorkflow/DigitReaderSpec.h" +#include "Framework/CCDBParamSpec.h" + +#include + +namespace o2::iotof::reco_workflow +{ + +framework::WorkflowSpec getWorkflow(bool useMC, + // const std::string& hitRecoConfig, + bool upstreamDigits, + bool upstreamClusters, + bool disableRootOutput) +{ + framework::WorkflowSpec specs; + + if (!(upstreamDigits || upstreamClusters)) { + specs.emplace_back(o2::iotof::getIOTOFDigitReaderSpec(useMC, false, "tf3digits.root")); + } + if (!upstreamClusters) { + // specs.emplace_back(o2::iotof::getClustererSpec(useMC)); + } + + if (!disableRootOutput) { + // specs.emplace_back(o2::iotof::getClusterWriterSpec(useMC)); + } + + return specs; +} + +} // namespace o2::iotof::reco_workflow diff --git a/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/iotof-reco-workflow.cxx b/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/iotof-reco-workflow.cxx index 079b9670051d4..ef0f48d4c2099 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/iotof-reco-workflow.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/iotof-reco-workflow.cxx @@ -20,8 +20,8 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -// #include "TRKWorkflow/RecoWorkflow.h" -// #include "CommonUtils/ConfigurableParam.h" +#include "IOTOFWorkflow/RecoWorkflow.h" +#include "CommonUtils/ConfigurableParam.h" // #include "ITStracking/TrackingConfigParam.h" // #include "ITStracking/Configuration.h" @@ -29,7 +29,7 @@ #include "Framework/ConfigContext.h" #include "Framework/CompletionPolicyHelpers.h" -// #include +#include using namespace o2::framework; @@ -52,11 +52,12 @@ void customize(std::vector& workflowOptions) {"clusters-from-upstream", VariantType::Bool, false, {"clusters will be provided from upstream, skip clusterizer"}}, {"disable-root-output", VariantType::Bool, false, {"do not write output root files"}}, {"disable-mc", VariantType::Bool, false, {"disable MC propagation even if available"}}, - {"tracking-from-hits-config", VariantType::String, "", {"JSON file with tracking from hits configuration"}}, - {"disable-tracking", VariantType::Bool, false, {"disable tracking step"}}, - {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}, - {"use-gpu-workflow", VariantType::Bool, false, {"use GPU workflow (default: false)"}}, - {"gpu-device", VariantType::Int, 1, {"use gpu device: CPU=1,CUDA=2,HIP=3 (default: CPU)"}}}; + // {"tracking-from-hits-config", VariantType::String, "", {"JSON file with tracking from hits configuration"}}, + // {"disable-tracking", VariantType::Bool, false, {"disable tracking step"}}, + {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}} //, + // {"use-gpu-workflow", VariantType::Bool, false, {"use GPU workflow (default: false)"}}, + // {"gpu-device", VariantType::Int, 1, {"use gpu device: CPU=1,CUDA=2,HIP=3 (default: CPU)"}} + }; std::swap(workflowOptions, options); } @@ -67,9 +68,9 @@ o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext co { // Update the (declared) parameters if changed from the command line auto useMC = !configcontext.options().get("disable-mc"); - auto hitRecoConfig = configcontext.options().get("tracking-from-hits-config"); - auto useGpuWF = configcontext.options().get("use-gpu-workflow"); - auto gpuDevice = static_cast(configcontext.options().get("gpu-device")); + // auto hitRecoConfig = configcontext.options().get("tracking-from-hits-config"); + // auto useGpuWF = configcontext.options().get("use-gpu-workflow"); + // auto gpuDevice = static_cast(configcontext.options().get("gpu-device")); auto extDigits = configcontext.options().get("digits-from-upstream"); auto extClusters = configcontext.options().get("clusters-from-upstream"); auto disableRootOutput = configcontext.options().get("disable-root-output"); @@ -78,5 +79,5 @@ o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext co // write the configuration used for the reco workflow o2::conf::ConfigurableParam::writeINI("o2itsrecoflow_configuration.ini"); - return o2::iotof::reco_workflow::getWorkflow(useMC, hitRecoConfig, extDigits, extClusters, disableRootOutput, useGpuWF, gpuDevice); + return o2::iotof::reco_workflow::getWorkflow(useMC, /*hitRecoConfig,*/ extDigits, extClusters, disableRootOutput/*, useGpuWF, gpuDevice*/); } From 4cd9b20ab3df6f62ac4347d50ca51783233c1a4d Mon Sep 17 00:00:00 2001 From: maciacco Date: Wed, 3 Jun 2026 19:39:19 +0200 Subject: [PATCH 15/16] update segmentation parameters for updated geometry specs --- .../ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h b/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h index 6caca9514fa16..dc0d793f4410a 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h @@ -54,8 +54,8 @@ struct ITOFChipSpecifics : ChipSpecifics { struct OTOFChipSpecifics : ChipSpecifics { OTOFChipSpecifics() { - NCols = 251; - NRows = 487; + NCols = 517; + NRows = 243; PitchCol = 250.00e-4; PitchRow = 100.00e-4; PassiveEdgeSide = 106.48e-4; From 0410c47e301d8142c2305ad2a3a5ed77aedc017e Mon Sep 17 00:00:00 2001 From: maciacco Date: Thu, 4 Jun 2026 11:57:55 +0200 Subject: [PATCH 16/16] fix input name in digit reader + fix the branch types --- .../IOTOF/workflow/include/IOTOFWorkflow/DigitReaderSpec.h | 4 ++-- .../Upgrades/ALICE3/IOTOF/workflow/src/DigitReaderSpec.cxx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/DigitReaderSpec.h b/Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/DigitReaderSpec.h index 1c56c1c1644af..1309bfc711d23 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/DigitReaderSpec.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/workflow/include/IOTOFWorkflow/DigitReaderSpec.h @@ -37,8 +37,8 @@ class TF3DigitReader : public o2::framework::Task void connectTree(const std::string& filename); std::vector mDigits, *mDigitsPtr = &mDigits; - std::vector*> mDigROFRec, *mDigROFRecPtr = &mDigROFRec; - std::vector*> mDigMC2ROFs, *mDigMC2ROFsPtr = &mDigMC2ROFs; + std::vector mDigROFRec, *mDigROFRecPtr = &mDigROFRec; + std::vector mDigMC2ROFs, *mDigMC2ROFsPtr = &mDigMC2ROFs; o2::header::DataOrigin mOrigin = o2::header::gDataOriginTF3; std::unique_ptr mFile; diff --git a/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitReaderSpec.cxx b/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitReaderSpec.cxx index 99582712ab090..9ff4213a951b8 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitReaderSpec.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/workflow/src/DigitReaderSpec.cxx @@ -128,7 +128,7 @@ DataProcessorSpec getIOTOFDigitReaderSpec(bool useMC, bool useCalib, std::string outputSpec, AlgorithmSpec{adaptFromTask(o2::detectors::DetID::TF3, useMC, useCalib)}, Options{ - {"iotof-digit-infile", VariantType::String, defname, {"Name of the input digit file"}}}}; + {"tf3-digit-infile", VariantType::String, defname, {"Name of the input digit file"}}}}; } } // namespace o2::iotof