-
Notifications
You must be signed in to change notification settings - Fork 490
[EMCAL-732] implementation of EMCAL standalone AOD producer workflow #7644
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
80daf9b
8ff2446
b230a92
dfb4870
f25d6ae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| // Copyright 2019-2020 CERN and copyright holders of ALICE O2. | ||
| // See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. | ||
| // All rights not expressly granted are reserved. | ||
| // | ||
| // This software is distributed under the terms of the GNU General Public | ||
| // License v3 (GPL Version 3), copied verbatim in the file "COPYING". | ||
| // | ||
| // In applying this license CERN does not waive the privileges and immunities | ||
| // granted to it by virtue of its status as an Intergovernmental Organization | ||
| // or submit itself to any jurisdiction. | ||
|
|
||
| /// @file StandaloneAODProducerSpec.h | ||
| /// @brief Convert CTF (EncodedBlocks) to AO2D EMCal standalone | ||
|
|
||
| #ifndef O2_EMCAL_STANDALONEAODPRODUCERSPEC_SPEC | ||
| #define O2_EMCAL_STANDALONEAODPRODUCERSPEC_SPEC | ||
|
|
||
| #include "Framework/AnalysisDataModel.h" | ||
| #include "Framework/AnalysisHelpers.h" | ||
| #include "Framework/DataProcessorSpec.h" | ||
| #include "Framework/Task.h" | ||
| #include "DataFormatsEMCAL/EventHandler.h" | ||
| #include <TStopwatch.h> | ||
|
|
||
| namespace o2 | ||
| { | ||
| namespace emcal | ||
| { | ||
|
|
||
| class StandaloneAODProducerSpec : public o2::framework::Task | ||
| { | ||
| public: | ||
| StandaloneAODProducerSpec(); | ||
| ~StandaloneAODProducerSpec() override = default; | ||
| void run(o2::framework::ProcessingContext& pc) final; | ||
| void init(o2::framework::InitContext& ic) final; | ||
| void endOfStream(o2::framework::EndOfStreamContext& ec) final; | ||
|
|
||
| static const char* getCellBinding() { return "EMCCells"; } | ||
| static const char* getCellTriggerRecordBinding() { return "EMCCellsTrgR"; } | ||
|
|
||
| private: | ||
| int64_t mTFNumber = -1; // Timeframe ID | ||
| int mRunNumber = -1; // Run number | ||
| uint32_t mCaloAmp = 0xFFFFFF00; // 15 bits | ||
| uint32_t mCaloTime = 0xFFFFFF00; // 15 bits | ||
| o2::emcal::EventHandler<o2::emcal::Cell>* mCaloEventHandler = nullptr; ///< Pointer to the event builder for emcal cells | ||
| TStopwatch mTimer; | ||
|
|
||
| static const char* BININGCELLS; | ||
| static const char* BINDINGCELLSTRG; | ||
| }; | ||
|
|
||
| /// create a processor spec | ||
| framework::DataProcessorSpec getStandaloneAODProducerSpec(); | ||
|
|
||
| } // namespace emcal | ||
| } // namespace o2 | ||
|
|
||
| #endif | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,171 @@ | ||
| // 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 "EMCALWorkflow/StandaloneAODProducerSpec.h" | ||
| #include "Framework/TableBuilder.h" | ||
| #include "Framework/AnalysisDataModel.h" | ||
| #include "Framework/ConfigParamRegistry.h" | ||
| #include "Framework/DataTypes.h" | ||
| #include "Framework/InputRecordWalker.h" | ||
| #include "Framework/Logger.h" | ||
| #include "Framework/TableBuilder.h" | ||
| #include "Framework/TableTreeHelpers.h" | ||
| #include "MathUtils/Utils.h" | ||
|
|
||
| using namespace o2::framework; | ||
|
|
||
| namespace o2 | ||
| { | ||
| namespace emcal | ||
| { | ||
|
|
||
| StandaloneAODProducerSpec::StandaloneAODProducerSpec() | ||
| { | ||
| mTimer.Stop(); | ||
| mTimer.Reset(); | ||
| } | ||
|
|
||
| void StandaloneAODProducerSpec::init(o2::framework::InitContext& ic) | ||
| { | ||
| mCaloEventHandler = new o2::emcal::EventHandler<o2::emcal::Cell>(); | ||
| mCaloAmp = 0xFFFFFFFF; | ||
| mCaloTime = 0xFFFFFFFF; | ||
|
|
||
| mTFNumber = ic.options().get<int64_t>("aod-timeframe-id"); | ||
| mRunNumber = ic.options().get<int>("run-number"); | ||
| } | ||
|
|
||
| void StandaloneAODProducerSpec::run(ProcessingContext& pc) | ||
| { | ||
| auto cput = mTimer.CpuTime(); | ||
| mTimer.Start(false); | ||
|
|
||
| const auto* dh = o2::header::get<o2::header::DataHeader*>(pc.inputs().getFirstValid(true).header); | ||
| uint64_t tfNumber; | ||
| if (mTFNumber == -1L) { | ||
| // TODO has to be made globally unique (by using absolute time of TF). For now is unique within the run | ||
| tfNumber = uint64_t(dh->firstTForbit) + (uint64_t(dh->runNumber) << 32); // getTFNumber(mStartIR, runNumber); | ||
| } else { | ||
| tfNumber = mTFNumber; | ||
| } | ||
| const int runNumber = (mRunNumber == -1) ? int(dh->runNumber) : mRunNumber; | ||
|
|
||
| auto cellsIn = pc.inputs().get<gsl::span<o2::emcal::Cell>>(getCellBinding()); | ||
| auto triggersIn = pc.inputs().get<gsl::span<o2::emcal::TriggerRecord>>(getCellTriggerRecordBinding()); | ||
|
|
||
| LOG(INFO) << "FOUND " << cellsIn.size() << " EMC cells in CTF"; | ||
| LOG(INFO) << "FOUND " << triggersIn.size() << " EMC tiggers in CTF"; | ||
|
|
||
| auto& bcBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "BC"}); | ||
| auto& collisionsBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "COLLISION"}); | ||
| auto& caloCellsBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "CALO"}); | ||
| auto& caloCellsTRGTableBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "CALOTRIGGER"}); | ||
|
|
||
| auto bcCursor = bcBuilder.cursor<o2::aod::BCs>(); | ||
| auto collisionsCursor = collisionsBuilder.cursor<o2::aod::Collisions>(); | ||
| auto caloCellsCursor = caloCellsBuilder.cursor<o2::aod::Calos>(); | ||
| auto caloCellsTRGTableCursor = caloCellsTRGTableBuilder.cursor<o2::aod::CaloTriggers>(); | ||
|
|
||
| // build event for easier handling | ||
| mCaloEventHandler->reset(); | ||
| mCaloEventHandler->setCellData(cellsIn, triggersIn); | ||
|
|
||
| uint64_t triggerMask = 1; | ||
| // loop over events | ||
| for (int iev = 0; iev < mCaloEventHandler->getNumberOfEvents(); iev++) { | ||
| o2::emcal::EventData inputEvent = mCaloEventHandler->buildEvent(iev); | ||
| auto cellsInEvent = inputEvent.mCells; // get cells belonging to current event | ||
| auto interactionRecord = inputEvent.mInteractionRecord; // get interaction records belonging to current event | ||
|
|
||
| LOG(INFO) << "Found " << cellsInEvent.size() << " cells in event"; | ||
|
|
||
| auto bcID = interactionRecord.toLong(); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is wrong. You have to fill into the tables the tree entry of the BC entry in the BC tree. You get this with
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| bcCursor(0, | ||
| runNumber, | ||
| bcID, | ||
| triggerMask); | ||
| auto indexBC = iev; | ||
|
|
||
| for (auto& cell : cellsInEvent) { | ||
|
|
||
| // fill table | ||
| caloCellsCursor(0, | ||
| indexBC, | ||
| cell.getTower(), | ||
| o2::math_utils::detail::truncateFloatFraction(cell.getAmplitude(), mCaloAmp), | ||
| o2::math_utils::detail::truncateFloatFraction(cell.getTimeStamp(), mCaloTime), | ||
| cell.getType(), | ||
| 1); // hard coded for emcal (-1 would be undefined, 0 phos) | ||
| } // end of cell loop | ||
|
|
||
| // filled only with BCID, rest dummy for no2 | ||
| caloCellsTRGTableCursor(0, | ||
| indexBC, | ||
| 0, // fastOrAbsId (dummy value) | ||
| 0., // lnAmplitude (dummy value) | ||
| 0, // triggerBits (dummy value) | ||
| 1); // caloType (dummy value) | ||
|
|
||
| // fill collision cursor | ||
| collisionsCursor(0, | ||
| indexBC, | ||
| 0., // X-Pos dummy value | ||
| 0., // Y Pos | ||
| 0., // Z Pos | ||
| 0, // cov 0 | ||
| 0, // cov 1 | ||
| 0, // cov 2 | ||
| 0, // cov 3 | ||
| 0, // cov 4 | ||
| 0, // cov 5 | ||
| 0, // vertex bit field for flags | ||
| 0, // chi2 | ||
| 0, // ncontributors | ||
| 0, // rel interaction time | ||
| 0); // vertex time stamp | ||
|
|
||
| } // end of event loop | ||
| // std::cout << "Finished cell loop" << std::endl; | ||
|
|
||
| pc.outputs().snapshot(Output{"TFN", "TFNumber", 0, Lifetime::Timeframe}, tfNumber); | ||
|
|
||
| mTimer.Stop(); | ||
| } | ||
|
|
||
| void StandaloneAODProducerSpec::endOfStream(EndOfStreamContext& ec) | ||
| { | ||
| LOGF(INFO, "EMCAL Standalone AOD Producer total timing: Cpu: %.3e Real: %.3e s in %d slots", | ||
| mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); | ||
| } | ||
|
|
||
| DataProcessorSpec getStandaloneAODProducerSpec() | ||
| { | ||
| std::vector<OutputSpec> outputs; | ||
| outputs.emplace_back(OutputLabel{"O2bc"}, "AOD", "BC", 0, Lifetime::Timeframe); | ||
| outputs.emplace_back(OutputLabel{"O2collision"}, "AOD", "COLLISION", 0, Lifetime::Timeframe); | ||
| outputs.emplace_back(OutputLabel{"O2caloCell"}, "AOD", "CALO", 0, Lifetime::Timeframe); | ||
| outputs.emplace_back(OutputLabel{"O2caloCellTRGR"}, "AOD", "CALOTRIGGER", 0, Lifetime::Timeframe); | ||
| outputs.emplace_back(OutputSpec{"TFN", "TFNumber"}); | ||
|
|
||
| return DataProcessorSpec{ | ||
| "standalone-aod-producer-workflow", | ||
| Inputs{ | ||
| InputSpec{StandaloneAODProducerSpec::getCellTriggerRecordBinding(), "EMC", "CELLSTRGR", 0, Lifetime::Timeframe}, | ||
| InputSpec{StandaloneAODProducerSpec::getCellBinding(), "EMC", "CELLS", 0, Lifetime::Timeframe}}, | ||
| outputs, | ||
| AlgorithmSpec{adaptFromTask<StandaloneAODProducerSpec>()}, | ||
| Options{ | ||
| ConfigParamSpec{"run-number", VariantType::Int64, -1L, {"The run-number. If left default we try to get it from DPL header."}}, | ||
| ConfigParamSpec{"aod-timeframe-id", VariantType::Int64, -1L, {"Set timeframe number"}}}}; | ||
| } | ||
|
|
||
| } // namespace emcal | ||
| } // namespace o2 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| // Copyright 2019-2020 CERN and copyright holders of ALICE O2. | ||
| // See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. | ||
| // All rights not expressly granted are reserved. | ||
| // | ||
| // This software is distributed under the terms of the GNU General Public | ||
| // License v3 (GPL Version 3), copied verbatim in the file "COPYING". | ||
| // | ||
| // In applying this license CERN does not waive the privileges and immunities | ||
| // granted to it by virtue of its status as an Intergovernmental Organization | ||
| // or submit itself to any jurisdiction. | ||
|
|
||
| /// @file standalone-aod-producer-workflow.cxx | ||
| /// @author Florian Jonas | ||
| /// @since 2021-11-09 | ||
| /// @brief Conversion from CTF data -> AO2D standalone for EMCal (does not require other detectors like AODProducerWorklfow) | ||
|
|
||
| #include "EMCALWorkflow/StandaloneAODProducerSpec.h" | ||
| #include "CommonUtils/ConfigurableParam.h" | ||
| #include "Framework/ConfigParamSpec.h" | ||
|
|
||
| using namespace o2::framework; | ||
|
|
||
| // ------------------------------------------------------------------ | ||
|
|
||
| // we need to add workflow options before including Framework/runDataProcessing | ||
| void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) | ||
| { | ||
| // option allowing to set parameters | ||
| std::vector<ConfigParamSpec> options{ConfigParamSpec{"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}}; | ||
|
|
||
| std::swap(workflowOptions, options); | ||
| } | ||
|
|
||
| // ------------------------------------------------------------------ | ||
|
|
||
| #include "Framework/runDataProcessing.h" | ||
|
|
||
| WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) | ||
| { | ||
| WorkflowSpec wf; | ||
| // Update the (declared) parameters if changed from the command line | ||
| o2::conf::ConfigurableParam::updateFromString(cfgc.options().get<std::string>("configKeyValues")); | ||
| wf.emplace_back(o2::emcal::getStandaloneAODProducerSpec()); | ||
| return wf; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No longer needed.