QwAnalysis
QwSIS3320_Channel.cc
Go to the documentation of this file.
1 /**
2  * \file QwSIS3320_Channel.cc
3  *
4  * \brief Implementation of the decoding of SIS3320 sampling ADC data
5  *
6  * \author W. Deconinck
7  * \date 2009-09-04 18:06:23
8  * \ingroup QwCompton
9  *
10  * The QwSIS3320 set of classes is defined to read the integrated and sampled
11  * data from the Compton photon detector. Because the scope of this module is
12  * similar the the VQWK ADC module (integration and asymmetries), parts of
13  * this class are very similar to QwVQWK_Channel.
14  *
15  * Additional functionality is required to process the sampling data in the
16  * SIS3320 events.
17  *
18  */
19 
20 #include "QwSIS3320_Channel.h"
21 
22 // Qweak headers
23 #include "QwLog.h"
24 #include "QwHistogramHelper.h"
25 
26 // Initialize data storage format flags
27 const unsigned int QwSIS3320_Channel::FORMAT_ACCUMULATOR = 0x0;
28 const unsigned int QwSIS3320_Channel::FORMAT_LONG_WORD_SAMPLING = 0x1;
29 const unsigned int QwSIS3320_Channel::FORMAT_SHORT_WORD_SAMPLING = 0x2;
30 // Initialize sampling mode format flags
31 const unsigned int QwSIS3320_Channel::MODE_ACCUM_EVENT = 0x1;
32 const unsigned int QwSIS3320_Channel::MODE_MULTI_EVENT = 0x3;
33 const unsigned int QwSIS3320_Channel::MODE_SINGLE_EVENT = 0x4;
34 const unsigned int QwSIS3320_Channel::MODE_NOTREADY = 0xda00;
35 
36 // Compile-time debug level
37 const Bool_t QwSIS3320_Channel::kDEBUG = kFALSE;
38 
39 
40 /**
41  * Conversion factor to translate the average bit count in an ADC
42  * channel of the SIS3320 into average voltage.
43  * There are 2^12 possible states over the full 5 V range.
44  */
45 const Double_t QwSIS3320_Channel::kVoltsPerBit = 5.0 / pow(2.0, 12);
46 
47 /**
48  * Conversion factor to translate the single sampling period to time.
49  * The ADC will sample at 250 MHz, corresponding with 4 ns per sample.
50  */
51 const Double_t QwSIS3320_Channel::kNanoSecondsPerSample = 4.0;
52 
53 
54 /**
55  * Initialize the QwSIS3320_Channel by assigning it a name
56  * @param channel Number of the channel
57  * @param name Name for the channel
58  */
59 void QwSIS3320_Channel::InitializeChannel(UInt_t channel, TString name)
60 {
61  // Inherited from VQwDataElement
62  SetElementName(name);
64 
65  // Set channel number
66  fChannel = channel;
67 
68  // Set accumulator names
69  for (size_t i = 0; i < fAccumulators.size(); i++) {
70  TString name = GetElementName() + TString("_accum") + Form("%ld",i);
71  fAccumulators[i].SetElementName(name);
72  fAccumulatorsRaw[i].SetElementName(name + "_raw");
73  }
74 
75  // Start with zero samples
76  fSamples.clear(); fSamplesRaw.clear();
77  // Clear the average samples
80 
81  // Enabled by MMD
82  //for (size_t i = 0; i < fSamples.size(); i++) {
83  // TString name = GetElementName() + TString("_samples") + Form("%ld",i);
84  // fSamples[i].SetElementName(name);
85  // fSamplesRaw[i].SetElementName(name + "_raw");
86  //}
87 
88  // Default values when no event read yet
89  fCurrentEvent = -1;
90  fHasSamplingData = kFALSE;
91  fHasAccumulatorData = kFALSE;
92 
93  // Pedestal calibration
94  fPedestal = 0.0;
95  fCalibrationFactor = 1.0;
96 
97  // Mock data parameters
98  fMockAsymmetry = 0.0;
99  fMockGaussianMean = 0.0;
100  fMockGaussianSigma = 0.0;
101 }
102 
103 /**
104  * Check whether the event is a good event from the number of read samples
105  * @return kTRUE if samples have been read
106  */
108 {
109  Bool_t fEventIsGood = kTRUE;
110  for (size_t i = 0; i < fSamples.size(); i++)
111  fEventIsGood &= (fSamples[i].GetNumberOfSamples() > 0);
112  return fEventIsGood;
113 }
114 
115 /**
116  * Clear the event data in sampling buffer and accumulators
117  */
119 {
120  // Clear the sampled events
121  for (size_t i = 0; i < fSamples.size(); i++)
122  fSamples.at(i).ClearEventData();
123  fSamples.clear(); // and back to zero events
124  for (size_t i = 0; i < fSamplesRaw.size(); i++)
125  fSamplesRaw.at(i).ClearEventData();
126  fSamplesRaw.clear(); // and back to zero events
127  // Clear the average samples
130 
131  // Clear the accumulators
132  for (size_t i = 0; i < fAccumulators.size(); i++)
133  fAccumulators.at(i).ClearEventData();
134  for (size_t i = 0; i < fAccumulatorsRaw.size(); i++)
135  fAccumulatorsRaw.at(i).ClearEventData();
136  for (size_t i = 0; i < fLogicalAccumulators.size(); i++)
137  fLogicalAccumulators.at(i).ClearEventData();
138  // (the number of accumulators is constant, don't clear them)
139 }
140 
141 /**
142  * Extract the sampling and accumulator data from the CODA buffer
143  * @param buffer Input buffer
144  * @param num_words_left Number of words left in the input buffer
145  * @param index Starting position in the buffer
146  * @return Number of words processed in this method
147  */
148 Int_t QwSIS3320_Channel::ProcessEvBuffer(UInt_t* buffer, UInt_t num_words_left, UInt_t index)
149 {
150  UInt_t words_read = 0;
151 
152  if (IsNameEmpty()) {
153  // This channel is not used, but is present in the data stream.
154  // Skip over this data.
155  words_read = fNumberOfDataWords;
156  } else if (num_words_left >= fNumberOfDataWords) {
157 
158  // The first word of the buffer is in the format: 0xFADC/id/ch/, where id
159  // is the module identification, and ch the channel number in that module.
160 
161  // Check whether the first word has 0xFADC as the upper half
162  UInt_t local_tag = (buffer[0] >> 16) & 0xFFFF;
163  if (local_tag != 0xFADC) return words_read;
164 
165  // Check whether the first word contains the correct channel number
166  //UInt_t local_module = (buffer[0] >> 8) & 0xFF;
167  UInt_t local_channel = buffer[0] & 0xFF;
168 
169  if (local_channel != fChannel) return words_read;
170 
171  // Determine whether we are receiving a sampling or accumulator buffer:
172  // Most significant short word (upper half):
173  // - 0x0 in accumulator mode
174  // - 0x1 when an expanded sampling buffer follows (12-bit sample / 32-bit word)
175  // - 0x2 when a packed sampling buffer follows (2 * 12-bit samples / 32-bit word)
176  // Least significant short word (lower half): 0x/stop mode/setup mode/ where
177  // - stop mode is 1 for hardware trigger
178  // - setup mode is 1,2,3,4...
179  UInt_t local_format = (buffer[1] >> 16) & 0xFFFF;
180  //UInt_t local_stopmode = (buffer[1] >> 8) & 0xFF;
181 
182  UInt_t local_setupmode = (buffer[1]) & 0xFF;
183  words_read = 2;
184  UInt_t packedtiming; // locals declared outside of switch/case
185  switch (local_format) {
186 
187  // This is a sampling buffer using long words
189  QwWarning << "QwSIS3320_Channel: Expanded word format not implemented"
190  << QwLog::endl;
191  break; // end of FORMAT_LONG_WORD_SAMPLING
192 
193  // This is a sampling buffer using short words
195  UInt_t numberofsamples, numberofevents_expected, numberofevents_actual;
196  UInt_t samplepointer;
197  switch (local_setupmode) {
198 
199  // This is a sampling buffer in multi event mode:
200  // - many events are saved in one buffer for a complete helicity event
201  case MODE_ACCUM_EVENT:
202  case MODE_MULTI_EVENT:
203  samplepointer = buffer[2];
204  numberofsamples = buffer[3];
205  numberofevents_expected = buffer[4];
206  words_read = 5;
207 
208  // For all events in this buffer
209  SetNumberOfEvents(numberofevents_expected);
210  numberofevents_actual = 0; // double check while reading the events
211  for (size_t event = 0; event < GetNumberOfEvents(); event++) {
212  // create a new raw sampled event
213  fSamplesRaw[event].SetNumberOfSamples(numberofsamples);
214  fSamplesRaw[event].SetSamplePointer(samplepointer);
215  // pass the buffer to read the samples
216  UInt_t samples_read = fSamplesRaw[event].ProcessEvBuffer(&(buffer[words_read]), num_words_left-words_read);
217  // check whether we actually read any data
218  if (samples_read == 0) break;
219  // an actual sampled event was read
220  words_read += samples_read;
221  numberofevents_actual++;
222  if (kDEBUG) QwOut << "Samples " << event << ": " << fSamplesRaw[event] << QwLog::endl;
223  }
224  if (numberofevents_expected != numberofevents_actual) {
225  QwWarning << "QwSIS3320_Channel: Expected " << numberofevents_expected << " events, "
226  << "but only read " << numberofevents_actual << "." << QwLog::endl;
227  SetNumberOfEvents(numberofevents_actual);
228  }
229 
230  break;
231 
232  // This is a sampling buffer in single event mode:
233  // - one event only is saved in the buffer, and each event triggers
234  // a read-out so multiple event can occur in one helicity period
235  // - because a circular buffer is used the pointer to the last sample
236  // is stored
237  case MODE_SINGLE_EVENT:
238  samplepointer = buffer[2];
239  numberofsamples = buffer[3];
240  numberofevents_expected = 1;
241 
242  // Create a new raw sampled event
243  SetNumberOfEvents(numberofevents_expected);
244  // Pass the buffer to read the samples (only one event)
245  fSamplesRaw.at(0).SetNumberOfSamples(numberofsamples);
246  fSamplesRaw.at(0).SetSamplePointer(samplepointer);
247  fSamplesRaw.at(0).ProcessEvBuffer(buffer, num_words_left, samplepointer);
248 
249  break;
250 
251  // Default
252  default:
253  QwError << "QwSIS3320_Channel: Received unknown sampling format: "
254  << std::hex << local_setupmode << std::dec << "." << QwLog::endl;
255  words_read = 0;
256  return words_read;
257 
258  } // end of switch (local_setupmode)
259 
260  fHasSamplingData = kTRUE;
261  break; // end of FORMAT_SHORT_WORD_SAMPLING
262 
263  // This is an accumulator buffer
264  case FORMAT_ACCUMULATOR:
265 
266  // Definition of the accumulators: (numbered from 1)
267  // 1: digital sum of all samples in the event
268  //
269  // 2: threshold 1 < sample value
270  // 3: threshold 2 < sample value <= threshold 1
271  // 4: sample value <= threshold 2
272  // Test: 1 == 2 + 3 + 4
273  //
274  // 6: sample value <= threshold 2
275  // and add samples before and after
276  // 5: threshold 2 < sample value <= threshold 1
277  // and add samples before and after
278  // but samples added in accumulator 6 are not added to accumulator 5
279 
280  // Read the accumulator blocks
281  for (size_t i = 0; i < fAccumulatorsRaw.size(); i++) {
282  words_read += fAccumulatorsRaw[i].ProcessEvBuffer(&(buffer[words_read]), num_words_left-words_read);
283  if (kDEBUG) QwOut << "Accum " << i+1 << ": " << fAccumulatorsRaw[i] << QwLog::endl;
284  }
285  // Read the threshold information
286  fAccumulatorDAC = buffer[words_read++];
287  // Thresholds are maximum 12 bits, so they seem to have wasted a word here :-)
288  fAccumulatorThreshold1 = buffer[words_read++];
289  fAccumulatorThreshold2 = buffer[words_read++];
290  // Read the timing information, packed in one word
291  packedtiming = buffer[words_read++];
292  fAccumulatorTimingAfter6 = (packedtiming >>= 8) & 0xFF;
293  fAccumulatorTimingBefore6 = (packedtiming >>= 8) & 0xFF;
294  fAccumulatorTimingAfter5 = (packedtiming >>= 8) & 0xFF;
295  fAccumulatorTimingBefore5 = (packedtiming >>= 8) & 0xFF;
296  if (kDEBUG) {
297  QwOut << "DAC: " << fAccumulatorDAC << QwLog::endl;
298  QwOut << "Thresholds: " << fAccumulatorThreshold1 << ", "
300  QwOut << "Timings on accum 5: " << fAccumulatorTimingAfter5 << ", "
302  QwOut << "Timings on accum 6: " << fAccumulatorTimingAfter6 << ", "
304  }
305  if (kDEBUG) {
306  QwSIS3320_Accumulator sum("sum");
308  QwOut << "Accum 1: " << fAccumulatorsRaw[0] << QwLog::endl;
309  QwOut << "Accum 2 + 3 + 4: " << sum << QwLog::endl;
310  }
311 
312  fHasAccumulatorData = kTRUE;
313  break; // end of FORMAT_ACCUMULATOR
314 
315  // This is an incomplete buffer
316  case MODE_NOTREADY:
317  QwError << "QwSIS3320_Channel: SIS3320 was not ready yet!" << QwLog::endl;
318  break; // end of FORMAT_NOTREADY
319 
320  // Default
321  default:
322  QwError << "QwSIS3320_Channel: Received unknown mode: "
323  << std::hex << local_format << std::dec << "." << QwLog::endl;
324  words_read = 0;
325  return words_read;
326 
327  } // end of switch (local_format)
328 
329  } else {
330  QwError << "QwSIS3320_Channel: Not enough words while processing buffer!" << QwLog::endl;
331  }
332 
333  return words_read;
334 }
335 
336 void QwSIS3320_Channel::EncodeEventData(std::vector<UInt_t> &buffer)
337 {
338  // Long_t sample;
339  std::vector<UInt_t> header;
340  std::vector<UInt_t> samples;
341 
342  if (IsNameEmpty()) {
343  // This channel is not used, but is present in the data stream.
344  // Skip over this data.
345  } else {
346  header.push_back(fChannel); // Channel number
347  header.push_back(fSampleFormat); // Sample format (e.g. 0x20003)
348 // TODO
349 // header.push_back(fNumberOfSamples * fNumberOfEvents); // Total number of samples
350 // header.push_back(fNumberOfSamples); // Number of samples per event
351  header.push_back(fNumberOfEvents); // Number of events
352  // Data is stored with two short words per long word
353 // for (size_t i = 0; i < fSamplesRaw.size() / 2; i++) {
354 // sample = fSamplesRaw.at(2*i) << 16;
355 // sample |= fSamplesRaw.at(2*i+1);
356 // samples.push_back(sample);
357 // }
358 
359  for (size_t i = 0; i < header.size(); i++)
360  buffer.push_back(header.at(i));
361  for (size_t i = 0; i < samples.size(); i++)
362  buffer.push_back(samples.at(i));
363  }
364 }
365 
366 /**
367  * Process the event by removing pedestals and applying calibration
368  */
370 {
371  // Correct for pedestal and calibration factor
372  if (fSamplesRaw.size() > 0) fSamples.resize(fSamplesRaw.size(), fSamplesRaw[0]);
373  for (size_t i = 0; i < fSamplesRaw.size(); i++) {
374  fSamples[i] = fSamplesRaw[i];
375  fSamples[i] -= fPedestal;
377  fSamples[i].UpdateGraph();
378  }
379  for (size_t i = 0; i < fAccumulatorsRaw.size(); i++) {
381  fAccumulators[i] -= fPedestal * fAccumulatorsRaw[i].GetNumberOfSamples();
383  }
384 
385  for (size_t i = 0; i < fLogicalAccumulators.size(); i++) {
386  fLogicalAccumulators[i].ProcessEvent();
387  }
388 
389  // Calculate the average sample snapshot
390  if (fSamples.size() > 0) {
391  fAverageSamples.SetNumberOfSamples(fSamples[0].GetNumberOfSamples());
392  fAverageSamplesRaw.SetNumberOfSamples(fSamples[0].GetNumberOfSamples());
393  }
394  for (size_t i = 0; i < fSamples.size(); i++) {
397  }
398  if (fSamples.size() > 0) {
399  fAverageSamples /= fSamples.size();
401  }
402 
403  // Calculate the windowed sample sums
404  for (size_t i = 0; i < fSamples.size(); i++) {
405  for (size_t timewindow = 0; timewindow < fTimeWindows.size(); timewindow++) {
406  UInt_t start = fTimeWindows[timewindow].first;
407  UInt_t stop = fTimeWindows[timewindow].second;
408  fTimeWindowAverages[timewindow] += fSamples[i].GetSumInTimeWindow(start, stop);
409  }
410  }
411 }
412 
413 /**
414  * Addition of offset
415  * @param value Right-hand side
416  * @return Left-hand side
417  */
418 const QwSIS3320_Channel QwSIS3320_Channel::operator+ (const Double_t &value) const
419 {
420  QwSIS3320_Channel result = *this;
421  result += value;
422  return result;
423 }
424 
425 /**
426  * Subtraction of offset
427  * @param value Right-hand side
428  * @return Left-hand side
429  */
430 const QwSIS3320_Channel QwSIS3320_Channel::operator- (const Double_t &value) const
431 {
432  QwSIS3320_Channel result = *this;
433  result -= value;
434  return result;
435 }
436 
437 /**
438  * Addition
439  * @param value Right-hand side
440  * @return Left-hand side
441  */
443 {
444  QwSIS3320_Channel result = *this;
445  result += value;
446  return result;
447 }
448 
449 /**
450  * Subtraction
451  * @param value Right-hand side
452  * @return Left-hand side
453  */
455 {
456  QwSIS3320_Channel result = *this;
457  result -= value;
458  return result;
459 }
460 
461 /**
462  * Assignment
463  * @param value Right-hand side
464  * @return Left-hand side
465  */
467 {
468  if (!IsNameEmpty()) {
469  for (size_t i = 0; i < fSamples.size(); i++)
470  fSamples[i] = value.fSamples.at(i);
471  for (size_t i = 0; i < fAccumulators.size(); i++ ) {
472  fAccumulators[i] = value.fAccumulators.at(i);
473  }
474  for (size_t i = 0; i < fLogicalAccumulators.size(); i++ )
476  }
477  return *this;
478 }
479 
480 /**
481  * Addition assignment of offset
482  * @param value Right-hand side
483  * @return Left-hand side
484  */
486 {
487  if (!IsNameEmpty()) {
488  for (size_t i = 0; i < fSamples.size(); i++)
489  fSamples[i] += value;
490  for (size_t i = 0; i < fAccumulators.size(); i++)
491  fAccumulators[i] += value;
492  for (size_t i = 0; i < fLogicalAccumulators.size(); i++)
493  fLogicalAccumulators[i] += value;
494  }
495  return *this;
496 }
497 
498 /**
499  * Subtraction assignment of offset
500  * @param value Right-hand side
501  * @return Left-hand side
502  */
504 {
505  if (!IsNameEmpty()) {
506  for (size_t i = 0; i < fSamples.size(); i++)
507  fSamples[i] -= value;
508  for (size_t i = 0; i < fAccumulators.size(); i++)
509  fAccumulators[i] -= value;
510  for (size_t i = 0; i < fLogicalAccumulators.size(); i++)
511  fLogicalAccumulators[i] -= value;
512  }
513  return *this;
514 }
515 
516 /**
517  * Addition assignment
518  * @param value Right-hand side
519  * @return Left-hand side
520  */
522 {
523  if (!IsNameEmpty()) {
524  for (size_t i = 0; i < fSamples.size(); i++)
525  fSamples[i] += value.fSamples.at(i);
526  for (size_t i = 0; i < fAccumulators.size(); i++)
527  fAccumulators[i] += value.fAccumulators.at(i);
528  for (size_t i = 0; i < fLogicalAccumulators.size(); i++)
529  fLogicalAccumulators[i] += value.fLogicalAccumulators.at(i);
530  }
531  return *this;
532 }
533 
534 /**
535  * Subtraction assignment
536  * @param value Right-hand side
537  * @return Left-hand side
538  */
540 {
541  if (!IsNameEmpty()) {
542  for (size_t i = 0; i < fSamples.size(); i++)
543  fSamples[i] -= value.fSamples.at(i);
544  for (size_t i = 0; i < fAccumulators.size(); i++)
545  fAccumulators[i] -= value.fAccumulators.at(i);
546  for (size_t i = 0; i < fLogicalAccumulators.size(); i++)
547  fLogicalAccumulators[i] -= value.fLogicalAccumulators.at(i);
548  }
549  return *this;
550 }
551 
552 /**
553  * Sum of two channels
554  * @param value1
555  * @param value2
556  */
558 {
559  *this = value1;
560  *this += value2;
561 }
562 
563 /**
564  * Difference of two channels
565  * @param value1
566  * @param value2
567  */
569 {
570  *this = value1;
571  *this -= value2;
572 }
573 
575 {
576  if (!IsNameEmpty()) {
577  for (size_t i = 0; i < fAccumulators.size(); i++)
578  fAccumulators[i].Ratio(numer.fAccumulators[i],denom.fAccumulators[i]);
579  for (size_t i = 0; i < fLogicalAccumulators.size(); i++)
581  denom.fLogicalAccumulators[i]);
582  }
583 }
584 
585 /**
586  * Addition of a offset
587  * @param offset
588  */
589 void QwSIS3320_Channel::Offset(Double_t offset)
590 {
591  if (!IsNameEmpty()) {
592  for (size_t i = 0; i < fSamples.size(); i++)
593  fSamples[i] += offset;
594  for (size_t i = 0; i < fAccumulators.size(); i++)
595  fAccumulators[i] += offset;
596  }
597 }
598 
599 /**
600  * Scaling by a scale factor
601  * @param scale
602  */
603 void QwSIS3320_Channel::Scale(Double_t scale)
604 {
605  if (!IsNameEmpty()) {
606  for (size_t i = 0; i < fSamples.size(); i++)
607  fSamples[i] *= scale;
608  for (size_t i = 0; i < fAccumulators.size(); i++)
609  fAccumulators[i] *= scale;
610  for (size_t i = 0; i < fLogicalAccumulators.size(); i++)
611  fLogicalAccumulators[i] *= scale;
612  }
613 }
614 
615 void QwSIS3320_Channel::ConstructHistograms(TDirectory *folder, TString &prefix)
616 {
617  // If we have defined a subdirectory in the ROOT file, then change into it.
618  if (folder != NULL) folder->cd();
619 
620  if (IsNameEmpty()) {
621  // This channel is not used, so skip filling the histograms.
622  } else {
623 
624  // Accumulators
625  for (size_t i = 0; i < fAccumulators.size(); i++) {
626  fAccumulators[i].ConstructHistograms(folder,prefix);
627  fAccumulatorsRaw[i].ConstructHistograms(folder,prefix);
628  }
629 
630  // Logical Accumulators
631  for (size_t i = 0; i < fLogicalAccumulators.size(); i++)
632  fLogicalAccumulators[i].ConstructHistograms(folder,prefix);
633 
634  TString basename = prefix + GetElementName();
635 
636  fHistograms.resize(3, NULL);
637  size_t index = 0;
638  fHistograms[index++] = gQwHists.Construct1DHist(basename+Form("_sum"));
639  fHistograms[index++] = gQwHists.Construct1DHist(basename+Form("_ped"));
640  fHistograms[index++] = gQwHists.Construct1DHist(basename+Form("_ped_raw"));
641  }
642 }
643 
645 {
646  size_t index = -1;
647  if (fSamples.size() == 0) return;
648 
649  if (IsNameEmpty()) {
650  // This channel is not used, so skip creating the histograms.
651  } else {
652 
653  // Accumulators
654  for (size_t i = 0; i < fAccumulators.size(); i++) {
655  fAccumulators[i].FillHistograms();
656  fAccumulatorsRaw[i].FillHistograms();
657  }
658 
659  // Logical Accumulators
660  for (size_t i = 0; i< fLogicalAccumulators.size(); i++ ) {
661  fLogicalAccumulators[i].FillHistograms();
662  }
663 
664  if (fHistograms[++index] != NULL)
665  fHistograms[index]->Fill(fAverageSamples.GetSum());
666  if (fHistograms[++index] != NULL)
667  fHistograms[index]->Fill(fAverageSamples.GetSample(0));
668  if (fHistograms[++index] != NULL)
669  fHistograms[index]->Fill(fAverageSamplesRaw.GetSample(0));
670  }
671 }
672 
673 void QwSIS3320_Channel::ConstructBranchAndVector(TTree *tree, TString &prefix, std::vector<Double_t> &values)
674 {
675  // Accumulators
676  for (size_t i = 0; i < fAccumulators.size(); i++) {
677  fAccumulators[i].ConstructBranchAndVector(tree, prefix, values);
678  fAccumulatorsRaw[i].ConstructBranchAndVector(tree, prefix, values);
679  }
680  // Logical Accumulators
681  for (size_t i = 0; i < fLogicalAccumulators.size(); i++)
682  fLogicalAccumulators[i].ConstructBranchAndVector(tree, prefix, values);
683 
684  // Samples (only collected when running over data, so structure does not
685  // actually exist yet at time of branch construction)
686  TString basename = prefix + GetElementName() + "_samples";
687  tree->Branch(basename, &fSamples);
688  //tree->Branch(basename + "_avg", &fAverageSamples);
689 }
690 
691 void QwSIS3320_Channel::FillTreeVector(std::vector<Double_t> &values) const
692 {
693  // Accumulators
694  for (size_t i = 0; i < fAccumulators.size(); i++) {
695  fAccumulators[i].FillTreeVector(values);
696  fAccumulatorsRaw[i].FillTreeVector(values);
697  }
698 
699  // Logical Accumulators
700  for (size_t i = 0; i < fLogicalAccumulators.size(); i++)
702 }
703 
704 /**
705  * Print value of the QwSIS3320_Channel
706  */
708 {
709  QwMessage << std::setprecision(4)
710  << std::setw(18) << std::left << GetElementName() << ", "
711  << std::setw(15) << std::left << GetNumberOfEvents();
712  for (size_t i = 0; i < fAccumulators.size(); i++)
713  QwMessage << ", " << i << ":" << fAccumulators[i].GetAccumulatorSum();
714  for (size_t i = 0; i < fLogicalAccumulators.size(); i++)
715  QwMessage << ", " << i << ":" << fLogicalAccumulators[i].GetAccumulatorSum();
717 }
718 
719 
720 /**
721  * Print some debugging information about the QwSIS3320_Channel
722  */
724 {
725  QwOut << "QwSIS3320_Channel \"" << GetElementName() << "\":" << QwLog::endl;
726  QwOut << "Number of events: " << GetNumberOfEvents() << QwLog::endl;
727  QwOut << "fSamplesRaw:" << QwLog::endl;
728  for (size_t i = 0; i < fSamplesRaw.size(); i++) {
729  QwOut << "event " << i << ": " << fSamplesRaw.at(i) << QwLog::endl;
730  }
731  QwOut << "avg: " << fAverageSamplesRaw << QwLog::endl;
732  QwOut << "avg sum: " << fAverageSamplesRaw.GetSum() << QwLog::endl;
733  QwOut << "fSamples:" << QwLog::endl;
734  for (size_t i = 0; i < fSamples.size(); i++) {
735  QwOut << "event " << i << ": " << fSamples.at(i) << QwLog::endl;
736  }
737  QwOut << "avg: " << fAverageSamples << QwLog::endl;
738  QwOut << "avg sum: " << fAverageSamples.GetSum() << QwLog::endl;
739  QwOut << "fAccumulators -> fAccumulatorsRaw:" << QwLog::endl;
740  for (size_t i = 0; i < fAccumulators.size(); i++) {
741  QwOut << i << ": " << fAccumulatorsRaw.at(i) << " -> " << fAccumulators.at(i) << QwLog::endl;
742  }
743  QwOut << "fLogicalAccumulators:" << QwLog::endl;
744  for (size_t i = 0; i < fLogicalAccumulators.size(); i++) {
745  QwOut << i << ": " << fLogicalAccumulators.at(i) << QwLog::endl;
746  }
747  UInt_t nped = 10;
748  if (fSamplesRaw.size() > 0) {
749  QwOut << "Average pedestal is: " << fAverageSamplesRaw.GetSumInTimeWindow(0, nped) / (Double_t) nped << QwLog::endl;
750  }
751 }
752 
753 /**
754  * Create a logical accumulator
755  */
757  const TString name,
758  const std::vector<TString> accums,
759  const std::vector<Double_t> weights)
760 {
761  // Create new logical accumulator with requested name
762  QwSIS3320_LogicalAccumulator localLogAccum(GetElementName() + "_accum" + name);
763 
764  // Loop over all entries in this logical accumulator
765  for (size_t i = 0; i < accums.size(); i++) {
766 
767  // Find the accumulator with the correct name
768  size_t j;
769  for (j = 0; j < fAccumulators.size(); j++) {
770  if (accums[i] == fAccumulators[j].GetElementName())
771  break;
772  }
773  // Not found
774  if (j == fAccumulators.size()) {
775  QwWarning << "Logical accumulator " << name << " has undefined components: " << QwLog::endl;
776  QwWarning << accums[i] << " could not be found." << QwLog::endl;
777  return;
778  }
779 
780  // Add reference and weight
781  localLogAccum.AddAccumulatorReference(&(fAccumulators[j]),weights[i]);
782  }
783 
784  // Add logical accumulator to the list
785  fLogicalAccumulators.push_back(localLogAccum);
786 }
static const Bool_t kDEBUG
#define QwMessage
Predefined log drain for regular messages.
Definition: QwLog.h:50
const QwSIS3320_Channel operator+(const Double_t &value) const
Class for the decoding of the SIS3320 sampling ADC data.
#define QwOut
Predefined log drain for explicit output.
Definition: QwLog.h:35
static const unsigned int MODE_MULTI_EVENT
static const unsigned int FORMAT_ACCUMULATOR
const QwSIS3320_Channel operator-(const Double_t &value) const
Bool_t IsNameEmpty() const
Is the name of this element empty?
std::vector< QwSIS3320_Samples > fSamples
SIS3320 sampling ADC accumulator.
std::vector< TH1_ptr > fHistograms
Histograms associated with this data element.
Definition: MQwHistograms.h:46
QwSIS3320_Channel & operator=(const QwSIS3320_Channel &value)
SIS3320 sampling ADC accumulator.
std::vector< QwSIS3320_Samples > fSamplesRaw
static const unsigned int MODE_SINGLE_EVENT
Double_t fMockGaussianSigma
Sigma of normal distribution.
Definition: MQwMockable.h:93
UInt_t fSampleFormat
Number of triggered events.
void FillHistograms()
Fill the histograms for this data element.
static const unsigned int FORMAT_SHORT_WORD_SAMPLING
void ConstructHistograms(TDirectory *folder, TString &prefix)
Construct the histograms for this data element.
void InitializeChannel(UInt_t channel, TString name)
size_t GetNumberOfEvents() const
static const unsigned int FORMAT_LONG_WORD_SAMPLING
std::vector< QwSIS3320_Accumulator > fAccumulatorsRaw
std::vector< std::pair< UInt_t, UInt_t > > fTimeWindows
void ConstructBranchAndVector(TTree *tree, TString &prefix, std::vector< Double_t > &values)
QwSIS3320_Channel & operator-=(const Double_t &value)
void SetNumberOfSamples(const UInt_t nsamples)
A logfile class, based on an identical class in the Hermes analyzer.
void Offset(Double_t Offset)
static const Double_t kVoltsPerBit
Double_t fMockGaussianMean
Mean of normal distribution.
Definition: MQwMockable.h:92
std::vector< QwSIS3320_LogicalAccumulator > fLogicalAccumulators
void Scale(Double_t Offset)
void EncodeEventData(std::vector< UInt_t > &buffer)
Encode the event data into a CODA buffer.
Int_t ProcessEvBuffer(UInt_t *buffer, UInt_t num_words_left, UInt_t index=0)
void PrintInfo() const
void SetElementName(const TString &name)
Set the name of this element.
void Difference(QwSIS3320_Channel &value1, QwSIS3320_Channel &value2)
Double_t fMockAsymmetry
Helicity asymmetry.
Definition: MQwMockable.h:91
void Sum(QwSIS3320_Channel &value1, QwSIS3320_Channel &value2)
QwSIS3320_Type GetSumInTimeWindow(const UInt_t start, const UInt_t stop) const
QwHistogramHelper gQwHists
Globally defined instance of the QwHistogramHelper class.
void Ratio(QwSIS3320_Channel &numer, QwSIS3320_Channel &denom)
void SetNumberOfDataWords(const UInt_t &numwords)
Set the number of data words in this data element.
void AddLogicalAccumulator(const TString name, const std::vector< TString > accums, const std::vector< Double_t > weights)
void SetNumberOfEvents(UInt_t nevents)
void PrintValue() const
void FillTreeVector(std::vector< Double_t > &values) const
std::vector< QwSIS3320_Accumulator > fAccumulators
UInt_t fNumberOfDataWords
Number of raw data words in this data element.
static const unsigned int MODE_ACCUM_EVENT
std::vector< Double_t > fTimeWindowAverages
static std::ostream & endl(std::ostream &)
End of the line.
Definition: QwLog.cc:299
QwSIS3320_Samples fAverageSamples
virtual const TString & GetElementName() const
Get the name of this element.
QwSIS3320_Type GetSum() const
QwSIS3320_Samples fAverageSamplesRaw
void AddAccumulatorReference(QwSIS3320_Accumulator *accum, Double_t weight)
static const Double_t kNanoSecondsPerSample
#define QwWarning
Predefined log drain for warnings.
Definition: QwLog.h:45
QwSIS3320_Channel & operator+=(const Double_t &value)
static const unsigned int MODE_NOTREADY
QwSIS3320_Type GetSample(size_t i) const
TH1F * Construct1DHist(const TString &inputfile, const TString &name_title)
UInt_t fNumberOfEvents
Current triggered event (allow for negative sentinel)
#define QwError
Predefined log drain for errors.
Definition: QwLog.h:40