// $Id$ //----------------------------------------------------------------------- // The GSI Online Offline Object Oriented (Go4) Project // Experiment Data Processing at EE department, GSI //----------------------------------------------------------------------- // Copyright (C) 2000- GSI Helmholtzzentrum f�r Schwerionenforschung GmbH // Planckstr. 1, 64291 Darmstadt, Germany // Contact: http://go4.gsi.de //----------------------------------------------------------------------- // This software can be used under the license agreements as stated // in Go4License.txt file which is part of the distribution. //----------------------------------------------------------------------- #include "TEpicsProc.h" #include #include #include "TH1.h" #include "TH2.h" #include "TCutG.h" #include "TCanvas.h" #include "TLine.h" #include "TGo4MbsEvent.h" #include "TGo4WinCond.h" #include "TGo4PolyCond.h" #include "TGo4CondArray.h" #include "TGo4Picture.h" #include "TGo4StepFactory.h" #include "TGo4Analysis.h" #include "TGo4Version.h" #define CBM_EPIX_SUBID 0xa #define CBM_EPIX_NUMHIS_LONG 200 #define CBM_EPIX_NUMHIS_DOUBLE 200 #define CBM_EPIX_TRENDSIZE 120 #define CBM_EPIX_STATRANGE 5000 #define CBM_EPIX_useDOUBLES true extern "C" { INTS4 f_ut_utime(INTS4 l_sec, INTS4 l_msec, CHARS *pc_time); } #include "f_ut_utime.h" //*********************************************************** TEpicsProc::TEpicsProc() : TGo4EventProcessor() { } //*********************************************************** TEpicsProc::~TEpicsProc() { TGo4Log::Info("TEpicsProc: Delete instance"); } //*********************************************************** // this one is used in standard factory TEpicsProc::TEpicsProc(const char *name) : TGo4EventProcessor(name) { TGo4Log::Info("TEpicsProc: Create instance %s", name); fVerbose = false; } const char *TEpicsProc::GetUpdateTimeString() { if(fUTimeSeconds == 0) return "EPICS time not available"; UInt_t timeseconds=fUTimeSeconds; UInt_t timemicros=0; f_ut_utime(timeseconds, timemicros, fcTimeString); return fcTimeString; } //----------------------------------------------------------- // event function Bool_t TEpicsProc::BuildEvent(TGo4EventElement*) { // called by framework. We dont fill any output event here at all if (!GetInputEvent() || (GetInputEvent()->IsA() != TGo4MbsEvent::Class())) { TGo4Log::Error("TEpicsProc: no input MBS event found!"); return kFALSE; } TGo4MbsEvent* evnt = (TGo4MbsEvent*) GetInputEvent(); if(evnt->GetTrigger() > 11) { TGo4Log::Info("TEpicsProc: Skip trigger event"); return kFALSE; } evnt->ResetIterator(); TGo4MbsSubEvent *psubevt = nullptr; while((psubevt = evnt->NextSubEvent()) != nullptr) { // loop over subevents if (psubevt->GetProcid() != CBM_EPIX_SUBID) return kFALSE; Int_t* pdata = psubevt->GetDataField(); Int_t* theEnd = psubevt->GetDataField() + psubevt->GetIntLen(); //first payload: event id number fEventId = *pdata++; if (fVerbose) printf("Found EPICS event id %u\n", fEventId); // secondly get dabc record time expression fUTimeSeconds = (UInt_t) *pdata++; if (fVerbose) printf("Found EPICS time: %s\n", GetUpdateTimeString()); //int numlong = *pdata++; Long64_t* plong = (Long64_t*) pdata; int numlong= *plong++; if (fVerbose) printf("Num long: %d\n", numlong); std::vector fLongRecords; //plong= (Long64_t*) pdata; for (int i = 0; i < numlong; ++i) { Long64_t val = *plong++; if (fVerbose) printf(" Long[%d] = %lld\n", i, val); fLongRecords.emplace_back(val); } // get header with number of double records //int numdub = *pdata++; int numdub = *plong++; if (fVerbose) printf("Num double: %d\n", numdub); std::vector fDoubleRecords; //plong= (Long64_t*) pdata; Double_t* pdouble= (Double_t*) (plong); for (int i = 0; i < numdub; ++i) { #ifdef CBM_EPIX_useDOUBLES Double_t val = *pdouble++; Long64_t valint = val; plong++; // cout << "double("<(GetObject(fullname)); if(!gr) { gr = new TGraph(); gr->SetName(name); gr->SetMarkerStyle(33); TCanvas* c1 = new TCanvas("c1","c1",3); gr->Draw("A");// dummy create axis: delete c1; gr->GetXaxis()->SetTimeDisplay(1); gr->GetXaxis()->SetNdivisions(-503); gr->GetXaxis()->SetTimeFormat("%H:%M:%S"); gr->GetXaxis()->SetTimeOffset(0,"gmt"); AddObject(gr,dir.Data()); } gr->GetXaxis()->SetTimeOffset(0,"gmt"); return gr; } void TEpicsProc::UpdateTimeGraph(TGraph* gr, Double_t value, time_t time) { TDatime offs(1995,1,1,0,0,0); // substract begin of root time from unix epoch TDatime dt(time, kFALSE); Int_t npoints = gr->GetN(); gr->SetPoint(npoints,(dt.Convert() - offs.Convert()),value); } void TEpicsProc::UpdateTrending(TH1* histo, Double_t val, time_t time) { // first test: just use simple binwise trending IncTrending(histo, val, kTRUE); } void TEpicsProc::IncTrending( TH1 * histo, Double_t value, bool forwards ) { if(!histo) return; int bins = histo->GetNbinsX(); //bool forwards=true; int j = forwards ? bins : 0; int dj = forwards ? -1 : +1; for(int i=0;iGetBinContent(j+dj); histo->SetBinContent(j,oldval); } histo->SetBinContent(j+dj,value); } void TEpicsProc::UpdateHist(VariableHist* hst, double val, const char *varname) { if (!varname || !hst) return; hst->fStat->Fill(val); hst->fStat->SetTitle(Form("Statistics of %s at %s", varname, GetUpdateTimeString())); UpdateTrending(hst->fTrend, val, fUTimeSeconds); hst->fTrend->SetTitle(Form("Trending of %s at %s", varname, GetUpdateTimeString())); UpdateTimeGraph(hst->fGraph, val, fUTimeSeconds); hst->fGraph->SetTitle(Form("Timegraph of %s", varname)); }