Process an MBS sub-event.
62{
63 LOG(DEBUG) << "DriftTubeUnpack : Unpacking frame... size/bytes = " << size ;
64
66 assert(
df->header.size == size);
67 switch (
df->header.frameTime) {
68 case SoS: LOG(DEBUG) <<
"DriftTubeUnpacker: SoS frame." ;
return kTRUE;
69 case EoS: LOG(DEBUG) <<
"DriftTubeUnpacker: EoS frame." ;
return kTRUE;
70 default: break;
71 }
72 LOG(DEBUG) <<
"Sequential trigger number " <<
df->header.timeExtent ;
74 int nhitsTubes = 0;
75 int nhitsLateTubes = 0;
76 int nhitsScintillator = 0;
77 int nhitsBeamCounter = 0;
78 int nhitsMasterTrigger = 0;
79 int nhitsTriggers = 0;
80 auto flags =
df->header.flags;
81 int trigger = 0;
82 int expected_triggers = 5;
84 LOG(DEBUG) << "All TDCs are OK" ;
85 } else {
86 LOG(DEBUG) << "Not all TDCs are OK:" << std::bitset<16>(flags) ;
87 for (auto i : ROOT::MakeSeq(5)) {
88 if ((flags & 1 << (i + 1)) == 1 << (i + 1)) {
89 expected_triggers--;
90 LOG(WARNING) <<
"TDC " <<
i <<
" NOT OK" ;
91 } else {
92 LOG(DEBUG) <<
"TDC " <<
i <<
" OK" ;
93 }
94 }
95 }
96 ROOT::VecOps::RVec<RawDataHit> hits(
df->hits,
df->hits + nhits);
97 ROOT::VecOps::RVec<RawDataHit> leading, trailing;
98 int n_matched = 0;
99 int n_unmatched = 0;
101 for (auto &&hit : hits) {
102 channels.emplace(hit.channelId % 0x1000);
103 (hit.channelId < 0x1000 ? leading : trailing).emplace_back(hit);
104 }
105 assert(leading.size() + trailing.size() == hits.size());
106 LOG(DEBUG) << leading.size() << '\t' << trailing.size() << '\t' << hits.size();
107 const int n_leading = leading.size();
109 std::sort(leading.begin(), leading.end(), compare_hit_time);
110 std::sort(trailing.begin(), trailing.end(), compare_hit_time);
111 std::unordered_map<uint16_t, ROOT::VecOps::RVec<RawDataHit>> channel_leading;
112 for (auto &&hit : leading) {
113 assert(hit.channelId < 0x1000);
114 channel_leading[hit.channelId % 0x1000].emplace_back(hit);
115 }
116 std::unordered_map<uint16_t, ROOT::VecOps::RVec<RawDataHit>> channel_trailing;
117 for (auto &&hit : trailing) {
118 assert(hit.channelId >= 0x1000);
119 channel_trailing[hit.channelId % 0x1000].emplace_back(hit);
120 }
121 ROOT::VecOps::RVec<std::tuple<uint16_t, uint16_t, Float_t, bool, bool>> matches;
124 LOG(DEBUG) <<
"Channel: " <<
channel;
125 assert(channel < 0x1000);
126 auto leading_hits = channel_leading[
channel];
127 auto trailing_hits = channel_trailing[
channel];
128 auto difference =
int(leading_hits.size() - trailing_hits.size());
129 if (difference != 0) {
130 LOG(DEBUG) << "Difference between leading/trailing edges: " << difference;
131 }
132 for (
int i = 0, j = 0;
i < leading_hits.size();
i++) {
133 LOG(DEBUG) <<
"i=" <<
i <<
"\tj=" <<
j;
134 LOG(DEBUG) << "leading_hits.size()=" << leading_hits.size()
135 << "\ttrailing_hits.size()=" << trailing_hits.size();
136 assert(i < leading_hits.size());
137 if (j < trailing_hits.size() && leading_hits.at(i).hitTime < trailing_hits.at(j).hitTime &&
138 (i + 1 >= leading_hits.size() || trailing_hits.at(j).hitTime < leading_hits.at(i + 1).hitTime)) {
139
140 LOG(DEBUG) <<
"Successful match on channel " <<
channel;
141 uint16_t time = leading_hits.at(i).hitTime;
142 Float_t time_over_threshold = 0.098 * (trailing_hits.at(j).hitTime - leading_hits.at(i).hitTime);
143 matches.emplace_back(channel, time, time_over_threshold, first, true);
144 n_matched++;
147 } else if (j < trailing_hits.size() && leading_hits.at(i).hitTime > trailing_hits.at(j).hitTime &&
148 (
j + 1) < trailing_hits.size()) {
149
150
151 LOG(DEBUG) <<
"Try again for hit on channel " <<
channel;
154 } else {
155 LOG(DEBUG) <<
"No match found for hit on channel " <<
channel;
156
157 uint16_t time = leading_hits.at(i).hitTime;
158 Float_t time_over_threshold = 167.2;
159 matches.emplace_back(channel, time, time_over_threshold, first, false);
161 n_unmatched++;
162 }
163 }
164 }
165 assert(n_matched + n_unmatched == n_leading);
166 LOG(DEBUG) << "Successfully matched " << n_matched << "/" << n_leading << "(" << hits.size() << " hits)";
167
168 std::unordered_map<int, uint16_t> trigger_times;
169 ROOT::VecOps::RVec<std::tuple<uint16_t, uint16_t, Float_t, bool, uint16_t>> drifttube_hits;
170 uint16_t master_trigger_time = 0;
171 for (auto &&match : matches) {
173 Float_t time_over_threshold;
175 std::tie(channel, hit_time, time_over_threshold, first, matched) = match;
178 auto detectorId =
fCharm ?
id.GetDetectorIdCharm() :
id.GetDetectorId();
179 auto TDC = id.TDC;
180 if (detectorId == 0) {
181
182 trigger++;
183 if (trigger_times.find(TDC) != trigger_times.end()) {
184 LOG(DEBUG) << "Found time " << trigger_times[TDC] << " for TDC " << TDC ;
185 trigger_times[TDC] = std::min(hit_time, trigger_times[TDC]);
186 } else {
187 LOG(DEBUG) << "Inserting new time " << hit_time ;
188 trigger_times[TDC] = hit_time;
189 }
190 LOG(DEBUG) << TDC << '\t' << hit_time << '\t' << trigger_times[TDC] ;
191 new ((*fRawTriggers)[nhitsTriggers])
192 ScintillatorHit(detectorId, 0.098 * Float_t(hit_time), time_over_threshold, hit_flags,
channel);
193 nhitsTriggers++;
194 } else if (detectorId == -2) {
195
196 continue;
197 } else if (detectorId == 1) {
198
199
200
201 if (nhitsMasterTrigger == 0 || hit_time < master_trigger_time) {
202 master_trigger_time = hit_time;
203 }
204 new ((*fRawMasterTrigger)[nhitsMasterTrigger])
205 ScintillatorHit(detectorId, 0.098 * Float_t(hit_time), time_over_threshold, hit_flags,
channel);
206 nhitsMasterTrigger++;
207 } else if (detectorId == -1) {
208
209 new ((*fRawBeamCounter)[nhitsBeamCounter])
210 ScintillatorHit(detectorId, 0.098 * Float_t(hit_time), time_over_threshold, hit_flags,
channel);
211 nhitsBeamCounter++;
212 } else if (detectorId == 6 || detectorId == 7) {
213
215 LOG(ERROR) << "Scintillator hit found! There should not be any in the charmxsec measurement!"
216 ;
217 }
218 continue;
219 new ((*fRawScintillator)[nhitsScintillator])
220 ScintillatorHit(detectorId, 0.098 * Float_t(hit_time), time_over_threshold, hit_flags,
channel);
221 nhitsScintillator++;
222 } else {
223 drifttube_hits.emplace_back(channel, hit_time, time_over_threshold, first, hit_flags);
224 }
225 }
226
227 int32_t delay = 13500;
228 if (!trigger_times[4]) {
229 LOG(WARNING) << "No trigger in TDC 4, guessing delay" ;
231 } else if (master_trigger_time == 0) {
232 LOG(WARNING) << "No master trigger, guessing delay" ;
234 } else {
235 delay = trigger_times[4] - master_trigger_time;
236 LOG(DEBUG) << "Delay [ns]:";
237 LOG(DEBUG) << 0.098 * delay << " = " << 0.098 * trigger_times[4] << " - " << 0.098 * master_trigger_time;
238 }
239
240 for (auto &&hit : drifttube_hits) {
241 uint16_t
channel, raw_time, hit_flags;
242 Float_t time_over_threshold;
244 std::tie(channel, raw_time, time_over_threshold, first, hit_flags) = hit;
245 hit_flags |= flags;
247 auto detectorId =
fCharm ?
id.GetDetectorIdCharm() :
id.GetDetectorId();
248 auto TDC = id.TDC;
249 Float_t time;
250 try {
251 auto trigger_time = trigger_times.at(TDC);
252 time = 0.098 * (delay - trigger_time + raw_time);
253 } catch (const std::out_of_range &e) {
254 LOG(WARNING) << e.what() <<
"\t TDC " << TDC <<
"\t Detector ID " << detectorId <<
"\t Channel " <<
channel
255 <<
"\t Sequential trigger number " <<
df->header.timeExtent ;
256 time = 0.098 * raw_time;
258 }
259 if (time > 4000) {
260 LOG(WARNING) << "Late event found with time [ns]:";
261 LOG(WARNING) << time << " = " << 0.098 * delay << " - " << 0.098 * (delay + raw_time) - time << " - "
262 << 0.098 * raw_time;
263 }
264
266 MufluxSpectrometerHit(detectorId, time, time_over_threshold, hit_flags, channel);
267 (
first ? nhitsTubes : nhitsLateTubes)++;
268 }
269
270 if (trigger < expected_triggers) {
271 LOG(INFO) << trigger << " triggers." ;
272 } else {
273 LOG(DEBUG) << trigger << " triggers." ;
274 }
275
276 return kTRUE;
277}
std::unique_ptr< TClonesArray > fRawTubes
std::unique_ptr< TClonesArray > fRawLateTubes
integer(mpi) nhits
number of hits