Skip to content

Commit 06578c2

Browse files
author
Szymon Pulawski
committed
FT0: continue crosstalk handling in digitizer
1 parent e47af56 commit 06578c2

2 files changed

Lines changed: 105 additions & 13 deletions

File tree

Detectors/FIT/FT0/base/include/FT0Base/FT0DigParam.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ struct FT0DigParam : o2::conf::ConfigurableParamHelper<FT0DigParam> {
5050
float mMV_2_Nchannels = 2.; // amplitude channel 7 mV ->14channels
5151
float mMV_2_NchannelsInverse = 0.5; // inverse amplitude channel 7 mV ->14channels (nowhere used)
5252

53+
float Cross_Talk_Frac = 0.05f; // Crosstalk between channels
54+
5355
O2ParamDef(FT0DigParam, "FT0DigParam");
5456
};
5557
} // namespace o2::ft0

Detectors/FIT/FT0/simulation/src/Digitizer.cxx

100644100755
Lines changed: 103 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "FT0Base/Constants.h"
2121
#include <map>
2222
#include <array>
23+
#include <unordered_map>
2324
#include <regex>
2425
#include <string>
2526

@@ -376,19 +377,53 @@ void Digitizer::storeBC(BCCache& bc,
376377

377378
int vertex_time;
378379
const auto& params = FT0DigParam::Instance();
380+
381+
static bool pmGroupsInitialized = false;
382+
static std::vector<std::array<int, 4>> pmtChannelGroups;
383+
if (!pmGroupsInitialized) {
384+
std::unordered_map<uint8_t, std::vector<int>> tmpGroups;
385+
for (int ch = 0; ch < o2::ft0::Constants::sNCHANNELS_PM; ++ch) {
386+
tmpGroups[mChID2PMhash[static_cast<uint8_t>(ch)]].push_back(ch);
387+
}
388+
389+
for (auto& [pmHash, chVec] : tmpGroups) {
390+
std::sort(chVec.begin(), chVec.end());
391+
if (chVec.size() % 4 != 0) {
392+
LOG(fatal) << "PM hash " << int(pmHash) << " has " << chVec.size()
393+
<< " channels in LUT, expected multiplicity of 4";
394+
}
395+
for (size_t i = 0; i < chVec.size(); i += 4) {
396+
std::array<int, 4> arr = {chVec[i + 0], chVec[i + 1], chVec[i + 2], chVec[i + 3]};
397+
pmtChannelGroups.push_back(arr);
398+
}
399+
}
400+
pmGroupsInitialized = true;
401+
}
402+
379403
int first = digitsCh.size(), nStored = 0;
380404
auto& particles = bc.hits;
381405
std::sort(std::begin(particles), std::end(particles));
382406
auto channel_end = particles.begin();
383407
std::vector<float> channel_times;
384-
// std::set<int> disabledChannels = {40, 41, 42, 43, 88, 89, 90, 91, 56, 57, 58, 59, 60, 61, 62, 63, 72, 73, 74, 75, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 164, 165, 166, 167, 184, 185, 186, 187, 160, 161, 162, 163, 188, 189, 190, 191, 156, 157, 158, 159, 192, 193, 194, 195, 152, 153, 154, 155, 196, 197, 198, 199, 148, 149, 150, 151, 144, 145, 146, 147, 204, 205, 206, 207, 200, 201, 202, 203}; // przykładowe kanały
408+
std::vector<float> baseAmp(params.mMCPs, 0.f);
409+
std::vector<float> finalAmp(params.mMCPs, 0.f);
410+
std::vector<int> chTime(params.mMCPs, -5000);
411+
std::vector<int> chChain(params.mMCPs, 0);
412+
std::vector<bool> chValid(params.mMCPs, false);
413+
414+
static const std::array<std::array<int, 3>, 4> localNeighbours = {{
415+
{{1, 2, 3}},
416+
{{0, 3, 2}},
417+
{{0, 3, 1}},
418+
{{1, 2, 0}}
419+
}};
420+
421+
// std::set<int> disabledChannels = {40, 41, 42, 43, 88, 89, 90, 91, 56, 57, 58, 59, 60, 61, 62, 63, 72, 73, 74, 75, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 164, 165, 166, 167, 184, 185, 186, 187, 160, 161, 162, 163, 188, 189, 190, 191, 156, 157, 158, 159, 192, 193, 194, 195, 152, 153, 154, 155, 196, 197, 198, 199, 148, 149, 150, 151, 144, 145, 146, 147, 204, 205, 206, 207, 200, 201, 202, 203}; // przykładowe kanały
385422
for (Int_t ipmt = 0; ipmt < params.mMCPs; ++ipmt) {
386423
auto channel_begin = channel_end;
387424
channel_end = std::find_if(channel_begin, particles.end(),
388425
[ipmt](BCCache::particle const& p) { return p.hit_ch != ipmt; });
389426

390-
// The hits between 'channel_begin' and 'channel_end' now contains all hits for channel 'ipmt'
391-
392427
if (channel_end - channel_begin < params.mAmp_trsh) {
393428
continue;
394429
}
@@ -409,31 +444,86 @@ void Digitizer::storeBC(BCCache& bc,
409444
if (mCalibOffset) {
410445
miscalib = mCalibOffset->mTimeOffsets[ipmt];
411446
}
412-
int smeared_time = 1000. * (*cfd.particle - params.mCfdShift) * params.mChannelWidthInverse + miscalib; // + int(1000. * mIntRecord.getTimeOffsetWrtBC() * params.mChannelWidthInverse);
447+
int smeared_time = 1000. * (*cfd.particle - params.mCfdShift) * params.mChannelWidthInverse + miscalib;
413448
bool is_time_in_signal_gate = (smeared_time > -params.mTime_trg_gate && smeared_time < params.mTime_trg_gate);
414449
float charge = measure_amplitude(channel_times) * params.mCharge2amp;
415-
float amp = is_time_in_signal_gate ? params.mMV_2_Nchannels * charge : 0;
416-
if (amp > 4095) {
417-
amp = 4095;
450+
float amp = is_time_in_signal_gate ? params.mMV_2_Nchannels * charge : 0.f;
451+
if (amp > 4095.f) {
452+
amp = 4095.f;
418453
}
419454
// if (!disabledChannels.count(ipmt)) {
420455
// continue;
421456
// }
422457

423-
LOG(debug) << mEventID << " bc " << firstBCinDeque.bc << " orbit " << firstBCinDeque.orbit << ", ipmt " << ipmt << ", smeared_time " << smeared_time << " nStored " << nStored << " offset " << miscalib;
458+
LOG(debug) << mEventID << " bc " << firstBCinDeque.bc << " orbit " << firstBCinDeque.orbit
459+
<< ", ipmt " << ipmt << ", smeared_time " << smeared_time
460+
<< " nStored " << nStored << " offset " << miscalib
461+
<< " base amp " << amp;
424462
if (is_time_in_signal_gate) {
425463
chain |= (1 << o2::ft0::ChannelData::EEventDataBit::kIsCFDinADCgate);
426464
chain |= (1 << o2::ft0::ChannelData::EEventDataBit::kIsEventInTVDC);
427-
// Sum channel charge per PM (similar logic as in digits2trgFT0)
428-
if (ipmt < o2::ft0::Constants::sNCHANNELS_PM) {
429-
mapPMhash2sumAmpl[mChID2PMhash[static_cast<uint8_t>(ipmt)]] += static_cast<int>(amp);
465+
}
466+
467+
baseAmp[ipmt] = amp;
468+
finalAmp[ipmt] = amp;
469+
chTime[ipmt] = smeared_time;
470+
chChain[ipmt] = chain;
471+
chValid[ipmt] = true;
472+
}
473+
474+
for (const auto& channels : pmtChannelGroups) {
475+
for (int localIdx = 0; localIdx < 4; ++localIdx) {
476+
const int src = channels[localIdx];
477+
if (!chValid[src] || baseAmp[src] <= 0.f) {
478+
continue;
430479
}
480+
481+
const int nb1 = channels[localNeighbours[localIdx][0]];
482+
const int nb2 = channels[localNeighbours[localIdx][1]];
483+
const int diag = channels[localNeighbours[localIdx][2]];
484+
485+
const float directXtalk = baseAmp[src] * params.Cross_Talk_Frac;
486+
const float diagXtalk = baseAmp[src] * (params.Cross_Talk_Frac / 3.f);
487+
488+
finalAmp[nb1] += directXtalk;
489+
finalAmp[nb2] += directXtalk;
490+
finalAmp[diag] += diagXtalk;
491+
492+
auto propagateIfEmpty = [&](int dst) {
493+
if (!chValid[dst]) {
494+
chValid[dst] = true;
495+
chTime[dst] = chTime[src];
496+
chChain[dst] = chChain[src];
497+
}
498+
};
499+
500+
propagateIfEmpty(nb1);
501+
propagateIfEmpty(nb2);
502+
propagateIfEmpty(diag);
503+
}
504+
}
505+
506+
for (Int_t ipmt = 0; ipmt < params.mMCPs; ++ipmt) {
507+
if (!chValid[ipmt]) {
508+
continue;
431509
}
510+
511+
float amp = finalAmp[ipmt];
512+
if (amp > 4095.f) {
513+
amp = 4095.f;
514+
}
515+
516+
const int smeared_time = chTime[ipmt];
517+
const int chain = chChain[ipmt];
518+
const bool is_time_in_signal_gate = (smeared_time > -params.mTime_trg_gate && smeared_time < params.mTime_trg_gate);
519+
520+
if (is_time_in_signal_gate && ipmt < o2::ft0::Constants::sNCHANNELS_PM) {
521+
mapPMhash2sumAmpl[mChID2PMhash[static_cast<uint8_t>(ipmt)]] += static_cast<int>(amp);
522+
}
523+
432524
digitsCh.emplace_back(ipmt, smeared_time, int(amp), chain);
433525
nStored++;
434526

435-
// fill triggers
436-
437527
Bool_t is_A_side = (ipmt < 4 * mGeometry.NCellsA);
438528
if (!is_time_in_signal_gate) {
439529
continue;

0 commit comments

Comments
 (0)