DAQSimulator.cpp
Go to the documentation of this file.
1 /*
2  * File: DAQSimulator.cpp
3  * Author: denis
4  *
5  * Created on January 31, 2012, 4:56 PM
6  */
7 #ifdef NOVACMAKE
17 #else
18 #include "MockDataDAQ/DAQSimulator.h"
19 #include "MockDataDAQ/DCMSimulator.h"
20 #include "MockDataDAQ/BufferNodeSimulator.h"
21 #include "MockDataDAQ/GlobalTriggerSimulator.h"
22 #include "MockDataDAQ/DataLoggerSimulator.h"
23 #include "MockDataDAQ/Configuration.h"
24 #include "MockDataDAQ/Sorter.h"
25 #include "MockDataDAQ/NanoSliceOrder.h"
26 #include "MockDataDAQ/GlobalEventTime.h"
27 #endif
28 
29 #include "DAQDataFormats/RawMilliSlice.h"
30 #include "DAQDataFormats/RawTrigger.h"
31 #include "DAQDataFormats/RawDataBlock.h"
32 
33 #include "RawData/RawDigit.h"
35 
36 
37 // ART includes
39 
40 
41 #include <utility>
42 #include <algorithm>
43 
44 namespace mcdatadaq{
45 
46 //------------------------------------------------------------------------------
48  fGlobalTrigger(0),
49  fDataLoggerSimulator(0)
50 {
51  print();
52 }
53 
54 //------------------------------------------------------------------------------
56 
57  /// Delete DCM simulators
58  for(uint32_t idiblock = 0; idiblock < fDCMs.size() ; idiblock++)
59  for(uint32_t idcm = 0 ; idcm < fDCMs[idiblock].size(); idcm++)
60  delete fDCMs[idiblock][idcm];
61 
62  /// Delete BufferNode simulators
63  for(uint32_t ibn = 0; ibn < fBufferNodes.size(); ibn++)
64  delete fBufferNodes[ibn];
65 
66  /// Delete Global Trigger simulator
67  if(fGlobalTrigger) delete fGlobalTrigger;
68 
69  /// Delete DataLogger simulator
71 }
72 
73 //------------------------------------------------------------------------------
75 
78  const int detector_id = config->getDetector();
79  const uint32_t number_ofdiblocks_in_detector = cmap->Map()->getTotalNumberOfDiblocks();
80 
81  /// Construct DCM simulators
82  for(daqchannelmap::diblock_t idiblock = 1; idiblock <= number_ofdiblocks_in_detector; idiblock++){
83 
84  std::vector<DCMSimulator*> dcms_in_diblock_vector;
85 
86  // Encode a DChan to for the purpose of getting diblock type (DCM, FEB, and pixel are arbitrary for this.)
87  daqchannelmap::dchan dchan = cmap->Map()->encodeDChan(detector_id,idiblock,1,1,1);
88  const daqchannelmap::DiBlock_TYPE diblock_type = cmap->Map()->getDiBlockType(dchan);
89  const uint32_t number_of_dcms_in_diblock = cmap->Map()->getNumberOfDCM(diblock_type);
90 
91  for(daqchannelmap::dcm_id_t idcm = 1; idcm <= number_of_dcms_in_diblock; idcm++){
92  DCMSimulator* dcmsim = new DCMSimulator(idiblock, idcm);
93  dcms_in_diblock_vector.push_back(dcmsim);
94  }// end of loop over diblocks
95 
96  fDCMs.push_back(dcms_in_diblock_vector);
97  }// end of loop over DCMs
98 
99  /// Construct Buffer Nodes
100  for(uint32_t ibn = 1; ibn <= config->getNumberOfBufferNodes(); ibn++){
101  fBufferNodes.push_back(new BufferNodeSimulator(ibn));
102  }// ned of constructing Buffer Nodes
103 
104  /// Construct Global Trigger
106 
107  /// Construct Data Logger
109 
110 
111 
112 
113  return true;
114 }// end of DAQSimulator::init
115 
116 //------------------------------------------------------------------------------
117 bool DAQSimulator::processEvent(const std::vector<rawdata::RawDigit>& digits){
118 
120 
121  std::cout<<"Producing Microslices\n";
122  /// Produce MicroSlices in DCMs
123  fillMicroSlices(digits);
124  std::cout<<"End of Producing Microslices\n";
125 
126  /// If we are producing just MicroSlices, don't need to simulate anything else
127  if(!config->isProducingJustMicroSlices()) {
128 
129  /// Produce MilliSlices in DCMs
130  std::cout<<"Producing MilliSlices\n";
131  std::vector<daqdataformats::RawMilliSlice*> all_millislices_in_event;
132  fillMilliSlices(all_millislices_in_event);
133 
134  /// Produce a Trigger in Global Trigger
135  std::cout<<"Producing Trigger\n";
137 
138 
139  std::cout<<"Producing DataBlocks!!!!!!!!!!!!!\n";
140  /// get DataBlocks from BufferNodes
141  std::vector<daqdataformats::RawDataBlock*> all_datablocks;
142  fillDataBlocks(all_millislices_in_event, trigger, all_datablocks);
143 
144  std::cout<<"Producing Events!!!!!!!!!!!!!!!!!!!!!!!!!\n";
145  /// fill Event and Run in DataLogger
146  fillEventAndRun(all_datablocks, trigger);
147  }// end of checking whether we just need to produce MicroSlices
148 
149  /// Now we are ready to advance to the next event
150  nextEvent();
151 
152  return true;
153 }
154 
155 
156 //------------------------------------------------------------------------------
157 bool DAQSimulator::fillEventAndRun(const std::vector<daqdataformats::RawDataBlock*>& all_datablocks,
158  daqdataformats::RawTrigger* trigger){
159  fDataLoggerSimulator->produceEvent(all_datablocks, trigger);
160  return true;
161 }
162 
163 
164 //------------------------------------------------------------------------------
165 bool DAQSimulator::fillDataBlocks(const std::vector<daqdataformats::RawMilliSlice*>& input_millislices,
166  daqdataformats::RawTrigger* input_trigger,
167  std::vector<daqdataformats::RawDataBlock*>& output_datablocks){
168 
169  /// If no Millislices, nothing to do
170  if(input_millislices.size() == 0)return true;
171 
172  /// Send all MilliSlices from all DCMs to a destination BufferNode
173 
174  /// Empty vector of MilliSlices
175  const std::vector<daqdataformats::RawMilliSlice*> empty_vector_of_millislices;
176 
177  const std::vector<daqdataformats::RawMilliSlice*>* pointer_to_the_right_vector;
178 
179  /// Figure out destination buffer node from the first MilliSlice
180  const uint32_t destination_buffer_node = input_millislices[0]->getDestBuffID();
181 
182  /// Loop over Buffer Nodes and construct DataBlocks
183  for(uint32_t ibn = 0; ibn < fBufferNodes.size(); ++ibn){
184 
185  const uint32_t current_bn_id = fBufferNodes[ibn]->getBufferNodeID();
186 
187  if(current_bn_id == destination_buffer_node) pointer_to_the_right_vector = &input_millislices;
188  else pointer_to_the_right_vector = &empty_vector_of_millislices;
189 
190  daqdataformats::RawDataBlock* datablock = fBufferNodes[ibn]->getDataBlock(*pointer_to_the_right_vector, input_trigger);
191 
192  output_datablocks.push_back(datablock);
193  }// end of loop over Buffer Nodes
194 
195  return true;
196 }
197 
198 
199 
200 //------------------------------------------------------------------------------
201 bool DAQSimulator::fillMilliSlices(std::vector<daqdataformats::RawMilliSlice*>& all_millislices_in_event){
202 
203  for(daqchannelmap::diblock_t idiblock = 1; idiblock <= fDCMs.size(); idiblock++)
204  for(daqchannelmap::dcm_id_t idcm = 1; idcm <= fDCMs[idiblock-1].size(); idcm++){
205  DCMSimulator* dcm_simulator = getDCMSimulator(idiblock, idcm);
206 
207  daqdataformats::RawMilliSlice* millislice = dcm_simulator->fillMilliSlice();
208  all_millislices_in_event.push_back(millislice);
209 
210  /// Write out the MilliSlices for the event
211  dcm_simulator->writeMilliSlices();
212  }
213 
214  return true;
215 }
216 
217 //------------------------------------------------------------------------------
218 bool DAQSimulator::fillMicroSlices(const std::vector<rawdata::RawDigit>& digits){
219 
221  const daqdataformats::version_t nanoslice_version = config->getNanoSliceVersion();
222 
223  nanoslice_order_t nanoslice_order_vector;
224  getNanoSliceOrder(digits, nanoslice_order_vector);
225 
226  //print(digits, nanoslice_order_vector);
227 
229  // Filling NanoSlices
230  for(uint32_t idigit = 0 ; idigit < nanoslice_order_vector.size(); ++idigit){
231 
232  const uint32_t index = nanoslice_order_vector[idigit];
233  const rawdata::RawDigit* rd = &(digits[index]); //! Get Raw digit
234 
235  const daqchannelmap::lchan channel = rd->Channel();
236  const daqchannelmap::dchan daqchannel = cmap->Map()->encodeDChan(channel);
237 
238  const daqchannelmap::diblock_t diblock = cmap->Map()->getDiBlock(daqchannel);
239  const daqchannelmap::dcm_id_t dcm = cmap->Map()->getDCM(daqchannel);
240 
241  const feb_timestamp timestamp = rd->TDC();
242  const uint32_t pulse_height = rd->ADC();
243 
244  std::vector<uint32_t> data;
245  data.push_back(pulse_height);
246 
247  /// Filling other fields of data
248  // TODO: If simulation finally sets other ADC fields (greater than 0), then need to change this
249  if(nanoslice_version == 1){
250  data.push_back(1);
251  data.push_back(2);
252  data.push_back(1234);
253  }// end of filling other fields of data
254 
255  DCMSimulator* dcm_simulator = getDCMSimulator(diblock, dcm);
256 
257  dcm_simulator->generateNanoSlice(daqchannel, timestamp, data);
258  }/// end of looping over digits
259 
260  /// After we are done, write them out
261  for(daqchannelmap::diblock_t idiblock = 1; idiblock <= fDCMs.size(); idiblock++)
262  for(daqchannelmap::dcm_id_t idcm = 1; idcm <= fDCMs[idiblock-1].size(); idcm++){
263  DCMSimulator* dcm_simulator = getDCMSimulator(idiblock, idcm);
264 
265  dcm_simulator->writeMicroSlices();
266  }// end of writing out MicroSlices
267 
268 
269  return true;
270 }
271 
272 
273 //------------------------------------------------------------------------------
274 bool DAQSimulator::getNanoSliceOrder(const std::vector<rawdata::RawDigit>& digits, nanoslice_order_t& nanoslice_order_vector) const{
275 
276 
278  const NanoSliceOrder* nanoslice_order = NanoSliceOrder::getInstance();
279 
280  /// Sorter class.
281  /// It produces the order of nanoslices based on their location and time.
282  Sorter sorter;
283 
284  // Need to arrange the Raw DigitList in the FEB order and then in the time order
285  for(uint32_t i = 0; i < digits.size(); ++i){
286 
287  const rawdata::RawDigit* rd = &(digits[i]); //! Get Raw digit
288 
289  const daqchannelmap::lchan channel = rd->Channel();
290  const daqchannelmap::dchan daqchannel = cmap->Map()->encodeDChan(channel);
291 
292  const daqchannelmap::diblock_t diblock = cmap->Map()->getDiBlock(daqchannel);
293  const daqchannelmap::dcm_id_t dcm = cmap->Map()->getDCM(daqchannel);
294  const daqchannelmap::feb_t feb = cmap->Map()->getFEB(daqchannel);
295  const daqchannelmap::pixel_t pixel = cmap->Map()->getPixel(daqchannel);
296  const feb_timestamp timestamp = rd->TDC();
297 
298  const unsigned long long weight = nanoslice_order->calculateOrderingWeight(diblock,
299  dcm,
300  feb,
301  pixel,
302  timestamp);
303  /// Add the nanoslice index with it's weight
304  sorter.addNumber(weight);
305  }// end of loop over digits
306 
307  /// Sorting out the NanoSlices in the right order
308  sorter.sort();
309 
310  /// Nanoslice order. First by FEB, then by time
311  /// Vector of Digit's index number
312  sorter.getIndeces(nanoslice_order_vector);
313 
314  return true;
315 }
316 
317 
318 
319 //------------------------------------------------------------------------------
320 bool DAQSimulator::print(const std::vector<rawdata::RawDigit>& digits,
321  const nanoslice_order_t& digits_order) const {
322 
324 
325  /// Printing digits in the order assigned by digits_order
326  for(uint32_t idigit = 0; idigit < digits.size(); idigit++){
327 
328  const rawdata::RawDigit* rd = &(digits[digits_order[idigit]]); //! Get Raw digit
329 
330  const uint32_t daqchannel = rd->DaqChannel();
331 
332  const uint32_t diblock = cmap->Map()->getDiBlock(daqchannel);
333  const uint32_t dcm = cmap->Map()->getDCM(daqchannel);
334  const uint32_t feb = cmap->Map()->getFEB(daqchannel);
335  const uint32_t pixel = cmap->Map()->getPixel(daqchannel);
336 
337  const uint32_t TimeStamp = rd->TDC();
338 
339  std::cout<<" DIB "<<diblock;
340  std::cout<<" DCM "<<dcm;
341  std::cout<<" FEB "<<feb;
342  std::cout<<" TIME "<<TimeStamp;
343  std::cout<<" PIX "<<pixel<<"\n";
344  }// end of loop over digits
345 
346  return true;
347 }
348 
349 //------------------------------------------------------------------------------
350 // Print the introductory version of the DAQ Simulator
351 bool DAQSimulator::print() const {
352 
353  std::cout<<"========================================================================================="<<std::endl;
354  std::cout<<"DAQ Simulator Version "<<DAQSIMULATION_VERSION<<".00"<<std::endl;
355  std::cout<<"========================================================================================="<<std::endl;
356 
357  return true;
358 }
359 
360 //------------------------------------------------------------------------------
362  const daqchannelmap::dcm_id_t dcm)const{
363  return fDCMs[diblock-1][dcm-1];
364 }
365 
366 //------------------------------------------------------------------------------
368 
370  GlobalEventTime* global_event_time = GlobalEventTime::getInstance();
371 
372  /// Advance the event global time
373  global_event_time->advanceEventTime();
374 
375  /// Get DCMs ready for the next event - clear the MicroSlice vector and the MilliSlice
376  for(daqchannelmap::diblock_t idiblock = 1; idiblock <= fDCMs.size(); idiblock++)
377  for(daqchannelmap::dcm_id_t idcm = 1 ; idcm <= fDCMs[idiblock-1].size(); idcm++){
378  DCMSimulator* dcm_simulator = getDCMSimulator(idiblock, idcm);
379 
380  dcm_simulator->nextEvent();
381  }// end of loop over DCMs getting them ready for the next event
382 
383  /// If we are producing just MicroSlices, don't need to simulate anything else
384  if(!config->isProducingJustMicroSlices()){
385 
386  /// Make Buffer Nodes ready for the next event - clear DataBlock
387  for(uint32_t ibn = 0; ibn < fBufferNodes.size(); ibn++){
388  fBufferNodes[ibn]->nextEvent();
389  }// end of making Buffer Nodes ready for the next event
390 
391  /// Make Data Logger ready for the next event - clear Event
393  }// end of advancing event for Buffer nodes and data logger
394 
395  return true;
396 }
397 
398 } // end of namespace
bool generateNanoSlice(const daqchannelmap::dchan, const uint32_t time_stamp, const uint32_t pulse_height)
Generate NanoSlice with a given pixel, TimeStamp and PulseHeight.
std::vector< BufferNodeSimulator * > fBufferNodes
All Buffer Nodes.
Definition: DAQSimulator.h:85
bool isProducingJustMicroSlices() const
Do we produce just microslices?
DCMSimulator * getDCMSimulator(const daqchannelmap::diblock_t, const daqchannelmap::dcm_id_t) const
Get an instance of DCMSilulator for a given diblock and a local DCM id for that diblock.
bool fillMicroSlices(const std::vector< rawdata::RawDigit > &)
Produce MicroSlices in all DCMs with input RawDigits.
diblock
print "ROW IS " print row
Definition: geo2elec.py:31
virtual unsigned int getNumberOfDCM(DiBlock_TYPE dbt) const =0
How many DCMs does this diblock have?
int32_t TDC() const
The time of the last baseline sample.
Definition: RawDigit.h:94
bool init()
Initialize DAQ Simulator. Need to know the Geometry at this point.
bool writeMicroSlices()
Write all MicroSlices into the output file.
const Var weight
uint32_t pixel_t
Type for physical pixel on APD.
DAQSimulator()
Constructor.
static NanoSliceOrder * getInstance()
Method to obtain the class instance.
uint32_t getNumberOfBufferNodes() const
Number of buffer nodes.
bool getNanoSliceOrder(const std::vector< rawdata::RawDigit > &, nanoslice_order_t &) const
Produce a nanoslice order from an input vector of RawDigits.
bool fillMilliSlices(std::vector< daqdataformats::RawMilliSlice * > &)
Given all MicroSlices on DCMs which were already produced, now produce MilliSlices on each DCM...
bool writeMilliSlices()
Write MilliSlice into the output file.
const daqchannelmap::DAQChannelMap * Map() const
Definition: CMap.h:57
Definition: config.py:1
std::vector< std::vector< DCMSimulator * > > fDCMs
All DCMs in the detector.
Definition: DAQSimulator.h:84
void advanceEventTime()
Increment the time of the next event time by fEventTimeDifference.
Class to hold the data from the global trigger in the correct format.
Definition: RawTrigger.h:40
const XML_Char const XML_Char * data
Definition: expat.h:268
static Configuration * getInstance()
Method to obtain the class instance.
bool fillEventAndRun(const std::vector< daqdataformats::RawDataBlock * > &, daqdataformats::RawTrigger *)
uint32_t DaqChannel() const
Definition: RawDigit.h:85
GlobalTriggerSimulator * fGlobalTrigger
Global Trigger.
Definition: DAQSimulator.h:86
bool addNumber(const unsigned long long)
Add number. The index assigned to the number is the order in which the number is added.
Definition: Sorter.cpp:29
Something conflicts with RandomNumberGenerator. Keep DAQSimulator.h include below Art Framework inclu...
std::vector< uint32_t > getIndeces() const
Get indeces.
Definition: Sorter.cpp:59
int getDetector() const
Get Detector ID.
virtual unsigned int getTotalNumberOfDiblocks() const =0
How many diblocks does the detector have?
bool processEvent(const std::vector< rawdata::RawDigit > &)
bool fillDataBlocks(const std::vector< daqdataformats::RawMilliSlice * > &, daqdataformats::RawTrigger *, std::vector< daqdataformats::RawDataBlock * > &)
Produce Trigger. Also, given all MilliSlices on DCMs which were already produced, now produce DataBlo...
std::vector< uint32_t > nanoslice_order_t
Order of the nanoslices. i-th nanoslice element represents the number in RawDigits vector...
Definition: DAQSimulator.h:42
uint32_t feb_t
Type for DCM link port. Counts from 0.
mask_t calculateOrderingWeight(const daqchannelmap::diblock_t, const daqchannelmap::dcm_id_t, const daqchannelmap::feb_t, const daqchannelmap::pixel_t, const feb_timestamp) const
bool produceEvent(const std::vector< daqdataformats::RawDataBlock * > &, daqdataformats::RawTrigger *)
~DAQSimulator()
Destructor.
OStream cout
Definition: OStream.cxx:6
uint32_t dcm_id_t
Type for DCM number, counts from 1.
DataLoggerSimulator * fDataLoggerSimulator
DataLogger.
Definition: DAQSimulator.h:87
pixel_t getPixel(dchan daqchan) const
Decode the pixel id from a dchan.
daqdataformats::version_t getNanoSliceVersion() const
Get NanoSlice version.
daqdataformats::RawTrigger * getNewTrigger()
Generates a new trigger.
bool print() const
Print the introductory version of the DAQ Simulator.
static const uint32_t DAQSIMULATION_VERSION
Version of the DAQ simulation.
Definition: DAQSimulator.h:39
int16_t ADC(uint32_t i) const
Definition: RawDigit.cxx:58
int32_t version_t
Definition: RawDAQData.h:72
uint32_t Channel() const
Definition: RawDigit.h:84
uint32_t diblock_t
Type for diblocks and blocks.
static GlobalEventTime * getInstance()
Method to obtain the class instance.
dcm_id_t getDCM(dchan daqchan) const
Decode the dcm ID from a dchan.
dchan encodeDChan(int detID, diblock_t diblock, dcm_id_t dcm, feb_t feb, pixel_t pixel) const
bool sort()
Sorting the indeces by numbers.
Definition: Sorter.cpp:39
DiBlock_TYPE
Types of Diblock.
uint32_t dchan
< DAQ Channel Map Package
uint32_t feb_timestamp
diblock_t getDiBlock(dchan daqchan) const
Decode the diblock ID from a dchan.
virtual DiBlock_TYPE getDiBlockType(dchan chan) const =0
What format is the diblock? Only relevant in NDOS.
daqdataformats::RawMilliSlice * fillMilliSlice()
Fill MilliSlices out.
bool nextEvent()
Advance to the next event - clear Event and advance it&#39;s number.
bool nextEvent()
Advance to next event. Advancing MilliSlice. Clearing MicroSlice vector.
bool nextEvent()
Prepare DAQ for the next event.
feb_t getFEB(dchan daqchan) const
Decode the feb id from a dchan.