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

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