00001
00002
00003
00004 #include "TRootanaEventLoop.hxx"
00005 #include "XmlOdb.h"
00006 #ifdef OLD_SERVER
00007 #include "midasServer.h"
00008 #endif
00009 #ifdef HAVE_LIBNETDIRECTORY
00010 #include "libNetDirectory/netDirectoryServer.h"
00011 #endif
00012 #include "TPeriodicClass.hxx"
00013 #include "MainWindow.hxx"
00014
00015
00016 #include <TSystem.h>
00017 #include <TROOT.h>
00018 #include <TH1D.h>
00019
00020 #include <stdio.h>
00021 #include <sys/time.h>
00022 #include <iostream>
00023 #include <assert.h>
00024 #include <signal.h>
00025
00026 #include "sys/time.h"
00027
00028 struct timeval raLastTime;
00029 int raTotalEventsProcessed = 0;
00030 void PrintCurrentStats(){
00031
00032 if((raTotalEventsProcessed%500)==0){
00033 if(raTotalEventsProcessed==0){
00034 gettimeofday(&raLastTime, NULL);
00035 printf("Processed %d events.\n",raTotalEventsProcessed);
00036 }else{
00037
00038 struct timeval nowTime;
00039 gettimeofday(&nowTime, NULL);
00040
00041 double dtime = nowTime.tv_sec - raLastTime.tv_sec + (nowTime.tv_usec - raLastTime.tv_usec)/1000000.0;
00042 double rate = 0;
00043 if (time !=0)
00044 rate = 500.0/(dtime);
00045 printf("Processed %d events. Analysis rate = %f events/seconds. \n",raTotalEventsProcessed,rate);
00046 gettimeofday(&raLastTime, NULL);
00047 }
00048 }
00049
00050 raTotalEventsProcessed++;
00051
00052 }
00053
00054
00055
00056
00057 TRootanaEventLoop* TRootanaEventLoop::fTRootanaEventLoop = NULL;
00058
00059 TRootanaEventLoop& TRootanaEventLoop::Get(void) {
00060
00061 if(!fTRootanaEventLoop){
00062 std::cerr << "Singleton Not Instantiated! "
00063 << " Need to call something like SomeClass::CreateSingleton<SomeClass>(); Exiting!"
00064 <<std::endl; exit(0);
00065 }
00066 return *fTRootanaEventLoop;
00067 }
00068
00069
00070
00071 TRootanaEventLoop::TRootanaEventLoop (){
00072
00073 fOutputFile = 0;
00074 fOutputFilename = std::string("output");
00075 fDisableRootOutput = false;
00076 fODB = 0;
00077 fOnlineHistDir = 0;
00078 fMaxEvents = 0;
00079 fCurrentRunNumber = 0;
00080 fIsOffline = true;
00081
00082 fCreateMainWindow = true;
00083 fSuppressTimestampWarnings = false;
00084
00085 fBufferName = std::string("SYSTEM");
00086 fOnlineName = std::string("rootana");
00087
00088 fDataContainer = new TDataContainer();
00089
00090
00091 char **argv2 = NULL;
00092 fApp = new TApplication("rootana", 0, argv2);
00093
00094 }
00095
00096 TRootanaEventLoop::~TRootanaEventLoop (){
00097
00098 if(fODB) delete fODB;
00099 CloseRootFile();
00100
00101 }
00102
00103
00104 void TRootanaEventLoop::Initialize(void){};
00105
00106 void TRootanaEventLoop::BeginRun(int transition,int run,int time){};
00107
00108 void TRootanaEventLoop::EndRun(int transition,int run,int time){};
00109
00110 void TRootanaEventLoop::Finalize(){};
00111
00112 void TRootanaEventLoop::Usage(void){};
00113 void TRootanaEventLoop::UsageRAD(void){};
00114
00115
00116 bool TRootanaEventLoop::CheckOption(std::string option){return false;}
00117 bool TRootanaEventLoop::CheckOptionRAD(std::string option){return false;}
00118
00119
00120 bool TRootanaEventLoop::CheckEventID(int eventId){
00121
00122
00123 if(fProcessEventIDs.size()==0) return true;
00124
00125
00126 for(unsigned int i = 0; i < fProcessEventIDs.size(); i++){
00127 if(fProcessEventIDs[i] == (eventId & 0xFFFF))
00128 return true;
00129 }
00130
00131 return false;
00132 }
00133
00134 void TRootanaEventLoop::PrintHelp(){
00135
00136 printf("\nUsage:\n");
00137 printf("\n./analyzer.exe [-h] [-Hhostname] [-Eexptname] [-eMaxEvents] [-P9091] [-p9090] [-m] [-g] [file1 file2 ...]\n");
00138 printf("\n");
00139 printf("\t-h: print this help message\n");
00140 printf("\t-T: test mode - start and serve a test histogram\n");
00141 printf("\t-Hhostname: connect to MIDAS experiment on given host\n");
00142 printf("\t-Eexptname: connect to this MIDAS experiment\n");
00143 printf("\t-bbuffer: connect to this MIDAS buffer\n");
00144 printf("\t-P: Start the TNetDirectory server on specified tcp port (for use with roody -Plocalhost:9091)\n");
00145 printf("\t-p: Start the old midas histogram server on specified tcp port (for use with roody -Hlocalhost:9090)\n");
00146 printf("\t-eXXX: Number of events XXX to read from input data files\n");
00147
00148 printf("\t-g: Enable graphics display when processing data files\n");
00149 UsageRAD();
00150 Usage();
00151 printf("\n");
00152 printf("Example1: analyze online data: ./analyzer.exe -P9091\n");
00153 printf("Example2: analyze existing data: ./analyzer.exe /data/alpha/current/run00500.mid\n");
00154
00155 exit(1);
00156 }
00157
00158
00159 int TRootanaEventLoop::ExecuteLoop(int argc, char *argv[]){
00160
00161 setbuf(stdout,NULL);
00162 setbuf(stderr,NULL);
00163
00164 signal(SIGILL, SIG_DFL);
00165 signal(SIGBUS, SIG_DFL);
00166 signal(SIGSEGV, SIG_DFL);
00167
00168 std::vector<std::string> args;
00169 for (int i=0; i<argc; i++)
00170 {
00171 if (strcmp(argv[i],"-h")==0)
00172 PrintHelp();
00173 args.push_back(argv[i]);
00174 }
00175
00176
00177 if(gROOT->IsBatch()) {
00178 printf("Cannot run in batch mode\n");
00179 return 1;
00180 }
00181
00182 bool forceEnableGraphics = false;
00183 bool testMode = false;
00184 int tcpPort = 0;
00185 const char* hostname = NULL;
00186 const char* exptname = NULL;
00187
00188 for (unsigned int i=1; i<args.size(); i++)
00189 {
00190 const char* arg = args[i].c_str();
00191
00192
00193 if (strncmp(arg,"-e",2)==0)
00194 fMaxEvents = atoi(arg+2);
00195 else if (strncmp(arg,"-m",2)==0)
00196 ;
00197 else if (strncmp(arg,"-P",2)==0)
00198 tcpPort = atoi(arg+2);
00199 else if (strcmp(arg,"-T")==0)
00200 testMode = true;
00201 else if (strcmp(arg,"-g")==0)
00202 forceEnableGraphics = true;
00203 else if (strncmp(arg,"-H",2)==0)
00204 hostname = strdup(arg+2);
00205 else if (strncmp(arg,"-E",2)==0)
00206 exptname = strdup(arg+2);
00207 else if (strncmp(arg,"-b",2)==0){
00208 fBufferName = std::string(arg+2);
00209 }else if (strcmp(arg,"-h")==0)
00210 PrintHelp();
00211 else if(arg[0] == '-')
00212 if(!CheckOptionRAD(args[i]))
00213 if(!CheckOption(args[i]))
00214 PrintHelp();
00215 }
00216
00217
00218
00219 fIsOffline = false;
00220 for (unsigned int i=1; i<args.size(); i++){
00221 const char* arg = args[i].c_str();
00222 if (arg[0] != '-')
00223 {
00224 fIsOffline = true;
00225 }
00226 }
00227
00228
00229 MainWindow *mainWindow=0;
00230 if(fCreateMainWindow){
00231 mainWindow = new MainWindow(gClient->GetRoot(), 200, 300);
00232 }
00233
00234 gROOT->cd();
00235 fOnlineHistDir = new TDirectory("rootana", "rootana online plots");
00236
00237 #ifdef HAVE_LIBNETDIRECTORY
00238 if (tcpPort)
00239 StartNetDirectoryServer(tcpPort, fOnlineHistDir);
00240 #else
00241 if (tcpPort)
00242 fprintf(stderr,"ERROR: No support for the TNetDirectory server!\n");
00243 #endif
00244
00245
00246 Initialize();
00247
00248 for (unsigned int i=1; i<args.size(); i++){
00249 const char* arg = args[i].c_str();
00250 if (arg[0] != '-')
00251 {
00252 ProcessMidasFile(fApp,arg);
00253 }
00254 }
00255
00256 if (testMode){
00257 std::cout << "Entering test mode." << std::endl;
00258 fOnlineHistDir->cd();
00259 TH1D* hh = new TH1D("test", "test", 100, 0, 100);
00260 hh->Fill(1);
00261 hh->Fill(10);
00262 hh->Fill(50);
00263
00264 fApp->Run(kTRUE);
00265 if(fCreateMainWindow) delete mainWindow;
00266 return 0;
00267 }
00268
00269
00270
00271 if (fIsOffline){
00272 if(fCreateMainWindow) delete mainWindow;
00273 return 0;
00274 }
00275
00276 #ifdef HAVE_MIDAS
00277 ProcessMidasOnline(fApp, hostname, exptname);;
00278 #endif
00279
00280 if(fCreateMainWindow) delete mainWindow;
00281
00282 Finalize();
00283
00284 return 0;
00285
00286 }
00287
00288
00289
00290 int TRootanaEventLoop::ProcessMidasFile(TApplication*app,const char*fname)
00291 {
00292 TMidasFile f;
00293 bool tryOpen = f.Open(fname);
00294
00295 if (!tryOpen){
00296 printf("Cannot open input file \"%s\"\n",fname);
00297 return -1;
00298 }
00299
00300
00301 int i=0;
00302 while (1)
00303 {
00304 TMidasEvent event;
00305 if (!f.Read(&event))
00306 break;
00307
00308
00309 int eventId = event.GetEventId();
00310
00311
00312
00313 if ((eventId & 0xFFFF) == 0x8000){
00314
00315 event.Print();
00316
00317
00318 if (fODB) delete fODB;
00319 fODB = new XmlOdb(event.GetData(),event.GetDataSize());
00320
00321 fCurrentRunNumber = event.GetSerialNumber();
00322 OpenRootFile(fCurrentRunNumber);
00323 BeginRun(0,event.GetSerialNumber(),0);
00324
00325 } else if ((eventId & 0xFFFF) == 0x8001){
00326
00327 event.Print();
00328
00329
00330
00331 } else if ((eventId & 0xFFFF) == 0x8002){
00332
00333 event.Print();
00334 printf("Log message: %s\n", event.GetData());
00335
00336 }else if(CheckEventID(eventId)){
00337
00338
00339 event.SetBankList();
00340
00341
00342 fDataContainer->SetMidasEventPointer(event);
00343
00344
00345 if(PreFilter(*fDataContainer))
00346 ProcessMidasEvent(*fDataContainer);
00347
00348
00349 fDataContainer->CleanupEvent();
00350
00351 }
00352
00353 PrintCurrentStats();
00354
00355
00356 i++;
00357 if ((fMaxEvents!=0)&&(i>=fMaxEvents)){
00358 printf("Reached event %d, exiting loop.\n",i);
00359 break;
00360 }
00361 }
00362
00363 f.Close();
00364
00365 EndRun(0,fCurrentRunNumber,0);
00366 CloseRootFile();
00367
00368
00369
00370
00371 return 0;
00372 }
00373
00374
00375 void TRootanaEventLoop::OpenRootFile(int run){
00376
00377 if(fDisableRootOutput) return;
00378
00379 if(fOutputFile) {
00380 fOutputFile->Write();
00381 fOutputFile->Close();
00382 fOutputFile=0;
00383 }
00384
00385 char filename[1024];
00386 sprintf(filename, "%s%05d.root",fOutputFilename.c_str(), run);
00387 fOutputFile = new TFile(filename,"RECREATE");
00388 std::cout << "Opened output file with name : " << filename << std::endl;
00389
00390
00391 #ifdef HAVE_LIBNETDIRECTORY
00392 NetDirectoryExport(fOutputFile, "outputFile");
00393 #endif
00394 }
00395
00396
00397 void TRootanaEventLoop::CloseRootFile(){
00398
00399 if(fOutputFile) {
00400 std::cout << "Closing ROOT file " << std::endl;
00401 fOutputFile->Write();
00402 fOutputFile->Close();
00403 fOutputFile=0;
00404 }
00405
00406 }
00407
00408
00409
00410
00411
00412
00413
00414
00415 #ifdef HAVE_MIDAS
00416
00417
00418
00419 static bool onlineEventLock = false;
00420
00421
00422
00423 int numberConsSkipped=0;
00424 double nextWarn = 1.0;
00425
00426
00427 int numberOldTimestamps=0;
00428 double nextWarnTimestamps = 1.0;
00429
00430
00431
00432
00433 void onlineEventHandler(const void*pheader,const void*pdata,int size)
00434 {
00435
00436
00437
00438
00439 if(onlineEventLock) return;
00440 onlineEventLock = true;
00441
00442
00443
00444
00445
00446
00447 if(TRootanaEventLoop::Get().IsRootOutputEnabled()
00448 && !TRootanaEventLoop::Get().IsRootFileValid()){
00449
00450 numberConsSkipped++;
00451 if(numberConsSkipped >= nextWarn){
00452 printf("onlineEventHandler Warning: Output ROOT file is not validly open, so can't fill histograms. Have skipped %i events now.\n",
00453 numberConsSkipped);
00454 nextWarn *= 3.16227;
00455 }
00456
00457 onlineEventLock = false;
00458 return;
00459 }
00460 numberConsSkipped = 0;
00461 nextWarn = 1.0;
00462
00463
00464 TMidasEvent event;
00465 memcpy(event.GetEventHeader(), pheader, sizeof(TMidas_EVENT_HEADER));
00466 event.SetData(size, (char*)pdata);
00467 event.SetBankList();
00468
00469
00470 if(!TRootanaEventLoop::Get().CheckEventID(event.GetEventId())){
00471 onlineEventLock = false;
00472 return;
00473 }
00474
00475
00476 TRootanaEventLoop::Get().GetDataContainer()->SetMidasEventPointer(event);
00477
00478
00479 if(TRootanaEventLoop::Get().PreFilter(*TRootanaEventLoop::Get().GetDataContainer())){
00480 TRootanaEventLoop::Get().ProcessMidasEvent(*TRootanaEventLoop::Get().GetDataContainer());
00481 }
00482
00483 PrintCurrentStats();
00484
00485
00486 TRootanaEventLoop::Get().GetDataContainer()->CleanupEvent();
00487
00488
00489
00490 if(!TRootanaEventLoop::Get().GetSuppressTimestampWarnings()){
00491 struct timeval now;
00492 gettimeofday(&now, NULL);
00493 if(event.GetTimeStamp() < now.tv_sec - 10){
00494 numberOldTimestamps++;
00495 if(numberOldTimestamps >= nextWarnTimestamps){
00496 printf("onlineEventHandler Warning: the time for this bank (%i) is more than 10 sec older \nthan current time (%i). Has happenned %i times now.",
00497 event.GetTimeStamp(),(int) now.tv_sec,numberOldTimestamps);
00498 printf("Either the analyzer is falling behind the data taking \n(try modifying the fraction of events plotted) or times on different computers are not synchronized.\n");
00499
00500 int buffer_level = TMidasOnline::instance()->getBufferLevel();
00501 int buffer_size = TMidasOnline::instance()->getBufferSize();
00502 printf("Buffer level = %i bytes out of %i bytes maximum \n\n",buffer_level,buffer_size);
00503 nextWarnTimestamps *= 3.16227;
00504 }
00505 }
00506 }
00507
00508 onlineEventLock = false;
00509 }
00510
00511
00512 void onlineBeginRunHandler(int transition,int run,int time)
00513 {
00514 TRootanaEventLoop::Get().OpenRootFile(run);
00515 TRootanaEventLoop::Get().SetCurrentRunNumber(run);
00516 TRootanaEventLoop::Get().BeginRun(transition,run,time);
00517 }
00518
00519 void onlineEndRunHandler(int transition,int run,int time)
00520 {
00521 TRootanaEventLoop::Get().SetCurrentRunNumber(run);
00522 TRootanaEventLoop::Get().EndRun(transition,run,time);
00523 TRootanaEventLoop::Get().CloseRootFile();
00524 }
00525
00526
00527 void MidasPollHandlerLocal()
00528 {
00529
00530 if (!(TMidasOnline::instance()->poll(0)))
00531 gSystem->ExitLoop();
00532 }
00533
00534 int TRootanaEventLoop::ProcessMidasOnline(TApplication*app, const char* hostname, const char* exptname)
00535 {
00536 TMidasOnline *midas = TMidasOnline::instance();
00537
00538 int err = midas->connect(hostname, exptname, fOnlineName.c_str());
00539 if (err != 0)
00540 {
00541 fprintf(stderr,"Cannot connect to MIDAS, error %d\n", err);
00542 return -1;
00543 }
00544
00545 fODB = midas;
00546
00547
00548
00549 fCurrentRunNumber = fODB->odbReadInt("/runinfo/Run number");
00550
00551
00552
00553 OpenRootFile(fCurrentRunNumber);
00554 BeginRun(0,fCurrentRunNumber,0);
00555
00556
00557 midas->setTransitionHandlers(onlineBeginRunHandler,onlineEndRunHandler,NULL,NULL);
00558 midas->registerTransitions();
00559
00560
00561 midas->setEventHandler(onlineEventHandler);
00562
00563 midas->eventRequest(fBufferName.c_str(),-1,-1,(1<<1));
00564
00565
00566
00567
00568 TPeriodicClass tm(100,MidasPollHandlerLocal);
00569
00570
00571
00572
00573 app->Run(kTRUE);
00574
00575
00576 EndRun(0,fCurrentRunNumber,0);
00577 CloseRootFile();
00578
00579
00580 midas->disconnect();
00581
00582 return 0;
00583 }
00584
00585 #endif