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