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

Last change on this file since 18630 was 18630, checked in by tbretz, 3 years ago
Distribute run and event number with the EVENT_DATA service
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);
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
1045            const float max = DrsCalibrate::GetPixelStats(edat.data, vec.data(), roi, 15, 5);
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.