134 mTrapConfigName = ic.
options().
get<std::string>(
"trd-trapconfig");
135 mEnableOnlineGainCorrection = ic.
options().
get<
bool>(
"trd-onlinegaincorrection");
136 mOnlineGainTableName = ic.
options().
get<std::string>(
"trd-onlinegaintable");
137 mRunNumber = ic.
options().
get<
int>(
"trd-runnum");
138 mEnableTrapConfigDump = ic.
options().
get<
bool>(
"trd-dumptrapconfig");
139 mUseFloatingPointForQ = ic.
options().
get<
bool>(
"float-arithmetic");
140 mChargeScalingFactor = ic.
options().
get<
int>(
"scale-q");
141 if (mChargeScalingFactor != -1) {
142 if (mChargeScalingFactor < 1) {
143 LOG(error) <<
"Charge scaling factor < 1 defined. Setting it to 1";
145 mChargeScalingFactor = 1;
146 }
else if (mChargeScalingFactor > 1024) {
147 LOG(error) <<
"Charge scaling factor > 1024 defined. Setting it to 1024";
149 mChargeScalingFactor = 1024;
152 if (mUseFloatingPointForQ) {
153 LOG(info) <<
"Tracklet charges will be calculated using floating point arithmetic";
154 if (mChargeScalingFactor != -1) {
155 LOG(error) <<
"Charge scaling factor defined, but floating point arithmetic configured. Charge scaling has no effect";
158 LOG(info) <<
"Tracklet charges will be calculated using a fixed multiplier";
163 int maxThreads = omp_get_max_threads();
164 if (askedThreads < 0) {
165 mNumThreads = maxThreads;
167 mNumThreads = std::min(maxThreads, askedThreads);
169 LOG(info) <<
"Trap simulation running with " << mNumThreads <<
" threads ";
176 LOG(info) <<
"TRD Trap Simulator Device running over incoming message";
178 if (!mInitCcdbObjectsDone) {
180 auto timeStamp = (mRunNumber < 0) ? creationTime : mRunNumber;
181 mCalib = std::make_unique<Calibrations>();
182 mCalib->getCCDBObjects(timeStamp);
183 initTrapConfig(timeStamp);
184 setOnlineGainTables();
185 mInitCcdbObjectsDone =
true;
189 auto digits = pc.
inputs().
get<gsl::span<o2::trd::Digit>>(
"digitinput");
190 auto triggerRecords = pc.
inputs().
get<std::vector<o2::trd::TriggerRecord>>(
"triggerrecords");
191 LOG(
debug) <<
"Received " <<
digits.size() <<
" digits from " << triggerRecords.size() <<
" collisions";
196 std::optional<lblType> lblDigits;
199 lblDigitsPtr = &lblDigits.value();
202 LOG(warn) <<
"Digits and Labels coming into TrapSimulator are of differing sizes, labels will be jibberish. " << lblDigitsPtr->
getIndexedSize() <<
"!=" <<
digits.size();
207 std::vector<Digit> digitsOut;
211 auto timeProcessingStart = std::chrono::high_resolution_clock::now();
214 auto sortStart = std::chrono::high_resolution_clock::now();
215 std::vector<unsigned int> digitIdxArray(
digits.size());
216 std::iota(digitIdxArray.begin(), digitIdxArray.end(), 0);
217 for (
auto& trig : triggerRecords) {
218 std::stable_sort(std::begin(digitIdxArray) + trig.getFirstDigit(), std::begin(digitIdxArray) + trig.getNumberOfDigits() + trig.getFirstDigit(),
219 [&
digits](
unsigned int i,
unsigned int j) { return digits[i].getHCId() < digits[j].getHCId(); });
221 auto sortTime = std::chrono::high_resolution_clock::now() - sortStart;
224 std::vector<int> nTracklets(triggerRecords.size());
225 std::vector<std::vector<Tracklet64>> trackletsAccum;
226 trackletsAccum.resize(triggerRecords.size());
227 std::vector<std::vector<short>> digitCountsAccum;
230 std::vector<std::vector<int>> digitIndicesAccum;
231 digitCountsAccum.resize(triggerRecords.size());
232 digitIndicesAccum.resize(triggerRecords.size());
234 auto timeParallelStart = std::chrono::high_resolution_clock::now();
237#pragma omp parallel for schedule(dynamic) num_threads(mNumThreads)
239 for (
size_t iTrig = 0; iTrig < triggerRecords.size(); ++iTrig) {
241 std::array<TrapSimulator, NMCMHCMAX> trapSimulators{};
242 for (
int iDigit = triggerRecords[iTrig].getFirstDigit(); iDigit < (triggerRecords[iTrig].getFirstDigit() + triggerRecords[iTrig].getNumberOfDigits()); ++iDigit) {
243 const auto& digit = &
digits[digitIdxArray[iDigit]];
245 currHCId = digit->getHCId();
247 if (currHCId != digit->getHCId()) {
249 processTRAPchips(nTracklets[iTrig], trackletsAccum[iTrig], trapSimulators, digitCountsAccum[iTrig], digitIndicesAccum[iTrig]);
250 currHCId = digit->getHCId();
253 int trapIdx = (digit->getROB() / 2) *
NMCMROB + digit->getMCM();
254 if (!trapSimulators[trapIdx].isDataSet()) {
255 trapSimulators[trapIdx].init(mTrapConfig, digit->getDetector(), digit->getROB(), digit->getMCM());
256 if (mUseFloatingPointForQ) {
257 trapSimulators[trapIdx].setUseFloatingPointForQ();
258 }
else if (mChargeScalingFactor != -1) {
259 trapSimulators[trapIdx].setChargeScalingFactor(mChargeScalingFactor);
262 if (digit->getChannel() != 22) {
264 trapSimulators[trapIdx].setData(digit->getChannel(), digit->getADC(), digitIdxArray[iDigit]);
268 processTRAPchips(nTracklets[iTrig], trackletsAccum[iTrig], trapSimulators, digitCountsAccum[iTrig], digitIndicesAccum[iTrig]);
270 auto parallelTime = std::chrono::high_resolution_clock::now() - timeParallelStart;
273 int nDigitsRejected = 0;
274 for (
size_t iTrig = 0; iTrig < triggerRecords.size(); ++iTrig) {
276 int currDigitIndex = 0;
278 for (
int iTrklt = 0; iTrklt < nTracklets[iTrig]; ++iTrklt) {
279 int tmp = currDigitIndex;
280 for (
int iDigitIndex = tmp; iDigitIndex < tmp + digitCountsAccum[iTrig][iTrklt]; ++iDigitIndex) {
281 if (iDigitIndex == tmp) {
283 lblTracklets.
addElements(trkltIdxStart + iTrklt, lblDigitsPtr->
getLabels(digitIndicesAccum[iTrig][iDigitIndex]));
288 auto currentLabels = lblTracklets.
getLabels(trkltIdxStart + iTrklt);
289 auto newLabels = lblDigitsPtr->
getLabels(digitIndicesAccum[iTrig][iDigitIndex]);
290 for (
const auto& newLabel : newLabels) {
291 bool alreadyIn =
false;
292 for (
const auto& currLabel : currentLabels) {
293 if (currLabel == newLabel) {
299 lblTracklets.
addElement(trkltIdxStart + iTrklt, newLabel);
307 tracklets.insert(
tracklets.end(), trackletsAccum[iTrig].begin(), trackletsAccum[iTrig].end());
308 triggerRecords[iTrig].setTrackletRange(
tracklets.size() - nTracklets[iTrig], nTracklets[iTrig]);
309 if ((iTrig % mDigitDownscaling) == 0) {
311 digitsOut.insert(digitsOut.end(),
digits.begin() + triggerRecords[iTrig].getFirstDigit(),
digits.begin() + triggerRecords[iTrig].getFirstDigit() + triggerRecords[iTrig].getNumberOfDigits());
312 triggerRecords[iTrig].setDigitRange(digitsOut.size() - triggerRecords[iTrig].getNumberOfDigits(), triggerRecords[iTrig].getNumberOfDigits());
315 nDigitsRejected += triggerRecords[iTrig].getNumberOfDigits();
316 triggerRecords[iTrig].setDigitRange(digitsOut.size(), 0);
320 auto processingTime = std::chrono::high_resolution_clock::now() - timeProcessingStart;
322 LOG(info) <<
"Trap simulator found " <<
tracklets.size() <<
" tracklets from " <<
digits.size() <<
" Digits.";
323 LOG(info) <<
"In total " << nDigitsRejected <<
" digits were rejected due to digit downscaling factor of " << mDigitDownscaling;
325 LOG(info) <<
"In total " << lblTracklets.
getNElements() <<
" MC labels are associated to the " << lblTracklets.
getIndexedSize() <<
" tracklets";
327 LOG(info) <<
"Total processing time : " << std::chrono::duration_cast<std::chrono::milliseconds>(processingTime).count() <<
"ms";
328 LOG(info) <<
"Digit Sorting took: " << std::chrono::duration_cast<std::chrono::milliseconds>(sortTime).count() <<
"ms";
329 LOG(info) <<
"Processing time for parallel region: " << std::chrono::duration_cast<std::chrono::milliseconds>(parallelTime).count() <<
"ms";
338 LOG(
debug) <<
"TRD Trap Simulator Device exiting";
343 std::vector<InputSpec> inputs;
344 std::vector<OutputSpec> outputs;
346 inputs.emplace_back(
"digitinput",
"TRD",
"DIGITS", 1);
347 inputs.emplace_back(
"triggerrecords",
"TRD",
"TRKTRGRD", 1);
349 outputs.emplace_back(
"TRD",
"DIGITS", 0, Lifetime::Timeframe);
350 outputs.emplace_back(
"TRD",
"TRACKLETS", 0, Lifetime::Timeframe);
351 outputs.emplace_back(
"TRD",
"TRKTRGRD", 0, Lifetime::Timeframe);
354 inputs.emplace_back(
"labelinput",
"TRD",
"LABELS", 0);
355 outputs.emplace_back(
"TRD",
"TRKLABELS", 0, Lifetime::Timeframe);
361 AlgorithmSpec{adaptFromTask<TRDDPLTrapSimulatorTask>(useMC, digitDownscaling)},
363 {
"scale-q", VariantType::Int, -1, {
"Divide tracklet charges by this number. For -1 the value from the TRAP config will be taken instead"}},
364 {
"float-arithmetic", VariantType::Bool,
false, {
"Enable floating point calculation of the tracklet charges instead of using fixed multiplier"}},
365 {
"trd-trapconfig", VariantType::String,
"cf_pg-fpnp32_zs-s16-deh_tb30_trkl-b5n-fs1e24-ht200-qs0e24s24e23-pidlinear-pt100_ptrg.r5549", {
"TRAP config name"}},
366 {
"trd-onlinegaincorrection", VariantType::Bool,
false, {
"Apply online gain calibrations, mostly for back checking to run2 by setting FGBY to 0"}},
367 {
"trd-onlinegaintable", VariantType::String,
"Krypton_2015-02", {
"Online gain table to be use, names found in CCDB, obviously trd-onlinegaincorrection must be set as well."}},
368 {
"trd-dumptrapconfig", VariantType::Bool,
false, {
"Dump the selected trap configuration at loading time, to text file"}},
369 {
"trd-runnum", VariantType::Int, -1, {
"Run number to use to anchor simulation to (from Run 2 297595 was used)"}}}};
DataAllocator & outputs()
The data allocator is used to allocate memory for the output data.
ServiceRegistryRef services()
The services registry associated with this processing context.