Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Df250EmulatorAlgorithm_v1.cc
Go to the documentation of this file.
2 
4  // Enables forced use of default values
5  FORCE_DEFAULT = 0;
6  // Default values for the essential parameters
7  NSA_DEF = 20;
8  NSB_DEF = 5;
9  THR_DEF = 120;
10  // Set verbosity
11  VERBOSE = 0;
12 
13  if(gPARMS){
14  gPARMS->SetDefaultParameter("EMULATION250:FORCE_DEFAULT", FORCE_DEFAULT,"Set to >0 to force use of default values");
15  gPARMS->SetDefaultParameter("EMULATION250:NSA", NSA_DEF,"Set NSA for firmware emulation, will be overwritten by BORConfig if present");
16  gPARMS->SetDefaultParameter("EMULATION250:NSB", NSB_DEF,"Set NSB for firmware emulation, will be overwritten by BORConfig if present");
17  gPARMS->SetDefaultParameter("EMULATION250:THR", THR_DEF,"Set threshold for firmware emulation, will be overwritten by BORConfig if present");
18  gPARMS->SetDefaultParameter("EMULATION250:VERBOSE", VERBOSE,"Set verbosity for f250 emulation");
19  }
20 }
21 
23  std::vector<Df250PulseTime*> &pt_objs,
24  std::vector<Df250PulsePedestal*> &pp_objs,
25  std::vector<Df250PulseIntegral*> &pi_objs)
26 {
27  // This is the main routine called by JEventSource_EVIO::GetObjects() and serves as the entry point for the code.
28  if (VERBOSE > 0) {
29  jout << " Df250EmulatorAlgorithm_v1::EmulateFirmware ==> Starting emulation <==" << endl;
30  jout << "rocid : " << rawData->rocid << " slot: " << rawData->slot << " channel: " << rawData->channel << endl;
31  }
32 
33  // First check that we have window raw data available
34  if (rawData == NULL) {
35  jerr << " ERROR: Df250EmulatorAlgorithm_v1::EmulateFirmware - raw sample data is missing" << endl;
36  jerr << " Contact mstaib@jlab.org" << endl;
37  return;
38  }
39 
40  // We need the channel number to get the threshold
41  uint32_t channel = rawData->channel;
42 
43  // First grab the config objects from the raw data and get the quantities we need from them
44  // The only things we need for this version of the f250 firmware are NSB, NSA, and the threshold.
45  // These are all stored in the BOR config. We can grab this from the raw data since that was already associated in JEventSource_EVIO::GetObjects.
46  const Df250BORConfig *f250BORConfig = NULL;
47  rawData->GetSingle(f250BORConfig);
48 
49  uint32_t NSA, NSB;
50  uint16_t THR;
51  //If this does not exist, or we force it, use the default values
52  if (f250BORConfig == NULL || FORCE_DEFAULT){
53  static int counter = 0;
54  NSA = NSA_DEF;
55  NSB = NSA_DEF;
56  THR = THR_DEF;
57  if (counter < 10){
58  counter++;
59  if (counter == 10) jout << " WARNING Df250EmulatorAlgorithm_v1::EmulateFirmware No Df250BORConfig == Using default values == LAST WARNING" << endl;
60  else jout << " WARNING Df250EmulatorAlgorithm_v1::EmulateFirmware No Df250BORConfig == Using default values" << endl;
61  }
62  }
63  else{
64  NSA = f250BORConfig->adc_nsa & 0x7F;
65  NSB = f250BORConfig->adc_nsb & 0x7F;
66  THR = f250BORConfig->adc_thres[channel];
67  if (VERBOSE > 0) jout << "Df250EmulatorAlgorithm_v1::EmulateFirmware NSA: " << NSA << " NSB: " << NSB << " THR: " << THR << endl;
68  }
69 
70  std::vector<const Df250PulseTime*> pulseTimes;
71  std::vector<const Df250PulsePedestal*> pulsePedestals;
72  std::vector<const Df250PulseIntegral*> pulseIntegrals;
73  rawData->Get(pulseTimes);
74  rawData->Get(pulsePedestals);
75  rawData->Get(pulseIntegrals);
76 
77  // Now we can start to loop over the raw data
78  // This requires a few passes due to some features in the way the quantities are calculated...
79  // The first step is to scan the samples for TC (threshold crossing sample) and compute the
80  // integrals of all pulses found.
81 
82  vector<uint16_t> samples = rawData->samples;
83  uint16_t NW = samples.size();
84  int npulses = 0;
85  const int max_pulses = 3;
86  uint32_t TC[max_pulses] = {};
87  uint32_t TMIN[max_pulses] = {3};
88  uint32_t pulse_integral[max_pulses] = {};
89 
90  for (unsigned int i=0; i < NW; i++) {
91  if (VERBOSE > 5) jout << "Df250EmulatorAlgorithm_v1::EmulateFirmware samples[" << i << "]: " << samples[i] << endl;
92  }
93 
94  for (unsigned int i=0; i < NW; i++) {
95  if ((samples[i] & 0xfff) > THR) {
96  TC[npulses] = i+1;
97  unsigned int ibegin = i > NSB ? (i - NSB) : 0; // Set to beginning of window if too early
98  unsigned int iend = (i + NSA) < uint32_t(NW) ? (i + NSA) : NW; // Set to last sample if too late
99  for (i = ibegin; i < iend; ++i)
100  pulse_integral[npulses] += (samples[i] & 0xfff);
101  for (; i < NW && (samples[i] & 0xfff) > THR; ++i) {}
102  if (++npulses == max_pulses)
103  break;
104  TMIN[npulses] = i;
105  }
106  }
107 
108  // That concludes the first pass over the data.
109  // Now we can head into the fine timing pass over the data.
110 
111  uint32_t VPEAK[max_pulses] = {};
112  uint16_t TMID[max_pulses] = {};
113  uint16_t VMID[max_pulses] = {};
114  uint16_t TFINE[max_pulses] = {};
115  uint32_t pulse_time[max_pulses] = {};
116  bool reportTC[max_pulses] = {};
117 
118  // The first 4 samples are used for the pedestal calculation
119  uint32_t VMIN = 0;
120  for (unsigned int i=0; i < 4; i++) {
121  VMIN += (samples[i] & 0xfff);
122  // There is an error if any of the first four samples are above threshold
123  // "A problem in the computation of the high resolution time will occur when VMIN is greater than VPEAK.
124  // In the current implementation of the algorithm, the simplest way to protect against this situation is
125  // to require that all 4 samples that determine the VMIN must be at or below threshold for the high resolution
126  // timing algorithm to be used. If this condition is not satisfied, the reported pulse time is TC, and
127  // both VMIN and VPEAK are reported as 0 in the pulse parameter data word (type 10) to identify the condition."
128  if ((samples[i] & 0xfff) > THR){
129  if (VERBOSE > 1) jout << "WARNING Df250EmulatorAlgorithm_v1::EmulateFirmware sample above threshold in pedestal calculation " << endl;
130  VMIN = 99999 << 2;
131  break;
132  }
133  }
134  VMIN = VMIN >> 2;
135 
136  for (int p=0; p < npulses; ++p) {
137  while (true) {
138  if (VMIN == 99999) {
139  VPEAK[p] = 0;
140  reportTC[p] = true;
141  pulse_time[p] = (TC[p] << 6);
142  break;
143  }
144  int ipeak;
145  for (ipeak = TC[p]; ipeak < NW; ++ipeak) {
146  if ((samples[ipeak] & 0xfff) < (samples[ipeak-1] & 0xfff)) {
147  VPEAK[p] = (samples[ipeak-1] & 0xfff);
148  break;
149  }
150  }
151  // There is an error condition if the TC sample is within 5 from the end of the window
152  // (and a typo in the document, the firmware is looking for (NW - TC) <= 5).
153  // "In the current implementation of the algorithm, a technical difficulty arises when TC is near the
154  // end of the trigger window. If (NW - TC) < 5, the reported pulse time is TC, and the pulse parameter
155  // data word (type 10) reports VPEAK = 0 and VMIN as measured.
156  //
157  // Note by RTJ:
158  // I believe that the algorithmic glitch is associated with (NW - TPEAK) < 5,
159  // which Mike may have found often corresponds to (NW - TC) <= 5, but not always.
160  if (NW - ipeak < 5) {
161  VPEAK[p] = 0;
162  pulse_time[p] = ((TC[p] - 1) << 6);
163  reportTC[p] = true;
164  break;
165  }
166  // If the peak search failed, there is another special error condition
167  // "A problem with the algorithm occurs if VPEAK is not found within the trigger window. In this case, the reported
168  // pulse time is TC. To identify this condition, the pulse parameter data word (type 10) reports VPEAK = 0 and VMIN as measured."
169  if (VPEAK[p] == 0) {
170  pulse_time[p] = (TC[p] << 6);
171  reportTC[p] = true;
172  break;
173  }
174 
175  if (VERBOSE > 1) {
176  jout << " pulse " << p << ": VMIN: " << VMIN << " reportTC: " << int(reportTC[p])
177  << " TC: " << TC[p] << " VPEAK: " << VPEAK[p] << endl;
178  }
179 
180  VMID[p] = (VMIN + VPEAK[p]) >> 1;
181  for (unsigned int i = TMIN[p] + 1; i < (uint32_t)ipeak; ++i) {
182  if ((samples[i] & 0xfff) > VMID[p]) {
183  TMID[p] = i;
184  break;
185  }
186  }
187  if (TMID[p] == 0) {
188 #if EMULATION250_MODE_8
189  if (p == 0) {
190 #else
191  if (false) {
192 #endif
193  TMID[p] = 1;
194  TFINE[p] = 0; // empirical constant
195  }
196  else {
197  TMID[p] = TC[p];
198  TFINE[p] = 0;
199  }
200  }
201  else {
202  int Vnext = (samples[TMID[p]] & 0xfff);
203  int Vlast = (samples[TMID[p]-1] & 0xfff);
204  if (Vnext > Vlast && VMID[p] >= Vlast)
205  TFINE[p] = 64 * (VMID[p] - Vlast) / (Vnext - Vlast);
206  else
207  TFINE[p] = 62;
208  }
209  pulse_time[p] = (TMID[p] << 6) + TFINE[p];
210  break;
211  }
212  VMIN = (VMIN < 99999)? VMIN : 0;
213 
214  if (VERBOSE > 1) {
215  jout << " pulse " << p << ": VMID: " << VMID[p] << " TMID: " << TMID[p]
216  << " TFINE: " << TFINE[p] << " time: " << pulse_time[p]
217  << " integral: " << pulse_integral[p] << endl;
218  }
219 
220  Df250PulseTime* f250PulseTime = new Df250PulseTime;
221  f250PulseTime->rocid = rawData->rocid;
222  f250PulseTime->slot = rawData->slot;
223  f250PulseTime->channel = rawData->channel;
224  f250PulseTime->itrigger = rawData->itrigger;
225  f250PulseTime->pulse_number = p;
226  f250PulseTime->quality_factor = reportTC[p];
227  f250PulseTime->time = pulse_time[p];
228  f250PulseTime->emulated = true;
229  f250PulseTime->time_emulated = pulse_time[p];
230  f250PulseTime->quality_factor_emulated = reportTC[p];
231  f250PulseTime->AddAssociatedObject(rawData);
232  pt_objs.push_back(f250PulseTime);
233 
234  Df250PulsePedestal* f250PulsePedestal = new Df250PulsePedestal;
235  f250PulsePedestal->rocid = rawData->rocid;
236  f250PulsePedestal->slot = rawData->slot;
237  f250PulsePedestal->channel = rawData->channel;
238  f250PulsePedestal->itrigger = rawData->itrigger;
239  f250PulsePedestal->pulse_number = p;
240  f250PulsePedestal->pedestal = VMIN;
241  f250PulsePedestal->pulse_peak = VPEAK[p];
242  f250PulsePedestal->emulated = true;
243  f250PulsePedestal->pedestal_emulated = VMIN;
244  f250PulsePedestal->pulse_peak_emulated = VPEAK[p];
245  f250PulsePedestal->AddAssociatedObject(rawData);
246  pp_objs.push_back(f250PulsePedestal);
247 
248  Df250PulseIntegral* f250PulseIntegral = new Df250PulseIntegral;
249  f250PulseIntegral->rocid = rawData->rocid;
250  f250PulseIntegral->slot = rawData->slot;
251  f250PulseIntegral->channel = rawData->channel;
252  f250PulseIntegral->itrigger = rawData->itrigger;
253  f250PulseIntegral->pulse_number = p;
254  f250PulseIntegral->quality_factor = reportTC[p];
255  f250PulseIntegral->integral = pulse_integral[p];
256  f250PulseIntegral->pedestal = VMIN;
257  f250PulseIntegral->nsamples_integral = NSA + NSB;
258  f250PulseIntegral->nsamples_pedestal = 1;
259  f250PulseIntegral->emulated = true;
260  f250PulseIntegral->integral_emulated = pulse_integral[p];
261  f250PulseIntegral->pedestal_emulated = VMIN;
262  f250PulseIntegral->AddAssociatedObject(rawData);
263  pi_objs.push_back(f250PulseIntegral);
264  }
265 
266  if (VERBOSE > 0) jout << " Df250EmulatorAlgorithm_v1::EmulateFirmware ==> Emulation complete <==" << endl;
267  return;
268 }
uint32_t pedestal_emulated
Calculated from raw data (when available)
void EmulateFirmware(const Df250WindowRawData *rawData, std::vector< Df250PulseTime * > &pt_objs, std::vector< Df250PulsePedestal * > &pp_objs, std::vector< Df250PulseIntegral * > &pi_objs)
uint32_t pulse_number
from Pulse Pedestal Data word
bool emulated
true if made from Window Raw Data
uint32_t quality_factor
from Pulse Integral Data word
uint32_t pulse_number
from Pulse Time Data word
uint32_t nsamples_integral
number of samples used in integral
vector< uint16_t > samples
uint32_t pulse_peak
from Pulse Pedestal Data word
bool emulated
true if made from Window Raw Data
double counter
Definition: FitGains.C:151
uint32_t quality_factor_emulated
Calculated from raw data if available.
uint32_t adc_nsa
Definition: bor_roc.h:90
uint32_t quality_factor
from Pulse Time Data word
uint32_t pulse_number
from Pulse Integral Data word
uint32_t time
from Pulse Time Data word
uint32_t time_emulated
Calculated from raw data if available.
uint32_t integral_emulated
Value calculated from raw data (if available)
bool emulated
true if made from Window Raw Data
uint32_t integral
from Pulse Integral Data word
uint32_t pedestal
from Pulse Integral Data word (future)
uint32_t pedestal_emulated
Value calculated from raw data (if available)
uint32_t channel
Definition: DDAQAddress.h:34
const double TMIN
uint32_t pulse_peak_emulated
Calculated from raw data (when available)
uint32_t adc_nsb
Definition: bor_roc.h:89
uint32_t rocid
Definition: DDAQAddress.h:32
uint16_t adc_thres[16]
Definition: bor_roc.h:91
uint32_t pedestal
from Pulse Pedestal Data word
uint32_t nsamples_pedestal
number of samples used in pedestal
uint32_t itrigger
Definition: DDAQAddress.h:35
uint32_t slot
Definition: DDAQAddress.h:33