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

Last change on this file since 15192 was 15192, checked in by tbretz, 12 years ago
Plot a message about a new file format only when it was changed; reset fLastOpened at the beginning of the 'night'
File size: 49.2 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
40extern "C" {
41 extern void StartEvtBuild();
42 extern int CloseRunFile(uint32_t runId, uint32_t closeTime, uint32_t maxEvt);
43}
44
45// ========================================================================
46
47class EventBuilderWrapper
48{
49public:
50 // FIXME
51 static EventBuilderWrapper *This;
52
53 MessageImp &fMsg;
54
55private:
56 boost::thread fThread;
57
58 enum CommandStates_t // g_runStat
59 {
60 kAbort = -2, // quit as soon as possible ('abort')
61 kExit = -1, // stop reading, quit when buffered events done ('exit')
62 kInitialize = 0, // 'initialize' (e.g. dim not yet started)
63 kHybernate = 1, // do nothing for long time ('hybernate') [wakeup within ~1sec]
64 kSleep = 2, // do nothing ('sleep') [wakeup within ~10msec]
65 kModeFlush = 10, // read data from camera, but skip them ('flush')
66 kModeTest = 20, // read data and process them, but do not write to disk ('test')
67 kModeFlag = 30, // read data, process and write all to disk ('flag')
68 kModeRun = 40, // read data, process and write selected to disk ('run')
69 };
70
71 enum
72 {
73 kCurrent = 0,
74 kTotal = 1,
75 kEventId = 2,
76 kTriggerId = 3,
77 };
78
79 FAD::FileFormat_t fFileFormat;
80
81 uint32_t fMaxRun;
82 uint32_t fLastOpened;
83 uint32_t fLastClosed;
84 uint32_t fNumEvts[4];
85
86 DimWriteStatistics fDimWriteStats;
87 DimDescribedService fDimRuns;
88 DimDescribedService fDimEvents;
89 DimDescribedService fDimRawData;
90 DimDescribedService fDimEventData;
91 DimDescribedService fDimFeedbackData;
92 DimDescribedService fDimFwVersion;
93 DimDescribedService fDimRunNumber;
94 DimDescribedService fDimStatus;
95 DimDescribedService fDimDNA;
96 DimDescribedService fDimTemperature;
97 DimDescribedService fDimPrescaler;
98 DimDescribedService fDimRefClock;
99 DimDescribedService fDimRoi;
100 DimDescribedService fDimDac;
101 DimDescribedService fDimDrsRuns;
102 DimDescribedService fDimDrsCalibration;
103 DimDescribedService fDimStatistics1;
104 DimDescribedService fDimStatistics2;
105 DimDescribedService fDimFileFormat;
106
107 bool fDebugStream;
108 bool fDebugRead;
109 bool fDebugLog;
110
111 string fPath;
112 uint64_t fNightAsInt;
113 uint32_t fRunNumber;
114
115protected:
116 bool InitRunNumber(const string &path="")
117 {
118 if (!path.empty())
119 {
120 if (!DimWriteStatistics::DoesPathExist(path, fMsg))
121 {
122 fMsg.Error("Data path "+path+" does not exist!");
123 return false;
124 }
125
126 fPath = path;
127 fDimWriteStats.SetCurrentFolder(fPath);
128
129 fMsg.Info("Data path set to "+path+".");
130 }
131
132 // Get current night
133 const uint64_t night = Time().NightAsInt();
134 if (night==fNightAsInt)
135 return true;
136
137 // Check for run numbers
138 fRunNumber = 1000;
139
140 while (--fRunNumber>0)
141 {
142 const string name = DataProcessorImp::FormFileName(fPath, night, fRunNumber, "");
143
144 if (access((name+"bin").c_str(), F_OK) == 0)
145 break;
146 if (access((name+"fits").c_str(), F_OK) == 0)
147 break;
148 if (access((name+"drs.fits").c_str(), F_OK) == 0)
149 break;
150 }
151
152 // This is now the first file which does not exist
153 fRunNumber++;
154 fLastOpened = 0;
155
156 // Check if we have exceeded the maximum
157 if (fRunNumber==1000)
158 {
159 fMsg.Error("You have a file with run-number 1000 in "+fPath+" ["+to_string(night)+"]");
160 return false;
161 }
162
163 ostringstream str;
164 if (fNightAsInt==0)
165 str << "First night...";
166 else
167 str << "Night has changd from " << fNightAsInt << "... new";
168 str << " run-number is " << night << "-" << setfill('0') << setw(3) << fRunNumber << " [" << (fPath.empty()?".":fPath) << "]";
169 fMsg.Message(str);
170
171 fNightAsInt = night;
172
173 return true;
174 }
175
176public:
177 EventBuilderWrapper(MessageImp &imp) : fMsg(imp),
178 fFileFormat(FAD::kNone), fMaxRun(0), fLastOpened(0), fLastClosed(0),
179 fDimWriteStats ("FAD_CONTROL", imp),
180 fDimRuns ("FAD_CONTROL/RUNS", "I:5;C",
181 "Run files statistics"
182 "|stats[int]:num of open files, min/max run no, last opened or closed run"
183 "|file[string]:filename of last opened file"),
184 fDimEvents ("FAD_CONTROL/EVENTS", "I:4",
185 "Event counts"
186 "|evtsCount[int]:Num evts cur. run, total (all run), evt ID, trig. Num"),
187 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",
188 "|roi[uint16]:number of samples per pixel"
189 "|roi_tm[uint16]:number of samples per time-marker channel"
190 "|num_fad[uint32]:event number from FADs"
191 "|num_ftm[uint32]:trigger number from FTM"
192 "|type[uint16]:trigger type from FTM"
193 "|num_boards[uint32]:number of active boards"
194 "|error[uint8]:event builder error counters"
195 "|dummy[]:"
196 "|time[uint32]:PC time as unix time stamp"
197 "|time_board[uint32]:Time stamp of FAD boards"
198 "|start_pix[int16]:start sample of pixels"
199 "|start_tm[int16]:start sample of time marker channels"
200 "|adc[int16]:adc data"),
201 fDimEventData ("FAD_CONTROL/EVENT_DATA", "F:1440;F:1440;F:1440;F:1440", "|avg:|rms:|max:|pos"),
202 fDimFeedbackData("FAD_CONTROL/FEEDBACK_DATA", "F:1440", ""),
203 fDimFwVersion ("FAD_CONTROL/FIRMWARE_VERSION", "F:42",
204 "Firmware version number of fad boards"
205 "|firmware[float]:Version number of firmware, for each board. 40=min, 41=max"),
206 fDimRunNumber ("FAD_CONTROL/RUN_NUMBER", "I:42",
207 "Run numbers coming from FAD boards"
208 "|runNumbers[int]:current run number of each FAD board. 40=min, 41=max"),
209 fDimStatus ("FAD_CONTROL/STATUS", "S:42",
210 "Status of FAD boards"
211 "|status[bitpattern]:Status of each FAD board. Maybe buggy"),
212 fDimDNA ("FAD_CONTROL/DNA", "X:40",
213 "DNA of FAD boards"
214 "|DNA[hex]:Hex identifier of each FAD board"),
215 fDimTemperature ("FAD_CONTROL/TEMPERATURE", "F:82",
216 "FADs temperatures"
217 "|temp[deg. C]:0 global min, 1-40 min, 41 global max, 42-81 max"),
218 fDimPrescaler ("FAD_CONTROL/PRESCALER", "S:42",
219 "Trigger generator prescaler of fad boards"
220 "|prescaler[int]:Trigger generator prescaler value, for each board"),
221 fDimRefClock ("FAD_CONTROL/REFERENCE_CLOCK", "I:42",
222 "Reference clock of FAD boards"
223 "|refClocks[t]:ref clocks of FAD boards. 40=min, 41=max"),
224 fDimRoi ("FAD_CONTROL/REGION_OF_INTEREST", "S:2", "roi:|roi_rm:"),
225 fDimDac ("FAD_CONTROL/DAC", "S:336",
226 "DAC settings of each FAD board"
227 "|DAC[int]:DAC counts, sequentially DAC 0 board 0, 0/1, 0/2... (plus min max)"),
228 fDimDrsRuns ("FAD_CONTROL/DRS_RUNS", "I:1;I:3",
229 "|roi:Region of interest of secondary baseline"
230 "|run:Run numbers of DRS runs (0=none)"),
231 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",
232 "|roi:Region of interest of secondary baseline"
233 "|run:Run numbers of DRS runs (0=none)"),
234 fDimStatistics1 ("FAD_CONTROL/STATISTICS1", "I:3;I:5;X:4;I:3;I:3;I:40;I:1;I:2;C:40;I:40;I:40;X:40",
235 "Event Builder status for GUI display"
236 "|threadInfo[int]:Number of read, proc and writes"
237 "|bufferInfo[int]:Events in buffer, incomp., comp., tot., max past cycle, total"
238 "|memInfo[int]:total buf. mem, used mem, max used, max past cycle"
239 "|EvtCnt[int]:Number of events skipped, written, with errors"
240 "|badRoi[int]:Num boards with wrong ROI in event, run or board"
241 "|badRoiBoard[int]:Num boards with wrong ROI"
242 "|deltaT[ms]:Time in ms for rates"
243 "|rateNew[int]:Number of new start events received"
244 "|numConn[int]:Number of connections per board"
245 "|errConn[int]:IO errors per board"
246 "|rateBytes[int]:Bytes read this cycle"
247 "|totBytes[int]:Bytes read (counter)"),
248 fDimStatistics2 ("FAD_CONTROL/STATISTICS2", "I:1;I:280;X:40;I:40;I:4;I:4;I:2;I:2;I:3;C:40",
249 "Event Builder status, events oriented"
250 "|reset[int]:If increased, reset all counters"
251 "|numRead[int]:How often sucessful read from N sockets per loop"
252 "|gotByte[int]:number of bytes read per board"
253 "|gotErr[int]:number of com. errors per board"
254 "|evtStat[int]:number of evts read, completed, with errors, incomplete"
255 "|procStat[int]:num. of evts proc., w probs, acc. or rej. by SW trigger"
256 "|feedStat[int]:number of evts used or rejected by feedback system"
257 "|wrtStat[int]:number of evts written to disk, with errors"
258 "|runStat[int]:number of run opened, closed, with open or close errors"
259 "|numConn[int]:number of sockets successfully opened per board"),
260 fDimFileFormat ("FAD_CONTROL/FILE_FORMAT", "S:1", ""),
261 fDebugStream(false), fDebugRead(false), fDebugLog(false), fNightAsInt(0)
262 {
263 if (This)
264 throw logic_error("EventBuilderWrapper cannot be instantiated twice.");
265
266 This = this;
267
268 memset(fNumEvts, 0, sizeof(fNumEvts));
269 fDimEvents.Update(fNumEvts);
270
271 for (size_t i=0; i<40; i++)
272 ConnectSlot(i, tcp::endpoint());
273 }
274 virtual ~EventBuilderWrapper()
275 {
276 Abort();
277
278 // FIXME: Used timed_join and abort afterwards
279 // What's the maximum time the eb need to abort?
280 fThread.join();
281 //ffMsg.Info("EventBuilder stopped.");
282
283 for (vector<DataProcessorImp*>::iterator it=fFiles.begin(); it!=fFiles.end(); it++)
284 delete *it;
285 }
286
287 set<uint32_t> fIsRunStarted;
288 map<uint32_t, FAD::RunDescription> fExpectedRuns;
289
290 uint32_t StartNewRun(int64_t maxtime, int64_t maxevt, const pair<string, FAD::Configuration> &ref)
291 {
292 if (maxtime<=0 || maxtime>24*60*60)
293 maxtime = 24*60*60;
294 if (maxevt<=0 || maxevt>INT32_MAX)
295 maxevt = INT32_MAX;
296
297 const FAD::RunDescription descr =
298 {
299 uint32_t(maxtime),
300 uint32_t(maxevt),
301 ref.first,
302 ref.second,
303 };
304
305 if (!InitRunNumber())
306 return 0;
307
308 // FIMXE: Maybe reset an event counter so that the mcp can count events?
309
310 //fMsg.Info(" ==> TODO: Set a limit on the size of fExpectedRuns!");
311
312 fExpectedRuns[fRunNumber] = descr;
313 fIsRunStarted.insert(fRunNumber);
314 return fRunNumber++;
315 }
316
317 bool IsThreadRunning()
318 {
319 return !fThread.timed_join(boost::posix_time::microseconds(0));
320 }
321
322 void SetMaxMemory(unsigned int mb) const
323 {
324 /*
325 if (mb*1000000<GetUsedMemory())
326 {
327 // ffMsg.Warn("...");
328 return;
329 }*/
330
331 g_maxMem = size_t(mb)*1000000;
332 }
333
334 void StartThread(const vector<tcp::endpoint> &addr)
335 {
336 if (IsThreadRunning())
337 {
338 fMsg.Warn("Start - EventBuilder still running");
339 return;
340 }
341
342 fLastMessage.clear();
343
344 for (size_t i=0; i<40; i++)
345 ConnectSlot(i, addr[i]);
346
347 g_runStat = kModeRun;
348 g_maxProc = 3;
349
350 fMsg.Message("Starting EventBuilder thread");
351
352 fThread = boost::thread(StartEvtBuild);
353 }
354 void ConnectSlot(unsigned int i, const tcp::endpoint &addr)
355 {
356 if (i>39)
357 return;
358
359 if (addr==tcp::endpoint())
360 {
361 DisconnectSlot(i);
362 return;
363 }
364
365 g_port[i].sockAddr.sin_family = AF_INET;
366 g_port[i].sockAddr.sin_addr.s_addr = htonl(addr.address().to_v4().to_ulong());
367 g_port[i].sockAddr.sin_port = htons(addr.port());
368 // In this order
369 g_port[i].sockDef = 1;
370 }
371 void DisconnectSlot(unsigned int i)
372 {
373 if (i>39)
374 return;
375
376 g_port[i].sockDef = 0;
377 // In this order
378 g_port[i].sockAddr.sin_family = AF_INET;
379 g_port[i].sockAddr.sin_addr.s_addr = 0;
380 g_port[i].sockAddr.sin_port = 0;
381 }
382 void IgnoreSlot(unsigned int i)
383 {
384 if (i>39)
385 return;
386 if (g_port[i].sockAddr.sin_port==0)
387 return;
388
389 g_port[i].sockDef = -1;
390 }
391
392
393 void Abort()
394 {
395 fMsg.Message("Signal abort to EventBuilder thread...");
396 g_runStat = kAbort;
397 }
398
399 void ResetThread(bool soft)
400 {
401 /*
402 if (g_reset > 0)
403
404 * suspend reading
405 * reset = g_reset;
406 * g_reset=0
407
408 * reset% 10
409 == 0 leave event Buffers as they are
410 == 1 let all buffers drain (write (incomplete) events)
411 > 1 flush all buffers (do not write buffered events)
412
413 * (reset/10)%10
414 > 0 close all sockets and destroy them (also free the
415 allocated read-buffers)
416 recreate before resuming operation
417 [ this is more than just close/open that can be
418 triggered by e.g. close/open the base-socket ]
419
420 * (reset/100)%10
421 > 0 close all open run-files
422
423 * (reset/1000)
424 sleep so many seconds before resuming operation
425 (does not (yet) take into account time left when waiting
426 for buffers getting empty ...)
427
428 * resume_reading
429
430 */
431 fMsg.Message("Signal reset to EventBuilder thread...");
432 g_reset = soft ? 101 : 102;
433 }
434
435 void Exit()
436 {
437 fMsg.Message("Signal exit to EventBuilder thread...");
438 g_runStat = kExit;
439 }
440
441 /*
442 void Wait()
443 {
444 fThread.join();
445 ffMsg.Message("EventBuilder stopped.");
446 }*/
447
448 void Hybernate() const { g_runStat = kHybernate; }
449 void Sleep() const { g_runStat = kSleep; }
450 void FlushMode() const { g_runStat = kModeFlush; }
451 void TestMode() const { g_runStat = kModeTest; }
452 void FlagMode() const { g_runStat = kModeFlag; }
453 void RunMode() const { g_runStat = kModeRun; }
454
455 // FIXME: To be removed
456 //void SetMode(int mode) const { g_runStat = mode; }
457
458 bool IsConnected(int i) const { return gi_NumConnect[i]==7; }
459 bool IsConnecting(int i) const { return !IsConnected(i) && !IsDisconnected(i); }
460 bool IsDisconnected(int i) const { return gi_NumConnect[i]<=0 && g_port[i].sockDef==0; }
461 int GetNumConnected(int i) const { return gi_NumConnect[i]; }
462 int GetNumFilesOpen() const { return fFiles.size(); }
463
464 /*
465 bool IsConnected(int i) const { return gi_NumConnect[i]>0; }
466 bool IsConnecting(int i) const { return !IsConnected(i) && !IsDisconnected(i); }
467 bool IsDisconnected(int i) const { return gi_NumConnect[i]<=0 && g_port[i].sockDef==0; }
468 int GetNumConnected(int i) const { return gi_NumConnect[i]; }
469 */
470
471 void SetIgnore(int i, bool b) const { if (g_port[i].sockDef!=0) g_port[i].sockDef=b?-1:1; }
472 bool IsIgnored(int i) const { return g_port[i].sockDef==-1; }
473
474 void SetOutputFormat(FAD::FileFormat_t f)
475 {
476 const bool changed = f!=fFileFormat;
477
478 fFileFormat = f;
479 fDimFileFormat.Update(uint16_t(f));
480
481 string msg = "File format set to: ";
482 switch (f)
483 {
484 case FAD::kNone: msg += "kNone."; break;
485 case FAD::kDebug: msg += "kDebug."; break;
486 case FAD::kFits: msg += "kFits."; break;
487 case FAD::kCfitsio: msg += "kCfitsio"; break;
488 case FAD::kRaw: msg += "kRaw"; break;
489 case FAD::kCalib:
490 DataCalib::Restart();
491 DataCalib::Update(fDimDrsCalibration, fDimDrsRuns);
492 fMsg.Message("Resetted DRS calibration.");
493 return;
494 }
495
496 if (changed)
497 fMsg.Message(msg);
498 }
499
500 virtual int ResetSecondaryDrsBaseline()
501 {
502 if (DataCalib::ResetTrgOff(fDimDrsCalibration, fDimDrsRuns))
503 {
504 fFileFormat = FAD::kCalib;
505 fDimFileFormat.Update(uint16_t(fFileFormat));
506 fMsg.Message("Resetted DRS calibration for secondary baseline.");
507 }
508 else
509 fMsg.Warn("Could not reset DRS calibration of secondary baseline.");
510
511 return 0;
512 }
513
514 void SetDebugLog(bool b) { fDebugLog = b; }
515
516 void SetDebugStream(bool b)
517 {
518 fDebugStream = b;
519 if (b)
520 return;
521
522 for (int i=0; i<40; i++)
523 {
524 if (!fDumpStream[i].is_open())
525 continue;
526
527 fDumpStream[i].close();
528
529 ostringstream name;
530 name << "socket_dump-" << setfill('0') << setw(2) << i << ".bin";
531 fMsg.Message("Closed file '"+name.str()+"'");
532 }
533 }
534
535 void SetDebugRead(bool b)
536 {
537 fDebugRead = b;
538 if (b || !fDumpRead.is_open())
539 return;
540
541 fDumpRead.close();
542 fMsg.Message("Closed file 'socket_events.txt'");
543 }
544
545// size_t GetUsedMemory() const { return gi_usedMem; }
546
547 void LoadDrsCalibration(const char *fname)
548 {
549 if (!DataCalib::ReadFits(fname, fMsg))
550 return;
551 fMsg.Info("Successfully loaded DRS calibration from "+string(fname));
552 DataCalib::Update(fDimDrsCalibration, fDimDrsRuns);
553 }
554
555 virtual int CloseOpenFiles() { CloseRunFile(0, 0, 0); return 0; }
556
557
558 /*
559 struct OpenFileToDim
560 {
561 int code;
562 char fileName[FILENAME_MAX];
563 };
564
565 SignalRunOpened(runid, filename);
566 // Send num open files
567 // Send runid, (more info about the run?), filename via dim
568
569 SignalEvtWritten(runid);
570 // Send num events written of newest file
571
572 SignalRunClose(runid);
573 // Send new num open files
574 // Send empty file-name if no file is open
575
576 */
577
578 // -------------- Mapped event builder callbacks ------------------
579
580 void UpdateRuns(const string &fname="")
581 {
582 uint32_t values[5] =
583 {
584 static_cast<uint32_t>(fFiles.size()),
585 0xffffffff,
586 0,
587 fLastOpened,
588 fLastClosed
589 };
590
591 for (vector<DataProcessorImp*>::const_iterator it=fFiles.begin();
592 it!=fFiles.end(); it++)
593 {
594 const DataProcessorImp *file = *it;
595
596 if (file->GetRunId()<values[1])
597 values[1] = file->GetRunId();
598
599 if (file->GetRunId()>values[2])
600 values[2] = file->GetRunId();
601 }
602
603 fMaxRun = values[2];
604
605 vector<char> data(sizeof(values)+fname.size()+1);
606 memcpy(data.data(), values, sizeof(values));
607 strcpy(data.data()+sizeof(values), fname.c_str());
608
609 fDimRuns.Update(data);
610 }
611
612 vector<DataProcessorImp*> fFiles;
613
614 FileHandle_t runOpen(uint32_t runid, RUN_HEAD *h, size_t)
615 {
616 //fMsg.Info(" ==> TODO: Update run configuration in database!");
617
618 map<uint32_t,FAD::RunDescription>::iterator it = fExpectedRuns.begin();
619 while (it!=fExpectedRuns.end())
620 {
621 if (it->first<runid)
622 {
623 ostringstream str;
624 str << "runOpen - Missed run " << it->first << ".";
625 fMsg.Info(str);
626
627 fExpectedRuns.erase(it++);
628 continue;
629 }
630 if (it->first==runid)
631 break;
632 it++;
633 }
634
635 FAD::RunDescription desc;
636
637 if (it==fExpectedRuns.end())
638 {
639 ostringstream str;
640 str << "runOpen - Run " << runid << " wasn't expected (maybe manual triggers)";
641 fMsg.Warn(str);
642 }
643 else
644 {
645 desc = it->second;
646 fExpectedRuns.erase(it);
647 }
648
649 // Check if file already exists...
650 DataProcessorImp *file = 0;
651 switch (fFileFormat)
652 {
653 case FAD::kNone: file = new DataDump(fPath, fNightAsInt, runid, fMsg); break;
654 case FAD::kDebug: file = new DataDebug(fPath, fNightAsInt, runid, fMsg); break;
655 case FAD::kCfitsio: file = new DataWriteFits(fPath, fNightAsInt, runid, fMsg); break;
656 case FAD::kFits: file = new DataWriteFits2(fPath, fNightAsInt, runid, fMsg); break;
657 case FAD::kRaw: file = new DataWriteRaw(fPath, fNightAsInt, runid, fMsg); break;
658 case FAD::kCalib: file = new DataCalib(fPath, fNightAsInt, runid, fDimDrsCalibration, fDimDrsRuns, fMsg); break;
659 }
660
661 try
662 {
663 if (!file->Open(h, desc))
664 return 0;
665 }
666 catch (const exception &e)
667 {
668 fMsg.Error("Exception trying to open file: "+string(e.what()));
669 return 0;
670 }
671
672 fFiles.push_back(file);
673
674 ostringstream str;
675 str << "Opened: " << file->GetFileName() << " (" << file->GetRunId() << ")";
676 fMsg.Info(str);
677
678 fDimWriteStats.FileOpened(file->GetFileName());
679
680 fLastOpened = runid;
681 UpdateRuns(file->GetFileName());
682
683 fNumEvts[kEventId] = 0;
684 fNumEvts[kTriggerId] = 0;
685
686 fNumEvts[kCurrent] = 0;
687 fDimEvents.Update(fNumEvts);
688 // fDimCurrentEvent.Update(uint32_t(0));
689
690 return reinterpret_cast<FileHandle_t>(file);
691 }
692
693 int runWrite(FileHandle_t handler, EVENT *e, size_t /*sz*/)
694 {
695 DataProcessorImp *file = reinterpret_cast<DataProcessorImp*>(handler);
696
697 if (!file->WriteEvt(e))
698 return -1;
699
700 if (file->GetRunId()==fMaxRun)
701 {
702 fNumEvts[kCurrent]++;
703 fNumEvts[kEventId] = e->EventNum;
704 fNumEvts[kTriggerId] = e->TriggerNum;
705 }
706
707 fNumEvts[kTotal]++;
708
709 static Time oldt(boost::date_time::neg_infin);
710 Time newt;
711 if (newt>oldt+boost::posix_time::seconds(1))
712 {
713 fDimEvents.Update(fNumEvts);
714 oldt = newt;
715 }
716
717
718 // ===> SignalEvtWritten(runid);
719 // Send num events written of newest file
720
721 /* close run runId (all all runs if runId=0) */
722 /* return: 0=close scheduled / >0 already closed / <0 does not exist */
723 //CloseRunFile(file->GetRunId(), time(NULL)+2) ;
724
725 return 0;
726 }
727
728 virtual void CloseRun(uint32_t /*runid*/) { }
729
730 int runClose(FileHandle_t handler, RUN_TAIL *tail, size_t)
731 {
732 //fMsg.Info(" ==> TODO: Update run configuration in database!");
733
734 DataProcessorImp *file = reinterpret_cast<DataProcessorImp*>(handler);
735
736 const vector<DataProcessorImp*>::iterator it = find(fFiles.begin(), fFiles.end(), file);
737 if (it==fFiles.end())
738 {
739 ostringstream str;
740 str << "File handler (" << handler << ") requested to close by event builder doesn't exist.";
741 fMsg.Fatal(str);
742 return -1;
743 }
744
745 fFiles.erase(it);
746
747 fLastClosed = file->GetRunId();
748 CloseRun(fLastClosed);
749 UpdateRuns();
750
751 fDimEvents.Update(fNumEvts);
752
753 const bool rc = file->Close(tail);
754 if (!rc)
755 {
756 // Error message
757 }
758
759 ostringstream str;
760 str << "Closed: " << file->GetFileName() << " (" << file->GetRunId() << ")";
761 fMsg.Info(str);
762
763 delete file;
764
765 // ==> SignalRunClose(runid);
766 // Send new num open files
767 // Send empty file-name if no file is open
768
769 return rc ? 0 : -1;
770 }
771
772 ofstream fDumpStream[40];
773
774 void debugStream(int isock, void *buf, int len)
775 {
776 if (!fDebugStream)
777 return;
778
779 const int slot = isock/7;
780 if (slot<0 || slot>39)
781 return;
782
783 if (!fDumpStream[slot].is_open())
784 {
785 ostringstream name;
786 name << "socket_dump-" << setfill('0') << setw(2) << slot << ".bin";
787
788 fDumpStream[slot].open(name.str().c_str(), ios::app);
789 if (!fDumpStream[slot])
790 {
791 ostringstream str;
792 str << "Open file '" << name << "': " << strerror(errno) << " (errno=" << errno << ")";
793 fMsg.Error(str);
794
795 return;
796 }
797
798 fMsg.Message("Opened file '"+name.str()+"' for writing.");
799 }
800
801 fDumpStream[slot].write(reinterpret_cast<const char*>(buf), len);
802 }
803
804 ofstream fDumpRead; // Stream to possibly dump docket events
805
806 void debugRead(int isock, int ibyte, uint32_t event, uint32_t ftmevt, uint32_t runno, int state, uint32_t tsec, uint32_t tusec)
807 {
808 // isock = socketID (0-279)
809 // ibyte = #bytes gelesen
810 // event = eventId (oder 0 wenn noch nicht bekannt)
811 // state : 1=finished reading data
812 // 0=reading data
813 // -1=start reading data (header)
814 // -2=start reading data,
815 // eventId not known yet (too little data)
816 // tsec, tusec = time when reading seconds, microseconds
817 //
818 if (!fDebugRead || ibyte==0)
819 return;
820
821 if (!fDumpRead.is_open())
822 {
823 fDumpRead.open("socket_events.txt", ios::app);
824 if (!fDumpRead)
825 {
826 ostringstream str;
827 str << "Open file 'socket_events.txt': " << strerror(errno) << " (errno=" << errno << ")";
828 fMsg.Error(str);
829
830 return;
831 }
832
833 fMsg.Message("Opened file 'socket_events.txt' for writing.");
834
835 fDumpRead << "# START: " << Time().GetAsStr() << endl;
836 fDumpRead << "# state time_sec time_usec socket slot runno event_id trigger_id bytes_received" << endl;
837 }
838
839 fDumpRead
840 << setw(2) << state << " "
841 << setw(8) << tsec << " "
842 << setw(9) << tusec << " "
843 << setw(3) << isock << " "
844 << setw(2) << isock/7 << " "
845 << runno << " "
846 << event << " "
847 << ftmevt << " "
848 << ibyte << endl;
849 }
850
851 array<uint16_t,2> fVecRoi;
852
853 int eventCheck(uint32_t runNr, PEVNT_HEADER *fadhd, EVENT *event, int /*iboard*/)
854 {
855 /*
856 fadhd[i] ist ein array mit den 40 fad-headers
857 (falls ein board nicht gelesen wurde, ist start_package_flag =0 )
858
859 event ist die Struktur, die auch die write routine erhaelt;
860 darin sind im header die 'soll-werte' fuer z.B. eventID
861 als auch die ADC-Werte (falls Du die brauchst)
862
863 Wenn die routine einen negativen Wert liefert, wird das event
864 geloescht (nicht an die write-routine weitergeleitet [mind. im Prinzip]
865 */
866
867 const array<uint16_t,2> roi = {{ event->Roi, event->RoiTM }};
868
869 if (roi!=fVecRoi)
870 {
871 Update(fDimRoi, roi);
872 fVecRoi = roi;
873 }
874
875 const FAD::EventHeader *beg = reinterpret_cast<FAD::EventHeader*>(fadhd);
876 const FAD::EventHeader *end = reinterpret_cast<FAD::EventHeader*>(fadhd)+40;
877
878 // FIMXE: Compare with target configuration
879
880 for (const FAD::EventHeader *ptr=beg; ptr!=end; ptr++)
881 {
882 // FIXME: Compare with expectations!!!
883 if (ptr->fStartDelimiter==0)
884 {
885 if (ptr==beg)
886 beg++;
887 continue;
888 }
889
890 if (beg->fStatus != ptr->fStatus)
891 {
892 fMsg.Error("Inconsistency in FAD status detected.... closing run.");
893 CloseRunFile(runNr, 0, 0);
894 return -1;
895 }
896
897 if (beg->fRunNumber != ptr->fRunNumber)
898 {
899 fMsg.Error("Inconsistent run number detected.... closing run.");
900 CloseRunFile(runNr, 0, 0);
901 return -1;
902 }
903
904 /*
905 if (beg->fVersion != ptr->fVersion)
906 {
907 Error("Inconsist firmware version detected.... closing run.");
908 CloseRunFile(runNr, 0, 0);
909 break;
910 }
911 */
912 if (beg->fEventCounter != ptr->fEventCounter)
913 {
914 fMsg.Error("Inconsistent FAD event number detected.... closing run.");
915 CloseRunFile(runNr, 0, 0);
916 return -1;
917 }
918
919 if (beg->fTriggerCounter != ptr->fTriggerCounter)
920 {
921 fMsg.Error("Inconsistent FTM trigger number detected.... closing run.");
922 CloseRunFile(runNr, 0, 0);
923 return -1;
924 }
925
926 if (beg->fAdcClockPhaseShift != ptr->fAdcClockPhaseShift)
927 {
928 fMsg.Error("Inconsistent phase shift detected.... closing run.");
929 CloseRunFile(runNr, 0, 0);
930 return -1;
931 }
932
933 if (memcmp(beg->fDac, ptr->fDac, sizeof(beg->fDac)))
934 {
935 fMsg.Error("Inconsistent DAC values detected.... closing run.");
936 CloseRunFile(runNr, 0, 0);
937 return -1;
938 }
939
940 if (beg->fTriggerType != ptr->fTriggerType)
941 {
942 fMsg.Error("Inconsistent trigger type detected.... closing run.");
943 CloseRunFile(runNr, 0, 0);
944 return -1;
945 }
946 }
947
948 // check REFCLK_frequency
949 // check consistency with command configuration
950 // how to log errors?
951 // need gotNewRun/closedRun to know it is finished
952
953 return 0;
954 }
955
956 void SendRawData(PEVNT_HEADER *fadhd, EVENT *event)
957 {
958 // Currently we send any event no matter what its trigger id is...
959 // To be changed.
960 static Time oldt(boost::date_time::neg_infin);
961 Time newt;
962
963 static int skip = 0;
964
965 // FIXME: Only send events if the have newer run-numbers
966 if (newt<oldt+boost::posix_time::milliseconds(skip>0 ? 100 : 1000))
967 return;
968 oldt = newt;
969
970 // Workaround to find a valid header.....
971 const FAD::EventHeader *beg = reinterpret_cast<FAD::EventHeader*>(fadhd);
972 const FAD::EventHeader *end = reinterpret_cast<FAD::EventHeader*>(fadhd)+40;
973
974 // FIMXE: Compare with target configuration
975 const FAD::EventHeader *ptr=beg;
976 for (; ptr!=end; ptr++)
977 {
978 if (ptr->fStartDelimiter!=0)
979 break;
980 }
981 if (ptr==end)
982 return;
983
984
985 vector<char> data(sizeof(EVENT)+event->Roi*sizeof(float)*(1440+160));
986 memcpy(data.data(), event, sizeof(EVENT));
987
988 float *vec = reinterpret_cast<float*>(data.data()+sizeof(EVENT));
989
990 DataCalib::Apply(vec, event->Adc_Data, event->StartPix, event->Roi);
991 DrsCalibrate::RemoveSpikes(vec, event->Roi);
992
993 vector<float> data2(1440*4); // Mean, RMS, Max, Pos
994 const double max = DrsCalibrate::GetPixelStats(data2.data(), vec, event->Roi);
995
996 // Maximum above roughly 5pe
997 if (ptr->IsTriggerPhys() && max<100 && skip<10)
998 {
999 skip++;
1000 return;
1001 }
1002
1003 skip = 0;
1004
1005 fDimRawData.setQuality(ptr->fTriggerType);
1006 fDimRawData.Update(data);
1007
1008 fDimEventData.setQuality(ptr->fTriggerType);
1009 fDimEventData.Update(data2);
1010 }
1011
1012 void SendFeedbackData(PEVNT_HEADER *fadhd, EVENT *event)
1013 {
1014 /*
1015 if (!DataCalib::IsValid())
1016 return;
1017
1018 // Workaround to find a valid header.....
1019 const FAD::EventHeader *beg = reinterpret_cast<FAD::EventHeader*>(fadhd);
1020 const FAD::EventHeader *end = reinterpret_cast<FAD::EventHeader*>(fadhd)+40;
1021
1022 // FIMXE: Compare with target configuration
1023
1024 const FAD::EventHeader *ptr=beg;
1025 for (; ptr<end; ptr++)
1026 {
1027 if (ptr->fStartDelimiter!=0)
1028 break;
1029 }
1030
1031 if (ptr==end)
1032 return;
1033
1034 if (!ptr->HasTriggerLPext() && !ptr->HasTriggerLPint())
1035 return;
1036
1037 vector<float> data(event->Roi*1440);
1038 DataCalib::Apply(data.data(), event->Adc_Data, event->StartPix, event->Roi);
1039
1040 DrsCalibrate::RemoveSpikes(data.data(), event->Roi);
1041
1042 vector<float> data2(1440); // Mean, RMS, Max, Pos, first, last
1043 DrsCalibrate::GetPixelMax(data2.data(), data.data(), event->Roi, 0, event->Roi-1);
1044
1045 fDimFeedbackData.Update(data2);
1046 */
1047 }
1048
1049 int subProcEvt(int threadID, PEVNT_HEADER *fadhd, EVENT *event, int16_t /*iboard*/, void */*buffer*/)
1050 {
1051 switch (threadID)
1052 {
1053 case 0:
1054 SendRawData(fadhd, event);
1055 return 1;
1056 case 1:
1057 SendFeedbackData(fadhd, event);
1058 return 2;
1059 }
1060 return 100;
1061 }
1062
1063
1064 bool IsRunStarted() const
1065 {
1066 const set<uint32_t>::const_iterator it = fIsRunStarted.find(fRunNumber-1);
1067 return it==fIsRunStarted.end();// ? true : it->second.started;
1068 }
1069
1070 uint32_t GetRunNumber() const
1071 {
1072 return fRunNumber;
1073 }
1074
1075 bool IsRunFileOpen()
1076 {
1077 return fLastOpened==fRunNumber-1;
1078 }
1079
1080 bool IncreaseRunNumber(uint32_t run)
1081 {
1082 if (!InitRunNumber())
1083 return false;
1084
1085 if (run<fRunNumber)
1086 {
1087 ostringstream msg;
1088 msg <<
1089 "Run number " << run << " smaller than next available "
1090 "run number " << fRunNumber << " in " << fPath << " [" << fNightAsInt << "]";
1091 fMsg.Error(msg);
1092 return false;
1093 }
1094
1095 fRunNumber = run;
1096
1097 return true;
1098 }
1099
1100 void gotNewRun(uint32_t runnr, PEVNT_HEADER */*headers*/)
1101 {
1102 // This function is called even when writing is switched off
1103 set<uint32_t>::iterator it = fIsRunStarted.begin();
1104 while (it!=fIsRunStarted.end())
1105 {
1106 if (*it<runnr)
1107 {
1108 ostringstream str;
1109 str << "gotNewRun - Missed run " << *it << ".";
1110 fMsg.Info(str);
1111
1112 fIsRunStarted.erase(it++);
1113 continue;
1114 }
1115 if (*it==runnr)
1116 break;
1117 it++;
1118 }
1119 if (it==fIsRunStarted.end())
1120 {
1121 ostringstream str;
1122 str << "gotNewRun - Not waiting for run " << runnr << ".";
1123 fMsg.Warn(str);
1124 return;
1125 }
1126
1127 map<uint32_t,FAD::RunDescription>::iterator i2 = fExpectedRuns.find(runnr);
1128 if (i2==fExpectedRuns.end())
1129 {
1130 ostringstream str;
1131 str << "gotNewRun - Run " << runnr << " wasn't expected.";
1132 fMsg.Warn(str);
1133 return;
1134 }
1135
1136 CloseRunFile(runnr, time(NULL)+i2->second.maxtime, i2->second.maxevt);
1137 // return: 0=close scheduled / >0 already closed / <0 does not exist
1138
1139 // FIXME: Move configuration from expected runs to runs which will soon
1140 // be opened/closed
1141
1142 fIsRunStarted.erase(it);
1143 }
1144
1145 map<boost::thread::id, string> fLastMessage;
1146
1147 void factOut(int severity, int err, const char *message)
1148 {
1149 if (!fDebugLog && severity==99)
1150 return;
1151
1152 ostringstream str;
1153 //str << boost::this_thread::get_id() << " ";
1154 str << "EventBuilder(";
1155 if (err<0)
1156 str << "---";
1157 else
1158 str << err;
1159 str << "): " << message;
1160
1161 string &old = fLastMessage[boost::this_thread::get_id()];
1162
1163 if (str.str()==old)
1164 return;
1165 old = str.str();
1166
1167 fMsg.Update(str, severity);
1168 }
1169
1170/*
1171 void factStat(int64_t *stat, int len)
1172 {
1173 if (len!=7)
1174 {
1175 fMsg.Warn("factStat received unknown number of values.");
1176 return;
1177 }
1178
1179 vector<int64_t> data(1, g_maxMem);
1180 data.insert(data.end(), stat, stat+len);
1181
1182 static vector<int64_t> last(8);
1183 if (data==last)
1184 return;
1185 last = data;
1186
1187 fDimStatistics.Update(data);
1188
1189 // len ist die Laenge des arrays.
1190 // array[4] enthaelt wieviele bytes im Buffer aktuell belegt sind; daran
1191 // kannst Du pruefen, ob die 100MB voll sind ....
1192
1193 ostringstream str;
1194 str
1195 << "Wait=" << stat[0] << " "
1196 << "Skip=" << stat[1] << " "
1197 << "Del=" << stat[2] << " "
1198 << "Tot=" << stat[3] << " "
1199 << "Mem=" << stat[4] << "/" << g_maxMem << " "
1200 << "Read=" << stat[5] << " "
1201 << "Conn=" << stat[6];
1202
1203 fMsg.Info(str);
1204 }
1205 */
1206
1207 void factStat(const EVT_STAT &stat)
1208 {
1209 fDimStatistics2.Update(stat);
1210 }
1211
1212 void factStat(const GUI_STAT &stat)
1213 {
1214 fDimStatistics1.Update(stat);
1215 }
1216
1217
1218 array<FAD::EventHeader, 40> fVecHeader;
1219
1220 template<typename T, class S>
1221 array<T, 42> Compare(const S *vec, const T *t)
1222 {
1223 const int offset = reinterpret_cast<const char *>(t) - reinterpret_cast<const char *>(vec);
1224
1225 const T *min = NULL;
1226 const T *val = NULL;
1227 const T *max = NULL;
1228
1229 array<T, 42> arr;
1230
1231 // bool rc = true;
1232 for (int i=0; i<40; i++)
1233 {
1234 const char *base = reinterpret_cast<const char*>(vec+i);
1235 const T *ref = reinterpret_cast<const T*>(base+offset);
1236
1237 arr[i] = *ref;
1238
1239 if (gi_NumConnect[i]!=7)
1240 {
1241 arr[i] = 0;
1242 continue;
1243 }
1244
1245 if (!val)
1246 {
1247 min = ref;
1248 val = ref;
1249 max = ref;
1250 }
1251
1252 if (*ref<*min)
1253 min = ref;
1254
1255 if (*ref>*max)
1256 max = ref;
1257
1258 // if (*val!=*ref)
1259 // rc = false;
1260 }
1261
1262 arr[40] = val ? *min : 1;
1263 arr[41] = val ? *max : 0;
1264
1265 return arr;
1266 }
1267
1268 template<typename T>
1269 array<T, 42> CompareBits(const FAD::EventHeader *h, const T *t)
1270 {
1271 const int offset = reinterpret_cast<const char *>(t) - reinterpret_cast<const char *>(h);
1272
1273 T val = 0;
1274 T rc = 0;
1275
1276 array<T, 42> vec;
1277
1278 bool first = true;
1279
1280 for (int i=0; i<40; i++)
1281 {
1282 const char *base = reinterpret_cast<const char*>(&fVecHeader[i]);
1283 const T *ref = reinterpret_cast<const T*>(base+offset);
1284
1285 vec[i+2] = *ref;
1286
1287 if (gi_NumConnect[i]!=7)
1288 {
1289 vec[i+2] = 0;
1290 continue;
1291 }
1292
1293 if (first)
1294 {
1295 first = false;
1296 val = *ref;
1297 rc = 0;
1298 }
1299
1300 rc |= val^*ref;
1301 }
1302
1303 vec[0] = rc;
1304 vec[1] = val;
1305
1306 return vec;
1307 }
1308
1309 template<typename T, size_t N>
1310 void Update(DimDescribedService &svc, const array<T, N> &data, int n=N)
1311 {
1312// svc.setQuality(vec[40]<=vec[41]);
1313 svc.setData(const_cast<T*>(data.data()), sizeof(T)*n);
1314 svc.Update();
1315 }
1316
1317 template<typename T>
1318 void Print(const char *name, const pair<bool,array<T, 43>> &data)
1319 {
1320 cout << name << "|" << data.first << "|" << data.second[1] << "|" << data.second[0] << "<x<" << data.second[1] << ":";
1321 for (int i=0; i<40;i++)
1322 cout << " " << data.second[i+3];
1323 cout << endl;
1324 }
1325
1326 vector<uint> fNumConnected;
1327
1328 void debugHead(int /*socket*/, const FAD::EventHeader &h)
1329 {
1330 const uint16_t id = h.Id();
1331 if (id>39)
1332 return;
1333
1334 if (fNumConnected.size()!=40)
1335 fNumConnected.resize(40);
1336
1337 const vector<uint> con(gi_NumConnect, gi_NumConnect+40);
1338
1339 const bool changed = con!=fNumConnected || !IsThreadRunning();
1340
1341 fNumConnected = con;
1342
1343 const FAD::EventHeader old = fVecHeader[id];
1344 fVecHeader[id] = h;
1345
1346 if (old.fVersion != h.fVersion || changed)
1347 {
1348 const array<uint16_t,42> ver = Compare(&fVecHeader[0], &fVecHeader[0].fVersion);
1349
1350 array<float,42> data;
1351 for (int i=0; i<42; i++)
1352 {
1353 ostringstream str;
1354 str << (ver[i]>>8) << '.' << (ver[i]&0xff);
1355 data[i] = stof(str.str());
1356 }
1357 Update(fDimFwVersion, data);
1358 }
1359
1360 if (old.fRunNumber != h.fRunNumber || changed)
1361 {
1362 const array<uint32_t,42> run = Compare(&fVecHeader[0], &fVecHeader[0].fRunNumber);
1363 fDimRunNumber.Update(run);
1364 }
1365
1366 if (old.fTriggerGeneratorPrescaler != h.fTriggerGeneratorPrescaler || changed)
1367 {
1368 const array<uint16_t,42> pre = Compare(&fVecHeader[0], &fVecHeader[0].fTriggerGeneratorPrescaler);
1369 fDimPrescaler.Update(pre);
1370 }
1371
1372 if (old.fDNA != h.fDNA || changed)
1373 {
1374 const array<uint64_t,42> dna = Compare(&fVecHeader[0], &fVecHeader[0].fDNA);
1375 Update(fDimDNA, dna, 40);
1376 }
1377
1378 if (old.fStatus != h.fStatus || changed)
1379 {
1380 const array<uint16_t,42> sts = CompareBits(&fVecHeader[0], &fVecHeader[0].fStatus);
1381 Update(fDimStatus, sts);
1382 }
1383
1384 if (memcmp(old.fDac, h.fDac, sizeof(h.fDac)) || changed)
1385 {
1386 array<uint16_t, FAD::kNumDac*42> dacs;
1387
1388 for (int i=0; i<FAD::kNumDac; i++)
1389 {
1390 const array<uint16_t, 42> dac = Compare(&fVecHeader[0], &fVecHeader[0].fDac[i]);
1391 memcpy(&dacs[i*42], &dac[0], sizeof(uint16_t)*42);
1392 }
1393
1394 Update(fDimDac, dacs);
1395 }
1396
1397 // -----------
1398
1399 static Time oldt(boost::date_time::neg_infin);
1400 Time newt;
1401
1402 if (newt>oldt+boost::posix_time::seconds(1))
1403 {
1404 oldt = newt;
1405
1406 // --- RefClock
1407
1408 const array<uint32_t,42> clk = Compare(&fVecHeader[0], &fVecHeader[0].fFreqRefClock);
1409 Update(fDimRefClock, clk);
1410
1411 // --- Temperatures
1412
1413 const array<int16_t,42> tmp[4] =
1414 {
1415 Compare(&fVecHeader[0], &fVecHeader[0].fTempDrs[0]), // 0-39:val, 40:min, 41:max
1416 Compare(&fVecHeader[0], &fVecHeader[0].fTempDrs[1]), // 0-39:val, 40:min, 41:max
1417 Compare(&fVecHeader[0], &fVecHeader[0].fTempDrs[2]), // 0-39:val, 40:min, 41:max
1418 Compare(&fVecHeader[0], &fVecHeader[0].fTempDrs[3]) // 0-39:val, 40:min, 41:max
1419 };
1420
1421 vector<int16_t> data;
1422 data.reserve(82);
1423 data.push_back(tmp[0][40]); // min: 0
1424 data.insert(data.end(), tmp[0].data(), tmp[0].data()+40); // val: 1-40
1425 data.push_back(tmp[0][41]); // max: 41
1426 data.insert(data.end(), tmp[0].data(), tmp[0].data()+40); // val: 42-81
1427
1428 for (int j=1; j<=3; j++)
1429 {
1430 const array<int16_t,42> &ref = tmp[j];
1431
1432 // Gloabl min
1433 if (ref[40]<data[0]) // 40=min
1434 data[0] = ref[40];
1435
1436 // Global max
1437 if (ref[41]>data[41]) // 41=max
1438 data[41] = ref[41];
1439
1440 for (int i=0; i<40; i++)
1441 {
1442 // min per board
1443 if (ref[i]<data[i+1]) // data: 1-40
1444 data[i+1] = ref[i]; // ref: 0-39
1445
1446 // max per board
1447 if (ref[i]>data[i+42]) // data: 42-81
1448 data[i+42] = ref[i]; // ref: 0-39
1449 }
1450
1451
1452 }
1453
1454 vector<float> deg(82); // 0: global min, 1-40: min
1455 for (int i=0; i<82; i++) // 41: global max, 42-81: max
1456 deg[i] = data[i]/16.;
1457 fDimTemperature.Update(deg);
1458 }
1459 }
1460};
1461
1462EventBuilderWrapper *EventBuilderWrapper::This = 0;
1463
1464// ----------- Event builder callbacks implementation ---------------
1465extern "C"
1466{
1467 FileHandle_t runOpen(uint32_t irun, RUN_HEAD *runhd, size_t len)
1468 {
1469 return EventBuilderWrapper::This->runOpen(irun, runhd, len);
1470 }
1471
1472 int runWrite(FileHandle_t fileId, EVENT *event, size_t len)
1473 {
1474 return EventBuilderWrapper::This->runWrite(fileId, event, len);
1475 }
1476
1477 int runClose(FileHandle_t fileId, RUN_TAIL *runth, size_t len)
1478 {
1479 return EventBuilderWrapper::This->runClose(fileId, runth, len);
1480 }
1481
1482 // -----
1483
1484 //void *runStart(uint32_t /*irun*/, RUN_HEAD */*runhd*/, size_t /*len*/)
1485 //{
1486 // return NULL;
1487 //}
1488
1489 int subProcEvt(int threadID, PEVNT_HEADER *fadhd, EVENT *event, int16_t mboard, void *runPtr)
1490 {
1491 return EventBuilderWrapper::This->subProcEvt(threadID, fadhd, event, mboard, runPtr);
1492 }
1493
1494 int runEnd(uint32_t, void */*runPtr*/)
1495 {
1496 return 0;
1497 }
1498
1499 // -----
1500
1501 int eventCheck(uint32_t runNr, PEVNT_HEADER *fadhd, EVENT *event, int mboard)
1502 {
1503 return EventBuilderWrapper::This->eventCheck(runNr, fadhd, event, mboard);
1504 }
1505
1506 void gotNewRun(uint32_t runnr, PEVNT_HEADER *headers)
1507 {
1508 return EventBuilderWrapper::This->gotNewRun(runnr, headers);
1509 }
1510
1511 // -----
1512
1513 void factOut(int severity, int err, const char *message)
1514 {
1515 EventBuilderWrapper::This->factOut(severity, err, message);
1516 }
1517
1518 void factStat(GUI_STAT stat)
1519 {
1520 EventBuilderWrapper::This->factStat(stat);
1521 }
1522
1523 void factStatNew(EVT_STAT stat)
1524 {
1525 EventBuilderWrapper::This->factStat(stat);
1526 }
1527
1528 // ------
1529
1530 void debugHead(int socket, int/*board*/, void *buf)
1531 {
1532 const FAD::EventHeader &h = *reinterpret_cast<FAD::EventHeader*>(buf);
1533 EventBuilderWrapper::This->debugHead(socket, h);
1534 }
1535
1536 void debugStream(int isock, void *buf, int len)
1537 {
1538 return EventBuilderWrapper::This->debugStream(isock, buf, len);
1539 }
1540
1541 void debugRead(int isock, int ibyte, int32_t event, int32_t ftmevt, int32_t runno, int state, uint32_t tsec, uint32_t tusec)
1542 {
1543 EventBuilderWrapper::This->debugRead(isock, ibyte, event, ftmevt, runno, state, tsec, tusec);
1544 }
1545}
1546
1547#endif
Note: See TracBrowser for help on using the repository browser.