FACT++  1.0
EventBuilderWrapper.h
Go to the documentation of this file.
1 #ifndef FACT_EventBuilderWrapper
2 #define FACT_EventBuilderWrapper
3 
4 #include <sstream>
5 
6 #if BOOST_VERSION < 104400
7 #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 4))
8 #undef BOOST_HAS_RVALUE_REFS
9 #endif
10 #endif
11 #include <boost/thread.hpp>
12 #include <boost/filesystem.hpp>
13 #include <boost/date_time/posix_time/posix_time_types.hpp>
14 
15 #include "DimWriteStatistics.h"
16 
17 #include "DataCalib.h"
18 #include "DataWriteRaw.h"
19 
20 #ifdef HAVE_FITS
21 #include "DataWriteFits.h"
22 #else
23 #define DataWriteFits DataWriteFits2
24 #endif
25 
26 #include "DataWriteFits2.h"
27 
28 namespace ba = boost::asio;
29 namespace bs = boost::system;
30 namespace fs = boost::filesystem;
31 
32 using ba::ip::tcp;
33 
34 using namespace std;
35 
36 // ========================================================================
37 
38 #include "EventBuilder.h"
39 
40 void StartEvtBuild();
41 void CloseRunFile();
42 
43 // ========================================================================
44 
46 {
47 public:
48  // FIXME
50 
52 
53 private:
54  boost::thread fThreadMain;
55 
56  enum
57  {
58  kCurrent = 0,
59  kTotal = 1,
60  kEventId = 2,
61  kTriggerId = 3,
62  };
63 
65 
66  //uint32_t fMaxRun;
67  uint32_t fLastOpened;
68  uint32_t fLastClosed;
69  array<uint32_t,4> fNumEvts;
70 
90  //DimDescribedService fDimStatistics2;
93 
94  struct EventData
95  {
96  uint32_t runNum;
97  uint32_t evNum;
98  float data[4*1440];
99  } __attribute__((__packed__));
100 
107  Queue<tuple<Time,uint32_t,EventData/*array<float,1440*4>*/>> fQueueEventData;
109 
110  string fPath;
111  uint32_t fNightAsInt;
112  uint32_t fRunNumber;
113  int64_t fRunInProgress;
114 
115  array<uint16_t,2> fVecRoi;
116  pair<float,EventData/*array<float, 1440*4>*/> fMaxEvent; // Maximum event from applyCalib
117 
118 protected:
119  bool InitRunNumber(const string &path="")
120  {
121  if (!path.empty())
122  {
123  if (!DimWriteStatistics::DoesPathExist(path, fMsg))
124  {
125  fMsg.Error("Data path "+path+" does not exist!");
126  return false;
127  }
128 
129  fPath = path;
130  fDimWriteStats.SetCurrentFolder(fPath);
131 
132  fMsg.Info("Data path set to "+path+".");
133  }
134 
135  // Get current night
136  const Time now;
137 
138  const uint32_t night = now.NightAsInt();
139  if (night==fNightAsInt)
140  return true;
141 
142  const string crosscheck = now.GetPrevSunRise().GetAsStr("%Y%m%d");
143  if (crosscheck!=to_string(night))
144  {
145  fMsg.Warn("The crosscheck for the night failed. "+crosscheck+" is not equal to "+to_string(night)+"... keeping old one.");
146  fMsg.Warn("This is a severe error. Please restart fadctrl.");
147  return true;
148  }
149 
150  // In some circumstances, I do not understand yet (but I guess it can happen
151  // when the shared objects are re-compiled while the program is not
152  // re-started), it can happen that the returned value is wrong by one day.
153  // So this is just another check to avoid problems.
154  const uint32_t night_test = Time(now-boost::posix_time::seconds(1)).NightAsInt();
155  if (night_test != night)
156  return true;
157 
158  // And another check. Let's read the clock again.
159  // In both cases a false condition is no error and can happen. But if it happens,
160  // the bahaviour will change a fraction of a second later and the conditon
161  // will be true. No run should be taken just around that moment and if one
162  // is taken, then the date doesn't matter.
163  if (Time().NightAsInt() != night)
164  return true;
165 
166  if (night<fNightAsInt)
167  {
168  fMsg.Warn("New night "+to_string(night)+" ["+now.GetAsStr()+"] before current night "+to_string(night)+"... keeping old one.");
169  fMsg.Warn("Please check the system clock.");
170  return true;
171  }
172 
173  // Check for run numbers
174  fRunNumber = 1000;
175 
176  while (--fRunNumber>0)
177  {
178  const string name = DataProcessorImp::FormFileName(fPath, night, fRunNumber, "");
179 
180  if (access((name+"bin").c_str(), F_OK) == 0)
181  break;
182  if (access((name+"fits").c_str(), F_OK) == 0)
183  break;
184  if (access((name+"fits.fz").c_str(), F_OK) == 0)
185  break;
186  if (access((name+"fits.gz").c_str(), F_OK) == 0)
187  break;
188  if (access((name+"drs.fits").c_str(), F_OK) == 0)
189  break;
190  }
191 
192  // This is now the first file which does not exist
193  fRunNumber++;
194  fLastOpened = 0;
195 
196  // Check if we have exceeded the maximum
197  if (fRunNumber==1000)
198  {
199  fMsg.Error("You have a file with run-number 1000 in "+fPath+" ["+to_string(night)+"]");
200  return false;
201  }
202 
203  ostringstream str;
204  if (fNightAsInt==0)
205  str << "First night...";
206  else
207  str << "Night has changed from " << fNightAsInt << " [" << now << "]... ";
208  str << " next run-number is " << night << "-" << setfill('0') << setw(3) << fRunNumber << " [" << (fPath.empty()?".":fPath) << "]";
209  fMsg.Message(str);
210 
211  fNightAsInt = night;
212 
213  return true;
214  }
215 
216 public:
217  EventBuilderWrapper(MessageImp &imp) : fMsg(imp),
218  fFileFormat(FAD::kNone), /*fMaxRun(0),*/ fLastOpened(0), fLastClosed(0),
219  fDimWriteStats ("FAD_CONTROL", imp),
220  fDimRuns ("FAD_CONTROL/RUNS", "I:2;C",
221  "Run files statistics"
222  "|stats[int]:last opened or closed run"
223  "|file[string]:filename of last opened file"),
224  fDimEvents ("FAD_CONTROL/EVENTS", "I:4",
225  "Event counts"
226  "|evtsCount[int]:Num evts cur. run, total (all run), evt ID, trig. Num"),
227  fDimTrigger ("FAD_CONTROL/TRIGGER_COUNTER", "I:1;I:1;I:1;I:1;I:1;I:1;I:1;I:1",
228  "Trigger counter"
229  "|N_trg[uint32]:Number of physics triggers"
230  "|N_ped[uint32]:Number of pure pedestal triggers"
231  "|N_lpe[uint32]:Number of external light pulser triggers"
232  "|N_tim[uint32]:Number of time calibration triggers"
233  "|N_lpi[uint32]:Number of internal light pulser triggers"
234  "|N_ext1[uint32]:Number of external triggers at input ext1"
235  "|N_ext2[uint32]:Number of external triggers at input ext2"
236  "|N_misc[uint32]:Number of all other triggers"),
237  fDimRawData ("FAD_CONTROL/RAW_DATA", "S:1;S:1;I:1;I:1;S:1;I:1;I:2;I:40;S:1440;S:160;F",
238  "|roi[uint16]:number of samples per pixel"
239  "|roi_tm[uint16]:number of samples per time-marker channel"
240  "|num_fad[uint32]:event number from FADs"
241  "|num_ftm[uint32]:trigger number from FTM"
242  "|type[uint16]:trigger type from FTM"
243  "|num_boards[uint32]:number of active boards"
244  "|time[uint32]:PC time as unix time stamp"
245  "|time_board[uint32]:Time stamp of FAD boards"
246  "|start_pix[int16]:start sample of pixels"
247  "|start_tm[int16]:start sample of time marker channels"
248  "|adc[int16]:adc data"),
249  fDimEventData ("FAD_CONTROL/EVENT_DATA", "I:1;I:1;F:1440;F:1440;F:1440;F:1440", "|run:|evt:|avg:|rms:|max:|pos"),
250  fDimFeedbackData("FAD_CONTROL/FEEDBACK_DATA", "F:1440", ""),
251  fDimFwVersion ("FAD_CONTROL/FIRMWARE_VERSION", "F:42",
252  "Firmware version number of fad boards"
253  "|firmware[float]:Version number of firmware, for each board. 40=min, 41=max"),
254  fDimRunNumber ("FAD_CONTROL/RUN_NUMBER", "I:42",
255  "Run numbers coming from FAD boards"
256  "|runNumbers[int]:current run number of each FAD board. 40=min, 41=max"),
257  fDimStatus ("FAD_CONTROL/STATUS", "S:42",
258  "Status of FAD boards"
259  "|status[bitpattern]:Status of each FAD board. Maybe buggy"),
260  fDimDNA ("FAD_CONTROL/DNA", "X:40",
261  "DNA of FAD boards"
262  "|DNA[hex]:Hex identifier of each FAD board"),
263  fDimTemperature ("FAD_CONTROL/TEMPERATURE", "S:1;F:160",
264  "DRS temperatures"
265  "|cnt[uint16]:Counter of averaged values"
266  "|temp[deg C]:average temp of all DRS chips"),
267  fDimPrescaler ("FAD_CONTROL/PRESCALER", "S:42",
268  "Trigger generator prescaler of fad boards"
269  "|prescaler[int]:Trigger generator prescaler value, for each board"),
270  fDimRefClock ("FAD_CONTROL/REFERENCE_CLOCK", "S:1;F:40",
271  "Reference clock of FAD boards"
272  "|cnt[uint16]:Counter of averaged values"
273  "|clk[Hz]:Averaged clock of ref clocks of FAD boards"),
274  fDimRoi ("FAD_CONTROL/REGION_OF_INTEREST", "S:2", "roi:|roi_rm:"),
275  fDimDac ("FAD_CONTROL/DAC", "S:336",
276  "DAC settings of each FAD board"
277  "|DAC[int]:DAC counts, sequentially DAC 0 board 0, 0/1, 0/2... (plus min max)"),
278  fDimDrsRuns ("FAD_CONTROL/DRS_RUNS", "I:1;I:3;I:1",
279  "|roi:Region of interest of secondary baseline"
280  "|run:Run numbers of DRS runs (0=none)"
281  "|night:Night as int of the first run (0 if none)"),
282  fDimDrsCalibration("FAD_CONTROL/DRS_CALIBRATION", "I:1;I:3;F:1474560;F:1474560;F:1474560;F:1474560;F:1474560;F:1474560;F:163840;F:163840",
283  "|roi:Region of interest of secondary baseline"
284  "|run:Run numbers of DRS runs (0=none)"),
285  fDimStatistics1 ("FAD_CONTROL/STATISTICS1", "I:5;X:3;I:1;I:2;C:40;I:40;I:40",
286  "Event Builder status for GUI display"
287  "|bufferInfo[int]:Events in buffer, incomp., comp., write, proc., tot."
288  "|memInfo[int]:total mem allocated, used mem, max memory"
289  "|deltaT[ms]:Time in ms for rates"
290  "|rateNew[int]:Number of new start events received"
291  "|numConn[int]:Number of connections per board"
292  "|rateBytes[int]:Bytes read during last cylce"
293  "|relBytes[int]:Relative number of total bytes received (received - released)"),
294  fDimFileFormat("FAD_CONTROL/FILE_FORMAT", "S:1", "|format[int]:Current file format"),
295  fDimIncomplete("FAD_CONTROL/INCOMPLETE", "X:1", "|incomplete[bits]:bit_index=c*10+b. board b(0..3) in crate c(0..9)"),
296  // It is important to instantiate them after the DimServices
297  fQueueStatistics1(std::bind(&EventBuilderWrapper::UpdateDimStatistics1, this, placeholders::_1)),
298  fQueueProcHeader( std::bind(&EventBuilderWrapper::procHeader, this, placeholders::_1)),
299  fQueueEvents( std::bind(&EventBuilderWrapper::UpdateDimEvents, this, placeholders::_1)),
300  fQueueTrigger( std::bind(&EventBuilderWrapper::UpdateDimTrigger, this, placeholders::_1)),
301  fQueueRoi( std::bind(&EventBuilderWrapper::UpdateDimRoi, this, placeholders::_1)),
302  fQueueRawData( std::bind(&EventBuilderWrapper::UpdateDimRawData, this, placeholders::_1)),
303  fQueueEventData( std::bind(&EventBuilderWrapper::UpdateDimEventData, this, placeholders::_1)),
304  fQueueTempRefClk( std::bind(&EventBuilderWrapper::UpdateDimTempRefClk, this, placeholders::_1)),
305  fNightAsInt(0), fRunInProgress(-1),
306  fMaxEvent(make_pair(-FLT_MAX, EventData()/*array<float,1440*4>()*/))
307  {
308  if (This)
309  throw logic_error("EventBuilderWrapper cannot be instantiated twice.");
310 
311  This = this;
312 
313  fVecRoi.fill(0);
314 
315  memset(fNumEvts.data(), 0, sizeof(fNumEvts));
316  fDimEvents.Update(fNumEvts);
317 
318  for (size_t i=0; i<40; i++)
319  ConnectSlot(i, tcp::endpoint());
320  }
321 
323  {
324  Abort();
325 
326  // FIXME: Used timed_join and abort afterwards
327  // What's the maximum time the eb need to abort?
328  fThreadMain.join();
329  }
330 
331  map<uint32_t, FAD::RunDescription> fExpectedRuns;
332 
333  mutex mtx_newrun;
334 
335  uint32_t StartNewRun(int64_t maxtime, int64_t maxevt, const pair<string, FAD::Configuration> &ref)
336  {
337  if (maxtime<=0 || maxtime>24*60*60)
338  maxtime = 24*60*60;
339  if (maxevt<=0 || maxevt>INT32_MAX)
340  maxevt = INT32_MAX;
341 
342  if (!InitRunNumber())
343  return 0;
344 
345  const FAD::RunDescription descr =
346  {
347  uint32_t(maxtime),
348  uint32_t(maxevt),
349  fNightAsInt,
350  ref.first,
351  ref.second,
352  };
353 
354  const lock_guard<mutex> lock(mtx_newrun);
355  fExpectedRuns[fRunNumber] = descr;
356  return fRunNumber++;
357  }
358 
360  {
361  return fThreadMain.joinable();
362  }
363 
364  void SetMaxMemory(unsigned int mb) const
365  {
366  g_maxMem = size_t(mb)*1000000;
367  }
368  void SetEventTimeout(uint16_t to) const
369  {
370  g_evtTimeout = to;
371  }
372 
373  void StartThread(const vector<tcp::endpoint> &addr)
374  {
375  if (IsThreadRunning())
376  {
377  fMsg.Warn("Start - EventBuilder still running");
378  return;
379  }
380 
381  //fLastMessage.clear();
382 
383  for (size_t i=0; i<40; i++)
384  ConnectSlot(i, addr[i]);
385 
386  fMsg.Message("Starting EventBuilder thread");
387 
388  fThreadMain = boost::thread(StartEvtBuild);
389 
390  // Run a detached thread which ensures that our thread
391  // is joined so that it is not joinable anymore once
392  // it is finished (I think this is similar to
393  // boost::thread_guard, but I could not figure out
394  // how it works)
395  std::thread([this] { this->fThreadMain.join(); }).detach();
396  }
397 
398  void ConnectSlot(unsigned int i, const tcp::endpoint &addr)
399  {
400  if (i>39)
401  return;
402 
403  fRunInProgress = -1;
404 
405  if (addr==tcp::endpoint())
406  {
407  // In this order
408  g_port[i].sockDef = 0;
409 
410  fDimIncomplete.setQuality(0);
411  fDimIncomplete.Update(uint64_t(0));
412  return;
413  }
414 
415  struct sockaddr_in sockaddr; //IP for each socket
416  sockaddr.sin_family = AF_INET;
417  sockaddr.sin_addr.s_addr = htonl(addr.address().to_v4().to_ulong());
418  sockaddr.sin_port = htons(addr.port());
419  memcpy(&g_port[i].sockAddr, &sockaddr, sizeof(struct sockaddr_in));
420 
421  // In this order
422  g_port[i].sockDef = 1;
423 
424  fDimIncomplete.setQuality(0);
425  fDimIncomplete.Update(uint64_t(0));
426  }
427 
428  void IgnoreSlot(unsigned int i)
429  {
430  if (i>39)
431  return;
432 
433  if (g_port[i].sockAddr.sin_port==0)
434  return;
435 
436  g_port[i].sockDef = -1;
437  }
438 
439 
440  void Abort()
441  {
442  fMsg.Message("Signal abort to EventBuilder thread...");
443  g_reset = 2;
444  }
445 
446  void ResetThread(bool soft)
447  {
448  fMsg.Message("Signal reset to EventBuilder thread...");
449  g_reset = soft ? 101 : 102;
450  }
451 
452  void Exit()
453  {
454  fMsg.Message("Signal exit to EventBuilder thread...");
455  g_reset = 1;
456  }
457 
458  bool IsConnected(int i) const { return gi_NumConnect[i]==1; }
459  bool IsConnecting(int i) const { return gi_NumConnect[i]==0 && g_port[i].sockDef!=0; }
460  bool IsDisconnected(int i) const { return gi_NumConnect[i]==0 && g_port[i].sockDef==0; }
461  bool IsRunInProgress() const { return fRunInProgress>=0; }
462 
463  void SetIgnore(int i, bool b) const { if (g_port[i].sockDef!=0) g_port[i].sockDef=b?-1:1; }
464  bool IsIgnored(int i) const { return g_port[i].sockDef==-1; }
465 
467  {
468  const bool changed = f!=fFileFormat;
469 
470  fFileFormat = f;
471  fDimFileFormat.Update(uint16_t(f));
472 
473  string msg = "File format set to: ";
474  switch (f)
475  {
476  case FAD::kNone: msg += "kNone."; break;
477  case FAD::kDebug: msg += "kDebug."; break;
478  case FAD::kFits: msg += "kFits."; break;
479  case FAD::kZFits: msg += "kZFits."; break;
480  case FAD::kCfitsio: msg += "kCfitsio"; break;
481  case FAD::kRaw: msg += "kRaw"; break;
482  case FAD::kCalib:
484  DataCalib::Update(fDimDrsCalibration, fDimDrsRuns);
485  fMsg.Message("Resetted DRS calibration.");
486  return;
487  }
488 
489  if (changed)
490  fMsg.Message(msg);
491  }
492 
494  {
495  if (DataCalib::ResetTrgOff(fDimDrsCalibration, fDimDrsRuns))
496  {
497  fFileFormat = FAD::kCalib;
498  fDimFileFormat.Update(uint16_t(fFileFormat));
499  fMsg.Message("Resetted DRS calibration for secondary baseline.");
500  }
501  else
502  fMsg.Warn("Could not reset DRS calibration of secondary baseline.");
503 
504  return 0;
505  }
506 
507  void LoadDrsCalibration(const char *fname)
508  {
509  if (!DataCalib::ReadFits(fname, fMsg))
510  return;
511 
512  fMsg.Info("Successfully loaded DRS calibration from "+string(fname));
513  DataCalib::Update(fDimDrsCalibration, fDimDrsRuns);
514  }
515 
516  virtual int CloseOpenFiles() { CloseRunFile(); fRunInProgress = -1; return 0; }
517 
518 
519  // -------------- Mapped event builder callbacks ------------------
520 
521  void UpdateRuns(const string &fname="")
522  {
523  uint32_t values[2] =
524  {
525  fLastOpened,
526  fLastClosed
527  };
528 
529  vector<char> data(sizeof(values)+fname.size()+1);
530  memcpy(data.data(), values, sizeof(values));
531  strcpy(data.data()+sizeof(values), fname.c_str());
532  fDimRuns.setQuality((bool)fFile);
533  fDimRuns.Update(data);
534 
535  if (!fname.empty())
536  fDimWriteStats.FileOpened(fname);
537  }
538 
539  shared_ptr<DataProcessorImp> fFile;
540 
541  bool UpdateDimEvents(const pair<Time,array<uint32_t,4>> &stat)
542  {
543  fDimEvents.setData(stat.second.data(), sizeof(uint32_t)*4);
544  fDimEvents.Update(stat.first);
545  return true;
546  }
547 
548  bool UpdateDimTrigger(const tuple<Time,char,array<uint32_t,8>> &stat)
549  {
550  fDimTrigger.setQuality(get<1>(stat));
551  fDimTrigger.setData(get<2>(stat).data(), sizeof(uint32_t)*8);
552  fDimTrigger.Update(get<0>(stat));
553  return true;
554  }
555 
556  bool runOpen(const EVT_CTRL2 &evt)
557  {
558  const uint32_t night = evt.runCtrl->night;
559  const uint32_t runid = evt.runNum>0 ? evt.runNum : time(NULL);
560 
561  // If there is still an open file: close it
562  if (fFile)
563  runClose(evt);
564 
565  // Keep a copy of the currently valid drs calibration
566  // and associate it to the run control structure
567  evt.runCtrl->calib = make_shared<DrsCalibration>(DataCalib::GetCalibration());
568 
569  // Crate the file
570  DataProcessorImp *file = 0;
571  switch (fFileFormat)
572  {
573  case FAD::kNone: file = new DataDump(fPath, night, runid, fMsg); break;
574  case FAD::kDebug: file = new DataDebug(fPath, night, runid, fMsg); break;
575  case FAD::kCfitsio: file = new DataWriteFits(fPath, night, runid, fMsg); break;
576  case FAD::kFits: file = new DataWriteFits2(fPath, night, runid, fMsg); break;
577  case FAD::kZFits: file = new DataWriteFits2(fPath, night, runid, *evt.runCtrl->calib, fMsg); break;
578  case FAD::kRaw: file = new DataWriteRaw(fPath, night, runid, fMsg); break;
579  case FAD::kCalib: file = new DataCalib(fPath, night, runid, *evt.runCtrl->calib, fDimDrsCalibration, fDimDrsRuns, fMsg); break;
580  }
581 
582  try
583  {
584  // Try to open the file
585  FAD::RunDescription desc;
586  desc.maxevt = evt.runCtrl->maxEvt;
587  desc.maxtime = evt.runCtrl->closeTime - evt.runCtrl->openTime;
588  desc.name = evt.runCtrl->runType;
589 
590  if (!file->Open(evt, desc))
591  return false;
592  }
593  catch (const exception &e)
594  {
595  fMsg.Error("Exception trying to open file: "+string(e.what()));
596  return false;
597  }
598 
599  fLastOpened = runid;
600 
601  // Signal that a file is open
602  fFile = shared_ptr<DataProcessorImp>(file);
603 
604  // Now do all the calls which potentially block (dim)
605 
606  // Time for update runs before time for update events
607  UpdateRuns(file->GetFileName());
608  fNumEvts[kEventId] = 0;
609  fNumEvts[kTriggerId] = 0;
610  fNumEvts[kCurrent] = 0;
611 
612  const Time time;
613 
614  fQueueEvents.emplace(time, fNumEvts);
615  fQueueTrigger.emplace(time, 'o', evt.triggerCounter);
616 
617  ostringstream str;
618  str << "Opened: " << file->GetFileName() << " (" << file->GetRunId() << ")";
619  fMsg.Info(str);
620 
621  return true;
622  }
623 
624  bool runWrite(const EVT_CTRL2 &e)
625  {
626  /*
627  const size_t size = sizeof(EVENT)+1440*(evt.Roi+evt.RoiTM)*2;
628  vector evt(e.fEvent, e.fEvent+size);
629 
630  const EVENT &evt = *reinterpret_cast<EVENT*>(evt.data());
631 
632  int16_t *val = evt.Adc_Data;
633  const int16_t *off = e.runCtrl->zcalib.data();
634  for (const int16_t *start=evt.StartPix; start<evt.StartPix+1440; val+=1024, off+=1024, start++)
635  {
636  if (*start<0)
637  continue;
638 
639  for (size_t i=0; i<roi; i++)
640  val[i] -= offset[(*start+i)%1024];
641  }*/
642 
643  if (!fFile->WriteEvt(e))
644  return false;
645 
646  //const EVENT &evt = *e.fEvent;
647 
648  fNumEvts[kCurrent]++;
649  fNumEvts[kEventId] = e.evNum;//evt.EventNum;
650  fNumEvts[kTriggerId] = e.trgNum;//evt.TriggerNum;
651  fNumEvts[kTotal]++;
652 
653  static Time oldt(boost::date_time::neg_infin);
654  Time newt;
655  if (newt>oldt+boost::posix_time::seconds(1))
656  {
657  fQueueEvents.emplace(newt, fNumEvts);
658  fQueueTrigger.emplace(newt, 'w', e.triggerCounter);
659  oldt = newt;
660  }
661 
662  return true;
663  }
664 
665  void runClose(const EVT_CTRL2 &evt)
666  {
667  if (!fFile)
668  return;
669 
670  // It can happen that runFinished was never called
671  // (e.g. runWrite failed)
672  if (fRunInProgress==fFile->GetRunId())
673  fRunInProgress = -1;
674 
675  // Close the file
676  const bool rc = fFile->Close(evt);
677 
678  fLastClosed = fFile->GetRunId();
679 
680  ostringstream str;
681  str << "Closed: " << fFile->GetFileName() << " (" << fFile->GetRunId() << ")";
682  if (!rc)
683  str << "... failed!";
684 
685  // Signal that the file is closed
686 
687  fFile.reset();
688 
689  // Now do all the calls which can potentially block (dim)
690 
691  CloseRun(fLastClosed);
692 
693  // Time for update events before time for update runs
694  const Time time;
695 
696  fQueueEvents.emplace(time, fNumEvts);
697  fQueueTrigger.emplace(time, 'c', evt.triggerCounter);
698 
699  UpdateRuns();
700 
701  // Do the potentially blocking call after all others
702  rc ? fMsg.Info(str) : fMsg.Error(str);
703 
704  // If a Drs Calibration has just been finished, all following events
705  // should also be processed with this calibration.
706  // Note that this is a generally dangerous operation. Here, the previous
707  // DRS calibration shared_ptr gets freed and if it is the last in use,
708  // the memory will vanish. If another thread accesses that pointer,
709  // it _must_ make a copy of the shared_ptr first to ensure that
710  // the memory will stay in scope until the end of its operation.
712 
713  RUN_CTRL2 &run = *evt.runCtrl;
714  if (!run.calib || run.calib->fStep != cal.fStep || run.calib->fRoi!=cal.fRoi)
715  run.calib = make_shared<DrsCalibration>(cal);
716  }
717 
718  virtual void CloseRun(uint32_t /*runid*/) { }
719 
720  bool UpdateDimRoi(const pair<Time, array<uint16_t,2>> &roi)
721  {
722  fDimRoi.setData(roi.second.data(), sizeof(uint16_t)*2);
723  fDimRoi.Update(roi.first);
724  return true;
725  }
726 
727  bool UpdateDimTempRefClk(const tuple<Time, array<uint32_t,40>, array<int16_t,160>> &dat)
728  {
729  const auto delay = boost::posix_time::seconds(5);
730 
731  const Time &tm = get<0>(dat);
732 
733  const array<uint32_t,40> &clk = get<1>(dat);
734  const array<int16_t,160> &tmp = get<2>(dat);
735 
736  // --------------- RefClock ---------------
737 
738  // history, add current data to history
739  static list<pair<Time,array<uint32_t,40>>> listclk;
740  listclk.emplace_back(tm, clk);
741 
742  // --------------- Temperatures ---------------
743 
744  // history, add current data to history
745  static list<pair<Time,array<int16_t,160>>> listtmp;
746  listtmp.emplace_back(tm, tmp);
747 
748  // ========== Update dim services once a second =========
749 
750  static Time oldt(boost::date_time::neg_infin);
751  Time newt;
752 
753  if (newt<oldt+delay)
754  return true;
755 
756  oldt = newt;
757 
758  // --------------- RefClock ---------------
759 
760  // remove expired data from history
761  while (1)
762  {
763  auto it=listclk.begin();
764  if (it==listclk.end() || it->first+delay>tm)
765  break;
766  listclk.pop_front();
767  }
768 
769  // Structure for dim service
770  struct Clock
771  {
772  uint16_t num;
773  float val[40];
774  Clock() { memset(this, 0, sizeof(Clock)); }
775  } __attribute__((__packed__));
776 
777  // Calculate average and fll structure
778  vector<uint16_t> clknum(40);
779 
780  Clock avgclk;
781  avgclk.num = listclk.size();
782  for (auto it=listclk.begin(); it!=listclk.end(); it++)
783  for (int i=0; i<40; i++)
784  if (it->second[i]!=UINT32_MAX)
785  {
786  avgclk.val[i] += it->second[i];
787  clknum[i]++;
788  }
789  for (int i=0; i<40; i++)
790  avgclk.val[i] *= 2.048/clknum[i];
791 
792  // Update dim service
793  fDimRefClock.setData(avgclk);
794  fDimRefClock.Update(tm);
795 
796  listclk.clear();
797 
798  // --------------- Temperatures ---------------
799 
800  // remove expired data from history
801  while (1)
802  {
803  auto it=listtmp.begin();
804  if (it==listtmp.end() || it->first+delay>tm)
805  break;
806  listtmp.pop_front();
807  }
808 
809  // Structure for dim service
810  struct Temp
811  {
812  uint16_t num;
813  float val[160];
814  Temp() { memset(this, 0, sizeof(Temp)); }
815  } __attribute__((__packed__));
816 
817  // Calculate average and fll structure
818  vector<uint32_t> tmpnum(160);
819 
820  Temp avgtmp;
821  avgtmp.num = listtmp.size();
822  for (auto it=listtmp.begin(); it!=listtmp.end(); it++)
823  for (int i=0; i<160; i++)
824  if (it->second[i]!=INT16_MIN)
825  {
826  avgtmp.val[i] += it->second[i];
827  tmpnum[i]++;
828  }
829  for (int i=0; i<160; i++)
830  avgtmp.val[i] /= tmpnum[i]*16;
831 
832  // Update dim service
833  fDimTemperature.setData(avgtmp);
834  fDimTemperature.Update(tm);
835 
836  listtmp.clear();
837 
838  return true;
839  }
840 
841  bool eventCheck(const EVT_CTRL2 &evt)
842  {
843  const EVENT *event = evt.fEvent;
844 
845  const Time tm(evt.time);
846 
847  const array<uint16_t,2> roi = {{ event->Roi, event->RoiTM }};
848 
849  if (roi!=fVecRoi)
850  {
851  fQueueRoi.emplace(tm, roi);
852  fVecRoi = roi;
853  }
854 
855  const FAD::EventHeader *beg = reinterpret_cast<const FAD::EventHeader*>(evt.FADhead);
856  const FAD::EventHeader *end = reinterpret_cast<const FAD::EventHeader*>(evt.FADhead)+40;
857 
858  // FIMXE: Compare with target configuration
859 
860  // Copy data to array
861  array<uint32_t,40> clk;
862  array<int16_t,160> tmp;
863 
864  for (int i=0; i<40; i++)
865  clk[i] = UINT32_MAX;
866 
867  for (int i=0; i<160; i++)
868  tmp[i] = INT16_MIN;
869 
870  //fill(clk.data(), clk.data()+ 40, UINT32_MAX);
871  //fill(tmp.data(), tmp.data()+160, INT16_MIN);
872 
873  for (const FAD::EventHeader *ptr=beg; ptr!=end; ptr++)
874  {
875  // FIXME: Compare with expectations!!!
876  if (ptr->fStartDelimiter==0)
877  {
878  if (ptr==beg)
879  beg++;
880  continue;
881  }
882 
883  clk[ptr->Id()] = ptr->fFreqRefClock;
884  for (int i=0; i<4; i++)
885  tmp[ptr->Id()*4+i] = ptr->fTempDrs[i];
886 
887  if (beg->fStatus != ptr->fStatus)
888  {
889  fMsg.Error("Inconsistency in FAD status detected.... closing run.");
890  return false;
891  }
892 
893  if (beg->fRunNumber != ptr->fRunNumber)
894  {
895  fMsg.Error("Inconsistent run number detected.... closing run.");
896  return false;
897  }
898 
899  /*
900  if (beg->fVersion != ptr->fVersion)
901  {
902  Error("Inconsist firmware version detected.... closing run.");
903  CloseRunFile(runNr, 0, 0);
904  break;
905  }
906  */
907  if (beg->fEventCounter != ptr->fEventCounter)
908  {
909  fMsg.Error("Inconsistent FAD event number detected.... closing run.");
910  return false;
911  }
912 
913  if (beg->fTriggerCounter != ptr->fTriggerCounter)
914  {
915  fMsg.Error("Inconsistent FTM trigger number detected.... closing run.");
916  return false;
917  }
918 
919  // FIXME: Check with first event!
920  if (beg->fAdcClockPhaseShift != ptr->fAdcClockPhaseShift)
921  {
922  fMsg.Error("Inconsistent phase shift detected.... closing run.");
923  return false;
924  }
925 
926  // FIXME: Check with first event!
927  if (memcmp(beg->fDac, ptr->fDac, sizeof(beg->fDac)))
928  {
929  fMsg.Error("Inconsistent DAC values detected.... closing run.");
930  return false;
931  }
932 
933  if (beg->fTriggerType != ptr->fTriggerType)
934  {
935  fMsg.Error("Inconsistent trigger type detected.... closing run.");
936  return false;
937  }
938  }
939 
940  // check REFCLK_frequency
941  // check consistency with command configuration
942  // how to log errors?
943  // need gotNewRun/closedRun to know it is finished
944 
945  fQueueTempRefClk.emplace(tm, clk, tmp);
946 
947  if (evt.runCtrl->fileStat == kFileClosed)
948  {
949  static Time oldt(boost::date_time::neg_infin);
950  if (tm>oldt+boost::posix_time::seconds(1))
951  {
952  fQueueTrigger.emplace(tm, 0, evt.runCtrl->triggerCounter);
953  oldt = tm;
954  }
955  }
956 
957  return true;
958  }
959 
962 
963  bool UpdateDimRawData(const vector<char> &v)
964  {
965  const EVENT *evt = reinterpret_cast<const EVENT*>(v.data());
966 
967  fDimRawData.setData(v);
968  fDimRawData.setQuality(evt->TriggerType);
969  fDimRawData.Update(Time(evt->PCTime, evt->PCUsec));
970 
971  return true;
972  }
973 
974  bool UpdateDimEventData(const tuple<Time,uint32_t,EventData/*array<float, 1440*4>*/> &tup)
975  {
976  fDimEventData.setQuality(get<1>(tup));
977  fDimEventData.setData(get<2>(tup));
978  fDimEventData.Update(get<0>(tup));
979 
980  return true;
981  }
982 
983  void applyCalib(const EVT_CTRL2 &evt, const size_t &size)
984  {
985  const EVENT *event = evt.fEvent;
986  const int16_t *start = event->StartPix;
987 
988  // Get the reference to the run associated information
989  RUN_CTRL2 &run = *evt.runCtrl;
990 
991  if (size==1) // If there is more than one event waiting (including this one), throw them away
992  {
993  Time now;
994 
995  // ------------------- Copy event data to new memory --------------------
996  // (to make it thread safe; a static buffer might improve memory handling)
997  const uint16_t roi = event->Roi;
998 
999  // ------------------- Apply full DRS calibration ------------------------
1000  // (Is that necessray, or would a simple offset correct do well already?)
1001 
1002  // This is a very important step. Making a copy of the shared pointer ensures
1003  // that another thread (here: runClose) can set a new shared_ptr with new
1004  // data without this thread being affected. If we just did run.calib->Apply
1005  // the shared_pointer in use here might vanash during the processing, the
1006  // memory is freed and we access invalid memory. It is not important
1007  // which memory we acces (the old or the new one) because it is just for
1008  // display purpose anyway.
1009  const shared_ptr<DrsCalibration> cal = run.calib;
1010 
1011  // There seems to be a problem using std::array... maybe the size is too big?
1012  // array<float, (1440+160)*1024> vec2;
1013  vector<float> vec((1440+160)*roi);
1014  cal->Apply(vec.data(), event->Adc_Data, start, roi);
1015 
1016  // ------------------- Appy DRS-step correction --------------------------
1017  for (auto it=run.prevStart.begin(); it!=run.prevStart.end(); it++)
1018  {
1019  DrsCalibrate::CorrectStep(vec.data(), 1440, roi, it->data(), start, roi+10);
1020  DrsCalibrate::CorrectStep(vec.data(), 1440, roi, it->data(), start, 3);
1021  }
1022 
1023  // ------------------------- Remove spikes --------------------------------
1024  DrsCalibrate::RemoveSpikes4(vec.data(), roi);
1025 
1026  // -------------- Update raw data dim sevice (VERY SLOW) -----------------
1027  if (fQueueRawData.empty() && now>fLastDimRawData+boost::posix_time::seconds(5))
1028  {
1029  vector<char> data1(sizeof(EVENT)+vec.size()*sizeof(float));
1030  memcpy(data1.data(), event, sizeof(EVENT));
1031  memcpy(data1.data()+sizeof(EVENT), vec.data(), vec.size()*sizeof(float));
1032  fQueueRawData.emplace(data1);
1033 
1034  fLastDimRawData = now;
1035  }
1036 
1037  // ------------------------- Basic statistics -----------------------------
1038  DrsCalibrate::SlidingAverage(vec.data(), roi, 10);
1039 
1040  // If this is a cosmic event
1041  EventData edat;
1042  edat.runNum = evt.runNum;
1043  edat.evNum = evt.evNum;
1044  //array<float, 1440*4> stats; // Mean, RMS, Max, Pos
1045  const float max = DrsCalibrate::GetPixelStats(edat.data, vec.data(), roi, 15, 5);
1046  if (evt.trgTyp==0 && max>fMaxEvent.first)
1047  fMaxEvent = make_pair(max, edat);
1048 
1049  // ------------------ Update dim service (statistics) ---------------------
1050 
1051  if (fQueueEventData.empty() && now>fLastDimEventData+boost::posix_time::milliseconds(4999))
1052  {
1053  edat.evNum = evt.evNum;
1054  edat.runNum = evt.runNum;
1055 
1056  fQueueEventData.emplace(evt.time, evt.trgTyp, evt.trgTyp==0 ? fMaxEvent.second : edat);
1057  if (evt.trgTyp==0)
1058  fMaxEvent.first = -FLT_MAX;
1059 
1060  fLastDimEventData = now;
1061  }
1062 
1063  // === SendFeedbackData(PEVNT_HEADER *fadhd, EVENT *event)
1064  //
1065  // if (!ptr->HasTriggerLPext() && !ptr->HasTriggerLPint())
1066  // return;
1067  //
1068  // vector<float> data2(1440); // Mean, RMS, Max, Pos, first, last
1069  // DrsCalibrate::GetPixelMax(data2.data(), data.data(), event->Roi, 0, event->Roi-1);
1070  //
1071  // fDimFeedbackData.Update(data2);
1072  }
1073 
1074  // Keep the start cells of the last five events for further corrections
1075  // As a performance improvement we could also just store the
1076  // pointers to the last five events...
1077  // What if a new run is started? Do we mind?
1078  auto &l = run.prevStart; // History for start cells of previous events (for step calibration)
1079 
1080  if (l.size()<5)
1081  l.emplace_front();
1082  else
1083  {
1084  auto it = l.end();
1085  l.splice(l.begin(), l, --it);
1086  }
1087 
1088  memcpy(l.front().data(), start, 1440*sizeof(int16_t));
1089  }
1090 
1092  {
1093  const lock_guard<mutex> lock(mtx_newrun);
1094  return fExpectedRuns.find(fRunNumber-1)!=fExpectedRuns.end();
1095  }
1096 
1097  uint32_t GetRunNumber() const
1098  {
1099  return fRunNumber;
1100  }
1101 
1102  bool IncreaseRunNumber(uint32_t run)
1103  {
1104  if (!InitRunNumber())
1105  return false;
1106 
1107  if (run<fRunNumber)
1108  {
1109  ostringstream msg;
1110  msg <<
1111  "Run number " << run << " smaller than next available "
1112  "run number " << fRunNumber << " in " << fPath << " [" << fNightAsInt << "]";
1113  fMsg.Error(msg);
1114  return false;
1115  }
1116 
1117  fRunNumber = run;
1118 
1119  return true;
1120  }
1121 
1123  {
1124  // This is to secure iteration over fExpectedRuns
1125  const lock_guard<mutex> lock(mtx_newrun);
1126 
1127  map<uint32_t,FAD::RunDescription>::iterator it = fExpectedRuns.begin();
1128  while (it!=fExpectedRuns.end())
1129  {
1130  if (it->first<run.runId)
1131  {
1132  ostringstream str;
1133  str << "runOpen - Missed run " << it->first << ".";
1134  fMsg.Info(str);
1135 
1136  // Increase the iterator first, it becomes invalid with the next call
1137  const auto is = it++;
1138  fExpectedRuns.erase(is);
1139  continue;
1140  }
1141 
1142  if (it->first==run.runId)
1143  break;
1144 
1145  it++;
1146  }
1147 
1148  if (it==fExpectedRuns.end())
1149  {
1150  ostringstream str;
1151  str << "runOpen - Run " << run.runId << " wasn't expected (maybe manual triggers)";
1152  fMsg.Warn(str);
1153 
1154  // This is not ideal, but the best we can do
1155  run.night = fNightAsInt;
1156 
1157  return;
1158  }
1159 
1160  const FAD::RunDescription &conf = it->second;
1161 
1162  run.runType = conf.name;
1163  run.maxEvt = conf.maxevt;
1164  run.closeTime = conf.maxtime + run.openTime;
1165  run.night = conf.night;
1166 
1167  fExpectedRuns.erase(it);
1168 
1169  // Now signal the fadctrl (configuration process that a run is in progress)
1170  // Maybe this could be done earlier, but we are talking about a
1171  // negligible time scale here.
1172  fRunInProgress = run.runId;
1173  }
1174 
1176  {
1177  // This is called when the last event of a run (run time exceeded or
1178  // max number of events exceeded) has been received.
1179  fRunInProgress = -1;
1180  }
1181 
1182  //map<boost::thread::id, string> fLastMessage;
1183 
1184  void factOut(int severity, const char *message)
1185  {
1186  ostringstream str;
1187  str << "EventBuilder: " << message;
1188 
1189  /*
1190  string &old = fLastMessage[boost::this_thread::get_id()];
1191 
1192  if (str.str()==old)
1193  return;
1194  old = str.str();
1195  */
1196 
1197  fMsg.Update(str, severity);
1198  }
1199 
1200 /*
1201  void factStat(int64_t *stat, int len)
1202  {
1203  if (len!=7)
1204  {
1205  fMsg.Warn("factStat received unknown number of values.");
1206  return;
1207  }
1208 
1209  vector<int64_t> data(1, g_maxMem);
1210  data.insert(data.end(), stat, stat+len);
1211 
1212  static vector<int64_t> last(8);
1213  if (data==last)
1214  return;
1215  last = data;
1216 
1217  fDimStatistics.Update(data);
1218 
1219  // len ist die Laenge des arrays.
1220  // array[4] enthaelt wieviele bytes im Buffer aktuell belegt sind; daran
1221  // kannst Du pruefen, ob die 100MB voll sind ....
1222 
1223  ostringstream str;
1224  str
1225  << "Wait=" << stat[0] << " "
1226  << "Skip=" << stat[1] << " "
1227  << "Del=" << stat[2] << " "
1228  << "Tot=" << stat[3] << " "
1229  << "Mem=" << stat[4] << "/" << g_maxMem << " "
1230  << "Read=" << stat[5] << " "
1231  << "Conn=" << stat[6];
1232 
1233  fMsg.Info(str);
1234  }
1235  */
1236 
1237  bool UpdateDimStatistics1(const pair<Time,GUI_STAT> &stat)
1238  {
1239  fDimStatistics1.setData(&stat.second, sizeof(GUI_STAT));
1240  fDimStatistics1.Update(stat.first);
1241 
1242  return true;
1243  }
1244 
1245  void factStat(const GUI_STAT &stat)
1246  {
1247  fQueueStatistics1.emplace(Time(), stat);
1248  }
1249 
1250  void factReportIncomplete(uint64_t rep)
1251  {
1252  fDimIncomplete.setQuality(1);
1253  fDimIncomplete.Update(rep);
1254  }
1255 
1256  array<FAD::EventHeader, 40> fVecHeader;
1257 
1258  template<typename T, class S>
1259  array<T, 42> Compare(const S *vec, const T *t)
1260  {
1261  const int offset = reinterpret_cast<const char *>(t) - reinterpret_cast<const char *>(vec);
1262 
1263  const T *min = NULL;
1264  const T *val = NULL;
1265  const T *max = NULL;
1266 
1267  array<T, 42> arr;
1268 
1269  // bool rc = true;
1270  for (int i=0; i<40; i++)
1271  {
1272  const char *base = reinterpret_cast<const char*>(vec+i);
1273  const T *ref = reinterpret_cast<const T*>(base+offset);
1274 
1275  arr[i] = *ref;
1276 
1277  if (gi_NumConnect[i]==0)
1278  {
1279  arr[i] = 0;
1280  continue;
1281  }
1282 
1283  if (!val)
1284  {
1285  min = ref;
1286  val = ref;
1287  max = ref;
1288  }
1289 
1290  if (*ref<*min)
1291  min = ref;
1292 
1293  if (*ref>*max)
1294  max = ref;
1295 
1296  // if (*val!=*ref)
1297  // rc = false;
1298  }
1299 
1300  arr[40] = val ? *min : 1;
1301  arr[41] = val ? *max : 0;
1302 
1303  return arr;
1304  }
1305 
1306  template<typename T>
1307  array<T, 42> CompareBits(const FAD::EventHeader *h, const T *t)
1308  {
1309  const int offset = reinterpret_cast<const char *>(t) - reinterpret_cast<const char *>(h);
1310 
1311  T val = 0;
1312  T rc = 0;
1313 
1314  array<T, 42> vec;
1315 
1316  bool first = true;
1317 
1318  for (int i=0; i<40; i++)
1319  {
1320  const char *base = reinterpret_cast<const char*>(&fVecHeader[i]);
1321  const T *ref = reinterpret_cast<const T*>(base+offset);
1322 
1323  vec[i+2] = *ref;
1324 
1325  if (gi_NumConnect[i]==0)
1326  {
1327  vec[i+2] = 0;
1328  continue;
1329  }
1330 
1331  if (first)
1332  {
1333  first = false;
1334  val = *ref;
1335  rc = 0;
1336  }
1337 
1338  rc |= val^*ref;
1339  }
1340 
1341  vec[0] = rc;
1342  vec[1] = val;
1343 
1344  return vec;
1345  }
1346 
1347  template<typename T, size_t N>
1348  void Update(DimDescribedService &svc, const array<T, N> &data, const Time &t=Time(), int n=N)
1349  {
1350  svc.setData(const_cast<T*>(data.data()), sizeof(T)*n);
1351  svc.Update(t);
1352  }
1353 
1354  template<typename T>
1355  void Print(const char *name, const pair<bool,array<T, 43>> &data)
1356  {
1357  cout << name << "|" << data.first << "|" << data.second[1] << "|" << data.second[0] << "<x<" << data.second[1] << ":";
1358  for (int i=0; i<40;i++)
1359  cout << " " << data.second[i+3];
1360  cout << endl;
1361  }
1362 
1363  vector<uint> fNumConnected;
1364 
1365  bool procHeader(const tuple<Time,bool,FAD::EventHeader> &dat)
1366  {
1367  const Time &t = get<0>(dat);
1368  const bool changed = get<1>(dat);
1369  const FAD::EventHeader &h = get<2>(dat);
1370 
1371  const FAD::EventHeader old = fVecHeader[h.Id()];
1372  fVecHeader[h.Id()] = h;
1373 
1374  if (old.fVersion != h.fVersion || changed)
1375  {
1376  const array<uint16_t,42> ver = Compare(&fVecHeader[0], &fVecHeader[0].fVersion);
1377 
1378  array<float,42> data;
1379  for (int i=0; i<42; i++)
1380  {
1381  ostringstream str;
1382  str << (ver[i]>>8) << '.' << (ver[i]&0xff);
1383  data[i] = stof(str.str());
1384  }
1385  Update(fDimFwVersion, data, t);
1386  }
1387 
1388  if (old.fRunNumber != h.fRunNumber || changed)
1389  {
1390  const array<uint32_t,42> run = Compare(&fVecHeader[0], &fVecHeader[0].fRunNumber);
1391  fDimRunNumber.setData(&run[0], 42*sizeof(uint32_t));
1392  fDimRunNumber.Update(t);
1393  }
1394 
1395  if (old.fTriggerGeneratorPrescaler != h.fTriggerGeneratorPrescaler || changed)
1396  {
1397  const array<uint16_t,42> pre = Compare(&fVecHeader[0], &fVecHeader[0].fTriggerGeneratorPrescaler);
1398  fDimPrescaler.setData(&pre[0], 42*sizeof(uint16_t));
1399  fDimPrescaler.Update(t);
1400  }
1401 
1402  if (old.fDNA != h.fDNA || changed)
1403  {
1404  const array<uint64_t,42> dna = Compare(&fVecHeader[0], &fVecHeader[0].fDNA);
1405  Update(fDimDNA, dna, t, 40);
1406  }
1407 
1408  if (old.fStatus != h.fStatus || changed)
1409  {
1410  const array<uint16_t,42> sts = CompareBits(&fVecHeader[0], &fVecHeader[0].fStatus);
1411  Update(fDimStatus, sts, t);
1412  }
1413 
1414  if (memcmp(old.fDac, h.fDac, sizeof(h.fDac)) || changed)
1415  {
1416  array<uint16_t, FAD::kNumDac*42> dacs;
1417 
1418  for (int i=0; i<FAD::kNumDac; i++)
1419  {
1420  const array<uint16_t, 42> dac = Compare(&fVecHeader[0], &fVecHeader[0].fDac[i]);
1421  memcpy(&dacs[i*42], &dac[0], sizeof(uint16_t)*42);
1422  }
1423 
1424  Update(fDimDac, dacs, t);
1425  }
1426 
1427  return true;
1428  }
1429 
1430  void debugHead(const FAD::EventHeader &h)
1431  {
1432  const uint16_t id = h.Id();
1433  if (id>39)
1434  return;
1435 
1436  if (fNumConnected.size()!=40)
1437  fNumConnected.resize(40);
1438 
1439  const vector<uint> con(gi_NumConnect, gi_NumConnect+40);
1440 
1441  const bool changed = con!=fNumConnected || !IsThreadRunning();
1442 
1443  fNumConnected = con;
1444 
1445  fQueueProcHeader.emplace(Time(), changed, h);
1446  }
1447 };
1448 
1450 
1451 // ----------- Event builder callbacks implementation ---------------
1452 bool runOpen(const EVT_CTRL2 &evt)
1453 {
1454  return EventBuilderWrapper::This->runOpen(evt);
1455 }
1456 
1457 bool runWrite(const EVT_CTRL2 &evt)
1458 {
1459  return EventBuilderWrapper::This->runWrite(evt);
1460 }
1461 
1462 void runClose(const EVT_CTRL2 &evt)
1463 {
1464  EventBuilderWrapper::This->runClose(evt);
1465 }
1466 
1467 bool eventCheck(const EVT_CTRL2 &evt)
1468 {
1469  return EventBuilderWrapper::This->eventCheck(evt);
1470 }
1471 
1473 {
1474  EventBuilderWrapper::This->gotNewRun(run);
1475 }
1476 
1478 {
1479  EventBuilderWrapper::This->runFinished();
1480 }
1481 
1482 void applyCalib(const EVT_CTRL2 &evt, const size_t &size)
1483 {
1484  EventBuilderWrapper::This->applyCalib(evt, size);
1485 }
1486 
1487 void factOut(int severity, const char *message)
1488 {
1489  EventBuilderWrapper::This->factOut(severity, message);
1490 }
1491 
1492 void factStat(const GUI_STAT &stat)
1493 {
1494  EventBuilderWrapper::This->factStat(stat);
1495 }
1496 
1497 void factReportIncomplete(uint64_t rep)
1498 {
1499  EventBuilderWrapper::This->factReportIncomplete(rep);
1500 }
1501 
1502 // ------
1503 
1504 void debugHead(void *buf)
1505 {
1506  const FAD::EventHeader &h = *reinterpret_cast<FAD::EventHeader*>(buf);
1507  EventBuilderWrapper::This->debugHead(h);
1508 }
1509 
1510 #endif
DimDescribedService fDimDNA
void ConnectSlot(unsigned int i, const tcp::endpoint &addr)
int start(int initState)
Definition: feeserver.c:1740
DimDescribedService fDimStatistics1
DimDescribedService fDimRawData
static const DrsCalibration & GetCalibration()
Definition: DataCalib.h:54
array< FAD::EventHeader, 40 > fVecHeader
std::string runType
Definition: EventBuilder.h:72
bool runWrite(const EVT_CTRL2 &evt)
void Update(DimDescribedService &svc, const array< T, N > &data, const Time &t=Time(), int n=N)
bool IncreaseRunNumber(uint32_t run)
uint32_t GetRunNumber() const
DimDescribedService fDimFileFormat
DimDescribedService fDimStatus
void SetMaxMemory(unsigned int mb) const
PEVNT_HEADER * FADhead
Definition: EventBuilder.h:131
static Step CorrectStep(float *vec, uint16_t nch, uint16_t roi, const int16_t *prev, const int16_t *start, const int16_t offset, const uint16_t *map=NULL)
Definition: DrsCalib.h:509
Queue< tuple< Time, char, array< uint32_t, 8 > > > fQueueTrigger
DimDescribedService fDimRuns
uint32_t evNum
Definition: EventBuilder.h:116
EVENT * fEvent
Definition: EventBuilder.h:132
Time GetPrevSunRise(double horizon) const
Definition: Time.cc:313
uint32_t fRunNumber
Definition: HeadersFAD.h:190
static bool ResetTrgOff(DimDescribedService &dim, DimDescribedService &runs)
Definition: DataCalib.cc:35
bool eventCheck(const EVT_CTRL2 &evt)
bool UpdateDimEventData(const tuple< Time, uint32_t, EventData > &tup)
static void SlidingAverage(float *const vec, const uint32_t roi, const uint16_t w)
Definition: DrsCalib.h:780
uint16_t fStatus
Definition: HeadersFAD.h:173
array< T, 42 > Compare(const S *vec, const T *t)
EventBuilderWrapper(MessageImp &imp)
void runClose(const EVT_CTRL2 &evt)
bool IsDisconnected(int i) const
int i
Definition: db_dim_client.c:21
void setQuality(int quality)
Definition: discpp.cxx:1256
The base implementation of a distributed messaging system.
Definition: MessageImp.h:10
Adds some functionality to boost::posix_time::ptime for our needs.
Definition: Time.h:30
char str[80]
Definition: test_client.c:7
uint16_t fRoi
Definition: DrsCalib.h:1318
uint32_t NightAsInt() const
Definition: Time.cc:397
int64_t runId
Definition: EventBuilder.h:57
static void Restart()
Definition: DataCalib.cc:15
uint32_t runNum
Definition: EventBuilder.h:115
STL namespace.
void factStat(const GUI_STAT &stat)
bool runOpen(const EVT_CTRL2 &evt)
bool UpdateDimTempRefClk(const tuple< Time, array< uint32_t, 40 >, array< int16_t, 160 >> &dat)
void applyCalib(const EVT_CTRL2 &evt, const size_t &size)
uint gi_NumConnect[NBOARDS]
Definition: EventBuilder.cc:82
void Print(const char *name, const pair< bool, array< T, 43 >> &data)
Definition: Queue.h:28
Queue< pair< Time, array< uint16_t, 2 > > > fQueueRoi
void factOut(int severity, const char *message)
FACT_SOCK g_port[NBOARDS]
Definition: EventBuilder.cc:80
map< uint32_t, FAD::RunDescription > fExpectedRuns
bool UpdateDimStatistics1(const pair< Time, GUI_STAT > &stat)
int64_t first
Size of this column in the tile.
Definition: zofits.h:26
bool UpdateDimEvents(const pair< Time, array< uint32_t, 4 >> &stat)
bool FileOpened(const std::string &fileName)
DimDescribedService fDimDac
static bool DoesPathExist(std::string path, MessageImp &log)
void debugHead(const FAD::EventHeader &h)
DimDescribedService fDimPrescaler
uint32_t trgTyp
Definition: EventBuilder.h:119
void UpdateRuns(const string &fname="")
virtual int ResetSecondaryDrsBaseline()
array< T, 42 > CompareBits(const FAD::EventHeader *h, const T *t)
DimDescribedService fDimFeedbackData
void gotNewRun(RUN_CTRL2 &run)
Queue< pair< Time, array< uint32_t, 4 > > > fQueueEvents
DimDescribedService fDimRunNumber
DimDescribedService fDimTemperature
size_t g_maxMem
Definition: EventBuilder.cc:76
bool UpdateDimRoi(const pair< Time, array< uint16_t, 2 >> &roi)
void SetOutputFormat(FAD::FileFormat_t f)
FAD::FileFormat_t fFileFormat
DimDescribedService fDimDrsRuns
DimDescribedService fDimRefClock
void debugHead(void *buf)
bool empty() const
Definition: Queue.h:308
bool runOpen(const EVT_CTRL2 &evt)
Queue< tuple< Time, uint32_t, EventData > > fQueueEventData
DimDescribedService fDimEventData
bool procHeader(const tuple< Time, bool, FAD::EventHeader > &dat)
bool eventCheck(const EVT_CTRL2 &evt)
#define DataWriteFits
DimDescribedService fDimRoi
void StartThread(const vector< tcp::endpoint > &addr)
void setData(const void *ptr, size_t sz)
void factReportIncomplete(uint64_t rep)
uint32_t maxEvt
Definition: EventBuilder.h:67
int Error(const std::string &str)
Definition: MessageImp.h:49
int sockDef
Definition: FAD.h:125
void gotNewRun(RUN_CTRL2 &run)
vector< uint > fNumConnected
int Update(const std::string &txt, int severity=kMessage)
Definition: MessageImp.cc:156
void runFinished()
typedef __attribute__
uint64_t fDNA
Number of boards answered per crate.
Definition: HeadersFAD.h:187
Warning because the service this data corrsponds to might have been last updated longer ago than Local time
Definition: smartfact.txt:92
void factOut(int severity, const char *message)
int Warn(const std::string &str)
Definition: MessageImp.h:48
bool runWrite(const EVT_CTRL2 &e)
DimWriteStatistics fDimWriteStats
Queue< pair< Time, GUI_STAT > > fQueueStatistics1
std::shared_ptr< RUN_CTRL2 > runCtrl
Definition: EventBuilder.h:139
uint16_t fTriggerGeneratorPrescaler
Definition: HeadersFAD.h:185
DimDescribedService fDimIncomplete
double end
static int run
Definition: dim_fork.cxx:9
provides a statistics service telling the free space on disk and the total size written so far ...
uint32_t StartNewRun(int64_t maxtime, int64_t maxevt, const pair< string, FAD::Configuration > &ref)
bool IsRunInProgress() const
bool UpdateDimRawData(const vector< char > &v)
Queue< tuple< Time, bool, FAD::EventHeader > > fQueueProcHeader
uint32_t night
Definition: EventBuilder.h:64
static bool ReadFits(const string &fname, MessageImp &msg)
Definition: DataCalib.cc:204
void factStat(const GUI_STAT &stat)
pair< float, EventData > fMaxEvent
void IgnoreSlot(unsigned int i)
int size
Definition: db_dim_server.c:17
DimDescribedService fDimTrigger
float data[4 *1440]
timeval time
Definition: EventBuilder.h:129
DimDescribedService fDimEvents
uint16_t fVersion
Definition: HeadersFAD.h:172
void SetEventTimeout(uint16_t to) const
uint32_t trgNum
Definition: EventBuilder.h:118
bool SetCurrentFolder(const std::string &folder)
Configures that current folder where files are written to.
uint32_t fStep
Definition: DrsCalib.h:1317
shared_ptr< DataProcessorImp > fFile
virtual void CloseRun(uint32_t)
void factReportIncomplete(uint64_t rep)
FileFormat_t
Definition: HeadersFAD.h:74
DimDescribedService fDimDrsCalibration
uint16_t g_evtTimeout
Definition: EventBuilder.cc:78
void LoadDrsCalibration(const char *fname)
bool IsConnected(int i) const
array< uint32_t, 4 > fNumEvts
TT t
Definition: test_client.c:26
bool InitRunNumber(const string &path="")
int Info(const std::string &str)
Definition: MessageImp.h:47
time_t openTime
Definition: EventBuilder.h:61
void runClose(const EVT_CTRL2 &evt)
static double GetPixelStats(float *ptr, const float *data, uint16_t roi, uint16_t begskip=0, uint16_t endskip=0)
Definition: DrsCalib.h:855
int Message(const std::string &str)
Definition: MessageImp.h:46
std::list< std::array< int16_t, 1440 > > prevStart
Definition: EventBuilder.h:79
void applyCalib(const EVT_CTRL2 &evt, const size_t &size)
std::array< uint32_t, 8 > triggerCounter
Definition: EventBuilder.h:137
static EventBuilderWrapper * This
void ResetThread(bool soft)
bool IsIgnored(int i) const
DimDescribedService fDimFwVersion
std::shared_ptr< DrsCalibration > calib
Definition: EventBuilder.h:78
int g_reset
Definition: EventBuilder.cc:74
std::string GetAsStr(const char *fmt="%Y-%m-%d %H:%M:%S") const
Definition: Time.cc:240
void CloseRunFile()
void SetIgnore(int i, bool b) const
Queue< vector< char > > fQueueRawData
char message[1024]
Definition: db_dim_client.c:16
bool UpdateDimTrigger(const tuple< Time, char, array< uint32_t, 8 >> &stat)
void StartEvtBuild()
time_t closeTime
Definition: EventBuilder.h:63
virtual int CloseOpenFiles()
static void RemoveSpikes4(float *ptr, uint32_t roi)
Definition: DrsCalib.h:718
array< uint16_t, 2 > fVecRoi
static void Update(DimDescribedService &dim, DimDescribedService &runs)
Definition: DataCalib.cc:56
static std::string FormFileName(const std::string &path, uint64_t night, uint32_t runid, const std::string &extension)
Queue< tuple< Time, array< uint32_t, 40 >, array< int16_t, 160 > > > fQueueTempRefClk
uint16_t fDac[kNumDac]
Definition: HeadersFAD.h:194
bool IsConnecting(int i) const