Project
Loading...
Searching...
No Matches
PreClusterSinkSpec.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
16
17#include "PreClusterSinkSpec.h"
18
19#include <iostream>
20#include <fstream>
21#include <array>
22#include <stdexcept>
23#include <vector>
24
25#include <gsl/span>
26
31#include "Framework/Lifetime.h"
32#include "Framework/Task.h"
33#include "Framework/Logger.h"
34
37#include "MCHBase/PreCluster.h"
39
40namespace o2
41{
42namespace mch
43{
44
45using namespace std;
46using namespace o2::framework;
47
49{
50 public:
51 //_________________________________________________________________________________________________
53 {
55 LOG(info) << "initializing precluster sink";
56
57 mText = ic.options().get<bool>("txt");
58
59 auto outputFileName = ic.options().get<std::string>("outfile");
60 mOutputFile.open(outputFileName, (mText ? ios::out : (ios::out | ios::binary)));
61 if (!mOutputFile.is_open()) {
62 throw invalid_argument("Cannot open output file" + outputFileName);
63 }
64
65 mUseRun2DigitUID = ic.options().get<bool>("useRun2DigitUID");
66
67 auto stop = [this]() {
69 LOG(info) << "stop precluster sink";
70 this->mOutputFile.close();
71 };
72 ic.services().get<CallbackService>().set<CallbackService::Id::Stop>(stop);
73 }
74
75 //_________________________________________________________________________________________________
77 {
79
80 // get the input preclusters and associated digits
81 auto rofs = pc.inputs().get<gsl::span<ROFRecord>>("rofs");
82 auto preClusters = pc.inputs().get<gsl::span<PreCluster>>("preclusters");
83 auto digits = pc.inputs().get<gsl::span<Digit>>("digits");
84
85 // convert the pad ID into a digit UID if requested (need to copy the digits to modify them)
86 std::vector<Digit> digitsCopy{};
87 if (mUseRun2DigitUID) {
88 digitsCopy.insert(digitsCopy.end(), digits.begin(), digits.end());
89 convertPadID2DigitUID(digitsCopy);
90 digits = gsl::span<const Digit>(digitsCopy);
91 }
92
93 std::vector<PreCluster> eventPreClusters{};
94 for (const auto& rof : rofs) {
95
96 if (mText) {
97
98 // write the preclusters of the current event in text format
99 mOutputFile << rof.getNEntries() << " preclusters:" << endl;
100 for (const auto& precluster : preClusters.subspan(rof.getFirstIdx(), rof.getNEntries())) {
101 precluster.print(mOutputFile, digits);
102 }
103
104 } else {
105
106 // get the preclusters and associated digits of the current event
107 auto eventDigits = getEventPreClustersAndDigits(rof, preClusters, digits, eventPreClusters);
108
109 // write the number of preclusters and the total number of digits in these preclusters
110 int nPreClusters = eventPreClusters.size();
111 mOutputFile.write(reinterpret_cast<char*>(&nPreClusters), sizeof(int));
112 int nDigits = eventDigits.size();
113 mOutputFile.write(reinterpret_cast<char*>(&nDigits), sizeof(int));
114
115 // write the preclusters and the digits
116 mOutputFile.write(reinterpret_cast<const char*>(eventPreClusters.data()),
117 eventPreClusters.size() * sizeof(PreCluster));
118 mOutputFile.write(reinterpret_cast<const char*>(eventDigits.data()), eventDigits.size_bytes());
119 }
120 }
121 }
122
123 private:
124 //_________________________________________________________________________________________________
125 gsl::span<const Digit> getEventPreClustersAndDigits(const ROFRecord& rof, gsl::span<const PreCluster> preClusters,
126 gsl::span<const Digit> digits,
127 std::vector<PreCluster>& eventPreClusters) const
128 {
132
133 eventPreClusters.clear();
134
135 if (rof.getNEntries() < 1) {
136 return {};
137 }
138
139 if (rof.getLastIdx() >= preClusters.size()) {
140 throw length_error("missing preclusters");
141 }
142
143 eventPreClusters.insert(eventPreClusters.end(), preClusters.begin() + rof.getFirstIdx(),
144 preClusters.begin() + rof.getLastIdx() + 1);
145
146 auto digitOffset = eventPreClusters.front().firstDigit;
147 for (auto& preCluster : eventPreClusters) {
148 preCluster.firstDigit -= digitOffset;
149 }
150
151 if (eventPreClusters.back().lastDigit() + digitOffset >= digits.size()) {
152 throw length_error("missing digits");
153 }
154
155 return digits.subspan(digitOffset, eventPreClusters.back().lastDigit() + 1);
156 }
157
158 //_________________________________________________________________________________________________
159 void convertPadID2DigitUID(std::vector<Digit>& digits)
160 {
162
163 // cathode number of the bending plane for each DE
164 static const std::array<std::vector<int>, 10> bendingCathodes{
165 {{0, 1, 0, 1},
166 {0, 1, 0, 1},
167 {0, 1, 0, 1},
168 {0, 1, 0, 1},
169 {0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1},
170 {0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1},
171 {0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1},
172 {0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1},
173 {0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1},
174 {0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}}};
175
176 for (auto& digit : digits) {
177
178 int deID = digit.getDetID();
180 int padID = digit.getPadID();
181 int cathode = bendingCathodes[deID / 100 - 1][deID % 100];
182 if (!segmentation.isBendingPad(padID)) {
183 cathode = 1 - cathode;
184 }
185 int manuID = segmentation.padDualSampaId(padID);
186 int manuCh = segmentation.padDualSampaChannel(padID);
187
188 int digitID = (deID) | (manuID << 12) | (manuCh << 24) | (cathode << 30);
189 digit.setPadID(digitID);
190 }
191 }
192
193 std::ofstream mOutputFile{};
194 bool mText = false;
195 bool mUseRun2DigitUID = false;
196};
197
198//_________________________________________________________________________________________________
200{
201 return DataProcessorSpec{
202 specName,
203 Inputs{InputSpec{"rofs", "MCH", "PRECLUSTERROFS", 0, Lifetime::Timeframe},
204 InputSpec{"preclusters", "MCH", "PRECLUSTERS", 0, Lifetime::Timeframe},
205 InputSpec{"digits", "MCH", "PRECLUSTERDIGITS", 0, Lifetime::Timeframe}},
206 Outputs{},
207 AlgorithmSpec{adaptFromTask<PreClusterSinkTask>()},
208 Options{{"outfile", VariantType::String, "preclusters.out", {"output filename"}},
209 {"txt", VariantType::Bool, false, {"output preclusters in text format"}},
210 {"useRun2DigitUID", VariantType::Bool, false, {"mPadID = digit UID in run2 format"}}}};
211}
212
213} // end namespace mch
214} // end namespace o2
Definition of the MCH precluster minimal structure.
Definition of the MCH ROFrame record.
Definition of a data processor to write preclusters.
const char * specName
ServiceRegistryRef services()
Definition InitContext.h:34
ConfigParamRegistry const & options()
Definition InitContext.h:33
decltype(auto) get(R binding, int part=0) const
InputRecord & inputs()
The inputs associated with this processing context.
void run(framework::ProcessingContext &pc)
void init(framework::InitContext &ic)
int getLastIdx() const
get the index of the last associated object
Definition ROFRecord.h:59
int getNEntries() const
get the number of associated objects
Definition ROFRecord.h:55
int getFirstIdx() const
get the index of the first associated object
Definition ROFRecord.h:57
int padDualSampaId(int dePadIndex) const
bool isBendingPad(int dePadIndex) const
int padDualSampaChannel(int dePadIndex) const
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
std::vector< ConfigParamSpec > Options
std::vector< InputSpec > Inputs
std::vector< OutputSpec > Outputs
O2MCHMAPPINGIMPL3_EXPORT const Segmentation & segmentation(int detElemId)
o2::framework::DataProcessorSpec getPreClusterSinkSpec(const char *specName)
gsl::span< const PreCluster > preClusters(preClusterizer.getPreClusters().data(), preClusterizer.getPreClusters().size())
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Defining DataPointCompositeObject explicitly as copiable.
precluster minimal structure
Definition PreCluster.h:33
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Digit > digits