JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
QwADC18_Channel.cc
Go to the documentation of this file.
1/*!
2 * \file QwADC18_Channel.cc
3 * \brief Implementation for HAPPEX 18-bit ADC channel decoding
4 */
5
6#include "QwADC18_Channel.h"
7
8// System headers
9#include <stdexcept>
10
11// ROOT headers
12#include <TTree.h>
13
14// Qweak headers
15#include "QwLog.h"
16#include "QwUnits.h"
17#include "QwBlinder.h"
18#include "QwHistogramHelper.h"
19#include "QwRootFile.h"
20#ifdef __USE_DATABASE__
21#include "QwDBInterface.h"
22#endif
23
24const Bool_t QwADC18_Channel::kDEBUG = kFALSE;
25
31const Int_t QwADC18_Channel::kMaxChannels = 4;
32
33const UInt_t QwADC18_Channel::mask31x = 0x80000000; // Header bit mask
34const UInt_t QwADC18_Channel::mask3029x = 0x60000000; // Channel number mask
35const UInt_t QwADC18_Channel::mask2625x = 0x06000000; // Divider value mask
36const UInt_t QwADC18_Channel::mask2422x = 0x01c00000; // Data type mask
37const UInt_t QwADC18_Channel::mask21x = 0x00200000; // Data type 0 value sign mask
38const UInt_t QwADC18_Channel::mask200x = 0x001fffff; // Data type 0 value field mask
39const UInt_t QwADC18_Channel::mask2118x = 0x003c0000; // Data types 1-2 sample number mask
40const UInt_t QwADC18_Channel::mask170x = 0x0003ffff; // Data types 1-2 value field mask
41const UInt_t QwADC18_Channel::mask150x = 0x0000ffff; // Data type 4 value field mask
42
43
44
45const Double_t QwADC18_Channel::kTimePerSample = 2.0 * Qw::us; // FIXME
46
47/*! Conversion factor to translate the average bit count in an ADC
48 * channel into average voltage.
49 * The base factor is roughly 76 uV per count, and zero counts corresponds
50 * to zero voltage.
51 * Store as the exact value for 20 V range, 18 bit ADC.
52 */
53const Double_t QwADC18_Channel::kADC18_VoltsPerBit = (20./(1<<18)); // FIXME
54
55/*! Static member function to return the word offset within a data buffer
56 * given the module number index and the channel number index.
57 * @param moduleindex Module index within this buffer; counts from zero
58 * @param channelindex Channel index within this module; counts from -1 (header)
59 * @return The number of words offset to the beginning of this
60 * channel's data from the beginning of the ADC18 buffer.
61 */
62Int_t QwADC18_Channel::GetBufferOffset(Int_t moduleindex, Int_t channelindex)
63{
64 Int_t offset = -1;
65 if (moduleindex<0 ){
66 QwError << "QwADC18_Channel::GetBufferOffset: Invalid module index,"
67 << moduleindex
68 << ". Must be zero or greater."
69 << QwLog::endl;
70 } else if (channelindex<-1 || channelindex>kMaxChannels){
71 QwError << "QwADC18_Channel::GetBufferOffset: Invalid channel index,"
72 << channelindex
73 << ". Must be in range [-1," << kMaxChannels << "]."
74 << QwLog::endl;
75 } else {
76 if (channelindex == -1) {
77 // Header
78 offset = kHeaderWordsPerBank
80 } else {
81 // Data word
82 offset = kHeaderWordsPerBank
85 + channelindex * kDataWordsPerChannel;
86 }
87 }
88 return offset;
89}
90
91
92/********************************************************/
94{
95 Bool_t bStatus;
96 if (bEVENTCUTMODE>0){//Global switch to ON/OFF event cuts set at the event cut file
97
98 if (bDEBUG)
99 QwWarning<<" QwQWVK_Channel "<<GetElementName()<<" "<<GetNumberOfSamples()<<QwLog::endl;
100
101 // Sample size check
102 bStatus = MatchNumberOfSamples(fNumberOfSamples_map);//compare the default sample size with no.of samples read by the module
103 if (!bStatus) {
105 }
106
107 //check sequence number
109 if (fSequenceNo_Counter==0 || GetSequenceNumber()==0){//starting the data run
111 }
112
113 if (!MatchSequenceNumber(fSequenceNo_Prev)){//we have a sequence number error
115 if (bDEBUG) QwWarning<<" QwQWVK_Channel "<<GetElementName()<<" Sequence number previous value = "<<fSequenceNo_Prev<<" Current value= "<< GetSequenceNumber()<<QwLog::endl;
116 }
117 }
118 else {
119 fGoodEventCount = 1;
120 fErrorFlag = 0;
121 }
122
123 return fErrorFlag;
124}
125
126
127/********************************************************/
130 fErrorCount_sample++; //increment the hw error counter
132 fErrorCount_SW_HW++; //increment the hw error counter
134 fErrorCount_Sequence++; //increment the hw error counter
136 fErrorCount_SameHW++; //increment the hw error counter
138 fErrorCount_ZeroHW++; //increment the hw error counter
141 fNumEvtsWithEventCutsRejected++; //increment the event cut error counter
142 }
143}
144
145/********************************************************/
146
147void QwADC18_Channel::InitializeChannel(TString name, TString datatosave)
148{
149 SetElementName(name);
150 SetDataToSave(datatosave);
153
154 kFoundPedestal = 0;
155 kFoundGain = 0;
156
157 fPedestal = 0.0;
158 fCalibrationFactor = 1.0;
159
160 fTreeArrayIndex = 0;
162
164
168
169 // Use internal random variable by default
171
172 // Mock drifts
173 fMockDriftAmplitude.clear();
174 fMockDriftFrequency.clear();
175 fMockDriftPhase.clear();
176
177 // Mock asymmetries
178 fMockAsymmetry = 0.0;
179 fMockGaussianMean = 0.0;
180 fMockGaussianSigma = 0.0;
181
182 // Event cuts
183 fULimit=-1;
184 fLLimit=1;
186
187 fErrorFlag=0; //Initialize the error flag
188 fErrorConfigFlag=0; //Initialize the error config. flag
189
190 //init error counters//
197
198 fRunningSum = 0;
199
203
204 fGoodEventCount = 0;
205
206 bEVENTCUTMODE = 0;
207
208 //std::cout<< "name = "<<name<<" error count same _HW = "<<fErrorCount_SameHW <<std::endl;
209 return;
210}
211
212/********************************************************/
213
214void QwADC18_Channel::InitializeChannel(TString subsystem, TString instrumenttype, TString name, TString datatosave){
215 InitializeChannel(name,datatosave);
216 SetSubsystemName(subsystem);
217 SetModuleType(instrumenttype);
218 //PrintInfo();
219}
220
222 UInt_t value = 0;
223 if (paramfile.ReturnValue("sample_size",value)){
225 } else {
226 QwWarning << "ADC18 Channel "
227 << GetElementName()
228 << " cannot set the default sample size."
229 << QwLog::endl;
230 }
231};
232
233
235{
236 fDiff_Raw = 0;
237 fBase_Raw = 0;
238 fPeak_Raw = 0;
239 fValue = 0.0;
240 fValueM2 = 0.0;
241 fValueError = 0.0;
242 fSequenceNumber = 0;
244 fGoodEventCount = 0;
245 fErrorFlag = 0;
246}
247
248void QwADC18_Channel::RandomizeEventData(int helicity, double time)
249{
250 // Calculate drift (if time is not specified, it stays constant at zero)
251 Double_t drift = 0.0;
252 for (UInt_t i = 0; i < fMockDriftFrequency.size(); i++) {
253 drift += fMockDriftAmplitude[i] * sin(2.0 * Qw::pi * fMockDriftFrequency[i] * time + fMockDriftPhase[i]);
254 }
255
256 Double_t value = fMockGaussianMean * (1 + helicity * fMockAsymmetry)
258 + drift;
259
260 fValue = value;
261 fSequenceNumber = 0;
263}
264
266{
267 fValue = resolution*GetRandomValue();
268 fValueM2 = 0.0;
271}
272
273// SetEventData() is used by the mock data generator to turn "model"
274// data values into their equivalent raw data. It should be used
275// nowhere else. -- pking, 2010-09-16
276
278{
279 fValue = value;
280 fDiff_Raw = (UInt_t) value;
281 fPeak_Raw = (UInt_t) value;
282 fBase_Raw = (UInt_t) 0;
283 fSequenceNumber = 0;
285}
286
293
294// FIXME here goes the encoding of raw data into CODA blocks
295void QwADC18_Channel::EncodeEventData(std::vector<UInt_t> &buffer)
296{
297 UInt_t localbuf[kDataWordsPerChannel] = {0};
298
299 if (IsNameEmpty()) {
300 // This channel is not used, but is present in the data stream.
301 // Fill in with zero.
302 localbuf[0] = 0;
303 } else {
304 localbuf[0] |= mask31x & (0 << 31);
305 localbuf[0] |= mask3029x & (0 << 29);
306 localbuf[0] |= mask2625x & (0 << 25);
307 UInt_t exp_dtype = 1;
308 switch (exp_dtype) {
309 case 0:
310 break;
311 case 1:
312 case 2:
313 localbuf[0] |= mask2422x & (2 << 22);
314 localbuf[0] |= mask170x & fPeak_Raw;
315 break;
316 case 4:
317 break;
318 default:
319 QwError << "QwADC18_Channel::EncodeEventData: Unknown data type" << QwLog::endl;
320 }
321 }
322
323 for (Int_t i = 0; i < kDataWordsPerChannel; i++) {
324 buffer.push_back(localbuf[i]);
325 }
326}
327
328Bool_t QwADC18_Channel::IsHeaderWord(UInt_t rawd) const
329{
330 return ((rawd & mask31x) != 0);
331}
332
334{
335 // "Actual" values from data word
336 UInt_t act_dtype = (rawd & mask2422x) >> 22;
337 [[maybe_unused]]
338 UInt_t act_chan = (act_dtype != 4) ?
339 ((rawd & mask3029x) >> 29) : 0;
340 UInt_t act_dvalue = (rawd & mask2625x) >> 25;
341 UInt_t act_snum = (act_dtype == 1 || act_dtype == 2) ?
342 ((rawd & mask2118x) >> 18) : 0;
343
344 // Interpret by data type
345 UInt_t value_raw = 0;
346 switch (act_dtype) {
347 case 0: // Diff word
348 static UInt_t prev_dvalue = act_dvalue;
349 if (act_dvalue != prev_dvalue) {
350 QwError << "QwADC18_Channel::ProcessEvBuffer: Number of samples changed " << act_dvalue << " " << prev_dvalue << QwLog::endl;
351 return 0;
352 }
353 value_raw = rawd & mask200x;
354 if (rawd & mask21x) value_raw = -((~value_raw & 0x1fffffff) + 1);
355 fNumberOfSamples = (1 << act_dvalue);
356 return value_raw;
357 break;
358 case 1: // Peak word
359 case 2: // Base word
360 if (act_snum != fNumberOfSamples) {
361 QwError << "QwADC18_Channel::ProcessEvBuffer: Number of samples changed " << act_snum << " " << fNumberOfSamples << QwLog::endl;
362 return 0;
363 }
364 if (act_dvalue != 0) {
365 QwError << "QwADC18_Channel::ProcessEvBuffer: Divider value non-zero 0x" << std::hex << rawd << std::dec << QwLog::endl;
366 return 0;
367 }
368 return rawd & mask170x;
369 break;
370 case 4: // DAC word
371 if (act_dvalue != 0) {
372 QwError << "QwADC18_Channel::ProcessEvBuffer: Divider value non-zero 0x" << std::hex << rawd << std::dec << QwLog::endl;
373 return 0;
374 }
375 return rawd & mask150x;
376 break;
377 default:
378 QwError << "QwADC18_Channel::ProcessEvBuffer: Unknown data type 0x" << std::hex << rawd << std::dec << QwLog::endl;
379 return 0;
380 }
381}
382
383// FIXME here goes the decoding of raw data from CODA blocks
384Int_t QwADC18_Channel::ProcessEvBuffer(UInt_t* buffer, UInt_t num_words_left, UInt_t index)
385{
386 Bool_t debug = false;
387
388 // Print buffer
389 if (debug) {
390 QwOut << GetElementName() << " : " << QwLog::endl << std::hex;
391 UInt_t n = 25;
392 for (size_t i = 0; i < num_words_left; i++) {
393 QwOut << "0x" << std::setfill('0') << std::setw(8) << buffer[i] << " ";
394 if (i % n == n - 1) QwOut << QwLog::endl;
395 }
396 QwOut << std::dec << std::setfill(' ') << std::setw(0) << QwLog::endl;
397 }
398
399 UInt_t words_read = 0;
400 if (IsNameEmpty()) {
401 // This channel is not used, but is present in the data stream.
402 // Skip over this data.
403 words_read = kDataWordsPerChannel;
404 } else if (num_words_left >= fNumberOfDataWords) {
405
406 // Is this a header word?
407 if (IsHeaderWord(buffer[0])) {
408
409 // Debug output
410 if (debug) {
411 QwOut << " : header " << std::hex;
412 UInt_t n = kHeaderWordsPerModule;
413 for (size_t i = 0; i < n && i < num_words_left; i++) {
414 QwOut << "0x" << std::setfill('0') << std::setw(8) << buffer[i] << " ";
415 }
416 QwOut << std::dec << std::setfill(' ') << std::setw(0) << QwLog::endl;
417 }
418
419 // Check if enough words left
420 if (num_words_left < kHeaderWordsPerModule) {
421 QwError << "QwADC18_Channel::ProcessEvBuffer: Not enough words left!" << QwLog::endl;
422 return num_words_left;
423 }
424
425 // FIXME Catch 0xfa180bad
426
427 // Header word: read DAC value
429
430 words_read = kHeaderWordsPerModule;
431
432 } else {
433
434 // Debug output
435 if (debug) {
436 QwOut << " : channel " << std::hex;
437 UInt_t n = kDataWordsPerChannel;
438 for (size_t i = 0; i < n && i < num_words_left; i++) {
439 QwOut << "0x" << std::setfill('0') << std::setw(8) << buffer[i] << " ";
440 }
441 QwOut << std::dec << std::setfill(' ') << std::setw(0) << QwLog::endl;
442 }
443
444 // Check if enough words left
445 if (num_words_left < kDataWordsPerChannel) {
446 QwError << "QwADC18_Channel::ProcessEvBuffer: Not enough words left!" << QwLog::endl;
447 return num_words_left;
448 }
449
450 // Data channel words: read diff, peak, base
451 fDiff_Raw = ProcessDataWord(buffer[0]);
452 fPeak_Raw = ProcessDataWord(buffer[1]);
453 fBase_Raw = ProcessDataWord(buffer[2]);
454
455 words_read = kDataWordsPerChannel;
456 }
457
458 } else {
459 QwError << "QwADC18_Channel::ProcessEvBuffer: Not enough words!" << QwLog::endl;
460 }
461
462 return words_read;
463}
464
465
466
468{
469 if (fNumberOfSamples == 0 && fDiff_Raw == 0) {
470 // There isn't valid data for this channel. Just flag it and move on.
471 fValue = 0.0;
472 fValueM2 = 0.0;
474 } else if (fNumberOfSamples == 0) {
475 // This is probably a more serious problem.
476 QwWarning << "QwADC18_Channel::ProcessEvent: Channel "
477 << GetElementName()
478 << " has fNumberOfSamples == 0 but has valid data in the value filed."
479 << "Flag this as an error."
480 << QwLog::endl;
481 fValue = 0.0;
482 fValueM2 = 0.0;
484 } else {
486 fValueM2 = 0.0; // second moment is zero for single events
487 }
488}
489
494
496{
497 QwMessage<<"***************************************"<<QwLog::endl;
498 QwMessage<<"Subsystem "<<GetSubsystemName()<<QwLog::endl;
499 QwMessage<<"Beam Instrument Type: "<<GetModuleType()<<QwLog::endl;
500 QwMessage<<"QwADC18 channel: "<<GetElementName()<<QwLog::endl;
501 QwMessage<<"fPedestal= "<< fPedestal<<QwLog::endl;
502 QwMessage<<"fCalibrationFactor= "<<fCalibrationFactor<<QwLog::endl;
503 QwMessage<<"fSequenceNumber= "<<fSequenceNumber<<QwLog::endl;
504 QwMessage<<"fNumberOfSamples= "<<fNumberOfSamples<<QwLog::endl;
505 QwMessage<<"fDiff_Raw= "<<fDiff_Raw<<QwLog::endl;
506 QwMessage<<"fPeak_Raw= "<<fPeak_Raw<<QwLog::endl;
507 QwMessage<<"fBase_Raw= "<<fBase_Raw<<QwLog::endl;
508 QwMessage<<"fValue = "<<std::setprecision(8) <<fValue << QwLog::endl;
509}
510
511void QwADC18_Channel::ConstructHistograms(TDirectory *folder, TString &prefix)
512{
513 // If we have defined a subdirectory in the ROOT file, then change into it.
514 if (folder != NULL) folder->cd();
515
516 if (IsNameEmpty()){
517 // This channel is not used, so skip filling the histograms.
518 } else {
519 // Now create the histograms.
520 if (prefix == TString("asym_")
521 || prefix == TString("diff_")
522 || prefix == TString("yield_"))
524
525 TString basename, fullname;
526 basename = prefix + GetElementName();
527
528 if(fDataToSave==kRaw)
529 {
530 fHistograms.resize(2, NULL);
531 size_t index=0;
532 fHistograms[index++] = gQwHists.Construct1DHist(basename);
533 fHistograms[index++] = gQwHists.Construct1DHist(basename+Form("_raw"));
534 }
535 else if(fDataToSave==kDerived)
536 {
537 fHistograms.resize(1, NULL);
538 Int_t index=0;
539 fHistograms[index++] = gQwHists.Construct1DHist(basename);
540 }
541 else
542 {
543 // this is not recognized
544 }
545 }
546}
547
549{
550 Int_t index=0;
551
552 if (IsNameEmpty())
553 {
554 // This channel is not used, so skip creating the histograms.
555 } else
556 {
557 if(fDataToSave==kRaw)
558 {
559 if (fHistograms[index] != NULL && (fErrorFlag)==0)
560 fHistograms[index++]->Fill(GetValue());
561 if (fHistograms[index] != NULL && (fErrorFlag)==0)
562 fHistograms[index++]->Fill(GetRawValue());
563 }
564 else if(fDataToSave==kDerived)
565 {
566 if (fHistograms[index] != NULL && (fErrorFlag)==0)
567 fHistograms[index++]->Fill(GetValue());
568 }
569 }
570}
571
572void QwADC18_Channel::ConstructBranchAndVector(TTree *tree, TString &prefix, QwRootTreeBranchVector &values)
573{
574 if (IsNameEmpty()){
575 // This channel is not used, so skip setting up the tree.
576 } else {
577 // Decide what to store based on prefix
578 SetDataToSaveByPrefix(prefix);
579
580 TString basename = prefix(0, (prefix.First("|") >= 0)? prefix.First("|"): prefix.Length()) + GetElementName();
581 fTreeArrayIndex = values.size();
582
583 values.push_back("value", 'D');
584 if (fDataToSave == kMoments) {
585 values.push_back("value_m2", 'D');
586 values.push_back("value_err", 'D');
587 }
588
589 values.push_back("Device_Error_Code", 'i');
590 if (fDataToSave == kRaw){
591 values.push_back("raw", 'I');
592 values.push_back("diff", 'I');
593 values.push_back("peak", 'I');
594 values.push_back("base", 'I');
595 }
596
598 if (gQwHists.MatchDeviceParamsFromList(basename.Data()))
599 tree->Branch(basename, &(values[fTreeArrayIndex]), values.LeafList(fTreeArrayIndex).c_str());
600 }
601}
602
603void QwADC18_Channel::ConstructBranch(TTree *tree, TString &prefix)
604{
605 if (IsNameEmpty()){
606 // This channel is not used, so skip setting up the tree.
607 } else {
608 TString basename = prefix + GetElementName();
609 tree->Branch(basename, &fValue, basename+"/D");
610 }
611}
612
614{
615 if (IsNameEmpty()) {
616 // This channel is not used, so skip setting up the tree.
617 } else if (fTreeArrayNumEntries == 0) {
618 static bool warned = false;
619 if (!warned) {
620 QwError << "QwADC18_Channel::FillTreeVector: fTreeArrayNumEntries=="
621 << fTreeArrayNumEntries << " (no branch constructed?)" << QwLog::endl;
622 QwError << "Offending element is " << GetElementName() << QwLog::endl;
623 warned = true;
624 }
625 } else if (values.size() < fTreeArrayIndex+fTreeArrayNumEntries) {
626 QwError << "QwADC18_Channel::FillTreeVector: values.size()=="
627 << values.size() << " name: " << fElementName
628 << "; fTreeArrayIndex+fTreeArrayNumEntries=="
629 << fTreeArrayIndex << '+' << fTreeArrayNumEntries << '='
631 << QwLog::endl;
632 } else {
633 size_t index = fTreeArrayIndex;
634 values.SetValue(index++, this->fValue);
635 if (fDataToSave == kMoments) {
636 values.SetValue(index++, fValueM2);
637 values.SetValue(index++, fValueError);
638 }
639 values.SetValue(index++, this->fErrorFlag);
640 if(fDataToSave==kRaw){
641 values.SetValue(index++, this->fValue_Raw);
642 values.SetValue(index++, this->fDiff_Raw);
643 values.SetValue(index++, this->fPeak_Raw);
644 values.SetValue(index++, this->fBase_Raw);
645 }
646 }
647}
648
649#ifdef HAS_RNTUPLE_SUPPORT
650void QwADC18_Channel::ConstructNTupleAndVector(std::unique_ptr<ROOT::RNTupleModel>& model, TString& prefix, std::vector<Double_t>& values, std::vector<std::shared_ptr<Double_t>>& fieldPtrs)
651{
652 if (IsNameEmpty()){
653 // This channel is not used, so skip setting up the RNTuple.
654 } else {
655 // Decide what to store based on prefix
656 SetDataToSaveByPrefix(prefix);
657
658 TString basename = prefix(0, (prefix.First("|") >= 0)? prefix.First("|"): prefix.Length()) + GetElementName();
659 fTreeArrayIndex = values.size();
660
661 // Calculate how many elements we need to avoid multiple push_back calls
662 size_t numElements = 2; // value + Device_Error_Code
663 if (fDataToSave == kMoments) numElements += 2; // _m2 + _err
664 if (fDataToSave == kRaw) numElements += 4; // _raw + _diff + _peak + _base
665
666 // Resize vectors once to avoid reallocation
667 size_t oldSize = values.size();
668 values.resize(oldSize + numElements, 0.0);
669 fieldPtrs.reserve(fieldPtrs.size() + numElements);
670
671 // Main value
672 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
673
674 if (fDataToSave == kMoments) {
675 fieldPtrs.push_back(model->MakeField<Double_t>((basename + "_m2").Data()));
676 fieldPtrs.push_back(model->MakeField<Double_t>((basename + "_err").Data()));
677 }
678
679 // Device error code
680 fieldPtrs.push_back(model->MakeField<Double_t>((basename + "_Device_Error_Code").Data()));
681
682 if (fDataToSave == kRaw){
683 fieldPtrs.push_back(model->MakeField<Double_t>((basename + "_raw").Data()));
684 fieldPtrs.push_back(model->MakeField<Double_t>((basename + "_diff").Data()));
685 fieldPtrs.push_back(model->MakeField<Double_t>((basename + "_peak").Data()));
686 fieldPtrs.push_back(model->MakeField<Double_t>((basename + "_base").Data()));
687 }
688
689 fTreeArrayNumEntries = values.size() - fTreeArrayIndex;
690 }
691}
692
693void QwADC18_Channel::FillNTupleVector(std::vector<Double_t>& values) const
694{
695 if (IsNameEmpty()) {
696 // This channel is not used, so skip filling.
697 } else if (fTreeArrayNumEntries < 0) {
698 QwError << "QwADC18_Channel::FillNTupleVector: fTreeArrayNumEntries=="
700 } else if (fTreeArrayNumEntries == 0) {
701 static bool warned = false;
702 if (!warned) {
703 QwError << "QwADC18_Channel::FillNTupleVector: fTreeArrayNumEntries=="
704 << fTreeArrayNumEntries << " (no construction done?)" << QwLog::endl;
705 QwError << "Offending element is " << GetElementName() << QwLog::endl;
706 warned = true;
707 }
708 } else if (values.size() < fTreeArrayIndex+fTreeArrayNumEntries) {
709 QwError << "QwADC18_Channel::FillNTupleVector: values.size()=="
710 << values.size() << " name: " << fElementName
711 << "; fTreeArrayIndex+fTreeArrayNumEntries=="
712 << fTreeArrayIndex << '+' << fTreeArrayNumEntries << '='
714 << QwLog::endl;
715 } else {
716 size_t index = fTreeArrayIndex;
717 values[index++] = this->fValue;
718 if (fDataToSave == kMoments) {
719 values[index++] = fValueM2;
720 values[index++] = fValueError;
721 }
722 values[index++] = this->fErrorFlag;
723 if(fDataToSave==kRaw){
724 values[index++] = this->fValue_Raw;
725 values[index++] = this->fDiff_Raw;
726 values[index++] = this->fPeak_Raw;
727 values[index++] = this->fBase_Raw;
728 }
729 }
730}
731#endif // HAS_RNTUPLE_SUPPORT
732
733
735{
736 if (this == &value) return *this;
737
738 if (!IsNameEmpty()) {
740 this->fDiff_Raw = value.fDiff_Raw;
741 this->fPeak_Raw = value.fPeak_Raw;
742 this->fBase_Raw = value.fBase_Raw;
743 this->fValue_Raw = value.fValue_Raw;
744 this->fValue = value.fValue;
745 this->fValueError = value.fValueError;
746 this->fValueM2 = value.fValueM2;
747 }
748 return *this;
749}
750
752 Double_t scale)
753{
754 if(this == &value) return;
755
756 if (!IsNameEmpty()) {
757 this->fValue = value.fValue * scale;
758 this->fValueError = value.fValueError;
759 this->fValueM2 = value.fValueM2 * scale * scale;
760 this->fErrorFlag = value.fErrorFlag;//error code is updated.
761 this->fGoodEventCount = value.fGoodEventCount;
762 }
763}
764
766{
767 const QwADC18_Channel* tmpptr;
768 tmpptr = dynamic_cast<const QwADC18_Channel*>(valueptr);
769 if (tmpptr!=NULL){
770 *this = *tmpptr;
771 } else {
772 TString loc="Standard exception from QwADC18_Channel::AssignValueFrom = "
773 +valueptr->GetElementName()+" is an incompatible type.";
774 throw std::invalid_argument(loc.Data());
775 }
776}
778{
779 const QwADC18_Channel* tmpptr;
780 tmpptr = dynamic_cast<const QwADC18_Channel*>(valueptr);
781 if (tmpptr!=NULL){
782 *this += *tmpptr;
783 } else {
784 TString loc="Standard exception from QwADC18_Channel::AddValueFrom = "
785 +valueptr->GetElementName()+" is an incompatible type.";
786 throw std::invalid_argument(loc.Data());
787 }
788}
790{
791 const QwADC18_Channel* tmpptr;
792 tmpptr = dynamic_cast<const QwADC18_Channel*>(valueptr);
793 if (tmpptr!=NULL){
794 *this -= *tmpptr;
795 } else {
796 TString loc="Standard exception from QwADC18_Channel::SubtractValueFrom = "
797 +valueptr->GetElementName()+" is an incompatible type.";
798 throw std::invalid_argument(loc.Data());
799 }
800}
802{
803 const QwADC18_Channel* tmpptr;
804 tmpptr = dynamic_cast<const QwADC18_Channel*>(valueptr);
805 if (tmpptr!=NULL){
806 *this *= *tmpptr;
807 } else {
808 TString loc="Standard exception from QwADC18_Channel::MultiplyBy = "
809 +valueptr->GetElementName()+" is an incompatible type.";
810 throw std::invalid_argument(loc.Data());
811 }
812}
814{
815 const QwADC18_Channel* tmpptr;
816 tmpptr = dynamic_cast<const QwADC18_Channel*>(valueptr);
817 if (tmpptr!=NULL){
818 *this /= *tmpptr;
819 } else {
820 TString loc="Standard exception from QwADC18_Channel::DivideBy = "
821 +valueptr->GetElementName()+" is an incompatible type.";
822 throw std::invalid_argument(loc.Data());
823 }
824}
825
826
828{
829 QwADC18_Channel result = *this;
830 result += value;
831 return result;
832}
833
835{
836 if (!IsNameEmpty()) {
837 this->fValue += value.fValue;
838 this->fValueM2 = 0.0;
839 this->fErrorFlag |= value.fErrorFlag;//error code is ORed.
840 }
841 return *this;
842}
843
845{
846 QwADC18_Channel result = *this;
847 result -= value;
848 return result;
849}
850
852{
853 if (!IsNameEmpty()){
854 this->fValue -= value.fValue;
855 this->fValueM2 = 0.0;
856 this->fErrorFlag |= (value.fErrorFlag);//error code is ORed.
857 }
858 return *this;
859}
860
862{
863 QwADC18_Channel result = *this;
864 result *= value;
865 return result;
866}
867
869{
870 if (!IsNameEmpty()){
871 this->fValue *= value.fValue;
872 this->fDiff_Raw = 0;
873 this->fPeak_Raw = 0;
874 this->fBase_Raw = 0;
875 this->fValueM2 = 0.0;
876 this->fErrorFlag |= (value.fErrorFlag);//error code is ORed.
877 }
878 return *this;
879}
880
882{
883 const QwADC18_Channel* tmpptr;
884 tmpptr = dynamic_cast<const QwADC18_Channel*>(&source);
885 if (tmpptr!=NULL){
886 *this += *tmpptr;
887 } else {
888 TString loc="Standard exception from QwADC18_Channel::operator+= "
889 +source.GetElementName()+" "
890 +this->GetElementName()+" are not of the same type";
891 throw(std::invalid_argument(loc.Data()));
892 }
893 return *this;
894}
895
897{
898 const QwADC18_Channel* tmpptr;
899 tmpptr = dynamic_cast<const QwADC18_Channel*>(&source);
900 if (tmpptr!=NULL){
901 *this -= *tmpptr;
902 } else {
903 TString loc="Standard exception from QwADC18_Channel::operator-= "
904 +source.GetElementName()+" "
905 +this->GetElementName()+" are not of the same type";
906 throw(std::invalid_argument(loc.Data()));
907 }
908 return *this;
909}
910
912{
913 const QwADC18_Channel* tmpptr;
914 tmpptr = dynamic_cast<const QwADC18_Channel*>(&source);
915 if (tmpptr!=NULL){
916 *this *= *tmpptr;
917 } else {
918 TString loc="Standard exception from QwADC18_Channel::operator*= "
919 +source.GetElementName()+" "
920 +this->GetElementName()+" are not of the same type";
921 throw(std::invalid_argument(loc.Data()));
922 }
923 return *this;
924}
925
927{
928 const QwADC18_Channel* tmpptr;
929 tmpptr = dynamic_cast<const QwADC18_Channel*>(&source);
930 if (tmpptr!=NULL){
931 *this /= *tmpptr;
932 } else {
933 TString loc="Standard exception from QwADC18_Channel::operator/= "
934 +source.GetElementName()+" "
935 +this->GetElementName()+" are not of the same type";
936 throw(std::invalid_argument(loc.Data()));
937 }
938 return *this;
939}
940
941
942void QwADC18_Channel::Sum(const QwADC18_Channel &value1, const QwADC18_Channel &value2)
943{
944 *this = value1;
945 *this += value2;
946}
947
949{
950 *this = value1;
951 *this -= value2;
952}
953
955{
956 if (!IsNameEmpty()) {
957 *this = numer;
958 *this /= denom;
959
960 // Set the raw values to zero.
961 fDiff_Raw = 0;
962 fPeak_Raw = 0;
963 fBase_Raw = 0;
964
965 // Remaining variables
967 fErrorFlag = (numer.fErrorFlag|denom.fErrorFlag);//error code is ORed.
968 }
969}
970
972{
973 // In this function, leave the "raw" variables untouched.
974 Double_t ratio;
975 Double_t variance;
976 if (!IsNameEmpty()) {
977 // The variances are calculated using the following formula:
978 // Var[ratio] = ratio^2 (Var[numer] / numer^2 + Var[denom] / denom^2)
979 //
980 // This requires that both the numerator and denominator are non-zero!
981 //
982 if (this->fValue != 0.0 && denom.fValue != 0.0){
983 ratio = (this->fValue) / (denom.fValue);
984 variance = ratio * ratio *
985 (this->fValueM2 / this->fValue / this->fValue
986 + denom.fValueM2 / denom.fValue / denom.fValue);
987 fValue = ratio;
988 fValueM2 = variance;
989 } else if (this->fValue == 0.0) {
990 fValue = 0.0;
991 fValueM2 = 0.0;
992 } else {
993 QwVerbose << "Attempting to divide by zero in "
995 fValue = 0.0;
996 fValueM2 = 0.0;
997 }
998
999 // Remaining variables
1000 // Don't change fGoodEventCount.
1001 // 'OR' the device error codes together.
1002 fErrorFlag |= denom.fErrorFlag;
1003 }
1004
1005 // Nanny
1006 if (fValue != fValue)
1007 QwWarning << "Angry Nanny: NaN detected in " << GetElementName() << QwLog::endl;
1008 return *this;
1009}
1010
1011//--------------------------------------------------------------------------------------------
1012
1014{
1015 if (!IsNameEmpty()) {
1016 this->fValue = atan(value.fValue);
1017 }
1018 // FIXME stuff missing here
1019}
1020
1021//--------------------------------------------------------------------------------------------
1023{
1024 if (!IsNameEmpty()){
1025 fValue = value1.fValue * value2.fValue;
1026 fDiff_Raw = 0;
1027 fPeak_Raw = 0;
1028 fBase_Raw = 0;
1029
1030 // Remaining variables
1032 fErrorFlag = (value1.fErrorFlag | value2.fErrorFlag);//error code is ORed.
1033 }
1034}
1035
1036/**
1037This function will add a offset to the hw_sum and add the same offset for blocks.
1038 */
1040{
1041 if (!IsNameEmpty())
1042 {
1043 fValue += offset;
1044 }
1045}
1046
1047void QwADC18_Channel::Scale(Double_t scale)
1048{
1049 if (!IsNameEmpty())
1050 {
1051 fValue *= scale;
1052 fValueM2 *= scale * scale;
1053 }
1054}
1055
1057{
1058 *this /= denom;
1059}
1060
1061
1062/** Moments and uncertainty calculation on the running sums and averages
1063 * The calculation of the first and second moments of the running sum is not
1064 * completely straightforward due to numerical instabilities associated with
1065 * small variances and large average values. The naive computation taking
1066 * the difference of the square of the average and the average of the squares
1067 * leads to the subtraction of two very large numbers to get a small number.
1068 *
1069 * Alternative algorithms (including for higher order moments) are supplied in
1070 * Pebay, Philippe (2008), "Formulas for Robust, One-Pass Parallel Computation
1071 * of Covariances and Arbitrary-Order Statistical Moments", Technical Report
1072 * SAND2008-6212, Sandia National Laboratories.
1073 * http://infoserve.sandia.gov/sand_doc/2008/086212.pdf
1074 *
1075 * In the following formulas the moments \f$ M^1 \f$ and \f$ M^2 \f$ are defined
1076 * \f{eqnarray}
1077 * M^1 & = & \frac{1}{n} \sum^n y \\
1078 * M^2 & = & \sum^n (y - \mu)
1079 * \f}
1080 *
1081 * Recurrence relations for the addition of a single event:
1082 * \f{eqnarray}
1083 * M^1_n & = & M^1_{n-1} + \frac{y - M^1_{n-1}}{n} \\
1084 * M^2_n & = & M^2_{n-1} + (y - M^1_{n-1})(y - M^1_n)
1085 * \f}
1086 *
1087 * For the addition of an already accumulated sum:
1088 * \f{eqnarray}
1089 * M^1 & = & M^1_1 + n_2 \frac{M^1_2 - M^1_1}{n} \\
1090 * M^2 & = & M^2_1 + M^2_2 + n_1 n_2 \frac{(M^1_2 - M^1_1)^2}{n}
1091 * \f}
1092 *
1093 * In these recursive formulas we start from \f$ M^1 = y \f$ and \f$ M^2 = 0 \f$.
1094 *
1095 * To calculate the mean and standard deviation we use
1096 * \f{eqnarray}
1097 * \mu & = & M^1 \\
1098 * \sigma^2 & = & \frac{1}{n} M^2
1099 * \f}
1100 * The standard deviation is a biased estimator, but this is what ROOT uses.
1101 * Better would be to divide by \f$ (n-1) \f$.
1102 *
1103 * We use the formulas provided there for the calculation of the first and
1104 * second moments (i.e. average and variance).
1105 */
1106// Accumulate the running moments M1 and M2.
1107// See header for parameter and return documentation.
1108void QwADC18_Channel::AccumulateRunningSum(const QwADC18_Channel& value, Int_t count, Int_t ErrorMask)
1109{
1110
1111 if(count==0){
1112 count = value.fGoodEventCount;
1113 }
1114
1115 // Moment calculations
1116 Int_t n1 = fGoodEventCount;
1117 Int_t n2 = count;
1118
1119 // If there are no good events, check whether device HW is good
1120 if (n2 == 0 && value.fErrorFlag == 0) {
1121 n2 = 1;
1122 }
1123
1124 if (ErrorMask == kPreserveError){
1125 //n = 1;
1126 if (n2 == 0) {
1127 n2 = 1;
1128 }
1129 if (count == -1) {
1130 n2 = -1;
1131 }
1132 }
1133
1134 Int_t n = n1 + n2;
1135
1136 // Set up variables
1137 Double_t M11 = fValue;
1138 Double_t M12 = value.fValue;
1139 Double_t M22 = value.fValueM2;
1140 if (n2 == 0) {
1141 // no good events for addition
1142 return;
1143 } else if (n2 == 1) {
1144 // simple version for addition of single event
1146 fValue += (M12 - M11) / n;
1147 fValueM2 += (M12 - M11) * (M12 - fValue); // note: using updated mean
1148 } else if (n2 > 1) {
1149 // general version for addition of multi-event sets
1150 fGoodEventCount += n2;
1151 fValue += n2 * (M12 - M11) / n;
1152 fValueM2 += M22 + n1 * n2 * (M12 - M11) * (M12 - M11) / n;
1153 }
1154
1155 // Nanny
1156 if (fValue != fValue)
1157 QwWarning << "Angry Nanny: NaN detected in " << GetElementName() << QwLog::endl;
1158}
1159
1160
1162{
1163 // See notes in QwVQWK_Channel; we are using:
1164 // error = sqrt(M2)/n,
1165 // or alternately we could use the unbiased estimator for both
1166 // the sigma and error on the mean:
1167 // error = sqrt(M2)/(n-1)
1168 if(fGoodEventCount > 0) {
1170 } else {
1171 fValueError = 0.0;
1172 }
1173}
1174
1175
1177{
1178 QwMessage << std::setprecision(8)
1179 << std::setw(18) << std::left << GetSubsystemName() << ""
1180 << std::setw(18) << std::left << GetModuleType() << ""
1181 << std::setw(18) << std::left << GetElementName() << ""
1182 << std::setw(12) << std::left << GetValue() << " +/- "
1183 << std::setw(12) << std::left << GetValueError() << " sig "
1184 << std::setw(12) << std::left << GetValueWidth() << ""
1185 << std::setw(12) << std::left << fGoodEventCount << ""
1186 << QwLog::endl;
1187}
1188
1189std::ostream& operator<< (std::ostream& stream, const QwADC18_Channel& channel)
1190{
1191 stream << channel.GetValue();
1192 return stream;
1193}
1194
1195/**
1196 * Blind this channel as an asymmetry
1197 * @param blinder Blinder
1198 */
1200{
1201 if (!IsNameEmpty()) {
1202 if (blinder->IsBlinderOkay() && ((fErrorFlag)==0) ){
1203 blinder->BlindValue(fValue);
1204 } else {
1207 }
1208 }
1209}
1210
1211/**
1212 * Blind this channel as a difference with specified yield
1213 * @param blinder Blinder
1214 * @param yield Corresponding yield
1215 */
1216void QwADC18_Channel::Blind(const QwBlinder *blinder, const QwADC18_Channel& yield)
1217{
1218 if (!IsNameEmpty()) {
1219 if (blinder->IsBlinderOkay() && ((fErrorFlag) ==0) ){
1220 blinder->BlindValue(fValue, yield.fValue);
1221 } else {
1222 blinder->ModifyThisErrorCode(fErrorFlag);//update the HW error code
1224 }
1225 }
1226}
1227
1229{
1230 Bool_t status = kTRUE;
1231 if (!IsNameEmpty()){
1232 status = (fSequenceNumber == seqnum);
1233 }
1234 return status;
1235}
1236
1238{
1239 Bool_t status = kTRUE;
1240 if (!IsNameEmpty()){
1241 status = (fNumberOfSamples==numsamp);
1242 if (! status){
1243 if (bDEBUG)
1244 QwError << "QwADC18_Channel::MatchNumberOfSamples: Channel "
1245 << GetElementName()
1246 << " had fNumberOfSamples==" << fNumberOfSamples
1247 << " and was supposed to have " << numsamp
1248 << std::endl;
1249 }
1250 }
1251 return status;
1252}
1253
1254//only check to see HW_Sum is within these given limits
1255Bool_t QwADC18_Channel::ApplySingleEventCuts(Double_t LL,Double_t UL)
1256{
1257 Bool_t status = kFALSE;
1258
1259 if (UL < LL){
1260 status=kTRUE;
1261 } else if (GetValue()<=UL && GetValue()>=LL){
1262 if ((fErrorFlag & kPreserveError)!=0)
1263 status=kTRUE;
1264 else
1265 status=kFALSE;//If the device HW is failed
1266 }
1267 std::cout<<(this->fErrorFlag & kPreserveError)<<std::endl;
1268 return status;
1269}
1270
1271Bool_t QwADC18_Channel::ApplySingleEventCuts()//This will check the limits and update event_flags and error counters
1272{
1273 Bool_t status;
1274
1275 if (bEVENTCUTMODE>=2){//Global switch to ON/OFF event cuts set at the event cut file
1276
1277 if (fULimit < fLLimit){
1278 status=kTRUE;
1279 } else if (GetValue()<=fULimit && GetValue()>=fLLimit){
1280 if ((fErrorFlag)==0)
1281 status=kTRUE;
1282 else
1283 status=kFALSE;//If the device HW is failed
1284 }
1285 else{
1286 if (GetValue()> fULimit)
1288 else
1290 status=kFALSE;
1291 }
1292
1293 if (bEVENTCUTMODE==3){
1294 status=kTRUE; //Update the event cut fail flag but pass the event.
1295 }
1296
1297
1298 }
1299 else{
1300 status=kTRUE;
1301 //fErrorFlag=0;//we need to keep the device error codes
1302 }
1303
1304 return status;
1305}
1306
1308{
1309 TString message;
1310 message = Form("%30s","Device name");
1311 message += Form("%9s", "HW Sat");
1312 message += Form("%9s", "Sample");
1313 message += Form("%9s", "SW_HW");
1314 message += Form("%9s", "Sequence");
1315 message += Form("%9s", "SameHW");
1316 message += Form("%9s", "ZeroHW");
1317 message += Form("%9s", "EventCut");
1318 QwMessage << "---------------------------------------------------------------------------------------------" << QwLog::endl;
1319 QwMessage << message << QwLog::endl;
1320 QwMessage << "---------------------------------------------------------------------------------------------" << QwLog::endl;
1321}
1322
1324{
1325 QwMessage << "---------------------------------------------------------------------------------------------" << QwLog::endl;
1326}
1327
1329{
1330 TString message;
1332 message = Form("%30s", GetElementName().Data());
1333 message += Form("%9d", fErrorCount_HWSat);
1334 message += Form("%9d", fErrorCount_sample);
1335 message += Form("%9d", fErrorCount_SW_HW);
1336 message += Form("%9d", fErrorCount_Sequence);
1337 message += Form("%9d", fErrorCount_SameHW);
1338 message += Form("%9d", fErrorCount_ZeroHW);
1339 message += Form("%9d", fNumEvtsWithEventCutsRejected);
1340
1341 if((fDataToSave == kRaw) && (!kFoundPedestal||!kFoundGain)){
1342 message += " >>>>> No Pedestal or Gain in map file";
1343 }
1344
1345 QwMessage << message << QwLog::endl;
1346 }
1347}
1348
1349void QwADC18_Channel::ScaledAdd(Double_t scale, const VQwHardwareChannel *value)
1350{
1351 const QwADC18_Channel* input = dynamic_cast<const QwADC18_Channel*>(value);
1352
1353 // follows same steps as += but w/ scaling factor
1354 if(input!=NULL && !IsNameEmpty()){
1355 // QwWarning << "Adding " << input->GetElementName()
1356 // << " to " << GetElementName()
1357 // << " with scale factor " << scale
1358 // << QwLog::endl;
1359 // PrintValue();
1360 // input->PrintValue();
1361 this->fDiff_Raw = 0;
1362 this->fPeak_Raw = 0;
1363 this->fBase_Raw = 0;
1364 this->fValue += scale * input->fValue;
1365 this->fValueM2 = 0.0;
1366 this->fNumberOfSamples += input->fNumberOfSamples;
1367 this->fSequenceNumber = 0;
1368 this->fErrorFlag |= (input->fErrorFlag);
1369 } else if (input == NULL && value != NULL) {
1370 TString loc="Standard exception from QwADC18_Channel::ScaledAdd "
1371 +value->GetElementName()+" "
1372 +this->GetElementName()+" are not of the same type";
1373 throw(std::invalid_argument(loc.Data()));
1374 }
1375}
1376
1377#ifdef __USE_DATABASE__
1378void QwADC18_Channel::AddErrEntriesToList(std::vector<QwErrDBInterface> &row_list)
1379{
1380 // TString message;
1381 // message = Form("%30s",GetElementName().Data());
1382 // message += Form("%9d", fErrorCount_HWSat);
1383 // message += Form("%9d", fErrorCount_sample);
1384 // message += Form("%9d", fErrorCount_SW_HW);
1385 // message += Form("%9d", fErrorCount_Sequence);
1386 // message += Form("%9d", fErrorCount_SameHW);
1387 // message += Form("%9d", fErrorCount_ZeroHW);
1388 // message += Form("%9d", fNumEvtsWithEventCutsRejected);
1389 // QwMessage << message << QwLog::endl;
1390
1391 // kErrorFlag_ADC18_Sat =0x1; //ADC18 Saturation Cut. Currently saturation limit is set to +/-8.5V
1392 // kErrorFlag_sample =0x2; //If sample size mis-matches with the default value in the map file.
1393 // kErrorFlag_Sequence =0x8; //If the ADC sequence number is not incrementing properly
1394 // kErrorFlag_SameHW =0x10; //If ADC value keep returning the same value
1395 // kErrorFlag_ZeroHW =0x20; //Check to see ADC is returning zero
1396
1397
1398
1399 // kErrorFlag_EventCut_L =0x40; //Flagged if lower limit of the event cut has failed
1400 // kErrorFlag_EventCut_U =0x80; //Flagged if upper limit of the event cut has failed
1401 // >>>>>> fNumEvtsWithEventCutsRejected
1402
1403 // outside QwADC18_Channel
1404 // kErrorFlag_BlinderFail = 0x0200;// in Decimal 512 to identify the blinder fail flag
1405 // kStabilityCutError = 0x10000000;// in Decimal 2^28 to identify the stability cut failure
1406
1407 // This is my modified mysql DB, Thursday, December 8 16:40:36 EST 2011, jhlee
1408 // Error code must be matched to MySQL DB
1409 //
1410 // mysql> select * from error_code;
1411 // +---------------+------------------------------+
1412 // | error_code_id | quantity |
1413 // +---------------+------------------------------+
1414 // | 1 | kErrorFlag_ADC18_Sat |
1415 // | 2 | kErrorFlag_sample |
1416 // | 3 | kErrorFlag_SW_HW |
1417 // | 4 | kErrorFlag_Sequence |
1418 // | 5 | kErrorFlag_SameHW |
1419 // | 6 | kErrorFlag_ZeroHW |
1420 // | 7 | kErrorFlag_EventCut_Rejected |
1421 // | 8 | kErrorFlag_EventCut_L |
1422 // | 9 | kErrorFlag_EventCut_U |
1423 // | 10 | kErrorFlag_BlinderFail |
1424 // | 11 | kStabilityCutError |
1425 // +---------------+------------------------------+
1426 // 11 rows in set (0.00 sec)
1427
1428
1429 QwErrDBInterface row;
1430 TString name = GetElementName();
1431
1432 row.Reset();
1433 row.SetDeviceName(name);
1434 row.SetErrorCodeId(1);
1436 row_list.push_back(row);
1437
1438 row.Reset();
1439 row.SetDeviceName(name);
1440 row.SetErrorCodeId(2);
1442 row_list.push_back(row);
1443
1444 row.Reset();
1445 row.SetDeviceName(name);
1446 row.SetErrorCodeId(3);
1448 row_list.push_back(row);
1449
1450
1451 row.Reset();
1452 row.SetDeviceName(name);
1453 row.SetErrorCodeId(4);
1455 row_list.push_back(row);
1456
1457
1458 row.Reset();
1459 row.SetDeviceName(name);
1460 row.SetErrorCodeId(5);
1462 row_list.push_back(row);
1463
1464 row.Reset();
1465 row.SetDeviceName(name);
1466 row.SetErrorCodeId(6);
1468 row_list.push_back(row);
1469
1470
1471 row.Reset();
1472 row.SetDeviceName(name);
1473 row.SetErrorCodeId(7);
1475 row_list.push_back(row);
1476 return;
1477
1478}
1479#endif
Physical units and constants for Qweak analysis.
Helper functions and utilities for ROOT histogram management.
QwHistogramHelper gQwHists
Globally defined instance of the QwHistogramHelper class.
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 QwOut
Predefined log drain for explicit output.
Definition QwLog.h:34
#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 kErrorFlag_SW_HW
Definition QwTypes.h:161
static const UInt_t kErrorFlag_sample
Definition QwTypes.h:160
static const UInt_t kPreserveError
Definition QwTypes.h:186
static const UInt_t kErrorFlag_SameHW
Definition QwTypes.h:163
static const UInt_t kErrorFlag_Sequence
Definition QwTypes.h:162
Database interface for QwIntegrationPMT and subsystems.
std::ostream & operator<<(std::ostream &stream, const QwADC18_Channel &channel)
A class for blinding data, adapted from G0 blinder class.
static const double pi
Angles: base unit is radian.
Definition QwUnits.h:107
static const double us
Definition QwUnits.h:78
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.
bool fUseExternalRandomVariable
Flag to use an externally provided normal random variable.
Double_t fMockGaussianSigma
Sigma of normal distribution.
Double_t fMockGaussianMean
Mean of normal distribution.
std::vector< Double_t > fMockDriftPhase
Harmonic drift phase.
Double_t GetRandomValue()
static const Int_t kFooterWordsPerModule
static const Int_t kMaxChannels
Double_t GetValue(size_t element) const override
static const Int_t kHeaderWordsPerBank
UInt_t fNumberOfSamples
Number of samples read through the module.
static const Int_t kHeaderWordsPerModule
static const Bool_t kDEBUG
Double_t GetValueError() const
Int_t fErrorCount_HWSat
check to see ADC channel is saturated
void PrintInfo() const override
Print multiple lines of information about this data element.
QwADC18_Channel & operator*=(const QwADC18_Channel &value)
static const Double_t kADC18_VoltsPerBit
void AddValueFrom(const VQwHardwareChannel *valueptr) override
Int_t ApplyHWChecks() override
Int_t fErrorCount_SW_HW
HW_sum==SW_sum check.
void RandomizeEventData(int helicity=0.0, double time=0.0) override
Internally generate random event data.
void ProcessEvent() override
Process the event data according to pedestal and calibration factor.
static void PrintErrorCounterHead()
static const UInt_t mask3029x
static const Int_t kFooterWordsPerBank
const QwADC18_Channel operator+(const QwADC18_Channel &value) const
Int_t fSequenceNo_Counter
Internal counter to keep track of the sequence number.
Int_t fErrorCount_SameHW
check to see ADC returning same HW value
void FillHistograms() override
Fill the histograms for this data element.
void Product(const QwADC18_Channel &value1, const QwADC18_Channel &value2)
void SubtractValueFrom(const VQwHardwareChannel *valueptr) override
Int_t fErrorCount_sample
for sample size check
Int_t fSequenceNo_Prev
Keep the sequence number of the last event.
void ArcTan(const QwADC18_Channel &value)
void Sum(const QwADC18_Channel &value1, const QwADC18_Channel &value2)
void ConstructHistograms(TDirectory *folder, TString &prefix) override
Construct the histograms for this data element.
void Scale(Double_t Offset) override
void CalculateRunningAverage() override
size_t GetSequenceNumber() const
void Difference(const QwADC18_Channel &value1, const QwADC18_Channel &value2)
void PrintValue() const override
Print single line of value and error of this data element.
void FillTreeVector(QwRootTreeBranchVector &values) const override
Int_t fErrorCount_ZeroHW
check to see ADC returning zero
void ConstructBranch(TTree *tree, TString &prefix) override
static const UInt_t mask2422x
void AddChannelOffset(Double_t Offset)
void PrintErrorCounters() const override
report number of events failed due to HW and event cut failure
void AccumulateRunningSum(const QwADC18_Channel &value, Int_t count=0, Int_t ErrorMask=0xFFFFFFF)
static const UInt_t mask2625x
void Ratio(const QwADC18_Channel &numer, const QwADC18_Channel &denom)
static const UInt_t mask170x
Int_t fADC_Same_NumEvt
Keep track of how many events with same ADC value returned.
void SetRawEventData() override
void ClearEventData() override
Clear the event data in this element.
void ScaledAdd(Double_t scale, const VQwHardwareChannel *value) override
void AssignScaledValue(const QwADC18_Channel &value, Double_t scale)
const QwADC18_Channel operator-(const QwADC18_Channel &value) const
QwADC18_Channel & operator=(const QwADC18_Channel &value)
Bool_t MatchNumberOfSamples(size_t numsamp)
static const Bool_t bDEBUG
debugging display purposes
QwADC18_Channel * fRunningSum
Pointer to the running sum for this channel.
void SmearByResolution(double resolution) override
void ConstructBranchAndVector(TTree *tree, TString &prefix, QwRootTreeBranchVector &values) override
void SetEventData(Double_t value)
void LoadChannelParameters(QwParameterFile &paramfile) override
UInt_t fPreviousSequenceNumber
Previous event sequence number for this channel.
Int_t fNumEvtsWithEventCutsRejected
Counts the Event cut rejected events.
QwADC18_Channel & operator-=(const QwADC18_Channel &value)
static const UInt_t mask200x
static const UInt_t mask31x
VQwHardwareChannel & operator/=(const VQwHardwareChannel &input) override
Double_t GetAverageVolts() const
void IncrementErrorCounters() override
void Blind(const QwBlinder *blinder)
Blind this channel as an asymmetry.
static const Double_t kTimePerSample
void MultiplyBy(const VQwHardwareChannel *valueptr) override
Bool_t ApplySingleEventCuts() override
QwADC18_Channel & operator+=(const QwADC18_Channel &value)
Double_t GetValueWidth() const
static const UInt_t mask2118x
static Int_t GetBufferOffset(Int_t moduleindex, Int_t channelindex)
Bool_t IsHeaderWord(UInt_t word) const
Decode the event data from a CODA buffer.
void InitializeChannel(TString name, TString datatosave) override
Initialize the fields in this object.
static void PrintErrorCounterTail()
Double_t GetValue() const
static const UInt_t mask21x
static const Int_t kDataWordsPerChannel
Bool_t MatchSequenceNumber(size_t seqnum)
UInt_t fNumberOfSamples_map
Number of samples in the expected to read through the module. This value is set in the QwBeamline map...
size_t GetNumberOfSamples() const
Int_t GetRawValue() const
void AssignValueFrom(const VQwDataElement *valueptr) override
Int_t fErrorCount_Sequence
sequence number check
Int_t ProcessEvBuffer(UInt_t *buffer, UInt_t num_words_left, UInt_t index=0) override
Process the CODA event buffer for this element.
void EncodeEventData(std::vector< UInt_t > &buffer) override
Encode the event data into a CODA buffer.
void DivideBy(const VQwHardwareChannel *valueptr) override
void SetDefaultSampleSize(size_t num_samples_map)
const QwADC18_Channel operator*(const QwADC18_Channel &value) const
static const UInt_t mask150x
Int_t ProcessDataWord(UInt_t word)
UInt_t fSequenceNumber
Event sequence number for this channel.
void SetN(UInt_t in)
void SetDeviceName(TString &in)
void SetErrorCodeId(UInt_t in)
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
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.
TString GetModuleType() const
Return the type of the beam instrument.
void SetModuleType(TString ModuleType)
set the type of the beam instrument
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.
virtual void AddErrEntriesToList(std::vector< QwErrDBInterface > &)
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.
Data blinding utilities for parity violation analysis.
Definition QwBlinder.h:57
const Bool_t & IsBlinderOkay() const
Definition QwBlinder.h:206
void ModifyThisErrorCode(UInt_t &errorcode) const
Definition QwBlinder.h:119
void BlindValue(Double_t &value) const
Asymmetry blinding.
Definition QwBlinder.h:124
static constexpr const Double_t kValue_BlinderFail
Definition QwBlinder.h:79