Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
LinkAssociations.h
Go to the documentation of this file.
1 // $Id:$
2 //
3 // File: LinkAssociations.h
4 // Created: Tue May 17 08:15:00 EDT 2016
5 // Creator: davidl (on Linux gluon49.jlab.org 2.6.32-431.20.3.el6.x86_64)
6 //
7 
8 #ifndef _LinkAssociations_
9 #define _LinkAssociations_
10 
11 #include <stdint.h>
12 #include <vector>
13 using std::vector;
14 
15 //==============================================================
16 // Sort Routines:
17 //
18 // These are used to sort object lists based on various
19 // members. This is needed for some of the more complex
20 // matching routines below.
21 
22 //----------------
23 // SortByROCID
24 //----------------
25 template<class T>
26 inline bool SortByROCID(const T* const &obj1, const T* const &obj2)
27 {
28  return obj1->rocid < obj2->rocid;
29 }
30 
31 //----------------
32 // SortByModule
33 //----------------
34 template<class T>
35 inline bool SortByModule(const T* const &obj1, const T* const &obj2)
36 {
37  if(obj1->rocid < obj2->rocid) return true;
38  if(obj1->rocid > obj2->rocid) return false;
39  return obj1->slot < obj2->slot;
40 }
41 
42 //----------------
43 // SortByChannel
44 //----------------
45 template<class T>
46 inline bool SortByChannel(const T* const &obj1, const T* const &obj2)
47 {
48  if(obj1->rocid < obj2->rocid ) return true;
49  if(obj1->rocid > obj2->rocid ) return false;
50  if(obj1->slot < obj2->slot ) return true;
51  if(obj1->slot > obj2->slot ) return false;
52  return obj1->channel < obj2->channel;
53 }
54 
55 //----------------
56 // SortByPulseNumber
57 //----------------
58 template<class T>
59 inline bool SortByPulseNumber(const T* const &obj1, const T* const &obj2)
60 {
61  if(obj1->rocid < obj2->rocid ) return true;
62  if(obj1->rocid > obj2->rocid ) return false;
63  if(obj1->slot < obj2->slot ) return true;
64  if(obj1->slot > obj2->slot ) return false;
65  if(obj1->channel < obj2->channel ) return true;
66  if(obj1->channel > obj2->channel ) return false;
67  return obj1->pulse_number < obj2->pulse_number;
68 }
69 
70 
71 //==============================================================
72 // What follows are 2 sets of routines used to add objects to
73 // other objects' associated objects lists. The first set of routines
74 // are what should be called externally. These call an appropriate
75 // matching routine, passing it a lambda function for what to do
76 // once a match is found. This may be as simple as adding one to the
77 // other's associated objects list. There are also a few cases where
78 // we need to do some additional copying such as the pedestal from a
79 // PulsePedestal object into the pedestal member of a PulseIntegral
80 // object.
81 
82 
83 // LinkConfig
84 template<class T, class U>
85 inline void LinkConfig(vector<T*> &a, vector<U*> &b)
86 { MatchConfigF(a, b, [](T *a, U *b){b->AddAssociatedObject(a);}); }
87 
88 // LinkConfigSamplesCopy
89 template<class T, class U>
90 inline void LinkConfigSamplesCopy(vector<T*> &a, vector<U*> &b)
91 { MatchConfigF(a, b, [](T *a, U *b){b->AddAssociatedObject(a); b->nsamples_integral = a->NSA_NSB; b->nsamples_pedestal = a->NPED;}); }
92 
93 // LinkModule
94 template<class T, class U>
95 inline void LinkModule(vector<T*> &a, vector<U*> &b)
96 { MatchModuleF(a, b, [](T *a, U *b){b->AddAssociatedObject(a);}); }
97 
98 // LinkModuleBORSamplesCopy
99 template<class T, class U>
100 inline void LinkModuleBORSamplesCopy(vector<T*> &a, vector<U*> &b)
101 { MatchModuleF(a, b, [](T *a, U *b){b->AddAssociatedObject(a); b->nsamples_integral = a->NSA+a->NSB; b->nsamples_pedestal = a->NPED;}); }
102 
103 // LinkChannel
104 template<class T, class U>
105 inline void LinkChannel(vector<T*> &a, vector<U*> &b)
106 { MatchChannelF(a, b, [](T *a, U *b){b->AddAssociatedObject(a); a->AddAssociatedObject(b);}); }
107 
108 // LinkPulse
109 template<class T, class U>
110 inline void LinkPulse(vector<T*> &a, vector<U*> &b)
111 { MatchPulseF(a, b, [](T *a, U *b){b->AddAssociatedObject(a);}); }
112 
113 // LinkPulsePedCopy
114 template<class T, class U>
115 inline void LinkPulsePedCopy(vector<T*> &a, vector<U*> &b)
116 { MatchPulseF(a, b, [](T *a, U *b){b->AddAssociatedObject(a); b->pedestal = a->pedestal;}); }
117 
118 // PulsePedCopy
119 template<class T, class U>
120 inline void PulsePedCopy(vector<T*> &a, vector<U*> &b)
121 { MatchPulseF(a, b, [](T *a, U *b){b->pedestal = a->pedestal;}); }
122 
123 
124 //----------------------------
125 // MatchConfig
126 //----------------------------
127 template<class T, class U, typename F>
128 void MatchConfig(vector<T*> &a, vector<U*> &b, F func)
129 {
130  for(auto bptr : b){
131  uint32_t slot_mask = 1 << bptr->slot;
132  for(auto aptr : a){
133  if(aptr->rocid!=bptr->rocid) continue;
134  if(aptr->slot_mask & slot_mask){
135  func(aptr, bptr);
136  }
137  }
138  }
139 }
140 
141 //----------------------------
142 // MatchModule
143 //----------------------------
144 template<class T, class U, typename F>
145 void MatchModule(vector<T*> &a, vector<U*> &b, F func)
146 {
147  for(auto aptr : a){
148  for(auto bptr : b){
149  if(aptr->rocid != bptr->rocid) continue;
150  if(aptr->slot != bptr->slot ) continue;
151  func(aptr, bptr);
152  }
153  }
154 }
155 
156 //----------------------------
157 // MatchChannel
158 //----------------------------
159 template<class T, class U, typename F>
160 void MatchChannel(vector<T*> &a, vector<U*> &b, F func)
161 {
162  for(auto aptr : a){
163  for(auto bptr : b){
164  if(aptr->rocid != bptr->rocid ) continue;
165  if(aptr->slot != bptr->slot ) continue;
166  if(aptr->channel!= bptr->channel) continue;
167  func(aptr, bptr);
168  }
169  }
170 }
171 
172 //----------------------------
173 // MatchPulse
174 //----------------------------
175 template<class T, class U, typename F>
176 void MatchPulse(vector<T*> &a, vector<U*> &b, F func)
177 {
178  for(auto aptr : a){
179  for(auto bptr : b){
180  if(aptr->rocid != bptr->rocid ) continue;
181  if(aptr->slot != bptr->slot ) continue;
182  if(aptr->channel != bptr->channel ) continue;
183  if(aptr->pulse_number != bptr->pulse_number) continue;
184  func(aptr, bptr);
185  }
186  }
187 }
188 
189 //==============================================================
190 // The following are alternatives to the matching routines
191 // above. These will step through both vectors simultaneously
192 // to find matching ranges as opposed to simply comparing each
193 // element of vector "a" with each element of vector "b". For this
194 // to work, both the a and b vectors must be sorted. The benefit
195 // here is a slight performance improvement (though it's a little
196 // hard to measure.) Providing the sorting has been done, these
197 // routines should each do the same thing as their counterparts
198 // that don't have the "F" suffix".
199 
200 
201 //----------------------------
202 // MatchConfigF
203 //----------------------------
204 template<class T, class U, typename F>
205 void MatchConfigF(vector<T*> &a, vector<U*> &b, F func)
206 {
207  /// Template routine to loop over two vectors: The first points
208  /// to DDAQConfig objects and the second to DDAQAddress objects.
209  /// DDAQAddress objects are matched by the rocid and slotmask of
210  /// the DDAQConfig object.
211  ///
212  /// Note that this assumes the input vectors have been sorted by
213  /// rocid in ascending order.
214 
215  // Bail early if nothing to link
216  if(b.empty()) return;
217  if(a.empty()) return;
218 
219  for(uint32_t i=0, j=0; i<b.size(); ){
220 
221  uint32_t rocid = b[i]->rocid;
222 
223  // Find start and end of range in b
224  uint32_t istart = i;
225  uint32_t iend = i+1; // index of first element outside of ROI
226  for(; iend<b.size(); iend++){
227  if(b[iend]->rocid != rocid) break;
228  }
229  i = iend; // setup for next iteration
230 
231  // Find start of range in a
232  for(; j<a.size(); j++){
233  if( a[j]->rocid >= rocid ) break;
234  }
235  if(j>=a.size()) break; // exhausted all a's. we're done
236  if( a[j]->rocid > rocid ) continue; // couldn't find rocid in a
237 
238  // Find end of range in a
239  uint32_t jend = j+1;
240  for(; jend<a.size(); jend++){
241  if(a[jend]->rocid != rocid) break;
242  }
243 
244  // Loop over all combos of both ranges and make associations
245  uint32_t jstart = j;
246  for(uint32_t ii=istart; ii<iend; ii++){
247  uint32_t slot_mask = 1 << b[ii]->slot;
248 
249  for(uint32_t jj=jstart; jj<jend; jj++){
250  if(a[jj]->slot_mask & slot_mask){
251  func(a[jj], b[ii]);
252  }
253  }
254  }
255  j = jend;
256 
257  if( i>=b.size() ) break;
258  if( j>=a.size() ) break;
259  }
260 }
261 
262 //----------------------------
263 // MatchModuleF
264 //----------------------------
265 template<class T, class U, typename F>
266 void MatchModuleF(vector<T*> &a, vector<U*> &b, F func)
267 {
268  /// Template routine to loop over two vectors of pointers to
269  /// objects derived from DDAQAddress. This will match any hits
270  /// coming from the same DAQ module (channel number is not checked)
271  ///
272  /// Note that this assumes the input vectors have been sorted by
273  /// rocid, then slot in ascending order.
274 
275  // Bail early if nothing to link
276  if(b.empty()) return;
277  if(a.empty()) return;
278 
279  for(uint32_t i=0, j=0; i<b.size(); ){
280 
281  uint32_t rocid = b[i]->rocid;
282  uint32_t slot = b[i]->slot;
283 
284  // Find start and end of range in b
285  uint32_t istart = i;
286  uint32_t iend = i+1; // index of first element outside of ROI
287  for(; iend<b.size(); iend++){
288  if(b[iend]->rocid != rocid) break;
289  if(b[iend]->slot != slot ) break;
290  }
291  i = iend; // setup for next iteration
292 
293  // Find start of range in a
294  for(; j<a.size(); j++){
295  if( a[j]->rocid > rocid ) break;
296  if( a[j]->rocid == rocid ){
297  if( a[j]->slot >= slot ) break;
298  }
299  }
300  if(j>=a.size()) break; // exhausted all a's. we're done
301 
302  if( a[j]->rocid > rocid ) continue; // couldn't find rocid in a
303  if( a[j]->slot > slot ) continue; // couldn't find slot in a
304 
305  // Find end of range in a
306  uint32_t jend = j+1;
307  for(; jend<a.size(); jend++){
308  if(a[jend]->rocid != rocid) break;
309  if(a[jend]->slot != slot ) break;
310  }
311 
312  // Loop over all combos of both ranges and make associations
313  uint32_t jstart = j;
314  for(uint32_t ii=istart; ii<iend; ii++){
315  for(uint32_t jj=jstart; jj<jend; jj++){
316  func(a[jj], b[ii]);
317  }
318  }
319  j = jend;
320 
321  if( i>=b.size() ) break;
322  if( j>=a.size() ) break;
323  }
324 }
325 
326 //----------------------------
327 // MatchChannelF
328 //----------------------------
329 template<class T, class U, typename F>
330 void MatchChannelF(vector<T*> &a, vector<U*> &b, F func)
331 {
332  /// Template routine to loop over two vectors of pointers to
333  /// objects derived from DDAQAddress. This will match any hits
334  /// coming from the same DAQ module and channel.
335  ///
336  /// Note that this assumes the input vectors have been sorted by
337  /// rocid, then slot in ascending order.
338 
339  // Bail early if nothing to link
340  if(b.empty()) return;
341  if(a.empty()) return;
342 
343  for(uint32_t i=0, j=0; i<b.size(); ){
344 
345  uint32_t rocid = b[i]->rocid;
346  uint32_t slot = b[i]->slot;
347  uint32_t channel = b[i]->channel;
348 
349  // Find start and end of range in b
350  uint32_t istart = i;
351  uint32_t iend = i+1; // index of first element outside of ROI
352  for(; iend<b.size(); iend++){
353  if(b[iend]->rocid != rocid ) break;
354  if(b[iend]->slot != slot ) break;
355  if(b[iend]->channel != channel ) break;
356  }
357  i = iend; // setup for next iteration
358 
359  // Find start of range in a
360  for(; j<a.size(); j++){
361  if( a[j]->rocid > rocid ) break;
362  if( a[j]->rocid == rocid ){
363  if( a[j]->slot > slot ) break;
364  if( a[j]->slot == slot ){
365  if( a[j]->channel >= channel ) break;
366  }
367  }
368  }
369  if(j>=a.size()) break; // exhausted all a's. we're done
370 
371  if( a[j]->rocid > rocid ) continue; // couldn't find rocid in a
372  if( a[j]->slot > slot ) continue; // couldn't find slot in a
373  if( a[j]->channel > channel ) continue; // couldn't find channel in a
374 
375  // Find end of range in a
376  uint32_t jend = j+1;
377  for(; jend<a.size(); jend++){
378  if(a[jend]->rocid != rocid ) break;
379  if(a[jend]->slot != slot ) break;
380  if(a[jend]->channel != channel ) break;
381  }
382 
383  // Loop over all combos of both ranges and make associations
384  uint32_t jstart = j;
385  for(uint32_t ii=istart; ii<iend; ii++){
386  for(uint32_t jj=jstart; jj<jend; jj++){
387  func(a[jj], b[ii]);
388  }
389  }
390  j = jend;
391 
392  if( i>=b.size() ) break;
393  if( j>=a.size() ) break;
394  }
395 }
396 
397 //----------------------------
398 // MatchPulseF
399 //----------------------------
400 template<class T, class U, typename F>
401 void MatchPulseF(vector<T*> &a, vector<U*> &b, F func)
402 {
403  /// Template routine to loop over two vectors of pointers to
404  /// objects derived from DDAQAddress. This will match any hits
405  /// coming from the same DAQ module, channel with the same pulse
406  /// number.
407  ///
408  /// Note that this assumes the input vectors have been sorted by
409  /// rocid, then slot in ascending order.
410 
411  // Bail early if nothing to link
412  if(b.empty()) return;
413  if(a.empty()) return;
414 
415  for(uint32_t i=0, j=0; i<b.size(); ){
416 
417  uint32_t rocid = b[i]->rocid;
418  uint32_t slot = b[i]->slot;
419  uint32_t channel = b[i]->channel;
420  uint32_t pulse_number = b[i]->pulse_number;
421 
422  // Find start and end of range in b
423  uint32_t istart = i;
424  uint32_t iend = i+1; // index of first element outside of ROI
425  for(; iend<b.size(); iend++){
426  if(b[iend]->rocid != rocid ) break;
427  if(b[iend]->slot != slot ) break;
428  if(b[iend]->channel != channel ) break;
429  if(b[iend]->pulse_number != pulse_number ) break;
430  }
431  i = iend; // setup for next iteration
432 
433  // Find start of range in a
434  for(; j<a.size(); j++){
435  if( a[j]->rocid > rocid ) break;
436  if( a[j]->rocid == rocid ){
437  if( a[j]->slot > slot ) break;
438  if( a[j]->slot == slot ){
439  if( a[j]->channel > channel ) break;
440  if( a[j]->channel == channel ){
441  if( a[j]->pulse_number >= pulse_number ) break;
442  }
443  }
444  }
445  }
446  if(j>=a.size()) break; // exhausted all a's. we're done
447 
448  if( a[j]->rocid > rocid ) continue; // couldn't find rocid in a
449  if( a[j]->slot > slot ) continue; // couldn't find slot in a
450  if( a[j]->channel > channel ) continue; // couldn't find channel in a
451  if( a[j]->pulse_number > pulse_number ) continue; // couldn't find pulse_number in a
452 
453  // Find end of range in a
454  uint32_t jend = j+1;
455  for(; jend<a.size(); jend++){
456  if(a[jend]->rocid != rocid ) break;
457  if(a[jend]->slot != slot ) break;
458  if(a[jend]->channel != channel ) break;
459  if(a[jend]->pulse_number != pulse_number ) break;
460  }
461 
462  // Loop over all combos of both ranges and make associations
463  uint32_t jstart = j;
464  for(uint32_t ii=istart; ii<iend; ii++){
465  for(uint32_t jj=jstart; jj<jend; jj++){
466  func(a[jj], b[ii]);
467  }
468  }
469  j = jend;
470 
471  if( i>=b.size() ) break;
472  if( j>=a.size() ) break;
473  }
474 }
475 
476 #endif // _LinkAssociations_
477 
#define F(x, y, z)
double func(double *x, double *par)
Definition: timewalk_fits.C:16