00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <stdio.h>
00010 #include <sys/time.h>
00011 #include <iostream>
00012 #include <assert.h>
00013 #include <signal.h>
00014
00015 #include "TMidasOnline.h"
00016 #include "TMidasEvent.h"
00017 #include "TMidasFile.h"
00018 #include "XmlOdb.h"
00019 #ifdef HAVE_MIDASSERVER
00020 #include "midasServer.h"
00021 #endif
00022 #ifdef HAVE_LIBNETDIRECTORY
00023 #include "libNetDirectory/netDirectoryServer.h"
00024 #endif
00025 #ifdef HAVE_XMLSERVER
00026 #include "libXmlServer/xmlServer.h"
00027 #endif
00028
00029 #include <TSystem.h>
00030 #include <TROOT.h>
00031 #include <TApplication.h>
00032 #include <TTimer.h>
00033 #include <TFile.h>
00034 #include <TDirectory.h>
00035 #include <TGClient.h>
00036 #include <TGFrame.h>
00037 #include <TFolder.h>
00038
00039 #include "Globals.h"
00040
00041
00042 int gRunNumber = 0;
00043 bool gIsRunning = false;
00044 bool gIsPedestalsRun = false;
00045 bool gIsOffline = false;
00046 int gEventCutoff = 0;
00047
00048 TDirectory* gOnlineHistDir = NULL;
00049 TFile* gOutputFile = NULL;
00050 VirtualOdb* gOdb = NULL;
00051
00052
00053
00054 double GetTimeSec()
00055 {
00056 struct timeval tv;
00057 gettimeofday(&tv,NULL);
00058 return tv.tv_sec + 0.000001*tv.tv_usec;
00059 }
00060
00061 class MyPeriodic : public TTimer
00062 {
00063 public:
00064 typedef void (*TimerHandler)(void);
00065
00066 int fPeriod_msec;
00067 TimerHandler fHandler;
00068 double fLastTime;
00069
00070 MyPeriodic(int period_msec,TimerHandler handler)
00071 {
00072 assert(handler != NULL);
00073 fPeriod_msec = period_msec;
00074 fHandler = handler;
00075 fLastTime = GetTimeSec();
00076 Start(period_msec,kTRUE);
00077 }
00078
00079 Bool_t Notify()
00080 {
00081 double t = GetTimeSec();
00082
00083
00084 if (t - fLastTime >= 0.9*fPeriod_msec*0.001)
00085 {
00086
00087 if (fHandler)
00088 (*fHandler)();
00089
00090 fLastTime = t;
00091 }
00092
00093 Reset();
00094 return kTRUE;
00095 }
00096
00097 ~MyPeriodic()
00098 {
00099 TurnOff();
00100 }
00101 };
00102
00103
00104 void startRun(int transition,int run,int time)
00105 {
00106 gIsRunning = true;
00107 gRunNumber = run;
00108 gIsPedestalsRun = gOdb->odbReadBool("/experiment/edit on start/Pedestals run");
00109 printf("Begin run: %d, pedestal run: %d\n", gRunNumber, gIsPedestalsRun);
00110
00111 if(gOutputFile!=NULL)
00112 {
00113 gOutputFile->Write();
00114 gOutputFile->Close();
00115 gOutputFile=NULL;
00116 }
00117
00118 char filename[1024];
00119 sprintf(filename, "output%05d.root", run);
00120 gOutputFile = new TFile(filename, "RECREATE");
00121
00122
00123
00124
00125 assert(gOutputFile);
00126 assert(gOutputFile->IsOpen());
00127
00128
00129
00130 #ifdef HAVE_LIBNETDIRECTORY
00131 NetDirectoryExport(gOutputFile, "outputFile");
00132 #endif
00133 }
00134
00135 void endRun(int transition,int run,int time)
00136 {
00137 gIsRunning = false;
00138 gRunNumber = run;
00139
00140 #ifdef HAVE_MIDASSERVER
00141 if (gManaHistosFolder)
00142 gManaHistosFolder->Clear();
00143 #endif
00144
00145 if (gOutputFile)
00146 {
00147 gOutputFile->Write();
00148 gOutputFile->Close();
00149 gOutputFile = NULL;
00150 }
00151
00152 printf("End of run %d\n",run);
00153 }
00154
00155 #include <TH1D.h>
00156
00157 void HandleSample(int ichan, void* ptr, int wsize)
00158 {
00159 uint16_t *samples = (uint16_t*) ptr;
00160 int numSamples = wsize;
00161
00162 if (numSamples != 512)
00163 return;
00164
00165 char name[256];
00166 sprintf(name, "channel%d", ichan);
00167
00168 if (gOutputFile)
00169 gOutputFile->cd();
00170
00171 TH1D* samplePlot = (TH1D*)gDirectory->Get(name);
00172
00173 if (!samplePlot)
00174 {
00175 printf("Create [%s]\n", name);
00176 samplePlot = new TH1D(name, name, numSamples, 0, numSamples);
00177
00178 #ifdef HAVE_MIDASSERVER
00179 if (gManaHistosFolder)
00180 gManaHistosFolder->Add(samplePlot);
00181 #endif
00182 }
00183
00184 for(int ti=0; ti<numSamples; ti++)
00185 samplePlot->SetBinContent(ti, samples[ti]);
00186 }
00187
00188
00189 void HandleMidasEvent(TMidasEvent& event)
00190 {
00191 int eventId = event.GetEventId();
00192
00193 if (false&&(eventId == 1))
00194 {
00195 void *ptr;
00196 int size = event.LocateBank(NULL, "CHA3", &ptr);
00197 if (ptr)
00198 HandleSample(3, ptr, size);
00199 }
00200 if (false&&(eventId == 1)&&(gIsRunning==true)&&(gIsPedestalsRun==false))
00201 {
00202
00203
00204
00205
00206
00207 }
00208 else if (false&&(eventId == 2)&&(gIsRunning==true))
00209 {
00210
00211
00212
00213
00214
00215 }
00216 else if (false&&(eventId==5)&&(gIsRunning==true)&&(gIsPedestalsRun==false))
00217 {
00218
00219
00220
00221
00222
00223
00224 }
00225 else
00226 {
00227
00228 event.Print();
00229 }
00230 }
00231
00232 void eventHandler(const void*pheader,const void*pdata,int size)
00233 {
00234 TMidasEvent event;
00235 memcpy(event.GetEventHeader(), pheader, sizeof(TMidas_EVENT_HEADER));
00236 event.SetData(size, (char*)pdata);
00237 event.SetBankList();
00238 HandleMidasEvent(event);
00239 }
00240
00241 int ProcessMidasFile(TApplication*app,const char*fname)
00242 {
00243 TMidasFile f;
00244 bool tryOpen = f.Open(fname);
00245
00246 if (!tryOpen)
00247 {
00248 printf("Cannot open input file \"%s\"\n",fname);
00249 return -1;
00250 }
00251
00252 int i=0;
00253 while (1)
00254 {
00255 TMidasEvent event;
00256 if (!f.Read(&event))
00257 break;
00258
00259 int eventId = event.GetEventId();
00260
00261
00262 if ((eventId & 0xFFFF) == 0x8000)
00263 {
00264
00265 event.Print();
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 if (gOdb)
00276 delete gOdb;
00277 gOdb = new XmlOdb(event.GetData(),event.GetDataSize());
00278
00279 startRun(0,event.GetSerialNumber(),0);
00280 }
00281 else if ((eventId & 0xFFFF) == 0x8001)
00282 {
00283
00284 event.Print();
00285 }
00286 else if ((eventId & 0xFFFF) == 0x8002)
00287 {
00288
00289 event.Print();
00290 printf("Log message: %s\n", event.GetData());
00291 }
00292 else
00293 {
00294 event.SetBankList();
00295
00296 HandleMidasEvent(event);
00297 }
00298
00299 if((i%500)==0)
00300 {
00301
00302 printf("Processing event %d\n",i);
00303
00304
00305 }
00306
00307 i++;
00308 if ((gEventCutoff!=0)&&(i>=gEventCutoff))
00309 {
00310 printf("Reached event %d, exiting loop.\n",i);
00311 break;
00312 }
00313 }
00314
00315 f.Close();
00316
00317 endRun(0,gRunNumber,0);
00318
00319
00320
00321
00322 return 0;
00323 }
00324
00325 #ifdef HAVE_MIDAS
00326
00327 void MidasPollHandler()
00328 {
00329 if (!(TMidasOnline::instance()->poll(0)))
00330 gSystem->ExitLoop();
00331 }
00332
00333 int ProcessMidasOnline(TApplication*app, const char* hostname, const char* exptname)
00334 {
00335 TMidasOnline *midas = TMidasOnline::instance();
00336
00337 int err = midas->connect(hostname, exptname, "rootana");
00338 if (err != 0)
00339 {
00340 fprintf(stderr,"Cannot connect to MIDAS, error %d\n", err);
00341 return -1;
00342 }
00343
00344 gOdb = midas;
00345
00346 midas->setTransitionHandlers(startRun,endRun,NULL,NULL);
00347 midas->registerTransitions();
00348
00349
00350
00351 midas->setEventHandler(eventHandler);
00352 midas->eventRequest("SYSTEM",-1,-1,(1<<1));
00353
00354
00355
00356 gRunNumber = gOdb->odbReadInt("/runinfo/Run number");
00357
00358 if ((gOdb->odbReadInt("/runinfo/State") == 3))
00359 startRun(0,gRunNumber,0);
00360
00361 printf("Startup: run %d, is running: %d, is pedestals run: %d\n",gRunNumber,gIsRunning,gIsPedestalsRun);
00362
00363 MyPeriodic tm(100,MidasPollHandler);
00364
00365
00366
00367
00368
00369
00370
00371 app->Run(kTRUE);
00372
00373
00374 midas->disconnect();
00375
00376 return 0;
00377 }
00378
00379 #endif
00380
00381 #include <TGMenu.h>
00382
00383 class MainWindow: public TGMainFrame {
00384
00385 private:
00386 TGPopupMenu* menuFile;
00387
00388 TGMenuBar* menuBar;
00389 TGLayoutHints* menuBarLayout;
00390 TGLayoutHints* menuBarItemLayout;
00391
00392 public:
00393 MainWindow(const TGWindow*w,int s1,int s2);
00394 virtual ~MainWindow();
00395 virtual void CloseWindow();
00396
00397 Bool_t ProcessMessage(Long_t msg, Long_t parm1, Long_t parm2);
00398 };
00399
00400 #define M_FILE_EXIT 0
00401
00402 Bool_t MainWindow::ProcessMessage(Long_t msg, Long_t parm1, Long_t parm2)
00403 {
00404
00405 switch (GET_MSG(msg))
00406 {
00407 default:
00408 break;
00409 case kC_COMMAND:
00410 switch (GET_SUBMSG(msg))
00411 {
00412 default:
00413 break;
00414 case kCM_MENU:
00415 switch (parm1)
00416 {
00417 default:
00418 break;
00419 case M_FILE_EXIT:
00420 if(gIsRunning)
00421 endRun(0,gRunNumber,0);
00422 gSystem->ExitLoop();
00423 break;
00424 }
00425 break;
00426 }
00427 break;
00428 }
00429
00430 return kTRUE;
00431 }
00432
00433 MainWindow::MainWindow(const TGWindow*w,int s1,int s2)
00434 : TGMainFrame(w,s1,s2)
00435 {
00436
00437
00438 SetWindowName("ROOT Analyzer Control");
00439
00440
00441 menuFile = new TGPopupMenu(gClient->GetRoot());
00442 menuFile->AddEntry("Exit", M_FILE_EXIT);
00443
00444 menuBarItemLayout = new TGLayoutHints(kLHintsTop|kLHintsLeft, 0, 4, 0, 0);
00445
00446 menuFile->Associate(this);
00447
00448
00449 menuBar = new TGMenuBar(this, 1, 1, kRaisedFrame);
00450 menuBar->AddPopup("&File", menuFile, menuBarItemLayout);
00451
00452 menuBar->Layout();
00453
00454 menuBarLayout = new TGLayoutHints(kLHintsTop|kLHintsLeft|kLHintsExpandX);
00455 AddFrame(menuBar,menuBarLayout);
00456
00457 MapSubwindows();
00458 Layout();
00459 MapWindow();
00460 }
00461
00462 MainWindow::~MainWindow()
00463 {
00464 delete menuFile;
00465
00466 delete menuBar;
00467 delete menuBarLayout;
00468 delete menuBarItemLayout;
00469 }
00470
00471 void MainWindow::CloseWindow()
00472 {
00473 if(gIsRunning)
00474 endRun(0,gRunNumber,0);
00475 gSystem->ExitLoop();
00476 }
00477
00478 static bool gEnableShowMem = false;
00479
00480 int ShowMem(const char* label)
00481 {
00482 if (!gEnableShowMem)
00483 return 0;
00484
00485 FILE* fp = fopen("/proc/self/statm","r");
00486 if (!fp)
00487 return 0;
00488
00489 int mem = 0;
00490 fscanf(fp,"%d",&mem);
00491 fclose(fp);
00492
00493 if (label)
00494 printf("memory at %s is %d\n", label, mem);
00495
00496 return mem;
00497 }
00498
00499 void help()
00500 {
00501 printf("\nUsage:\n");
00502 printf("\n./analyzer.exe [-h] [-Hhostname] [-Eexptname] [-eMaxEvents] [-P9091] [-p9090] [-m] [-g] [file1 file2 ...]\n");
00503 printf("\n");
00504 printf("\t-h: print this help message\n");
00505 printf("\t-T: test mode - start and serve a test histogram\n");
00506 printf("\t-Hhostname: connect to MIDAS experiment on given host\n");
00507 printf("\t-Eexptname: connect to this MIDAS experiment\n");
00508 printf("\t-P: Start the TNetDirectory server on specified tcp port (for use with roody -Plocalhost:9091)\n");
00509 printf("\t-p: Start the old midas histogram server on specified tcp port (for use with roody -Hlocalhost:9090)\n");
00510 printf("\t-e: Number of events to read from input data files\n");
00511 printf("\t-m: Enable memory leak debugging\n");
00512 printf("\t-g: Enable graphics display when processing data files\n");
00513 printf("\n");
00514 printf("Example1: analyze online data: ./analyzer.exe -P9091\n");
00515 printf("Example2: analyze existing data: ./analyzer.exe /data/alpha/current/run00500.mid\n");
00516 exit(1);
00517 }
00518
00519
00520
00521 int main(int argc, char *argv[])
00522 {
00523 setbuf(stdout,NULL);
00524 setbuf(stderr,NULL);
00525
00526 signal(SIGILL, SIG_DFL);
00527 signal(SIGBUS, SIG_DFL);
00528 signal(SIGSEGV, SIG_DFL);
00529 signal(SIGPIPE, SIG_DFL);
00530
00531 std::vector<std::string> args;
00532 for (int i=0; i<argc; i++)
00533 {
00534 if (strcmp(argv[i],"-h")==0)
00535 help();
00536 args.push_back(argv[i]);
00537 }
00538
00539 TApplication *app = new TApplication("rootana", &argc, argv);
00540
00541 if(gROOT->IsBatch()) {
00542 printf("Cannot run in batch mode\n");
00543 return 1;
00544 }
00545
00546 bool forceEnableGraphics = false;
00547 bool testMode = false;
00548 int oldTcpPort = 0;
00549 int tcpPort = 0;
00550 int xmlTcpPort = 0;
00551 const char* hostname = NULL;
00552 const char* exptname = NULL;
00553
00554 for (unsigned int i=1; i<args.size(); i++)
00555 {
00556 const char* arg = args[i].c_str();
00557
00558
00559 if (strncmp(arg,"-e",2)==0)
00560 gEventCutoff = atoi(arg+2);
00561 else if (strncmp(arg,"-m",2)==0)
00562 gEnableShowMem = true;
00563 else if (strncmp(arg,"-p",2)==0)
00564 oldTcpPort = atoi(arg+2);
00565 else if (strncmp(arg,"-P",2)==0)
00566 tcpPort = atoi(arg+2);
00567 else if (strncmp(arg,"-X",2)==0)
00568 xmlTcpPort = atoi(arg+2);
00569 else if (strcmp(arg,"-T")==0)
00570 testMode = true;
00571 else if (strcmp(arg,"-g")==0)
00572 forceEnableGraphics = true;
00573 else if (strncmp(arg,"-H",2)==0)
00574 hostname = strdup(arg+2);
00575 else if (strncmp(arg,"-E",2)==0)
00576 exptname = strdup(arg+2);
00577 else if (strcmp(arg,"-h")==0)
00578 help();
00579 else if (arg[0] == '-')
00580 help();
00581 }
00582
00583 MainWindow mainWindow(gClient->GetRoot(), 200, 300);
00584
00585 gROOT->cd();
00586 gOnlineHistDir = new TDirectory("rootana", "rootana online plots");
00587
00588 #ifdef HAVE_MIDASSERVER
00589 if (oldTcpPort)
00590 StartMidasServer(oldTcpPort);
00591 #else
00592 if (oldTcpPort)
00593 fprintf(stderr,"ERROR: No support for the old midas server!\n");
00594 #endif
00595 #ifdef HAVE_LIBNETDIRECTORY
00596 if (tcpPort)
00597 StartNetDirectoryServer(tcpPort, gOnlineHistDir);
00598 #else
00599 if (tcpPort)
00600 fprintf(stderr,"ERROR: No support for the TNetDirectory server!\n");
00601 #endif
00602 #ifdef HAVE_XMLSERVER
00603 XmlServer* xmlServer = NULL;
00604 if (xmlTcpPort)
00605 {
00606 xmlServer = new XmlServer();
00607 xmlServer->SetVerbose(true);
00608 xmlServer->Start(xmlTcpPort);
00609 xmlServer->Export(gOnlineHistDir, gOnlineHistDir->GetName());
00610 }
00611 #else
00612 if (xmlTcpPort)
00613 fprintf(stderr,"ERROR: No support for the XML Server!\n");
00614 #endif
00615
00616 gIsOffline = false;
00617
00618 for (unsigned int i=1; i<args.size(); i++)
00619 {
00620 const char* arg = args[i].c_str();
00621
00622 if (arg[0] != '-')
00623 {
00624 gIsOffline = true;
00625
00626
00627 ProcessMidasFile(app,arg);
00628 }
00629 }
00630
00631 if (testMode)
00632 {
00633 gOnlineHistDir->cd();
00634 TH1D* hh = new TH1D("test", "test", 100, 0, 100);
00635 hh->Fill(1);
00636 hh->Fill(10);
00637 hh->Fill(50);
00638
00639 app->Run(kTRUE);
00640 return 0;
00641 }
00642
00643
00644
00645 if (gIsOffline)
00646 return 0;
00647
00648 gIsOffline = false;
00649
00650 #ifdef HAVE_MIDAS
00651 ProcessMidasOnline(app, hostname, exptname);
00652 #endif
00653
00654 return 0;
00655 }
00656
00657