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

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