Belle II Software development
klm_trig_linear_fit.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9
10
11#include "trg/klm/modules/klmtrigger/klm_trig_linear_fit.h"
12#include "trg/klm/modules/klmtrigger/IO_csv.h"
13#include "trg/klm/modules/klmtrigger/bit_operations.h"
14
15#include "trg/klm/modules/klmtrigger/ntuples_full.h"
16
17
18#include <exception>
19
20#include <array>
21
22using namespace Belle2::KLM_TRG_definitions;
23
24
25namespace Belle2 {
31 void bitshift(int64_t& out, int64_t& shift, int64_t in, int64_t deltashift)
32 {
33 int64_t mask = 0xFFFFFF;
34 if (((mask << deltashift) & in) > 0) {
35 throw std::runtime_error("bitshift error");
36 }
37
38 out |= (in << shift);
39 shift += deltashift;
40 }
41
42 template <typename T>
43 constexpr int64_t get_index(const T& e, int track_id = 0)
44 {
45 int64_t ret = 0;
46 int64_t shift = 0;
47 bitshift(ret, shift, track_id, 5);
48 bitshift(ret, shift, e.layer, 6);
49 bitshift(ret, shift, e.plane, 2);
50 bitshift(ret, shift, e.sector, 6);
51 bitshift(ret, shift, e.section, 3);
52 bitshift(ret, shift, e.subdetector, 3);
53
54
55 return ret;
56 };
57
59 double y_cutoff = 0;
60 int m_number_of_tracks = 4;
61 struct internal {
62 double last_x = 0, last_y = 0;
63 int nDigits = 0;
64 };
65
66 std::map< int, internal > m_storage;
67
68
69 template <typename T>
70 int operator()(const T& e)
71 {
72 for (int j = 0; j < m_number_of_tracks; ++j) {
73
74 auto& track = m_storage[get_index(e, j)];
75 if (
76 std::abs(track.last_y - e.y_pos) < y_cutoff
77 ||
78 track.nDigits == 0
79 ) {
80 update_track(j, e);
81 return j;
82 }
83 }
84
85 const auto last_track = m_number_of_tracks - 1;
86 update_track(last_track, e);
87 return last_track;
88
89 }
90
91 template <typename T>
92 void update_track(int Track_ID, const T& e)
93 {
94 auto& track = m_storage[get_index(e, Track_ID)];
95 track.last_y = e.y_pos;
96 track.last_x = e.x_pos;
97 track.nDigits++;
98 }
99
100 };
101
103 template <typename Container_T>
104 auto operator()(const Container_T& container) const
105 {
106
107
108
109 int64_t sumX = 0, sumY = 0, sumXX = 0, sumXY = 0, sumYY = 0;
110 for (const auto& e : container) {
111 sumX += e.x_pos;
112 sumXX += e.x_pos * e.x_pos;
113
114 sumY += e.y_pos;
115 sumYY += e.y_pos * e.y_pos;
116
117 sumXY += e.x_pos * e.y_pos;
118 }
119 int64_t nHits = container.size();
120 int denom = sumXX * nHits - sumX * sumX;
121 if (denom == 0) {
122 return nt::ntuple(slopeXY(1e9), interceptXY(1e9), ipXY(1e9), chisqXY(1e9), Nhits(nHits));
123 }
124
125 auto slopeXY_ = slopeXY((double)(sumXY * nHits - sumX * sumY) / (double)denom);
126 auto interceptXY_ = interceptXY((double)(sumXX * sumY - sumX * sumXY) / (double)denom);
127
128 auto ipXY_ = ipXY(interceptXY_ * interceptXY_ * (1.0 - slopeXY_ * slopeXY_));
129
130 auto chisqXY_ = chisqXY(slopeXY_ * slopeXY_ * sumXX
131 + interceptXY_ * interceptXY_ * nHits
132 + sumYY
133 + 2.0 * slopeXY_ * interceptXY_ * sumX
134 - 2.0 * slopeXY_ * sumXY
135 - 2.0 * interceptXY_ * sumY);
136
137 return nt::ntuple(slopeXY_, interceptXY_, ipXY_, chisqXY_, Nhits(nHits));
138 }
139 };
140 constexpr Linear_fit_of_Hits_t Linear_fit_of_Hits;
141
142
143
144
145
146
147
148 void klm_trig_linear_fit_t::clear_geometry()
149 {
150 m_KLMgeomap.clear();
151
152 }
153
154 void klm_trig_linear_fit_t::add_geometry(const KLM_geo_fit_t& geometry)
155 {
156
157 m_KLMgeomap[get_index(geometry)] = geo_KLM_t{
158 geometry.slopeX,
159 geometry.offsetX,
160 geometry.slopeY,
161 geometry.offsetY
162 };
163
164
165 }
166
167 void klm_trig_linear_fit_t::run(const KLM_Digit_compact_ts& hits)
168 {
169
170 __CSV__WRITE__(hits);
171 m_linear_fits.clear();
172
173
174 auto hits_w_geo_fit = nt::algorithms::add_column(
175 hits,
176 [&](const auto & e1) {
177 auto ret = nt::ntuple(
178 Belle2::KLM_TRG_definitions::x_pos(0),
179 Belle2::KLM_TRG_definitions::y_pos(0)
180 );
181
182 auto&& e2 = m_KLMgeomap[get_index(e1)];
183 ret.x_pos.v = e1.layer * e2.slopeX + e2.offsetX;
184 ret.y_pos.v = e1.strip * e2.slopeY + e2.offsetY;
185 return ret;
186
187 }
188 );
189
190
191 __CSV__WRITE__(hits_w_geo_fit);
192 nt::algorithms::sort(hits_w_geo_fit);
193
194
195 auto track_maker_ = track_maker_t{};
196 track_maker_.y_cutoff = y_cutoff;
197
198
199 auto hits_w_geo_fit_w_tracks = nt::algorithms::add_column(
200 hits_w_geo_fit,
201 [&](const auto & e) {
202 return nt::ntuple{
203 track_id(track_maker_(e))
204 };
205
206
207 }
208
209 );
210
211
212 __CSV__WRITE__(hits_w_geo_fit_w_tracks);
213
214
215
216 m_linear_fits = nt_group(
217 hits_w_geo_fit_w_tracks[0].subdetector,
218 hits_w_geo_fit_w_tracks[0].section,
219 hits_w_geo_fit_w_tracks[0].sector,
220 hits_w_geo_fit_w_tracks[0].plane,
221 hits_w_geo_fit_w_tracks[0].track_id
222 ).apply_append(
223 hits_w_geo_fit_w_tracks,
224 Linear_fit_of_Hits
225 );
226 __CSV__WRITE__(m_linear_fits);
227
228
229 nt::algorithms::filter(m_linear_fits, [&](const auto & e) { return std::abs(e.interceptXY) <= m_intercept_cutoff; });
230
231
232 auto m_linear_fits1 = nt_group(
233 m_linear_fits[0].subdetector,
234 m_linear_fits[0].section,
235 m_linear_fits[0].sector
236 ).apply_append(
237 m_linear_fits,
238 [](const auto & es) {
239 bool plane0 = false;
240 bool plane1 = false;
241 for (const auto& e : es) {
242 if (e.plane == 0) { plane0 = true; }
243 if (e.plane == 1) { plane1 = true; }
244 }
245 return nt::ntuple{
246 ax_maker(trigger_or) = (int)(plane0 || plane1),
247 ax_maker(trigger_and) = (int)(plane0 && plane1)
248 };
249 }
250 );
251 __CSV__WRITE__(m_linear_fits1);
252
253 m_sections_trig = nt_group(
254 m_linear_fits1[0].subdetector,
255 m_linear_fits1[0].section
256 ).apply_append(
257 m_linear_fits1,
258 [](const auto & e) {
259 auto ret = nt::ntuple{
260 KLM_TRG_definitions::sector_mask {},
261 KLM_TRG_definitions::sector_mask_or{}
262 };
263 auto trig_and = nt::algorithms::filter_copy(e, [](const auto & x) { return x.trigger_and > 0; });
264 ret.sector_mask.v = Belle2::to_bit_mask< sector >(trig_and);
265 ret.sector_mask_or.v = Belle2::to_bit_mask< sector >(e);
266 return ret;
267
268 }
269 );
270 __CSV__WRITE__(m_sections_trig);
271
272
273 }
274
275 const KLM_trig_linear_fits& klm_trig_linear_fit_t::get_result() const
276 {
277 return m_linear_fits;
278 }
279
280
281
282 int klm_trig_linear_fit_t::get_triggermask(int subdetector, int section)
283 {
284 for (const auto& e : m_sections_trig) {
285 if (e.subdetector == subdetector && e.section == section) {
286 return e.sector_mask;
287 }
288 }
289 return 0;
290 }
291
292 int klm_trig_linear_fit_t::get_triggermask_or(int subdetector, int section)
293 {
294 for (const auto& e : m_sections_trig) {
295 if (e.subdetector == subdetector && e.section == section) {
296 return e.sector_mask_or;
297 }
298 }
299 return 0;
300 }
301
302 void klm_trig_linear_fit_t::set_y_cutoff(int cutoff)
303 {
304 y_cutoff = cutoff;
305 }
306
307 void klm_trig_linear_fit_t::set_intercept_cutoff(int cutoff)
308 {
309 m_intercept_cutoff = cutoff;
310 }
311
313}
314
315
Abstract base class for different kinds of events.