#ifndef FACT_FactGui #define FACT_FactGui #include "MainWindow.h" #include #include #include #include #include #include "CheckBoxDelegate.h" #include "src/Converter.h" #include "src/HeadersFTM.h" #include "src/DimNetwork.h" #include "src/tools.h" #include "TROOT.h" #include "TSystem.h" #include "TGraph.h" #include "TH1.h" #include "TStyle.h" #include "TMarker.h" #include "TColor.h" #define HAS_ROOT using namespace std; // ######################################################################### class Camera : public TObject { typedef pair Position; typedef vector Positions; Positions fGeom; void CreatePalette() { /* double ss[5] = {0., 0.10, 0.45, 0.75, 1.00}; double rr[5] = {0., 0.35, 0.85, 1.00, 1.00}; double gg[5] = {0., 0.10, 0.20, 0.73, 1.00}; double bb[5] = {0., 0.03, 0.06, 0.00, 1.00}; */ double ss[5] = {0., 0.25, 0.50, 0.75, 1.00}; double rr[5] = {0., 0.00, 0.00, 1.00, 1.00}; double gg[5] = {0., 0.00, 1.00, 0.00, 1.00}; double bb[5] = {0., 1.00, 0.00, 0.00, 1.00}; const Int_t nn = 1438; Int_t idx = TColor::CreateGradientColorTable(5, ss, rr, gg, bb, nn); for (int i=0; i 395.75) continue; fGeom.push_back(make_pair(yy, xx-0.5)); } } } } valarray fData; map fBold; map fEnable; int fWhite; public: Camera() : fData(0., 1438), fWhite(-1) { CreatePalette(); CreateGeometry(); for (int i=0; i<1438; i++) fData[i] = i; } void Reset() { fBold.clear(); } void SetBold(int idx) { fBold[idx]=true; } void SetWhite(int idx) { fWhite=idx; } void SetEnable(int idx, bool b) { fEnable[idx]=b; } void Toggle(int idx) { fEnable[idx]=!fEnable[idx]; } const char *GetName() const { return "Camera"; } vector fPalette; void Paint(const Position &p) { static const Double_t fgCos60 = 0.5; // TMath::Cos(60/TMath::RadToDeg()); static const Double_t fgSin60 = sqrt(3.)/2; // TMath::Sin(60/TMath::RadToDeg()); static const Double_t fgDy[6] = { fgCos60, 0., -fgCos60, -fgCos60, 0., fgCos60 }; static const Double_t fgDx[6] = { fgSin60/3, fgSin60*2/3, fgSin60/3, -fgSin60/3, -fgSin60*2/3, -fgSin60/3 }; // // calculate the positions of the pixel corners // Double_t x[7], y[7]; for (Int_t i=0; i<7; i++) { x[i] = p.first + fgDx[i%6]; y[i] = p.second + fgDy[i%6]; } gPad->PaintFillArea(6, x, y); gPad->PaintPolyLine(7, x, y); } void Paint(Option_t *) { gStyle->SetPalette(fPalette.size(), fPalette.data()); const double r = double(gPad->GetWw())/gPad->GetWh(); const double max = 20.5; // 20.5 rings in x and y if (r>1) gPad->Range(-r*max, -max, r*max, max); else gPad->Range(-max, -max/r, max, max/r); const double min = fData.min(); const double scale = fData.max()==fData.min() ? 1 : fData.max()-fData.min(); TAttFill fill(0, 1001); TAttLine line; int cnt=0; for (Positions::iterator p=fGeom.begin(); p!=fGeom.end(); p++, cnt++) { if (fBold[cnt]) continue; const int col = (fData[cnt]-min)/scale*(fPalette.size()-1); if (fEnable[cnt]) fill.SetFillColor(gStyle->GetColorPalette(col)); else fill.SetFillColor(kWhite); fill.Modify(); Paint(*p); } line.SetLineWidth(2); line.Modify(); cnt = 0; for (Positions::iterator p=fGeom.begin(); p!=fGeom.end(); p++, cnt++) { if (!fBold[cnt]) continue; const int col = (fData[cnt]-min)/scale*(fPalette.size()-1); if (fEnable[cnt]) fill.SetFillColor(gStyle->GetColorPalette(col)); else fill.SetFillColor(kWhite); fill.Modify(); Paint(*p); } TMarker m(0,0,kStar); m.DrawMarker(0, 0); if (fWhite<0) return; const Position &p = fGeom[fWhite]; line.SetLineColor(kWhite); line.Modify(); const int col = (fData[fWhite]-min)/scale*(fPalette.size()-1); if (fEnable[fWhite]) fill.SetFillColor(gStyle->GetColorPalette(col)); else fill.SetFillColor(kWhite); fill.Modify(); Paint(p); } int GetIdx(float px, float py) const { static const double sqrt3 = sqrt(3); int idx = 0; for (Positions::const_iterator p=fGeom.begin(); p!=fGeom.end(); p++, idx++) { const Double_t dy = py - p->second; if (fabs(dy)>0.5) continue; const Double_t dx = px - p->first; if (TMath::Abs(dy + dx*sqrt3) > 1) continue; if (TMath::Abs(dy - dx*sqrt3) > 1) continue; return idx; } return -1; } char* GetObjectInfo(Int_t px, Int_t py) const { static stringstream stream; static string str; const float x = gPad->PadtoX(gPad->AbsPixeltoX(px)); const float y = gPad->PadtoY(gPad->AbsPixeltoY(py)); const int idx = GetIdx(x, y); stream.seekp(0); if (idx>=0) stream << "Pixel=" << idx << " Data=" << fData[idx] << '\0'; str = stream.str(); return const_cast(str.c_str()); } Int_t DistancetoPrimitive(Int_t px, Int_t py) { const float x = gPad->PadtoX(gPad->AbsPixeltoX(px)); const float y = gPad->PadtoY(gPad->AbsPixeltoY(py)); return GetIdx(x, y)>=0 ? 0 : 99999; } void SetData(const valarray &data) { fData = data; } }; // ######################################################################### class FactGui : public MainWindow, public DimNetwork { private: class FunctionEvent : public QEvent { public: boost::function fFunction; FunctionEvent(const boost::function &f) : QEvent((QEvent::Type)QEvent::registerEventType()), fFunction(f) { } bool Exec() { fFunction(*this); return true; } }; valarray fFtuStatus; DimStampedInfo fDimDNS; DimStampedInfo fDimLoggerStats; DimStampedInfo fDimLoggerFilenameNight; DimStampedInfo fDimLoggerFilenameRun; DimStampedInfo fDimLoggerNumSubs; DimStampedInfo fDimFtmPassport; DimStampedInfo fDimFtmTriggerCounter; DimStampedInfo fDimFtmError; DimStampedInfo fDimFtmFtuList; DimStampedInfo fDimFtmStaticData; DimStampedInfo fDimFtmDynamicData; DimStampedInfo fDimFtmCounter; map fServices; // ========================== LED Colors ================================ enum LedColor_t { kLedRed, kLedGreen, kLedYellow, kLedOrange, kLedGray }; void SetLedColor(QPushButton *button, LedColor_t col, const Time &t) { switch (col) { case kLedRed: button->setIcon(QIcon(":/Resources/icons/red circle 1.png")); break; case kLedGreen: button->setIcon(QIcon(":/Resources/icons/green circle 1.png")); break; case kLedYellow: button->setIcon(QIcon(":/Resources/icons/yellow circle 1.png")); break; case kLedOrange: button->setIcon(QIcon(":/Resources/icons/orange circle 1.png")); break; case kLedGray: button->setIcon(QIcon(":/Resources/icons/gray circle 1.png")); break; } //button->setToolTip("Last change: "+QDateTime::currentDateTimeUtc().toString()+" UTC"); button->setToolTip(("Last change: "+t.GetAsStr()+" UTC").c_str()); } // ===================== Services and Commands ========================== QStandardItem *AddServiceItem(const std::string &server, const std::string &service, bool iscmd) { QListView *servers = iscmd ? fDimCmdServers : fDimSvcServers; QListView *services = iscmd ? fDimCmdCommands : fDimSvcServices; QListView *description = iscmd ? fDimCmdDescription : fDimSvcDescription; QStandardItemModel *m = dynamic_cast(servers->model()); if (!m) { m = new QStandardItemModel(this); servers->setModel(m); services->setModel(m); description->setModel(m); } QList l = m->findItems(server.c_str()); if (l.size()>1) { cout << "hae" << endl; return 0; } QStandardItem *col = l.size()==0 ? NULL : l[0]; if (!col) { col = new QStandardItem(server.c_str()); m->appendRow(col); if (!services->rootIndex().isValid()) { services->setRootIndex(col->index()); servers->setCurrentIndex(col->index()); } } QStandardItem *item = 0; for (int i=0; irowCount(); i++) { QStandardItem *coli = col->child(i); if (coli->text().toStdString()==service) return coli; } item = new QStandardItem(service.c_str()); col->appendRow(item); col->sortChildren(0); if (!description->rootIndex().isValid()) { description->setRootIndex(item->index()); services->setCurrentIndex(item->index()); } if (!iscmd) item->setCheckable(true); return item; } void AddDescription(QStandardItem *item, const vector &vec) { if (!item) return; if (vec.size()==0) return; item->setToolTip(vec[0].comment.c_str()); const string str = Description::GetHtmlDescription(vec); QStandardItem *desc = new QStandardItem(str.c_str()); desc->setSelectable(false); item->setChild(0, 0, desc); } void AddServer(const std::string &s) { DimNetwork::AddServer(s); QApplication::postEvent(this, new FunctionEvent(boost::bind(&FactGui::handleAddServer, this, s))); } void RemoveServer(const std::string &s) { UnsubscribeServer(s); DimNetwork::RemoveServer(s); QApplication::postEvent(this, new FunctionEvent(boost::bind(&FactGui::handleRemoveServer, this, s))); } void RemoveAllServers() { UnsubscribeAllServers(); vector v = GetServerList(); for (vector::iterator i=v.begin(); i &vec) { QApplication::postEvent(this, new FunctionEvent(boost::bind(&FactGui::handleAddDescription, this, server, service, vec))); } // ====================================================================== void handleAddServer(const std::string &server) { const State s = GetState(server, GetCurrentState(server)); handleStateChanged(Time(), server, s); } void handleRemoveServer(const string &server) { handleStateOffline(server); handleRemoveAllServices(server); } void handleRemoveAllServers() { QStandardItemModel *m = 0; if ((m=dynamic_cast(fDimCmdServers->model()))) m->removeRows(0, m->rowCount()); if ((m = dynamic_cast(fDimSvcServers->model()))) m->removeRows(0, m->rowCount()); } void handleAddService(const std::string &server, const std::string &service, const std::string &/*fmt*/, bool iscmd) { QStandardItem *item = AddServiceItem(server, service, iscmd); const vector v = GetDescription(server, service); AddDescription(item, v); } void handleRemoveService(const std::string &server, const std::string &service, bool iscmd) { QListView *servers = iscmd ? fDimCmdServers : fDimSvcServers; QStandardItemModel *m = dynamic_cast(servers->model()); if (!m) return; QList l = m->findItems(server.c_str()); if (l.size()!=1) return; for (int i=0; irowCount(); i++) { QStandardItem *row = l[0]->child(i); if (row->text().toStdString()==service) { l[0]->removeRow(row->index().row()); return; } } } void handleRemoveAllServices(const std::string &server) { QStandardItemModel *m = 0; if ((m=dynamic_cast(fDimCmdServers->model()))) { QList l = m->findItems(server.c_str()); if (l.size()==1) m->removeRow(l[0]->index().row()); } if ((m = dynamic_cast(fDimSvcServers->model()))) { QList l = m->findItems(server.c_str()); if (l.size()==1) m->removeRow(l[0]->index().row()); } } void handleAddDescription(const std::string &server, const std::string &service, const vector &vec) { const bool iscmd = IsCommand(server, service)==true; QStandardItem *item = AddServiceItem(server, service, iscmd); AddDescription(item, vec); } // ====================================================================== void SubscribeService(const string &service) { if (fServices.find(service)!=fServices.end()) { cout << "ERROR - We are already subscribed to " << service << endl; return; } fServices[service] = new DimStampedInfo(service.c_str(), (void*)NULL, 0, this); } void UnsubscribeService(const string &service) { const map::iterator i=fServices.find(service); if (i==fServices.end()) { cout << "ERROR - We are not subscribed to " << service << endl; return; } delete i->second; fServices.erase(i); } void UnsubscribeServer(const string &server) { for (map::iterator i=fServices.begin(); i!=fServices.end(); i++) if (i->first.substr(0, server.length()+1)==server+'/') { delete i->second; fServices.erase(i); } } void UnsubscribeAllServers() { for (map::iterator i=fServices.begin(); i!=fServices.end(); i++) delete i->second; fServices.clear(); } // ====================================================================== struct DimData { Time time; int qos; string name; string format; vector data; DimInfo *info; // this is ONLY for a fast check of the type of the DimData!! DimData(DimInfo *inf) : qos(inf->getQuality()), name(inf->getName()), format(inf->getFormat()), data(inf->getString(), inf->getString()+inf->getSize()), info(inf) { // Must be called in exactly this order! const int tsec = inf->getTimestamp(); const int tms = inf->getTimestampMillisecs(); time = Time(tsec, tms*1000); } template T get() const { return *reinterpret_cast(data.data()); } vector vec(int b) const { return vector(data.begin()+b, data.end()); } string str(unsigned int b) const { return b>=data.size()?string():string(data.data()+b, data.size()-b); } const char *c_str() const { return (char*)data.data(); } vector any() const { const Converter conv(format); conv.Print(); return conv.GetAny(data.data(), data.size()); } int size() const { return data.size(); } const void *ptr() const { return data.data(); } }; // ======================= DNS ========================================== void handleDimDNS(const DimData &d) { const int version = d.get(); ostringstream str; str << "V" << version/100 << 'r' << version%100; SetLedColor(fStatusDNSLed, version==0 ? kLedRed : kLedGreen, Time()); fStatusDNSLabel->setText(version==0?"Offline":str.str().c_str()); fStatusDNSLabel->setToolTip(version==0?"No connection to DIM DNS.":"Connection to DIM DNS established."); } // ======================= Logger ======================================= void handleLoggerStats(const DimData &d) { const bool connected = d.size()!=0; fLoggerET->setEnabled(connected); fLoggerRate->setEnabled(connected); fLoggerWritten->setEnabled(connected); fLoggerFreeSpace->setEnabled(connected); fLoggerSpaceLeft->setEnabled(connected); if (!connected) return; const uint64_t *vals = reinterpret_cast(d.ptr()); const size_t written = vals[0]; const size_t space = vals[1]; const size_t rate = vals[2]; fLoggerFreeSpace->setSuffix(" MB"); fLoggerFreeSpace->setDecimals(0); fLoggerFreeSpace->setValue(space*1e-6); if (space> 1000000) // > 1GB { fLoggerFreeSpace->setSuffix(" GB"); fLoggerFreeSpace->setDecimals(2); fLoggerFreeSpace->setValue(space*1e-9); } if (space>= 3000000) // >= 3GB { fLoggerFreeSpace->setSuffix(" GB"); fLoggerFreeSpace->setDecimals(1); fLoggerFreeSpace->setValue(space*1e-9); } if (space>=100000000) // >= 100GB { fLoggerFreeSpace->setSuffix(" GB"); fLoggerFreeSpace->setDecimals(0); fLoggerFreeSpace->setValue(space*1e-9); } fLoggerET->setTime(QTime().addSecs(rate>0?space/rate:0)); fLoggerRate->setValue(rate*1e-3); // kB/s fLoggerWritten->setValue(written*1e-6); fLoggerRate->setSuffix(" kB/s"); fLoggerRate->setDecimals(2); fLoggerRate->setValue(rate*1e-3); if (rate> 2000) // > 2kB/s { fLoggerRate->setSuffix(" kB/s"); fLoggerRate->setDecimals(1); fLoggerRate->setValue(rate*1e-3); } if (rate>=100000) // >100kB/s { fLoggerRate->setSuffix(" kB/s"); fLoggerRate->setDecimals(0); fLoggerRate->setValue(rate*1e-3); } if (rate>=1000000) // >100kB/s { fLoggerRate->setSuffix(" MB/s"); fLoggerRate->setDecimals(2); fLoggerRate->setValue(rate*1e-6); } if (rate>=10000000) // >1MB/s { fLoggerRate->setSuffix(" MB/s"); fLoggerRate->setDecimals(1); fLoggerRate->setValue(rate*1e-6); } if (rate>=100000000) // >10MB/s { fLoggerRate->setSuffix(" MB/s"); fLoggerRate->setDecimals(0); fLoggerRate->setValue(rate*1e-6); } if (space/1000000>static_cast(fLoggerSpaceLeft->maximum())) fLoggerSpaceLeft->setValue(fLoggerSpaceLeft->maximum()); // GB else fLoggerSpaceLeft->setValue(space/1000000); // MB } void handleLoggerFilenameNight(const DimData &d) { const bool connected = d.size()!=0; fLoggerFilenameNight->setEnabled(connected); if (!connected) return; fLoggerFilenameNight->setText(d.c_str()+4); const uint32_t files = d.get(); SetLedColor(fLoggerLedLog, files&1 ? kLedGreen : kLedGray, d.time); SetLedColor(fLoggerLedRep, files&2 ? kLedGreen : kLedGray, d.time); SetLedColor(fLoggerLedFits, files&4 ? kLedGreen : kLedGray, d.time); } void handleLoggerFilenameRun(const DimData &d) { const bool connected = d.size()!=0; fLoggerFilenameRun->setEnabled(connected); if (!connected) return; fLoggerFilenameRun->setText(d.c_str()+4); const uint32_t files = d.get(); SetLedColor(fLoggerLedLog, files&1 ? kLedGreen : kLedGray, d.time); SetLedColor(fLoggerLedRep, files&2 ? kLedGreen : kLedGray, d.time); SetLedColor(fLoggerLedFits, files&4 ? kLedGreen : kLedGray, d.time); } void handleLoggerNumSubs(const DimData &d) { const bool connected = d.size()!=0; fLoggerSubscriptions->setEnabled(connected); fLoggerOpenFiles->setEnabled(connected); if (!connected) return; const uint32_t *vals = reinterpret_cast(d.ptr()); fLoggerSubscriptions->setValue(vals[0]); fLoggerOpenFiles->setValue(vals[1]); } // ===================== FTM ============================================ void handleFtmTriggerCounter(const DimData &d) { if (d.size()==0) return; if (d.size()!=sizeof(FTM::DimTriggerCounter)) { cout << "Size mismatch: " << d.size() << " " << sizeof(FTM::DimTriggerCounter) << endl; return; } const FTM::DimTriggerCounter &sdata = *reinterpret_cast(d.ptr()); fFtmTime->setText(QString::number(sdata.fTimeStamp)); fTriggerCounter->setText(QString::number(sdata.fTriggerCounter)); } void handleFtmCounter(const DimData &d) { if (d.size()==0) return; if (d.size()!=sizeof(uint32_t)*6) { cout << "Size mismatch: " << d.size() << " " << sizeof(uint32_t)*6 << endl; return; } const uint32_t *sdata = reinterpret_cast(d.ptr()); fFtmCounterH->setValue(sdata[0]); fFtmCounterS->setValue(sdata[1]); fFtmCounterD->setValue(sdata[2]); fFtmCounterF->setValue(sdata[3]); fFtmCounterE->setValue(sdata[4]); fFtmCounterR->setValue(sdata[5]); } void handleFtmDynamicData(const DimData &d) { if (d.size()==0) return; if (d.size()!=sizeof(FTM::DimDynamicData)) { cout << "Size mismatch: " << d.size() << " " << sizeof(FTM::DimDynamicData) << endl; return; } const FTM::DimDynamicData &sdata = *reinterpret_cast(d.ptr()); fFtmTime->setText(QString::number(sdata.fTimeStamp)); fOnTime->setText(QString::number(sdata.fOnTimeCounter)); fFtmTemp0->setValue(sdata.fTempSensor[0]*0.1); fFtmTemp1->setValue(sdata.fTempSensor[1]*0.1); fFtmTemp2->setValue(sdata.fTempSensor[2]*0.1); fFtmTemp3->setValue(sdata.fTempSensor[3]*0.1); // ---------------------------------------------- #ifdef HAS_ROOT TCanvas *c = fFtmTempCanv->GetCanvas(); static int cntr = 0; double_t tm = cntr++;//Time().RootTime(); TH1 *h = (TH1*)c->FindObject("MyFrame"); h->FindBin(tm); fGraphFtmTemp[0].SetPoint(fGraphFtmTemp[0].GetN(), tm, sdata.fTempSensor[0]*0.1); fGraphFtmTemp[1].SetPoint(fGraphFtmTemp[1].GetN(), tm, sdata.fTempSensor[1]*0.1); fGraphFtmTemp[2].SetPoint(fGraphFtmTemp[2].GetN(), tm, sdata.fTempSensor[2]*0.1); fGraphFtmTemp[3].SetPoint(fGraphFtmTemp[3].GetN(), tm, sdata.fTempSensor[3]*0.1); c->Modified(); c->Update(); // ---------------------------------------------- valarray dat(0., 1438); for (int i=0; i<1438; i++) dat[i] = sdata.fRatePatch[fPatch[i]]; c = fRatesCanv->GetCanvas(); Camera *cam = (Camera*)c->FindObject("Camera"); cam->SetData(dat); c->Modified(); c->Update(); #endif } FTM::DimStaticData fFtmStaticData; void SetFtuLed(int idx, int counter, const Time &t) { if (counter==0 || counter>3) counter = 3; if (counter<0) counter = 0; const LedColor_t col[4] = { kLedGray, kLedGreen, kLedOrange, kLedRed }; SetLedColor(fFtuLED[idx], col[counter], t); fFtuStatus[idx] = counter; } void SetFtuStatusLed(const Time &t) { const int max = fFtuStatus.max(); switch (max) { case 0: SetLedColor(fStatusFTULed, kLedGray, t); fStatusFTULabel->setText("All disabled"); fStatusFTULabel->setToolTip("All FTUs are disabled"); break; case 1: SetLedColor(fStatusFTULed, kLedGreen, t); fStatusFTULabel->setToolTip("Communication with FTU is smooth."); fStatusFTULabel->setText("ok"); break; case 2: SetLedColor(fStatusFTULed, kLedOrange, t); fStatusFTULabel->setText("Warning"); fStatusFTULabel->setToolTip("At least one FTU didn't answer immediately"); break; case 3: SetLedColor(fStatusFTULed, kLedRed, t); fStatusFTULabel->setToolTip("At least one FTU didn't answer!"); fStatusFTULabel->setText("ERROR"); break; } } void handleFtmStaticData(const DimData &d) { if (d.size()==0) return; if (d.size()!=sizeof(FTM::DimStaticData)) { cout << "Size mismatch: " << d.size() << " " << sizeof(FTM::DimStaticData) << endl; return; } const FTM::DimStaticData &sdata = *reinterpret_cast(d.ptr()); fTriggerInterval->setValue(sdata.fTriggerInterval); fPhysicsCoincidence->setValue(sdata.fCoincidencePhysics); fCalibCoincidence->setValue(sdata.fCoincidenceCalib); fPhysicsWindow->setValue(sdata.fWindowPhysics); fCalibWindow->setValue(sdata.fWindowCalib); fTriggerDelay->setValue(sdata.fDelayTrigger); fTimeMarkerDelay->setValue(sdata.fDelayTimeMarker); fDeadTime->setValue(sdata.fDeadTime); fClockCondR0->setValue(sdata.fClockConditioner[0]); fClockCondR1->setValue(sdata.fClockConditioner[1]); fClockCondR8->setValue(sdata.fClockConditioner[2]); fClockCondR9->setValue(sdata.fClockConditioner[3]); fClockCondR11->setValue(sdata.fClockConditioner[4]); fClockCondR13->setValue(sdata.fClockConditioner[5]); fClockCondR14->setValue(sdata.fClockConditioner[6]); fClockCondR15->setValue(sdata.fClockConditioner[7]); fTriggerSeqPed->setValue(sdata.fTriggerSeqPed); fTriggerSeqLPint->setValue(sdata.fTriggerSeqLPint); fTriggerSeqLPext->setValue(sdata.fTriggerSeqLPext); fEnableTrigger->setChecked(sdata.HasTrigger()); fEnableVeto->setChecked(sdata.HasVeto()); fEnableExt1->setChecked(sdata.HasExt1()); fEnableExt2->setChecked(sdata.HasExt2()); fEnableTimeMarker->setChecked(sdata.HasTimeMarker()); for (int i=0; i<40; i++) { if (!sdata.IsActive(i)) SetFtuLed(i, -1, d.time); else { if (fFtuStatus[i]==0) SetFtuLed(i, 1, d.time); } fFtuLED[i]->setChecked(false); } SetFtuStatusLed(d.time); #ifdef HAS_ROOT Camera *cam = (Camera*)fRatesCanv->GetCanvas()->FindObject("Camera"); for (int i=0; i<1438; i++) cam->SetEnable(i, sdata.IsEnabled(i)); #endif const int patch1 = fThresholdIdx->value(); fThresholdVal->setValue(sdata.fThreshold[patch1<0?0:patch1]); fPrescalingVal->setValue(sdata.fPrescaling[0]); fFtmStaticData = sdata; } void handleFtmPassport(const DimData &d) { if (d.size()==0) return; if (d.size()!=sizeof(FTM::DimPassport)) { cout << "Size mismatch: " << d.size() << " " << sizeof(FTM::DimPassport) << endl; return; } const FTM::DimPassport &sdata = *reinterpret_cast(d.ptr()); stringstream str1, str2; str1 << hex << "0x" << setfill('0') << setw(16) << sdata.fBoardId; str2 << sdata.fFirmwareId; fFtmBoardId->setText(str1.str().c_str()); fFtmFirmwareId->setText(str2.str().c_str()); } void handleFtmFtuList(const DimData &d) { if (d.size()==0) return; if (d.size()!=sizeof(FTM::DimFtuList)) { cout << "Size mismatch: " << d.size() << " " << sizeof(FTM::DimFtuList) << endl; return; } fPing->setChecked(false); const FTM::DimFtuList &sdata = *reinterpret_cast(d.ptr()); stringstream str; str << "" << setfill('0'); str << ""; for (int i=0; i<40; i++) { str << ""; str << ""; str << ""; str << ""; str << ""; str << ""; str << ""; } str << "
NumAddrDNA
" << dec << i << hex << ":0x" << setw(2) << (int)sdata.fAddr[i] << ":0x" << setw(16) << sdata.fDNA[i] << "
"; fFtuDNA->setText(str.str().c_str()); fFtuAnswersTotal->setValue(sdata.fNumBoards); fFtuAnswersCrate0->setValue(sdata.fNumBoardsCrate[0]); fFtuAnswersCrate1->setValue(sdata.fNumBoardsCrate[1]); fFtuAnswersCrate2->setValue(sdata.fNumBoardsCrate[2]); fFtuAnswersCrate3->setValue(sdata.fNumBoardsCrate[3]); for (int i=0; i<40; i++) SetFtuLed(i, sdata.IsActive(i) ? sdata.fPing[i] : -1, d.time); SetFtuStatusLed(d.time); } void handleFtmError(const DimData &d) { if (d.size()==0) return; const FTM::DimError &sdata = *reinterpret_cast(d.ptr()); SetFtuLed(sdata.fError.fDestAddress , sdata.fError.fNumCalls, d.time); SetFtuStatusLed(d.time); // Write to special window! Out() << "Error:" << endl; Out() << sdata.fError << endl; } // ====================== MessageImp ==================================== bool fChatOnline; void handleStateChanged(const Time &time, const std::string &server, const State &s) { // FIXME: Prefix tooltip with time if (server=="FTM_CONTROL") { fStatusFTMLabel->setText(s.name.c_str()); fStatusFTMLabel->setToolTip(s.comment.c_str()); bool enable = false; if (s.indexsetEnabled(enable); fFtuWidget->setEnabled(enable); fRatesWidget->setEnabled(enable); if (!enable) { SetLedColor(fStatusFTULed, kLedGray, time); fStatusFTULabel->setText("Offline"); fStatusFTULabel->setToolTip("FTM is not online."); } } if (server=="FAD_CONTROL") { fStatusFADLabel->setText(s.name.c_str()); fStatusFADLabel->setToolTip(s.comment.c_str()); if (s.indexsetText(s.name.c_str()); fStatusLoggerLabel->setToolTip(s.comment.c_str()); bool enable = true; if (s.index<=30) // Ready/Waiting SetLedColor(fStatusLoggerLed, kLedYellow, time); if (s.index<-1) // Offline { SetLedColor(fStatusLoggerLed, kLedGray, time); enable = false; } if (s.index>=0x100) // Error SetLedColor(fStatusLoggerLed, kLedRed, time); if (s.index==40) // Logging SetLedColor(fStatusLoggerLed, kLedGreen, time); fLoggerWidget->setEnabled(enable); } if (server=="CHAT") { fStatusChatLabel->setText(s.name.c_str()); fChatOnline = s.index==0; SetLedColor(fStatusChatLed, fChatOnline ? kLedGreen : kLedRed, time); fChatSend->setEnabled(fChatOnline); fChatMessage->setEnabled(fChatOnline); } if (server=="SCHEDULER") { fStatusSchedulerLabel->setText(s.name.c_str()); SetLedColor(fStatusSchedulerLed, s.index>=0 ? kLedGreen : kLedRed, time); } } void handleStateOffline(const string &server) { handleStateChanged(Time(), server, State(-2, "Offline", "No connection via DIM.")); } void on_fTabWidget_currentChanged(int which) { if (fTabWidget->tabText(which)=="Chat") fTabWidget->setTabIcon(which, QIcon()); } void handleWrite(const Time &time, const string &text, int qos) { stringstream out; if (text.substr(0, 6)=="CHAT: ") { out << "["; out << Time::fmt("%H:%M:%S") << time << "] "; out << text.substr(6); fChatText->append(out.str().c_str()); if (fTabWidget->tabText(fTabWidget->currentIndex())=="Chat") return; static int num = 0; if (num++<2) return; for (int i=0; icount(); i++) if (fTabWidget->tabText(i)=="Chat") { fTabWidget->setTabIcon(i, QIcon(":/Resources/icons/warning 3.png")); break; } return; } out << "" << time.GetAsStr() << " - " << text << ""; fLogText->append(out.str().c_str()); if (qos>=kWarn) fTextEdit->append(out.str().c_str()); } void IndicateStateChange(const Time &time, const std::string &server) { const State s = GetState(server, GetCurrentState(server)); QApplication::postEvent(this, new FunctionEvent(boost::bind(&FactGui::handleStateChanged, this, time, server, s))); } int Write(const Time &time, const string &txt, int qos) { QApplication::postEvent(this, new FunctionEvent(boost::bind(&FactGui::handleWrite, this, time, txt, qos))); return 0; } // ====================== Dim infoHandler================================ void handleDimService(const string &txt) { fDimSvcText->append(txt.c_str()); } void infoHandlerService(DimInfo &info) { const string fmt = string(info.getFormat()).empty() ? "C" : info.getFormat(); stringstream dummy; const Converter conv(dummy, fmt, false); const Time tm(info.getTimestamp(), info.getTimestampMillisecs()*1000); stringstream out; out << "[" << Time::fmt("%H:%M:%S.%f") << tm << "] " << info.getName() << " - "; bool iserr = true; if (!conv) { out << "Compilation of format string '" << fmt << "' failed!"; } else { try { const string dat = conv.GetString(info.getData(), info.getSize()); out << dat; iserr = false; } catch (const runtime_error &e) { out << "Conversion to string failed!
" << e.what() << "
"; } } // srand(hash()(string(info.getName()))); // int bg = rand()&0xffffff; int bg = hash()(string(info.getName())); // allow only light colors bg = ~(bg&0x1f1f1f)&0xffffff; if (iserr) bg = 0xffffff; stringstream bgcol; bgcol << hex << setfill('0') << setw(6) << bg; const string col = iserr ? "red" : "black"; const string str = "
"+out.str()+"
"; QApplication::postEvent(this, new FunctionEvent(boost::bind(&FactGui::handleDimService, this, str))); } void CallInfoHandler(void (FactGui::*handler)(const DimData&), const DimData &d) { fInHandler = true; (this->*handler)(d); fInHandler = false; } /* void CallInfoHandler(const boost::function &func) { // This ensures that newly received values are not sent back to the emitter // because changing the value emits the valueChanged signal (or similar) fInHandler = true; func(); fInHandler = false; }*/ void PostInfoHandler(void (FactGui::*handler)(const DimData&)) { //const boost::function f = boost::bind(handler, this, DimData(getInfo())); FunctionEvent *evt = new FunctionEvent(boost::bind(&FactGui::CallInfoHandler, this, handler, DimData(getInfo()))); // FunctionEvent *evt = new FunctionEvent(boost::bind(&FactGui::CallInfoHandler, this, f)); // FunctionEvent *evt = new FunctionEvent(boost::bind(handler, this, DimData(getInfo())))); QApplication::postEvent(this, evt); } void infoHandler() { // Initialize the time-stamp (what a weird workaround...) if (getInfo()) getInfo()->getTimestamp(); if (getInfo()==&fDimDNS) return PostInfoHandler(&FactGui::handleDimDNS); cout << "HandleDimInfo " << getInfo()->getName() << endl; if (getInfo()==&fDimLoggerStats) return PostInfoHandler(&FactGui::handleLoggerStats); if (getInfo()==&fDimLoggerFilenameNight) return PostInfoHandler(&FactGui::handleLoggerFilenameNight); if (getInfo()==&fDimLoggerNumSubs) return PostInfoHandler(&FactGui::handleLoggerNumSubs); if (getInfo()==&fDimLoggerFilenameRun) return PostInfoHandler(&FactGui::handleLoggerFilenameRun); if (getInfo()==&fDimFtmTriggerCounter) return PostInfoHandler(&FactGui::handleFtmTriggerCounter); if (getInfo()==&fDimFtmCounter) return PostInfoHandler(&FactGui::handleFtmCounter); if (getInfo()==&fDimFtmDynamicData) return PostInfoHandler(&FactGui::handleFtmDynamicData); if (getInfo()==&fDimFtmPassport) return PostInfoHandler(&FactGui::handleFtmPassport); if (getInfo()==&fDimFtmFtuList) return PostInfoHandler(&FactGui::handleFtmFtuList); if (getInfo()==&fDimFtmStaticData) return PostInfoHandler(&FactGui::handleFtmStaticData); if (getInfo()==&fDimFtmError) return PostInfoHandler(&FactGui::handleFtmError); for (map::iterator i=fServices.begin(); i!=fServices.end(); i++) if (i->second==getInfo()) { infoHandlerService(*i->second); return; } DimNetwork::infoHandler(); } // ====================================================================== bool event(QEvent *evt) { if (dynamic_cast(evt)) return static_cast(evt)->Exec(); if (dynamic_cast(evt)) { const QStandardItem &item = static_cast(evt)->item; const QStandardItem *par = item.parent(); if (par) { const QString server = par->text(); const QString service = item.text(); const string s = (server+'/'+service).toStdString(); if (item.checkState()==Qt::Checked) SubscribeService(s); else UnsubscribeService(s); } } return MainWindow::event(evt); // unrecognized } void on_fDimCmdSend_clicked() { const QString server = fDimCmdServers->currentIndex().data().toString(); const QString command = fDimCmdCommands->currentIndex().data().toString(); const QString arguments = fDimCmdLineEdit->displayText(); // FIXME: Sending a command exactly when the info Handler changes // the list it might lead to confusion. try { SendDimCommand(server.toStdString(), command.toStdString()+" "+arguments.toStdString()); fTextEdit->append("Command '"+server+'/'+command+"' successfully emitted."); fDimCmdLineEdit->clear(); } catch (const runtime_error &e) { stringstream txt; txt << e.what(); string buffer; while (getline(txt, buffer, '\n')) fTextEdit->append(("
"+buffer+"
").c_str()); } } void ChoosePatch(Camera &cam, int idx) { cam.Reset(); fThresholdIdx->setValue(idx); fThresholdVal->setValue(fFtmStaticData.fThreshold[idx<0?0:idx]); if (idx<0) return; for (unsigned int i=0; i(obj)) return; TQtWidget *tipped = static_cast(sender()); if (evt==11/*kMouseReleaseEvent*/) { if (dynamic_cast(obj)) { const float xx = gPad->PadtoX(gPad->AbsPixeltoX(tipped->GetEventX())); const float yy = gPad->PadtoY(gPad->AbsPixeltoY(tipped->GetEventY())); Camera *cam = static_cast(obj); const int idx = cam->GetIdx(xx, yy); ChoosePixel(*cam, idx); } return; } if (evt==61/*kMouseDoubleClickEvent*/) { if (dynamic_cast(obj)) { const float xx = gPad->PadtoX(gPad->AbsPixeltoX(tipped->GetEventX())); const float yy = gPad->PadtoY(gPad->AbsPixeltoY(tipped->GetEventY())); Camera *cam = static_cast(obj); const int idx = cam->GetIdx(xx, yy); cam->Toggle(idx); } return; } // Find the object which will get picked by the GetObjectInfo // due to buffer overflows in many root-versions // in TH1 and TProfile we have to work around and implement // our own GetObjectInfo which make everything a bit more // complicated. #if ROOT_VERSION_CODE > ROOT_VERSION(5,22,00) const char *objectInfo = obj->GetObjectInfo(tipped->GetEventX(),tipped->GetEventY()); #else const char *objectInfo = dynamic_cast(obj) ? "" : obj->GetObjectInfo(tipped->GetEventX(),tipped->GetEventY()); #endif QString tipText; tipText += obj->GetName(); tipText += " ["; tipText += obj->ClassName(); tipText += "]: "; tipText += objectInfo; if (dynamic_cast(obj)) { const float xx = gPad->PadtoX(gPad->AbsPixeltoX(tipped->GetEventX())); const float yy = gPad->PadtoY(gPad->AbsPixeltoY(tipped->GetEventY())); Camera *cam = static_cast(obj); int idx = fPatch[cam->GetIdx(xx, yy)]; tipText+=" Patch="; tipText+=QString::number(idx); } fStatusBar->showMessage(tipText, 3000); gSystem->ProcessEvents(); //QWhatsThis::display(tipText) } void slot_RootUpdate() { gSystem->ProcessEvents(); QTimer::singleShot(0, this, SLOT(slot_RootUpdate())); } void on_fThresholdIdx_valueChanged(int idx) { Camera *cam = (Camera*)fRatesCanv->GetCanvas()->FindObject("Camera"); ChoosePatch(*cam, idx); } #endif TGraph fGraphFtmTemp[4]; map fPatch; public: FactGui() : fFtuStatus(40), fDimDNS("DIS_DNS/VERSION_NUMBER", 1, int(0), this), fDimLoggerStats ("DATA_LOGGER/STATS", (void*)NULL, 0, this), fDimLoggerFilenameNight("DATA_LOGGER/FILENAME_NIGHTLY", const_cast(""), 0, this), fDimLoggerFilenameRun ("DATA_LOGGER/FILENAME_RUN", const_cast(""), 0, this), fDimLoggerNumSubs ("DATA_LOGGER/NUM_SUBS", const_cast(""), 0, this), fDimFtmPassport ("FTM_CONTROL/PASSPORT", (void*)NULL, 0, this), fDimFtmTriggerCounter("FTM_CONTROL/TRIGGER_COUNTER", (void*)NULL, 0, this), fDimFtmError ("FTM_CONTROL/ERROR", (void*)NULL, 0, this), fDimFtmFtuList ("FTM_CONTROL/FTU_LIST", (void*)NULL, 0, this), fDimFtmStaticData ("FTM_CONTROL/STATIC_DATA", (void*)NULL, 0, this), fDimFtmDynamicData ("FTM_CONTROL/DYNAMIC_DATA", (void*)NULL, 0, this), fDimFtmCounter ("FTM_CONTROL/COUNTER", (void*)NULL, 0, this) { fTriggerWidget->setEnabled(false); fFtuWidget->setEnabled(false); fRatesWidget->setEnabled(false); fLoggerWidget->setEnabled(false); fChatSend->setEnabled(false); fChatMessage->setEnabled(false); DimClient::sendCommand("CHAT/MSG", "GUI online."); // + MessageDimRX // -------------------------------------------------------------------------- ifstream fin("fact-trigger-all.txt"); int l = 0; string buf; while (getline(fin, buf, '\n')) { buf = Tools::Trim(buf); if (buf[0]=='#') continue; stringstream str(buf); for (int i=0; i<9; i++) { int n; str >> n; fPatch[n] = l; } l++; } // -------------------------------------------------------------------------- #ifdef HAS_ROOT TCanvas *c = fFtmTempCanv->GetCanvas(); c->SetBit(TCanvas::kNoContextMenu); c->SetBorderMode(0); c->SetFrameBorderMode(0); c->SetFillColor(kWhite); c->SetRightMargin(0.03); c->SetTopMargin(0.03); c->cd(); TH1F h("MyFrame", "", 1000, 0, 1);//Time().RootTime()-1./24/60/60, Time().RootTime()); h.SetDirectory(0); h.SetBit(TH1::kCanRebin); h.SetStats(kFALSE); h.SetMinimum(-20); h.SetMaximum(100); h.SetXTitle("Time"); h.SetYTitle("Temperature / °C"); h.GetXaxis()->CenterTitle(); h.GetYaxis()->CenterTitle(); // h.GetXaxis()->SetTitleSize(1.2); // h.GetYaxis()->SetTitleSize(1.2); h.DrawCopy(); fGraphFtmTemp[0].SetMarkerStyle(kFullDotSmall); fGraphFtmTemp[1].SetMarkerStyle(kFullDotSmall); fGraphFtmTemp[2].SetMarkerStyle(kFullDotSmall); fGraphFtmTemp[3].SetMarkerStyle(kFullDotSmall); fGraphFtmTemp[1].SetLineColor(kBlue); fGraphFtmTemp[2].SetLineColor(kRed); fGraphFtmTemp[3].SetLineColor(kGreen); fGraphFtmTemp[1].SetMarkerColor(kBlue); fGraphFtmTemp[2].SetMarkerColor(kRed); fGraphFtmTemp[3].SetMarkerColor(kGreen); fGraphFtmTemp[0].Draw("LP"); fGraphFtmTemp[1].Draw("LP"); fGraphFtmTemp[2].Draw("LP"); fGraphFtmTemp[3].Draw("LP"); // -------------------------------------------------------------------------- c = fRatesCanv->GetCanvas(); c->SetBit(TCanvas::kNoContextMenu); c->SetBorderMode(0); c->SetFrameBorderMode(0); c->SetFillColor(kWhite); c->cd(); Camera *cam = new Camera; cam->SetBit(kCanDelete); cam->Draw(); ChoosePixel(*cam, 1); // QTimer::singleShot(0, this, SLOT(slot_RootUpdate())); //widget->setMouseTracking(true); //widget->EnableSignalEvents(kMouseMoveEvent); fFtmTempCanv->setMouseTracking(true); fFtmTempCanv->EnableSignalEvents(kMouseMoveEvent); fRatesCanv->setMouseTracking(true); fRatesCanv->EnableSignalEvents(kMouseMoveEvent|kMouseReleaseEvent|kMouseDoubleClickEvent); connect(fRatesCanv, SIGNAL( RootEventProcessed(TObject*, unsigned int, TCanvas*)), this, SLOT (slot_RootEventProcessed(TObject*, unsigned int, TCanvas*))); connect(fFtmTempCanv, SIGNAL( RootEventProcessed(TObject*, unsigned int, TCanvas*)), this, SLOT (slot_RootEventProcessed(TObject*, unsigned int, TCanvas*))); #endif } ~FactGui() { UnsubscribeAllServers(); } }; #endif