Skip to content

Commit f8f221c

Browse files
shahor02sawenzel
authored andcommitted
ITS/MFT cluster reader DPL device
1 parent 2a651da commit f8f221c

5 files changed

Lines changed: 335 additions & 0 deletions

File tree

Detectors/ITSMFT/common/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
add_subdirectory(base)
1818
add_subdirectory(simulation)
1919
add_subdirectory(reconstruction)
20+
add_subdirectory(workflow)
2021

2122
install(
2223
DIRECTORY data
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
set(MODULE_NAME "ITSMFTWorkflow")
2+
set(MODULE_BUCKET_NAME ITSMFT_workflow_bucket)
3+
4+
O2_SETUP(NAME ${MODULE_NAME})
5+
6+
set(SRCS
7+
src/ClusterReaderSpec.cxx
8+
)
9+
10+
set(LIBRARY_NAME ${MODULE_NAME})
11+
set(BUCKET_NAME ${MODULE_BUCKET_NAME})
12+
13+
O2_GENERATE_LIBRARY()
14+
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Copyright CERN and copyright holders of ALICE O2. This software is
2+
// distributed under the terms of the GNU General Public License v3 (GPL
3+
// Version 3), copied verbatim in the file "COPYING".
4+
//
5+
// See http://alice-o2.web.cern.ch/license for full licensing information.
6+
//
7+
// In applying this license CERN does not waive the privileges and immunities
8+
// granted to it by virtue of its status as an Intergovernmental Organization
9+
// or submit itself to any jurisdiction.
10+
11+
/// @file ClusterReaderSpec.h
12+
13+
#ifndef O2_ITSMFT_CLUSTERREADER
14+
#define O2_ITSMFT_CLUSTERREADER
15+
16+
#include "TFile.h"
17+
18+
#include "Framework/DataProcessorSpec.h"
19+
#include "Framework/Task.h"
20+
#include "Headers/DataHeader.h"
21+
#include "DataFormatsITSMFT/CompCluster.h"
22+
#include "DataFormatsITSMFT/Cluster.h"
23+
#include "SimulationDataFormat/MCCompLabel.h"
24+
#include "SimulationDataFormat/MCTruthContainer.h"
25+
#include "DataFormatsITSMFT/ROFRecord.h"
26+
27+
using namespace o2::framework;
28+
29+
namespace o2
30+
{
31+
namespace itsmft
32+
{
33+
34+
class ClusterReader : public Task
35+
{
36+
public:
37+
ClusterReader() = delete;
38+
ClusterReader(o2::detectors::DetID id, bool useMC = true, bool useClFull = true, bool useClComp = true);
39+
~ClusterReader() override = default;
40+
void init(InitContext& ic) final;
41+
void run(ProcessingContext& pc) final;
42+
43+
protected:
44+
void accumulate();
45+
46+
std::vector<o2::itsmft::ROFRecord>*mClusROFRecInp = nullptr, mClusROFRecOut;
47+
std::vector<o2::itsmft::Cluster>*mClusterArrayInp = nullptr, mClusterArrayOut;
48+
std::vector<o2::itsmft::CompClusterExt>*mClusterCompArrayInp = nullptr, mClusterCompArrayOut;
49+
o2::dataformats::MCTruthContainer<o2::MCCompLabel>*mClusterMCTruthInp = nullptr, mClusterMCTruthOut;
50+
51+
o2::header::DataOrigin mOrigin = o2::header::gDataOriginInvalid;
52+
53+
bool mFinished = false;
54+
55+
bool mUseMC = true; // use MC truth
56+
bool mUseClFull = true; // use full clusters
57+
bool mUseClComp = true; // use compact clusters
58+
59+
std::string mDetName = "";
60+
std::string mDetNameLC = "";
61+
std::string mInputFileName = "";
62+
63+
std::string mClusTreeName = "o2sim";
64+
std::string mClusROFTreeName = "ClustersROF";
65+
std::string mClusterBranchName = "Cluster";
66+
std::string mClusterCompBranchName = "ClusterComp";
67+
std::string mClustMCTruthBranchName = "ClusterMCTruth";
68+
};
69+
70+
class ITSClusterReader : public ClusterReader
71+
{
72+
public:
73+
ITSClusterReader(bool useMC = true, bool useClFull = true, bool useClComp = true)
74+
: ClusterReader(o2::detectors::DetID::ITS, useMC, useClFull, useClComp)
75+
{
76+
mOrigin = o2::header::gDataOriginITS;
77+
}
78+
};
79+
80+
class MFTClusterReader : public ClusterReader
81+
{
82+
public:
83+
MFTClusterReader(bool useMC = true, bool useClFull = true, bool useClComp = true)
84+
: ClusterReader(o2::detectors::DetID::MFT, useMC, useClFull, useClComp)
85+
{
86+
mOrigin = o2::header::gDataOriginMFT;
87+
}
88+
};
89+
90+
/// create a processor spec
91+
/// read ITS/MFT cluster data from a root file
92+
framework::DataProcessorSpec getITSClusterReaderSpec(bool useMC = true, bool useClFull = true, bool useClComp = true);
93+
framework::DataProcessorSpec getMFTClusterReaderSpec(bool useMC = true, bool useClFull = true, bool useClComp = true);
94+
95+
} // namespace itsmft
96+
} // namespace o2
97+
98+
#endif /* O2_ITSMFT_CLUSTERREADER */
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
// Copyright CERN and copyright holders of ALICE O2. This software is
2+
// distributed under the terms of the GNU General Public License v3 (GPL
3+
// Version 3), copied verbatim in the file "COPYING".
4+
//
5+
// See http://alice-o2.web.cern.ch/license for full licensing information.
6+
//
7+
// In applying this license CERN does not waive the privileges and immunities
8+
// granted to it by virtue of its status as an Intergovernmental Organization
9+
// or submit itself to any jurisdiction.
10+
11+
/// @file ClusterReaderSpec.cxx
12+
13+
#include <vector>
14+
15+
#include "TTree.h"
16+
17+
#include "Framework/ControlService.h"
18+
#include "ITSMFTWorkflow/ClusterReaderSpec.h"
19+
20+
using namespace o2::framework;
21+
using namespace o2::itsmft;
22+
23+
namespace o2
24+
{
25+
namespace itsmft
26+
{
27+
28+
ClusterReader::ClusterReader(o2::detectors::DetID id, bool useMC, bool useClFull, bool useClComp)
29+
{
30+
assert(id == o2::detectors::DetID::ITS || id == o2::detectors::DetID::MFT);
31+
mDetNameLC = mDetName = id.getName();
32+
mUseMC = useMC;
33+
mUseClFull = useClFull;
34+
mUseClComp = useClComp;
35+
std::transform(mDetNameLC.begin(), mDetNameLC.end(), mDetNameLC.begin(), ::tolower);
36+
}
37+
38+
void ClusterReader::init(InitContext& ic)
39+
{
40+
mInputFileName = ic.options().get<std::string>((mDetNameLC + "-cluster-infile").c_str());
41+
}
42+
43+
void ClusterReader::run(ProcessingContext& pc)
44+
{
45+
46+
if (mFinished) {
47+
return;
48+
}
49+
accumulate();
50+
51+
LOG(INFO) << mDetName << "ClusterReader pushes " << mClusROFRecOut.size() << " ROFRecords,"
52+
<< mClusterArrayOut.size() << " full clusters, " << mClusterCompArrayOut.size()
53+
<< " compact clusters";
54+
55+
// This is a very ugly way of providing DataDescription, which anyway does not need to contain detector name.
56+
// To be fixed once the names-definition class is ready
57+
pc.outputs().snapshot(Output{ mOrigin, mOrigin == o2::header::gDataOriginITS ? "ITSClusterROF" : "MFTClusterROF",
58+
0, Lifetime::Timeframe },
59+
mClusROFRecOut);
60+
if (mUseClFull) {
61+
pc.outputs().snapshot(Output{ mOrigin, "CLUSTERS", 0, Lifetime::Timeframe }, mClusterArrayOut);
62+
}
63+
if (mUseClComp) {
64+
pc.outputs().snapshot(Output{ mOrigin, "COMPCLUSTERS", 0, Lifetime::Timeframe }, mClusterCompArrayOut);
65+
}
66+
if (mUseMC) {
67+
pc.outputs().snapshot(Output{ mOrigin, "CLUSTERSMCTR", 0, Lifetime::Timeframe }, mClusterMCTruthOut);
68+
}
69+
70+
mFinished = true;
71+
pc.services().get<ControlService>().readyToQuit(false);
72+
}
73+
74+
void ClusterReader::accumulate()
75+
{
76+
// load data from files
77+
TFile clFile(mInputFileName.c_str(), "read");
78+
if (clFile.IsZombie()) {
79+
LOG(FATAL) << "Failed to open cluster file " << mInputFileName;
80+
}
81+
TTree* clTree = (TTree*)clFile.Get(mClusTreeName.c_str());
82+
if (!clTree) {
83+
LOG(FATAL) << "Failed to load clusters tree " << mClusTreeName << " from " << mInputFileName;
84+
}
85+
TTree* rofTree = (TTree*)clFile.Get((mDetName + mClusROFTreeName).c_str());
86+
if (!rofTree) {
87+
LOG(FATAL) << "Failed to load clusters ROF tree " << rofTree << " from " << mInputFileName;
88+
}
89+
LOG(INFO) << "Loaded cluter tree " << mClusTreeName << " and ROFRecords " << mClusROFTreeName << " from " << mInputFileName;
90+
91+
rofTree->SetBranchAddress((mDetName + mClusROFTreeName).c_str(), &mClusROFRecInp);
92+
93+
if (mUseClFull) {
94+
clTree->SetBranchAddress((mDetName + mClusterBranchName).c_str(), &mClusterArrayInp);
95+
}
96+
if (mUseClComp) {
97+
clTree->SetBranchAddress((mDetName + mClusterCompBranchName).c_str(), &mClusterCompArrayInp);
98+
}
99+
if (mUseMC) {
100+
if (clTree->GetBranch((mDetName + mClustMCTruthBranchName).c_str())) {
101+
clTree->SetBranchAddress((mDetName + mClustMCTruthBranchName).c_str(), &mClusterMCTruthInp);
102+
LOG(INFO) << "Will use MC-truth from " << mDetName + mClustMCTruthBranchName;
103+
} else {
104+
LOG(INFO) << "MC-truth is missing";
105+
mUseMC = false;
106+
}
107+
}
108+
// it is possible that the cluster data is stored in multiple entries, in this case we need to refill to 1 single vector
109+
if (rofTree->GetEntries() > 1) {
110+
LOG(FATAL) << "Clusters ROFRecords tree has " << rofTree->GetEntries() << " entries instead of 1";
111+
}
112+
rofTree->GetEntry(0);
113+
int nROFs = mClusROFRecInp->size();
114+
mClusROFRecOut.swap(*mClusROFRecInp);
115+
int nEnt = clTree->GetEntries();
116+
if (nEnt == 1) {
117+
clTree->GetEntry(0);
118+
if (mUseClFull) {
119+
mClusterArrayOut.swap(*mClusterArrayInp);
120+
}
121+
if (mUseClComp) {
122+
mClusterCompArrayOut.swap(*mClusterCompArrayInp);
123+
}
124+
if (mUseMC) {
125+
mClusterMCTruthOut.mergeAtBack(*mClusterMCTruthInp);
126+
}
127+
} else {
128+
int lastEntry = -1;
129+
int nclAcc = 0;
130+
for (auto& rof : mClusROFRecOut) {
131+
auto rEntry = rof.getROFEntry().getEvent();
132+
if (lastEntry != rEntry) {
133+
clTree->GetEntry((lastEntry = rEntry));
134+
}
135+
// full clusters
136+
if (mUseClFull) {
137+
auto cl0 = mClusterArrayInp->begin() + rof.getROFEntry().getIndex();
138+
auto cl1 = cl0 + rof.getNROFEntries();
139+
std::copy(cl0, cl1, std::back_inserter(mClusterArrayOut));
140+
}
141+
// compact clusters
142+
if (mUseClComp) {
143+
auto cl0 = mClusterCompArrayInp->begin() + rof.getROFEntry().getIndex();
144+
auto cl1 = cl0 + rof.getNROFEntries();
145+
std::copy(cl0, cl1, std::back_inserter(mClusterCompArrayOut));
146+
}
147+
// MC
148+
if (mUseMC) {
149+
mClusterMCTruthOut.mergeAtBack(*mClusterMCTruthInp);
150+
}
151+
rof.getROFEntry().setEvent(0);
152+
rof.getROFEntry().setIndex(nclAcc);
153+
nclAcc += rof.getNROFEntries();
154+
}
155+
}
156+
}
157+
158+
DataProcessorSpec getITSClusterReaderSpec(bool useMC, bool useClFull, bool useClComp)
159+
{
160+
std::vector<OutputSpec> outputSpec;
161+
outputSpec.emplace_back("ITS", "ITSClusterROF", 0, Lifetime::Timeframe);
162+
if (useClFull) {
163+
outputSpec.emplace_back("ITS", "CLUSTERS", 0, Lifetime::Timeframe);
164+
}
165+
if (useClComp) {
166+
outputSpec.emplace_back("ITS", "COMPCLUSTERS", 0, Lifetime::Timeframe);
167+
}
168+
if (useMC) {
169+
outputSpec.emplace_back("ITS", "CLUSTERSMCTR", 0, Lifetime::Timeframe);
170+
}
171+
172+
return DataProcessorSpec{
173+
"its-cluster-reader",
174+
Inputs{},
175+
outputSpec,
176+
AlgorithmSpec{ adaptFromTask<ITSClusterReader>(useMC, useClFull, useClComp) },
177+
Options{
178+
{ "its-cluster-infile", VariantType::String, "o2clus_its.root", { "Name of the input cluster file" } } }
179+
};
180+
}
181+
182+
DataProcessorSpec getMFTClusterReaderSpec(bool useMC, bool useClFull, bool useClComp)
183+
{
184+
std::vector<OutputSpec> outputSpec;
185+
outputSpec.emplace_back("MFT", "MFTClusterROF", 0, Lifetime::Timeframe);
186+
if (useClFull) {
187+
outputSpec.emplace_back("MFT", "CLUSTERS", 0, Lifetime::Timeframe);
188+
}
189+
if (useClComp) {
190+
outputSpec.emplace_back("MFT", "COMPCLUSTERS", 0, Lifetime::Timeframe);
191+
}
192+
if (useMC) {
193+
outputSpec.emplace_back("MFT", "CLUSTERSMCTR", 0, Lifetime::Timeframe);
194+
}
195+
196+
return DataProcessorSpec{
197+
"mft-cluster-reader",
198+
Inputs{},
199+
outputSpec,
200+
AlgorithmSpec{ adaptFromTask<MFTClusterReader>(useMC, useClFull, useClComp) },
201+
Options{
202+
{ "mft-cluster-infile", VariantType::String, "o2clus_mft.root", { "Name of the input cluster file" } } }
203+
};
204+
}
205+
206+
} // namespace itsmft
207+
} // namespace o2

cmake/O2Dependencies.cmake

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,21 @@ o2_define_bucket(
958958
${CMAKE_SOURCE_DIR}/Detectors/ITSMFT/ITS/tracking/include
959959
)
960960

961+
o2_define_bucket(
962+
NAME
963+
ITSMFT_workflow_bucket
964+
965+
DEPENDENCIES
966+
Framework
967+
data_format_itsmft_bucket
968+
itsmft_reconstruction_bucket
969+
ITSMFTReconstruction
970+
DataFormatsITSMFT
971+
972+
INCLUDE_DIRECTORIES
973+
${CMAKE_SOURCE_DIR}/Detectors/ITSMFT/common/workflow/include
974+
)
975+
961976
o2_define_bucket(
962977
NAME
963978
hitanalysis_bucket

0 commit comments

Comments
 (0)