JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
QwLinearDiodeArray.cc
Go to the documentation of this file.
1/**********************************************************\
2* File: QwLinearDiodeArray.cc *
3* *
4* Author: B. Waidyawansa *
5* Time-stamp: 09-14-2010 *
6\**********************************************************/
7
9
10// System headers
11#include <stdexcept>
12
13// ROOT headers for RNTuple support
14#ifdef HAS_RNTUPLE_SUPPORT
15#include <ROOT/RNTupleModel.hxx>
16#include <ROOT/RNTupleWriter.hxx>
17#endif // HAS_RNTUPLE_SUPPORT
18
19// Qweak headers
20#include "QwParameterFile.h"
21#ifdef __USE_DATABASE__
22#include "QwDBInterface.h"
23#endif // __USE_DATABASE__
24
25template <typename ChannelType>
27
28/*Individual pads of the linear array*/
29template <typename ChannelType>
30const TString QwLinearDiodeArray<ChannelType>::subelement[8]={"p1","p2","p3","p4","p5","p6","p7","p8"};
31
32/* Pad size in mm*/
33template <typename ChannelType>
35
36/**
37 * \brief Initialize this linear diode array with a detector name.
38 * \param name Detector name used for subchannel naming.
39 */
40template <typename ChannelType>
42{
43
44 Int_t i=0;
45 Bool_t localdebug = kFALSE;
47
48 for(i=0;i<8;i++) {
49 fPhotodiode[i].InitializeChannel(name+subelement[i],"raw");
50
51 if(localdebug)
52 std::cout<<" photodiode ["<<i<<"]="<<fPhotodiode[i].GetElementName()<<"\n";
53 }
54
55
56 fEffectiveCharge.InitializeChannel(name+"WS","derived");
57
58 // We don't initialize the photodiode channels yet.
59 fRelPos[0].InitializeChannel(name+"RelMean","derived");
60 fRelPos[1].InitializeChannel(name+"RelVariance","derived");
61
62 bFullSave=kTRUE;
63
64 return;
65}
66
67/**
68 * \brief Initialize this linear diode array with subsystem and name.
69 * \param subsystem Subsystem identifier.
70 * \param name Detector name used for subchannel naming.
71 */
72template <typename ChannelType>
73void QwLinearDiodeArray<ChannelType>::InitializeChannel(TString subsystem, TString name)
74{
75
76 Int_t i=0;
77 Bool_t localdebug = kFALSE;
78
80
81 for(i=0;i<8;i++) {
82 fPhotodiode[i].InitializeChannel(subsystem, "QwLinearDiodeArray", name+subelement[i],"raw");
83 if(localdebug)
84 std::cout<<" photodiode ["<<i<<"]="<<fPhotodiode[i].GetElementName()<<"\n";
85 }
86
87 fEffectiveCharge.InitializeChannel(subsystem, "QwLinearDiodeArray", name+"WS","derived");
88
89 // We don't initialize the photodiode channels yet.
90
91 fRelPos[0].InitializeChannel(subsystem, "QwLinearDiodeArray", name+"RelMean","derived");
92 fRelPos[1].InitializeChannel(subsystem, "QwLinearDiodeArray", name+"RelVariance","derived");
93
94 bFullSave=kTRUE;
95
96 return;
97}
98
99/** \brief Clear event-scoped data for all pads and derived channels. */
100template <typename ChannelType>
102{
103 size_t i=0;
104
105 for(i=0;i<8;i++) fPhotodiode[i].ClearEventData();
106
107 for(i=kXAxis;i<kNumAxes;i++){
108 fRelPos[i].ClearEventData();
109 }
110 fEffectiveCharge.ClearEventData();
111
112 return;
113}
114
115
116/**
117 * \brief Apply hardware checks for all photodiode pads.
118 * \return kTRUE if no hardware error was detected; otherwise kFALSE.
119 */
120template <typename ChannelType>
122{
123 Bool_t eventokay=kTRUE;
124
125 UInt_t deviceerror=0;
126 for(size_t i=0;i<8;i++)
127 {
128 deviceerror|= fPhotodiode[i].ApplyHWChecks(); //OR the error code from each wire
129 eventokay &= (deviceerror & 0x0);//AND with 0 since zero means HW is good.
130
131 if (bDEBUG) std::cout<<" Inconsistent within LinearArray terminals photodiode[ "<<i<<" ] "<<std::endl;
132 if (bDEBUG) std::cout<<" photodiode[ "<<i<<" ] sequence num "<<fPhotodiode[i].GetSequenceNumber()<<" sample size "<<fPhotodiode[i].GetNumberOfSamples()<<std::endl;
133 }
134
135 return eventokay;
136}
137
138/** \brief Increment error counters for all internal channels. */
139template <typename ChannelType>
141{
142 size_t i=0;
143 for(i=0;i<8;i++) fPhotodiode[i].IncrementErrorCounters();
144 for(i=kXAxis;i<kNumAxes;i++) {
145 fRelPos[i].IncrementErrorCounters();
146 }
147 fEffectiveCharge.IncrementErrorCounters();
148}
149
150/** \brief Print error counters for all internal channels. */
151template <typename ChannelType>
153{
154 size_t i=0;
155 for(i=0;i<8;i++) fPhotodiode[i].PrintErrorCounters();
156 for(i=kXAxis;i<kNumAxes;i++) {
157 fRelPos[i].PrintErrorCounters();
158 }
159 fEffectiveCharge.PrintErrorCounters();
160}
161
162/** \brief Aggregate and return the event-cut error flag for this array. */
163template <typename ChannelType>
165{
166 size_t i=0;
167 UInt_t error=0;
168 for(i=0;i<8;i++) error|=fPhotodiode[i].GetEventcutErrorFlag();
169 for(i=kXAxis;i<kNumAxes;i++) {
170 error|=fRelPos[i].GetEventcutErrorFlag();
171 }
172 error|=fEffectiveCharge.GetEventcutErrorFlag();
173
174 return error;
175}
176
177/** \brief Update and return the aggregated event-cut error flag. */
178template <typename ChannelType>
180{
181 size_t i=0;
182 UInt_t error1=0;
183 UInt_t error2=0;
184 for(i=0;i<8;i++){
185 error1|=fPhotodiode[i].GetErrorCode();
186 error2|=fPhotodiode[i].GetEventcutErrorFlag();
187 }
188 for(i=kXAxis;i<kNumAxes;i++) {
189 fRelPos[i].UpdateErrorFlag(error1);
190 error2|=fRelPos[i].GetEventcutErrorFlag();
191 }
192 fEffectiveCharge.UpdateErrorFlag(error1);
193 error2|=fEffectiveCharge.GetEventcutErrorFlag();
194 return error2;
195}
196
197/**
198 * \brief Apply single-event cuts across photodiodes and derived channels.
199 * \return kTRUE if the event passes all configured cuts; otherwise kFALSE.
200 */
201template <typename ChannelType>
203{
204 Bool_t status=kTRUE;
205 size_t i=0;
206 UInt_t error_code = 0;
207 //Event cuts for four wires
208 for(i=0;i<8;i++){
210 status&=kTRUE;
211 }
212 else{
213 status&=kFALSE;
214 if (bDEBUG) std::cout<<" array ["<<i<<"] event cut failed ";
215 }
216 //Get the Event cut error flag for wires
217 error_code|=fPhotodiode[i].GetErrorCode();
218 }
219
220 //Event cuts for Relative X & Y
221 for(i=kXAxis;i<kNumAxes;i++){
222 fRelPos[i].UpdateErrorFlag(error_code);//To update the event cut failed error code from the channels/wires error codes
223 if (fRelPos[i].ApplySingleEventCuts()){ //for RelX
224 status&=kTRUE;
225 }
226 else{
227 status&=kFALSE;
228 if (bDEBUG) std::cout<<" Rel X event cut failed ";
229 }
230 }
231
232 //Event cuts for four wire sum (EffectiveCharge)
233 fEffectiveCharge.UpdateErrorFlag(error_code);//To update the eff-charge error code from the channels/wires event cut error codes
234 if (fEffectiveCharge.ApplySingleEventCuts()){
235 status&=kTRUE;
236 }
237 else{
238 status&=kFALSE;
239 if (bDEBUG) std::cout<<"EffectiveCharge event cut failed ";
240 }
241 return status;
242}
243
244
245/**
246 * \brief Resolve an internal channel pointer by subelement name.
247 * \param ch_name Subelement symbolic name (e.g., relx, rely, absx, absy).
248 * \return Non-owning pointer to the requested hardware channel.
249 */
250template <typename ChannelType>
252{
253 VQwHardwareChannel* tmpptr = NULL;
254 ch_name.ToLower();
255 if (ch_name=="relx"){
256 tmpptr = &fRelPos[0];
257 }else if (ch_name=="rely"){
258 tmpptr = &fRelPos[1];
259 }else if (ch_name=="absx" || ch_name=="x" ){
260 tmpptr = &fAbsPos[0];
261 }else if (ch_name=="absy" || ch_name=="y"){
262 tmpptr = &fAbsPos[1];
263 }else if (ch_name=="effectivecharge" || ch_name=="charge"){
264 tmpptr = &fEffectiveCharge;
265 } else {
266 TString loc="QwLinearDiodeArray::GetSubelementByName for"
267 + this->GetElementName() + " was passed "
268 + ch_name + ", which is an unrecognized subelement name.";
269 throw std::invalid_argument(loc.Data());
270 }
271 return tmpptr;
272}
273
274/*
275void QwLinearDiodeArray<ChannelType>::SetSingleEventCuts(TString ch_name, Double_t minX, Double_t maxX)
276{
277 QwWarning << "QwLinearDiodeArray::SetSingleEventCuts: "
278 << "Does not do anything yet." << QwLog::endl;
279}*/
280
281/**
282 * \brief Configure detailed single-event cuts for a named subelement.
283 * \param ch_name Subelement name.
284 * \param errorflag Device-specific error flag mask to set.
285 * \param minX Lower limit.
286 * \param maxX Upper limit.
287 * \param stability Stability threshold.
288 * \param burplevel Burp detection threshold.
289 */
290template <typename ChannelType>
291void QwLinearDiodeArray<ChannelType>::SetSingleEventCuts(TString ch_name, UInt_t errorflag,Double_t minX, Double_t maxX, Double_t stability, Double_t burplevel){
292 errorflag|=kBPMErrorFlag;//update the device flag (Do not have a error flag yet)
293 // QwWarning << "QwLinearDiodeArray::SetSingleEventCuts: " << "Does not do anything yet." << QwLog::endl;
294 if (ch_name=="relx"){
295 QwMessage<<"RelX LL " << minX <<" UL " << maxX <<QwLog::endl;
296 fRelPos[0].SetSingleEventCuts(errorflag,minX,maxX,stability,burplevel);
297
298 }else if (ch_name=="rely"){
299 QwMessage<<"RelY LL " << minX <<" UL " << maxX <<QwLog::endl;
300 fRelPos[1].SetSingleEventCuts(errorflag,minX,maxX,stability,burplevel);
301
302 } else if (ch_name=="effectivecharge"){
303 QwMessage<<"EffectveQ LL " << minX <<" UL " << maxX <<QwLog::endl;
304 fEffectiveCharge.SetSingleEventCuts(errorflag,minX,maxX,stability,burplevel);
305
306 } else if (ch_name=="photodiode"){
307 QwMessage<<"photodiode LL " << minX <<" UL " << maxX <<QwLog::endl;
308 fPhotodiode[1].SetSingleEventCuts(errorflag,minX,maxX,stability,burplevel);
309 }
310}
311
312/**
313 * \brief Check for burp failures against another linear array of same type.
314 * \param ev_error Reference array to compare against.
315 * \return kTRUE if a burp failure was detected; otherwise kFALSE.
316 */
317template <typename ChannelType>
319 Short_t i=0;
320 Bool_t burpstatus = kFALSE;
321 try {
322 if(typeid(*ev_error)==typeid(*this)) {
323 //std::cout<<" Here in QwLinearDiodeArray::CheckForBurpFail \n";
324 if (this->GetElementName()!="") {
325 const QwLinearDiodeArray* value_lin = dynamic_cast<const QwLinearDiodeArray* >(ev_error);
326 for(i=kXAxis;i<kNumAxes;i++) {
327 burpstatus |= fRelPos[i].CheckForBurpFail(&(value_lin->fRelPos[i]));
328 }
329 for(i=0;i<8;i++){
330 burpstatus |= fPhotodiode[i].CheckForBurpFail(&(value_lin->fPhotodiode[i]));
331 }
332 burpstatus |= fEffectiveCharge.CheckForBurpFail(&(value_lin->fEffectiveCharge));
333 }
334 } else {
335 TString loc="Standard exception from QwLinearDiodeArray::CheckForBurpFail :"+
336 ev_error->GetElementName()+" "+this->GetElementName()+" are not of the "
337 +"same type";
338 throw std::invalid_argument(loc.Data());
339 }
340 } catch (std::exception& e) {
341 std::cerr<< e.what()<<std::endl;
342 }
343 return burpstatus;
344};
345
346template <typename ChannelType>
348 Short_t i=0;
349 try {
350 if(typeid(*ev_error)==typeid(*this)) {
351 // std::cout<<" Here in QwQPD::UpdateErrorFlag \n";
352 if (this->GetElementName()!="") {
353 const QwLinearDiodeArray* value_bpm = dynamic_cast<const QwLinearDiodeArray* >(ev_error);
354 for(i=0;i<4;i++){
355 fPhotodiode[i].UpdateErrorFlag(value_bpm->fPhotodiode[i]);
356 }
357 for(i=kXAxis;i<kNumAxes;i++) {
358 fRelPos[i].UpdateErrorFlag(value_bpm->fRelPos[i]);
359 }
360 fEffectiveCharge.UpdateErrorFlag(value_bpm->fEffectiveCharge);
361 }
362 } else {
363 TString loc="Standard exception from QwLinearDiodeArray::UpdateErrorFlag :"+
364 ev_error->GetElementName()+" "+this->GetElementName()+" are not of the "
365 +"same type";
366 throw std::invalid_argument(loc.Data());
367 }
368 } catch (std::exception& e) {
369 std::cerr<< e.what()<<std::endl;
370 }
371};
372
373template <typename ChannelType>
375{
376 Bool_t localdebug = kFALSE;
377 static ChannelType mean, meansqr;
378 static ChannelType tmp("tmp");
379 static ChannelType tmp2("tmp2");
380
381 mean.InitializeChannel("mean","raw");
382 meansqr.InitializeChannel("meansqr","raw");
383
384
385 size_t i = 0;
386
387
389 //first apply HW checks and update HW error flags.
390 // Calling this routine here and not in ApplySingleEventCuts
391 //makes a difference for a LinearArrays because they have derived devices.
392
393 fEffectiveCharge.ClearEventData();
394 for(i=0;i<8;i++){
395 fPhotodiode[i].ProcessEvent();
397 }
398
399
400 // First calculate the mean pad position and mean of squared pad position
401 // with respect to the center of the array, in units of pad spacing.
402 mean.ClearEventData();
403 meansqr.ClearEventData();
404 for (i=0;i<8;i++){
405 Double_t pos = kQwLinearDiodeArrayPadSize*i*0.5;
406 tmp = fPhotodiode[i];
407 tmp.Scale(pos); // Scale for S(i)*pos
408 mean+=tmp;
409 tmp.Scale(pos); // Scale again for S(i)*(pos**2)
410 meansqr+=tmp;
411 }
412 fRelPos[0].Ratio(mean,fEffectiveCharge);
413 tmp = meansqr;
414 meansqr.Ratio(tmp,fEffectiveCharge);
415 tmp2.Product(fRelPos[0], fRelPos[0]);
416
417 // Now calculate the variance
418 fRelPos[1].Difference(meansqr,tmp2);
419
420 if(localdebug){
421 std::cout<<"\n#################"<<std::endl;
422 std::cout<<" LinearArray name="<<fElementName<<std::endl;
423 std::cout<<" Size of the linear array = "<<8<<std::endl;
424 std::cout<<" event number= "<<fPhotodiode[0].GetSequenceNumber()<<std::endl;
425 for(Int_t i = 0; i<8; i++)
426 std::cout<<" pad"<<i<<" ="<<fPhotodiode[i].GetValue()<<std::endl;
427 std::cout<<" mean ="<<fRelPos[0].GetValue()<<std::endl;
428 std::cout<<" variance ="<<fRelPos[1].GetValue()<<std::endl;
429 std::cout<<" total charge ="<<fEffectiveCharge.GetValue()<<std::endl;
430
431 }
432
433 return;
434}
435
436template <typename ChannelType>
437Int_t QwLinearDiodeArray<ChannelType>::ProcessEvBuffer(UInt_t* buffer, UInt_t word_position_in_buffer,UInt_t index)
438{
439 if(index<8)
440 {
441 fPhotodiode[index].ProcessEvBuffer(buffer,word_position_in_buffer);
442 }
443 else
444 {
445 std::cerr <<
446 "QwLinearDiodeArray::ProcessEvBuffer(): attempt to fill in raw data for a pad that doesn't exist \n";
447 }
448 return word_position_in_buffer;
449}
450
451
452template <typename ChannelType>
454{
455 for (size_t i = 0; i < 2; i++) {
456 fRelPos[i].PrintValue();
457 }
458 return;
459}
460
461template <typename ChannelType>
463{
464 size_t i = 0;
465 for (i = 0; i < 8; i++) fPhotodiode[i].PrintInfo();
466 for (i = 0; i < 2; i++) {
467 fAbsPos[i].PrintInfo();
468 }
469 fEffectiveCharge.PrintInfo();
470}
471
472template <typename ChannelType>
474{
475 TString thisname;
476 size_t localindex=kInvalidSubelementIndex;
477 if (subindex>-1) localindex = subindex;
478
479 if(localindex<8)
480 thisname=fPhotodiode[subindex].GetElementName();
481 else
482 std::cerr<< "QwLinearDiodeArray::GetSubElementName for "
483 << GetElementName()<<" this subindex, "
484 << subindex << ", doesn't exist \n";
485
486 return thisname;
487}
488
489template <typename ChannelType>
491{
492 size_t localindex=kInvalidSubelementIndex;
493 TString padindex;
494
495 padindex = subname(subname.Sizeof()-2,1);
496 // Interpret the subname as the pad index.
497 if (padindex.IsDigit()){
498 Int_t tmpval = padindex.Atoi();
499 if (tmpval>-1) localindex = tmpval-1;
500 }
501
502 // localindex is unsigned int and always positive
503 if (localindex > kMaxElements){
504 std::cerr << "QwLinearDiodeArray::GetSubElementIndex is unable to associate the string -"
505 <<subname<<"- to any index"<<std::endl;
506 localindex=kInvalidSubelementIndex;
507 }
508 return localindex;
509}
510
511template <typename ChannelType>
513{
514 for(size_t i=kXAxis;i<kNumAxes;i++){
515 fAbsPos[i].AddChannelOffset(fPositionCenter[i]);
516 }
517
518}
519
520
521template <typename ChannelType>
523{
524 *(dynamic_cast<QwLinearDiodeArray*>(this)) =
525 *(dynamic_cast<const QwLinearDiodeArray*>(&value));
526 return *this;
527}
528
529template <typename ChannelType>
531{
532 VQwBPM::operator= (value);
533
534 if (GetElementName()!=""){
535 size_t i = 0;
537 for(i=0;i<8;i++) this->fPhotodiode[i]=value.fPhotodiode[i];
538 for(i=kXAxis;i<kNumAxes;i++) {
539 this->fRelPos[i]=value.fRelPos[i];
540 }
541 }
542 return *this;
543}
544
545template <typename ChannelType>
547{
548 *(dynamic_cast<QwLinearDiodeArray*>(this)) +=
549 *(dynamic_cast<const QwLinearDiodeArray*>(&value));
550 return *this;
551}
552
553template <typename ChannelType>
555{
556
557 if (GetElementName()!=""){
558 size_t i = 0;
560 for(i=0;i<8;i++) this->fPhotodiode[i]+=value.fPhotodiode[i];
561 for(i=kXAxis;i<kNumAxes;i++) {
562 this->fRelPos[i]+=value.fRelPos[i];
563 }
564 }
565 return *this;
566}
567
568template <typename ChannelType>
570{
571 *(dynamic_cast<QwLinearDiodeArray*>(this)) -=
572 *(dynamic_cast<const QwLinearDiodeArray*>(&value));
573 return *this;
574}
575
576template <typename ChannelType>
578{
579
580 if (GetElementName()!=""){
581 size_t i = 0;
583 for(i=0;i<8;i++) this->fPhotodiode[i]-=value.fPhotodiode[i];
584 for(i=kXAxis;i<kNumAxes;i++) {
585 this->fRelPos[i]-=value.fRelPos[i];
586 }
587 }
588 return *this;
589}
590
591
592template <typename ChannelType>
594{
595 // this function is called when forming asymmetries. In this case what we actually want for the
596 // LinearArray is the difference only not the asymmetries
597
598 *this=numer;
599 this->fEffectiveCharge.Ratio(numer.fEffectiveCharge,denom.fEffectiveCharge);
600 return;
601}
602
603template <typename ChannelType>
605{
606 Ratio(*(dynamic_cast<QwLinearDiodeArray*>(&numer)), *(dynamic_cast<QwLinearDiodeArray*>(&denom)));
607}
608
609
610template <typename ChannelType>
612{
613 size_t i = 0;
614 fEffectiveCharge.Scale(factor);
615
616 for(i=0;i<8;i++) fPhotodiode[i].Scale(factor);
617 for(i=kXAxis;i<kNumAxes;i++){
618 fRelPos[i].Scale(factor);
619 }
620 return;
621}
622
623
624template <typename ChannelType>
626{
627 size_t i = 0;
628 for(i=0;i<8;i++) fPhotodiode[i].CalculateRunningAverage();
629 for (i = 0; i < 2; i++) fRelPos[i].CalculateRunningAverage();
630 fEffectiveCharge.CalculateRunningAverage();
631 return;
632}
633
634template <typename ChannelType>
635void QwLinearDiodeArray<ChannelType>::AccumulateRunningSum(const VQwBPM& value, Int_t count, Int_t ErrorMask){
636 AccumulateRunningSum(*dynamic_cast<const QwLinearDiodeArray* >(&value), count, ErrorMask);
637}
638
639template <typename ChannelType>
640void QwLinearDiodeArray<ChannelType>::AccumulateRunningSum(const QwLinearDiodeArray& value, Int_t count, Int_t ErrorMask)
641{
642 size_t i = 0;
643 for(i=0;i<8;i++) fPhotodiode[i].AccumulateRunningSum(value.fPhotodiode[i], count, ErrorMask);
644 for (i = 0; i < 2; i++) fRelPos[i].AccumulateRunningSum(value.fRelPos[i], count, ErrorMask);
645 fEffectiveCharge.AccumulateRunningSum(value.fEffectiveCharge, count, ErrorMask);
646 return;
647}
648
649template <typename ChannelType>
651 DeaccumulateRunningSum(*dynamic_cast<QwLinearDiodeArray* >(&value), ErrorMask);
652}
653
654template <typename ChannelType>
656{
657 size_t i = 0;
658 for(i=0;i<8;i++) fPhotodiode[i].DeaccumulateRunningSum(value.fPhotodiode[i], ErrorMask);
659 for (i = 0; i < 2; i++) fRelPos[i].DeaccumulateRunningSum(value.fRelPos[i], ErrorMask);
660 fEffectiveCharge.DeaccumulateRunningSum(value.fEffectiveCharge, ErrorMask);
661 return;
662}
663
664
665
666template <typename ChannelType>
667void QwLinearDiodeArray<ChannelType>::ConstructHistograms(TDirectory *folder, TString &prefix)
668{
669
670 if (GetElementName()=="") {
671 // This channel is not used, so skip filling the histograms.
672 } else {
673 fEffectiveCharge.ConstructHistograms(folder, prefix);
674 TString thisprefix=prefix;
675
676 if(prefix.Contains("asym_"))
677 thisprefix.ReplaceAll("asym_","diff_");
678 SetRootSaveStatus(prefix);
679 size_t i = 0;
680 if(bFullSave) {
681 for(i=0;i<8;i++) fPhotodiode[i].ConstructHistograms(folder, thisprefix);
682 }
683 for(i=kXAxis;i<kNumAxes;i++) {
684 fRelPos[i].ConstructHistograms(folder, thisprefix);
685 }
686 }
687 return;
688}
689
690template <typename ChannelType>
692{
693 if (GetElementName()=="") {
694 // This channel is not used, so skip filling the histograms.
695 }
696 else {
697 fEffectiveCharge.FillHistograms();
698 size_t i = 0;
699 if(bFullSave) {
700 for(i=0;i<8;i++) fPhotodiode[i].FillHistograms();
701 }
702 for(i=kXAxis;i<kNumAxes;i++){
703 fRelPos[i].FillHistograms();
704 }
705 }
706 return;
707}
708
709template <typename ChannelType>
711{
712 if (GetElementName()==""){
713 // This channel is not used, so skip constructing trees.
714 }
715 else {
716 TString thisprefix=prefix;
717 if(prefix.Contains("asym_"))
718 thisprefix.ReplaceAll("asym_","diff_");
719
720 SetRootSaveStatus(prefix);
721
722 fEffectiveCharge.ConstructBranchAndVector(tree,prefix,values);
723 size_t i = 0;
724 if(bFullSave) {
725 for(i=0;i<8;i++) fPhotodiode[i].ConstructBranchAndVector(tree,thisprefix,values);
726 }
727 for(i=kXAxis;i<kNumAxes;i++) {
728 fRelPos[i].ConstructBranchAndVector(tree,thisprefix,values);
729 }
730
731 }
732 return;
733}
734
735template <typename ChannelType>
736void QwLinearDiodeArray<ChannelType>::ConstructBranch(TTree *tree, TString &prefix)
737{
738 if (GetElementName()==""){
739 // This channel is not used, so skip constructing trees.
740 }
741 else {
742 TString thisprefix=prefix;
743 if(prefix.Contains("asym_"))
744 thisprefix.ReplaceAll("asym_","diff_");
745
746 SetRootSaveStatus(prefix);
747
748 fEffectiveCharge.ConstructBranch(tree,prefix);
749 size_t i = 0;
750 if(bFullSave) {
751 for(i=0;i<8;i++) fPhotodiode[i].ConstructBranch(tree,thisprefix);
752 }
753 for(i=kXAxis;i<kNumAxes;i++) {
754 fRelPos[i].ConstructBranch(tree,thisprefix);
755 }
756
757 }
758 return;
759}
760
761template <typename ChannelType>
762void QwLinearDiodeArray<ChannelType>::ConstructBranch(TTree *tree, TString &prefix, QwParameterFile& modulelist)
763{
764 TString devicename;
765
766 devicename=GetElementName();
767 devicename.ToLower();
768 if (GetElementName()==""){
769 // This channel is not used, so skip filling the histograms.
770 } else
771 {
772 if (modulelist.HasValue(devicename)){
773 TString thisprefix=prefix;
774 if(prefix.Contains("asym_"))
775 thisprefix.ReplaceAll("asym_","diff_");
776
777 SetRootSaveStatus(prefix);
778
779 fEffectiveCharge.ConstructBranch(tree,prefix);
780 size_t i = 0;
781 if(bFullSave) {
782 for(i=0;i<8;i++) fPhotodiode[i].ConstructBranch(tree,thisprefix);
783 }
784 for(i=kXAxis;i<kNumAxes;i++) {
785 fRelPos[i].ConstructBranch(tree,thisprefix);
786 }
787
788 QwMessage <<" Tree leaves added to "<<devicename<<" Corresponding channels"<<QwLog::endl;
789 }
790 // this functions doesn't do anything yet
791 }
792
793
794
795
796
797 return;
798}
799
800template <typename ChannelType>
802{
803 if (GetElementName()=="") {
804 // This channel is not used, so skip filling the tree.
805 }
806 else {
807 fEffectiveCharge.FillTreeVector(values);
808 size_t i = 0;
809 if(bFullSave) {
810 for(i=0;i<8;i++) fPhotodiode[i].FillTreeVector(values);
811 }
812 for(i=kXAxis;i<kNumAxes;i++){
813 fRelPos[i].FillTreeVector(values);
814 }
815 }
816 return;
817}
818
819#ifdef HAS_RNTUPLE_SUPPORT
820template <typename ChannelType>
821void QwLinearDiodeArray<ChannelType>::ConstructNTupleAndVector(std::unique_ptr<ROOT::RNTupleModel>& model, TString& prefix, std::vector<Double_t>& values, std::vector<std::shared_ptr<Double_t>>& fieldPtrs)
822{
823 if (GetElementName()==""){
824 // This channel is not used, so skip constructing.
825 }
826 else {
827 TString thisprefix=prefix;
828 if(prefix.Contains("asym_"))
829 thisprefix.ReplaceAll("asym_","diff_");
830
831 SetRootSaveStatus(prefix);
832
833 fEffectiveCharge.ConstructNTupleAndVector(model,prefix,values,fieldPtrs);
834 size_t i = 0;
835 if(bFullSave) {
836 for(i=0;i<8;i++) fPhotodiode[i].ConstructNTupleAndVector(model,thisprefix,values,fieldPtrs);
837 }
838 for(i=kXAxis;i<kNumAxes;i++) {
839 fRelPos[i].ConstructNTupleAndVector(model,thisprefix,values,fieldPtrs);
840 }
841
842 }
843 return;
844}
845
846template <typename ChannelType>
847void QwLinearDiodeArray<ChannelType>::FillNTupleVector(std::vector<Double_t>& values) const
848{
849 if (GetElementName()=="") {
850 // This channel is not used, so skip filling.
851 }
852 else {
853 fEffectiveCharge.FillNTupleVector(values);
854 size_t i = 0;
855 if(bFullSave) {
856 for(i=0;i<8;i++) fPhotodiode[i].FillNTupleVector(values);
857 }
858 for(i=kXAxis;i<kNumAxes;i++){
859 fRelPos[i].FillNTupleVector(values);
860 }
861 }
862 return;
863}
864#endif
865
866
867template <typename ChannelType>
869{
870 size_t i = 0;
871 // bEVENTCUTMODE=bcuts;
872 for (i=0;i<8;i++) fPhotodiode[i].SetEventCutMode(bcuts);
873 for (i=kXAxis;i<kNumAxes;i++) {
874 fRelPos[i].SetEventCutMode(bcuts);
875 fAbsPos[i].SetEventCutMode(bcuts);
876 }
877 fEffectiveCharge.SetEventCutMode(bcuts);
878}
879
880template<typename ChannelType>
882{
883 for (size_t i = kXAxis; i < kNumAxes; i++) {
884 ChannelType relpos(fRelPos[i]);
885 relpos = fRelPos[i];
886 fLinearArrayElementList.push_back(relpos);
887 }
888 ChannelType effectivecharge(fEffectiveCharge);
889 effectivecharge = fEffectiveCharge;
890 fLinearArrayElementList.push_back(effectivecharge);
891}
892
893#ifdef __USE_DATABASE__
894template <typename ChannelType>
895std::vector<QwDBInterface> QwLinearDiodeArray<ChannelType>::GetDBEntry()
896{
897 std::vector <QwDBInterface> row_list;
898 row_list.clear();
899
900 for(size_t i=0;i<2;i++) {
901 fRelPos[i].AddEntriesToList(row_list);
902 }
903 fEffectiveCharge.AddEntriesToList(row_list);
904 return row_list;
905}
906
907template <typename ChannelType>
908std::vector<QwErrDBInterface> QwLinearDiodeArray<ChannelType>::GetErrDBEntry()
909{
910 std::vector <QwErrDBInterface> row_list;
911 row_list.clear();
912 for(size_t i=0;i<2;i++) {
913 fRelPos[i].AddErrEntriesToList(row_list);
914 }
915 fEffectiveCharge.AddErrEntriesToList(row_list);
916 return row_list;
917}
918#endif // __USE_DATABASE__
919
920
921/**********************************
922 * Mock data generation routines
923 **********************************/
924
925template <typename ChannelType>
926void QwLinearDiodeArray<ChannelType>::SetRandomEventParameters(Double_t meanX, Double_t sigmaX, Double_t meanY, Double_t sigmaY)
927{
928 // Average values of the signals in the stripline ADCs
929 Double_t sumX = 1.1e8; // These are just guesses, but I made X and Y different
930 Double_t sumY = 0.9e8; // to make it more interesting for the analyzer...
931
932
933 // Determine the asymmetry from the position
934 Double_t meanXP = (1.0 + meanX) * sumX / 2.0;
935 Double_t meanXM = (1.0 - meanX) * sumX / 2.0; // = sumX - meanXP;
936 Double_t meanYP = (1.0 + meanY) * sumY / 2.0;
937 Double_t meanYM = (1.0 - meanY) * sumY / 2.0; // = sumY - meanYP;
938
939 // Determine the spread of the asymmetry (this is not tested yet)
940 // (negative sigma should work in the QwVQWK_Channel, but still using fabs)
941 Double_t sigmaXP = fabs(sumX * sigmaX / meanX);
942 Double_t sigmaXM = sigmaXP;
943 Double_t sigmaYP = fabs(sumY * sigmaY / meanY);
944 Double_t sigmaYM = sigmaYP;
945
946 // Propagate these parameters to the ADCs
947 fPhotodiode[0].SetRandomEventParameters(meanXP, sigmaXP);
948 fPhotodiode[1].SetRandomEventParameters(meanXM, sigmaXM);
949 fPhotodiode[2].SetRandomEventParameters(meanYP, sigmaYP);
950 fPhotodiode[3].SetRandomEventParameters(meanYM, sigmaYM);
951}
952
953template <typename ChannelType>
955{
956 for (size_t i=0; i<8; i++) fPhotodiode[i].RandomizeEventData(helicity, time);
957
958 return;
959}
960
961template <typename ChannelType>
962void QwLinearDiodeArray<ChannelType>::SetEventData(Double_t* relpos, UInt_t sequencenumber)
963{
964 for (size_t i=0; i<2; i++)
965 {
966 fRelPos[i].SetHardwareSum(relpos[i], sequencenumber);
967 }
968
969 return;
970}
971
972
973template <typename ChannelType>
975{
976 for (size_t i=0; i<8; i++) fPhotodiode[i].EncodeEventData(buffer);
977}
978
979
980template <typename ChannelType>
982{
983 for(size_t i=0;i<8;i++) fPhotodiode[i].SetDefaultSampleSize((size_t)sample_size);
984 return;
985}
986
987template <typename ChannelType>
989{
990 fPhotodiode[j].SetPedestal(value);
991 return;
992}
993
994template <typename ChannelType>
996{
997 fPhotodiode[j].SetCalibrationFactor(value);
998 return;
999}
1000
static const UInt_t kBPMErrorFlag
Definition QwTypes.h:170
static const UInt_t kInvalidSubelementIndex
Definition QwTypes.h:198
Parameter file parsing and management.
#define QwMessage
Predefined log drain for regular messages.
Definition QwLog.h:49
Database interface for QwIntegrationPMT and subsystems.
Linear diode array beam position monitor implementation.
static std::ostream & endl(std::ostream &)
End of the line.
Definition QwLog.cc:297
Configuration file parser with flexible tokenization and search capabilities.
Bool_t HasValue(TString &vname)
A helper class to manage a vector of branch entries for ROOT trees.
Definition QwRootFile.h:55
VQwDataElement()
Default constructor.
TString fElementName
Name of this data element.
virtual const TString & GetElementName() const
Get the name of this element.
Abstract base for concrete hardware channels implementing dual-operator pattern.
Linear diode array beam position monitor implementation.
VQwBPM & operator=(const VQwBPM &value) override
void ProcessEvent() override
void SetSubElementPedestal(Int_t j, Double_t value) override
std::vector< ChannelType > fLinearArrayElementList
void SetSingleEventCuts(TString ch_name, UInt_t errorflag, Double_t minX, Double_t maxX, Double_t stability, Double_t burplevel)
Inherited from VQwDataElement to set the upper and lower limits (fULimit and fLLimit),...
void EncodeEventData(std::vector< UInt_t > &buffer) override
void SetRandomEventParameters(Double_t meanX, Double_t sigmaX, Double_t meanY, Double_t sigmaY) override
UInt_t UpdateErrorFlag() override
Update and return the aggregated event-cut error flag.
Bool_t ApplyHWChecks()
Apply hardware checks for all photodiode pads.
void FillHistograms() override
Fill the histograms for this data element.
TString GetSubElementName(Int_t subindex) override
void GetAbsolutePosition() override
void ConstructBranch(TTree *tree, TString &prefix) override
void DeaccumulateRunningSum(QwLinearDiodeArray &value, Int_t ErrorMask=0xFFFFFFF)
VQwBPM & operator-=(const VQwBPM &value) override
void SetEventCutMode(Int_t bcuts) override
Bool_t CheckForBurpFail(const VQwDataElement *ev_error) override
Check for burp failures against another linear array of same type.
static const Double_t kQwLinearDiodeArrayPadSize
void FillTreeVector(QwRootTreeBranchVector &values) const override
void PrintErrorCounters() const override
Print error counters for all internal channels.
Bool_t ApplySingleEventCuts() override
Apply single-event cuts across photodiodes and derived channels.
std::array< ChannelType, 2 > fAbsPos
void ConstructBranchAndVector(TTree *tree, TString &prefix, QwRootTreeBranchVector &values) override
void PrintInfo() const override
Print multiple lines of information about this data element.
VQwHardwareChannel * GetSubelementByName(TString ch_name) override
Resolve an internal channel pointer by subelement name.
void PrintValue() const override
Print single line of value and error of this data element.
static const size_t kMaxElements
void RandomizeEventData(int helicity=0, double time=0.0) override
void SetSubElementCalibrationFactor(Int_t j, Double_t value) override
void AccumulateRunningSum(const QwLinearDiodeArray &value, Int_t count=0, Int_t ErrorMask=0xFFFFFFF)
static UInt_t GetSubElementIndex(TString subname)
std::array< ChannelType, 8 > fPhotodiode
Int_t ProcessEvBuffer(UInt_t *buffer, UInt_t word_position_in_buffer, UInt_t indexnumber) override
Process the CODA event buffer for this element.
static const TString subelement[8]
VQwBPM & operator+=(const VQwBPM &value) override
void IncrementErrorCounters() override
Increment error counters for all internal channels.
void SetDefaultSampleSize(Int_t sample_size) override
void Ratio(VQwBPM &numer, VQwBPM &denom) override
void CalculateRunningAverage() override
void InitializeChannel(TString name)
Initialize this linear diode array with a detector name.
void ConstructHistograms(TDirectory *folder, TString &prefix) override
Construct the histograms for this data element.
UInt_t GetEventcutErrorFlag() override
Aggregate and return the event-cut error flag for this array.
std::array< ChannelType, 2 > fRelPos
void ClearEventData() override
Clear event-scoped data for all pads and derived channels.
void Scale(Double_t factor) override
void SetEventData(Double_t *block, UInt_t sequencenumber)
Double_t fPositionCenter[3]
Definition VQwBPM.h:330
@ kXAxis
Definition VQwBPM.h:72
@ kNumAxes
Definition VQwBPM.h:72
void SetRootSaveStatus(TString &prefix)
Definition VQwBPM.cc:221
void InitializeChannel(TString name)
Initialize common BPM state and set the element name.
Definition VQwBPM.cc:36
static const Bool_t bDEBUG
Definition VQwBPM.h:352
Bool_t bFullSave
Definition VQwBPM.h:350
virtual VQwBPM & operator=(const VQwBPM &value)=0
Definition VQwBPM.cc:157
VQwBPM()
Definition VQwBPM.h:76