JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
QwScaler_Channel.cc
Go to the documentation of this file.
1/**********************************************************\
2* File: QwScaler_Channel.cc *
3* *
4* Author: J. Pan *
5* Date: Thu Sep 16 18:08:33 CDT 2009 *
6\**********************************************************/
7
8#include <boost/algorithm/string.hpp>
9
10#include "QwScaler_Channel.h"
11#include "QwHistogramHelper.h"
12#include "QwRootFile.h"
13
14#include <stdexcept>
15#include <QwLog.h>
16
17
18const Bool_t VQwScaler_Channel::kDEBUG = kFALSE;
19
20
21/********************************************************/
22void VQwScaler_Channel::InitializeChannel(TString name, TString datatosave)
23{
24 fNormChannelPtr = NULL;
25 fNeedsExternalClock = kFALSE;
27
28 SetElementName(name);
29 SetDataToSave(datatosave);
30 SetNumberOfDataWords(1); //Scaler - single word, 32 bits
32
33 // Default mockdata parameters
34 SetRandomEventParameters(300.0, 50.0);
35
36 fHeader = 0;
38 fValue_Raw = 0;
39 fValue = 0.0;
40 fValueM2 = 0.0;
41 fValueError = 0.0;
42 fPedestal = 0.0;
44
46
49
50 fNumEvtsWithHWErrors=0;//init error counters
51 fNumEvtsWithEventCutsRejected=0;//init error counters
52
53 fErrorFlag = 0;
56 return;
57};
58
59/********************************************************/
60
61void VQwScaler_Channel::InitializeChannel(TString subsystem, TString instrumenttype, TString name, TString datatosave){
62 InitializeChannel(name,datatosave);
63 SetSubsystemName(subsystem);
64 SetModuleType(instrumenttype);
65}
66
68{
69 fHeader = 0;
70 fValue_Raw = 0;
71 fValue = 0.0;
72 fValueM2 = 0.0;
73 fValueError = 0.0;
74
76 fErrorFlag = 0;
77}
78
79void VQwScaler_Channel::RandomizeEventData(int helicity, double time)
80{
81 // Calculate drift (if time is not specified, it stays constant at zero)
82 Double_t drift = 0.0;
83 for (UInt_t i = 0; i < fMockDriftFrequency.size(); i++) {
84 drift += fMockDriftAmplitude[i] * sin(2.0 * Qw::pi * fMockDriftFrequency[i] * time + fMockDriftPhase[i]);
85 }
86
87 Double_t value = fMockGaussianMean * (1 + helicity * fMockAsymmetry)
89 + drift;
90
91 fValue = value;
92 fValue_Raw = Int_t(value / fCalibrationFactor + fPedestal);
93}
94
96{
97 fValue = resolution*GetRandomValue();
98 fValueM2 = 0.0;
100}
101
102
103/*! Static member function to return the word offset within a data buffer
104 * given the module number index and the channel number index.
105 * @param scalerindex Scaler index within this buffer; counts from 1
106 * @param wordindex Word index within this scaler; counts from 1
107 * @param header Number of header words; normally is 1
108 * @return The number of words offset to the beginning of this
109 * scaler word from the beginning of the buffer.
110 */
111Int_t VQwScaler_Channel::GetBufferOffset(Int_t scalerindex, Int_t wordindex, UInt_t header)
112{
113 Int_t offset = -1;
114 Int_t kMaxWords = 32; // usually the scalers have 32 data words starting from 0
115
116 if (scalerindex<0 ){
117 QwError << "QwScaler_Channel::GetBufferOffset: Invalid scaler index,"
118 << scalerindex
119 << ". Must be zero or greater."
120 << QwLog::endl;
121 } else if (scalerindex<0 || wordindex>kMaxWords){
122 QwError << "QwScaler_Channel::GetBufferOffset: Invalid word index,"
123 << wordindex
124 << ". Must be in range [0," << kMaxWords << "]."
125 << QwLog::endl;
126 } else {
127 offset = (header + kMaxWords)*scalerindex + header + wordindex ;
128 }
129 return offset;
130}
131
132
134
135 this->fValue = value;
136 this->fValue_Raw = (UInt_t)value;
137 //std::cout<<"fValue is set to: value = "<<value<<std::endl;
138
139}
140
142 std::string varvalue;
143 if (paramfile.ReturnValue("normclock",varvalue)){
144 boost::to_lower(varvalue);
145 SetExternalClockName(varvalue);
146 fNeedsExternalClock = kTRUE;
147 }
148};
149
150template<unsigned int data_mask, unsigned int data_shift>
152{
153 if (IsNameEmpty()) {
154 // This channel is not used, but is present in the data stream.
155 // Fill in with zero.
156 buffer.push_back( 0 );
157 } else {
158 buffer.push_back( ((this->fValue_Raw<<data_shift)&data_mask) );
159 //std::cout<<"this->fValue="<<this->fValue<<std::endl;
160 }
161}
162
163
164template<unsigned int data_mask, unsigned int data_shift>
165Int_t QwScaler_Channel<data_mask,data_shift>::ProcessEvBuffer(UInt_t* buffer, UInt_t num_words_left,
166 UInt_t index)
167{
168 UInt_t words_read = 0;
169 if (IsNameEmpty()){
170 // This channel is not used, but is present in the data stream.
171 // Skip over this data.
172 words_read = fNumberOfDataWords;
173 } else if (num_words_left >= fNumberOfDataWords) {
174 fHeader = (buffer[0] & ~data_mask);
175 fValue_Raw = ((buffer[0] & data_mask) >> data_shift);
176 fValue = fCalibrationFactor * (Double_t(fValue_Raw) - Double_t(fValue_Raw_Old) - fPedestal);
177 words_read = fNumberOfDataWords;
178
179 // Store old raw value for differential scalers
182 else
183 fValue_Raw_Old = 0;
184
185 } else {
186 //QwError << "QwScaler_Channel::ProcessEvBuffer: Not enough words!"<< QwLog::endl;
187 }
188 return words_read;
189}
190
191
193{
194 if (NeedsExternalClock()){
195 if(fNormChannelPtr){
196 Double_t time = fNormChannelPtr->GetValue();
197 //QwError << "VQwScaler_Channel::ProcessEvent() "<<GetElementName()<<" "<< fValue_Raw<< " "<< fValue<<" "<<fCalibrationFactor<<" "<< fPedestal<<QwLog::endl;
198 fValue = fCalibrationFactor * (Double_t(fValue_Raw)/time - fPedestal);
199 } else {
200 QwWarning << "VQwScaler_Channel::ProcessEvent: "
201 << "Missing the reference clock, "
203 << ", for data element "
204 << GetElementName()
205 << QwLog::endl;
206 }
207 }
208}
209
210
212{
213 QwMessage << std::setprecision(4)
214 << std::setw(18) << std::left << GetSubsystemName() << " "
215 << std::setw(18) << std::left << GetModuleType() << " "
216 << std::setw(18) << std::left << GetElementName() << " "
217 << std::setw(12) << std::left << GetValue() << " +/- "
218 << std::setw(12) << std::left << GetValueError() << " sig "
219 << std::setw(12) << std::left << GetValueWidth() << " "
220 << std::setw(12) << std::left << GetGoodEventCount() << " "
221 << QwLog::endl;
222}
223
225{
226 QwMessage << "***************************************" << QwLog::endl;
227 QwMessage << "QwScaler channel: " << GetElementName()
228 << QwLog::endl;
229}
230
231void VQwScaler_Channel::ConstructHistograms(TDirectory *folder, TString &prefix){
232 // If we have defined a subdirectory in the ROOT file, then change into it.
233 if (folder != NULL) folder->cd();
234
235 if (GetElementName()==""){
236 // This channel is not used, so skip filling the histograms.
237 } else {
238 // Now create the histograms.
239 TString basename = prefix + GetElementName();
240
241 fHistograms.resize(1, NULL);
242 size_t index=0;
243 fHistograms[index] = gQwHists.Construct1DHist(basename);
244 index += 1;
245 }
246}
247
249{
250 size_t index = 0;
251 if (IsNameEmpty()) {
252 // This channel is not used, so skip creating the histograms.
253 } else {
254 if (index < fHistograms.size() && fHistograms[index] != NULL && fErrorFlag==0)
255 fHistograms[index]->Fill(this->fValue);
256 index += 1;
257 }
258}
259
260
261template<unsigned int data_mask, unsigned int data_shift>
263{
264 if (IsNameEmpty()){
265 // This channel is not used, so skip setting up the tree.
266 } else {
267 // Decide what to store based on prefix
268 SetDataToSaveByPrefix(prefix);
269
270 TString basename = prefix(0, (prefix.First("|") >= 0)? prefix.First("|"): prefix.Length()) + GetElementName();
271 fTreeArrayIndex = values.size();
272
273 values.push_back("value", 'D');
274 if (fDataToSave == kMoments) {
275 values.push_back("value_m2", 'D');
276 values.push_back("value_err", 'D');
277 values.push_back("num_samples", 'I');
278 }
279 values.push_back("Device_Error_Code", 'i');
280 if(fDataToSave==kRaw){
281 values.push_back("raw", 'I');
282 if ((~data_mask) != 0){
283 values.push_back("header", 'I');
284 }
285 }
286 //std::cout << basename <<": first==" << fTreeArrayIndex << ", last==" << values.size() << std::endl;
288 if (gQwHists.MatchDeviceParamsFromList(basename.Data()))
289 tree->Branch(basename, &(values[fTreeArrayIndex]), values.LeafList(fTreeArrayIndex).c_str());
292
293void VQwScaler_Channel::ConstructBranch(TTree *tree, TString &prefix)
294{
295 if (IsNameEmpty()){
296 // This channel is not used, so skip setting up the tree.
297 } else {
298 TString basename = prefix + GetElementName();
299
300 tree->Branch(basename, &fValue, basename+"/D");
301 }
302}
303
304template<unsigned int data_mask, unsigned int data_shift>
306{
307 //std::cout<<"inside QwScaler_Channel::FillTreeVector"<< std::endl;
308 if (IsNameEmpty()) {
309 // This channel is not used, so skip setting up the tree.
310 } else if (fTreeArrayNumEntries == 0) {
311 static bool warned = false;
312 if (!warned) {
313 QwError << "VQwScaler_Channel::FillTreeVector: fTreeArrayNumEntries=="
314 << fTreeArrayNumEntries << " (no branch constructed?)" << QwLog::endl;
315 QwError << "Offending element is " << GetElementName() << QwLog::endl;
316 warned = true;
317 }
318 } else if (values.size() < fTreeArrayIndex+fTreeArrayNumEntries) {
319 QwError << "VQwScaler_Channel::FillTreeVector: values.size()=="
320 << values.size() << " name: " << fElementName
321 << "; fTreeArrayIndex+fTreeArrayNumEntries=="
322 << fTreeArrayIndex << '+' << fTreeArrayNumEntries << '='
324 << QwLog::endl;
325 } else {
326 size_t index = fTreeArrayIndex;
327 values.SetValue(index++, this->fValue);
328 if (fDataToSave == kMoments) {
329 values.SetValue(index++, fValueM2);
330 values.SetValue(index++, fValueError);
331 values.SetValue(index++, fGoodEventCount);
332 }
333 values.SetValue(index++, this->fErrorFlag);
334 if(fDataToSave==kRaw){
335 values.SetValue(index++, this->fValue_Raw);
336 if ((~data_mask) != 0){
337 values.SetValue(index++, this->fHeader);
338 }
339 }
340 }
341}
342
343#ifdef HAS_RNTUPLE_SUPPORT
344template<unsigned int data_mask, unsigned int data_shift>
345void QwScaler_Channel<data_mask,data_shift>::ConstructNTupleAndVector(std::unique_ptr<ROOT::RNTupleModel>& model, TString& prefix, std::vector<Double_t>& values, std::vector<std::shared_ptr<Double_t>>& fieldPtrs)
346{
347 if (IsNameEmpty()){
348 // This channel is not used, so skip setting up the RNTuple.
349 } else {
350 // Decide what to store based on prefix
351 SetDataToSaveByPrefix(prefix);
352
353 TString basename = prefix(0, (prefix.First("|") >= 0)? prefix.First("|"): prefix.Length()) + GetElementName();
354 fTreeArrayIndex = values.size();
355
356 // Calculate how many elements we need to avoid multiple push_back calls
357 size_t numElements = 2; // value + Device_Error_Code
358 if (fDataToSave == kMoments) numElements += 3; // _m2 + _err + num_samples
359 if (fDataToSave == kRaw) {
360 numElements += 1; // raw
361 if ((~data_mask) != 0) numElements += 1; // header
362 }
363
364 // Resize vectors once to avoid reallocation
365 size_t oldSize = values.size();
366 values.resize(oldSize + numElements, 0.0);
367 fieldPtrs.reserve(fieldPtrs.size() + numElements);
368
369 // Main value
370 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
371
372 if (fDataToSave == kMoments) {
373 fieldPtrs.push_back(model->MakeField<Double_t>((basename + "_m2").Data()));
374 fieldPtrs.push_back(model->MakeField<Double_t>((basename + "_err").Data()));
375 fieldPtrs.push_back(model->MakeField<Double_t>((basename + "_num_samples").Data()));
376 }
377
378 // Device error code
379 fieldPtrs.push_back(model->MakeField<Double_t>((basename + "_Device_Error_Code").Data()));
380
381 if(fDataToSave==kRaw){
382 fieldPtrs.push_back(model->MakeField<Double_t>((basename + "_raw").Data()));
383
384 if ((~data_mask) != 0){
385 fieldPtrs.push_back(model->MakeField<Double_t>((basename + "_header").Data()));
386 }
387 }
388
389 fTreeArrayNumEntries = values.size() - fTreeArrayIndex;
390 }
391}
392
393template<unsigned int data_mask, unsigned int data_shift>
394void QwScaler_Channel<data_mask,data_shift>::FillNTupleVector(std::vector<Double_t>& values) const
395{
396 if (IsNameEmpty()) {
397 // This channel is not used, so skip filling.
398 } else if (fTreeArrayNumEntries < 0) {
399 QwError << "QwScaler_Channel::FillNTupleVector: fTreeArrayNumEntries=="
400 << fTreeArrayNumEntries << QwLog::endl;
401 } else if (fTreeArrayNumEntries == 0) {
402 static bool warned = false;
403 if (!warned) {
404 QwError << "QwScaler_Channel::FillNTupleVector: fTreeArrayNumEntries=="
405 << fTreeArrayNumEntries << " (no construction done?)" << QwLog::endl;
406 QwError << "Offending element is " << GetElementName() << QwLog::endl;
407 warned = true;
408 }
409 } else if (values.size() < fTreeArrayIndex+fTreeArrayNumEntries) {
410 QwError << "QwScaler_Channel::FillNTupleVector: values.size()=="
411 << values.size() << " name: " << fElementName
412 << "; fTreeArrayIndex+fTreeArrayNumEntries=="
413 << fTreeArrayIndex << '+' << fTreeArrayNumEntries << '='
414 << fTreeArrayIndex+fTreeArrayNumEntries
415 << QwLog::endl;
416 } else {
417 size_t index = fTreeArrayIndex;
418 values[index++] = this->fValue;
419 if (fDataToSave == kMoments) {
420 values[index++] = fValueM2;
421 values[index++] = fValueError;
422 values[index++] = fGoodEventCount;
423 }
424 values[index++] = this->fErrorFlag;
425 if(fDataToSave==kRaw){
426 values[index++] = this->fValue_Raw;
427 if ((~data_mask) != 0){
428 values[index++] = this->fHeader;
429 }
430 }
431 }
432}
433#endif // HAS_RNTUPLE_SUPPORT
434
435
437 const VQwScaler_Channel* tmpptr;
438 tmpptr = dynamic_cast<const VQwScaler_Channel*>(valueptr);
439 if (tmpptr!=NULL){
440 *this = *tmpptr;
441 } else {
442 TString loc="Standard exception from VQwScaler_Channel::AssignValueFrom = "
443 +valueptr->GetElementName()+" is an incompatible type.";
444 throw std::invalid_argument(loc.Data());
445 }
446}
448{
449 const VQwScaler_Channel* tmpptr;
450 tmpptr = dynamic_cast<const VQwScaler_Channel*>(valueptr);
451 if (tmpptr!=NULL){
452 *this += *tmpptr;
453 } else {
454 TString loc="Standard exception from VQwScaler_Channel::AddValueFrom = "
455 +valueptr->GetElementName()+" is an incompatible type.";
456 throw std::invalid_argument(loc.Data());
457 }
458}
460{
461 const VQwScaler_Channel* tmpptr;
462 tmpptr = dynamic_cast<const VQwScaler_Channel*>(valueptr);
463 if (tmpptr!=NULL){
464 *this -= *tmpptr;
465 } else {
466 TString loc="Standard exception from VQwScaler_Channel::SubtractValueFrom = "
467 +valueptr->GetElementName()+" is an incompatible type.";
468 throw std::invalid_argument(loc.Data());
469 }
470}
472{
473 const VQwScaler_Channel* tmpptr;
474 tmpptr = dynamic_cast<const VQwScaler_Channel*>(valueptr);
475 if (tmpptr!=NULL){
476 *this *= *tmpptr;
477 } else {
478 TString loc="Standard exception from VQwScaler_Channel::MultiplyBy = "
479 +valueptr->GetElementName()+" is an incompatible type.";
480 throw std::invalid_argument(loc.Data());
481 }
482}
483
485{
486 const VQwScaler_Channel* tmpptr;
487 tmpptr = dynamic_cast<const VQwScaler_Channel*>(valueptr);
488 if (tmpptr!=NULL){
489 *this /= *tmpptr;
490 } else {
491 TString loc="Standard exception from VQwScaler_Channel::DivideBy = "
492 +valueptr->GetElementName()+" is an incompatible type.";
493 throw std::invalid_argument(loc.Data());
494 }
495}
496
498{
499 if(this == &value) return *this;
500 if (!IsNameEmpty()) {
502 this->fHeader = value.fHeader;
503 this->fValue_Raw = value.fValue_Raw;
504 this->fValue = value.fValue;
505 this->fValueError = value.fValueError;
506 this->fValueM2 = value.fValueM2;
507 }
508 return *this;
509}
510
512 Double_t scale)
513{
514 if (!IsNameEmpty()) {
515 this->fValue = value.fValue * scale;
516 this->fValueError = value.fValueError;
517 this->fValueM2 = value.fValueM2 * scale * scale;
518 this->fErrorFlag = value.fErrorFlag;//error code is updated.
519 this->fGoodEventCount = value.fGoodEventCount;
520 }
521 return;
522}
523
524
526{
527 if (!IsNameEmpty()){
528 this->fValue += value.fValue;
529 this->fValueM2 = 0.0;
530 this->fErrorFlag |= value.fErrorFlag;//error code is ORed.
531 }
532 return *this;
533}
534
536{
537 if (!IsNameEmpty()){
538 this->fValue -= value.fValue;
539 this->fValueM2 = 0.0;
540 this->fErrorFlag |= (value.fErrorFlag);//error code is ORed.
541 }
542 return *this;
543}
544
546{
547 if (!IsNameEmpty()){
548 this->fValue *= value.fValue;
549 fHeader = 0;
550 fValue_Raw = 0;
551 this->fValueM2 = 0.0;
552 this->fErrorFlag |= (value.fErrorFlag);//error code is ORed.
553 }
554 return *this;
555}
556
558{
559 try {
560 const VQwScaler_Channel* tmpptr;
561 tmpptr = dynamic_cast<const VQwScaler_Channel*>(&source);
562 *this += *tmpptr;
563 } catch(const std::exception& e) {
564 TString loc="Standard exception from VQwScaler_Channel::operator+= "
565 +source.GetElementName()+" "
566 +this->GetElementName()+" are not of the same type";
567 throw(std::invalid_argument(loc.Data()));
568 }
569 return *this;
570}
572{
573 const VQwScaler_Channel* tmpptr;
574 tmpptr = dynamic_cast<const VQwScaler_Channel*>(&source);
575 if (tmpptr!=NULL){
576 *this -= *tmpptr;
577 } else {
578 TString loc="Standard exception from VQwScaler_Channel::operator-= "
579 +source.GetElementName()+" "
580 +this->GetElementName()+" are not of the same type";
581 throw(std::invalid_argument(loc.Data()));
582 }
583 return *this;
584}
586{
587 const VQwScaler_Channel* tmpptr;
588 tmpptr = dynamic_cast<const VQwScaler_Channel*>(&source);
589 if (tmpptr!=NULL){
590 *this *= *tmpptr;
591 } else {
592 TString loc="Standard exception from VQwScaler_Channel::operator*= "
593 +source.GetElementName()+" "
594 +this->GetElementName()+" are not of the same type";
595 throw(std::invalid_argument(loc.Data()));
596 }
597 return *this;
598}
600{
601 const VQwScaler_Channel* tmpptr;
602 tmpptr = dynamic_cast<const VQwScaler_Channel*>(&source);
603 if (tmpptr!=NULL){
604 *this /= *tmpptr;
605 } else {
606 TString loc="Standard exception from VQwScaler_Channel::operator/= "
607 +source.GetElementName()+" "
608 +this->GetElementName()+" are not of the same type";
609 throw(std::invalid_argument(loc.Data()));
610 }
611 return *this;
612}
613
615{
616 *this = value1;
617 *this += value2;
618}
619
621 *this = value1;
622 *this -= value2;
623}
624
626{
627 if (!IsNameEmpty()){
628 *this = numer;
629 *this /= denom;
630
631 // Set the raw values to zero.
632 fHeader = 0;
633 fValue_Raw = 0;
634
635 // Remaining variables
637 fErrorFlag = (numer.fErrorFlag|denom.fErrorFlag);//error code is ORed.
638 }
639}
640
642{
643 // In this function, leave the "raw" variables untouched.
644 Double_t ratio;
645 Double_t variance;
646 if (!IsNameEmpty()){
647 // The variances are calculated using the following formula:
648 // Var[ratio] = ratio^2 (Var[numer] / numer^2 + Var[denom] / denom^2)
649 //
650 // This requires that both the numerator and denominator are non-zero!
651 //
652 if (this->fValue != 0.0 && denom.fValue != 0.0){
653 ratio = (this->fValue) / (denom.fValue);
654 variance = ratio * ratio *
655 (this->fValueM2 / this->fValue / this->fValue
656 + denom.fValueM2 / denom.fValue / denom.fValue);
657 fValue = ratio;
658 fValueM2 = variance;
659 } else if (this->fValue == 0.0) {
660 fValue = 0.0;
661 fValueM2 = 0.0;
662 } else {
663 QwVerbose << "Attempting to divide by zero in "
665 fValue = 0.0;
666 fValueM2 = 0.0;
667 }
668
669 // Remaining variables
670 // Don't change fGoodEventCount.
671 // 'OR' the device error codes together.
672 fErrorFlag |= denom.fErrorFlag;
673 }
674
675 // Nanny
676 if (fValue != fValue)
677 QwWarning << "Angry Nanny: NaN detected in " << GetElementName() << QwLog::endl;
678 return *this;
679}
680
682{
683 if (!IsNameEmpty()){
684 fValue = numer.fValue * denom.fValue;
685 fHeader = 0;
686 fValue_Raw = 0;
687
688 // Remaining variables
690 fErrorFlag = (numer.fErrorFlag|denom.fErrorFlag);//error code is ORed.
691 }
692}
693
694
696{
697 if (!IsNameEmpty())
698 {
699 fValue += offset;
700 }
701}
702
703
704void VQwScaler_Channel::Scale(Double_t scale)
705{
706 if (!IsNameEmpty())
707 {
708 fValue *= scale;
709 fValueM2 *= scale * scale;
710 }
711}
712
714{
715 *this /= denom;
716}
717
718/********************************************************/
720 // fErrorFlag=0;
721 if (bEVENTCUTMODE>0){//Global switch to ON/OFF event cuts set at the event cut file
722 //check for the hw_sum is zero
723 if (GetRawValue()==0){
725 }
726 }
727 return fErrorFlag;
728}
729
730
731
733{
734 //std::cout << "Here in VQwScaler_Channel: "<< std::endl;
735 Bool_t status;
736 //QwError<<" Single Event Check ! "<<QwLog::endl;
737 if (bEVENTCUTMODE>=2){//Global switch to ON/OFF event cuts set at the event cut file
738 //std::cout << "Upper : " << fULimit << " , Lower: " << fLLimit << std::endl;
739 if (fULimit < fLLimit){
740 // std::cout << "First" << std::endl;
741 status=kTRUE;
742 } else if (GetValue()<=fULimit && GetValue()>=fLLimit){
743 //std::cout << "Second" << std::endl;
744 //QwError<<" Single Event Cut passed "<<GetElementName()<<" "<<GetValue()<<QwLog::endl;
745 if (fErrorFlag !=0)
746 status=kFALSE;
747 else
748 status=kTRUE;
749 }
750 else{
751 //std::cout << "Third" << std::endl;
752 //QwError<<" Single Event Cut Failed "<<GetElementName()<<" "<<GetValue()<<QwLog::endl;
753 if (GetValue()> fULimit)
755 else
757 status=kFALSE;
758 }
759
760 if (bEVENTCUTMODE==3){
761 status=kTRUE; //Update the event cut fail flag but pass the event.
762 }
763
764 }
765 else{
766 status=kTRUE;
767 fErrorFlag=0;
768 }
769
770
771 return status;
772}
773
775{
777 fNumEvtsWithHWErrors++; //increment the hw error counter
778 }
781 fNumEvtsWithEventCutsRejected++; //increment the event cut error counter
782 }
783}
784
785
786void VQwScaler_Channel::AccumulateRunningSum(const VQwScaler_Channel& value, Int_t count, Int_t ErrorMask)
787{
788
789 if(count==0){
790 count = value.fGoodEventCount;
791 }
792
793 // Moment calculations
794 Int_t n1 = fGoodEventCount;
795 Int_t n2 = count;
796
797 // If there are no good events, check whether device HW is good
798 if (n2 == 0 && value.fErrorFlag == 0) {
799 n2 = 1;
800 }
801
802 // If a single event is removed from the sum, check all but stability fail flags
803 if (n2 == -1) {
804 if ((value.fErrorFlag & ErrorMask) == 0) {
805 n2 = -1;
806 } else {
807 n2 = 0;
808 }
809 }
810
811 if (ErrorMask == kPreserveError){
812 //n = 1;
813 if (n2 == 0) {
814 n2 = 1;
815 }
816 if (count == -1) {
817 n2 = -1;
818 }
819 }
820
821 // New total number of good events
822 Int_t n = n1 + n2;
823
824 // Set up variables
825 Double_t M11 = fValue;
826 Double_t M12 = value.fValue;
827 Double_t M22 = value.fValueM2;
828 if (n2 == 0) {
829 // no good events for addition
830 return;
831 } else if (n2 == -1) {
832 // simple version for removal of single event from the sum
834 if (n > 1) {
835 fValue -= (M12 - M11) / n;
836 fValueM2 -= (M12 - M11)
837 * (M12 - fValue); // note: using updated mean
838 } else if (n == 1) {
839 fValue -= (M12 - M11) / n;
840 fValueM2 -= (M12 - M11)
841 * (M12 - fValue); // note: using updated mean
842 if (fabs(fValueM2) < 10.*std::numeric_limits<double>::epsilon())
843 fValueM2 = 0; // rounding
844 } else if (n == 0) {
845 fValue -= M12;
846 fValueM2 -= M22;
847 if (fabs(fValue) < 10.*std::numeric_limits<double>::epsilon())
848 fValue = 0; // rounding
849 if (fabs(fValueM2) < 10.*std::numeric_limits<double>::epsilon())
850 fValueM2 = 0; // rounding
851 } else {
852 QwWarning << "Running sum has deaccumulated to negative good events." << QwLog::endl;
853 }
854 } else if (n2 == 1) {
855 // simple version for addition of single event
857 fValue += (M12 - M11) / n;
858 fValueM2 += (M12 - M11) * (M12 - fValue); // note: using updated mean
859 } else if (n2 > 1) {
860 // general version for addition of multi-event sets
861 fGoodEventCount += n2;
862 fValue += n2 * (M12 - M11) / n;
863 fValueM2 += M22 + n1 * n2 * (M12 - M11) * (M12 - M11) / n;
864 }
865
866 // Nanny
867 if (fValue != fValue)
868 QwWarning << "Angry Nanny: NaN detected in " << GetElementName() << QwLog::endl;
869}
870
872{
873 // See notes in QwVQWK_Channel; we are using:
874 // error = sqrt(M2)/n,
875 // or alternately we could use the unbiased estimator for both
876 // the sigma and error on the mean:
877 // error = sqrt(M2)/(n-1)
878 if(fGoodEventCount > 0) {
880 } else {
881 fValueError = 0.0;
882 }
883
884}
885
888 QwMessage << "QwScaler_Channel " << GetElementName()
889 << " had " << fNumEvtsWithHWErrors
890 << " events with a hardware failure."
891 << QwLog::endl;
892
894 QwMessage << "QwScaler_Channel " << GetElementName()
896 << " events rejected by Event Cuts."
897 << QwLog::endl;
898 }
899
900void VQwScaler_Channel::ScaledAdd(Double_t scale, const VQwHardwareChannel *value){
901
902 const VQwScaler_Channel* input = dynamic_cast<const VQwScaler_Channel*>(value);
903
904 // follows same steps as += but w/ scaling factor
905 if (input!=NULL && !IsNameEmpty()){
906 this->fValue += scale * input->fValue;
907 this->fValueM2 = 0.0;
908 this->fErrorFlag |= (input->fErrorFlag);
909 } else if (input == NULL && value != NULL) {
910 TString loc="Standard exception from VQwScaler_Channel::ScaledAdd "
911 +value->GetElementName()+" "
912 +this->GetElementName()+" are not of the same type";
913 throw(std::invalid_argument(loc.Data()));
914 }
915}
916
917
918/**
919 * Clone the channel, saving the specified data.
920 * @param datatosave Data to save flag
921 * @return Pointer to the cloned hardware channel
922 */
923template<>
927
928/**
929 * Clone the channel, saving the specified data.
930 * @param datatosave Data to save flag
931 * @return Pointer to the cloned hardware channel
932 */
933template<>
937
938// These explicit class template instantiations should be the
939// last thing in this file. This list should cover all of the
940// types that are typedef'ed in the header file.
941template class QwScaler_Channel<0x00ffffff,0>; // QwSIS3801D24_Channel
942template class QwScaler_Channel<0xffffffff,0>; // QwSIS3801_Channel, etc.
943
944
Helper functions and utilities for ROOT histogram management.
QwHistogramHelper gQwHists
Globally defined instance of the QwHistogramHelper class.
Base and derived classes for scaler channel data handling.
A logfile class, based on an identical class in the Hermes analyzer.
#define QwVerbose
Predefined log drain for verbose messages.
Definition QwLog.h:54
#define QwError
Predefined log drain for errors.
Definition QwLog.h:39
#define QwWarning
Predefined log drain for warnings.
Definition QwLog.h:44
#define QwMessage
Predefined log drain for regular messages.
Definition QwLog.h:49
ROOT file and tree management wrapper classes.
static const UInt_t kErrorFlag_ZeroHW
Definition QwTypes.h:164
static const UInt_t kErrorFlag_EventCut_L
Definition QwTypes.h:165
static const UInt_t kErrorFlag_EventCut_U
Definition QwTypes.h:166
static const UInt_t kPreserveError
Definition QwTypes.h:186
static const double pi
Angles: base unit is radian.
Definition QwUnits.h:107
std::vector< TH1_ptr > fHistograms
Histograms associated with this data element.
std::vector< Double_t > fMockDriftAmplitude
Harmonic drift amplitude.
std::vector< Double_t > fMockDriftFrequency
Harmonic drift frequency.
Double_t fMockAsymmetry
Helicity asymmetry.
Double_t fMockGaussianSigma
Sigma of normal distribution.
Double_t fMockGaussianMean
Mean of normal distribution.
std::vector< Double_t > fMockDriftPhase
Harmonic drift phase.
void SetRandomEventParameters(Double_t mean, Double_t sigma)
Set the normal random event parameters.
Double_t GetRandomValue()
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 ReturnValue(const std::string keyname, T &retvalue)
A helper class to manage a vector of branch entries for ROOT trees.
Definition QwRootFile.h:53
size_type size() const noexcept
Definition QwRootFile.h:81
std::string LeafList(size_type start_index=0) const
Definition QwRootFile.h:228
void push_back(const std::string &name, const char type='D')
Definition QwRootFile.h:195
void SetValue(size_type index, Double_t val)
Definition QwRootFile.h:108
static const Bool_t kDEBUG
void Difference(VQwScaler_Channel &value1, VQwScaler_Channel &value2)
void InitializeChannel(TString name, TString datatosave="raw") override
Initialize the fields in this object.
Double_t GetValueError() const
void Product(VQwScaler_Channel &numer, VQwScaler_Channel &denom)
void ProcessEvent() override
void ClearEventData() override
Clear the event data in this element.
void Scale(Double_t Offset) override
Bool_t NeedsExternalClock() override
void AddValueFrom(const VQwHardwareChannel *valueptr) override
void LoadChannelParameters(QwParameterFile &paramfile) override
void SubtractValueFrom(const VQwHardwareChannel *valueptr) override
void ConstructHistograms(TDirectory *folder, TString &prefix) override
Construct the histograms for this data element.
Bool_t ApplySingleEventCuts() override
void RandomizeEventData(int helicity=0, double time=0.0) override
Internally generate random event data.
void ConstructBranch(TTree *tree, TString &prefix) override
VQwScaler_Channel & operator=(const VQwScaler_Channel &value)
void Sum(VQwScaler_Channel &value1, VQwScaler_Channel &value2)
void SetExternalClockName(const std::string name) override
void FillHistograms() override
Fill the histograms for this data element.
VQwHardwareChannel & operator/=(const VQwHardwareChannel &input) override
void PrintInfo() const override
Print multiple lines of information about this data element.
static Int_t GetBufferOffset(Int_t scalerindex, Int_t wordindex, UInt_t header=1)
void PrintErrorCounters() const override
report number of events failed due to HW and event cut failure
void ScaledAdd(Double_t scale, const VQwHardwareChannel *value) override
std::string fNormChannelName
void SmearByResolution(double resolution) override
void SetRawEventData() override
void MultiplyBy(const VQwHardwareChannel *valueptr) override
Int_t ApplyHWChecks() override
VQwScaler_Channel & operator+=(const VQwScaler_Channel &value)
virtual Bool_t IsDifferentialScaler()
Double_t GetValueWidth() const
const VQwHardwareChannel * fNormChannelPtr
void PrintValue() const override
Print single line of value and error of this data element.
void SetEventData(Double_t value)
VQwScaler_Channel & operator*=(const VQwScaler_Channel &value)
void CalculateRunningAverage() override
void Ratio(const VQwScaler_Channel &numer, const VQwScaler_Channel &denom)
Double_t GetValue() const
void DivideBy(const VQwHardwareChannel *valueptr) override
VQwScaler_Channel & operator-=(const VQwScaler_Channel &value)
Int_t GetRawValue() const
void AddChannelOffset(Double_t Offset)
void IncrementErrorCounters() override
void AssignValueFrom(const VQwDataElement *valueptr) override
void AssignScaledValue(const VQwScaler_Channel &value, Double_t scale)
void AccumulateRunningSum(const VQwScaler_Channel &value, Int_t count=0, Int_t ErrorMask=0xFFFFFFF)
Templated concrete scaler channel with configurable data masking.
void ConstructBranchAndVector(TTree *tree, TString &prefix, QwRootTreeBranchVector &values) override
Int_t ProcessEvBuffer(UInt_t *buffer, UInt_t num_words_left, UInt_t index=0) override
Process the CODA event buffer for this element.
virtual VQwHardwareChannel * Clone() const
void EncodeEventData(std::vector< UInt_t > &buffer) override
Encode the event data into a CODA buffer.
void FillTreeVector(QwRootTreeBranchVector &values) const override
UInt_t fGoodEventCount
Number of good events accumulated in this element.
VQwDataElement()
Default constructor.
UInt_t fErrorConfigFlag
contains the global/local/stability flags
void SetSubsystemName(TString sysname)
Set the name of the inheriting subsystem name.
TString fElementName
Name of this data element.
virtual const TString & GetElementName() const
Get the name of this element.
UInt_t fErrorFlag
This the standard error code generated for the channel that contains the global/local/stability flags...
void SetElementName(const TString &name)
Set the name of this element.
Bool_t IsNameEmpty() const
Is the name of this element empty?
TString GetSubsystemName() const
Return the name of the inheriting subsystem name.
UInt_t GetGoodEventCount() const
TString GetModuleType() const
Return the type of the beam instrument.
void SetModuleType(TString ModuleType)
set the type of the beam instrument
Abstract base for concrete hardware channels implementing dual-operator pattern.
void SetDataToSave(TString datatosave)
Set the flag indicating if raw or derived values are in this data element.
void SetNumberOfSubElements(const size_t elements)
Set the number of data words in this data element.
VQwHardwareChannel & operator=(const VQwHardwareChannel &value)
Arithmetic assignment operator: Should only copy event-based data.
void SetNumberOfDataWords(const UInt_t &numwords)
Set the number of data words in this data element.
UInt_t fNumberOfDataWords
Number of raw data words in this data element.
void SetDataToSaveByPrefix(const TString &prefix)
Set the flag indicating if raw or derived values are in this data element based on prefix.