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

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