source: trunk/FACT++/src/EventBuilderWrapper.h@ 17398

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