Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DEVIOBufferWriter.cc
Go to the documentation of this file.
1 // This class is responsible for taking a single event and writing it
2 // into a buffer in EVIO format - based on hdl3
3 // https://halldsvn.jlab.org/repos/trunk/online/packages/monitoring/src/hdl3
4 
5 #include "DEVIOBufferWriter.h"
6 
7 
8 //------------------
9 // WriteEventToBuffer
10 //------------------
11 void DEVIOBufferWriter::WriteEventToBuffer(JEventLoop *loop, vector<uint32_t> &buff) const
12 {
13  vector<const JObject *> objects_to_save_null;
14  WriteEventToBuffer(loop, buff, objects_to_save_null);
15 }
16 
17 //------------------
18 // WriteEventToBuffer
19 //------------------
20 void DEVIOBufferWriter::WriteEventToBuffer(JEventLoop *loop, vector<uint32_t> &buff, vector<const JObject *> objects_to_save) const
21 {
22  /// This method will grab certain low-level objects and write them
23  /// into EVIO banks in a format compatible with the DAQ library.
24 
25  // Handle BOR events separately
26  // These should only be at the beginning of a file or when the run changes
27  if( loop->GetJEvent().GetStatusBit(kSTATUS_BOR_EVENT) ){
28  buff.clear();
29  WriteBORData(loop, buff);
30  return;
31  }
32 
33  // First, grab all of the low level objects
34  vector<const Df250TriggerTime*> f250tts;
35  vector<const Df250PulseData*> f250pulses;
36  vector<const Df250PulseIntegral*> f250pis;
37  vector<const Df250WindowRawData*> f250wrds;
38  vector<const Df125TriggerTime*> f125tts;
39  vector<const Df125PulseIntegral*> f125pis;
40  vector<const Df125CDCPulse*> f125cdcpulses;
41  vector<const Df125FDCPulse*> f125fdcpulses;
42  vector<const Df125WindowRawData*> f125wrds;
43  vector<const Df125Config*> f125configs;
44  vector<const DDIRCTriggerTime*> dirctts;
45  vector<const DDIRCTDCHit*> dirctdchits;
46  vector<const DCAEN1290TDCHit*> caen1290hits;
47  vector<const DCAEN1290TDCConfig*> caen1290configs;
48  vector<const DF1TDCHit*> F1hits;
49  vector<const DF1TDCTriggerTime*> F1tts;
50  vector<const DF1TDCConfig*> F1configs;
51  vector<const DEPICSvalue*> epicsValues;
52  vector<const DCODAEventInfo*> coda_events;
53  vector<const DCODAROCInfo*> coda_rocinfos;
54  vector<const DL1Info*> l1_info;
55  vector<const Df250Scaler*> f250scalers;
56 
57  // Optionally, allow the user to only save hits from specific objects
58  if(objects_to_save.size()==0) {
59  // If no special object list is passed, assume we should save everything
60  loop->Get(f250tts);
61  loop->Get(f250pulses);
62  loop->Get(f250pis);
63  loop->Get(f250wrds);
64  loop->Get(f125tts);
65  loop->Get(f125pis);
66  loop->Get(f125cdcpulses);
67  loop->Get(f125fdcpulses);
68  loop->Get(f125wrds);
69  loop->Get(f125configs);
70  loop->Get(dirctdchits);
71  loop->Get(dirctts);
72  loop->Get(caen1290hits);
73  loop->Get(caen1290configs);
74  loop->Get(F1hits);
75  loop->Get(F1tts);
76  loop->Get(F1configs);
77  loop->Get(epicsValues);
78  loop->Get(coda_events);
79  loop->Get(coda_rocinfos);
80  loop->Get(l1_info);
81  loop->Get(f250scalers);
82  } else {
83  // only save hits that correspond to certain reconstructed objects
84  loop->Get(epicsValues); // always read EPICS data
85  loop->Get(l1_info); // always read extra trigger data
86  loop->Get(f250scalers);
87  loop->Get(coda_events);
88  loop->Get(coda_rocinfos);
89  loop->Get(f125configs);
90  loop->Get(F1configs);
91  loop->Get(caen1290configs);
92 
93  // For ease-of-use, the list of reconstructed objects is passed as a vector<const JObject *>
94  // to handle the storage of the many different types of objects: showers, tracks, TOF hits, etc.
95  // The only downside is that we then don't know the actual type of the object.
96  // Therefore, we have to do some gymnastics:
97  // 1) see if the object pointed to is a base hit type
98  // 2) for any reconstructed object, just blindly grab all of the associated low-level hits and add them
99  // This technique only works assuming that all of the object associations have been properly formed
100  for(vector<const JObject *>::iterator obj_itr = objects_to_save.begin();
101  obj_itr != objects_to_save.end(); obj_itr++) {
102  const JObject *obj_ptr = *obj_itr;
103 
104  // first, see if these are low-level hit objects
105  if(auto *llobj_ptr = dynamic_cast<const Df250TriggerTime *>(obj_ptr)) {
106  f250tts.push_back(llobj_ptr);
107  } else if(auto *llobj_ptr = dynamic_cast<const Df250PulseData *>(obj_ptr)) {
108  f250pulses.push_back(llobj_ptr);
109  } else if(auto *llobj_ptr = dynamic_cast<const Df250PulseIntegral *>(obj_ptr)) {
110  f250pis.push_back(llobj_ptr);
111  } else if(auto *llobj_ptr = dynamic_cast<const Df250WindowRawData *>(obj_ptr)) {
112  f250wrds.push_back(llobj_ptr);
113  } else if(auto *llobj_ptr = dynamic_cast<const Df125TriggerTime *>(obj_ptr)) {
114  f125tts.push_back(llobj_ptr);
115  } else if(auto *llobj_ptr = dynamic_cast<const Df125PulseIntegral *>(obj_ptr)) {
116  f125pis.push_back(llobj_ptr);
117  } else if(auto *llobj_ptr = dynamic_cast<const Df125CDCPulse *>(obj_ptr)) {
118  f125cdcpulses.push_back(llobj_ptr);
119  } else if(auto *llobj_ptr = dynamic_cast<const Df125FDCPulse *>(obj_ptr)) {
120  f125fdcpulses.push_back(llobj_ptr);
121  } else if(auto *llobj_ptr = dynamic_cast<const Df125WindowRawData *>(obj_ptr)) {
122  f125wrds.push_back(llobj_ptr);
123  } else if(auto *llobj_ptr = dynamic_cast<const DDIRCTDCHit *>(obj_ptr)) {
124  dirctdchits.push_back(llobj_ptr);
125  } else if(auto *llobj_ptr = dynamic_cast<const DDIRCTriggerTime *>(obj_ptr)) {
126  dirctts.push_back(llobj_ptr);
127  } else if(auto *llobj_ptr = dynamic_cast<const DCAEN1290TDCHit *>(obj_ptr)) {
128  caen1290hits.push_back(llobj_ptr);
129  } else if(auto *llobj_ptr = dynamic_cast<const DF1TDCHit *>(obj_ptr)) {
130  F1hits.push_back(llobj_ptr);
131  } else if(auto *llobj_ptr = dynamic_cast<const DF1TDCTriggerTime *>(obj_ptr)) {
132  F1tts.push_back(llobj_ptr);
133  } else {
134  // if not, assume this is a reconstructed object, and just get all of the possible hits
135  vector<const Df250TriggerTime*> obj_f250tts;
136  vector<const Df250PulseData*> obj_f250pulses;
137  vector<const Df250PulseIntegral*> obj_f250pis;
138  vector<const Df250WindowRawData*> obj_f250wrds;
139  vector<const Df125TriggerTime*> obj_f125tts;
140  vector<const Df125PulseIntegral*> obj_f125pis;
141  vector<const Df125CDCPulse*> obj_f125cdcpulses;
142  vector<const Df125FDCPulse*> obj_f125fdcpulses;
143  vector<const Df125WindowRawData*> obj_f125wrds;
144  vector<const DDIRCTDCHit*> obj_dirctdchits;
145  vector<const DDIRCTriggerTime*> obj_dirctts;
146  vector<const DCAEN1290TDCHit*> obj_caen1290hits;
147  vector<const DF1TDCHit*> obj_F1hits;
148  vector<const DF1TDCTriggerTime*> obj_F1tts;
149 
150  obj_ptr->Get(obj_f250tts);
151  obj_ptr->Get(obj_f250pulses);
152  obj_ptr->Get(obj_f250pis);
153  obj_ptr->Get(obj_f250wrds);
154  obj_ptr->Get(obj_f125tts);
155  obj_ptr->Get(obj_f125pis);
156  obj_ptr->Get(obj_f125cdcpulses);
157  obj_ptr->Get(obj_f125fdcpulses);
158  obj_ptr->Get(obj_f125wrds);
159  obj_ptr->Get(obj_dirctdchits);
160  obj_ptr->Get(obj_dirctts);
161  obj_ptr->Get(obj_caen1290hits);
162  obj_ptr->Get(obj_F1hits);
163  obj_ptr->Get(obj_F1tts);
164 
165  f250tts.insert(f250tts.end(), obj_f250tts.begin(), obj_f250tts.end());
166  f250pulses.insert(f250pulses.end(), obj_f250pulses.begin(), obj_f250pulses.end());
167  f250pis.insert(f250pis.end(), obj_f250pis.begin(), obj_f250pis.end());
168  f250wrds.insert(f250wrds.end(), obj_f250wrds.begin(), obj_f250wrds.end());
169  f125tts.insert(f125tts.end(), obj_f125tts.begin(), obj_f125tts.end());
170  f125pis.insert(f125pis.end(), obj_f125pis.begin(), obj_f125pis.end());
171  f125cdcpulses.insert(f125cdcpulses.end(), obj_f125cdcpulses.begin(), obj_f125cdcpulses.end());
172  f125fdcpulses.insert(f125fdcpulses.end(), obj_f125fdcpulses.begin(), obj_f125fdcpulses.end());
173  f125wrds.insert(f125wrds.end(), obj_f125wrds.begin(), obj_f125wrds.end());
174  dirctts.insert(dirctts.end(), obj_dirctts.begin(), obj_dirctts.end());
175  dirctdchits.insert(dirctdchits.end(), obj_dirctdchits.begin(), obj_dirctdchits.end());
176  caen1290hits.insert(caen1290hits.end(), obj_caen1290hits.begin(), obj_caen1290hits.end());
177  F1hits.insert(F1hits.end(), obj_F1hits.begin(), obj_F1hits.end());
178  F1tts.insert(F1tts.end(), obj_F1tts.begin(), obj_F1tts.end());
179  }
180  }
181  }
182 
183  // Get the DL3Trigger object for the event. We go to some trouble
184  // here not to activate the factory ourselves and only check if the
185  // object already exists. This is because we may have skipped creating
186  // the object due to this being an unbiased event.
187  const DL3Trigger *l3trigger = NULL;
188  JFactory_base *fac = loop->GetFactory("DL3Trigger");
189  if(fac){
190  int nobjs = fac->GetNrows(false, true); // don't create objects if not already existing
191  if(nobjs>0){
192  loop->GetSingle(l3trigger, "", false); // don't throw exception if nobjs>1
193  }
194  }
195 
196  // If there are any EPICS values then asume this is an EPICS event
197  // with no CODA data. In this case, write the EPICS banks and then
198  // return before writing the Physics Bank
199  if( !epicsValues.empty() ){
200  buff.clear();
201  WriteEPICSData(buff, epicsValues);
202  return;
203  }
204 
205  // Get list of rocids with hits
206  set<uint32_t> rocids;
207  rocids.insert(1); // This *may* be from TS (don't know). There is such a id in run 2391
208  for(uint32_t i=0; i<f250pulses.size(); i++) rocids.insert( f250pulses[i]->rocid );
209  for(uint32_t i=0; i<f250pis.size(); i++) rocids.insert( f250pis[i]->rocid );
210  for(uint32_t i=0; i<f250wrds.size(); i++) rocids.insert( f250wrds[i]->rocid );
211  for(uint32_t i=0; i<f125pis.size(); i++) rocids.insert( f125pis[i]->rocid );
212  for(uint32_t i=0; i<f125cdcpulses.size();i++) rocids.insert( f125cdcpulses[i]->rocid);
213  for(uint32_t i=0; i<f125fdcpulses.size();i++) rocids.insert( f125fdcpulses[i]->rocid);
214  for(uint32_t i=0; i<f125wrds.size(); i++) rocids.insert( f125wrds[i]->rocid );
215  for(uint32_t i=0; i<dirctdchits.size(); i++) rocids.insert( dirctdchits[i]->rocid );
216  for(uint32_t i=0; i<caen1290hits.size(); i++) rocids.insert( caen1290hits[i]->rocid );
217  for(uint32_t i=0; i<F1hits.size(); i++) rocids.insert( F1hits[i]->rocid );
218 
219  // If COMPACT is true, filter coda_rocinfos to only have rocids with hits
220  if(COMPACT){
221  vector<const DCODAROCInfo*> my_coda_rocinfos;
222  for(uint32_t i=0; i<coda_rocinfos.size(); i++){
223  const DCODAROCInfo *rocinfo = coda_rocinfos[i];
224  if(rocids.find(coda_rocinfos[i]->rocid)!=rocids.end()){
225  my_coda_rocinfos.push_back(rocinfo);
226  }
227  }
228 
229  // Replace coda_rocinfos with filtered list
230  coda_rocinfos = my_coda_rocinfos;
231  }
232 
233  unsigned int Nevents = loop->GetNevents();
234 
235  // Physics Bank Header
236  buff.clear();
237  buff.push_back(0); // Physics Event Length (must be updated at the end)
238  buff.push_back(0xFF701001);// 0xFF70=SEB in single event mode, 0x10=bank of banks, 0x01=1event
239 
240  // Write Built Trigger Bank
241  WriteBuiltTriggerBank(buff, loop, coda_rocinfos, coda_events);
242 
243  // Write EventTag
244  WriteEventTagData(buff, loop->GetJEvent().GetStatus(), l3trigger);
245 
246  // Write CAEN1290TDC hits
247  WriteCAEN1290Data(buff, caen1290hits, caen1290configs, Nevents);
248 
249  // Write F1TDC hits
250  WriteF1Data(buff, F1hits, F1tts, F1configs, Nevents);
251 
252 
253  // Write f250 hits
254  // For now, output with the same data format as we got in
255  if(f250pis.size() > 0)
256  Writef250Data(buff, f250pis, f250tts, f250wrds, f250scalers, Nevents);
257  if(f250pulses.size() > 0)
258  Writef250Data(buff, f250pulses, f250tts, f250wrds, f250scalers, Nevents);
259 
260  // Write f125 hits
261  Writef125Data(buff, f125pis, f125cdcpulses, f125fdcpulses, f125tts, f125wrds, f125configs, Nevents);
262 
263  // Write DIRC SSP hits
264  WriteDircData(buff, dirctdchits, dirctts, Nevents);
265 
266  // Write out extra TS data if it exists ("sync event")
267  if(l1_info.size() > 0) {
268  WriteTSSyncData(loop, buff, l1_info[0]);
269  }
270 
271  // save any extra objects
272  for(vector<const JObject *>::iterator obj_itr = objects_to_save.begin();
273  obj_itr != objects_to_save.end(); obj_itr++) {
274  const JObject *obj_ptr = *obj_itr;
275 
276  // first, see if these are low-level hit objects
277  if(auto *vertex_ptr = dynamic_cast<const DVertex *>(obj_ptr)) {
278  WriteDVertexData(loop, buff, vertex_ptr);
279  }
280  if(auto *vertex_ptr = dynamic_cast<const DEventRFBunch *>(obj_ptr)) {
281  WriteDEventRFBunchData(loop, buff, vertex_ptr);
282  }
283  }
284 
285  // Update global header length
286  if(!buff.empty()) buff[0] = buff.size()-1;
287 }
288 
289 
290 //------------------
291 // WriteBuiltTriggerBank
292 //------------------
293 void DEVIOBufferWriter::WriteBuiltTriggerBank(vector<uint32_t> &buff,
294  JEventLoop *loop,
295  vector<const DCODAROCInfo*> &coda_rocinfos,
296  vector<const DCODAEventInfo*> &coda_events) const
297 {
298  // Built Trigger Bank
299  uint32_t built_trigger_bank_len_idx = buff.size();
300  buff.push_back(0); // Length
301  buff.push_back(0xFF232000 + coda_rocinfos.size()); // 0xFF23=Trigger Bank Tag, 0x20=segment
302 
303  //--- Common Data Segments ---
304  // uint64_t segments for Event Number, avg. timestamp, Run Number, and Run Type
305  uint32_t run_number = loop->GetJEvent().GetRunNumber();
306  uint32_t run_type = 1; // observed in run 2931. Not sure shat it should be
307  uint64_t event_number = loop->GetJEvent().GetEventNumber();
308  uint64_t avg_timestamp = time(NULL);
309  if(!coda_events.empty()){
310  run_number = coda_events[0]->run_number;
311  run_type = coda_events[0]->run_type;
312  event_number = coda_events[0]->event_number;
313  avg_timestamp = coda_events[0]->avg_timestamp;
314  }
315 
316  buff.push_back(0xD30A0006); // 0xD3=EB id (D3 stands for hallD level 3), 0x0A=64bit segment, 0006=length of segment (in 32bit words!)
317  buff.push_back(event_number & 0xFFFFFFFF); // low 32 bits of event number
318  buff.push_back(event_number>>32); // high 32 bits of event number
319  buff.push_back(avg_timestamp & 0xFFFFFFFF); // low 32 bits of avg. timestamp
320  buff.push_back(avg_timestamp>>32); // high 32 bits of avg. timestamp
321  buff.push_back(run_type);
322  buff.push_back(run_number); // this is swapped from what one would expect (see JEventSource_EVIO::FindRunNumber()) - sdobbs (3/13/2016)
323 
324  // uint16_t segment for Event Types
325  uint16_t event_type = 1; // observed in run 2931. Not sure what it should be
326  if(!coda_events.empty()){
327  event_type = coda_events[0]->event_type;
328  }
329  buff.push_back(0xD3850001); // 0xD3=EB id (D3 stands for hallD level 3), 0x85=16bit segment(8 is for padding), 0001=length of segment
330  buff.push_back((uint32_t)event_type);
331 
332  //--- ROC Data ---
333  // uint32_t segments for ROC timestamp and misc. data
334  for(uint32_t i=0; i<coda_rocinfos.size(); i++){
335  const DCODAROCInfo *rocinfo = coda_rocinfos[i];
336 
337  // Write ROC data for one roc
338  uint32_t len = 2 + rocinfo->misc.size(); // 2 = 2 words for 64bit timestamp
339  buff.push_back( (rocinfo->rocid<<24) + 0x00010000 + len); // 0x01=32bit segment
340  buff.push_back(rocinfo->timestamp & 0xFFFFFFFF); // low 32 bits of timestamp
341  buff.push_back(rocinfo->timestamp>>32); // high 32 bits of timestamp
342  if(!rocinfo->misc.empty()){
343  buff.insert(buff.end(), rocinfo->misc.begin(), rocinfo->misc.end()); // add all misc words
344  }
345  }
346 
347  // Update Built trigger bank length
348  buff[built_trigger_bank_len_idx] = buff.size() - built_trigger_bank_len_idx - 1;
349 }
350 
351 //------------------
352 // WriteCAEN1290Data
353 //------------------
354 void DEVIOBufferWriter::WriteCAEN1290Data(vector<uint32_t> &buff,
355  vector<const DCAEN1290TDCHit*> &caen1290hits,
356  vector<const DCAEN1290TDCConfig*> &caen1290configs,
357  unsigned int Nevents) const
358 {
359  // Create lists of F1 hit objects indexed by rocid,slot
360  // At same time, make map of module types (32channel or 48 channel)
361  map<uint32_t, map<uint32_t, vector<const DCAEN1290TDCHit*> > > modules; // outer map index is rocid, inner map index is slot
362  map<uint32_t, set<const DCAEN1290TDCConfig*> > configs;
363  for(uint32_t i=0; i<caen1290hits.size(); i++){
364  const DCAEN1290TDCHit *hit = caen1290hits[i];
365  if(write_out_all_rocs || (rocs_to_write_out.find(hit->rocid) != rocs_to_write_out.end()) ) {
366  modules[hit->rocid][hit->slot].push_back(hit);
367  }
368  }
369 
370  // Copy config pointers into map indexed by rocid
371  for(uint32_t i=0; i<caen1290configs.size(); i++){
372  const DCAEN1290TDCConfig *config = caen1290configs[i];
373  configs[config->rocid].insert(config);
374  }
375 
376  // Loop over rocids
377  map<uint32_t, map<uint32_t, vector<const DCAEN1290TDCHit*> > >::iterator it;
378  for(it=modules.begin(); it!=modules.end(); it++){
379  uint32_t rocid = it->first;
380 
381  // Write Physics Event's Data Bank Header for this rocid
382  uint32_t data_bank_idx = buff.size();
383  buff.push_back(0); // Total bank length (will be overwritten later)
384  buff.push_back( (rocid<<16) + 0x1001 ); // 0x10=bank of banks, 0x01=1 event
385 
386  // Write Config Bank
387  set<const DCAEN1290TDCConfig*> &confs = configs[rocid];
388  if(!confs.empty()){
389 
390  uint32_t config_bank_idx = buff.size();
391  buff.push_back(0); // Total bank length (will be overwritten later)
392  buff.push_back( 0x00550101 ); // 0x55=config bank, 0x01=uint32_t bank, 0x01=1 event
393 
394  set<const DCAEN1290TDCConfig*>::iterator it_conf;
395  for(it_conf=confs.begin(); it_conf!=confs.end(); it_conf++){
396  const DCAEN1290TDCConfig *conf = *it_conf;
397 
398  uint32_t header_idx = buff.size();
399  buff.push_back(0); // Nvals and slot mask (will be filled below)
400  uint32_t Nvals = 0; // keep count of how many params we write
401  if(conf->WINWIDTH != 0xFFFF) {buff.push_back( (kPARAMCAEN1290_WINWIDTH <<16) + conf->WINWIDTH ); Nvals++;}
402  if(conf->WINOFFSET != 0xFFFF) {buff.push_back( (kPARAMCAEN1290_WINOFFSET <<16) + conf->WINOFFSET ); Nvals++;}
403 
404  buff[header_idx] = (Nvals<<24) + conf->slot_mask;
405  }
406 
407  // Update Config Bank length
408  buff[config_bank_idx] = buff.size() - config_bank_idx - 1;
409  }
410 
411  // Write Data Block Bank Header
412  uint32_t data_block_bank_idx = buff.size();
413  buff.push_back(0); // Total bank length (will be overwritten later)
414  buff.push_back( 0x00140101 ); // 0x00=status w/ little endian, 0x14=CAEN1290TDC, 0x01=uint32_t bank, 0x01=1 event
415 
416  // Loop over slots
417  map<uint32_t, vector<const DCAEN1290TDCHit*> >::iterator it2;
418  for(it2=it->second.begin(); it2!=it->second.end(); it2++){
419  uint32_t slot = it2->first;
420 
421  // Write global header
422  uint32_t global_header_idx = buff.size();
423  buff.push_back( 0x40000100 + (0x01<<5) + slot ); // Global Header 0x04=global header, 0x01<<5=event count
424 
425  // Write module data
426  vector<const DCAEN1290TDCHit*> &hits = it2->second;
427  uint32_t last_id = 0x0;
428  for(uint32_t i=0; i<hits.size(); i++){
429  const DCAEN1290TDCHit *hit = hits[i];
430 
431  // Check if we need to write a new TDC header
432  uint32_t id = (hit->tdc_num<<24) + (hit->event_id<<12) + (hit->bunch_id);
433  if(id != last_id){
434  // Write event header
435  buff.push_back( 0x08000000 + id ); // TDC Header
436  last_id = id;
437  }
438 
439  // Write Hit
440  buff.push_back( (hit->edge<<26) + (hit->channel<<21) + (hit->time&0x1fffff) );
441  }
442 
443  // Write module block trailer
444  uint32_t Nwords_in_block = buff.size()-global_header_idx+1;
445  buff.push_back( 0x80000000 + (Nwords_in_block<<5) + (slot) );
446  }
447 
448  // Update Data Block Bank length
449  buff[data_block_bank_idx] = buff.size() - data_block_bank_idx - 1;
450 
451  // Update Physics Event's Data Bank length
452  buff[data_bank_idx] = buff.size() - data_bank_idx - 1;
453  }
454 }
455 
456 //------------------
457 // WriteF1Data
458 //------------------
459 void DEVIOBufferWriter::WriteF1Data(vector<uint32_t> &buff,
460  vector<const DF1TDCHit*> &F1hits,
461  vector<const DF1TDCTriggerTime*> &F1tts,
462  vector<const DF1TDCConfig*> &F1configs,
463  unsigned int Nevents) const
464 {
465  // Create lists of F1 hit objects indexed by rocid,slot
466  // At same time, make map of module types (32channel or 48 channel)
467  map<uint32_t, map<uint32_t, vector<const DF1TDCHit*> > > modules; // outer map index is rocid, inner map index is slot
468  map<uint32_t, map<uint32_t, MODULE_TYPE> > mod_types;
469  for(uint32_t i=0; i<F1hits.size(); i++){
470  const DF1TDCHit *hit = F1hits[i];
471  if(write_out_all_rocs || (rocs_to_write_out.find(hit->rocid) != rocs_to_write_out.end()) ) {
472  modules[hit->rocid][hit->slot].push_back(hit);
473  mod_types[hit->rocid][hit->slot] = hit->modtype;
474  }
475  }
476 
477  // Copy F1 config pointers into map indexed by rocid
478  map<uint32_t, set<const DF1TDCConfig*> > configs;
479  for(uint32_t i=0; i<F1configs.size(); i++){
480  const DF1TDCConfig *config = F1configs[i];
481  configs[config->rocid].insert(config);
482  }
483 
484  // Loop over rocids
485  map<uint32_t, map<uint32_t, vector<const DF1TDCHit*> > >::iterator it;
486  for(it=modules.begin(); it!=modules.end(); it++){
487  uint32_t rocid = it->first;
488 
489  // Write Physics Event's Data Bank Header for this rocid
490  uint32_t data_bank_idx = buff.size();
491  buff.push_back(0); // Total bank length (will be overwritten later)
492  buff.push_back( (rocid<<16) + 0x1001 ); // 0x10=bank of banks, 0x01=1 event
493 
494  // Write Config Bank
495  set<const DF1TDCConfig*> &confs = configs[rocid];
496  if(!confs.empty()){
497 
498  uint32_t config_bank_idx = buff.size();
499  buff.push_back(0); // Total bank length (will be overwritten later)
500  buff.push_back( 0x00550101 ); // 0x55=config bank, 0x01=uint32_t bank, 0x01=1 event
501 
502  set<const DF1TDCConfig*>::iterator it_conf;
503  for(it_conf=confs.begin(); it_conf!=confs.end(); it_conf++){
504  const DF1TDCConfig *conf = *it_conf;
505 
506  uint32_t header_idx = buff.size();
507  buff.push_back(0); // Nvals and slot mask (will be filled below)
508  uint32_t Nvals = 0; // keep count of how many params we write
509  if(conf->REFCNT != 0xFFFF) {buff.push_back( (kPARAMF1_REFCNT <<16) + conf->REFCNT ); Nvals++;}
510  if(conf->TRIGWIN != 0xFFFF) {buff.push_back( (kPARAMF1_TRIGWIN <<16) + conf->TRIGWIN ); Nvals++;}
511  if(conf->TRIGLAT != 0xFFFF) {buff.push_back( (kPARAMF1_TRIGLAT <<16) + conf->TRIGLAT ); Nvals++;}
512  if(conf->HSDIV != 0xFFFF) {buff.push_back( (kPARAMF1_HSDIV <<16) + conf->HSDIV ); Nvals++;}
513  if(conf->BINSIZE != 0xFFFF) {buff.push_back( (kPARAMF1_BINSIZE <<16) + conf->BINSIZE ); Nvals++;}
514  if(conf->REFCLKDIV != 0xFFFF) {buff.push_back( (kPARAMF1_REFCLKDIV <<16) + conf->REFCLKDIV ); Nvals++;}
515 
516  buff[header_idx] = (Nvals<<24) + conf->slot_mask;
517  }
518 
519  // Update Config Bank length
520  buff[config_bank_idx] = buff.size() - config_bank_idx - 1;
521  }
522 
523  // Write Data Block Bank Header
524  // In principle, we could write one of these for each module, but
525  // we write all modules into the same data block bank to save space.
526  // n.b. the documentation mentions Single Event Mode (SEM) and that
527  // the values in the header and even the first couple of words depend
528  // on whether it is in that mode. It appears this mode is an alternative
529  // to having a Built Trigger Bank. Our data all seems to have been taken
530  // *not* in SEM. Empirically, it looks like the data also doesn't have
531  // the initial "Starting Event Number" though the documentation does not
532  // declare that as optional. We omit it here as well.
533  uint32_t data_block_bank_idx = buff.size();
534  buff.push_back(0); // Total bank length (will be overwritten later)
535  buff.push_back( 0x001A0101 ); // 0x00=status w/ little endian, 0x1A=F1TDC, 0x01=uint32_t bank, 0x01=1 event
536 
537  // Loop over slots
538  map<uint32_t, vector<const DF1TDCHit*> >::iterator it2;
539  for(it2=it->second.begin(); it2!=it->second.end(); it2++){
540  uint32_t slot = it2->first;
541  MODULE_TYPE modtype = mod_types[rocid][slot];
542 
543  // Find Trigger Time object
544  const DF1TDCTriggerTime *tt = NULL;
545  for(uint32_t i=0; i<F1tts.size(); i++){
546  if( (F1tts[i]->rocid==rocid) && (F1tts[i]->slot==slot) ){
547  tt = F1tts[i];
548  break;
549  }
550  }
551 
552  // Set itrigger number and trigger time
553  uint32_t itrigger = (tt==NULL) ? (Nevents&0x3FFFFF):tt->DDAQAddress::itrigger;
554  uint64_t trig_time = (tt==NULL) ? time(NULL):tt->time;
555 
556  // Write module block and event headers
557  uint32_t block_header_idx = buff.size();
558  buff.push_back( 0x80000101 + (modtype<<18) + (slot<<22) ); // Block Header 0x80=data defining, modtype=F1TDC, 0x01=event block number,0x01=number of events in block
559  buff.push_back( 0x90000000 + (slot<<22) + itrigger); // Event Header
560 
561  // Write Trigger Time
562  buff.push_back(0x98000000 + ((trig_time>>0 )&0x00FFFFFF));
563  buff.push_back(0x00000000 + ((trig_time>>24)&0x00FFFFFF));
564 
565  // Write module data
566  vector<const DF1TDCHit*> &hits = it2->second;
567  for(uint32_t i=0; i<hits.size(); i++){
568 
569  // NOTE: We write out the chip header word here (data type 8)
570  // even though it contains mostly redundant information with the time
571  // measurement words written below. The primary exception is the
572  // 9bit "F1 Chip Trigger Time" value stored in the trig_time member
573  // of the DF1TDCHit object. This is not useful in the analysis other than
574  // to verify that separate chips on the module are in sync. To do this
575  // compactly, we would need to sort the list of hits by chip number as
576  // well so that we wrote one chip header for hits on that chip. That would
577  // make this more complicated and probably slower. Given
578  // that the original data contains lots of chip header words, even for
579  // chips with no hits, writing a header word per chip will still be more
580  // compact pretty much all of the time (unless there is really high occupancy
581  // in ALL F1TDC modules!)
582  // It may be worth noting that including this chip header does increase the
583  // output file size by about 3.5% for run 2931. We may want to consider
584  // only writing it when COMPACT=0 at some point since, as noted, it is not
585  // used anywhere in the reconstruction.
586  uint32_t data_word = hits[i]->data_word;
587  uint32_t chip_header = 0xC0000000;
588  chip_header += (data_word&0x07000000); // Resolution status, overflow statuses
589  chip_header += (hits[i]->trig_time<<7)&0x01FF; // 9bit trigger time
590  chip_header += (data_word>>16)&0x3F; // chip number and channel on chip
591  buff.push_back( chip_header );
592 
593  // Write Hit
594  buff.push_back( data_word ); // original data word for F1 is conveniently recorded!
595  }
596 
597  // Write module block trailer
598  uint32_t Nwords_in_block = buff.size()-block_header_idx+1;
599  buff.push_back( 0x88000000 + (slot<<22) + Nwords_in_block );
600  }
601 
602  // Update Data Block Bank length
603  buff[data_block_bank_idx] = buff.size() - data_block_bank_idx - 1;
604 
605  // Update Physics Event's Data Bank length
606  buff[data_bank_idx] = buff.size() - data_bank_idx - 1;
607  }
608 }
609 
610 //------------------
611 // Writef250Data
612 // old data format (pre-Fall 2016)
613 //------------------
614 void DEVIOBufferWriter::Writef250Data(vector<uint32_t> &buff,
615  vector<const Df250PulseIntegral*> &f250pis,
616  vector<const Df250TriggerTime*> &f250tts,
617  vector<const Df250WindowRawData*> &f250wrds, vector<const Df250Scaler*> &f250scalers,
618  unsigned int Nevents ) const
619 {
620  // Create lists of Pulse Integral objects indexed by rocid,slot
621  // At same time, make list of config objects to write
622  map<uint32_t, map<uint32_t, vector<const Df250PulseIntegral*> > > modules; // outer map index is rocid, inner map index is slot
623  map<uint32_t, set<const Df250Config*> > configs;
624  for(uint32_t i=0; i<f250pis.size(); i++){
625  const Df250PulseIntegral *pi = f250pis[i];
626  if(write_out_all_rocs || (rocs_to_write_out.find(pi->rocid) != rocs_to_write_out.end()) ) {
627  modules[pi->rocid][pi->slot].push_back(pi);
628 
629  const Df250Config *config = NULL;
630  pi->GetSingle(config);
631  if(config) configs[pi->rocid].insert(config);
632  }
633  }
634 
635 
636 
637 
638  // Make sure entries exist for all Df250WindowRawData objects as well
639  // so when we loop over rocid,slot below we can write those out under
640  // the appropriate block header.
641  for(uint32_t i=0; i<f250wrds.size(); i++) modules[f250wrds[i]->rocid][f250wrds[i]->slot];
642 
643  // Loop over rocids
644  map<uint32_t, map<uint32_t, vector<const Df250PulseIntegral*> > >::iterator it;
645  for(it=modules.begin(); it!=modules.end(); it++){
646  uint32_t rocid = it->first;
647 
648  // Write Physics Event's Data Bank Header for this rocid
649  uint32_t data_bank_idx = buff.size();
650  buff.push_back(0); // Total bank length (will be overwritten later)
651  buff.push_back( (rocid<<16) + 0x1001 ); // 0x10=bank of banks, 0x01=1 event
652 
653  // Write Config Bank
654  set<const Df250Config*> &confs = configs[rocid];
655  if(!confs.empty()){
656 
657  uint32_t config_bank_idx = buff.size();
658  buff.push_back(0); // Total bank length (will be overwritten later)
659  buff.push_back( 0x00550101 ); // 0x55=config bank, 0x01=uint32_t bank, 0x01=1 event
660 
661  set<const Df250Config*>::iterator it_conf;
662  for(it_conf=confs.begin(); it_conf!=confs.end(); it_conf++){
663  const Df250Config *conf = *it_conf;
664 
665  uint32_t header_idx = buff.size();
666  buff.push_back(0); // Nvals and slot mask (will be filled below)
667  uint32_t Nvals = 0; // keep count of how many params we write
668  if(conf->NSA != 0xFFFF) {buff.push_back( (kPARAM250_NSA <<16) + conf->NSA ); Nvals++;}
669  if(conf->NSB != 0xFFFF) {buff.push_back( (kPARAM250_NSB <<16) + conf->NSB ); Nvals++;}
670  if(conf->NSA_NSB != 0xFFFF) {buff.push_back( (kPARAM250_NSA_NSB<<16) + conf->NSA_NSB); Nvals++;}
671  if(conf->NPED != 0xFFFF) {buff.push_back( (kPARAM250_NPED <<16) + conf->NPED ); Nvals++;}
672 
673  buff[header_idx] = (Nvals<<24) + conf->slot_mask;
674  }
675 
676  // Update Config Bank length
677  buff[config_bank_idx] = buff.size() - config_bank_idx - 1;
678  }
679 
680 
681  // Write Data Block Bank Header
682  // In principle, we could write one of these for each module, but
683  // we write all modules into the same data block bank to save space.
684  // n.b. the documentation mentions Single Event Mode (SEM) and that
685  // the values in the header and even the first couple of words depend
686  // on whether it is in that mode. It appears this mode is an alternative
687  // to having a Built Trigger Bank. Our data all seems to have been taken
688  // *not* in SEM. Empirically, it looks like the data also doesn't have
689  // the initial "Starting Event Number" though the documentation does not
690  // declare that as optional. We omit it here as well.
691  uint32_t data_block_bank_idx = buff.size();
692  buff.push_back(0); // Total bank length (will be overwritten later)
693  buff.push_back(0x00060101); // 0x00=status w/ little endian, 0x06=f250, 0x01=uint32_t bank, 0x01=1 event
694 
695  // Loop over slots
696  map<uint32_t, vector<const Df250PulseIntegral*> >::iterator it2;
697  for(it2=it->second.begin(); it2!=it->second.end(); it2++){
698  uint32_t slot = it2->first;
699 
700  // Find Trigger Time object
701  const Df250TriggerTime *tt = NULL;
702  for(uint32_t i=0; i<f250tts.size(); i++){
703  if( (f250tts[i]->rocid==rocid) && (f250tts[i]->slot==slot) ){
704  tt = f250tts[i];
705  break;
706  }
707  }
708 
709  // Should we print a warning if no Trigger Time object found?
710 
711  // Set itrigger number and trigger time
712  uint32_t itrigger = (tt==NULL) ? (Nevents&0x3FFFFF):tt->itrigger;
713  uint64_t trig_time = (tt==NULL) ? time(NULL):tt->time;
714 
715  // Write module block and event headers
716  uint32_t block_header_idx = buff.size();
717  buff.push_back( 0x80040101 + (slot<<22) ); // Block Header 0x80=data defining, 0x04=FADC250, 0x01=event block number,0x01=number of events in block
718  buff.push_back( 0x90000000 + (slot<<22) + itrigger); // Event Header
719 
720  // Write Trigger Time
721  buff.push_back(0x98000000 + ((trig_time>>0 )&0x00FFFFFF));
722  buff.push_back(0x00000000 + ((trig_time>>24)&0x00FFFFFF));
723 
724  // Write module data
725  vector<const Df250PulseIntegral*> &pis = it2->second;
726  for(uint32_t i=0; i<pis.size(); i++){
727  const Df250PulseIntegral *pi = pis[i];
728  const Df250PulseTime *pt = NULL;
729  const Df250PulsePedestal *pp = NULL;
730  pi->GetSingle(pt);
731  pi->GetSingle(pp);
732 
733  // Pulse Integral
734  if(pi->emulated == PREFER_EMULATED){
735  buff.push_back(0xB8000000 + (pi->channel<<23) + (pi->pulse_number<<21) + (pi->quality_factor<<19) + (pi->integral&0x7FFFF) );
736  }
737 
738  // Pulse Time
739  if(pt && (pt->emulated == PREFER_EMULATED) ){
740  buff.push_back(0xC0000000 + (pt->channel<<23) + (pt->pulse_number<<21) + (pt->quality_factor<<19) + (pt->time&0x7FFFF) );
741  }
742 
743  // Pulse Pedestal
744  if(pp && (pp->emulated == PREFER_EMULATED) ){
745  buff.push_back(0xD0000000 + (pp->channel<<23) + (pp->pulse_number<<21) + (pp->pedestal<<12) + (pp->pulse_peak&0x0FFF) );
746  }
747  }
748 
749  // Write Window Raw Data
750  // This is not the most efficient, but is needed to get these under
751  // the correct block header.
752  if(!PREFER_EMULATED){
753  for(uint32_t i=0; i<f250wrds.size(); i++){
754  const Df250WindowRawData *wrd = f250wrds[i];
755  if(wrd->rocid!=rocid || wrd->slot!=slot) continue;
756 
757  // IMPORTANT: At this time, the individual "not valid" bits for
758  // the samples is not preserved in the Df250WindowRawData class.
759  // We set them here only to indicate if the last sample is not
760  // valid due to there being an odd number of samples.
761  buff.push_back(0xA0000000 + (wrd->channel<<23) + (wrd->samples.size()) );
762  for(uint32_t j=0; j<(wrd->samples.size()+1)/2; j++){
763  uint32_t idx1 = 2*j;
764  uint32_t idx2 = idx1 + 1;
765  uint32_t sample_1 = wrd->samples[idx1];
766  uint32_t sample_2 = idx2<wrd->samples.size() ? wrd->samples[idx2]:0;
767  uint32_t invalid1 = 0;
768  uint32_t invalid2 = idx2>=wrd->samples.size();
769  buff.push_back( (invalid1<<29) + (sample_1<<16) + (invalid2<<13) + (sample_2<<0) );
770  }
771  }
772  }
773 
774  // Write module block trailer
775  uint32_t Nwords_in_block = buff.size()-block_header_idx+1;
776  buff.push_back( 0x88000000 + (slot<<22) + Nwords_in_block );
777  }
778 
779  // Update Data Block Bank length
780  buff[data_block_bank_idx] = buff.size() - data_block_bank_idx - 1;
781 
782 
783  // A.S. Write FADC scalers
784  if(f250scalers.size() > 0) {
785 
786  for(unsigned int ii = 0; ii < f250scalers.size(); ii++){
787 
788  const Df250Scaler *scaler = f250scalers[ii];
789 
790  unsigned int sc_crate = scaler->crate;
791 
792  if(sc_crate == rocid){
793 
794  uint32_t scaler_block_bank_idx = buff.size();
795  buff.push_back(0); // Total bank length (will be overwritten later)
796  buff.push_back(0xEE100101); // 0xEE01 = Scaler Bank Tag, 0x01=u32int
797 
798  // Save header information
799  buff.push_back(scaler->nsync);
800  buff.push_back(scaler->trig_number);
801  buff.push_back(scaler->version);
802 
803  if(scaler->fa250_sc.size() > 0){
804  for(unsigned int sc_ch = 0; sc_ch < scaler->fa250_sc.size(); sc_ch++)
805  buff.push_back(scaler->fa250_sc[sc_ch]);
806  }
807 
808  // Update Scaler Bank length
809  buff[scaler_block_bank_idx] = buff.size() - scaler_block_bank_idx - 1;
810 
811  }
812  }
813  } // FADC scalers exist
814 
815 
816  // Update Physics Event's Data Bank length
817  buff[data_bank_idx] = buff.size() - data_bank_idx - 1;
818 
819  } // Pulse Integral Data
820 
821 
822 
823  // A.S. Write fadc scalers for sync events for crates, which have no hits (Pulse Integral)
824 
825  if(f250scalers.size() > 0) {
826 
827  vector <unsigned int> scaler_index;
828 
829  for(unsigned int ii = 0; ii < f250scalers.size(); ii++){
830 
831  const Df250Scaler *scaler = f250scalers[ii];
832  unsigned int sc_crate = scaler->crate;
833 
834  int crate_found = 0;
835 
836 
837  for(uint32_t jj = 0; jj < f250pis.size(); jj++){
838  const Df250PulseIntegral *pi = f250pis[jj];
839  if(write_out_all_rocs || (rocs_to_write_out.find(pi->rocid) != rocs_to_write_out.end()) ) {
840  if(pi->rocid == sc_crate){
841  crate_found = 1;
842  break;
843  }
844  }
845 
846  }
847 
848  if(crate_found == 0)
849  scaler_index.push_back(ii);
850  }
851 
852 
853  // Write scalers to the data bank
854  for(unsigned int ii = 0; ii < scaler_index.size(); ii++){
855 
856  const Df250Scaler *scaler = f250scalers[scaler_index[ii]];
857 
858 
859  // Write Physics Event's Data Bank Header for this rocid
860  uint32_t data_bank_idx = buff.size();
861  buff.push_back(0); // Total bank length (will be overwritten later)
862  buff.push_back( (scaler->crate<<16) + 0x1001 ); // 0x10=bank of banks, 0x01=1 event
863 
864 
865  uint32_t scaler_block_bank_idx = buff.size();
866  buff.push_back(0); // Total bank length (will be overwritten later)
867  buff.push_back(0xEE100101); // 0xEE01 = Scaler Bank Tag, 0x01=u32int
868 
869  // Save header information
870  buff.push_back(scaler->nsync);
871  buff.push_back(scaler->trig_number);
872  buff.push_back(scaler->version);
873 
874  if(scaler->fa250_sc.size() > 0){
875  for(unsigned int sc_ch = 0; sc_ch < scaler->fa250_sc.size(); sc_ch++)
876  buff.push_back(scaler->fa250_sc[sc_ch]);
877  }
878 
879  // Update Scaler Bank length
880  buff[scaler_block_bank_idx] = buff.size() - scaler_block_bank_idx - 1;
881 
882 
883  // Update Physics Event's Data Bank length
884  buff[data_bank_idx] = buff.size() - data_bank_idx - 1;
885 
886  }
887 
888  } // FADC scalers exist
889 
890 
891 
892 
893 
894 
895 
896 
897 }
898 
899 //------------------
900 // Writef250Data
901 // new data format (starting Fall 2016)
902 //------------------
903 void DEVIOBufferWriter::Writef250Data(vector<uint32_t> &buff,
904  vector<const Df250PulseData*> &f250pulses,
905  vector<const Df250TriggerTime*> &f250tts,
906  vector<const Df250WindowRawData*> &f250wrds, vector<const Df250Scaler*> &f250scalers,
907  unsigned int Nevents ) const
908 {
909 
910  // Create lists of Pulse Integral objects indexed by rocid,slot
911  // At same time, make list of config objects to write
912  map<uint32_t, map<uint32_t, vector<const Df250PulseData*> > > modules; // outer map index is rocid, inner map index is slot
913  map<uint32_t, set<const Df250Config*> > configs;
914  for(uint32_t i=0; i<f250pulses.size(); i++){
915  const Df250PulseData *pulse = f250pulses[i];
916  if(write_out_all_rocs || (rocs_to_write_out.find(pulse->rocid) != rocs_to_write_out.end()) ) {
917  modules[pulse->rocid][pulse->slot].push_back(pulse);
918 
919  const Df250Config *config = NULL;
920  pulse->GetSingle(config);
921  if(config) configs[pulse->rocid].insert(config);
922  }
923  }
924 
925 
926  // Make sure entries exist for all Df250WindowRawData objects as well
927  // so when we loop over rocid,slot below we can write those out under
928  // the appropriate block header.
929  for(uint32_t i=0; i<f250wrds.size(); i++) modules[f250wrds[i]->rocid][f250wrds[i]->slot];
930 
931  // Loop over rocids
932  map<uint32_t, map<uint32_t, vector<const Df250PulseData*> > >::iterator it;
933  for(it=modules.begin(); it!=modules.end(); it++){
934  uint32_t rocid = it->first;
935 
936 
937  // Write Physics Event's Data Bank Header for this rocid
938  uint32_t data_bank_idx = buff.size();
939  buff.push_back(0); // Total bank length (will be overwritten later)
940  buff.push_back( (rocid<<16) + 0x1001 ); // 0x10=bank of banks, 0x01=1 event
941 
942 
943  // Write Config Bank
944  set<const Df250Config*> &confs = configs[rocid];
945  if(!confs.empty()){
946 
947  uint32_t config_bank_idx = buff.size();
948  buff.push_back(0); // Total bank length (will be overwritten later)
949  buff.push_back( 0x00550101 ); // 0x55=config bank, 0x01=uint32_t bank, 0x01=1 event
950 
951  set<const Df250Config*>::iterator it_conf;
952  for(it_conf=confs.begin(); it_conf!=confs.end(); it_conf++){
953  const Df250Config *conf = *it_conf;
954 
955  uint32_t header_idx = buff.size();
956  buff.push_back(0); // Nvals and slot mask (will be filled below)
957  uint32_t Nvals = 0; // keep count of how many params we write
958  if(conf->NSA != 0xFFFF) {buff.push_back( (kPARAM250_NSA <<16) + conf->NSA ); Nvals++;}
959  if(conf->NSB != 0xFFFF) {buff.push_back( (kPARAM250_NSB <<16) + conf->NSB ); Nvals++;}
960  if(conf->NSA_NSB != 0xFFFF) {buff.push_back( (kPARAM250_NSA_NSB<<16) + conf->NSA_NSB); Nvals++;}
961  if(conf->NPED != 0xFFFF) {buff.push_back( (kPARAM250_NPED <<16) + conf->NPED ); Nvals++;}
962 
963  buff[header_idx] = (Nvals<<24) + conf->slot_mask;
964  }
965 
966  // Update Config Bank length
967  buff[config_bank_idx] = buff.size() - config_bank_idx - 1;
968  }
969 
970 
971  // Write Data Block Bank Header
972  // In principle, we could write one of these for each module, but
973  // we write all modules into the same data block bank to save space.
974  // n.b. the documentation mentions Single Event Mode (SEM) and that
975  // the values in the header and even the first couple of words depend
976  // on whether it is in that mode. It appears this mode is an alternative
977  // to having a Built Trigger Bank. Our data all seems to have been taken
978  // *not* in SEM. Empirically, it looks like the data also doesn't have
979  // the initial "Starting Event Number" though the documentation does not
980  // declare that as optional. We omit it here as well.
981  uint32_t data_block_bank_idx = buff.size();
982  buff.push_back(0); // Total bank length (will be overwritten later)
983  buff.push_back(0x00060101); // 0x00=status w/ little endian, 0x06=f250, 0x01=uint32_t bank, 0x01=1 event
984 
985  // Loop over slots
986  map<uint32_t, vector<const Df250PulseData*> >::iterator it2;
987  for(it2=it->second.begin(); it2!=it->second.end(); it2++){
988  uint32_t slot = it2->first;
989 
990  // Find Trigger Time object
991  const Df250TriggerTime *tt = NULL;
992  for(uint32_t i=0; i<f250tts.size(); i++){
993  if( (f250tts[i]->rocid==rocid) && (f250tts[i]->slot==slot) ){
994  tt = f250tts[i];
995  break;
996  }
997  }
998 
999  // Should we print a warning if no Trigger Time object found?
1000 
1001  // Set itrigger number and trigger time
1002  uint32_t itrigger = (tt==NULL) ? (Nevents&0x3FFFFF):tt->itrigger;
1003  uint64_t trig_time = (tt==NULL) ? time(NULL):tt->time;
1004 
1005  // Write module block and event headers
1006  uint32_t block_header_idx = buff.size();
1007  buff.push_back( 0x80040101 + (slot<<22) ); // Block Header 0x80=data defining, 0x04=FADC250, 0x01=event block number,0x01=number of events in block
1008  buff.push_back( 0x90000000 + (slot<<22) + itrigger); // Event Header
1009 
1010  // Write Trigger Time
1011  buff.push_back(0x98000000 + ((trig_time>>0 )&0x00FFFFFF));
1012  buff.push_back(0x00000000 + ((trig_time>>24)&0x00FFFFFF));
1013 
1014  // Write module data
1015  vector<const Df250PulseData*> &pulses = it2->second;
1016  for(uint32_t i=0; i<pulses.size(); i++){
1017  const Df250PulseData *pulse = pulses[i];
1018 
1019  if(pulse->emulated == PREFER_EMULATED){
1020  // Word 1: Pulse Pedestal
1021  //buff.push_back(0xC8000000 + (pulse->event_within_block<<19) + (pulse->channel<<15)
1022  // first field is the "event_within_block", which is always 1 for reformatted events
1023  buff.push_back(0xC8000000 + (0x01<<19) + (pulse->channel<<15)
1024  + (pulse->QF_pedestal<<14) + (pulse->pedestal&0x3FFF) );
1025 
1026  // Word 2: Pulse Integral
1027  buff.push_back(0x40000000 + (pulse->integral<<12) + (pulse->QF_NSA_beyond_PTW<<11) + (pulse->QF_overflow<<10)
1028  + (pulse->QF_underflow<<9) + (pulse->nsamples_over_threshold&0x1FF) );
1029 
1030  // Word 3: Pulse Time
1031  buff.push_back(0x00000000 + (pulse->course_time<<21) + (pulse->fine_time<<15) + (pulse->pulse_peak<<3)
1032  + (pulse->QF_vpeak_beyond_NSA<<2) + (pulse->QF_vpeak_not_found<<1) + (pulse->QF_bad_pedestal&0x1) );
1033  }
1034  }
1035 
1036  // Write Window Raw Data
1037  // This is not the most efficient, but is needed to get these under
1038  // the correct block header.
1039  if(!PREFER_EMULATED){
1040  for(uint32_t i=0; i<f250wrds.size(); i++){
1041  const Df250WindowRawData *wrd = f250wrds[i];
1042  if(wrd->rocid!=rocid || wrd->slot!=slot) continue;
1043 
1044  // IMPORTANT: At this time, the individual "not valid" bits for
1045  // the samples is not preserved in the Df250WindowRawData class.
1046  // We set them here only to indicate if the last sample is not
1047  // valid due to there being an odd number of samples.
1048  buff.push_back(0xA0000000 + (wrd->channel<<23) + (wrd->samples.size()) );
1049  for(uint32_t j=0; j<(wrd->samples.size()+1)/2; j++){
1050  uint32_t idx1 = 2*j;
1051  uint32_t idx2 = idx1 + 1;
1052  uint32_t sample_1 = wrd->samples[idx1];
1053  uint32_t sample_2 = idx2<wrd->samples.size() ? wrd->samples[idx2]:0;
1054  uint32_t invalid1 = 0;
1055  uint32_t invalid2 = idx2>=wrd->samples.size();
1056  buff.push_back( (invalid1<<29) + (sample_1<<16) + (invalid2<<13) + (sample_2<<0) );
1057  }
1058  }
1059  }
1060 
1061  // Write module block trailer
1062  uint32_t Nwords_in_block = buff.size()-block_header_idx+1;
1063  buff.push_back( 0x88000000 + (slot<<22) + Nwords_in_block );
1064  }
1065 
1066  // Update Data Block Bank length
1067  buff[data_block_bank_idx] = buff.size() - data_block_bank_idx - 1;
1068 
1069 
1070  // A.S. Write FADC scalers
1071  if(f250scalers.size() > 0) {
1072 
1073  for(unsigned int ii = 0; ii < f250scalers.size(); ii++){
1074 
1075  const Df250Scaler *scaler = f250scalers[ii];
1076 
1077  unsigned int sc_crate = scaler->crate;
1078 
1079  if(sc_crate == rocid){
1080 
1081 
1082  uint32_t scaler_block_bank_idx = buff.size();
1083  buff.push_back(0); // Total bank length (will be overwritten later)
1084  buff.push_back(0xEE100101); // 0xEE01 = Scaler Bank Tag, 0x01=u32int
1085 
1086  // Save header information
1087  buff.push_back(scaler->nsync);
1088  buff.push_back(scaler->trig_number);
1089  buff.push_back(scaler->version);
1090 
1091  if(scaler->fa250_sc.size() > 0){
1092  for(unsigned int sc_ch = 0; sc_ch < scaler->fa250_sc.size(); sc_ch++)
1093  buff.push_back(scaler->fa250_sc[sc_ch]);
1094  }
1095 
1096  // Update Scaler Bank length
1097  buff[scaler_block_bank_idx] = buff.size() - scaler_block_bank_idx - 1;
1098 
1099  }
1100  }
1101  } // FADC scalers exist
1102 
1103  // Update Physics Event's Data Bank length
1104  buff[data_bank_idx] = buff.size() - data_bank_idx - 1;
1105 
1106  }
1107 
1108 
1109  // A.S. Write fadc scalers for sync events for crates, which have no hits (Pulse Integral)
1110 
1111  if(f250scalers.size() > 0) {
1112 
1113  vector <unsigned int> scaler_index;
1114 
1115  for(unsigned int ii = 0; ii < f250scalers.size(); ii++){
1116 
1117  const Df250Scaler *scaler = f250scalers[ii];
1118  unsigned int sc_crate = scaler->crate;
1119 
1120 
1121  int crate_found = 0;
1122 
1123  for(uint32_t jj = 0; jj < f250pulses.size(); jj++){
1124  const Df250PulseData *pulse = f250pulses[jj];
1125  if(write_out_all_rocs || (rocs_to_write_out.find(pulse->rocid) != rocs_to_write_out.end()) ){
1126  if(pulse->rocid == sc_crate){
1127  crate_found = 1;
1128  break;
1129  }
1130  }
1131  }
1132 
1133  if(crate_found == 0){
1134  scaler_index.push_back(ii);
1135  }
1136  }
1137 
1138 
1139  // Write scalers to the data bank
1140  for(unsigned int ii = 0; ii < scaler_index.size(); ii++){
1141 
1142  const Df250Scaler *scaler = f250scalers[scaler_index[ii]];
1143 
1144 
1145  // Write Physics Event's Data Bank Header for this rocid
1146  uint32_t data_bank_idx = buff.size();
1147  buff.push_back(0); // Total bank length (will be overwritten later)
1148  buff.push_back( (scaler->crate<<16) + 0x1001 ); // 0x10=bank of banks, 0x01=1 event
1149 
1150 
1151  uint32_t scaler_block_bank_idx = buff.size();
1152  buff.push_back(0); // Total bank length (will be overwritten later)
1153  buff.push_back(0xEE100101); // 0xEE01 = Scaler Bank Tag, 0x01=u32int
1154 
1155  // Save header information
1156  buff.push_back(scaler->nsync);
1157  buff.push_back(scaler->trig_number);
1158  buff.push_back(scaler->version);
1159 
1160  if(scaler->fa250_sc.size() > 0){
1161  for(unsigned int sc_ch = 0; sc_ch < scaler->fa250_sc.size(); sc_ch++)
1162  buff.push_back(scaler->fa250_sc[sc_ch]);
1163  }
1164 
1165  // Update Scaler Bank length
1166  buff[scaler_block_bank_idx] = buff.size() - scaler_block_bank_idx - 1;
1167 
1168 
1169  // Update Physics Event's Data Bank length
1170  buff[data_bank_idx] = buff.size() - data_bank_idx - 1;
1171 
1172  }
1173 
1174  } // FADC scalers exist
1175 
1176 
1177 
1178 }
1179 
1180 //------------------
1181 // Writef125Data
1182 //------------------
1183 void DEVIOBufferWriter::Writef125Data(vector<uint32_t> &buff,
1184  vector<const Df125PulseIntegral*> &f125pis,
1185  vector<const Df125CDCPulse*> &f125cdcpulses,
1186  vector<const Df125FDCPulse*> &f125fdcpulses,
1187  vector<const Df125TriggerTime*> &f125tts,
1188  vector<const Df125WindowRawData*> &f125wrds,
1189  vector<const Df125Config*> &f125configs,
1190  unsigned int Nevents) const
1191 {
1192  // Make map of rocid,slot values that have some hit data.
1193  // Simultaneously make map for each flavor of hit indexed by rocid,slot
1194  map<uint32_t, set<uint32_t> > modules; // outer map index is rocid, inner map index is slot
1195  map<uint32_t, map<uint32_t, vector<const Df125PulseIntegral*> > > pi_hits; // outer map index is rocid, inner map index is slot
1196  map<uint32_t, map<uint32_t, vector<const Df125CDCPulse* > > > cdc_hits; // outer map index is rocid, inner map index is slot
1197  map<uint32_t, map<uint32_t, vector<const Df125FDCPulse* > > > fdc_hits; // outer map index is rocid, inner map index is slot
1198  map<uint32_t, map<uint32_t, vector<const Df125WindowRawData*> > > wrd_hits; // outer map index is rocid, inner map index is slot
1199  for(uint32_t i=0; i<f125pis.size(); i++){
1200  const Df125PulseIntegral *hit = f125pis[i];
1201  if(write_out_all_rocs || (rocs_to_write_out.find(hit->rocid) != rocs_to_write_out.end()) ) {
1202  modules[hit->rocid].insert(hit->slot);
1203  pi_hits[hit->rocid][hit->slot].push_back( hit );
1204  }
1205  }
1206  for(uint32_t i=0; i<f125cdcpulses.size(); i++){
1207  const Df125CDCPulse *hit = f125cdcpulses[i];
1208  if(write_out_all_rocs || (rocs_to_write_out.find(hit->rocid) != rocs_to_write_out.end()) ) {
1209  modules[hit->rocid].insert(hit->slot);
1210  cdc_hits[hit->rocid][hit->slot].push_back( hit );
1211  }
1212  }
1213  for(uint32_t i=0; i<f125fdcpulses.size(); i++){
1214  const Df125FDCPulse *hit = f125fdcpulses[i];
1215  if(write_out_all_rocs || (rocs_to_write_out.find(hit->rocid) != rocs_to_write_out.end()) ) {
1216  modules[hit->rocid].insert(hit->slot);
1217  fdc_hits[hit->rocid][hit->slot].push_back( hit );
1218  }
1219  }
1220  for(uint32_t i=0; i<f125wrds.size(); i++){
1221  const Df125WindowRawData *hit = f125wrds[i];
1222  if(write_out_all_rocs || (rocs_to_write_out.find(hit->rocid) != rocs_to_write_out.end()) ) {
1223  modules[hit->rocid].insert(hit->slot);
1224  wrd_hits[hit->rocid][hit->slot].push_back( hit );
1225  }
1226  }
1227 
1228  // Copy f125 config pointers into map indexed by just rocid
1229  map<uint32_t, set<const Df125Config*> > configs;
1230  for(uint32_t i=0; i<f125configs.size(); i++){
1231  const Df125Config *config = f125configs[i];
1232  configs[config->rocid].insert(config);
1233  }
1234 
1235  // Loop over rocids
1236  map<uint32_t, set<uint32_t> >::iterator it;
1237  for(it=modules.begin(); it!=modules.end(); it++){
1238  uint32_t rocid = it->first;
1239 
1240  // Write Physics Event's Data Bank Header for this rocid
1241  uint32_t data_bank_idx = buff.size();
1242  buff.push_back(0); // Total bank length (will be overwritten later)
1243  buff.push_back( (rocid<<16) + 0x1001 ); // 0x10=bank of banks, 0x01=1 event
1244 
1245  // Write Config Bank
1246  set<const Df125Config*> &confs = configs[rocid];
1247  if(!confs.empty()){
1248 
1249  uint32_t config_bank_idx = buff.size();
1250  buff.push_back(0); // Total bank length (will be overwritten later)
1251  buff.push_back( 0x00550101 ); // 0x55=config bank, 0x01=uint32_t bank, 0x01=1 event
1252 
1253  set<const Df125Config*>::iterator it_conf;
1254  for(it_conf=confs.begin(); it_conf!=confs.end(); it_conf++){
1255  const Df125Config *conf = *it_conf;
1256 
1257  uint32_t header_idx = buff.size();
1258  buff.push_back(0); // Nvals and slot mask (will be filled below)
1259  uint32_t Nvals = 0; // keep count of how many params we write
1260  if(conf->NSA != 0xFFFF) {buff.push_back( (kPARAM125_NSA <<16) + conf->NSA ); Nvals++;}
1261  if(conf->NSB != 0xFFFF) {buff.push_back( (kPARAM125_NSB <<16) + conf->NSB ); Nvals++;}
1262  if(conf->NSA_NSB != 0xFFFF) {buff.push_back( (kPARAM125_NSA_NSB <<16) + conf->NSA_NSB ); Nvals++;}
1263  if(conf->NPED != 0xFFFF) {buff.push_back( (kPARAM125_NPED <<16) + conf->NPED ); Nvals++;}
1264  if(conf->WINWIDTH!= 0xFFFF) {buff.push_back( (kPARAM125_WINWIDTH<<16) + conf->WINWIDTH); Nvals++;}
1265 
1266  // See GlueX-doc-2274
1267  if(conf->PL != 0xFFFF) {buff.push_back( (kPARAM125_PL <<16) + conf->PL ); Nvals++;}
1268  if(conf->NW != 0xFFFF) {buff.push_back( (kPARAM125_NW <<16) + conf->NW ); Nvals++;}
1269  if(conf->NPK != 0xFFFF) {buff.push_back( (kPARAM125_NPK <<16) + conf->NPK ); Nvals++;}
1270  if(conf->P1 != 0xFFFF) {buff.push_back( (kPARAM125_P1 <<16) + conf->P1 ); Nvals++;}
1271  if(conf->P2 != 0xFFFF) {buff.push_back( (kPARAM125_P2 <<16) + conf->P2 ); Nvals++;}
1272  if(conf->PG != 0xFFFF) {buff.push_back( (kPARAM125_PG <<16) + conf->PG ); Nvals++;}
1273  if(conf->IE != 0xFFFF) {buff.push_back( (kPARAM125_IE <<16) + conf->IE ); Nvals++;}
1274  if(conf->H != 0xFFFF) {buff.push_back( (kPARAM125_H <<16) + conf->H ); Nvals++;}
1275  if(conf->TH != 0xFFFF) {buff.push_back( (kPARAM125_TH <<16) + conf->TH ); Nvals++;}
1276  if(conf->TL != 0xFFFF) {buff.push_back( (kPARAM125_TL <<16) + conf->TL ); Nvals++;}
1277  if(conf->IBIT != 0xFFFF) {buff.push_back( (kPARAM125_IBIT <<16) + conf->IBIT ); Nvals++;}
1278  if(conf->ABIT != 0xFFFF) {buff.push_back( (kPARAM125_ABIT <<16) + conf->ABIT ); Nvals++;}
1279  if(conf->PBIT != 0xFFFF) {buff.push_back( (kPARAM125_PBIT <<16) + conf->PBIT ); Nvals++;}
1280 
1281  buff[header_idx] = (Nvals<<24) + conf->slot_mask;
1282  }
1283 
1284  // Update Config Bank length
1285  buff[config_bank_idx] = buff.size() - config_bank_idx - 1;
1286  }
1287 
1288  // Write Data Block Bank Header
1289  // In principle, we could write one of these for each module, but
1290  // we write all modules into the same data block bank to save space.
1291  // n.b. the documentation mentions Single Event Mode (SEM) and that
1292  // the values in the header and even the first couple of words depend
1293  // on whether it is in that mode. It appears this mode is an alternative
1294  // to having a Built Trigger Bank. Our data all seems to have been taken
1295  // *not* in SEM. Empirically, it looks like the data also doesn't have
1296  // the initial "Starting Event Number" though the documentation does not
1297  // declare that as optional. We omit it here as well.
1298  uint32_t data_block_bank_idx = buff.size();
1299  buff.push_back(0); // Total bank length (will be overwritten later)
1300  buff.push_back(0x00100101); // 0x00=status w/ little endian, 0x10=f125, 0x01=uint32_t bank, 0x01=1 event
1301 
1302  // Loop over slots
1303  set<uint32_t>::iterator it2;
1304  for(it2=it->second.begin(); it2!=it->second.end(); it2++){
1305  uint32_t slot = *it2;
1306 
1307  // Find Trigger Time object
1308  const Df125TriggerTime *tt = NULL;
1309  for(uint32_t i=0; i<f125tts.size(); i++){
1310  if( (f125tts[i]->rocid==rocid) && (f125tts[i]->slot==slot) ){
1311  tt = f125tts[i];
1312  break;
1313  }
1314  }
1315 
1316  // Should we print a warning if no Trigger Time object found?
1317 
1318  // Set itrigger number and trigger time
1319  uint32_t itrigger = (tt==NULL) ? (Nevents&0x3FFFFF):tt->DDAQAddress::itrigger;
1320  uint64_t trig_time = (tt==NULL) ? time(NULL):tt->time;
1321 
1322  // Write module block and event headers
1323  uint32_t block_header_idx = buff.size();
1324  buff.push_back( 0x80080101 + (slot<<22) ); // Block Header 0x80=data defining, 0x08=FADC125, 0x01=event block number,0x01=number of events in block
1325  buff.push_back( 0x90000000 + itrigger); // Event Header
1326 
1327  // Write Trigger Time
1328  buff.push_back(0x98000000 + ((trig_time>>0 )&0x00FFFFFF));
1329  buff.push_back(0x00000000 + ((trig_time>>24)&0x00FFFFFF));
1330 
1331  // Write Pulse Integral (+Pedestal and Time) data
1332  vector<const Df125PulseIntegral*> &pis = pi_hits[rocid][slot];
1333  for(uint32_t i=0; i<pis.size(); i++){
1334  const Df125PulseIntegral *pi = pis[i];
1335  const Df125PulseTime *pt = NULL;
1336  const Df125PulsePedestal *pp = NULL;
1337  pi->GetSingle(pt);
1338  pi->GetSingle(pp);
1339 
1340  // Pulse Integral
1341  if(pi->emulated == PREFER_EMULATED){
1342  buff.push_back(0xB8000000 + (pi->channel<<20) + (pi->integral&0x7FFFF) );
1343  }
1344 
1345  // Pulse Time
1346  if(pt && (pt->emulated == PREFER_EMULATED) ){
1347  buff.push_back(0xC0000000 + (pt->channel<<20) + (pt->pulse_number<<18) + (pt->time&0x7FFFF) );
1348  }
1349 
1350  // Pulse Pedestal
1351  if(pp && (pp->emulated == PREFER_EMULATED) ){
1352  buff.push_back(0xD0000000 + (pp->pulse_number<<21) + (pp->pedestal<<12) + (pp->pulse_peak&0x0FFF) );
1353  }
1354  }
1355 
1356  // Write CDC Pulse data
1357  vector<const Df125CDCPulse*> &cdcpulses = cdc_hits[rocid][slot];
1358  for(uint32_t i=0; i<cdcpulses.size(); i++){
1359  const Df125CDCPulse *pulse = cdcpulses[i];
1360 
1361  if(pulse->emulated == PREFER_EMULATED){
1362  buff.push_back( pulse->word1 );
1363  buff.push_back( pulse->word2 );
1364  }
1365  }
1366 
1367  // Write FDC Pulse data
1368  vector<const Df125FDCPulse*> &fdcpulses = fdc_hits[rocid][slot];
1369  for(uint32_t i=0; i<fdcpulses.size(); i++){
1370  const Df125FDCPulse *pulse = fdcpulses[i];
1371 
1372  if(pulse->emulated == PREFER_EMULATED){
1373  buff.push_back( pulse->word1 );
1374  buff.push_back( pulse->word2 );
1375  }
1376  }
1377 
1378  // Write Window Raw Data
1379  // This is not the most efficient, but is needed to get these under
1380  // the correct block header.
1381  if(!PREFER_EMULATED){
1382  vector<const Df125WindowRawData*> &wrds = wrd_hits[rocid][slot];
1383  for(uint32_t i=0; i<wrds.size(); i++){
1384  const Df125WindowRawData *wrd = wrds[i];
1385 
1386  // IMPORTANT: At this time, the individual "not valid" bits for
1387  // the samples is not preserved in the Df125WindowRawData class.
1388  // We set them here only to indicate if the last sample is not
1389  // valid due to there being an odd number of samples.
1390  buff.push_back(0xA0000000 + (wrd->channel<<20) + (wrd->channel<<15) + (wrd->samples.size()) );
1391  for(uint32_t j=0; j<(wrd->samples.size()+1)/2; j++){
1392  uint32_t idx1 = 2*j;
1393  uint32_t idx2 = idx1 + 1;
1394  uint32_t sample_1 = wrd->samples[idx1];
1395  uint32_t sample_2 = idx2<wrd->samples.size() ? wrd->samples[idx2]:0;
1396  uint32_t invalid1 = 0;
1397  uint32_t invalid2 = idx2>=wrd->samples.size();
1398  buff.push_back( (invalid1<<29) + (sample_1<<16) + (invalid2<<13) + (sample_2<<0) );
1399  }
1400  }
1401  }
1402 
1403  // Write module block trailer
1404  uint32_t Nwords_in_block = buff.size()-block_header_idx+1;
1405  buff.push_back( 0x88000000 + (slot<<22) + Nwords_in_block );
1406  }
1407 
1408  // Update Data Block Bank length
1409  buff[data_block_bank_idx] = buff.size() - data_block_bank_idx - 1;
1410 
1411  // Update Physics Event's Data Bank length
1412  buff[data_bank_idx] = buff.size() - data_bank_idx - 1;
1413  }
1414 }
1415 
1416 
1417 //------------------
1418 // WriteDircData
1419 //------------------
1420 void DEVIOBufferWriter::WriteDircData(vector<uint32_t> &buff,
1421  vector<const DDIRCTDCHit*> &dirctdchits,
1422  vector<const DDIRCTriggerTime*> &dirctts,
1423  unsigned int Nevents) const
1424 {
1425  // Create lists of Pulse Integral objects indexed by rocid,slot
1426  // At same time, make list of config objects to write
1427  map<uint32_t, map<uint32_t, map<uint32_t, vector<const DDIRCTDCHit*> > > > modules; // outer map index is rocid, middle map index is slot, inner map index is dev_id
1428  //map<uint32_t, set<const DDIRCConfig*> > configs;
1429  for(uint32_t i=0; i<dirctdchits.size(); i++){
1430  const DDIRCTDCHit *tdchit = dirctdchits[i];
1431  if(write_out_all_rocs || (rocs_to_write_out.find(tdchit->rocid) != rocs_to_write_out.end()) ) {
1432  modules[tdchit->rocid][tdchit->slot][tdchit->dev_id].push_back(tdchit);
1433 
1434  //const Df250Config *config = NULL;
1435  //tdchit->GetSingle(config);
1436  //if(config) configs[tdchit->rocid].insert(config);
1437  }
1438  }
1439 
1440  // Loop over rocids
1441  //map<uint32_t, map<uint32_t, vector<const DDIRCTDCHit*> > >::iterator it;
1442  //for(it=modules.begin(); it!=modules.end(); it++){
1443  for( auto const &it : modules ) {
1444  uint32_t rocid = it.first;
1445 
1446  // Write Physics Event's Data Bank Header for this rocid
1447  uint32_t data_bank_idx = buff.size();
1448  buff.push_back(0); // Total bank length (will be overwritten later)
1449  buff.push_back( (rocid<<16) + 0x1001 ); // 0x10=bank of banks, 0x01=1 event
1450 
1451  // Write Data Block Bank Header
1452  // In principle, we could write one of these for each module, but
1453  // we write all modules into the same data block bank to save space.
1454  // n.b. the documentation mentions Single Event Mode (SEM) and that
1455  // the values in the header and even the first couple of words depend
1456  // on whether it is in that mode. It appears this mode is an alternative
1457  // to having a Built Trigger Bank. Our data all seems to have been taken
1458  // *not* in SEM. Empirically, it looks like the data also doesn't have
1459  // the initial "Starting Event Number" though the documentation does not
1460  // declare that as optional. We omit it here as well.
1461  uint32_t data_block_bank_idx = buff.size();
1462  buff.push_back(0); // Total bank length (will be overwritten later)
1463  buff.push_back(0x00280101); // 0x00=status w/ little endian, 0x28=DIRC SSP, 0x01=uint32_t bank, 0x01=1 event
1464 
1465  // Loop over slots
1466  //map<uint32_t, vector<const DDIRCTDCHit*> >::iterator it2;
1467  //for(it2=it->second.begin(); it2!=it->second.end(); it2++){
1468  for( auto const &it2 : it.second ) {
1469  uint32_t slot = it2.first;
1470 
1471  // Find Trigger Time object
1472  const DDIRCTriggerTime *tt = NULL;
1473  for(uint32_t i=0; i<dirctts.size(); i++){
1474  if( (dirctts[i]->rocid==rocid) && (dirctts[i]->slot==slot) ){
1475  tt = dirctts[i];
1476  break;
1477  }
1478  }
1479 
1480  // Should we print a warning if no Trigger Time object found?
1481 
1482  // Set itrigger number and trigger time
1483  uint32_t itrigger = (tt==NULL) ? (Nevents&0x3FFFFF):tt->itrigger;
1484  uint64_t trig_time = (tt==NULL) ? time(NULL):tt->time;
1485 
1486  // Write module block and event headers
1487  uint32_t block_header_idx = buff.size();
1488  buff.push_back( 0x80280101 + (slot<<22) ); // Block Header 0x80=data defining, 0x28=DIRC SSP, 0x01=event block number,0x01=number of events in block
1489  buff.push_back( 0x90000000 + (slot<<22) + itrigger); // Event Header
1490 
1491  // Write Trigger Time
1492  buff.push_back(0x98000000 + ((trig_time>>0 )&0x00FFFFFF));
1493  buff.push_back(0x00000000 + ((trig_time>>24)&0x00FFFFFF));
1494 
1495  // Loop over fibers/devices
1496  for( auto const &it3 : it2.second ) {
1497  uint32_t device_id = it3.first;
1498 
1499  // Write Device ID
1500  // pick event counter from the data
1501  buff.push_back(0xB8000000 + (device_id<<22) + (it3.second[0]->ievent_cnt));
1502 
1503  // Write module data
1504  //vector<const DDIRCTDCHit*> &tdchits = it2->second;
1505  //for(uint32_t i=0; i<tdchits.size(); i++){
1506  for( auto const tdchit : it3.second ) {
1507  //const DDIRCTDCHit *tdchit = tdchits[i];
1508 
1509  // SSP TDC Hit
1510  buff.push_back(0xC0000000 + (tdchit->edge<<26) + (tdchit->channel_fpga<<16) + (tdchit->time));
1511  }
1512  }
1513 
1514  // Write module block trailer
1515  uint32_t Nwords_in_block = buff.size()-block_header_idx+1;
1516  buff.push_back( 0x88000000 + (slot<<22) + Nwords_in_block );
1517  }
1518 
1519  // Update Data Block Bank length
1520  buff[data_block_bank_idx] = buff.size() - data_block_bank_idx - 1;
1521 
1522  // Update Physics Event's Data Bank length
1523  buff[data_bank_idx] = buff.size() - data_bank_idx - 1;
1524  }
1525 
1526 }
1527 
1528 
1529 //------------------
1530 // WriteEPICSData
1531 //------------------
1532 void DEVIOBufferWriter::WriteEPICSData(vector<uint32_t> &buff,
1533  vector<const DEPICSvalue*> epicsValues) const
1534 {
1535  // Store the EPICS event in EVIO as a bank of SEGMENTs
1536  // The first segment is a 32-bit unsigned int for the current
1537  // time. This is followed by additional SEGMENTs that are
1538  // 8-bit unsigned integer types, one for each variable being
1539  // written. All variables are written as strings in the form:
1540  //
1541  // varname=value
1542  //
1543  // where "varname" is the EPICS variable name and "value" its
1544  // value in string form. If there are multiple elements for
1545  // the PV, then value will be a comma separated list. The
1546  // contents of "value" are set in GetEPICSvalue() while
1547  // the "varname=value" string is formed here.
1548 
1549  // If no values to write then return now
1550  if(epicsValues.size() == 0) return;
1551 
1552  // Outermost EVIO header is a bank of segments.
1553  uint32_t epics_bank_idx = buff.size();
1554  buff.push_back(0); // Total bank length (will be overwritten later)
1555  buff.push_back( (0x60<<16) + (0xD<<8) + (0x1<<0) );
1556 
1557  // Time word (unsigned 32bit SEGMENT)
1558  buff.push_back( (0x61<<24) + (0x1<<16) + (1<<0) );
1559  buff.push_back( (uint32_t)epicsValues[0]->timestamp );
1560 
1561  // Loop over PVs, writing each as a SEGMENT to the buffer
1562  for(uint32_t i=0; i<epicsValues.size(); i++){
1563  const DEPICSvalue *epicsval = epicsValues[i];
1564  const string &str = epicsval->nameval;
1565  uint32_t Nbytes = str.size()+1; // +1 is for terminating 0
1566  uint32_t Nwords = (Nbytes+3)/4; // bytes needed for padding
1567  uint32_t Npad = (Nwords*4) - Nbytes;
1568 
1569  buff.push_back( (0x62<<24) + (Npad<<22) + (0x7<<16) + (Nwords<<0) ); // 8bit unsigned char segment
1570 
1571  // Increase buffer enough to hold this string
1572  uint32_t buff_str_idx = buff.size();
1573  buff.resize( buff_str_idx + Nwords );
1574 
1575  unsigned char *ichar = (unsigned char*)&buff[buff_str_idx];
1576  for(unsigned int j=0; j<Nbytes; j++) ichar[j] = str[j]; // copy entire string including terminating 0
1577  }
1578 
1579  // Update EPICS Bank length
1580  buff[epics_bank_idx] = buff.size() - epics_bank_idx - 1;
1581 }
1582 
1583 //------------------
1584 // WriteEventTagData
1585 //------------------
1586 void DEVIOBufferWriter::WriteEventTagData(vector<uint32_t> &buff,
1587  uint64_t event_status,
1588  const DL3Trigger* l3trigger) const
1589 {
1590  // Here we purposefully write the DEventTag data into a bank
1591  // based only on data extracted from other data objects, but
1592  // NOT the DEventTag object. This is so whenever an event is
1593  // written, it is guaranteed to have event tag data based on
1594  // current information as opposed to data passed in from a
1595  // previously run algorithm.
1596  uint32_t eventtag_bank_idx = buff.size();
1597 
1598  uint64_t L3_status = 0;
1599  uint32_t L3_decision = 0;
1600  uint32_t L3_algorithm = 0;
1601  if(l3trigger){
1602  L3_status = l3trigger->status;
1603  L3_decision = l3trigger->L3_decision;
1604  L3_algorithm = l3trigger->algorithm;
1605  }
1606 
1607  // Set L3 pass/fail status in event_status word to be written
1608  // (this is redundant with the L3_decision word written below
1609  // but makes the bits in the status word valid and costs nothing)
1610  switch(L3_decision){
1611  case DL3Trigger::kKEEP_EVENT : event_status |= kSTATUS_L3PASS; break;
1612  case DL3Trigger::kDISCARD_EVENT: event_status |= kSTATUS_L3FAIL; break;
1613  case DL3Trigger::kNO_DECISION : break;
1614  }
1615 
1616  // Length and Header words
1617  // This must fit the format of ROC data so we add a bank of banks
1618  // header with rocid=0xF56
1619  buff.push_back(0); // Total bank length (will be overwritten later)
1620  buff.push_back( 0x0F561001 ); // rocid=0xF56
1621  buff.push_back(0); // Bank length (will be overwritten later)
1622  buff.push_back( 0x00560101 ); // 0x56=event tag bank, 0x01=uint32_t bank, 0x01=1 event
1623 
1624  // event_status
1625  buff.push_back( (event_status>> 0)&0xFFFFFFFF ); // low order word
1626  buff.push_back( (event_status>>32)&0xFFFFFFFF ); // high order word
1627 
1628  // L3_status
1629  buff.push_back( (L3_status>> 0)&0xFFFFFFFF ); // low order word
1630  buff.push_back( (L3_status>>32)&0xFFFFFFFF ); // high order word
1631 
1632  // L3_decision
1633  buff.push_back( L3_decision );
1634 
1635  // L3_algorithm
1636  buff.push_back( L3_algorithm );
1637 
1638  // Update event tag Bank lengths
1639  buff[eventtag_bank_idx] = buff.size() - eventtag_bank_idx - 1;
1640  buff[eventtag_bank_idx+2] = buff[eventtag_bank_idx] - 2;
1641 }
1642 
1643 
1644 //------------------
1645 // WriteBORSingle
1646 //------------------
1647 template<typename T, typename M, typename F>
1648 void DEVIOBufferWriter::WriteBORSingle(vector<uint32_t> &buff, M m, F&& modFunc) const
1649 {
1650  /// Write BOR config objects for all crates containing
1651  /// a single module type. This is called from WriteBORData
1652  /// below.
1653 
1654  // This templated function saves duplicating this code for all
1655  // 4 BORconfig data types. It is complicated slightly by the
1656  // fact that the F1TDC comes in 2 types and so the last argument
1657  // must be a lambda function in order to set the module type
1658  // based on a value in object "c" in the innermost loop.
1659  // It is also a bit tricky since the DXXXBORConfig data types
1660  // use multiple inheritance with one type being the actual
1661  // data structure from bor_roc.h. This is really only needed
1662  // for the data structure length so we make it the first
1663  // template parameter so that it can be specified using the
1664  // template syntax when calling this.
1665 
1666  for(auto p : m){
1667  uint32_t rocid = p.first;
1668  uint32_t crate_idx = buff.size();
1669  buff.push_back(0); // crate bank length (will be overwritten later)
1670  buff.push_back( (0x71<<16) + (0x0C<<8) + (rocid<<0) ); // 0x71=crate config, 0x0c=tag segment, num=rocid
1671 
1672  for(auto c : p.second){
1673  uint32_t slot = c->slot;
1674  uint32_t modtype = modFunc(c);
1675  uint32_t tag = (slot<<5) + (modtype);
1676  uint32_t Nwords = sizeof(T)/sizeof(uint32_t);
1677  buff.push_back( (tag<<20) + (0x01<<16) + (Nwords)); // 0x1=uint32
1678  uint32_t *d = (uint32_t*)&c->rocid;
1679  for(uint32_t j=0; j<Nwords; j++) buff.push_back(*d++);
1680  }
1681 
1682  buff[crate_idx] = buff.size() - crate_idx - 1;
1683  }
1684 }
1685 
1686 
1687 //------------------
1688 // WriteBORData
1689 //------------------
1690 void DEVIOBufferWriter::WriteBORData(JEventLoop *loop, vector<uint32_t> &buff) const
1691 {
1692  // Write the BOR data into EVIO format.
1693 
1694  vector<const Df250BORConfig*> vDf250BORConfig;
1695  vector<const Df125BORConfig*> vDf125BORConfig;
1696  vector<const DF1TDCBORConfig*> vDF1TDCBORConfig;
1697  vector<const DCAEN1290TDCBORConfig*> vDCAEN1290TDCBORConfig;
1698 
1699  loop->Get(vDf250BORConfig);
1700  loop->Get(vDf125BORConfig);
1701  loop->Get(vDF1TDCBORConfig);
1702  loop->Get(vDCAEN1290TDCBORConfig);
1703 
1704  uint32_t Nconfig_objs = vDf250BORConfig.size() + vDf125BORConfig.size() + vDF1TDCBORConfig.size() + vDCAEN1290TDCBORConfig.size();
1705  if(Nconfig_objs == 0) return;
1706 
1707  // Sort config. objects by rocid into containers
1708  map<uint32_t, decltype(vDf250BORConfig)> mDf250BORConfig;
1709  map<uint32_t, decltype(vDf125BORConfig)> mDf125BORConfig;
1710  map<uint32_t, decltype(vDF1TDCBORConfig)> mDF1TDCBORConfig;
1711  map<uint32_t, decltype(vDCAEN1290TDCBORConfig)> mDCAEN1290TDCBORConfig;
1712  for(auto c : vDf250BORConfig) mDf250BORConfig[c->rocid].push_back(c);
1713  for(auto c : vDf125BORConfig) mDf125BORConfig[c->rocid].push_back(c);
1714  for(auto c : vDF1TDCBORConfig) mDF1TDCBORConfig[c->rocid].push_back(c);
1715  for(auto c : vDCAEN1290TDCBORConfig) mDCAEN1290TDCBORConfig[c->rocid].push_back(c);
1716 
1717  // Outermost EVIO header for BOR event
1718  uint32_t bor_bank_idx = buff.size();
1719  buff.push_back(0); // Total bank length (will be overwritten later)
1720  buff.push_back( (0x70<<16) + (0x0E<<8) + (0x1<<0) ); // 0x70=BOR event 0x0E=bank of banks 0x1=num
1721 
1722  // Write all config objects for each BOR data type
1723  // using the templated function above.
1724  WriteBORSingle<f250config>(buff, mDf250BORConfig, [](const Df250BORConfig *c){return DModuleType::FADC250;});
1725  WriteBORSingle<f125config>(buff, mDf125BORConfig, [](const Df125BORConfig *c){return DModuleType::FADC125;});
1726  WriteBORSingle<F1TDCconfig>(buff, mDF1TDCBORConfig, [](const DF1TDCBORConfig *c){return c->nchips==8 ? 0x3:0x4;});
1727  WriteBORSingle<caen1190config>(buff, mDCAEN1290TDCBORConfig, [](const DCAEN1290TDCBORConfig *c){return DModuleType::CAEN1290;});
1728 
1729  // Update BOR Bank length
1730  buff[bor_bank_idx] = buff.size() - bor_bank_idx - 1;
1731 }
1732 
1733 
1734 
1735 //------------------
1736 // WriteTSSyncData
1737 //------------------
1738 void DEVIOBufferWriter::WriteTSSyncData(JEventLoop *loop, vector<uint32_t> &buff, const DL1Info *l1info) const
1739 {
1740  // The Trigger Supervisor (TS) inserts information into the data stream
1741  // during periodic "sync events". The data is stored in one bank
1742  // so we build it here
1743 
1744  // TS data block bank
1745  uint32_t data_bank_len_idx = buff.size();
1746  buff.push_back(0); // will be updated later
1747  buff.push_back(0x00011001); // Data bank header: 0001=TS rocid , 10=Bank of Banks, 01=1 event
1748 
1749  // TS data bank
1750  uint32_t trigger_bank_len_idx = buff.size();
1751  buff.push_back(0); // Length
1752  buff.push_back(0xEE020100); // 0xEE02=TS Bank Tag, 0x01=u32int
1753 
1754  // Save header information
1755  buff.push_back(l1info->nsync);
1756  buff.push_back(l1info->trig_number);
1757  buff.push_back(l1info->live_time);
1758  buff.push_back(l1info->busy_time);
1759  buff.push_back(l1info->live_inst);
1760  buff.push_back(l1info->unix_time);
1761 
1762  // save GTP scalars
1763  for(uint32_t i=0; i<l1info->gtp_sc.size(); i++)
1764  buff.push_back(l1info->gtp_sc[i]);
1765 
1766  // save FP scalars
1767  for(uint32_t i=0; i<l1info->fp_sc.size(); i++)
1768  buff.push_back(l1info->fp_sc[i]);
1769 
1770  // Save GTP rates
1771  for(uint32_t i=0; i<l1info->gtp_rate.size(); i++)
1772  buff.push_back(l1info->gtp_rate[i]);
1773 
1774  // save FP rates
1775  for(uint32_t i=0; i<l1info->fp_rate.size(); i++)
1776  buff.push_back(l1info->fp_rate[i]);
1777 
1778  // Update bank length
1779  buff[trigger_bank_len_idx] = buff.size() - trigger_bank_len_idx - 1;
1780  buff[data_bank_len_idx] = buff.size() - data_bank_len_idx - 1;
1781 
1782 }
1783 
1784 //------------------
1785 // WriteDVertexData
1786 //------------------
1787 void DEVIOBufferWriter::WriteDVertexData(JEventLoop *loop, vector<uint32_t> &buff, const DVertex *vertex) const
1788 {
1789  // Physics Event's Data Bank
1790  uint32_t data_bank_len_idx = buff.size();
1791  buff.push_back(0); // will be updated later
1792  buff.push_back(0x00011001); // Data bank header: 0001=TS rocid , 10=Bank of Banks, 01=1 event
1793  // Use TS rocid for event-level data
1794 
1795  // DVertex data block bank
1796  uint32_t vertex_bank_len_idx = buff.size();
1797  buff.push_back(0); // Length
1798  buff.push_back(0x1D010100); // 0x1D01=DVertexTag, 0x01=u32int
1799 
1800 
1801  // Save 4-vector information - assume doubles are stored in 64-bits
1802  // This is usually a good assumption, but is not 100% portable...
1803  // We use memcpy to convert between doubles and integers, since
1804  // we only need the integers for the bit representations, and this avoids
1805  // a nest of nasty casting...
1806  uint64_t vertex_x_out, vertex_y_out, vertex_z_out, vertex_t_out;
1807  double vertex_x = vertex->dSpacetimeVertex.X();
1808  double vertex_y = vertex->dSpacetimeVertex.Y();
1809  double vertex_z = vertex->dSpacetimeVertex.Z();
1810  double vertex_t = vertex->dSpacetimeVertex.T();
1811  memcpy(&vertex_x_out, &vertex_x, sizeof(double));
1812  buff.push_back( (vertex_x_out>> 0)&0xFFFFFFFF ); // low order word
1813  buff.push_back( (vertex_x_out>>32)&0xFFFFFFFF ); // high order word
1814  memcpy(&vertex_y_out, &vertex_y, sizeof(double));
1815  buff.push_back( (vertex_y_out>> 0)&0xFFFFFFFF ); // low order word
1816  buff.push_back( (vertex_y_out>>32)&0xFFFFFFFF ); // high order word
1817  memcpy(&vertex_z_out, &vertex_z, sizeof(double));
1818  buff.push_back( (vertex_z_out>> 0)&0xFFFFFFFF ); // low order word
1819  buff.push_back( (vertex_z_out>>32)&0xFFFFFFFF ); // high order word
1820  memcpy(&vertex_t_out, &vertex_t, sizeof(double));
1821  buff.push_back( (vertex_t_out>> 0)&0xFFFFFFFF ); // low order word
1822  buff.push_back( (vertex_t_out>>32)&0xFFFFFFFF ); // high order word
1823 
1824  // Save other information
1825  buff.push_back( vertex->dKinFitNDF );
1826  uint64_t vertex_chi_sq_out;
1827  double vertex_chi_sq = vertex->dKinFitChiSq;
1828  memcpy(&vertex_chi_sq_out, &vertex_chi_sq, sizeof(double));
1829  buff.push_back( (vertex_chi_sq_out>>32)&0xFFFFFFFF ); // high order word
1830  buff.push_back( (vertex_chi_sq_out>> 0)&0xFFFFFFFF ); // low order word
1831 
1832  // Update bank length
1833  buff[vertex_bank_len_idx] = buff.size() - vertex_bank_len_idx - 1;
1834  buff[data_bank_len_idx] = buff.size() - data_bank_len_idx - 1;
1835 
1836 }
1837 
1838 
1839 //------------------
1840 // WriteDEventRFBunchData
1841 //------------------
1842 void DEVIOBufferWriter::WriteDEventRFBunchData(JEventLoop *loop, vector<uint32_t> &buff, const DEventRFBunch *rftime) const
1843 {
1844  // Physics Event's Data Bank
1845  uint32_t data_bank_len_idx = buff.size();
1846  buff.push_back(0); // will be updated later
1847  buff.push_back(0x00011001); // Data bank header: 0001=TS rocid , 10=Bank of Banks, 01=1 event
1848  // Use TS rocid for event-level data
1849 
1850  // DRFTime data block bank
1851  uint32_t rftime_bank_len_idx = buff.size();
1852  buff.push_back(0); // Length
1853  buff.push_back(0x1D020100); // 0x1D02=DRFTimeTag, 0x01=u32int
1854 
1855 
1856  // Save 4-vector information - assume doubles are stored in 64-bits
1857  // This is usually a good assumption, but is not 100% portable...
1858  // We use memcpy to convert between doubles and integers, since
1859  // we only need the integers for the bit representations, and this avoids
1860  // a nest of nasty casting...
1861  uint64_t time_out, time_var_out;
1862  double time = rftime->dTime;
1863  double time_var = rftime->dTimeVariance;
1864  buff.push_back( rftime->dTimeSource );
1865  buff.push_back( rftime->dNumParticleVotes );
1866  memcpy(&time_out, &time, sizeof(double));
1867  buff.push_back( (time_out>> 0)&0xFFFFFFFF ); // low order word
1868  buff.push_back( (time_out>>32)&0xFFFFFFFF ); // high order word
1869  memcpy(&time_var_out, &time_var, sizeof(double));
1870  buff.push_back( (time_var_out>> 0)&0xFFFFFFFF ); // low order word
1871  buff.push_back( (time_var_out>>32)&0xFFFFFFFF ); // high order word
1872 
1873  // Update bank length
1874  buff[rftime_bank_len_idx] = buff.size() - rftime_bank_len_idx - 1;
1875  buff[data_bank_len_idx] = buff.size() - data_bank_len_idx - 1;
1876 
1877 }
uint32_t live_inst
Definition: DL1Info.h:24
#define F(x, y, z)
void Writef250Data(vector< uint32_t > &buff, vector< const Df250PulseData * > &f250pulses, vector< const Df250TriggerTime * > &f250tts, vector< const Df250WindowRawData * > &f250wrds, vector< const Df250Scaler * > &f250scalers, unsigned int Nevents) const
uint16_t NSB
Definition: Df250Config.h:22
set< uint32_t > rocs_to_write_out
uint16_t NPED
Definition: Df250Config.h:24
uint32_t version
Definition: Df250Scaler.h:16
void WriteDVertexData(JEventLoop *loop, vector< uint32_t > &buff, const DVertex *vertex) const
uint32_t fine_time
uint32_t dev_id
device id
Definition: DDIRCTDCHit.h:24
uint16_t NSA_NSB
Definition: Df125Config.h:29
char str[256]
uint64_t timestamp
Definition: DCODAROCInfo.h:22
void WriteDEventRFBunchData(JEventLoop *loop, vector< uint32_t > &buff, const DEventRFBunch *rftime) const
uint16_t IBIT
Definition: Df125Config.h:44
uint16_t NSA
Definition: Df250Config.h:21
uint32_t pulse_number
from Pulse Pedestal Data word
unsigned int dKinFitNDF
Definition: DVertex.h:31
bool emulated
true if made from Window Raw Data
uint32_t pulse_peak
from Pulse Pedestal Data word
vector< uint32_t > fp_sc
Definition: DL1Info.h:28
#define c
uint16_t NPED
Definition: Df125Config.h:30
vector< uint32_t > fa250_sc
Definition: Df250Scaler.h:20
bool emulated
true if made from Window Raw Data
uint32_t nsync
Definition: Df250Scaler.h:14
uint32_t quality_factor
from Pulse Integral Data word
uint32_t pulse_number
from Pulse Time Data word
uint16_t PBIT
Definition: Df125Config.h:46
uint16_t IE
Definition: Df125Config.h:40
uint16_t TRIGWIN
Definition: DF1TDCConfig.h:22
uint16_t ABIT
Definition: Df125Config.h:45
uint32_t rocid
Definition: DCODAROCInfo.h:21
vector< uint16_t > samples
void WriteEventTagData(vector< uint32_t > &buff, uint64_t event_status, const DL3Trigger *l3trigger) const
uint32_t pulse_peak
from Pulse Pedestal Data word
uint32_t word2
second word
Definition: Df125FDCPulse.h:75
uint32_t slot_mask
Definition: DDAQConfig.h:32
void WriteDircData(vector< uint32_t > &buff, vector< const DDIRCTDCHit * > &dirctdchits, vector< const DDIRCTriggerTime * > &dirctts, unsigned int Nevents) const
string nameval
Definition: DEPICSvalue.h:63
bool emulated
true if made from Window Raw Data
uint16_t P2
Definition: Df125Config.h:38
void WriteTSSyncData(JEventLoop *loop, vector< uint32_t > &buff, const DL1Info *l1info) const
bool emulated
true if made from Window Raw Data
uint16_t TRIGLAT
Definition: DF1TDCConfig.h:23
bool emulated
true if made from Window Raw Data
uint16_t P1
Definition: Df125Config.h:37
uint32_t pulse_number
from Pulse Time Data word
uint32_t integral
uint32_t nsync
Definition: DL1Info.h:20
uint32_t pedestal
uint32_t time
from Pulse Time Data word
vector< uint16_t > samples
uint64_t status
Definition: DL3Trigger.h:78
uint16_t WINWIDTH
Definition: Df125Config.h:31
uint32_t word1
first word
Definition: Df125FDCPulse.h:74
uint16_t BINSIZE
Definition: DF1TDCConfig.h:25
uint16_t HSDIV
Definition: DF1TDCConfig.h:24
uint32_t pulse_number
from Pulse Pedestal Data word
uint32_t quality_factor
from Pulse Time Data word
uint32_t trig_number
Definition: Df250Scaler.h:15
uint32_t nsamples_over_threshold
bool emulated
true if made from Window Raw Data
uint32_t pulse_number
from Pulse Integral Data word
uint32_t pedestal
from Pulse Pedestal Data word
DLorentzVector dSpacetimeVertex
Definition: DVertex.h:28
double dTimeVariance
Definition: DEventRFBunch.h:31
bool emulated
true if emulated values are copied to the main input
Definition: Df125FDCPulse.h:78
MODULE_TYPE modtype
Definition: DF1TDCHit.h:35
void WriteBORData(JEventLoop *loop, vector< uint32_t > &buff) const
uint32_t time
from Pulse Time Data word
uint32_t unix_time
Definition: DL1Info.h:25
uint16_t NW
Definition: Df125Config.h:35
uint32_t algorithm
Definition: DL3Trigger.h:79
bool emulated
true if made from Window Raw Data
uint32_t integral
from Pulse Integral Data word
uint32_t busy_time
Definition: DL1Info.h:23
void WriteBuiltTriggerBank(vector< uint32_t > &buff, JEventLoop *loop, vector< const DCODAROCInfo * > &coda_rocinfos, vector< const DCODAEventInfo * > &coda_events) const
vector< uint32_t > gtp_sc
Definition: DL1Info.h:27
double Nevents
uint16_t PG
Definition: Df125Config.h:39
uint32_t integral
from Pulse Integral Data word
uint16_t NSA
Definition: Df125Config.h:27
uint32_t channel
Definition: DDAQAddress.h:34
uint32_t pulse_peak
uint16_t TL
Definition: Df125Config.h:43
uint16_t REFCLKDIV
Definition: DF1TDCConfig.h:26
uint16_t NSA_NSB
Definition: Df250Config.h:23
uint32_t live_time
Definition: DL1Info.h:22
DetectorSystem_t dTimeSource
Definition: DEventRFBunch.h:28
uint16_t TH
Definition: Df125Config.h:42
uint32_t rocid
Definition: DDAQAddress.h:32
void WriteEventToBuffer(JEventLoop *loop, vector< uint32_t > &buff, vector< const JObject * > objects_to_save) const
L3_decision_t L3_decision
Definition: DL3Trigger.h:77
uint32_t course_time
double dKinFitChiSq
Definition: DVertex.h:32
uint32_t pedestal
from Pulse Pedestal Data word
void WriteF1Data(vector< uint32_t > &buff, vector< const DF1TDCHit * > &F1hits, vector< const DF1TDCTriggerTime * > &F1tts, vector< const DF1TDCConfig * > &F1configs, unsigned int Nevents) const
uint32_t trig_number
Definition: DL1Info.h:21
vector< uint32_t > misc
Definition: DCODAROCInfo.h:23
unsigned int dNumParticleVotes
Definition: DEventRFBunch.h:32
vector< uint32_t > fp_rate
Definition: DL1Info.h:30
uint32_t word2
second word
Definition: Df125CDCPulse.h:70
bool emulated
true if emulated values are copied to the main input
Definition: Df125CDCPulse.h:73
uint32_t itrigger
Definition: DDAQAddress.h:35
void Writef125Data(vector< uint32_t > &buff, vector< const Df125PulseIntegral * > &f125pis, vector< const Df125CDCPulse * > &f125cdcpulses, vector< const Df125FDCPulse * > &f125fdcpulses, vector< const Df125TriggerTime * > &f125tts, vector< const Df125WindowRawData * > &f125wrds, vector< const Df125Config * > &f125configs, unsigned int Nevents) const
uint32_t rocid
Definition: DDAQConfig.h:31
void WriteBORSingle(vector< uint32_t > &buff, M m, F &&modFunc) const
uint16_t REFCNT
Definition: DF1TDCConfig.h:21
uint16_t H
Definition: Df125Config.h:41
vector< uint32_t > gtp_rate
Definition: DL1Info.h:29
uint16_t PL
Definition: Df125Config.h:34
void WriteCAEN1290Data(vector< uint32_t > &buff, vector< const DCAEN1290TDCHit * > &caen1290hits, vector< const DCAEN1290TDCConfig * > &caen1290configs, unsigned int Nevents) const
uint16_t NPK
Definition: Df125Config.h:36
void WriteEPICSData(vector< uint32_t > &buff, vector< const DEPICSvalue * > epicsValues) const
uint32_t word1
first word
Definition: Df125CDCPulse.h:69
A DEPICSvalue object holds information for a single EPICS value read from the data stream...
Definition: DEPICSvalue.h:37
uint32_t slot
Definition: DDAQAddress.h:33
uint16_t NSB
Definition: Df125Config.h:28