source: trunk/FACT++/gui/FactGui.h @ 19314

Last change on this file since 19314 was 18983, checked in by tbretz, 15 months ago
That's a dangerous way to write the conditional - fixed.
File size: 135.0 KB
Line 
1#ifndef FACT_FactGui
2#define FACT_FactGui
3
4#include "MainWindow.h"
5
6#include <iomanip>
7#include <valarray>
8
9#include <boost/regex.hpp>
10
11#include <QTimer>
12#include <QtSql/QSqlError>
13#include <QtSql/QSqlTableModel>
14#include <QStandardItemModel>
15
16#include "CheckBoxDelegate.h"
17
18#include "src/Dim.h"
19#include "src/Converter.h"
20#include "src/Configuration.h"
21#include "src/DimNetwork.h"
22#include "src/tools.h"
23#include "src/DimData.h"
24#include "externals/PixelMap.h"
25
26#ifdef HAVE_ROOT
27#include "TROOT.h"
28#include "TSystem.h"
29#include "TGraph.h"
30#include "TGraphErrors.h"
31#include "TH2.h"
32#include "TBox.h"
33#include "TStyle.h"
34#include "TMarker.h"
35#include "TColor.h"
36#endif
37
38#include "QCameraWidget.h"
39
40#include "src/FAD.h"
41#include "src/HeadersMCP.h"
42#include "src/HeadersFTM.h"
43#include "src/HeadersFAD.h"
44#include "src/HeadersFSC.h"
45#include "src/HeadersBIAS.h"
46#include "src/HeadersDrive.h"
47#include "src/HeadersFeedback.h"
48#include "src/HeadersRateScan.h"
49#include "src/HeadersRateControl.h"
50#include "src/HeadersMagicWeather.h"
51
52using namespace std;
53
54// #########################################################################
55
56class FactGui : public MainWindow, public DimNetwork, public DimInfoHandler
57{
58private:
59    class FunctionEvent : public QEvent
60    {
61    public:
62        function<void(const QEvent &)> fFunction;
63
64        FunctionEvent(const function<void(const QEvent &)> &f)
65            : QEvent((QEvent::Type)QEvent::registerEventType()),
66            fFunction(f) { }
67
68        bool Exec() { fFunction(*this); return true; }
69    };
70
71    valarray<int8_t> fFtuStatus;
72
73    PixelMap fPixelMap;
74
75    //vector<int>  fPixelMapHW; // Software -> Hardware
76    vector<int> fPatchMapHW; // Software -> Hardware
77
78    bool fInChoosePatchTH;   // FIXME. Find a better solution
79    bool fInChooseBiasHv;    // FIXME. Find a better solution
80    bool fInChooseBiasCam;   // FIXME. Find a better solution
81
82    DimStampedInfo fDimDNS;
83
84    DimStampedInfo fDimLoggerStats;
85    DimStampedInfo fDimLoggerFilenameNight;
86    DimStampedInfo fDimLoggerFilenameRun;
87    DimStampedInfo fDimLoggerNumSubs;
88
89    DimStampedInfo fDimFtmPassport;
90    DimStampedInfo fDimFtmTriggerRates;
91    DimStampedInfo fDimFtmError;
92    DimStampedInfo fDimFtmFtuList;
93    DimStampedInfo fDimFtmStaticData;
94    DimStampedInfo fDimFtmDynamicData;
95    DimStampedInfo fDimFtmCounter;
96
97    DimStampedInfo fDimFadWriteStats;
98    DimStampedInfo fDimFadStartRun;
99    DimStampedInfo fDimFadRuns;
100    DimStampedInfo fDimFadEvents;
101    DimStampedInfo fDimFadRawData;
102    DimStampedInfo fDimFadEventData;
103    DimStampedInfo fDimFadConnections;
104    DimStampedInfo fDimFadFwVersion;
105    DimStampedInfo fDimFadRunNumber;
106    DimStampedInfo fDimFadDNA;
107    DimStampedInfo fDimFadTemperature;
108    DimStampedInfo fDimFadPrescaler;
109    DimStampedInfo fDimFadRefClock;
110    DimStampedInfo fDimFadRoi;
111    DimStampedInfo fDimFadDac;
112    DimStampedInfo fDimFadDrsCalibration;
113    DimStampedInfo fDimFadStatus;
114    DimStampedInfo fDimFadStatistics1;
115    //DimStampedInfo fDimFadStatistics2;
116    DimStampedInfo fDimFadFileFormat;
117
118    DimStampedInfo fDimFscTemp;
119    DimStampedInfo fDimFscVolt;
120    DimStampedInfo fDimFscCurrent;
121    DimStampedInfo fDimFscHumidity;
122
123    DimStampedInfo fDimFeedbackCalibration;
124    DimStampedInfo fDimFeedbackCalibrated;
125
126    DimStampedInfo fDimBiasNominal;
127    DimStampedInfo fDimBiasVolt;
128    DimStampedInfo fDimBiasDac;
129    DimStampedInfo fDimBiasCurrent;
130
131    DimStampedInfo fDimRateScan;
132
133    DimStampedInfo fDimMagicWeather;
134
135    map<string, DimInfo*> fServices;
136
137    // ========================== LED Colors ================================
138
139    enum LedColor_t
140    {
141        kLedRed,
142        kLedGreen,
143        kLedGreenWarn,
144        kLedGreenCheck,
145        kLedGreenBar,
146        kLedYellow,
147        kLedOrange,
148        kLedGray,
149        kLedWarnBorder,
150        kLedWarn,
151        kLedWarnTriangleBorder,
152        kLedWarnTriangle,
153        kLedInProgress,
154    };
155
156    void SetLedColor(QPushButton *button, LedColor_t col, const Time &t)
157    {
158        switch (col)
159        {
160        case kLedRed:
161            button->setIcon(QIcon(":/Resources/icons/red circle 1.png"));
162            break;
163
164        case kLedGreen:
165            button->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
166            break;
167
168        case kLedGreenBar:
169            button->setIcon(QIcon(":/Resources/icons/green bar.png"));
170            break;
171
172        case kLedGreenWarn:
173            button->setIcon(QIcon(":/Resources/icons/green warn.png"));
174            break;
175
176        case kLedGreenCheck:
177            button->setIcon(QIcon(":/Resources/icons/green check.png"));
178            break;
179
180        case kLedYellow:
181            button->setIcon(QIcon(":/Resources/icons/yellow circle 1.png"));
182            break;
183
184        case kLedOrange:
185            button->setIcon(QIcon(":/Resources/icons/orange circle 1.png"));
186            break;
187
188        case kLedGray:
189            button->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
190            break;
191
192        case kLedWarnBorder:
193            button->setIcon(QIcon(":/Resources/icons/warning 1.png"));
194            break;
195
196        case kLedWarn:
197            button->setIcon(QIcon(":/Resources/icons/warning 2.png"));
198            break;
199
200        case kLedWarnTriangle:
201            button->setIcon(QIcon(":/Resources/icons/warning 3.png"));
202            break;
203
204        case kLedWarnTriangleBorder:
205            button->setIcon(QIcon(":/Resources/icons/warning 4.png"));
206            break;
207
208        case kLedInProgress:
209            button->setIcon(QIcon(":/Resources/icons/in progress.png"));
210            break;
211
212        }
213
214        //button->setToolTip("Last change: "+QDateTime::currentDateTimeUtc().toString()+" UTC");
215        button->setToolTip(("Last change: "+t.GetAsStr()+" (UTC)").c_str());
216    }
217
218    // ===================== Services and Commands ==========================
219
220    QStandardItem *AddServiceItem(const string &server, const string &service, bool iscmd)
221    {
222        QListView *servers     = iscmd ? fDimCmdServers     : fDimSvcServers;
223        QListView *services    = iscmd ? fDimCmdCommands    : fDimSvcServices;
224        QListView *description = iscmd ? fDimCmdDescription : fDimSvcDescription;
225
226        QStandardItemModel *m = dynamic_cast<QStandardItemModel*>(servers->model());
227        if (!m)
228        {
229            m = new QStandardItemModel(this);
230            servers->setModel(m);
231            services->setModel(m);
232            description->setModel(m);
233        }
234
235        QList<QStandardItem*> l = m->findItems(server.c_str());
236
237        if (l.size()>1)
238        {
239            cout << "hae" << endl;
240            return 0;
241        }
242
243        QStandardItem *col = l.size()==0 ? NULL : l[0];
244
245        if (!col)
246        {
247            col = new QStandardItem(server.c_str());
248            m->appendRow(col);
249
250            if (!services->rootIndex().isValid())
251            {
252                services->setRootIndex(col->index());
253                servers->setCurrentIndex(col->index());
254            }
255        }
256
257        QStandardItem *item = 0;
258        for (int i=0; i<col->rowCount(); i++)
259        {
260            QStandardItem *coli = col->child(i);
261            if (coli->text().toStdString()==service)
262                return coli;
263        }
264
265        item = new QStandardItem(service.c_str());
266        col->appendRow(item);
267        col->sortChildren(0);
268
269        if (!description->rootIndex().isValid())
270        {
271            description->setRootIndex(item->index());
272            services->setCurrentIndex(item->index());
273        }
274
275        if (!iscmd)
276            item->setCheckable(true);
277
278        return item;
279    }
280
281    void AddDescription(QStandardItem *item, const vector<Description> &vec)
282    {
283        if (!item)
284            return;
285        if (vec.size()==0)
286            return;
287
288        item->setToolTip(vec[0].comment.c_str());
289
290        const string str = Description::GetHtmlDescription(vec);
291
292        QStandardItem *desc = new QStandardItem(str.c_str());
293        desc->setSelectable(false);
294        item->setChild(0, 0, desc);
295    }
296
297    void AddServer(const string &s)
298    {
299        DimNetwork::AddServer(s);
300
301        const State state = GetState(s, GetCurrentState(s));
302
303        QApplication::postEvent(this,
304           new FunctionEvent(bind(&FactGui::handleAddServer, this, s, state)));
305    }
306
307    void AddService(const string &server, const string &service, const string &fmt, bool iscmd)
308    {
309        const vector<Description> v = GetDescription(server, service);
310
311        QApplication::postEvent(this,
312           new FunctionEvent(bind(&FactGui::handleAddService, this, server, service, fmt, iscmd, v)));
313    }
314
315    void RemoveService(string server, string service, bool iscmd)
316    {
317        UnsubscribeService(server+'/'+service, true);
318
319        QApplication::postEvent(this,
320           new FunctionEvent(bind(&FactGui::handleRemoveService, this, server, service, iscmd)));
321    }
322
323    void RemoveAllServices(const string &server)
324    {
325        UnsubscribeAllServices(server);
326
327        QApplication::postEvent(this,
328           new FunctionEvent(bind(&FactGui::handleRemoveAllServices, this, server)));
329    }
330
331    void AddDescription(const string &server, const string &service, const vector<Description> &vec)
332    {
333        const bool iscmd = IsCommand(server, service)==true;
334
335        QApplication::postEvent(this,
336           new FunctionEvent(bind(&FactGui::handleAddDescription, this, server, service, vec, iscmd)));
337    }
338
339    // ======================================================================
340
341    void handleAddServer(const string &server, const State &state)
342    {
343        handleStateChanged(Time(), server, state);
344    }
345
346    void handleAddService(const string &server, const string &service, const string &/*fmt*/, bool iscmd, const vector<Description> &vec)
347    {
348        QStandardItem *item = AddServiceItem(server, service, iscmd);
349        AddDescription(item, vec);
350    }
351
352    void handleRemoveService(const string &server, const string &service, bool iscmd)
353    {
354        QListView *servers = iscmd ? fDimCmdServers : fDimSvcServers;
355
356        QStandardItemModel *m = dynamic_cast<QStandardItemModel*>(servers->model());
357        if (!m)
358            return;
359
360        QList<QStandardItem*> l = m->findItems(server.c_str());
361        if (l.size()!=1)
362            return;
363
364        for (int i=0; i<l[0]->rowCount(); i++)
365        {
366            QStandardItem *row = l[0]->child(i);
367            if (row->text().toStdString()==service)
368            {
369                l[0]->removeRow(row->index().row());
370                return;
371            }
372        }
373    }
374
375    void handleRemoveAllServices(const string &server)
376    {
377        handleStateChanged(Time(), server, State(-2, "Offline", "No connection via DIM."));
378
379        QStandardItemModel *m = 0;
380        if ((m=dynamic_cast<QStandardItemModel*>(fDimCmdServers->model())))
381        {
382            QList<QStandardItem*> l = m->findItems(server.c_str());
383            if (l.size()==1)
384                m->removeRow(l[0]->index().row());
385        }
386
387        if ((m = dynamic_cast<QStandardItemModel*>(fDimSvcServers->model())))
388        {
389            QList<QStandardItem*> l = m->findItems(server.c_str());
390            if (l.size()==1)
391                m->removeRow(l[0]->index().row());
392        }
393    }
394
395    void handleAddDescription(const string &server, const string &service, const vector<Description> &vec, bool iscmd)
396    {
397        QStandardItem *item = AddServiceItem(server, service, iscmd);
398        AddDescription(item, vec);
399    }
400
401    // ======================================================================
402
403    void SubscribeService(const string &service)
404    {
405        if (fServices.find(service)!=fServices.end())
406        {
407            cerr << "ERROR - We are already subscribed to " << service << endl;
408            return;
409        }
410
411        fServices[service] = new DimStampedInfo(service.c_str(), (void*)NULL, 0, this);
412    }
413
414    void UnsubscribeService(const string &service, bool allow_unsubscribed=false)
415    {
416        const map<string,DimInfo*>::iterator i=fServices.find(service);
417
418        if (i==fServices.end())
419        {
420            if (!allow_unsubscribed)
421                cerr << "ERROR - We are not subscribed to " << service << endl;
422            return;
423        }
424
425        delete i->second;
426
427        fServices.erase(i);
428    }
429
430    void UnsubscribeAllServices(const string &server)
431    {
432        for (map<string,DimInfo*>::iterator i=fServices.begin();
433             i!=fServices.end(); i++)
434            if (i->first.substr(0, server.length()+1)==server+'/')
435            {
436                delete i->second;
437                fServices.erase(i);
438            }
439    }
440
441    // ======================= DNS ==========================================
442
443    uint32_t fDimVersion;
444
445    void UpdateGlobalStatus()
446    {
447        ostringstream dns;
448        dns << (fDimVersion==0?"No connection":"Connection");
449        dns << " to DIM DNS (" << getenv("DIM_DNS_NODE") << ")";
450        dns << (fDimVersion==0?".":" established");
451
452        ostringstream str;
453        str << "V" << fDimVersion/100 << 'r' << fDimVersion%100;
454
455        LedColor_t led = kLedGreen;
456        if (fDimVersion>0)
457        {
458            dns << fixed << setprecision(1) << right;
459            if (fFreeSpaceLogger!=UINT64_MAX)
460                dns << "<pre> * Data logger:   " << setw(7) << fFreeSpaceLogger*1e-7 << " GB</pre>";
461            if (fFreeSpaceData!=UINT64_MAX)
462                dns << "<pre> * Event Builder: " << setw(7) << fFreeSpaceData*1e-7 << " GB</pre>";
463
464            if (fFreeSpaceLogger<500000000 || fFreeSpaceData<500000000)
465                led = kLedGreenWarn;
466            if (fFreeSpaceLogger<200000000 || fFreeSpaceData<200000000)
467                led = kLedWarnTriangleBorder;
468
469            if (led!=kLedGreen)
470                str << " (Disk space!)";
471        }
472
473        fStatusDNSLabel->setToolTip(dns.str().c_str());
474
475        SetLedColor(fStatusDNSLed, fDimVersion==0 ? kLedRed : led, Time());
476
477        fStatusDNSLabel->setText(fDimVersion==0?"Offline":str.str().c_str());
478    }
479
480    void handleDimDNS(const DimData &d)
481    {
482        fDimVersion = d.size()!=4 ? 0 : d.get<uint32_t>();
483
484        UpdateGlobalStatus();
485
486        fShutdown->setEnabled(fDimVersion!=0);
487        fShutdownAll->setEnabled(fDimVersion!=0);
488    }
489
490
491    // ======================= Logger =======================================
492
493    uint64_t fFreeSpaceLogger;
494
495    void handleLoggerStats(const DimData &d)
496    {
497        const bool connected = d.size()!=0;
498
499        fLoggerET->setEnabled(connected);
500        fLoggerRate->setEnabled(connected);
501        fLoggerWritten->setEnabled(connected);
502        fLoggerFreeSpace->setEnabled(connected);
503        fLoggerSpaceLeft->setEnabled(connected);
504
505        fFreeSpaceLogger = UINT64_MAX;
506        UpdateGlobalStatus();
507
508        if (!connected)
509            return;
510
511        const uint64_t *vals = d.ptr<uint64_t>();
512
513        const size_t space   = vals[0];
514        const size_t written = vals[1];
515        const size_t rate    = float(vals[2])/vals[3];
516
517        fFreeSpaceLogger = space;
518        UpdateGlobalStatus();
519
520        fLoggerFreeSpace->setSuffix(" MB");
521        fLoggerFreeSpace->setDecimals(0);
522        fLoggerFreeSpace->setValue(space*1e-6);
523
524        if (space>   1000000)  // > 1GB
525        {
526            fLoggerFreeSpace->setSuffix(" GB");
527            fLoggerFreeSpace->setDecimals(2);
528            fLoggerFreeSpace->setValue(space*1e-9);
529        }
530        if (space>=  3000000)  // >= 3GB
531        {
532            fLoggerFreeSpace->setSuffix(" GB");
533            fLoggerFreeSpace->setDecimals(1);
534            fLoggerFreeSpace->setValue(space*1e-9);
535        }
536        if (space>=100000000)  // >= 100GB
537        {
538            fLoggerFreeSpace->setSuffix(" GB");
539            fLoggerFreeSpace->setDecimals(0);
540            fLoggerFreeSpace->setValue(space*1e-9);
541        }
542
543        fLoggerET->setTime(QTime().addSecs(rate>0?space/rate:0));
544        fLoggerRate->setValue(rate*1e-3); // kB/s
545        fLoggerWritten->setValue(written*1e-6);
546
547        fLoggerRate->setSuffix(" kB/s");
548        fLoggerRate->setDecimals(2);
549        fLoggerRate->setValue(rate);
550        if (rate>   2)  // > 2kB/s
551        {
552            fLoggerRate->setSuffix(" kB/s");
553            fLoggerRate->setDecimals(1);
554            fLoggerRate->setValue(rate);
555        }
556        if (rate>=100)  // >100kB/s
557        {
558            fLoggerRate->setSuffix(" kB/s");
559            fLoggerRate->setDecimals(0);
560            fLoggerRate->setValue(rate);
561        }
562        if (rate>=1000)  // >100kB/s
563        {
564            fLoggerRate->setSuffix(" MB/s");
565            fLoggerRate->setDecimals(2);
566            fLoggerRate->setValue(rate*1e-3);
567        }
568        if (rate>=10000)  // >1MB/s
569        {
570            fLoggerRate->setSuffix(" MB/s");
571            fLoggerRate->setDecimals(1);
572            fLoggerRate->setValue(rate*1e-3);
573        }
574        if (rate>=100000)  // >10MB/s
575        {
576            fLoggerRate->setSuffix(" MB/s");
577            fLoggerRate->setDecimals(0);
578            fLoggerRate->setValue(rate*1e-3);
579        }
580
581        if (space/1000000>static_cast<size_t>(fLoggerSpaceLeft->maximum()))
582            fLoggerSpaceLeft->setValue(fLoggerSpaceLeft->maximum());  // GB
583        else
584            fLoggerSpaceLeft->setValue(space/1000000);  // MB
585    }
586
587    void handleLoggerFilenameNight(const DimData &d)
588    {
589        const bool connected = d.size()!=0;
590
591        fLoggerFilenameNight->setEnabled(connected);
592        if (!connected)
593            return;
594
595        fLoggerFilenameNight->setText(d.c_str()+4);
596
597        const uint32_t files = d.get<uint32_t>();
598
599        SetLedColor(fLoggerLedLog,  files&1 ? kLedGreen : kLedGray, d.time);
600        SetLedColor(fLoggerLedRep,  files&2 ? kLedGreen : kLedGray, d.time);
601        SetLedColor(fLoggerLedFits, files&4 ? kLedGreen : kLedGray, d.time);
602    }
603
604    void handleLoggerFilenameRun(const DimData &d)
605    {
606        const bool connected = d.size()!=0;
607
608        fLoggerFilenameRun->setEnabled(connected);
609        if (!connected)
610            return;
611
612        fLoggerFilenameRun->setText(d.c_str()+4);
613
614        const uint32_t files = d.get<uint32_t>();
615
616        SetLedColor(fLoggerLedLog,  files&1 ? kLedGreen : kLedGray, d.time);
617        SetLedColor(fLoggerLedRep,  files&2 ? kLedGreen : kLedGray, d.time);
618        SetLedColor(fLoggerLedFits, files&4 ? kLedGreen : kLedGray, d.time);
619    }
620
621    void handleLoggerNumSubs(const DimData &d)
622    {
623        const bool connected = d.size()!=0;
624
625        fLoggerSubscriptions->setEnabled(connected);
626        fLoggerOpenFiles->setEnabled(connected);
627        if (!connected)
628            return;
629
630        const uint32_t *vals = d.ptr<uint32_t>();
631
632        fLoggerSubscriptions->setValue(vals[0]);
633        fLoggerOpenFiles->setValue(vals[1]);
634    }
635
636
637    // ===================== All ============================================
638
639    bool CheckSize(const DimData &d, size_t sz, bool print=true) const
640    {
641        if (d.size()==0)
642            return false;
643
644        if (d.size()!=sz)
645        {
646            if (print)
647                cerr << "Size mismatch in " << d.name << ": Found=" << d.size() << " Expected=" << sz << endl;
648            return false;
649        }
650
651        return true;
652    }
653
654    // ===================== FAD ============================================
655
656    uint64_t fFreeSpaceData;
657
658    void handleFadWriteStats(const DimData &d)
659    {
660        const bool connected = d.size()!=0;
661
662        fEvtBuilderET->setEnabled(connected);
663        fEvtBuilderRate->setEnabled(connected);
664        fEvtBuilderWritten->setEnabled(connected);
665        fEvtBuilderFreeSpace->setEnabled(connected);
666        fEvtBuilderSpaceLeft->setEnabled(connected);
667
668        fFreeSpaceData = UINT64_MAX;
669        UpdateGlobalStatus();
670
671        if (!connected)
672            return;
673
674        const uint64_t *vals = d.ptr<uint64_t>();
675
676        const size_t space   = vals[0];
677        const size_t written = vals[1];
678        const size_t rate    = float(vals[2])/vals[3];
679
680        fFreeSpaceData = space;
681        UpdateGlobalStatus();
682
683        fEvtBuilderFreeSpace->setSuffix(" MB");
684        fEvtBuilderFreeSpace->setDecimals(0);
685        fEvtBuilderFreeSpace->setValue(space*1e-6);
686
687        if (space>   1000000)  // > 1GB
688        {
689            fEvtBuilderFreeSpace->setSuffix(" GB");
690            fEvtBuilderFreeSpace->setDecimals(2);
691            fEvtBuilderFreeSpace->setValue(space*1e-9);
692        }
693        if (space>=  3000000)  // >= 3GB
694        {
695            fEvtBuilderFreeSpace->setSuffix(" GB");
696            fEvtBuilderFreeSpace->setDecimals(1);
697            fEvtBuilderFreeSpace->setValue(space*1e-9);
698        }
699        if (space>=100000000)  // >= 100GB
700        {
701            fEvtBuilderFreeSpace->setSuffix(" GB");
702            fEvtBuilderFreeSpace->setDecimals(0);
703            fEvtBuilderFreeSpace->setValue(space*1e-9);
704        }
705
706        fEvtBuilderET->setTime(QTime().addSecs(rate>0?space/rate:0));
707        fEvtBuilderRate->setValue(rate*1e-3); // kB/s
708        fEvtBuilderWritten->setValue(written*1e-6);
709
710        fEvtBuilderRate->setSuffix(" kB/s");
711        fEvtBuilderRate->setDecimals(2);
712        fEvtBuilderRate->setValue(rate);
713        if (rate>   2)  // > 2kB/s
714        {
715            fEvtBuilderRate->setSuffix(" kB/s");
716            fEvtBuilderRate->setDecimals(1);
717            fEvtBuilderRate->setValue(rate);
718        }
719        if (rate>=100)  // >100kB/s
720        {
721            fEvtBuilderRate->setSuffix(" kB/s");
722            fEvtBuilderRate->setDecimals(0);
723            fEvtBuilderRate->setValue(rate);
724        }
725        if (rate>=1000)  // >100kB/s
726        {
727            fEvtBuilderRate->setSuffix(" MB/s");
728            fEvtBuilderRate->setDecimals(2);
729            fEvtBuilderRate->setValue(rate*1e-3);
730        }
731        if (rate>=10000)  // >1MB/s
732        {
733            fEvtBuilderRate->setSuffix(" MB/s");
734            fEvtBuilderRate->setDecimals(1);
735            fEvtBuilderRate->setValue(rate*1e-3);
736        }
737        if (rate>=100000)  // >10MB/s
738        {
739            fEvtBuilderRate->setSuffix(" MB/s");
740            fEvtBuilderRate->setDecimals(0);
741            fEvtBuilderRate->setValue(rate*1e-3);
742        }
743
744        if (space/1000000>static_cast<size_t>(fEvtBuilderSpaceLeft->maximum()))
745            fEvtBuilderSpaceLeft->setValue(fEvtBuilderSpaceLeft->maximum());  // GB
746        else
747            fEvtBuilderSpaceLeft->setValue(space/1000000);  // MB
748    }
749
750    void handleFadRuns(const DimData &d)
751    {
752        if (d.size()==0)
753            return;
754
755        if (d.size()<8)
756        {
757            cerr << "Size mismatch in " << d.name << ": Found=" << d.size() << " Expected>=8" << endl;
758            return;
759        }
760
761        const uint32_t *ptr = d.ptr<uint32_t>();
762
763        fEvtBldLastOpened->setValue(ptr[0]);
764        fEvtBldLastClosed->setValue(ptr[1]);
765
766        if (d.size()>=8)
767            fEvtBldFilename->setText(d.ptr<char>(8));
768
769        fEvtBldLastOpened->setEnabled(d.qos);
770        fEvtBldLastClosed->setEnabled(d.qos);
771        fEvtBldFilename->setEnabled(d.qos);
772    }
773
774    void handleFadStartRun(const DimData &d)
775    {
776        if (!CheckSize(d, 16))
777            return;
778
779        const int64_t *runs = d.ptr<int64_t>();
780
781        fFadRunNoCur->setValue(runs[0]);
782        fFadRunNoNext->setValue(runs[1]);
783        fFadRunNoCur->setEnabled(runs[0]>=0);
784        //fMcpStopRun->setEnabled(runs[0]>=0);
785
786    }
787
788    void handleFadEvents(const DimData &d)
789    {
790        if (!CheckSize(d, 16))
791            return;
792
793        const uint32_t *ptr = d.ptr<uint32_t>();
794
795        fEvtsSuccessCurRun->setValue(ptr[0]);
796        fEvtsSuccessTotal->setValue(ptr[1]);
797        fEvtBldEventId->setValue(ptr[2]);
798        fFadEvtCounter->setValue(ptr[2]);
799        fEvtBldTriggerId->setValue(ptr[3]);
800    }
801
802    void handleFadTemperature(const DimData &d)
803    {
804        if (d.size()==0)
805        {
806            fFadTempMin->setEnabled(false);
807            fFadTempMax->setEnabled(false);
808            SetLedColor(fFadLedTemp, kLedGray, d.time);
809            return;
810        }
811
812        if (!CheckSize(d, sizeof(uint16_t)+160*sizeof(float)))
813            return;
814
815        const float *ptr = d.ptr<float>(2);
816
817        fFadTempMin->setEnabled(true);
818        fFadTempMax->setEnabled(true);
819
820        float min =  FLT_MAX;
821        float max = -FLT_MAX;
822
823        vector<float> mn(40,  FLT_MAX);
824        vector<float> mx(40, -FLT_MAX);
825        for (int i=0; i<160; i++)
826        {
827            if (!finite(ptr[i]))
828                continue;
829
830            if (ptr[i]<min)
831                min = ptr[i];
832            if (ptr[i]>max)
833                max = ptr[i];
834
835            if (ptr[i]<mn[i/4])
836                mn[i/4] = ptr[i];
837            if (ptr[i]>mx[i/4])
838                mx[i/4] = ptr[i];
839        }
840
841        fFadTempMin->setValue(min);
842        fFadTempMax->setValue(max);
843
844        handleFadToolTip(d.time, fFadTempMin, mn.data());
845        handleFadToolTip(d.time, fFadTempMax, mx.data());
846    }
847
848    void handleFadRefClock(const DimData &d)
849    {
850        if (d.size()==0)
851        {
852            fFadRefClockMin->setEnabled(false);
853            fFadRefClockMax->setEnabled(false);
854            SetLedColor(fFadLedRefClock, kLedGray, d.time);
855            return;
856        }
857
858        if (!CheckSize(d, sizeof(uint16_t)+40*sizeof(float)))
859            return;
860
861        const float *ptr = d.ptr<float>(2);
862
863        fFadRefClockMin->setEnabled(true);
864        fFadRefClockMax->setEnabled(true);
865
866        float min =  FLT_MAX;
867        float max = -FLT_MAX;
868        for (int i=0; i<40; i++)
869        {
870            if (!finite(ptr[i]))
871                continue;
872
873            if (ptr[i]<min)
874                min = ptr[i];
875            if (ptr[i]>max)
876                max = ptr[i];
877        }
878
879        fFadRefClockMin->setValue(min);
880        fFadRefClockMax->setValue(max);
881
882        const int64_t diff = int64_t(max) - int64_t(min);
883
884        SetLedColor(fFadLedRefClock, abs(diff)>3?kLedRed:kLedGreen, d.time);
885
886        handleFadToolTip(d.time, fFadLedRefClock, ptr);
887    }
888
889    void handleFadRoi(const DimData &d)
890    {
891        if (d.size()==0)
892        {
893            fFadRoi->setEnabled(false);
894            fFadRoiCh9->setEnabled(false);
895            //SetLedColor(fFadLedRoi, kLedGray, d.time);
896            return;
897        }
898
899        if (!CheckSize(d, 2*sizeof(uint16_t)))
900            return;
901
902        const uint16_t *ptr = d.ptr<uint16_t>();
903
904        fFadRoi->setEnabled(true);
905        fFadRoiCh9->setEnabled(true);
906
907        fFadRoi->setValue(ptr[0]);
908        fFadRoiCh9->setValue(ptr[1]);
909
910        //SetLedColor(fFadLedRoi, kLedGray, d.time);
911    }
912
913    void handleDac(QPushButton *led, QSpinBox *box, const DimData &d, int idx)
914    {
915        if (d.size()==0)
916        {
917            box->setEnabled(false);
918            SetLedColor(led, kLedGray, d.time);
919            return;
920        }
921
922        const uint16_t *ptr = d.ptr<uint16_t>()+idx*42;
923
924        box->setEnabled(true);
925        box->setValue(ptr[40]==ptr[41]?ptr[40]:0);
926
927        SetLedColor(led, ptr[40]==ptr[41]?kLedGreen:kLedOrange, d.time);
928        handleFadToolTip(d.time, led, ptr);
929    }
930
931    void handleFadDac(const DimData &d)
932    {
933        if (!CheckSize(d, 8*42*sizeof(uint16_t)) && d.size()!=0)
934            return;
935
936        handleDac(fFadLedDac0, fFadDac0, d, 0);
937        handleDac(fFadLedDac1, fFadDac1, d, 1);
938        handleDac(fFadLedDac2, fFadDac2, d, 2);
939        handleDac(fFadLedDac3, fFadDac3, d, 3);
940        handleDac(fFadLedDac4, fFadDac4, d, 4);
941        handleDac(fFadLedDac5, fFadDac5, d, 5);
942        handleDac(fFadLedDac6, fFadDac6, d, 6);
943        handleDac(fFadLedDac7, fFadDac7, d, 7);
944    }
945
946    EVENT *fEventData;
947#ifdef HAVE_ROOT
948    void DrawHorizontal(TH1 *hf, double xmax, TH1 &h, double scale)
949    {
950        for (Int_t i=1;i<=h.GetNbinsX();i++)
951        {
952            if (h.GetBinContent(i)<0.5 || h.GetBinContent(i)>h.GetEntries()-0.5)
953                continue;
954
955            TBox * box=new TBox(xmax, h.GetBinLowEdge(i),
956                                xmax+h.GetBinContent(i)*scale,
957                                h.GetBinLowEdge(i+1));
958
959            box->SetFillStyle(0);
960            box->SetLineColor(h.GetLineColor());
961            box->SetLineStyle(kSolid);
962            box->SetBit(kCannotPick|kNoContextMenu);
963            //box->Draw();
964
965            hf->GetListOfFunctions()->Add(box);
966        }
967    }
968#endif
969    void DisplayEventData()
970    {
971        if (!fEventData)
972            return;
973
974#ifdef HAVE_ROOT
975        TCanvas *c = fAdcDataCanv->GetCanvas();
976
977        TH1 *hf = dynamic_cast<TH1*>(c->FindObject("Frame"));
978        TH1 *= dynamic_cast<TH1*>(c->FindObject("EventData"));
979        TH1 *d0 = dynamic_cast<TH1*>(c->FindObject("DrsCalib0"));
980        TH1 *d1 = dynamic_cast<TH1*>(c->FindObject("DrsCalib1"));
981        TH1 *d2 = dynamic_cast<TH1*>(c->FindObject("DrsCalib2"));
982
983        const int roi = fAdcPhysical->isChecked() ? 1024 : (fEventData->Roi>0 ? fEventData->Roi : 1);
984
985        if ((hf && hf->GetNbinsX()!=roi) ||
986            (dynamic_cast<TH2*>(h) && !fAdcPersistent->isChecked()) ||
987            (!dynamic_cast<TH2*>(h) && fAdcPersistent->isChecked()))
988        {
989            delete hf;
990            delete h;
991            delete d0;
992            delete d1;
993            delete d2;
994            d0 = 0;
995            d1 = 0;
996            d2 = 0;
997            hf = 0;
998        }
999
1000        if (!hf)
1001        {
1002            hf = new TH1F("Frame", "", roi, -0.5, roi-0.5);
1003            hf->SetDirectory(0);
1004            hf->SetBit(kCanDelete);
1005            hf->SetStats(kFALSE);
1006            hf->SetYTitle("Voltage [mV]");
1007            hf->GetXaxis()->CenterTitle();
1008            hf->GetYaxis()->CenterTitle();
1009            hf->SetMinimum(-1250);
1010            hf->SetMaximum(2150);
1011
1012            if (!fAdcPersistent->isChecked())
1013                h = new TH1F("EventData", "", roi, -0.5, roi-0.5);
1014            else
1015            {
1016                h = new TH2F("EventData", "", roi, -0.5, roi-0.5, 6751, -2350.5*2000/4096, 4400.5*2000/4096);
1017                h->SetContour(50);
1018                gStyle->SetPalette(1, 0);
1019            }
1020
1021            h->SetDirectory(0);
1022            h->SetBit(kCanDelete);
1023            h->SetMarkerStyle(kFullDotMedium);
1024            h->SetMarkerColor(kBlue);
1025
1026            c->GetListOfPrimitives()->Add(hf, "");
1027
1028            if (dynamic_cast<TH2*>(h))
1029                c->GetListOfPrimitives()->Add(h, "col same");
1030        }
1031
1032        if (d0 && !(fDrsCalibBaselineOn->isChecked() && fDrsCalibBaseline->value()>0))
1033        {
1034            delete d0;
1035            d0 = 0;
1036        }
1037        if (d1 && !(fDrsCalibGainOn->isChecked() && fDrsCalibGain->value()>0))
1038        {
1039            delete d1;
1040            d1 = 0;
1041        }
1042        if (d2 && !(fDrsCalibTrgOffsetOn->isChecked() && fDrsCalibTrgOffset->value()>0))
1043        {
1044            delete d2;
1045            d2 = 0;
1046        }
1047
1048        if (!d0 && fDrsCalibBaselineOn->isChecked() && fDrsCalibBaseline->value()>0)
1049        {
1050            d0 = new TH1F("DrsCalib0", "", roi, -0.5, roi-0.5);
1051            d0->SetDirectory(0);
1052            d0->SetBit(kCanDelete);
1053            d0->SetMarkerStyle(kFullDotSmall);
1054            d0->SetMarkerColor(kRed);
1055            d0->SetLineColor(kRed);
1056            c->GetListOfPrimitives()->Add(d0, "PEX0same");
1057        }
1058
1059        if (!d1 && fDrsCalibGainOn->isChecked() && fDrsCalibGain->value()>0)
1060        {
1061            d1 = new TH1F("DrsCalib1", "", roi, -0.5, roi-0.5);
1062            d1->SetDirectory(0);
1063            d1->SetBit(kCanDelete);
1064            d1->SetMarkerStyle(kFullDotSmall);
1065            d1->SetMarkerColor(kMagenta);
1066            d1->SetLineColor(kMagenta);
1067            c->GetListOfPrimitives()->Add(d1, "PEX0same");
1068        }
1069
1070        if (!d2 && fDrsCalibTrgOffsetOn->isChecked() && fDrsCalibTrgOffset->value()>0)
1071        {
1072            d2 = new TH1F("DrsCalib2", "", roi, -0.5, roi-0.5);
1073            d2->SetDirectory(0);
1074            d2->SetBit(kCanDelete);
1075            d2->SetMarkerStyle(kFullDotSmall);
1076            d2->SetMarkerColor(kGreen);
1077            d2->SetLineColor(kGreen);
1078            c->GetListOfPrimitives()->Add(d2, "PEX0same");
1079        }
1080
1081        if (!dynamic_cast<TH2*>(h) && !c->GetListOfPrimitives()->FindObject(h))
1082            c->GetListOfPrimitives()->Add(h, "PLsame");
1083
1084        // -----------------------------------------------------------
1085
1086        const uint32_t p =
1087            fAdcChannel->value()    +
1088            fAdcChip->value()   *  9+
1089            fAdcBoard->value()  * 36+
1090            fAdcCrate->value()  *360;
1091
1092        ostringstream str;
1093        str << "CBPX = " << fAdcCrate->value() << '|' << fAdcBoard->value() << '|' << fAdcChip->value() << '|' << fAdcChannel->value() << " (" << p << ")";
1094        str << "   EventNum = " << fEventData->EventNum;
1095        str << "   TriggerNum = " << fEventData->TriggerNum;
1096        str << "   TriggerType = " << fEventData->TriggerType;
1097        str << "   BoardTime = " << fEventData->BoardTime[fAdcBoard->value()+fAdcCrate->value()*10];
1098        str << "   (" << Time(fEventData->PCTime, fEventData->PCUsec) << ")";
1099        hf->SetTitle(str.str().c_str());
1100        str.str("");
1101        str << "ADC Pipeline (start cell: " << fEventData->StartPix[p] << ")";
1102        hf->SetXTitle(str.str().c_str());
1103
1104        // -----------------------------------------------------------
1105
1106        const int16_t start = fEventData->StartPix[p];
1107
1108        fDrsCalibBaseline->setEnabled(fDrsCalibBaseline->value()>0);
1109        fDrsCalibGain->setEnabled(fDrsCalibGain->value()>0);
1110        fDrsCalibTrgOffset->setEnabled(fDrsCalibTrgOffset->value()>0);
1111        fDrsCalibROI->setEnabled(fDrsCalibROI->value()>0);
1112
1113        fDrsCalibBaseline2->setEnabled(fDrsCalibBaseline->value()>0);
1114        fDrsCalibGain2->setEnabled(fDrsCalibGain->value()>0);
1115        fDrsCalibTrgOffset2->setEnabled(fDrsCalibTrgOffset->value()>0);
1116        fDrsCalibROI2->setEnabled(fDrsCalibROI->value()>0);
1117
1118        SetLedColor(fFadLedDrsBaseline, fDrsCalibBaseline->value()>0 ?kLedGreen:kLedGray, Time());
1119        SetLedColor(fFadLedDrsGain,     fDrsCalibGain->value()>0     ?kLedGreen:kLedGray, Time());
1120        SetLedColor(fFadLedDrsTrgOff,   fDrsCalibTrgOffset->value()>0?kLedGreen:kLedGray, Time());
1121
1122        if (d0)//fDrsCalibBaseline->value()==0  || start<0)
1123            d0->Reset();
1124        if (d1)//fDrsCalibGain->value()==0      || start<0)
1125            d1->Reset();
1126        if (d2)//fDrsCalibTrgOffset->value()==0 || start<0)
1127            d2->Reset();
1128
1129        if (!dynamic_cast<TH2*>(h))
1130            h->Reset();
1131        if (d0)
1132            d0->SetEntries(0);
1133        if (d1)
1134            d1->SetEntries(0);
1135        if (d2)
1136            d2->SetEntries(0);
1137
1138        for (int i=0; i<fEventData->Roi; i++)
1139        {
1140            // FIXME: physcial: i -> (i+start)%1024
1141            // FIXME: logical:  i ->  i
1142
1143            const int ii = fAdcPhysical->isChecked() ? (i+start)%1024 : i;
1144
1145            //if (dynamic_cast<TH2*>(h))
1146                h->Fill(ii, reinterpret_cast<float*>(fEventData->Adc_Data)[p*fEventData->Roi+i]);
1147            //else
1148            //    h->SetBinContent(i+1, reinterpret_cast<float*>(fEventData->Adc_Data)[p*fEventData->Roi+i]);
1149            if (start<0)
1150                continue;
1151
1152            if (d0)
1153            {
1154                d0->SetBinContent(ii+1, fDrsCalibration[1440*1024*0 + p*1024+(start+i)%1024]);
1155                d0->SetBinError(ii+1,   fDrsCalibration[1440*1024*1 + p*1024+(start+i)%1024]);
1156
1157            }
1158            if (d1)
1159            {
1160                d1->SetBinContent(ii+1, fDrsCalibration[1440*1024*2 + p*1024+(start+i)%1024]);
1161                d1->SetBinError(ii+1,   fDrsCalibration[1440*1024*3 + p*1024+(start+i)%1024]);
1162            }
1163            if (d2)
1164            {
1165                d2->SetBinContent(ii+1, fDrsCalibration[1440*1024*4 + p*1024 + i]);
1166                d2->SetBinError(ii+1,   fDrsCalibration[1440*1024*5 + p*1024 + i]);
1167            }
1168        }
1169
1170        // -----------------------------------------------------------
1171        if (fAdcDynamicScale->isEnabled() && fAdcDynamicScale->isChecked())
1172        {
1173            h->SetMinimum();
1174            h->SetMaximum();
1175
1176            hf->SetMinimum(h->GetMinimum());
1177            hf->SetMaximum(h->GetMaximum());
1178        }
1179        if (fAdcManualScale->isEnabled() && fAdcManualScale->isChecked())
1180        {
1181            if (h->GetMinimumStored()==-1111)
1182            {
1183                h->SetMinimum(-1150);//-1026);
1184                hf->SetMinimum(-1150);//-1026);
1185            }
1186            if (h->GetMaximumStored()==-1111)
1187            {
1188                h->SetMaximum(2150);//1025);
1189                hf->SetMaximum(2150);//1025);
1190            }
1191        }
1192
1193        if (fAdcAutoScale->isEnabled() && fAdcAutoScale->isChecked())
1194        {
1195            h->SetMinimum();
1196            h->SetMaximum();
1197
1198            if (h->GetMinimum()<hf->GetMinimum())
1199                hf->SetMinimum(h->GetMinimum());
1200            if (h->GetMaximum()>hf->GetMaximum())
1201                hf->SetMaximum(h->GetMaximum());
1202        }
1203
1204        if (dynamic_cast<TH2*>(h))
1205        {
1206            h->SetMinimum();
1207            h->SetMaximum();
1208        }
1209
1210        // -----------------------------------------------------------
1211
1212        const int imin = ceil(hf->GetMinimum());
1213        const int imax = floor(hf->GetMaximum());
1214
1215        TH1S hd("", "", imax-imin+1, imin-0.5, imax+0.5);
1216        hd.SetDirectory(0);
1217        TH1S h0("", "", imax-imin+1, imin-0.5, imax+0.5);
1218        h0.SetDirectory(0);
1219        TH1S h1("", "", imax-imin+1, imin-0.5, imax+0.5);
1220        h1.SetDirectory(0);
1221        TH1S h2("", "", imax-imin+1, imin-0.5, imax+0.5);
1222        h2.SetDirectory(0);
1223        hd.SetLineColor(h->GetLineColor());
1224        if (d0)
1225            h0.SetLineColor(d0->GetLineColor());
1226        if (d1)
1227            h1.SetLineColor(d1->GetLineColor());
1228        if (d2)
1229            h2.SetLineColor(d2->GetLineColor());
1230
1231        for (int i=0; i<fEventData->Roi; i++)
1232        {
1233            if (!dynamic_cast<TH2*>(h))
1234                hd.Fill(h->GetBinContent(i+1));
1235            if (d0)
1236                h0.Fill(d0->GetBinContent(i+1));
1237            if (d1)
1238                h1.Fill(d1->GetBinContent(i+1));
1239            if (d2)
1240                h2.Fill(d2->GetBinContent(i+1));
1241        }
1242
1243        double mm = hd.GetMaximum(hd.GetEntries());
1244        if (h0.GetMaximum(h0.GetEntries())>mm)
1245            mm = h0.GetMaximum();
1246        if (h1.GetMaximum(h1.GetEntries())>mm)
1247            mm = h1.GetMaximum();
1248        if (h2.GetMaximum(h2.GetEntries())>mm)
1249            mm = h2.GetMaximum();
1250
1251        TIter Next(hf->GetListOfFunctions());
1252        TObject *obj = 0;
1253        while ((obj=Next()))
1254            if (dynamic_cast<TBox*>(obj))
1255                delete hf->GetListOfFunctions()->Remove(obj);
1256
1257        const double l = h->GetBinLowEdge(h->GetXaxis()->GetLast()+1);
1258        const double m = c->GetX2();
1259
1260        const double scale = 0.9*(m-l)/mm;
1261
1262        DrawHorizontal(hf, l, h2, scale);
1263        DrawHorizontal(hf, l, h1, scale);
1264        DrawHorizontal(hf, l, h0, scale);
1265        DrawHorizontal(hf, l, hd, scale);
1266
1267        // -----------------------------------------------------------
1268
1269        c->Modified();
1270        c->Update();
1271#endif
1272    }
1273
1274    void handleFadRawData(const DimData &d)
1275    {
1276        if (d.size()==0)
1277            return;
1278
1279        if (fAdcStop->isChecked())
1280            return;
1281
1282        const EVENT &dat = d.ref<EVENT>();
1283
1284        if (d.size()<sizeof(EVENT))
1285        {
1286            cerr << "Size mismatch in " << d.name << ": Found=" << d.size() << " Expected>=" << sizeof(EVENT) << endl;
1287            return;
1288        }
1289
1290        if (d.size()!=sizeof(EVENT)+dat.Roi*4*1440+dat.Roi*4*160)
1291        {
1292            cerr << "Size mismatch in " << d.name << ": Found=" << d.size() << " Expected=" << dat.Roi*4*1440+sizeof(EVENT) << " [roi=" << dat.Roi << "]" << endl;
1293            return;
1294        }
1295
1296        delete [] reinterpret_cast<char*>(fEventData);
1297        fEventData = reinterpret_cast<EVENT*>(new char[d.size()]);
1298        memcpy(fEventData, d.ptr<void>(), d.size());
1299
1300        DisplayEventData();
1301    }
1302
1303    void handleFadEventData(const DimData &d)
1304    {
1305        if (!CheckSize(d, 4*1440*sizeof(float)))
1306            return;
1307
1308        if (fEventsStop->isChecked())
1309            return;
1310
1311        const float *ptr = d.ptr<float>();
1312
1313        valarray<double> arr1(1440);
1314        valarray<double> arr2(1440);
1315        valarray<double> arr3(1440);
1316        valarray<double> arr4(1440);
1317
1318        for (vector<PixelMapEntry>::const_iterator it=fPixelMap.begin(); it!=fPixelMap.end(); it++)
1319        {
1320            arr1[it->index] = ptr[0*1440+it->hw()];
1321            arr2[it->index] = ptr[1*1440+it->hw()];
1322            arr3[it->index] = ptr[2*1440+it->hw()];
1323            arr4[it->index] = ptr[3*1440+it->hw()];
1324        }
1325
1326        fEventCanv1->SetData(arr1);
1327        fEventCanv2->SetData(arr2);
1328        fEventCanv3->SetData(arr3);
1329        fEventCanv4->SetData(arr4);
1330
1331        fEventCanv1->updateCamera();
1332        fEventCanv2->updateCamera();
1333        fEventCanv3->updateCamera();
1334        fEventCanv4->updateCamera();
1335    }
1336
1337    vector<float> fDrsCalibration;
1338
1339    void handleFadDrsCalibration(const DimData &d)
1340    {
1341        const size_t sz = 1024*1440*6+1024*160*2;
1342
1343        if (d.size()==0)
1344        {
1345            fDrsCalibBaseline->setValue(-1);
1346            fDrsCalibGain->setValue(-1);
1347            fDrsCalibTrgOffset->setValue(-1);
1348            fDrsCalibROI->setValue(-1);
1349
1350            fDrsCalibBaseline2->setValue(-1);
1351            fDrsCalibGain2->setValue(-1);
1352            fDrsCalibTrgOffset2->setValue(-1);
1353            fDrsCalibROI2->setValue(-1);
1354
1355            fDrsCalibration.assign(sz, 0);
1356            DisplayEventData();
1357            return;
1358        }
1359
1360        if (!CheckSize(d, sz*sizeof(float)+4*sizeof(uint32_t)))
1361            // Do WHAT?
1362            return;
1363
1364        const uint32_t *run = d.ptr<uint32_t>();
1365
1366        fDrsCalibROI->setValue(run[0]);
1367        fDrsCalibBaseline->setValue(run[1]);
1368        fDrsCalibGain->setValue(run[2]);
1369        fDrsCalibTrgOffset->setValue(run[3]);
1370
1371        fDrsCalibROI2->setValue(run[0]);
1372        fDrsCalibBaseline2->setValue(run[1]);
1373        fDrsCalibGain2->setValue(run[2]);
1374        fDrsCalibTrgOffset2->setValue(run[3]);
1375
1376        const float *dat = d.ptr<float>(sizeof(uint32_t)*4);
1377        fDrsCalibration.assign(dat, dat+sz);
1378
1379        DisplayEventData();
1380    }
1381
1382//    vector<uint8_t> fFadConnections;
1383
1384    void handleFadConnections(const DimData &d)
1385    {
1386        if (!CheckSize(d, 41))
1387        {
1388            fStatusEventBuilderLabel->setText("Offline");
1389            fStatusEventBuilderLabel->setToolTip("FADs or fadctrl seems to be offline.");
1390            fGroupEthernet->setEnabled(false);
1391            fGroupOutput->setEnabled(false);
1392
1393            SetLedColor(fStatusEventBuilderLed, kLedGray, d.time);
1394            return;
1395        }
1396
1397        const uint8_t *ptr = d.ptr<uint8_t>();
1398
1399        for (int i=0; i<40; i++)
1400        {
1401            const uint8_t stat1 = ptr[i]&3;
1402            const uint8_t stat2 = ptr[i]>>3;
1403
1404            if (stat1==0 && stat2==0)
1405            {
1406                SetLedColor(fFadLED[i], kLedGray,   d.time);
1407                continue;
1408            }
1409            if (stat1>=2 && stat2==8)
1410            {
1411                SetLedColor(fFadLED[i], stat1==2?kLedGreen:kLedGreenCheck,  d.time);
1412                continue;
1413            }
1414
1415            if (stat1==1 && stat2==1)
1416                SetLedColor(fFadLED[i], kLedRed, d.time);
1417            else
1418                SetLedColor(fFadLED[i], kLedOrange, d.time);
1419        }
1420
1421
1422        const bool runs = ptr[40]!=0;
1423
1424        fStatusEventBuilderLabel->setText(runs?"Running":"Not running");
1425        fStatusEventBuilderLabel->setToolTip(runs?"Event builder thread running.":"Event builder thread stopped.");
1426
1427        fGroupEthernet->setEnabled(runs);
1428        fGroupOutput->setEnabled(runs);
1429
1430        SetLedColor(fStatusEventBuilderLed, runs?kLedGreen:kLedRed, d.time);
1431
1432//        fFadConnections.assign(ptr, ptr+40);
1433    }
1434
1435    template<typename T>
1436        void handleFadToolTip(const Time &time, QWidget *w, T *ptr)
1437    {
1438        ostringstream tip;
1439        tip << "<table border='1'><tr><th colspan='11'>" << time.GetAsStr() << " (UTC)</th></tr><tr><th></th>";
1440        for (int b=0; b<10; b++)
1441            tip << "<th>" << b << "</th>";
1442        tip << "</tr>";
1443
1444        for (int c=0; c<4; c++)
1445        {
1446            tip << "<tr><th>" << c << "</th>";
1447            for (int b=0; b<10; b++)
1448                tip << "<td>" << ptr[c*10+b] << "</td>";
1449            tip << "</tr>";
1450        }
1451        tip << "</table>";
1452
1453        w->setToolTip(tip.str().c_str());
1454    }
1455
1456    template<typename T, class S>
1457        void handleFadMinMax(const DimData &d, QPushButton *led, S *wmin, S *wmax=0)
1458    {
1459        if (!CheckSize(d, 42*sizeof(T)))
1460            return;
1461
1462        const T *ptr = d.ptr<T>();
1463        const T  min = ptr[40];
1464        const T  max = ptr[41];
1465
1466        if (max==0 && min>max)
1467            SetLedColor(led, kLedGray, d.time);
1468        else
1469            SetLedColor(led, min==max?kLedGreen: kLedOrange, d.time);
1470
1471        if (!wmax && max!=min)
1472            wmin->setValue(0);
1473        else
1474            wmin->setValue(min);
1475
1476        if (wmax)
1477            wmax->setValue(max);
1478
1479        handleFadToolTip(d.time, led, ptr);
1480    }
1481
1482    void handleFadFwVersion(const DimData &d)
1483    {
1484        handleFadMinMax<float, QDoubleSpinBox>(d, fFadLedFwVersion, fFadFwVersion);
1485    }
1486
1487    void handleFadRunNumber(const DimData &d)
1488    {
1489        handleFadMinMax<uint32_t, QSpinBox>(d, fFadLedRunNumber, fFadRunNumber);
1490    }
1491
1492    void handleFadPrescaler(const DimData &d)
1493    {
1494        handleFadMinMax<uint16_t, QSpinBox>(d, fFadLedPrescaler, fFadPrescaler);
1495    }
1496
1497    void handleFadDNA(const DimData &d)
1498    {
1499        if (!CheckSize(d, 40*sizeof(uint64_t)))
1500            return;
1501
1502        const uint64_t *ptr = d.ptr<uint64_t>();
1503
1504        ostringstream tip;
1505        tip << "<table width='100%'>";
1506        tip << "<tr><th>Crate</th><td></td><th>Board</th><td></td><th>DNA</th></tr>";
1507
1508        for (int i=0; i<40; i++)
1509        {
1510            tip << dec;
1511            tip << "<tr>";
1512            tip << "<td align='center'>" << i/10 << "</td><td>:</td>";
1513            tip << "<td align='center'>" << i%10 << "</td><td>:</td>";
1514            tip << hex;
1515            tip << "<td>0x" << setfill('0') << setw(16) << ptr[i] << "</td>";
1516            tip << "</tr>";
1517        }
1518        tip << "</table>";
1519
1520        fFadDNA->setText(tip.str().c_str());
1521    }
1522
1523    void SetFadLed(QPushButton *led, const DimData &d, uint16_t bitmask, bool invert=false)
1524    {
1525        if (d.size()==0)
1526        {
1527            SetLedColor(led, kLedGray, d.time);
1528            return;
1529        }
1530
1531        const bool      quality = d.ptr<uint16_t>()[0]&bitmask;
1532        const bool      value   = d.ptr<uint16_t>()[1]&bitmask;
1533        const uint16_t *ptr     = d.ptr<uint16_t>()+2;
1534
1535        SetLedColor(led, quality?kLedOrange:(value^invert?kLedGreen:kLedGreenBar), d.time);
1536
1537        ostringstream tip;
1538        tip << "<table border='1'><tr><th colspan='11'>" << d.time.GetAsStr() << " (UTC)</th></tr><tr><th></th>";
1539        for (int b=0; b<10; b++)
1540            tip << "<th>" << b << "</th>";
1541        tip << "</tr>";
1542
1543        /*
1544         tip << "<tr>" << hex;
1545         tip << "<th>" << d.ptr<uint16_t>()[0] << " " << (d.ptr<uint16_t>()[0]&bitmask) << "</th>";
1546         tip << "<th>" << d.ptr<uint16_t>()[1] << " " << (d.ptr<uint16_t>()[1]&bitmask) << "</th>";
1547         tip << "</tr>";
1548         */
1549
1550        for (int c=0; c<4; c++)
1551        {
1552            tip << "<tr><th>" << dec << c << "</th>" << hex;
1553            for (int b=0; b<10; b++)
1554            {
1555                tip << "<td>"
1556                    << (ptr[c*10+b]&bitmask)
1557                    << "</td>";
1558            }
1559            tip << "</tr>";
1560        }
1561        tip << "</table>";
1562
1563        led->setToolTip(tip.str().c_str());
1564    }
1565
1566    void handleFadStatus(const DimData &d)
1567    {
1568        if (d.size()!=0 && !CheckSize(d, 42*sizeof(uint16_t)))
1569            return;
1570
1571        SetFadLed(fFadLedDrsEnabled,     d, FAD::EventHeader::kDenable);
1572        SetFadLed(fFadLedDrsWrite,       d, FAD::EventHeader::kDwrite);
1573        SetFadLed(fFadLedDcmLocked,      d, FAD::EventHeader::kDcmLocked);
1574        SetFadLed(fFadLedDcmReady,       d, FAD::EventHeader::kDcmReady);
1575        SetFadLed(fFadLedSpiSclk,        d, FAD::EventHeader::kSpiSclk);
1576        SetFadLed(fFadLedRefClockTooLow, d, FAD::EventHeader::kRefClkTooLow, true);
1577        SetFadLed(fFadLedBusyOn,         d, FAD::EventHeader::kBusyOn);
1578        SetFadLed(fFadLedBusyOff,        d, FAD::EventHeader::kBusyOff);
1579        SetFadLed(fFadLedTriggerLine,    d, FAD::EventHeader::kTriggerLine);
1580        SetFadLed(fFadLedContTrigger,    d, FAD::EventHeader::kContTrigger);
1581        SetFadLed(fFadLedSocket,         d, FAD::EventHeader::kSock17);
1582        SetFadLed(fFadLedPllLock,        d, 0xf000);
1583    }
1584
1585    void handleFadStatistics1(const DimData &d)
1586    {
1587        if (!CheckSize(d, sizeof(GUI_STAT)))
1588            return;
1589
1590        const GUI_STAT &stat = d.ref<GUI_STAT>();
1591
1592        fFadBufferMax->setValue(stat.totMem/1000000);  // Memory::allocated
1593        fFadBuffer->setMaximum(stat.maxMem/100);       // g_maxMem
1594        fFadBuffer->setValue(stat.usdMem/100);         // Memory::inuse
1595
1596        uint32_t sum = 0;
1597        int cnt = 0;
1598
1599        for (int i=0; i<40; i++)
1600        {
1601            if (stat.numConn[i]==1)
1602            {
1603                sum += stat.rateBytes[i];
1604                cnt++;
1605            }
1606        }
1607
1608        fFadEvtConn->setValue(cnt);
1609
1610        fFadEvtBufNew->setValue(stat.bufNew);  // Incomplete in buffer (evtCtrl)
1611        fFadEvtBufEvt->setValue(stat.bufTot);  // Complete events in buffer (max_inuse)
1612
1613        fFadEvtCheck->setValue(stat.bufEvt);  // Complete in buffer
1614        fFadEvtWrite->setValue(stat.bufWrite);
1615        fFadEvtProc->setValue(stat.bufProc);
1616
1617        if (stat.deltaT==0)
1618            return;
1619
1620        //fFadEthernetRateMin->setValue(min/stat.deltaT);
1621        //fFadEthernetRateMax->setValue(max/stat.deltaT);
1622        fFadEthernetRateTot->setValue(sum/stat.deltaT);
1623        fFadEthernetRateAvg->setValue(cnt==0 ? 0 : sum/cnt/stat.deltaT);
1624
1625        fFadTransmission->setValue(1000*stat.rateNew/stat.deltaT);
1626        fFadWriteRate->setValue(1000*stat.rateWrite/stat.deltaT);
1627    }
1628
1629    /*
1630    void handleFadStatistics2(const DimData &d)
1631    {
1632        if (!CheckSize(d, sizeof(EVT_STAT)))
1633            return;
1634
1635        //const EVT_STAT &stat = d.ref<EVT_STAT>();
1636    }*/
1637
1638    void handleFadFileFormat(const DimData &d)
1639    {
1640        if (!CheckSize(d, sizeof(uint16_t)))
1641            return;
1642
1643        const uint16_t &fmt = d.get<uint16_t>();
1644
1645        SetLedColor(fFadLedFileFormatNone,  fmt==FAD::kNone ?kLedGreen:kLedGray, d.time);
1646        SetLedColor(fFadLedFileFormatDebug, fmt==FAD::kDebug?kLedGreen:kLedGray, d.time);
1647        SetLedColor(fFadLedFileFormatRaw,   fmt==FAD::kRaw  ?kLedGreen:kLedGray, d.time);
1648        SetLedColor(fFadLedFileFormatFits,  fmt==FAD::kFits ?kLedGreen:kLedGray, d.time);
1649        SetLedColor(fFadLedFileFormatZFits, fmt==FAD::kZFits?kLedGreen:kLedGray, d.time);
1650        SetLedColor(fFadLedFileFormatCalib, fmt==FAD::kCalib?kLedGreen:kLedGray, d.time);
1651    }
1652
1653    // ===================== FTM ============================================
1654
1655    FTM::DimTriggerRates fTriggerRates;
1656
1657    void UpdateTriggerRate(const FTM::DimTriggerRates &sdata)
1658    {
1659#ifdef HAVE_ROOT
1660        TCanvas *c = fFtmRateCanv->GetCanvas();
1661
1662        TH1 *h = (TH1*)c->FindObject("TimeFrame");
1663
1664        if (sdata.fTimeStamp<=fTriggerRates.fTimeStamp)
1665        {
1666            fGraphFtmRate.Set(0);
1667
1668            const double tm = Time().RootTime();
1669
1670            h->SetBins(1, tm, tm+60);
1671            h->GetXaxis()->SetTimeFormat("%M'%S\"%F1995-01-01 00:00:00 GMT");
1672            h->GetXaxis()->SetTitle("Time");
1673
1674            c->Modified();
1675            c->Update();
1676            return;
1677        }
1678
1679        const double t1 = h->GetXaxis()->GetXmax();
1680        const double t0 = h->GetXaxis()->GetXmin();
1681
1682        const double now = t0+sdata.fTimeStamp/1000000.;
1683
1684        h->SetBins(h->GetNbinsX()+1, t0, now+1);
1685        fGraphFtmRate.SetPoint(fGraphFtmRate.GetN(), now, sdata.fTriggerRate);
1686
1687        if (t1-t0>300)
1688        {
1689            h->GetXaxis()->SetTimeFormat("%Hh%M'%F1995-01-01 00:00:00 GMT");
1690            h->GetXaxis()->SetTitle("Time");
1691        }
1692
1693        h->SetMinimum(0);
1694
1695        c->Modified();
1696        c->Update();
1697#endif
1698    }
1699
1700    void UpdateRatesCam(const FTM::DimTriggerRates &sdata)
1701    {
1702        if (fThresholdIdx->value()>=0)
1703        {
1704            const int isw = fThresholdIdx->value();
1705            const int ihw = fPatchMapHW[isw];
1706            fPatchRate->setValue(sdata.fPatchRate[ihw]);
1707            fBoardRate->setValue(sdata.fBoardRate[ihw/4]);
1708        }
1709
1710        const bool b = fBoardRatesEnabled->isChecked();
1711
1712        valarray<double> dat(0., 1440);
1713
1714        // fPatch converts from software id to software patch id
1715        for (int i=0; i<1440; i++)
1716        {
1717            const int ihw = fPixelMap.index(i).hw()/9;
1718            dat[i] = b ? sdata.fBoardRate[ihw/4] : sdata.fPatchRate[ihw];
1719        }
1720
1721        fRatesCanv->SetData(dat);
1722        fRatesCanv->updateCamera();
1723    }
1724
1725    int64_t fTimeStamp0;
1726
1727    void on_fBoardRatesEnabled_toggled(bool)
1728    {
1729        UpdateRatesCam(fTriggerRates);
1730    }
1731
1732    void UpdateRatesGraphs(const FTM::DimTriggerRates &sdata)
1733    {
1734#ifdef HAVE_ROOT
1735        if (fTimeStamp0<0)
1736        {
1737            fTimeStamp0 = sdata.fTimeStamp;
1738            return;
1739        }
1740
1741        TCanvas *c = fFtmRateCanv->GetCanvas();
1742
1743        TH1 *h = (TH1*)c->FindObject("TimeFrame");
1744
1745        const double tdiff = sdata.fTimeStamp-fTimeStamp0;
1746        fTimeStamp0 = sdata.fTimeStamp;
1747
1748        if (tdiff<0)
1749        {
1750            for (int i=0; i<160; i++)
1751                fGraphPatchRate[i].Set(0);
1752            for (int i=0; i<40; i++)
1753                fGraphBoardRate[i].Set(0);
1754
1755            return;
1756        }
1757
1758        //const double t1 = h->GetXaxis()->GetXmax();
1759        const double t0 = h->GetXaxis()->GetXmin();
1760
1761        for (int i=0; i<160; i++)
1762            if (fFtuStatus[i/4]>0)
1763                fGraphPatchRate[i].SetPoint(fGraphPatchRate[i].GetN(),
1764                                            t0+sdata.fTimeStamp/1000000., sdata.fPatchRate[i]);
1765        for (int i=0; i<40; i++)
1766            if (fFtuStatus[i]>0)
1767                fGraphBoardRate[i].SetPoint(fGraphBoardRate[i].GetN(),
1768                                            t0+sdata.fTimeStamp/1000000., sdata.fBoardRate[i]);
1769
1770        c->Modified();
1771        c->Update();
1772#endif
1773    }
1774
1775    void handleFtmTriggerRates(const DimData &d)
1776    {
1777        if (!CheckSize(d, sizeof(FTM::DimTriggerRates)))
1778            return;
1779
1780        const FTM::DimTriggerRates &sdata = d.ref<FTM::DimTriggerRates>();
1781
1782        fFtmTime->setText(QString::number(sdata.fTimeStamp/1000000., 'f', 6)+ " s");
1783        fTriggerCounter->setText(QString::number(sdata.fTriggerCounter));
1784
1785        if (sdata.fTimeStamp>0)
1786            fTriggerCounterRate->setValue(1000000.*sdata.fTriggerCounter/sdata.fTimeStamp);
1787        else
1788            fTriggerCounterRate->setValue(0);
1789
1790        // ----------------------------------------------
1791
1792        fOnTime->setText(QString::number(sdata.fOnTimeCounter/1000000., 'f', 6)+" s");
1793
1794        if (sdata.fTimeStamp>0)
1795            fOnTimeRel->setValue(100.*sdata.fOnTimeCounter/sdata.fTimeStamp);
1796        else
1797            fOnTimeRel->setValue(0);
1798
1799        // ----------------------------------------------
1800
1801        UpdateTriggerRate(sdata);
1802        UpdateRatesGraphs(sdata);
1803        UpdateRatesCam(sdata);
1804
1805        fTriggerRates = sdata;
1806    }
1807
1808    void handleFtmCounter(const DimData &d)
1809    {
1810        if (!CheckSize(d, sizeof(uint32_t)*6))
1811            return;
1812
1813        const uint32_t *sdata = d.ptr<uint32_t>();
1814
1815        fFtmCounterH->setValue(sdata[0]);
1816        fFtmCounterS->setValue(sdata[1]);
1817        fFtmCounterD->setValue(sdata[2]);
1818        fFtmCounterF->setValue(sdata[3]);
1819        fFtmCounterE->setValue(sdata[4]);
1820        fFtmCounterR->setValue(sdata[5]);
1821    }
1822
1823    void handleFtmDynamicData(const DimData &d)
1824    {
1825        if (!CheckSize(d, sizeof(FTM::DimDynamicData)))
1826            return;
1827
1828        const FTM::DimDynamicData &sdata = d.ref<FTM::DimDynamicData>();
1829
1830        fFtmTemp0->setValue(sdata.fTempSensor[0]*0.1);
1831        fFtmTemp1->setValue(sdata.fTempSensor[1]*0.1);
1832        fFtmTemp2->setValue(sdata.fTempSensor[2]*0.1);
1833        fFtmTemp3->setValue(sdata.fTempSensor[3]*0.1);
1834
1835        SetLedColor(fClockCondLed, sdata.fState&FTM::kFtmLocked ? kLedGreen : kLedRed, d.time);
1836    }
1837
1838    void DisplayRates()
1839    {
1840#ifdef HAVE_ROOT
1841        TCanvas *c = fFtmRateCanv->GetCanvas();
1842
1843        TList * l = c->GetListOfPrimitives();
1844
1845
1846        while (c->FindObject("PatchRate"))
1847            l->Remove(c->FindObject("PatchRate"));
1848
1849        while (c->FindObject("BoardRate"))
1850            l->Remove(c->FindObject("BoardRate"));
1851
1852        if (fRatePatch1->value()>=0)
1853        {
1854            fGraphPatchRate[fRatePatch1->value()].SetLineColor(kRed);
1855            fGraphPatchRate[fRatePatch1->value()].SetMarkerColor(kRed);
1856            l->Add(&fGraphPatchRate[fRatePatch1->value()], "PL");
1857        }
1858        if (fRatePatch2->value()>=0)
1859        {
1860            fGraphPatchRate[fRatePatch2->value()].SetLineColor(kGreen);
1861            fGraphPatchRate[fRatePatch2->value()].SetMarkerColor(kGreen);
1862            l->Add(&fGraphPatchRate[fRatePatch2->value()], "PL");
1863        }
1864        if (fRateBoard1->value()>=0)
1865        {
1866            fGraphBoardRate[fRateBoard1->value()].SetLineColor(kMagenta);
1867            fGraphBoardRate[fRateBoard1->value()].SetMarkerColor(kMagenta);
1868            l->Add(&fGraphBoardRate[fRateBoard1->value()], "PL");
1869        }
1870        if (fRateBoard2->value()>=0)
1871        {
1872            fGraphBoardRate[fRateBoard2->value()].SetLineColor(kCyan);
1873            fGraphBoardRate[fRateBoard2->value()].SetMarkerColor(kCyan);
1874            l->Add(&fGraphBoardRate[fRateBoard2->value()], "PL");
1875        }
1876
1877        c->Modified();
1878        c->Update();
1879#endif
1880    }
1881
1882    FTM::DimStaticData fFtmStaticData;
1883
1884    void SetFtuLed(int idx, int counter, const Time &t)
1885    {
1886        if (counter==0 || counter>3)
1887            counter = 3;
1888
1889        if (counter<0)
1890            counter = 0;
1891
1892        const LedColor_t col[4] = { kLedGray, kLedGreen, kLedOrange, kLedRed };
1893
1894        SetLedColor(fFtuLED[idx], col[counter], t);
1895
1896        fFtuStatus[idx] = counter;
1897    }
1898
1899    void SetFtuStatusLed(const Time &t)
1900    {
1901        const int max = fFtuStatus.max();
1902
1903        switch (max)
1904        {
1905        case 0:
1906            SetLedColor(fStatusFTULed, kLedGray, t);
1907            fStatusFTULabel->setText("All disabled");
1908            fStatusFTULabel->setToolTip("All FTUs are disabled");
1909            break;
1910
1911        case 1:
1912            SetLedColor(fStatusFTULed, kLedGreen, t);
1913            fStatusFTULabel->setToolTip("Communication with FTU is smooth.");
1914            fStatusFTULabel->setText("ok");
1915            break;
1916
1917        case 2:
1918            SetLedColor(fStatusFTULed, kLedOrange, t);
1919            fStatusFTULabel->setText("Warning");
1920            fStatusFTULabel->setToolTip("At least one FTU didn't answer immediately");
1921            break;
1922
1923        case 3:
1924            SetLedColor(fStatusFTULed, kLedRed, t);
1925            fStatusFTULabel->setToolTip("At least one FTU didn't answer!");
1926            fStatusFTULabel->setText("ERROR");
1927            break;
1928        }
1929
1930        const int cnt = count(&fFtuStatus[0], &fFtuStatus[40], 0);
1931        fFtuAllOn->setEnabled(cnt!=0);
1932        fFtuAllOff->setEnabled(cnt!=40);
1933    }
1934
1935    void handleFtmStaticData(const DimData &d)
1936    {
1937        if (!CheckSize(d, sizeof(FTM::DimStaticData)))
1938            return;
1939
1940        const FTM::DimStaticData &sdata = d.ref<FTM::DimStaticData>();
1941
1942        fTriggerInterval->setValue(sdata.fTriggerInterval);
1943        fPhysicsCoincidence->setValue(sdata.fMultiplicityPhysics);
1944        fCalibCoincidence->setValue(sdata.fMultiplicityCalib);
1945        fPhysicsWindow->setValue(sdata.fWindowPhysics);
1946        fCalibWindow->setValue(sdata.fWindowCalib);
1947
1948        fTriggerDelay->setValue(sdata.fDelayTrigger);
1949        fTimeMarkerDelay->setValue(sdata.fDelayTimeMarker);
1950        fDeadTime->setValue(sdata.fDeadTime);
1951
1952        fClockCondR0->setValue(sdata.fClockConditioner[0]);
1953        fClockCondR1->setValue(sdata.fClockConditioner[1]);
1954        fClockCondR8->setValue(sdata.fClockConditioner[2]);
1955        fClockCondR9->setValue(sdata.fClockConditioner[3]);
1956        fClockCondR11->setValue(sdata.fClockConditioner[4]);
1957        fClockCondR13->setValue(sdata.fClockConditioner[5]);
1958        fClockCondR14->setValue(sdata.fClockConditioner[6]);
1959        fClockCondR15->setValue(sdata.fClockConditioner[7]);
1960
1961        const uint32_t R0  = sdata.fClockConditioner[0];
1962        const uint32_t R14 = sdata.fClockConditioner[6];
1963        const uint32_t R15 = sdata.fClockConditioner[7];
1964
1965        const uint32_t Ndiv = (R15&0x1ffff00)<<2;
1966        const uint32_t Rdiv = (R14&0x007ff00)>>8;
1967        const uint32_t Cdiv = (R0 &0x000ff00)>>8;
1968
1969        double freq = 40.*Ndiv/(Rdiv*Cdiv);
1970
1971        fClockCondFreqRes->setValue(freq);
1972
1973        //fClockCondFreq->setEditText("");
1974        fClockCondFreq->setCurrentIndex(0);
1975
1976        fTriggerSeqPed->setValue(sdata.fTriggerSeqPed);
1977        fTriggerSeqLPint->setValue(sdata.fTriggerSeqLPint);
1978        fTriggerSeqLPext->setValue(sdata.fTriggerSeqLPext);
1979
1980        fLpIntIntensity->setValue(sdata.fIntensityLPint);
1981        fLpExtIntensity->setValue(sdata.fIntensityLPext);
1982
1983        fLpIntGroup1->setChecked(sdata.HasLPintG1());
1984        fLpIntGroup2->setChecked(sdata.HasLPintG2());
1985        fLpExtGroup1->setChecked(sdata.HasLPextG1());
1986        fLpExtGroup2->setChecked(sdata.HasLPextG2());
1987
1988        fEnableTrigger->setChecked(sdata.HasTrigger());
1989        fEnableVeto->setChecked(sdata.HasVeto());
1990        fEnableExt1->setChecked(sdata.HasExt1());
1991        fEnableExt2->setChecked(sdata.HasExt2());
1992        fEnableClockCond->setChecked(sdata.HasClockConditioner());
1993
1994        uint16_t multiplicity = sdata.fMultiplicity[0];
1995
1996        for (int i=0; i<40; i++)
1997        {
1998            if (!sdata.IsActive(i))
1999                SetFtuLed(i, -1, d.time);
2000            else
2001            {
2002                if (fFtuStatus[i]==0)
2003                    SetFtuLed(i, 1, d.time);
2004            }
2005            fFtuLED[i]->setChecked(false);
2006
2007            if (sdata.fMultiplicity[i]!=multiplicity)
2008                multiplicity = -1;
2009
2010        }
2011        SetFtuStatusLed(d.time);
2012
2013        fNoutof4Val->setValue(multiplicity);
2014
2015        for (vector<PixelMapEntry>::const_iterator it=fPixelMap.begin(); it!=fPixelMap.end(); it++)
2016            fRatesCanv->SetEnable(it->index, sdata.IsEnabled(it->hw()));
2017
2018        const PixelMapEntry &entry = fPixelMap.index(fPixelIdx->value());
2019        fPixelEnable->setChecked(sdata.IsEnabled(entry.hw()));
2020
2021        if (fThresholdIdx->value()>=0)
2022        {
2023            const int isw = fThresholdIdx->value();
2024            const int ihw = fPatchMapHW[isw];
2025            fThresholdVal->setValue(sdata.fThreshold[ihw]);
2026        }
2027
2028        fPrescalingVal->setValue(sdata.fPrescaling[0]);
2029
2030        fFtmStaticData = sdata;
2031    }
2032
2033    void handleFtmPassport(const DimData &d)
2034    {
2035        if (!CheckSize(d, sizeof(FTM::DimPassport)))
2036            return;
2037
2038        const FTM::DimPassport &sdata = d.ref<FTM::DimPassport>();
2039
2040        stringstream str1, str2;
2041        str1 << hex << "0x" << setfill('0') << setw(16) << sdata.fBoardId;
2042        str2 << sdata.fFirmwareId;
2043
2044        fFtmBoardId->setText(str1.str().c_str());
2045        fFtmFirmwareId->setText(str2.str().c_str());
2046    }
2047
2048    void handleFtmFtuList(const DimData &d)
2049    {
2050        if (!CheckSize(d, sizeof(FTM::DimFtuList)))
2051            return;
2052
2053        fFtuPing->setChecked(false);
2054
2055        const FTM::DimFtuList &sdata = d.ref<FTM::DimFtuList>();
2056
2057        stringstream str;
2058        str << "<table width='100%'>" << setfill('0');
2059        str << "<tr><th>Num</th><th></th><th>Addr</th><th></th><th>DNA</th></tr>";
2060        for (int i=0; i<40; i++)
2061        {
2062            str << "<tr>";
2063            str << "<td align='center'>"   << dec << i << hex << "</td>";
2064            str << "<td align='center'>:</td>";
2065            str << "<td align='center'>0x" << setw(2)  << (int)sdata.fAddr[i] << "</td>";
2066            str << "<td align='center'>:</td>";
2067            str << "<td align='center'>0x" << setw(16) << sdata.fDNA[i] << "</td>";
2068            str << "</tr>";
2069        }
2070        str << "</table>";
2071
2072        fFtuDNA->setText(str.str().c_str());
2073
2074        fFtuAnswersTotal->setValue(sdata.fNumBoards);
2075        fFtuAnswersCrate0->setValue(sdata.fNumBoardsCrate[0]);
2076        fFtuAnswersCrate1->setValue(sdata.fNumBoardsCrate[1]);
2077        fFtuAnswersCrate2->setValue(sdata.fNumBoardsCrate[2]);
2078        fFtuAnswersCrate3->setValue(sdata.fNumBoardsCrate[3]);
2079
2080        for (int i=0; i<40; i++)
2081            SetFtuLed(i, sdata.IsActive(i) ? sdata.fPing[i] : -1, d.time);
2082
2083        SetFtuStatusLed(d.time);
2084    }
2085
2086    void handleFtmError(const DimData &d)
2087    {
2088        if (!CheckSize(d, sizeof(FTM::DimError)))
2089            return;
2090
2091        const FTM::DimError &sdata = d.ref<FTM::DimError>();
2092
2093        SetFtuLed(sdata.fError.fDestAddress, sdata.fError.fNumCalls, d.time);
2094        SetFtuStatusLed(d.time);
2095
2096        // FIXME: Write to special window!
2097        //Out() << "Error:" << endl;
2098        //Out() << sdata.fError << endl;
2099    }
2100
2101    // ========================== FSC =======================================
2102
2103    void SetFscValue(QDoubleSpinBox *box, const DimData &d, int idx, bool enable)
2104    {
2105        //box->setEnabled(enable);
2106        if (!enable)
2107        {
2108            box->setToolTip(d.time.GetAsStr().c_str());
2109            return;
2110        }
2111
2112        ostringstream str;
2113        str << d.time << "  --  " << d.get<float>() << "s";
2114
2115        box->setToolTip(str.str().c_str());
2116        box->setValue(d.get<float>(idx*4+4));
2117    }
2118
2119
2120    void handleFscTemp(const DimData &d)
2121    {
2122        const bool enable = d.size()>0 && CheckSize(d, 60*sizeof(float));
2123        if (!enable)
2124            return;
2125
2126        QDoubleSpinBox *boxes[] = {
2127            fTempCam00, fTempCam01,
2128            fTempCam10, fTempCam11, fTempCam12, fTempCam13, fTempCam14, 
2129            fTempCam20, fTempCam21, fTempCam22, fTempCam23, fTempCam24, fTempCam25,
2130            fTempCam30, fTempCam31, fTempCam32, fTempCam33, fTempCam34, 
2131            fTempCam40, fTempCam41, fTempCam42, fTempCam43, fTempCam44, fTempCam45,
2132            fTempCam50, fTempCam51, fTempCam52, fTempCam53, fTempCam54,
2133            fTempCam60, fTempCam61,
2134            // 0:b/f 1:b/f 2:b/f 3:b/f
2135            fTempCrate0back, fTempCrate0front,
2136            fTempCrate1back, fTempCrate1front,
2137            fTempCrate2back, fTempCrate2front,
2138            fTempCrate3back, fTempCrate3front,
2139            // 0:b/f 1:b/f 2:b/f 3:b/f
2140            fTempPS0back, fTempPS0front,
2141            fTempPS1back, fTempPS1front,
2142            fTempPS2back, fTempPS2front,
2143            fTempPS3back, fTempPS3front,
2144            // AUX PS:  FTM t/b; FSC t/b
2145            fTempAuxFTMtop, fTempAuxFTMbottom,
2146            fTempAuxFSCtop, fTempAuxFSCbottom,
2147            // Backpanel:  FTM t/b; FSC t/b
2148            fTempBackpanelFTMtop, fTempBackpanelFTMbottom,
2149            fTempBackpanelFSCtop, fTempBackpanelFSCbottom,
2150            // top front/back; bottom front/back
2151            fTempSwitchboxTopFront,    fTempSwitchboxTopBack,
2152            fTempSwitchboxBottomFront, fTempSwitchboxBottomBack,
2153        };
2154
2155        for (int i=0; i<59; i++)
2156            SetFscValue(boxes[i], d, i, enable);
2157
2158        if (!enable)
2159            return;
2160
2161        const float *ptr = d.ptr<float>();
2162
2163        double avg = 0;
2164        int    num = 0;
2165        for (int i=1; i<32; i++)
2166            if (ptr[i]!=0)
2167            {
2168                avg += ptr[i];
2169                num ++;
2170            }
2171
2172        fTempCamAvg->setValue(num?avg/num:0);
2173    }
2174
2175    void handleFscVolt(const DimData &d)
2176    {
2177        const bool enable = d.size()>0 && CheckSize(d, 31*sizeof(float));
2178        if (!enable)
2179            return;
2180
2181        QDoubleSpinBox *boxes[] = {
2182            fVoltFad00, fVoltFad10, fVoltFad20, fVoltFad30,
2183            fVoltFad01, fVoltFad11, fVoltFad21, fVoltFad31,
2184            fVoltFad02, fVoltFad12, fVoltFad22, fVoltFad32,
2185            fVoltFPA00, fVoltFPA10, fVoltFPA20, fVoltFPA30,
2186            fVoltFPA01, fVoltFPA11, fVoltFPA21, fVoltFPA31,
2187            fVoltFPA02, fVoltFPA12, fVoltFPA22, fVoltFPA32,
2188            fVoltETH0,  fVoltETH1,
2189            fVoltFTM0,  fVoltFTM1,
2190            fVoltFFC,   fVoltFLP,
2191        };
2192
2193        for (int i=0; i<30; i++)
2194            SetFscValue(boxes[i], d, i, enable);
2195    }
2196
2197    void handleFscCurrent(const DimData &d)
2198    {
2199        const bool enable = d.size()>0 && CheckSize(d, 31*sizeof(float));
2200        if (!enable)
2201            return;
2202
2203        QDoubleSpinBox *boxes[] = {
2204            fAmpFad00, fAmpFad10, fAmpFad20, fAmpFad30,
2205            fAmpFad01, fAmpFad11, fAmpFad21, fAmpFad31,
2206            fAmpFad02, fAmpFad12, fAmpFad22, fAmpFad32,
2207            fAmpFPA00, fAmpFPA10, fAmpFPA20, fAmpFPA30,
2208            fAmpFPA01, fAmpFPA11, fAmpFPA21, fAmpFPA31,
2209            fAmpFPA02, fAmpFPA12, fAmpFPA22, fAmpFPA32,
2210            fAmpETH0,  fAmpETH1,
2211            fAmpFTM0,  fAmpFTM1,
2212            fAmpFFC,   fAmpFLP,
2213        };
2214
2215        for (int i=0; i<30; i++)
2216            SetFscValue(boxes[i], d, i, enable);
2217    }
2218
2219    void handleFscHumidity(const DimData &d)
2220    {
2221        const bool enable = d.size()>0 && CheckSize(d, 5*sizeof(float));
2222
2223        SetFscValue(fHumidity1, d, 0, enable);
2224        SetFscValue(fHumidity2, d, 1, enable);
2225        SetFscValue(fHumidity3, d, 2, enable);
2226        SetFscValue(fHumidity4, d, 3, enable);
2227    }
2228
2229    // ========================== Feedback ==================================
2230
2231#ifdef HAVE_ROOT
2232    TGraphErrors fGraphFeedbackDev;
2233    TGraphErrors fGraphFeedbackCmd;
2234
2235    void UpdateFeedback(TQtWidget &rwidget, const Time &time, TGraphErrors &graph, double avg, double rms)
2236    {
2237        TCanvas *c = rwidget.GetCanvas();
2238
2239        TH1 *h = (TH1*)c->FindObject("TimeFrame");
2240
2241        while (graph.GetN()>500)
2242            graph.RemovePoint(0);
2243
2244        const double now = time.RootTime();
2245
2246        while (graph.GetN()>0 && now-graph.GetX()[0]>3600)
2247            graph.RemovePoint(0);
2248
2249        const int n = graph.GetN();
2250
2251        const double xmin = n>0 ? graph.GetX()[0] : now;
2252
2253        h->SetBins(n+1, xmin-1, now+1);
2254        graph.SetPoint(n, now, avg);
2255        graph.SetPointError(n, 0, rms);
2256
2257        h->GetXaxis()->SetTimeFormat(now-xmin>300 ? "%Hh%M'%F1995-01-01 00:00:00 GMT" : "%M'%S\"%F1995-01-01 00:00:00 GMT");
2258
2259        c->Modified();
2260        c->Update();
2261    }
2262#endif
2263
2264    vector <float> fVecFeedbackCurrents;
2265
2266    void handleFeedbackCalibratedCurrents(const DimData &d)
2267    {
2268        if (!CheckSize(d, (416+1+1+1+1+1+416+1+1)*sizeof(float)+sizeof(uint32_t)))
2269            return;
2270
2271        const float *ptr = d.ptr<float>();
2272        const float *Uov = ptr+416+6;
2273
2274        fVecFeedbackCurrents.assign(ptr, ptr+416);
2275
2276        valarray<double> datc(0., 1440);
2277        valarray<double> datu(0., 1440);
2278
2279        // fPatch converts from software id to software patch id
2280        for (int i=0; i<1440; i++)
2281        {
2282            const PixelMapEntry &entry = fPixelMap.index(i);
2283
2284            datc[i] = fVecFeedbackCurrents[entry.hv()];
2285            datu[i] = Uov[entry.hv()];
2286
2287            if (fVecBiasCurrent.size()>0)
2288            {
2289                fBiasCamA->SetEnable(i, uint16_t(fVecBiasCurrent[entry.hv()])!=0x8000);
2290                fBiasCamA->highlightPixel(i, fVecBiasCurrent[entry.hv()]<0);
2291            }
2292        }
2293
2294        fBiasCamA->SetData(datc);
2295        fBiasCamA->updateCamera();
2296
2297        UpdateBiasValues();
2298
2299        // --------------------------------------------------------
2300
2301        double avg = 0;
2302        double rms = 0;
2303
2304        for (int i=0; i<320; i++)
2305        {
2306            avg += Uov[i];
2307            rms += Uov[i]*Uov[i];
2308        }
2309
2310        avg /= 320;
2311        rms /= 320;
2312        rms = sqrt(rms-avg*avg);
2313
2314
2315        fFeedbackDevCam->SetData(datu);
2316        //fFeedbackCmdCam->SetData(cmd);
2317
2318        fFeedbackDevCam->updateCamera();
2319        //fFeedbackCmdCam->updateCamera();
2320
2321#ifdef HAVE_ROOT
2322        UpdateFeedback(*fFeedbackDev, d.time, fGraphFeedbackDev, avg, rms);
2323        //UpdateFeedback(*fFeedbackCmd, d.time, fGraphFeedbackCmd, avgcmd, rmscmd);
2324#endif
2325    }
2326
2327    // ======================= Rate Scan ====================================
2328#ifdef HAVE_ROOT
2329    TGraph fGraphRateScan[201];
2330#endif
2331    void UpdateRateScan(uint32_t th, const float *rates)
2332    {
2333#ifdef HAVE_ROOT
2334        TCanvas *c = fRateScanCanv->GetCanvas();
2335
2336        TH1 *h = (TH1*)c->FindObject("Frame");
2337
2338        if (fGraphRateScan[0].GetN()==0 || th<fGraphRateScan[0].GetX()[fGraphRateScan[0].GetN()-1])
2339        {
2340            h->SetBins(1, th<10 ? 0 : th-10, th+10);
2341            h->SetMinimum(1);
2342            h->SetMaximum(rates[0]*2);
2343
2344            for (int i=0; i<201; i++)
2345            {
2346                fGraphRateScan[i].Set(0);
2347                fGraphRateScan[i].SetPoint(fGraphRateScan[i].GetN(), th, rates[i]);
2348            }
2349
2350            c->SetGrid();
2351            c->SetLogy();
2352
2353            c->Modified();
2354            c->Update();
2355            return;
2356        }
2357
2358        const double dac = h->GetXaxis()->GetXmin();
2359        h->SetBins(h->GetNbinsX()+1, dac, th+10);
2360
2361        for (int i=0; i<201; i++)
2362            fGraphRateScan[i].SetPoint(fGraphRateScan[i].GetN(), th, rates[i]);
2363
2364        c->Modified();
2365        c->Update();
2366#endif
2367    }
2368
2369    void DisplayRateScan()
2370    {
2371#ifdef HAVE_ROOT
2372        TCanvas *c = fRateScanCanv->GetCanvas();
2373
2374        TList *l = c->GetListOfPrimitives();
2375
2376        while (c->FindObject("PatchRate"))
2377            l->Remove(c->FindObject("PatchRate"));
2378
2379        while (c->FindObject("BoardRate"))
2380            l->Remove(c->FindObject("BoardRate"));
2381
2382        if (fRateScanPatch1->value()>=0)
2383        {
2384            fGraphRateScan[fRateScanPatch1->value()+41].SetLineColor(kRed);
2385            fGraphRateScan[fRateScanPatch1->value()+41].SetMarkerColor(kRed);
2386            l->Add(&fGraphRateScan[fRateScanPatch1->value()+41], "PL");
2387        }
2388        if (fRateScanPatch2->value()>=0)
2389        {
2390            fGraphRateScan[fRateScanPatch2->value()+41].SetLineColor(kGreen);
2391            fGraphRateScan[fRateScanPatch2->value()+41].SetMarkerColor(kGreen);
2392            l->Add(&fGraphRateScan[fRateScanPatch2->value()+41], "PL");
2393        }
2394        if (fRateScanBoard1->value()>=0)
2395        {
2396            fGraphRateScan[fRateScanBoard1->value()+1].SetLineColor(kMagenta);
2397            fGraphRateScan[fRateScanBoard1->value()+1].SetMarkerColor(kMagenta);
2398            l->Add(&fGraphRateScan[fRateScanBoard1->value()+1], "PL");
2399        }
2400        if (fRateScanBoard2->value()>=0)
2401        {
2402            fGraphRateScan[fRateScanBoard2->value()+1].SetLineColor(kCyan);
2403            fGraphRateScan[fRateScanBoard2->value()+1].SetMarkerColor(kCyan);
2404            l->Add(&fGraphRateScan[fRateScanBoard2->value()+1], "PL");
2405        }
2406
2407        c->Modified();
2408        c->Update();
2409#endif
2410    }
2411
2412    void handleRateScan(const DimData &d)
2413    {
2414        if (!CheckSize(d, 206*sizeof(float)))
2415            return;
2416
2417        UpdateRateScan(d.get<uint32_t>(8), d.ptr<float>(20));
2418    }
2419
2420    // ===================== MAGIC Weather ==================================
2421
2422    void handleMagicWeather(const DimData &d)
2423    {
2424        if (!CheckSize(d, 7*sizeof(float)+sizeof(uint16_t)))
2425            return;
2426
2427        const float *ptr = d.ptr<float>(2);
2428
2429        fMagicTemp->setValue(ptr[0]);
2430        fMagicDew->setValue(ptr[1]);
2431        fMagicHum->setValue(ptr[2]);
2432        fMagicPressure->setValue(ptr[3]);
2433        fMagicWind->setValue(ptr[4]);
2434        fMagicGusts->setValue(ptr[5]);
2435
2436        static const char *dir[] =
2437        {
2438            "N", "NNE", "NE", "ENE",
2439            "E", "ESE", "SE", "SSE",
2440            "S", "SSW", "SW", "WSW",
2441            "W", "WNW", "NW", "NNW"
2442        };
2443
2444        const uint16_t i = uint16_t(floor(fmod(ptr[6]+11.25, 360)/22.5));
2445        fMagicWindDir->setText(dir[i%16]);
2446    }
2447
2448    // ========================== FSC =======================================
2449
2450    vector<float>   fVecBiasVolt;
2451    vector<int16_t> fVecBiasDac;
2452    vector<int16_t> fVecBiasCurrent;
2453
2454    void handleBiasVolt(const DimData &d)
2455    {
2456        if (!CheckSize(d, 416*sizeof(float)))
2457            return;
2458
2459        const float *ptr = d.ptr<float>();
2460        fVecBiasVolt.assign(ptr, ptr+416);
2461
2462        on_fBiasDispRefVolt_stateChanged();
2463    }
2464
2465    void handleBiasDac(const DimData &d)
2466    {
2467        if (!CheckSize(d, 2*416*sizeof(int16_t)))
2468            return;
2469
2470        const int16_t *ptr = d.ptr<int16_t>();
2471        fVecBiasDac.assign(ptr, ptr+2*416);
2472
2473        on_fBiasDispRefVolt_stateChanged();
2474        UpdateBiasValues();
2475    }
2476
2477    int fStateFeedback;
2478
2479    void handleBiasCurrent(const DimData &d)
2480    {
2481        if (!CheckSize(d, 416*sizeof(int16_t)))
2482            return;
2483
2484        const int16_t *ptr = d.ptr<int16_t>();
2485
2486        fVecBiasCurrent.assign(ptr, ptr+416);
2487
2488        valarray<double> dat(0., 1440);
2489
2490        // fPatch converts from software id to software patch id
2491        for (int i=0; i<1440; i++)
2492        {
2493            const PixelMapEntry &entry = fPixelMap.index(i);
2494
2495            dat[i] = abs(ptr[entry.hv()]) * 5000./4096;
2496
2497            fBiasCamA->SetEnable(i, uint16_t(ptr[entry.hv()])!=0x8000);
2498            fBiasCamA->highlightPixel(i, ptr[entry.hv()]<0);
2499        }
2500
2501        if (fStateFeedback<Feedback::State::kCalibrated)
2502            fBiasCamA->SetData(dat);
2503
2504        fBiasCamA->updateCamera();
2505
2506        UpdateBiasValues();
2507    }
2508
2509    // ====================== MessageImp ====================================
2510
2511    bool fChatOnline;
2512
2513    void handleStateChanged(const Time &time, const string &server,
2514                            const State &s)
2515    {
2516        // FIXME: Prefix tooltip with time
2517        if (server=="MCP")
2518        {
2519            // FIXME: Enable FTU page!!!
2520            fStatusMCPLabel->setText(s.name.c_str());
2521            fStatusMCPLabel->setToolTip(s.comment.c_str());
2522
2523            if (s.index<MCP::State::kDisconnected) // No Dim connection
2524                SetLedColor(fStatusMCPLed, kLedGray, time);
2525            if (s.index==MCP::State::kDisconnected) // Disconnected
2526                SetLedColor(fStatusMCPLed, kLedRed, time);
2527            if (s.index==MCP::State::kConnecting) // Connecting
2528                SetLedColor(fStatusMCPLed, kLedOrange, time);
2529            if (s.index==MCP::State::kConnected) // Connected
2530                SetLedColor(fStatusMCPLed, kLedYellow, time);
2531            if (s.index==MCP::State::kIdle || s.index>=MCP::State::kConfigured) // Idle, TriggerOn, TakingData
2532                SetLedColor(fStatusMCPLed, kLedGreen, time);
2533
2534            if (s.index>MCP::State::kIdle && s.index<MCP::State::kConfigured)
2535                SetLedColor(fStatusMCPLed, kLedGreenBar, time);
2536
2537            fMcpStartRun->setEnabled(s.index>=MCP::State::kIdle);
2538            fMcpStopRun->setEnabled(s.index>=MCP::State::kIdle);
2539            fMcpReset->setEnabled(s.index>=MCP::State::kIdle && MCP::State::kConfigured);
2540        }
2541
2542        if (server=="FTM_CONTROL")
2543        {
2544            // FIXME: Enable FTU page!!!
2545            fStatusFTMLabel->setText(s.name.c_str());
2546            fStatusFTMLabel->setToolTip(s.comment.c_str());
2547
2548            bool enable = false;
2549            const bool configuring =
2550                s.index==FTM::State::kConfiguring1 ||
2551                s.index==FTM::State::kConfiguring2 ||
2552                s.index==FTM::State::kConfigured1  ||
2553                s.index==FTM::State::kConfigured2;
2554
2555            if (s.index<FTM::State::kDisconnected) // No Dim connection
2556                SetLedColor(fStatusFTMLed, kLedGray, time);
2557            if (s.index==FTM::State::kDisconnected) // Dim connection / FTM disconnected
2558                SetLedColor(fStatusFTMLed, kLedYellow, time);
2559            if (s.index==FTM::State::kConnected    ||
2560                s.index==FTM::State::kIdle         ||
2561                s.index==FTM::State::kValid        ||
2562                configuring) // Dim connection / FTM connected
2563                SetLedColor(fStatusFTMLed, kLedGreen, time);
2564            if (s.index==FTM::State::kTriggerOn) // Dim connection / FTM connected
2565                SetLedColor(fStatusFTMLed, kLedGreenCheck, time);
2566            if (s.index==FTM::State::kConnected ||
2567                s.index==FTM::State::kIdle ||
2568                s.index==FTM::State::kValid) // Dim connection / FTM connected
2569                enable = true;
2570            if (s.index>=FTM::State::kConfigError1) // Dim connection / FTM connected
2571                SetLedColor(fStatusFTMLed, kLedGreenWarn, time);
2572
2573            fFtmStartRun->setEnabled(!configuring && enable && s.index!=FTM::State::kTriggerOn);
2574            fFtmStopRun->setEnabled(!configuring && !enable);
2575
2576            fTriggerWidget->setEnabled(enable);
2577            fFtuGroupEnable->setEnabled(enable);
2578            fRatesControls->setEnabled(enable);
2579            fFtuWidget->setEnabled(s.index>FTM::State::kDisconnected);
2580
2581            if (s.index>=FTM::State::kConnected)
2582                SetFtuStatusLed(time);
2583            else
2584            {
2585                SetLedColor(fStatusFTULed, kLedGray, time);
2586                fStatusFTULabel->setText("Offline");
2587                fStatusFTULabel->setToolTip("FTM is not online.");
2588            }
2589        }
2590
2591        if (server=="FAD_CONTROL")
2592        {
2593            fStatusFADLabel->setText(s.name.c_str());
2594            fStatusFADLabel->setToolTip(s.comment.c_str());
2595
2596            bool enable = false;
2597
2598            if (s.index<FAD::State::kOffline) // No Dim connection
2599            {
2600                SetLedColor(fStatusFADLed, kLedGray, time);
2601
2602                // Timing problem - sometimes they stay gray :(
2603                //for (int i=0; i<40; i++)
2604                //    SetLedColor(fFadLED[i], kLedGray, time);
2605
2606                /*
2607                 fStatusEventBuilderLabel->setText("Offline");
2608                 fStatusEventBuilderLabel->setToolTip("No connection to fadctrl.");
2609                 fEvtBldWidget->setEnabled(false);
2610
2611                 SetLedColor(fStatusEventBuilderLed, kLedGray, time);
2612                 */
2613            }
2614            if (s.index==FAD::State::kOffline) // Dim connection / FTM disconnected
2615                SetLedColor(fStatusFADLed, kLedRed, time);
2616            if (s.index==FAD::State::kDisconnected) // Dim connection / FTM disconnected
2617                SetLedColor(fStatusFADLed, kLedOrange, time);
2618            if (s.index==FAD::State::kConnecting) // Dim connection / FTM disconnected
2619            {
2620                SetLedColor(fStatusFADLed, kLedYellow, time);
2621                // FIXME FIXME FIXME: The LEDs are not displayed when disabled!
2622                enable = true;
2623            }
2624            if (s.index>=FAD::State::kConnected) // Dim connection / FTM connected
2625            {
2626                SetLedColor(fStatusFADLed, kLedGreen, time);
2627                enable = true;
2628            }
2629
2630            fFadWidget->setEnabled(enable);
2631
2632            fFadStart->setEnabled    (s.index==FAD::State::kOffline);
2633            fFadStop->setEnabled     (s.index >FAD::State::kOffline);
2634            fFadAbort->setEnabled    (s.index >FAD::State::kOffline);
2635            fFadSoftReset->setEnabled(s.index >FAD::State::kOffline);
2636            fFadHardReset->setEnabled(s.index >FAD::State::kOffline);
2637        }
2638
2639        if (server=="FSC_CONTROL")
2640        {
2641            fStatusFSCLabel->setText(s.name.c_str());
2642            fStatusFSCLabel->setToolTip(s.comment.c_str());
2643
2644            bool enable = false;
2645
2646            if (s.index<FSC::State::kDisconnected)  // No Dim connection
2647                SetLedColor(fStatusFSCLed, kLedGray, time);
2648            if (s.index==FSC::State::kDisconnected) // Dim connection / FTM disconnected
2649                SetLedColor(fStatusFSCLed, kLedRed, time);
2650            if (s.index>=FSC::State::kConnected)    // Dim connection / FTM disconnected
2651            {
2652                SetLedColor(fStatusFSCLed, kLedGreen, time);
2653                enable = true;
2654            }
2655
2656            fAuxWidget->setEnabled(enable);
2657        }
2658
2659        if (server=="DRIVE_CONTROL")
2660        {
2661            fStatusDriveLabel->setText(s.name.c_str());
2662            fStatusDriveLabel->setToolTip(s.comment.c_str());
2663
2664            if (s.index<Drive::State::kDisconnected) // No Dim connection
2665                SetLedColor(fStatusDriveLed, kLedGray, time);
2666            if (s.index==Drive::State::kDisconnected) // Dim connection / No connection to cosy
2667                SetLedColor(fStatusDriveLed, kLedRed, time);
2668            if (s.index==Drive::State::kConnected || /*s.index==Drive::State::kNotReady ||*/ s.index==Drive::State::kLocked)  // Not Ready
2669                SetLedColor(fStatusDriveLed, kLedGreenBar, time);
2670            if (s.index==Drive::State::kConnected || s.index==Drive::State::kArmed)  // Connected / Armed
2671                SetLedColor(fStatusDriveLed, kLedGreen, time);
2672            if (s.index==Drive::State::kMoving)  // Moving
2673                SetLedColor(fStatusDriveLed, kLedInProgress, time);
2674            if (s.index==Drive::State::kTracking || s.index==Drive::State::kOnTrack)  // Tracking
2675                SetLedColor(fStatusDriveLed, kLedGreenCheck, time);
2676            if (s.index>=0xff)  // Error
2677                SetLedColor(fStatusDriveLed, kLedGreenWarn, time);
2678        }
2679
2680        if (server=="BIAS_CONTROL")
2681        {
2682            fStatusBiasLabel->setText(s.name.c_str());
2683            fStatusBiasLabel->setToolTip(s.comment.c_str());
2684
2685            if (s.index<1) // No Dim connection
2686                SetLedColor(fStatusBiasLed, kLedGray, time);
2687            if (s.index==BIAS::State::kDisconnected) // Dim connection / FTM disconnected
2688                SetLedColor(fStatusBiasLed, kLedRed, time);
2689            if (s.index==BIAS::State::kConnecting || s.index==BIAS::State::kInitializing) // Connecting / Initializing
2690                SetLedColor(fStatusBiasLed, kLedOrange, time);
2691            if (s.index==BIAS::State::kVoltageOff || BIAS::State::kLocked) // At reference
2692                SetLedColor(fStatusBiasLed, kLedGreenBar, time);
2693            if (s.index==BIAS::State::kNotReferenced) // At reference
2694                SetLedColor(fStatusBiasLed, kLedGreenWarn, time);
2695            if (s.index==BIAS::State::kRamping) // Ramping
2696                SetLedColor(fStatusBiasLed, kLedInProgress, time);
2697            if (s.index==BIAS::State::kVoltageOn) // At reference
2698                SetLedColor(fStatusBiasLed, kLedGreenCheck, time);
2699            if (s.index==BIAS::State::kOverCurrent) // Over current
2700                SetLedColor(fStatusBiasLed, kLedWarnBorder, time);
2701            if (s.index==BIAS::State::kExpertMode) // ExpertMode
2702                SetLedColor(fStatusBiasLed, kLedWarnTriangleBorder, time);
2703
2704            fBiasWidget->setEnabled(s.index>=BIAS::State::kInitializing);
2705        }
2706
2707        if (server=="FEEDBACK")
2708        {
2709            fStatusFeedbackLabel->setText(s.name.c_str());
2710            fStatusFeedbackLabel->setToolTip(s.comment.c_str());
2711
2712            const bool connected = s.index> Feedback::State::kConnecting;
2713            const bool idle      = s.index==Feedback::State::kCalibrated || s.index==Feedback::State::kWaitingForData;
2714
2715            if (s.index<=Feedback::State::kConnecting) // NoDim / Disconnected
2716                SetLedColor(fStatusFeedbackLed, kLedRed, time);
2717            if (s.index<Feedback::State::kDisconnected) // No Dim connection
2718                SetLedColor(fStatusFeedbackLed, kLedGray, time);
2719            if (s.index==Feedback::State::kConnecting) // Connecting
2720                SetLedColor(fStatusFeedbackLed, kLedOrange, time);
2721            if (connected) // Connected
2722                SetLedColor(fStatusFeedbackLed, kLedYellow, time);
2723            if (idle)
2724                SetLedColor(fStatusFeedbackLed, kLedGreen, time);
2725            if (s.index==Feedback::State::kInProgress)
2726                SetLedColor(fStatusFeedbackLed, kLedGreenCheck, time);
2727            if (s.index==Feedback::State::kCalibrating)
2728                SetLedColor(fStatusFeedbackLed, kLedInProgress, time);
2729
2730            fFeedbackWidget->setEnabled(connected);
2731
2732            fFeedbackCalibrate->setEnabled(s.index==Feedback::State::kConnected || s.index==Feedback::State::kCalibrated);
2733            fFeedbackStart->setEnabled(s.index==Feedback::State::kCalibrated);
2734            fFeedbackStop->setEnabled(s.index>Feedback::State::kCalibrated);
2735            fFeedbackOvervoltage->setEnabled(connected);
2736
2737            const bool enable = s.index>=Feedback::State::kCalibrated;
2738
2739            fFeedbackFrameLeft->setEnabled(enable);
2740            fFeedbackCanvLeft->setEnabled(enable);
2741
2742            fStateFeedback = s.index;
2743        }
2744
2745        if (server=="RATE_CONTROL")
2746        {
2747            fStatusRateControlLabel->setText(s.name.c_str());
2748            fStatusRateControlLabel->setToolTip(s.comment.c_str());
2749
2750            if (s.index==RateControl::State::kInProgress)
2751                SetLedColor(fStatusRateControlLed, kLedGreenCheck, time);
2752            if (s.index==RateControl::State::kGlobalThresholdSet)
2753                SetLedColor(fStatusRateControlLed, kLedGreen, time);
2754            if (s.index==RateControl::State::kSettingGlobalThreshold)
2755                SetLedColor(fStatusRateControlLed, kLedInProgress, time);
2756            if (s.index==RateControl::State::kConnected)
2757                SetLedColor(fStatusRateControlLed, kLedGreenBar, time);
2758            if (s.index==RateControl::State::kConnecting)
2759                SetLedColor(fStatusRateControlLed, kLedOrange, time);
2760            if (s.index<RateControl::State::kConnecting)
2761                SetLedColor(fStatusRateControlLed, kLedRed, time);
2762            if (s.index<RateControl::State::kDisconnected)
2763                SetLedColor(fStatusRateControlLed, kLedGray, time);
2764        }
2765
2766        if (server=="DATA_LOGGER")
2767        {
2768            fStatusLoggerLabel->setText(s.name.c_str());
2769            fStatusLoggerLabel->setToolTip(s.comment.c_str());
2770
2771            bool enable = true;
2772
2773            if (s.index<30)   // Ready/Waiting
2774                SetLedColor(fStatusLoggerLed, kLedYellow, time);
2775            if (s.index==30)   // Ready/Waiting
2776                SetLedColor(fStatusLoggerLed, kLedGreen, time);
2777            if (s.index<-1)     // Offline
2778            {
2779                SetLedColor(fStatusLoggerLed, kLedGray, time);
2780                enable = false;
2781            }
2782            if (s.index>=0x100) // Error
2783                SetLedColor(fStatusLoggerLed, kLedRed, time);
2784            if (s.index==40)   // Logging
2785                SetLedColor(fStatusLoggerLed, kLedGreen, time);
2786
2787            fLoggerWidget->setEnabled(enable);
2788            fLoggerStart->setEnabled(s.index>-1 && s.index<30);
2789            fLoggerStop->setEnabled(s.index>=30);
2790        }
2791
2792        if (server=="MAGIC_WEATHER")
2793        {
2794            fStatusWeatherLabel->setText(s.name.c_str());
2795
2796            if (s.index==MagicWeather::State::kReceiving)
2797                SetLedColor(fStatusWeatherLed, kLedGreen, time);
2798            if (s.index<MagicWeather::State::kReceiving)
2799                SetLedColor(fStatusWeatherLed, kLedRed, time);
2800            if (s.index<MagicWeather::State::kConnected)
2801                SetLedColor(fStatusWeatherLed, kLedGray, time);
2802        }
2803
2804        if (server=="CHAT")
2805        {
2806            fStatusChatLabel->setText(s.name.c_str());
2807
2808            fChatOnline = s.index==0;
2809
2810            SetLedColor(fStatusChatLed, fChatOnline ? kLedGreen : kLedGray, time);
2811
2812            fChatSend->setEnabled(fChatOnline);
2813            fChatMessage->setEnabled(fChatOnline);
2814        }
2815
2816        if (server=="RATESCAN")
2817            fRateScanControls->setEnabled(s.index>=RateScan::State::kConnected);
2818
2819        if (server=="SCHEDULER")
2820        {
2821            fStatusSchedulerLabel->setText(s.name.c_str());
2822
2823            SetLedColor(fStatusSchedulerLed, s.index>=0 ? kLedGreen : kLedRed, time);
2824        }
2825    }
2826
2827    void on_fTabWidget_currentChanged(int which)
2828    {
2829        if (fTabWidget->tabText(which)=="Chat")
2830            fTabWidget->setTabIcon(which, QIcon());
2831    }
2832
2833    void handleWrite(const Time &time, const string &text, int qos)
2834    {
2835        stringstream out;
2836
2837        if (text.substr(0, 6)=="CHAT: ")
2838        {
2839            if (qos==MessageImp::kDebug)
2840                return;
2841
2842            out << "<font size='-1' color='navy'>[<B>";
2843            out << time.GetAsStr("%H:%M:%S");
2844            out << "</B>]</FONT>  " << text.substr(6);
2845            fChatText->append(out.str().c_str());
2846
2847            if (fTabWidget->tabText(fTabWidget->currentIndex())=="Chat")
2848                return;
2849
2850            static int num = 0;
2851            if (num++<2)
2852                return;
2853
2854            for (int i=0; i<fTabWidget->count(); i++)
2855                if (fTabWidget->tabText(i)=="Chat")
2856                {
2857                    fTabWidget->setTabIcon(i, QIcon(":/Resources/icons/warning 3.png"));
2858                    break;
2859                }
2860
2861            return;
2862        }
2863
2864
2865        out << "<font style='font-family:monospace' color='";
2866
2867        switch (qos)
2868        {
2869        case kMessage: out << "black";   break;
2870        case kInfo:    out << "green";   break;
2871        case kWarn:    out << "#FF6600"; break;
2872        case kError:   out << "maroon";  break;
2873        case kFatal:   out << "maroon";  break;
2874        case kDebug:   out << "navy";    break;
2875        default:       out << "navy";    break;
2876        }
2877        out << "'>";
2878        out << time.GetAsStr("%H:%M:%S.%f").substr(0,12);
2879        out << " - " << text << "</font>";
2880
2881        fLogText->append(out.str().c_str());
2882
2883        if (qos>=kWarn && qos!=kDebug && qos!=kComment)
2884            fTextEdit->append(out.str().c_str());
2885    }
2886
2887    void IndicateStateChange(const Time &time, const string &server)
2888    {
2889        const State s = GetState(server, GetCurrentState(server));
2890
2891        QApplication::postEvent(this,
2892           new FunctionEvent(bind(&FactGui::handleStateChanged, this, time, server, s)));
2893    }
2894
2895    int Write(const Time &time, const string &txt, int qos)
2896    {
2897        QApplication::postEvent(this,
2898           new FunctionEvent(bind(&FactGui::handleWrite, this, time, txt, qos)));
2899
2900        return 0;
2901    }
2902
2903    // ====================== Dim infoHandler================================
2904
2905    void handleDimService(const string &txt)
2906    {
2907        fDimSvcText->append(txt.c_str());
2908    }
2909
2910    void infoHandlerService(DimInfo &info)
2911    {
2912        const string fmt = string(info.getFormat()).empty() ? "C" : info.getFormat();
2913
2914        stringstream dummy;
2915        const Converter conv(dummy, fmt, false);
2916
2917        const Time tm(info.getTimestamp(), info.getTimestampMillisecs()*1000);
2918
2919        stringstream out;
2920        out << "<font size'-1' color='navy'>[";
2921        out << tm.GetAsStr("%H:%M:%S.%f").substr(0,12);
2922        out << "]</font>   <B>" << info.getName() << "</B> - ";
2923
2924        uint8_t iserr = 2;
2925        if (!conv)
2926        {
2927            out << "Compilation of format string '" << fmt << "' failed!";
2928        }
2929        else
2930        {
2931            try
2932            {
2933                const string dat = info.getSize()==0 ? "&lt;empty&gt;" : conv.GetString(info.getData(), info.getSize());
2934                out << dat;
2935                iserr = info.getSize()==0;
2936            }
2937            catch (const runtime_error &e)
2938            {
2939                out << "Conversion to string failed!<pre>" << e.what() << "</pre>";
2940            }
2941        }
2942
2943        // srand(hash<string>()(string(info.getName())));
2944        // int bg = rand()&0xffffff;
2945
2946        int bg = hash<string>()(string(info.getName()));
2947
2948        // allow only light colors
2949        bg = ~(bg&0x1f1f1f)&0xffffff;
2950
2951        if (iserr==2)
2952            bg = 0xffffff;
2953
2954        stringstream bgcol;
2955        bgcol << hex << setfill('0') << setw(6) << bg;
2956
2957        const string col = iserr==0 ? "black" : (iserr==1 ? "#FF6600" : "black");
2958        const string str = "<table width='100%' bgcolor=#"+bgcol.str()+"><tr><td><font color='"+col+"'>"+out.str()+"</font></td></tr></table>";
2959
2960        QApplication::postEvent(this,
2961                                new FunctionEvent(bind(&FactGui::handleDimService, this, str)));
2962    }
2963
2964    void CallInfoHandler(void (FactGui::*handler)(const DimData&), const DimData &d)
2965    {
2966        fInHandler = true;
2967        (this->*handler)(d);
2968        fInHandler = false;
2969    }
2970
2971    /*
2972    void CallInfoHandler(const boost::function<void()> &func)
2973    {
2974        // This ensures that newly received values are not sent back to the emitter
2975        // because changing the value emits the valueChanged signal (or similar)
2976        fInHandler = true;
2977        func();
2978        fInHandler = false;
2979    }*/
2980
2981    void PostInfoHandler(void (FactGui::*handler)(const DimData&))
2982    {
2983        //const boost::function<void()> f = boost::bind(handler, this, DimData(getInfo()));
2984
2985        FunctionEvent *evt = new FunctionEvent(bind(&FactGui::CallInfoHandler, this, handler, DimData(getInfo())));
2986        // FunctionEvent *evt = new FunctionEvent(boost::bind(&FactGui::CallInfoHandler, this, f));
2987        // FunctionEvent *evt = new FunctionEvent(boost::bind(handler, this, DimData(getInfo()))));
2988
2989        QApplication::postEvent(this, evt);
2990    }
2991
2992    void infoHandler()
2993    {
2994        // Initialize the time-stamp (what a weird workaround...)
2995        if (getInfo())
2996            getInfo()->getTimestamp();
2997
2998        if (getInfo()==&fDimDNS)
2999            return PostInfoHandler(&FactGui::handleDimDNS);
3000#ifdef DEBUG_DIM
3001        cout << "HandleDimInfo " << getInfo()->getName() << endl;
3002#endif
3003        if (getInfo()==&fDimLoggerStats)
3004            return PostInfoHandler(&FactGui::handleLoggerStats);
3005
3006//        if (getInfo()==&fDimFadFiles)
3007//            return PostInfoHandler(&FactGui::handleFadFiles);
3008
3009        if (getInfo()==&fDimFadWriteStats)
3010            return PostInfoHandler(&FactGui::handleFadWriteStats);
3011
3012        if (getInfo()==&fDimFadConnections)
3013            return PostInfoHandler(&FactGui::handleFadConnections);
3014
3015        if (getInfo()==&fDimFadFwVersion)
3016            return PostInfoHandler(&FactGui::handleFadFwVersion);
3017
3018        if (getInfo()==&fDimFadRunNumber)
3019            return PostInfoHandler(&FactGui::handleFadRunNumber);
3020
3021        if (getInfo()==&fDimFadDNA)
3022            return PostInfoHandler(&FactGui::handleFadDNA);
3023
3024        if (getInfo()==&fDimFadTemperature)
3025            return PostInfoHandler(&FactGui::handleFadTemperature);
3026
3027        if (getInfo()==&fDimFadRefClock)
3028            return PostInfoHandler(&FactGui::handleFadRefClock);
3029
3030        if (getInfo()==&fDimFadRoi)
3031            return PostInfoHandler(&FactGui::handleFadRoi);
3032
3033        if (getInfo()==&fDimFadDac)
3034            return PostInfoHandler(&FactGui::handleFadDac);
3035
3036        if (getInfo()==&fDimFadDrsCalibration)
3037            return PostInfoHandler(&FactGui::handleFadDrsCalibration);
3038
3039        if (getInfo()==&fDimFadPrescaler)
3040            return PostInfoHandler(&FactGui::handleFadPrescaler);
3041
3042        if (getInfo()==&fDimFadStatus)
3043            return PostInfoHandler(&FactGui::handleFadStatus);
3044
3045        if (getInfo()==&fDimFadStatistics1)
3046            return PostInfoHandler(&FactGui::handleFadStatistics1);
3047
3048        //if (getInfo()==&fDimFadStatistics2)
3049        //    return PostInfoHandler(&FactGui::handleFadStatistics2);
3050
3051        if (getInfo()==&fDimFadFileFormat)
3052            return PostInfoHandler(&FactGui::handleFadFileFormat);
3053
3054        if (getInfo()==&fDimFadEvents)
3055            return PostInfoHandler(&FactGui::handleFadEvents);
3056
3057        if (getInfo()==&fDimFadRuns)
3058            return PostInfoHandler(&FactGui::handleFadRuns);
3059
3060        if (getInfo()==&fDimFadStartRun)
3061            return PostInfoHandler(&FactGui::handleFadStartRun);
3062
3063        if (getInfo()==&fDimFadRawData)
3064            return PostInfoHandler(&FactGui::handleFadRawData);
3065
3066        if (getInfo()==&fDimFadEventData)
3067            return PostInfoHandler(&FactGui::handleFadEventData);
3068
3069/*
3070        if (getInfo()==&fDimFadSetup)
3071            return PostInfoHandler(&FactGui::handleFadSetup);
3072*/
3073        if (getInfo()==&fDimLoggerFilenameNight)
3074            return PostInfoHandler(&FactGui::handleLoggerFilenameNight);
3075
3076        if (getInfo()==&fDimLoggerNumSubs)
3077            return PostInfoHandler(&FactGui::handleLoggerNumSubs);
3078
3079        if (getInfo()==&fDimLoggerFilenameRun)
3080            return PostInfoHandler(&FactGui::handleLoggerFilenameRun);
3081
3082        if (getInfo()==&fDimFtmTriggerRates)
3083            return PostInfoHandler(&FactGui::handleFtmTriggerRates);
3084
3085        if (getInfo()==&fDimFtmCounter)
3086            return PostInfoHandler(&FactGui::handleFtmCounter);
3087
3088        if (getInfo()==&fDimFtmDynamicData)
3089            return PostInfoHandler(&FactGui::handleFtmDynamicData);
3090
3091        if (getInfo()==&fDimFtmPassport)
3092            return PostInfoHandler(&FactGui::handleFtmPassport);
3093
3094        if (getInfo()==&fDimFtmFtuList)
3095            return PostInfoHandler(&FactGui::handleFtmFtuList);
3096
3097        if (getInfo()==&fDimFtmStaticData)
3098            return PostInfoHandler(&FactGui::handleFtmStaticData);
3099
3100        if (getInfo()==&fDimFtmError)
3101            return PostInfoHandler(&FactGui::handleFtmError);
3102
3103        if (getInfo()==&fDimFscTemp)
3104            return PostInfoHandler(&FactGui::handleFscTemp);
3105
3106        if (getInfo()==&fDimFscVolt)
3107            return PostInfoHandler(&FactGui::handleFscVolt);
3108
3109        if (getInfo()==&fDimFscCurrent)
3110            return PostInfoHandler(&FactGui::handleFscCurrent);
3111
3112        if (getInfo()==&fDimFscHumidity)
3113            return PostInfoHandler(&FactGui::handleFscHumidity);
3114
3115        //if (getInfo()==&fDimBiasNominal)
3116        //    return PostInfoHandler(&FactGui::handleBiasNominal);
3117
3118        if (getInfo()==&fDimBiasVolt)
3119            return PostInfoHandler(&FactGui::handleBiasVolt);
3120
3121        if (getInfo()==&fDimBiasDac)
3122            return PostInfoHandler(&FactGui::handleBiasDac);
3123
3124        if (getInfo()==&fDimBiasCurrent)
3125            return PostInfoHandler(&FactGui::handleBiasCurrent);
3126
3127        if (getInfo()==&fDimFeedbackCalibrated)
3128            return PostInfoHandler(&FactGui::handleFeedbackCalibratedCurrents);
3129
3130        if (getInfo()==&fDimRateScan)
3131            return PostInfoHandler(&FactGui::handleRateScan);
3132
3133        if (getInfo()==&fDimMagicWeather)
3134            return PostInfoHandler(&FactGui::handleMagicWeather);
3135
3136//        if (getInfo()==&fDimFadFiles)
3137//            return PostInfoHandler(&FactGui::handleFadFiles);
3138
3139        for (map<string,DimInfo*>::iterator i=fServices.begin(); i!=fServices.end(); i++)
3140            if (i->second==getInfo())
3141            {
3142                infoHandlerService(*i->second);
3143                return;
3144            }
3145
3146        //DimNetwork::infoHandler();
3147    }
3148
3149
3150    // ======================================================================
3151
3152    bool event(QEvent *evt)
3153    {
3154        if (dynamic_cast<FunctionEvent*>(evt))
3155            return static_cast<FunctionEvent*>(evt)->Exec();
3156
3157        if (dynamic_cast<CheckBoxEvent*>(evt))
3158        {
3159            const QStandardItem &item = static_cast<CheckBoxEvent*>(evt)->item;
3160            const QStandardItem *par  = item.parent();
3161            if (par)
3162            {
3163                const QString server  = par->text();
3164                const QString service = item.text();
3165
3166                const string s = (server+'/'+service).toStdString();
3167
3168                if (item.checkState()==Qt::Checked)
3169                    SubscribeService(s);
3170                else
3171                    UnsubscribeService(s);
3172            }
3173        }
3174
3175        return MainWindow::event(evt); // unrecognized
3176    }
3177
3178    void on_fDimCmdSend_clicked()
3179    {
3180        const QString server    = fDimCmdServers->currentIndex().data().toString();
3181        const QString command   = fDimCmdCommands->currentIndex().data().toString();
3182        const QString arguments = fDimCmdLineEdit->displayText();
3183
3184        // FIXME: Sending a command exactly when the info Handler changes
3185        //        the list it might lead to confusion.
3186        try
3187        {
3188            SendDimCommand(server.toStdString(), command.toStdString()+" "+arguments.toStdString());
3189            fTextEdit->append("<font color='green'>Command '"+server+'/'+command+"' successfully emitted.</font>");
3190            fDimCmdLineEdit->clear();
3191        }
3192        catch (const runtime_error &e)
3193        {
3194            stringstream txt;
3195            txt << e.what();
3196
3197            string buffer;
3198            while (getline(txt, buffer, '\n'))
3199                fTextEdit->append(("<font color='red'><pre>"+buffer+"</pre></font>").c_str());
3200        }
3201    }
3202
3203    void slot_RootEventProcessed(TObject *obj, unsigned int evt, TCanvas *canv)
3204    {
3205#ifdef HAVE_ROOT
3206        // kMousePressEvent       // TCanvas processed QEvent mousePressEvent
3207        // kMouseMoveEvent        // TCanvas processed QEvent mouseMoveEvent
3208        // kMouseReleaseEvent     // TCanvas processed QEvent mouseReleaseEvent
3209        // kMouseDoubleClickEvent // TCanvas processed QEvent mouseDoubleClickEvent
3210        // kKeyPressEvent         // TCanvas processed QEvent keyPressEvent
3211        // kEnterEvent            // TCanvas processed QEvent enterEvent
3212        // kLeaveEvent            // TCanvas processed QEvent leaveEvent
3213
3214        if (dynamic_cast<TCanvas*>(obj))
3215            return;
3216
3217        TQtWidget *tipped = static_cast<TQtWidget*>(sender());
3218
3219        if (evt==11/*kMouseReleaseEvent*/)
3220            return;
3221
3222        if (evt==61/*kMouseDoubleClickEvent*/)
3223            return;
3224
3225        if (obj)
3226        {
3227            // Find the object which will get picked by the GetObjectInfo
3228            // due to buffer overflows in many root-versions
3229            // in TH1 and TProfile we have to work around and implement
3230            // our own GetObjectInfo which make everything a bit more
3231            // complicated.
3232            canv->cd();
3233#if ROOT_VERSION_CODE > ROOT_VERSION(5,22,00)
3234            const char *objectInfo =
3235                obj->GetObjectInfo(tipped->GetEventX(),tipped->GetEventY());
3236#else
3237            const char *objectInfo = dynamic_cast<TH1*>(obj) ?
3238                "" : obj->GetObjectInfo(tipped->GetEventX(),tipped->GetEventY());
3239#endif
3240
3241            QString tipText;
3242            tipText += obj->GetName();
3243            tipText += " [";
3244            tipText += obj->ClassName();
3245            tipText += "]: ";
3246            tipText += objectInfo;
3247
3248            fStatusBar->showMessage(tipText, 3000);
3249        }
3250
3251        gSystem->DispatchOneEvent(kFALSE);
3252        //gSystem->ProcessEvents();
3253        //QWhatsThis::display(tipText)
3254#endif
3255    }
3256
3257    void slot_RootUpdate()
3258    {
3259#ifdef HAVE_ROOT
3260        gSystem->DispatchOneEvent(kFALSE);
3261        //gSystem->ProcessEvents();
3262        QTimer::singleShot(10, this, SLOT(slot_RootUpdate()));
3263#endif
3264    }
3265
3266    void ChoosePatchThreshold(Camera &cam, int isw)
3267    {
3268        cam.Reset();
3269
3270        fThresholdIdx->setValue(isw);
3271
3272        const int ihw = isw<0 ? 0 : fPatchMapHW[isw];
3273
3274        fPatchRate->setEnabled(isw>=0);
3275        fThresholdCrate->setEnabled(isw>=0);
3276        fThresholdBoard->setEnabled(isw>=0);
3277        fThresholdPatch->setEnabled(isw>=0);
3278
3279        if (isw<0)
3280            return;
3281
3282        const int patch = ihw%4;
3283        const int board = (ihw/4)%10;
3284        const int crate = (ihw/4)/10;
3285
3286        fInChoosePatchTH = true;
3287
3288        fThresholdCrate->setValue(crate);
3289        fThresholdBoard->setValue(board);
3290        fThresholdPatch->setValue(patch);
3291
3292        fInChoosePatchTH = false;
3293
3294        fThresholdVal->setValue(fFtmStaticData.fThreshold[ihw]);
3295        fPatchRate->setValue(fTriggerRates.fPatchRate[ihw]);
3296        fBoardRate->setValue(fTriggerRates.fBoardRate[ihw/4]);
3297
3298        // Loop over the software idx of all pixels
3299//        for (unsigned int i=0; i<1440; i++)
3300//            if (fPatchHW[i]==ihw)
3301//                cam.SetBold(i);
3302    }
3303
3304    void slot_ChoosePixelThreshold(int isw)
3305    {
3306        fPixelIdx->setValue(isw);
3307
3308        const PixelMapEntry &entry = fPixelMap.index(isw);
3309        fPixelEnable->setChecked(fFtmStaticData.IsEnabled(entry.hw()));
3310    }
3311
3312    void slot_CameraDoubleClick(int isw)
3313    {
3314        fPixelIdx->setValue(isw);
3315
3316        const PixelMapEntry &entry = fPixelMap.index(isw);
3317        Dim::SendCommand("FTM_CONTROL/TOGGLE_PIXEL", uint16_t(entry.hw()));
3318    }
3319
3320    void slot_CameraMouseMove(int isw)
3321    {
3322        const PixelMapEntry &entry = fPixelMap.index(isw);
3323
3324        QString tipText;
3325        tipText += fRatesCanv->GetName();
3326        ostringstream str;
3327        str << setfill('0') <<
3328            "  ||  HW: " << entry.crate() << "|" << entry.board() << "|" << entry.patch() << "|" << entry.pixel() << " (crate|board|patch|pixel)" <<
3329            "  ||  HV: " << entry.hv_board << "|" << setw(2) << entry.hv_channel << " (board|channel)" <<
3330            "  ||  ID: " << isw;
3331
3332
3333        tipText += str.str().c_str();
3334        fStatusBar->showMessage(tipText, 3000);
3335    }
3336
3337    void on_fPixelIdx_valueChanged(int isw)
3338    {
3339        int ii = 0;
3340        for (; ii<160; ii++)
3341            if (fPixelMap.index(isw).hw()/9==fPatchMapHW[ii])
3342                break;
3343
3344        fRatesCanv->SetWhite(isw);
3345        ChoosePatchThreshold(*fRatesCanv, ii);
3346
3347        const PixelMapEntry &entry = fPixelMap.index(isw);
3348        fPixelEnable->setChecked(fFtmStaticData.IsEnabled(entry.hw()));
3349    }
3350
3351    // ------------------- Bias display ---------------------
3352
3353    void UpdateBiasValues()
3354    {
3355        const int b = fBiasHvBoard->value();
3356        const int c = fBiasHvChannel->value();
3357
3358        const int ihw = b*32+c;
3359
3360        if (fVecBiasVolt.size()>0)
3361        {
3362            fBiasVoltCur->setValue(fVecBiasVolt[ihw]);
3363            SetLedColor(fBiasNominalLed,
3364                        fVecBiasDac[ihw]==fVecBiasDac[ihw+416]?kLedGreen:kLedRed, Time());
3365        }
3366
3367        if (fVecBiasCurrent.size()>0)
3368        {
3369            const double val = abs(fVecBiasCurrent[ihw]) * 5000./4096;
3370            fBiasCurrent->setValue(val);
3371            SetLedColor(fBiasOverCurrentLed,
3372                        fVecBiasCurrent[ihw]<0?kLedRed:kLedGreen, Time());
3373        }
3374
3375        const bool calibrated = fStateFeedback>=Feedback::State::kCalibrated &&
3376            fVecFeedbackCurrents.size()>0;
3377
3378        fBiasCalibrated->setValue(calibrated ? fVecFeedbackCurrents[ihw] : 0);
3379        fBiasCalibrated->setEnabled(calibrated);
3380    }
3381
3382    void UpdateBiasCam(const PixelMapEntry &entry)
3383    {
3384        fInChooseBiasCam = true;
3385
3386        fBiasCamCrate->setValue(entry.crate());
3387        fBiasCamBoard->setValue(entry.board());
3388        fBiasCamPatch->setValue(entry.patch());
3389        fBiasCamPixel->setValue(entry.pixel());
3390
3391        fInChooseBiasCam = false;
3392    }
3393
3394    void BiasHvChannelChanged()
3395    {
3396        if (fInChooseBiasHv)
3397            return;
3398
3399        const int b  = fBiasHvBoard->value();
3400        const int ch = fBiasHvChannel->value();
3401
3402        // FIXME: Mark corresponding patch in camera
3403        const PixelMapEntry &entry = fPixelMap.hv(b, ch);
3404        fBiasCamV->SetWhite(entry.index);
3405        fBiasCamA->SetWhite(entry.index);
3406        fBiasCamV->updateCamera();
3407        fBiasCamA->updateCamera();
3408
3409        UpdateBiasCam(entry);
3410        UpdateBiasValues();
3411    }
3412
3413    void UpdateBiasHv(const PixelMapEntry &entry)
3414    {
3415        fInChooseBiasHv = true;
3416
3417        fBiasHvBoard->setValue(entry.hv_board);
3418        fBiasHvChannel->setValue(entry.hv_channel);
3419
3420        fInChooseBiasHv = false;
3421    }
3422
3423    void BiasCamChannelChanged()
3424    {
3425        if (fInChooseBiasCam)
3426            return;
3427
3428        const int crate = fBiasCamCrate->value();
3429        const int board = fBiasCamBoard->value();
3430        const int patch = fBiasCamPatch->value();
3431        const int pixel = fBiasCamPixel->value();
3432
3433        // FIXME: Display corresponding patches
3434        const PixelMapEntry &entry = fPixelMap.cbpx(crate, board, patch, pixel);
3435        fBiasCamV->SetWhite(entry.index);
3436        fBiasCamA->SetWhite(entry.index);
3437        fBiasCamV->updateCamera();
3438        fBiasCamA->updateCamera();
3439
3440        UpdateBiasHv(entry);
3441        UpdateBiasValues();
3442    }
3443
3444    void slot_ChooseBiasChannel(int isw)
3445    {
3446        const PixelMapEntry &entry = fPixelMap.index(isw);
3447
3448        UpdateBiasHv(entry);
3449        UpdateBiasCam(entry);
3450        UpdateBiasValues();
3451    }
3452
3453    void on_fBiasDispRefVolt_stateChanged(int = 0)
3454    {
3455        // FIXME: Display patches for which ref==cur
3456
3457        valarray<double> dat(0., 1440);
3458        fBiasCamV->setTitle("Applied BIAS voltage");
3459
3460        if (fVecBiasVolt.size()>0 && fVecBiasDac.size()>0)
3461        {
3462            for (int i=0; i<1440; i++)
3463            {
3464                const PixelMapEntry &entry = fPixelMap.index(i);
3465
3466                dat[i] = fVecBiasVolt[entry.hv()];
3467                fBiasCamV->highlightPixel(i, fVecBiasDac[entry.hv()]!=fVecBiasDac[entry.hv()+416]);
3468            }
3469
3470            fBiasCamV->SetData(dat);
3471        }
3472
3473        fBiasCamV->updateCamera();
3474    }
3475
3476    // ------------------------------------------------------
3477
3478    void on_fPixelEnable_stateChanged(int b)
3479    {
3480        if (fInHandler)
3481            return;
3482
3483        const PixelMapEntry &entry = fPixelMap.index(fPixelIdx->value());
3484
3485        Dim::SendCommand(b==Qt::Unchecked ?
3486                         "FTM_CONTROL/DISABLE_PIXEL" : "FTM_CONTROL/ENABLE_PIXEL",
3487                         uint16_t(entry.hw()));
3488    }
3489
3490    void on_fPixelDisableOthers_clicked()
3491    {
3492        const PixelMapEntry &entry = fPixelMap.index(fPixelIdx->value());
3493        Dim::SendCommand("FTM_CONTROL/DISABLE_ALL_PIXELS_EXCEPT", uint16_t(entry.hw()));
3494    }
3495
3496    void on_fThresholdDisableOthers_clicked()
3497    {
3498        const int16_t isw = fThresholdIdx->value();
3499        const int16_t ihw = isw<0 ? -1 : fPatchMapHW[isw];
3500        if (ihw<0)
3501            return;
3502
3503        Dim::SendCommand("FTM_CONTROL/DISABLE_ALL_PATCHES_EXCEPT", ihw);
3504    }
3505
3506    void on_fThresholdEnablePatch_clicked()
3507    {
3508        const int16_t isw = fThresholdIdx->value();
3509        const int16_t ihw = isw<0 ? -1 : fPatchMapHW[isw];
3510       if (ihw<0)
3511            return;
3512
3513        Dim::SendCommand("FTM_CONTROL/ENABLE_PATCH", ihw);
3514    }
3515
3516    void on_fThresholdDisablePatch_clicked()
3517    {
3518        const int16_t isw = fThresholdIdx->value();
3519        const int16_t ihw = isw<0 ? -1 : fPatchMapHW[isw];
3520        if (ihw<0)
3521            return;
3522
3523        Dim::SendCommand("FTM_CONTROL/DISABLE_PATCH", ihw);
3524    }
3525
3526    void on_fThresholdVal_valueChanged(int v)
3527    {
3528        fThresholdVolt->setValue(2500./4095*v);
3529
3530        const int32_t isw = fThresholdIdx->value();
3531        const int32_t ihw = isw<0 ? -1 : fPatchMapHW[isw];
3532
3533        const int32_t d[2] = { ihw, v };
3534
3535        if (!fInHandler)
3536            Dim::SendCommand("FTM_CONTROL/SET_THRESHOLD", d);
3537    }
3538
3539#ifdef HAVE_ROOT
3540    TGraph fGraphFtmTemp[4];
3541    TGraph fGraphFtmRate;
3542    TGraph fGraphPatchRate[160];
3543    TGraph fGraphBoardRate[40];
3544
3545    TH1 *DrawTimeFrame(const char *ytitle)
3546    {
3547        const double tm = Time().RootTime();
3548
3549        TH1F *h=new TH1F("TimeFrame", "", 1, tm, tm+60);//Time().RootTime()-1./24/60/60, Time().RootTime());
3550        h->SetDirectory(0);
3551        h->SetBit(kCanDelete);
3552        h->SetStats(kFALSE);
3553//        h.SetMinimum(0);
3554//        h.SetMaximum(1);
3555        h->SetXTitle("Time");
3556        h->SetYTitle(ytitle);
3557        h->GetXaxis()->CenterTitle();
3558        h->GetYaxis()->CenterTitle();
3559        h->GetXaxis()->SetTimeDisplay(true);
3560        h->GetXaxis()->SetTimeFormat("%Mh%S'%F1995-01-01 00:00:00 GMT");
3561        h->GetXaxis()->SetLabelSize(0.025);
3562        h->GetYaxis()->SetLabelSize(0.025);
3563        h->GetYaxis()->SetTitleOffset(1.2);
3564        //        h.GetYaxis()->SetTitleSize(1.2);
3565        return h;
3566    }
3567#endif
3568
3569    pair<string,string> Split(const string &str) const
3570    {
3571        const size_t p = str.find_first_of('|');
3572        if (p==string::npos)
3573            return make_pair(str, "");
3574
3575        return make_pair(str.substr(0, p), str.substr(p+1));
3576    }
3577
3578public:
3579    FactGui(Configuration &conf) :
3580        fFtuStatus(40), 
3581        /*fPixelMapHW(1440),*/ fPatchMapHW(160), 
3582        fInChoosePatchTH(false),
3583        fInChooseBiasHv(false), fInChooseBiasCam(false),
3584        fDimDNS("DIS_DNS/VERSION_NUMBER", 1, int(0), this),
3585        //-
3586        fDimLoggerStats        ("DATA_LOGGER/STATS",            (void*)NULL, 0, this),
3587        fDimLoggerFilenameNight("DATA_LOGGER/FILENAME_NIGHTLY", (void*)NULL, 0, this),
3588        fDimLoggerFilenameRun  ("DATA_LOGGER/FILENAME_RUN",     (void*)NULL, 0, this),
3589        fDimLoggerNumSubs      ("DATA_LOGGER/NUM_SUBS",         (void*)NULL, 0, this),
3590        //-
3591        fDimFtmPassport        ("FTM_CONTROL/PASSPORT",         (void*)NULL, 0, this),
3592        fDimFtmTriggerRates    ("FTM_CONTROL/TRIGGER_RATES",    (void*)NULL, 0, this),
3593        fDimFtmError           ("FTM_CONTROL/ERROR",            (void*)NULL, 0, this),
3594        fDimFtmFtuList         ("FTM_CONTROL/FTU_LIST",         (void*)NULL, 0, this),
3595        fDimFtmStaticData      ("FTM_CONTROL/STATIC_DATA",      (void*)NULL, 0, this),
3596        fDimFtmDynamicData     ("FTM_CONTROL/DYNAMIC_DATA",     (void*)NULL, 0, this),
3597        fDimFtmCounter         ("FTM_CONTROL/COUNTER",          (void*)NULL, 0, this),
3598        //-
3599        fDimFadWriteStats      ("FAD_CONTROL/STATS",              (void*)NULL, 0, this),
3600        fDimFadStartRun        ("FAD_CONTROL/START_RUN",          (void*)NULL, 0, this),
3601        fDimFadRuns            ("FAD_CONTROL/RUNS",               (void*)NULL, 0, this),
3602        fDimFadEvents          ("FAD_CONTROL/EVENTS",             (void*)NULL, 0, this),
3603        fDimFadRawData         ("FAD_CONTROL/RAW_DATA",           (void*)NULL, 0, this),
3604        fDimFadEventData       ("FAD_CONTROL/EVENT_DATA",         (void*)NULL, 0, this),
3605        fDimFadConnections     ("FAD_CONTROL/CONNECTIONS",        (void*)NULL, 0, this),
3606        fDimFadFwVersion       ("FAD_CONTROL/FIRMWARE_VERSION",   (void*)NULL, 0, this),
3607        fDimFadRunNumber       ("FAD_CONTROL/RUN_NUMBER",         (void*)NULL, 0, this),
3608        fDimFadDNA             ("FAD_CONTROL/DNA",                (void*)NULL, 0, this),
3609        fDimFadTemperature     ("FAD_CONTROL/TEMPERATURE",        (void*)NULL, 0, this),
3610        fDimFadPrescaler       ("FAD_CONTROL/PRESCALER",          (void*)NULL, 0, this),
3611        fDimFadRefClock        ("FAD_CONTROL/REFERENCE_CLOCK",    (void*)NULL, 0, this),
3612        fDimFadRoi             ("FAD_CONTROL/REGION_OF_INTEREST", (void*)NULL, 0, this),
3613        fDimFadDac             ("FAD_CONTROL/DAC",                (void*)NULL, 0, this),
3614        fDimFadDrsCalibration  ("FAD_CONTROL/DRS_CALIBRATION",    (void*)NULL, 0, this),
3615        fDimFadStatus          ("FAD_CONTROL/STATUS",             (void*)NULL, 0, this),
3616        fDimFadStatistics1     ("FAD_CONTROL/STATISTICS1",        (void*)NULL, 0, this),
3617        //fDimFadStatistics2     ("FAD_CONTROL/STATISTICS2",        (void*)NULL, 0, this),
3618        fDimFadFileFormat      ("FAD_CONTROL/FILE_FORMAT",        (void*)NULL, 0, this),
3619        //-
3620        fDimFscTemp            ("FSC_CONTROL/TEMPERATURE",        (void*)NULL, 0, this),
3621        fDimFscVolt            ("FSC_CONTROL/VOLTAGE",            (void*)NULL, 0, this),
3622        fDimFscCurrent         ("FSC_CONTROL/CURRENT",            (void*)NULL, 0, this),
3623        fDimFscHumidity        ("FSC_CONTROL/HUMIDITY",           (void*)NULL, 0, this),
3624        //-
3625        fDimFeedbackCalibrated ("FEEDBACK/CALIBRATED_CURRENTS",   (void*)NULL, 0, this),
3626        //-
3627        fDimBiasNominal        ("BIAS_CONTROL/NOMINAL",           (void*)NULL, 0, this),
3628        fDimBiasVolt           ("BIAS_CONTROL/VOLTAGE",           (void*)NULL, 0, this),
3629        fDimBiasDac            ("BIAS_CONTROL/DAC",               (void*)NULL, 0, this),
3630        fDimBiasCurrent        ("BIAS_CONTROL/CURRENT",           (void*)NULL, 0, this),
3631        //-
3632        fDimRateScan           ("RATE_SCAN/DATA",                 (void*)NULL, 0, this),
3633        //-
3634        fDimMagicWeather       ("MAGIC_WEATHER/DATA",             (void*)NULL, 0, this),
3635        //-
3636        fDimVersion(0),
3637        fFreeSpaceLogger(UINT64_MAX), fFreeSpaceData(UINT64_MAX),
3638        fEventData(0),
3639        fDrsCalibration(1440*1024*6+160*1024*2),
3640        fTimeStamp0(0)
3641    {
3642        fClockCondFreq->addItem("--- Hz",  QVariant(-1));
3643        fClockCondFreq->addItem("800 MHz", QVariant(800));
3644        fClockCondFreq->addItem("1 GHz",   QVariant(1000));
3645        fClockCondFreq->addItem("2 GHz",   QVariant(2000));
3646        fClockCondFreq->addItem("3 GHz",   QVariant(3000));
3647        fClockCondFreq->addItem("4 GHz",   QVariant(4000));
3648        fClockCondFreq->addItem("5 GHz",   QVariant(5000));
3649
3650        cout << "-- run counter ---" << endl;
3651        fMcpNumEvents->addItem("unlimited", QVariant(0));
3652        const vector<uint32_t> runcount = conf.Vec<uint32_t>("run-count");
3653        for (vector<uint32_t>::const_iterator it=runcount.begin(); it!=runcount.end(); it++)
3654        {
3655            cout << *it << endl;
3656            ostringstream str;
3657            str << *it;
3658            fMcpNumEvents->addItem(str.str().c_str(), QVariant(*it));
3659        }
3660
3661        cout << "-- run times ---" << endl;
3662        fMcpTime->addItem("unlimited", QVariant(0));
3663        const vector<string> runtime = conf.Vec<string>("run-time");
3664        for (vector<string>::const_iterator it=runtime.begin(); it!=runtime.end(); it++)
3665        {
3666            const pair<string,string> p = Split(*it);
3667            cout << *it << "|" << p.second << "|" << p.first << "|" << endl;
3668            fMcpTime->addItem(p.second.c_str(), QVariant(stoi(p.first)));
3669        }
3670
3671        cout << "-- run types ---" << endl;
3672        const vector<string> runtype = conf.Vec<string>("run-type");
3673        for (vector<string>::const_iterator it=runtype.begin(); it!=runtype.end(); it++)
3674        {
3675            const pair<string,string> p = Split(*it);
3676            cout << *it << "|" << p.second << "|" << p.first << "|" << endl;
3677            fMcpRunType->addItem(p.second.c_str(), QVariant(p.first.c_str()));
3678        }
3679
3680        fTriggerWidget->setEnabled(false);
3681        fFtuWidget->setEnabled(false);
3682        fFtuGroupEnable->setEnabled(false);
3683        fRatesControls->setEnabled(false);
3684        fFadWidget->setEnabled(false);
3685        fGroupEthernet->setEnabled(false);
3686        fGroupOutput->setEnabled(false);
3687        fLoggerWidget->setEnabled(false);
3688        fBiasWidget->setEnabled(false);
3689        fAuxWidget->setEnabled(false);
3690
3691        fChatSend->setEnabled(false);
3692        fChatMessage->setEnabled(false);
3693
3694        DimClient::sendCommand("CHAT/MSG", "GUI online.");
3695        // + MessageDimRX
3696
3697        // --------------------------------------------------------------------------
3698
3699        if (!fPixelMap.Read(conf.Get<string>("pixel-map-file")))
3700        {
3701            cerr << "ERROR - Problems reading " << conf.Get<string>("pixel-map-file") << endl;
3702            exit(-1);
3703        }
3704
3705        // --------------------------------------------------------------------------
3706
3707        ifstream fin3("PatchList.txt");
3708
3709        string buf;
3710
3711        int l = 0;
3712        while (getline(fin3, buf, '\n'))
3713        {
3714            buf = Tools::Trim(buf);
3715            if (buf[0]=='#')
3716                continue;
3717
3718            unsigned int softid, hardid;
3719
3720            stringstream str(buf);
3721
3722            str >> softid;
3723            str >> hardid;
3724
3725            if (softid>=fPatchMapHW.size())
3726                continue;
3727
3728            fPatchMapHW[softid] = hardid-1;
3729
3730            l++;
3731        }
3732
3733        if (l!=160)
3734            cerr << "WARNING - Problems reading PatchList.txt" << endl;
3735
3736        // --------------------------------------------------------------------------
3737
3738        fCommentsWidget->setEnabled(false);
3739
3740        static const boost::regex expr("(([[:word:].-]+)(:(.+))?@)?([[:word:].-]+)(:([[:digit:]]+))?(/([[:word:].-]+))");
3741
3742        const string database = conf.Get<string>("CommentDB");
3743
3744        if (!database.empty())
3745        {
3746            boost::smatch what;
3747            if (!boost::regex_match(database, what, expr, boost::match_extra))
3748                throw runtime_error("Couldn't parse '"+database+"'.");
3749
3750            if (what.size()!=10)
3751                throw runtime_error("Error parsing '"+database+"'.");
3752
3753            const string user   = what[2];
3754            const string passwd = what[4];
3755            const string server = what[5];
3756            const string db     = what[9];
3757            const int port      = atoi(string(what[7]).c_str());
3758
3759            QSqlDatabase qdb = QSqlDatabase::addDatabase("QMYSQL");
3760            qdb.setHostName(server.c_str());
3761            qdb.setDatabaseName(db.c_str());
3762            qdb.setUserName(user.c_str());
3763            qdb.setPassword(passwd.c_str());
3764            qdb.setPort(port);
3765            qdb.setConnectOptions("CLIENT_SSL=1;MYSQL_OPT_RECONNECT=1");
3766            if (qdb.open())
3767            {
3768                QSqlTableModel *model = new QSqlTableModel(fTableComments, qdb);
3769                model->setTable("runcomments");
3770                model->setEditStrategy(QSqlTableModel::OnManualSubmit);
3771
3772                const bool ok2 = model->select();
3773
3774                if (ok2)
3775                {
3776                    fTableComments->setModel(model);
3777                    fTableComments->resizeColumnsToContents();
3778                    fTableComments->resizeRowsToContents();
3779
3780                    connect(fCommentSubmit, SIGNAL(clicked()), model, SLOT(submitAll()));
3781                    connect(fCommentRevert, SIGNAL(clicked()), model, SLOT(revertAll()));
3782                    connect(fCommentUpdateLayout, SIGNAL(clicked()), fTableComments, SLOT(resizeColumnsToContents()));
3783                    connect(fCommentUpdateLayout, SIGNAL(clicked()), fTableComments, SLOT(resizeRowsToContents()));
3784
3785                    fCommentsWidget->setEnabled(true);
3786                }
3787                else
3788                    cout << "\n==> ERROR: Select on table failed.\n" << endl;
3789            }
3790            else
3791                cout << "\n==> ERROR: Connection to database failed:\n           "
3792                    << qdb.lastError().text().toStdString() << endl << endl;
3793        }
3794
3795        // --------------------------------------------------------------------------
3796#ifdef HAVE_ROOT
3797
3798        fGraphFeedbackDev.SetLineColor(kBlue);
3799        fGraphFeedbackDev.SetMarkerColor(kBlue);
3800        fGraphFeedbackDev.SetMarkerStyle(kFullDotMedium);
3801
3802        fGraphFeedbackCmd.SetLineColor(kBlue);
3803        fGraphFeedbackCmd.SetMarkerColor(kBlue);
3804        fGraphFeedbackCmd.SetMarkerStyle(kFullDotMedium);
3805
3806        // Evolution of control deviation
3807        // Evolution of command values (bias voltage change)
3808        fGraphFeedbackDev.SetName("ControlDev");
3809        fGraphFeedbackCmd.SetName("CommandVal");
3810
3811        TCanvas *c = fFeedbackDev->GetCanvas();
3812        c->SetBorderMode(0);
3813        c->SetFrameBorderMode(0);
3814        c->SetFillColor(kWhite);
3815        c->SetRightMargin(0.03);
3816        c->SetTopMargin(0.03);
3817        c->SetGrid();
3818
3819        TH1 *hf = DrawTimeFrame("Overvoltage [V]   ");
3820        hf->GetXaxis()->SetLabelSize(0.07);
3821        hf->GetYaxis()->SetLabelSize(0.07);
3822        hf->GetYaxis()->SetTitleSize(0.08);
3823        hf->GetYaxis()->SetTitleOffset(0.55);
3824        hf->GetXaxis()->SetTitle("");
3825        hf->GetYaxis()->SetRangeUser(0, 1.5);
3826
3827        c->GetListOfPrimitives()->Add(hf, "");
3828        c->GetListOfPrimitives()->Add(&fGraphFeedbackDev, "LP");
3829
3830        c = fFeedbackCmd->GetCanvas();
3831        c->SetBorderMode(0);
3832        c->SetFrameBorderMode(0);
3833        c->SetFillColor(kWhite);
3834        c->SetRightMargin(0.03);
3835        c->SetTopMargin(0.03);
3836        c->SetGrid();
3837
3838        hf = DrawTimeFrame("Command temp delta [V]   ");
3839        hf->GetXaxis()->SetLabelSize(0.07);
3840        hf->GetYaxis()->SetLabelSize(0.07);
3841        hf->GetYaxis()->SetTitleSize(0.08);
3842        hf->GetYaxis()->SetTitleOffset(0.55);
3843        hf->GetXaxis()->SetTitle("");
3844        hf->GetYaxis()->SetRangeUser(-2, 2);
3845
3846        c->GetListOfPrimitives()->Add(hf, "");
3847        c->GetListOfPrimitives()->Add(&fGraphFeedbackCmd, "LP");
3848
3849        // --------------------------------------------------------------------------
3850
3851        c = fRateScanCanv->GetCanvas();
3852        //c->SetBit(TCanvas::kNoContextMenu);
3853        c->SetBorderMode(0);
3854        c->SetFrameBorderMode(0);
3855        c->SetFillColor(kWhite);
3856        c->SetRightMargin(0.03);
3857        c->SetTopMargin(0.03);
3858        c->SetGrid();
3859
3860        TH1F *h=new TH1F("Frame", "", 1, 0, 1);
3861        h->SetDirectory(0);
3862        h->SetBit(kCanDelete);
3863        h->SetStats(kFALSE);
3864        h->SetXTitle("Threshold [DAC]");
3865        h->SetYTitle("Rate [Hz]");
3866        h->GetXaxis()->CenterTitle();
3867        h->GetYaxis()->CenterTitle();
3868        h->GetXaxis()->SetLabelSize(0.025);
3869        h->GetYaxis()->SetLabelSize(0.025);
3870        h->GetYaxis()->SetTitleOffset(1.2);
3871        c->GetListOfPrimitives()->Add(h, "");
3872
3873        fGraphRateScan[0].SetName("CameraRate");
3874        for (int i=0; i<40; i++)
3875        {
3876            fGraphRateScan[i+1].SetName("BoardRate");
3877            fGraphRateScan[i+1].SetMarkerStyle(kFullDotMedium);
3878        }
3879        for (int i=0; i<160; i++)
3880        {
3881            fGraphRateScan[i+41].SetName("PatchRate");
3882            fGraphRateScan[i+41].SetMarkerStyle(kFullDotMedium);
3883        }
3884
3885        fGraphRateScan[0].SetLineColor(kBlue);
3886        fGraphRateScan[0].SetMarkerColor(kBlue);
3887        fGraphRateScan[0].SetMarkerStyle(kFullDotSmall);
3888        c->GetListOfPrimitives()->Add(&fGraphRateScan[0], "LP");
3889
3890        // --------------------------------------------------------------------------
3891
3892        c = fFtmRateCanv->GetCanvas();
3893        //c->SetBit(TCanvas::kNoContextMenu);
3894        c->SetBorderMode(0);
3895        c->SetFrameBorderMode(0);
3896        c->SetFillColor(kWhite);
3897        c->SetRightMargin(0.03);
3898        c->SetTopMargin(0.03);
3899        c->SetGrid();
3900
3901        hf = DrawTimeFrame("Trigger rate [Hz]");
3902        hf->GetYaxis()->SetRangeUser(0, 1010);
3903
3904        for (int i=0; i<160; i++)
3905        {
3906            fGraphPatchRate[i].SetName("PatchRate");
3907            //fGraphPatchRate[i].SetLineColor(kBlue);
3908            //fGraphPatchRate[i].SetMarkerColor(kBlue);
3909            fGraphPatchRate[i].SetMarkerStyle(kFullDotMedium);
3910        }
3911        for (int i=0; i<40; i++)
3912        {
3913            fGraphBoardRate[i].SetName("BoardRate");
3914            //fGraphBoardRate[i].SetLineColor(kBlue);
3915            //fGraphBoardRate[i].SetMarkerColor(kBlue);
3916            fGraphBoardRate[i].SetMarkerStyle(kFullDotMedium);
3917        }
3918
3919        fGraphFtmRate.SetLineColor(kBlue);
3920        fGraphFtmRate.SetMarkerColor(kBlue);
3921        fGraphFtmRate.SetMarkerStyle(kFullDotSmall);
3922
3923        c->GetListOfPrimitives()->Add(hf, "");
3924        c->GetListOfPrimitives()->Add(&fGraphFtmRate, "LP");
3925
3926        /*
3927        TCanvas *c = fFtmTempCanv->GetCanvas();
3928        c->SetBit(TCanvas::kNoContextMenu);
3929        c->SetBorderMode(0);
3930        c->SetFrameBorderMode(0);
3931        c->SetFillColor(kWhite);
3932        c->SetRightMargin(0.03);
3933        c->SetTopMargin(0.03);
3934        c->cd();
3935        */
3936        //CreateTimeFrame("Temperature / �C");
3937
3938        fGraphFtmTemp[0].SetMarkerStyle(kFullDotSmall);
3939        fGraphFtmTemp[1].SetMarkerStyle(kFullDotSmall);
3940        fGraphFtmTemp[2].SetMarkerStyle(kFullDotSmall);
3941        fGraphFtmTemp[3].SetMarkerStyle(kFullDotSmall);
3942
3943        fGraphFtmTemp[1].SetLineColor(kBlue);
3944        fGraphFtmTemp[2].SetLineColor(kRed);
3945        fGraphFtmTemp[3].SetLineColor(kGreen);
3946
3947        fGraphFtmTemp[1].SetMarkerColor(kBlue);
3948        fGraphFtmTemp[2].SetMarkerColor(kRed);
3949        fGraphFtmTemp[3].SetMarkerColor(kGreen);
3950
3951        //fGraphFtmTemp[0].Draw("LP");
3952        //fGraphFtmTemp[1].Draw("LP");
3953        //fGraphFtmTemp[2].Draw("LP");
3954        //fGraphFtmTemp[3].Draw("LP");
3955
3956        // --------------------------------------------------------------------------
3957
3958        c = fAdcDataCanv->GetCanvas();
3959        //c->SetBit(TCanvas::kNoContextMenu);
3960        c->SetBorderMode(0);
3961        c->SetFrameBorderMode(0);
3962        c->SetFillColor(kWhite);
3963        c->SetRightMargin(0.10);
3964        c->SetGrid();
3965        //c->cd();
3966#endif
3967
3968        // --------------------------------------------------------------------------
3969        fFeedbackDevCam->assignPixelMap(fPixelMap);
3970        fFeedbackDevCam->setAutoscaleLowerLimit((fFeedbackDevMin->minimum()+0.5*fFeedbackDevMin->singleStep()));
3971        fFeedbackDevCam->SetMin(fFeedbackDevMin->value());
3972        fFeedbackDevCam->SetMax(fFeedbackDevMax->value());
3973        fFeedbackDevCam->updateCamera();
3974
3975        fFeedbackCmdCam->assignPixelMap(fPixelMap);
3976        fFeedbackCmdCam->setAutoscaleLowerLimit((fFeedbackCmdMin->minimum()+0.5*fFeedbackCmdMin->singleStep()));
3977        fFeedbackCmdCam->SetMin(fFeedbackCmdMin->value());
3978        fFeedbackCmdCam->SetMax(fFeedbackCmdMax->value());
3979        fFeedbackCmdCam->updateCamera();
3980
3981        // --------------------------------------------------------------------------
3982
3983        fBiasCamV->assignPixelMap(fPixelMap);
3984        fBiasCamV->setAutoscaleLowerLimit((fBiasVoltMin->minimum()+0.5*fBiasVoltMin->singleStep()));
3985        fBiasCamV->SetMin(fBiasVoltMin->value());
3986        fBiasCamV->SetMax(fBiasVoltMax->value());
3987        fBiasCamV->updateCamera();
3988
3989        fBiasCamA->assignPixelMap(fPixelMap);
3990        fBiasCamA->setAutoscaleLowerLimit((fBiasCurrentMin->minimum()+0.5*fBiasCurrentMin->singleStep()));
3991        fBiasCamA->SetMin(fBiasCurrentMin->value());
3992        fBiasCamA->SetMax(fBiasCurrentMax->value());
3993        fBiasCamA->updateCamera();
3994
3995        // --------------------------------------------------------------------------
3996
3997        fRatesCanv->assignPixelMap(fPixelMap);
3998        fRatesCanv->setAutoscaleLowerLimit((fRatesMin->minimum()+0.5*fRatesMin->singleStep())*0.001);
3999        fRatesCanv->SetMin(fRatesMin->value());
4000        fRatesCanv->SetMax(fRatesMax->value());
4001        fRatesCanv->updateCamera();
4002        on_fPixelIdx_valueChanged(0);
4003
4004        // --------------------------------------------------------------------------
4005
4006        fRatesCanv->setTitle("Patch rates");
4007        fRatesCanv->setUnits("Hz");
4008
4009        fBiasCamA->setTitle("BIAS current");
4010        fBiasCamA->setUnits("uA");
4011
4012        fBiasCamV->setTitle("Applied BIAS voltage");
4013        fBiasCamV->setUnits("V");
4014
4015        fEventCanv1->setTitle("Average (all slices)");
4016        fEventCanv2->setTitle("RMS (all slices)");
4017        fEventCanv3->setTitle("Maximum (all slices)");
4018        fEventCanv4->setTitle("Position of maximum (all slices)");
4019
4020        fEventCanv1->setUnits("mV");
4021        fEventCanv2->setUnits("mV");
4022        fEventCanv3->setUnits("mV");
4023        fEventCanv4->setUnits("slice");
4024
4025        // --------------------------------------------------------------------------
4026
4027        fFeedbackDevCam->setTitle("Control deviation (Pulser amplitude voltage)");
4028        fFeedbackCmdCam->setTitle("Applied voltage change (BIAS voltage)");
4029
4030        fFeedbackDevCam->setUnits("mV");
4031        fFeedbackCmdCam->setUnits("mV");
4032
4033        // --------------------------------------------------------------------------
4034
4035        QTimer::singleShot(1000, this, SLOT(slot_RootUpdate()));
4036
4037        //widget->setMouseTracking(true);
4038        //widget->EnableSignalEvents(kMouseMoveEvent);
4039
4040        fFtmRateCanv->setMouseTracking(true);
4041        fFtmRateCanv->EnableSignalEvents(kMouseMoveEvent);
4042
4043        fAdcDataCanv->setMouseTracking(true);
4044        fAdcDataCanv->EnableSignalEvents(kMouseMoveEvent);
4045
4046        fRatesCanv->setMouseTracking(true);
4047        fEventCanv1->setMouseTracking(true);
4048        fEventCanv2->setMouseTracking(true);
4049        fEventCanv3->setMouseTracking(true);
4050        fEventCanv4->setMouseTracking(true);
4051
4052        fBiasCamV->setMouseTracking(true);
4053        fBiasCamA->setMouseTracking(true);
4054
4055        fFeedbackDevCam->setMouseTracking(true);
4056        fFeedbackCmdCam->setMouseTracking(true);
4057
4058        fEventCanv1->ShowPixelCursor(true);
4059        fEventCanv2->ShowPixelCursor(true);
4060        fEventCanv3->ShowPixelCursor(true);
4061        fEventCanv4->ShowPixelCursor(true);
4062
4063        fEventCanv1->ShowPatchCursor(true);
4064        fEventCanv2->ShowPatchCursor(true);
4065        fEventCanv3->ShowPatchCursor(true);
4066        fEventCanv4->ShowPatchCursor(true);
4067
4068        fFeedbackDevCam->ShowPixelCursor(true);
4069        fFeedbackCmdCam->ShowPixelCursor(true);
4070
4071        fFeedbackDevCam->ShowPatchCursor(true);
4072        fFeedbackCmdCam->ShowPatchCursor(true);
4073
4074        connect(fRatesCanv, SIGNAL(signalPixelMoveOver(int)),
4075                this, SLOT(slot_CameraMouseMove(int)));
4076        connect(fEventCanv1, SIGNAL(signalPixelMoveOver(int)),
4077                this, SLOT(slot_CameraMouseMove(int)));
4078        connect(fEventCanv2, SIGNAL(signalPixelMoveOver(int)),
4079                this, SLOT(slot_CameraMouseMove(int)));
4080        connect(fEventCanv3, SIGNAL(signalPixelMoveOver(int)),
4081                this, SLOT(slot_CameraMouseMove(int)));
4082        connect(fEventCanv4, SIGNAL(signalPixelMoveOver(int)),
4083                this, SLOT(slot_CameraMouseMove(int)));
4084
4085        connect(fBiasCamV, SIGNAL(signalPixelMoveOver(int)),
4086                this, SLOT(slot_CameraMouseMove(int)));
4087        connect(fBiasCamA, SIGNAL(signalPixelMoveOver(int)),
4088                this, SLOT(slot_CameraMouseMove(int)));
4089
4090        connect(fFeedbackDevCam, SIGNAL(signalPixelMoveOver(int)),
4091                this, SLOT(slot_CameraMouseMove(int)));
4092        connect(fFeedbackCmdCam, SIGNAL(signalPixelMoveOver(int)),
4093                this, SLOT(slot_CameraMouseMove(int)));
4094
4095        connect(fRatesCanv, SIGNAL(signalPixelDoubleClick(int)),
4096                this, SLOT(slot_CameraDoubleClick(int)));
4097        connect(fRatesCanv, SIGNAL(signalCurrentPixel(int)),
4098                this, SLOT(slot_ChoosePixelThreshold(int)));
4099        connect(fBiasCamV, SIGNAL(signalCurrentPixel(int)),
4100                this, SLOT(slot_ChooseBiasChannel(int)));
4101        connect(fBiasCamA, SIGNAL(signalCurrentPixel(int)),
4102                this, SLOT(slot_ChooseBiasChannel(int)));
4103
4104        connect(fFtmRateCanv, SIGNAL(     RootEventProcessed(TObject*, unsigned int, TCanvas*)),
4105                this,         SLOT  (slot_RootEventProcessed(TObject*, unsigned int, TCanvas*)));
4106        connect(fAdcDataCanv, SIGNAL(     RootEventProcessed(TObject*, unsigned int, TCanvas*)),
4107                this,         SLOT  (slot_RootEventProcessed(TObject*, unsigned int, TCanvas*)));
4108    }
4109
4110    ~FactGui()
4111    {
4112        // Unsubscribe all services
4113        for (map<string,DimInfo*>::iterator i=fServices.begin();
4114             i!=fServices.end(); i++)
4115            delete i->second;
4116
4117        // This is allocated as a chuck of chars
4118        delete [] reinterpret_cast<char*>(fEventData);
4119    }
4120};
4121
4122#endif
Note: See TracBrowser for help on using the repository browser.