00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 #ifdef HAVE_HBOOK
00408 #include "THbookFile.h"
00409 #endif
00410 #include "Roody.h"
00411 #include "RoodyXML.h"
00412
00413 #include "TAxisLimitsDialog.h"
00414
00415 ClassImp(Roody);
00416
00417 TPeakFindPanel *Roody::fgPeakFindPanel = 0;
00418
00419 Roody::Roody() : TGMainFrame( 0, 0, 0 )
00420 {}
00421
00422 Roody::Roody( const TGWindow *p, UInt_t w, UInt_t h,
00423 char **filenames, int fileCount,
00424 char const *hostname, char const *xmlFile )
00425 : TGMainFrame( p, w, h ),
00426 fParentDir( new TDirectory("parent","The Parent Directory") ),
00427 fFileList( new TList() ),
00428 fHistList( new TList() ),
00429 fTreeList( new TList() )
00430 {
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 fSock = 0;
00442 fHistNames = 0;
00443 fPopupMenu = 0;
00444 fAddToGroupPopup = 0;
00445 fOpeningFile = false;
00446
00447 fCurrentFile = 0;
00448 #ifdef HAVE_HBOOK
00449 fCurrentHbook = 0;
00450 #endif
00451 fSaveFile = 0;
00452
00453 fCanvasCount = 0;
00454 fZoomCanvas = 0;
00455 fCurrentCanvas = 0;
00456
00457 fFileList->SetOwner();
00458 fHistList->SetOwner();
00459 fTreeList->SetOwner();
00460
00461 SetWindowName("Roody");
00462
00463 #if 0
00464 gStyle->SetPalette( 1 );
00465
00466 gStyle->SetTitleTextColor( kBlue );
00467 gStyle->SetStatTextColor( kBlue );
00468 gStyle->SetTitleBorderSize( 0 );
00469 gStyle->SetStatBorderSize( 0 );
00470
00471 gStyle->SetFuncColor( kBlue );
00472 gStyle->SetOptFit( 1111 );
00473 gStyle->SetOptStat( 1111001 );
00474 #endif
00475
00476 LayoutGUI();
00477 AddPeakFind();
00478 AddAxisLimits();
00479 AddSetCut();
00480 AddZoomOption();
00481
00482 Resize( GetDefaultSize() );
00483 MapSubwindows();
00484 Layout();
00485 MapWindow();
00486 fStatusBar->SetText("Welcome to Roody");
00487
00488 fZoneRows = 1;
00489 fZoneColumns = 1;
00490 fUpdateTimerSec = 0;
00491 fOnlineAborted = kFALSE;
00492 fUpdateTimer = new TTimer(0,kTRUE);
00493
00494 if( xmlFile )RestoreFile( xmlFile );
00495 else
00496 {
00497 FILE *fp = fopen("default.xml","r");
00498 if( fp )
00499 {
00500 fclose( fp );
00501 RestoreFile( "default.xml" );
00502 }
00503 }
00504 if( filenames!=0 && fileCount>0 )
00505 {
00506 for( int i=0; i<fileCount; ++i )
00507 {
00508 if( TString(filenames[i]).Contains(".root") )OpenRootFile( filenames[i] );
00509 #ifdef HAVE_HBOOK
00510 else if( TString(filenames[i]).Contains(".hbook") )OpenHbookFile( filenames[i] );
00511 #endif
00512 }
00513 }
00514 if( hostname )ConnectServer( hostname );
00515
00516 TQObject::Connect( fUpdateTimer,"Timeout()","Roody",this,"UpdateHistograms()" );
00517 StartOnlineTimer();
00518
00519 fParentDir->cd();
00520 }
00521
00522 void Roody::RestoreFile( char const *xmlFilename )
00523 {
00524 RoodyXML xml;
00525 if( !xml.OpenFileForRead(xmlFilename) )
00526 {
00527 TString s("Failed to open XML file: ");
00528 s += xmlFilename;
00529 fStatusBar->SetText( s );
00530 new TGMsgBox( gClient->GetRoot(), this, "Error", s.Data(), kMBIconExclamation, 0, NULL );
00531 return;
00532 }
00533
00534 if( xml.GetOnlineNode() )
00535 {
00536
00537 if( !fSock )ConnectServer( xml.GetOnlineInfo().c_str() );
00538 }
00539 while( xml.GetFileNode() )
00540 {
00541 std::string fileName( xml.GetFileInfo() );
00542
00543 TGListTreeItem *fileItem =
00544 fFileOnlineContents->FindChildByName(fTreeItemFiles,fileName.c_str());
00545 if( fileItem )
00546 {
00547 fCloseFile = static_cast<TFile*>(static_cast<TObject*>(fileItem->GetUserData()));
00548 fTreeItemCurrent = fileItem;
00549 CloseFile();
00550 }
00551 bool errorOccurred = false;
00552 if( fileName.find(".root") != fileName.npos )errorOccurred = OpenRootFile( fileName.c_str() );
00553 #ifdef HAVE_HBOOK
00554 else errorOccurred = OpenHbookFile( fileName.c_str() );
00555 #endif
00556 if( errorOccurred )
00557 {
00558 std::string s("Could not open data file \"");
00559 s += fileName + "\"\nerror occurred while parsing xml file \"" + xmlFilename;
00560 new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
00561
00562 }
00563 }
00564 if( xml.GetGraphicsNode() )
00565 {
00566 xml.GetZones( fZoneColumns, fZoneRows );
00567 SetupZonesMenu();
00568
00569
00570 SetRefreshRate( xml.GetRefreshRate() );
00571
00572
00573 }
00574 while( xml.GetCanvasNode() )
00575 {
00576 int columns, rows;
00577 xml.GetZones( columns, rows );
00578
00579 fZoneColumns = columns;
00580 fZoneRows = rows;
00581 MakeNewCanvas();
00582 fDrawDestination = D_PLOT_NEXT;
00583 while( xml.GetHistogramNode() )
00584 {
00585 std::string name( xml.GetHistogramName() );
00586 std::string source( xml.GetHistogramSource() );
00587
00588 if( source == "online" )
00589 {
00590 if( !fSock )
00591 {
00592 std::string s("no online connection has been made\nerror occurred while parsing xml file \"");
00593 s += xmlFilename;
00594 new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
00595
00596 continue;
00597 }
00598 TObject *netObject = GetNetFolderObject( name.c_str() );
00599 if( !netObject )
00600 {
00601 std::string s("histogram \"");
00602 s += name + "\" not found in online area\nerror occurred while parsing xml file \"" + xmlFilename;
00603 new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
00604
00605 continue;
00606 }
00607 MarkObjectAsOnline( netObject );
00608 DrawObject( netObject );
00609 }
00610 else
00611 {
00612 TGListTreeItem *fileItem = fFileOnlineContents->FindChildByName(fTreeItemFiles,source.c_str());
00613 if( !fileItem )
00614 {
00615 std::string s("file \"");
00616 s += source + "\" not open\nerror occurred while parsing xml file \"" + xmlFilename;
00617 new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
00618
00619 continue;
00620 }
00621 TFile *fileObject = static_cast<TFile*>(static_cast<TObject*>(fileItem->GetUserData()));
00622 TObject *object = SearchDirectory( fileObject, name.c_str() );
00623 if( !object )
00624 {
00625 std::string s("histogram \"");
00626 s += name + "\" not found in \"" + source +
00627 "\"\nerror occurred while parsing xml file \"" + xmlFilename;
00628 new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
00629
00630 continue;
00631 }
00632 DrawObject( object );
00633 }
00634 }
00635 }
00636 while( xml.GetGroupNode() )
00637 {
00638 std::string groupname( xml.GetGroupName() );
00639
00640 TGListTreeItem *groupItem = fFileOnlineContents->FindChildByName(fTreeItemGroups,groupname.c_str());
00641 if( groupItem )
00642 {
00643 fTreeItemCurrent = groupItem;
00644 DeleteGroup();
00645 }
00646 if( !MakeNewGroup(groupname.c_str()) )
00647 {
00648 std::string s("Could not make new group \"");
00649 s += groupname + "\"\nerror occurred while parsing xml file \"" + xmlFilename;
00650 new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
00651
00652 continue;
00653 }
00654 while( xml.GetHistogramNode() )
00655 {
00656 std::string name( xml.GetHistogramName() );
00657 std::string source( xml.GetHistogramSource() );
00658
00659 TObject *object = 0;
00660 if( source == "online" )
00661 {
00662 if( !fSock )
00663 {
00664 std::string s("no online connection has been made\nerror occurred while parsing xml file \"");
00665 s += xmlFilename;
00666 new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
00667
00668 continue;
00669 }
00670 object = GetNetFolderObject( name.c_str() );
00671 if( !object )
00672 {
00673 std::string s("histogram \"");
00674 s += name + "\" not found in online area\nerror occurred while parsing xml file \"" + xmlFilename;
00675 new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
00676
00677 continue;
00678 }
00679 object = static_cast<TObjString*>(new TObjString(name.c_str()));
00680 AddHistogramToGroup( fGroupFolders.size()-1, object, "online" );
00681 }
00682 else
00683 {
00684 TGListTreeItem *fileItem =
00685 fFileOnlineContents->FindChildByName(fTreeItemFiles,source.c_str());
00686 if( !fileItem )
00687 {
00688 std::string s("file \"");
00689 s += source + "\" not open\nerror occurred while parsing xml file \"" + xmlFilename;
00690 new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
00691
00692 continue;
00693 }
00694 TFile *fileObject = static_cast<TFile*>(static_cast<TObject*>(fileItem->GetUserData()));
00695 object = SearchDirectory( fileObject, name.c_str() );
00696 if( !object )
00697 {
00698 std::string s("histogram \"");
00699 s += name + "\" not found in \"" + source +
00700 "\"\nerror occurred while parsing xml file \"" + xmlFilename;
00701 new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
00702
00703 continue;
00704 }
00705 AddHistogramToGroup( fGroupFolders.size()-1, object, source.c_str() );
00706 }
00707 }
00708 }
00709 }
00710
00711 void Roody::SetupZonesMenu()
00712 {
00713 UncheckAllZones();
00714 switch( fZoneColumns )
00715 {
00716 case 1:
00717 {
00718 switch( fZoneRows )
00719 {
00720 case 1:
00721 fMenuZones->CheckEntry( M_ZONES_11 );
00722 break;
00723 case 2:
00724 fMenuZones->CheckEntry( M_ZONES_12 );
00725 break;
00726 default:
00727 SetZonesUser();
00728 }
00729 break;
00730 }
00731 case 2:
00732 {
00733 switch( fZoneRows )
00734 {
00735 case 1:
00736 fMenuZones->CheckEntry( M_ZONES_21 );
00737 break;
00738 case 2:
00739 fMenuZones->CheckEntry( M_ZONES_22 );
00740 break;
00741 default:
00742 SetZonesUser();
00743 }
00744 break;
00745 }
00746 case 3:
00747 {
00748 switch( fZoneRows )
00749 {
00750 case 3:
00751 fMenuZones->CheckEntry( M_ZONES_33 );
00752 break;
00753 default:
00754 SetZonesUser();
00755 }
00756 break;
00757 }
00758 case 4:
00759 {
00760 switch( fZoneRows )
00761 {
00762 case 3:
00763 fMenuZones->CheckEntry( M_ZONES_44 );
00764 break;
00765 default:
00766 SetZonesUser();
00767 }
00768 break;
00769 }
00770 default:
00771 SetZonesUser();
00772 }
00773 }
00774
00775 void Roody::SetZonesUser()
00776 {
00777 fMenuZones->DeleteEntry( M_ZONES_USER );
00778 std::stringstream ss;
00779 ss << fZoneColumns << "x" << fZoneRows;
00780 fMenuZones->AddEntry( ss.str().c_str(), M_ZONES_USER,
00781 0, 0, fMenuZones->GetEntry(M_ZONES_DIALOG) );
00782 fMenuZones->CheckEntry( M_ZONES_USER );
00783 }
00784
00785 void Roody::SaveFile( char const *xmlFilename )
00786 {
00787 RoodyXML xml;
00788 std::ofstream &output( xml.OpenFileForWrite(xmlFilename) );
00789 if( output.rdstate() != std::ios::goodbit )
00790 {
00791 std::string s("Failed to open XML file \"");
00792 s += xmlFilename;
00793 new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
00794 return;
00795 }
00796 output << "<roody>\n";
00797
00798
00799
00800 if( fSock )
00801 {
00802 output << " <online>\n";
00803 output << " <host>" << xml.Encode(fHostName.Data()) << "</host>\n";
00804 output << " <port>" << xml.Encode(fPortName.Data()) << "</port>\n";
00805 output << " </online>\n";
00806 }
00807
00808
00809
00810 TGListTreeItem *temp = fTreeItemFiles->GetFirstChild();
00811 if( temp )
00812 {
00813 output << " <file>" << xml.Encode(temp->GetText()) << "</file>\n";
00814 TGListTreeItem *temp2;
00815 while( (temp2=temp->GetNextSibling()) )
00816 {
00817 output << " <file>" << xml.Encode(temp2->GetText()) << "</file>\n";
00818 temp = temp2;
00819 }
00820 }
00821
00822
00823
00824 output << " <graphics>\n";
00825 std::string zones = GetZoneSetting();
00826 output << " <zones>" << xml.Encode(zones) << "</zones>\n";
00827 output << " <refresh>" << fUpdateTimerSec << "</refresh>\n";
00828 output << " </graphics>\n";
00829
00830
00831
00832 TIter next( gROOT->GetListOfCanvases() );
00833 TCanvas *canvas;
00834 while((canvas = static_cast<TCanvas*>(next())))
00835 {
00836 output << " <canvas>\n";
00837 output << " <zones>" << fZoneSetting[canvas->GetName()] << "</zones>\n";
00838 TIter canvasNext( canvas->GetListOfPrimitives() );
00839 TObject *canvasObject;
00840 while( (canvasObject=static_cast<TObject*>(canvasNext())) )
00841 {
00842 if( canvasObject->InheritsFrom(TH1::Class()) )
00843 {
00844 output << " <histogram>\n";
00845 output << " <name>" << xml.Encode(canvasObject->GetName()) << "</name>\n";
00846 if( ObjectIsOnline(canvasObject) )
00847 output << " <source>online</source>\n";
00848 else
00849 output << " <source>"
00850 << xml.Encode(GetFileFromHist(static_cast<TH1*>(canvasObject)))
00851 << "</source>\n";
00852 output << " </histogram>\n";
00853 }
00854 else if( canvasObject->InheritsFrom(TPad::Class()) )
00855 {
00856 TPad *pad = static_cast<TPad*>(canvasObject);
00857 TIter padNext( pad->GetListOfPrimitives() );
00858 TObject *padObject;
00859 while( (padObject=static_cast<TObject*>(padNext())) )
00860 {
00861 if( padObject->InheritsFrom(TH1::Class()) )
00862 {
00863 output << " <histogram>\n";
00864 output << " <name>" << xml.Encode(padObject->GetName()) << "</name>\n";
00865 if( ObjectIsOnline(padObject) )
00866 output << " <source>online</source>\n";
00867 else
00868 output << " <source>"
00869 << xml.Encode(GetFileFromHist(static_cast<TH1*>(padObject)))
00870 << "</source>\n";
00871 output << " </histogram>\n";
00872 }
00873 }
00874 }
00875 }
00876 output << " </canvas>\n";
00877 }
00878
00879
00880
00881 std::size_t nGroups = fGroupFolders.size();
00882 for( std::size_t i=0; i<nGroups; ++i )
00883 {
00884 output << " <group>\n";
00885 TGListTreeItem *groupFolder = fGroupFolders[i];
00886 output << " <name>" << xml.Encode(groupFolder->GetText()) << "</name>\n";
00887 std::pair<GroupMap::iterator,GroupMap::iterator> p = fGroupHists.equal_range( i );
00888 for( GroupMap::iterator i=p.first; i!=p.second; ++i )
00889 {
00890 GroupItem groupItem( i->second );
00891 output << " <histogram>\n";
00892 output << " <name>" << xml.Encode(groupItem.item->GetText()) << "</name>\n";
00893 output << " <source>" << xml.Encode(groupItem.source) << "</source>\n";
00894 output << " </histogram>\n";
00895 }
00896 output << " </group>\n";
00897 }
00898 output << "</roody>\n";
00899 }
00900
00901 std::string Roody::GetFileFromHist( TH1 *hist )
00902 {
00903 TIter funcNext( hist->GetListOfFunctions() );
00904 TObject *func;
00905 std::string filename;
00906 while( (func=static_cast<TObject*>(funcNext())) )
00907 {
00908 if( func->InheritsFrom(TObjString::Class()) )
00909 {
00910 TObjString *str = static_cast<TObjString*>(func);
00911 std::string s( str->GetString().Data() );
00912 std::size_t size = s.size();
00913 if( size>=5 && s.substr(0,5) == "file:" )
00914 {
00915 filename = s.substr(5,size-5);
00916 break;
00917 }
00918 }
00919 }
00920 if( filename.empty() )filename = "unknown";
00921 return filename;
00922 }
00923
00924 Roody::~Roody()
00925 {
00926
00927 delete fMenuBarLayout1;
00928 delete fMenuBarLayout2;
00929 delete fMenuBarLayout3;
00930 delete fMenuFile;
00931 delete fMenuRefresh;
00932 delete fMenuZones;
00933 delete fMenuPlot;
00934 delete fMenuHelp;
00935 delete fMenuBar;
00936
00937
00938 delete fFrameLayout1;
00939 delete fFrameLayout2;
00940 delete fFrameLayout3;
00941 delete fStatusBarLayout;
00942
00943
00944 delete fRefreshButton;
00945
00946
00947 delete fFileOnlineContents;
00948
00949
00950 delete fFileOnlineCanvas;
00951
00952
00953
00954
00955 delete fStatusBar;
00956
00957
00958 delete fVerticalFrame;
00959 delete fHorizontalFrame;
00960
00961
00962 delete fUpdateTimer;
00963
00964
00965 fFileList->Clear();
00966 fTreeList->Clear();
00967
00968
00969 delete fFileList;
00970 delete fTreeList;
00971
00972
00973
00974
00975 std::vector<CanvasLimits*>::const_iterator end = fCanvasLimitsVector.end();
00976 for( std::vector<CanvasLimits*>::const_iterator i=fCanvasLimitsVector.begin(); i!=end; ++i )
00977 delete *i;
00978 }
00979
00980 void Roody::LayoutGUI()
00981 {
00982 LayoutMenuBar();
00983
00984
00985
00986 fFrameLayout1 = new TGLayoutHints( kLHintsTop|kLHintsLeft, 5, 5, 5, 5 );
00987 fFrameLayout2 = new TGLayoutHints( kLHintsTop|kLHintsExpandX|kLHintsExpandY, 5, 5, 5, 5 );
00988 fFrameLayout3 = new TGLayoutHints( kLHintsTop|kLHintsExpandX, 0, 0, 0, 0 );
00989
00990 fVerticalFrame = new TGVerticalFrame( this, 10, 10 );
00991
00992 fHorizontalFrame = new TGHorizontalFrame( fVerticalFrame, 10, 10 );
00993 fRefreshButton = new TGTextButton( fHorizontalFrame, " Refresh NOW ", M_REFRESH_BUTTON );
00994 fRefreshButton->Associate( this );
00995 fRefreshButton->SetToolTipText( "click to refresh online histograms once right now", 250 );
00996 fHorizontalFrame->AddFrame( fRefreshButton, new TGLayoutHints(kLHintsCenterX,2,2,2,2) );
00997 fRefreshButton->SetEnabled( kFALSE );
00998 fVerticalFrame->AddFrame( fHorizontalFrame, fFrameLayout3 );
00999
01000 fFileOnlineCanvas = new TGCanvas( fVerticalFrame, 340, 300 );
01001 fFileOnlineContents = new MTGListTree( fFileOnlineCanvas, kHorizontalFrame );
01002 fFileOnlineContents->AddItem( 0, "/" );
01003 fTreeItemCurrent = fFileOnlineContents->GetFirstItem();
01004 fTreeItemGroups = fFileOnlineContents->AddItem( fTreeItemCurrent, "Groups" );
01005 fTreeItemFiles = fFileOnlineContents->AddItem( fTreeItemCurrent, "Offline" );
01006
01007 fTreeItemOnline = fFileOnlineContents->AddItem( fTreeItemCurrent, "Online" );
01008 fFileOnlineContents->OpenItem( fTreeItemCurrent );
01009 fFileOnlineContents->Associate( this );
01010 fVerticalFrame->AddFrame( fFileOnlineCanvas, fFrameLayout2 );
01011
01012 AddFrame( fVerticalFrame, fFrameLayout2 );
01013
01014 fStatusBarLayout = new TGLayoutHints( kLHintsBottom|kLHintsLeft|kLHintsExpandX,
01015 0, 0, 2, 0 );
01016 fStatusBar = new TGStatusBar( this, 50, 10, kHorizontalFrame );
01017 AddFrame( fStatusBar, fStatusBarLayout );
01018 }
01019
01020 void Roody::LayoutMenuBar()
01021 {
01022 fMenuBarLayout1 = new TGLayoutHints( kLHintsNormal|kLHintsExpandX, 0, 0, 0, 10 );
01023 fMenuBarLayout2 = new TGLayoutHints( kLHintsTop|kLHintsLeft , 5, 0, 0, 0 );
01024 fMenuBarLayout3 = new TGLayoutHints( kLHintsTop|kLHintsRight, 0, 5, 0, 0 );
01025 fMenuFile = new TGPopupMenu( fClient->GetRoot() );
01026
01027 fMenuFile->AddEntry( "&Open data file...", M_FILE_OPEN );
01028 fMenuFile->AddEntry( "O&pen online...", M_FILE_ONLINE );
01029 fMenuFile->AddSeparator();
01030 fMenuFile->AddEntry( "&Save session", M_FILE_SAVE_DEFAULT );
01031 fMenuFile->AddEntry( "&Save session as...", M_FILE_SAVE );
01032 fMenuFile->AddEntry( "&Restore session...", M_FILE_RESTORE );
01033 fMenuFile->AddSeparator();
01034 fMenuFile->AddEntry( "&Exit", M_FILE_EXIT );
01035
01036 fMenuRefresh = new TGPopupMenu( fClient->GetRoot() );
01037 fMenuRefresh->AddEntry( "&Off", M_REFRESH_OFF );
01038 fMenuRefresh->AddEntry( "&Refresh now", M_REFRESH_NOW );
01039 fMenuRefresh->AddEntry( "&1 second", M_REFRESH_1SEC );
01040 fMenuRefresh->AddEntry( "&3 seconds", M_REFRESH_3SEC );
01041 fMenuRefresh->AddEntry( "&5 seconds", M_REFRESH_5SEC );
01042 fMenuRefresh->AddEntry( "10 seconds", M_REFRESH_10SEC );
01043 fMenuRefresh->AddEntry( "&Set refresh period...", M_REFRESH_DIALOG );
01044
01045 fMenuZones = new TGPopupMenu( fClient->GetRoot() );
01046 fMenuZones->AddEntry( "1x1", M_ZONES_11 );
01047 fMenuZones->AddEntry( "1x2", M_ZONES_12 );
01048 fMenuZones->AddEntry( "2x1", M_ZONES_21 );
01049 fMenuZones->AddEntry( "2x2", M_ZONES_22 );
01050 fMenuZones->AddEntry( "3x3", M_ZONES_33 );
01051 fMenuZones->AddEntry( "4x4", M_ZONES_44 );
01052 fMenuZones->AddEntry( "user", M_ZONES_USER );
01053 fMenuZones->AddEntry( "&Set zones...", M_ZONES_DIALOG );
01054 fMenuZones->CheckEntry(M_ZONES_11);
01055
01056 fMenuPlot = new TGPopupMenu( fClient->GetRoot() );
01057 fMenuPlot->AddEntry( "New canvas", M_PLOT_NEW );
01058 fMenuPlot->AddEntry( "Current pad", M_PLOT_REPLACE );
01059 fMenuPlot->AddEntry( "Overlay on Current pad", M_PLOT_SAME );
01060 fMenuPlot->AddEntry( "Next pad", M_PLOT_NEXT );
01061 SetDestination( D_PLOT_NEW );
01062
01063 fMenuClear = new TGPopupMenu( fClient->GetRoot() );
01064 fMenuClear->AddEntry( "&Reset all", M_RESET_ALL );
01065
01066 fMenuHelp = new TGPopupMenu( fClient->GetRoot() );
01067 fMenuHelp->AddEntry( "Contents", M_HELP_CONTENTS );
01068 fMenuHelp->AddEntry( "&About", M_HELP_ABOUT );
01069
01070 fMenuFile->Associate( this );
01071 fMenuRefresh->Associate( this );
01072 fMenuZones->Associate( this );
01073 fMenuPlot->Associate( this );
01074 fMenuClear->Associate( this );
01075 fMenuHelp->Associate( this );
01076
01077 fMenuBar = new TGMenuBar( this, 1, 1, kRaisedFrame );
01078 fMenuBar->AddPopup( "&File", fMenuFile, fMenuBarLayout2 );
01079 fMenuBar->AddPopup( "&Refresh", fMenuRefresh, fMenuBarLayout2 );
01080 fMenuBar->AddPopup( "&Zones", fMenuZones, fMenuBarLayout2 );
01081 fMenuBar->AddPopup( "&Plot in", fMenuPlot, fMenuBarLayout2 );
01082 fMenuBar->AddPopup( "&Reset", fMenuClear, fMenuBarLayout2 );
01083 fMenuBar->AddPopup( "&Help", fMenuHelp, fMenuBarLayout3 );
01084
01085 AddFrame( fMenuBar, fMenuBarLayout1 );
01086 }
01087
01088 void Roody::AddSetCut()
01089 {
01090 TClassMenuItem *menuItem = new TClassMenuItem( TClassMenuItem::kPopupUserFunction,
01091 Roody::Class(),
01092 "Send to Analyzer", "SetCut", this,
01093 "TObject*", 0);
01094 TCutG::Class()->GetMenuList()->AddFirst(menuItem);
01095 }
01096
01097 void Roody::SetCut( TObject *o )
01098 {
01099 TCutG *cut = static_cast<TCutG*>(o);
01100
01101 fSock->Send("SetCut");
01102 fSock->Send(cut->GetName());
01103 TMessage m (kMESS_OBJECT);
01104 m<<cut;
01105 fSock->Send(m);
01106 }
01107
01108 void Roody::AddZoomOption()
01109 {
01110 TClassMenuItem *menuItem = new TClassMenuItem( TClassMenuItem::kPopupUserFunction,
01111 Roody::Class(),
01112 "ZoomOption", "ZoomOption", this, "" );
01113 TH1C::Class()->GetMenuList()->AddFirst(menuItem);
01114 TH1S::Class()->GetMenuList()->AddFirst(menuItem);
01115 TH1I::Class()->GetMenuList()->AddFirst(menuItem);
01116 TH1F::Class()->GetMenuList()->AddFirst(menuItem);
01117 TH1D::Class()->GetMenuList()->AddFirst(menuItem);
01118 TFrame::Class()->GetMenuList()->AddFirst(menuItem);
01119 }
01120
01121 void Roody::ZoomOption()
01122 {
01123
01124
01125 if( !gPad || !strcmp(gPad->GetCanvas()->GetName(),"Zoom Canvas") )return;
01126
01127
01128
01129 std::vector<TH1*> histVec;
01130 TIter padNext( gPad->GetListOfPrimitives() );
01131 TObject *padObject;
01132 while( (padObject=static_cast<TObject*>(padNext())) )
01133 {
01134 if( padObject->InheritsFrom(TH1::Class()) )
01135 {
01136 if( ObjectIsOnline(padObject) )
01137 histVec.push_back(static_cast<TH1*>(GetNetFolderObject(padObject->GetName())));
01138 else
01139 histVec.push_back(static_cast<TH1*>(padObject->Clone(padObject->GetName())));
01140 }
01141 }
01142
01143
01144
01145 TVirtualPad *padSave = gPad;
01146
01147 MakeZoomCanvas();
01148 std::vector<TH1*>::const_iterator end = histVec.end();
01149 for( std::vector<TH1*>::const_iterator i=histVec.begin(); i!=end; ++i )
01150 {
01151 TH1*h = SetCanvasLimits( fZoomCanvas, *i );
01152 h->DrawCopy();
01153 }
01154 gPad = padSave;
01155 }
01156
01157 void Roody::AddAxisLimits()
01158 {
01159 TClassMenuItem *menuItem = new TClassMenuItem( TClassMenuItem::kPopupUserFunction,
01160 Roody::Class(),
01161 "XaxisLimits", "XaxisLimits", this, "" );
01162 TH1C::Class()->GetMenuList()->AddFirst(menuItem);
01163 TH1S::Class()->GetMenuList()->AddFirst(menuItem);
01164 TH1I::Class()->GetMenuList()->AddFirst(menuItem);
01165 TH1F::Class()->GetMenuList()->AddFirst(menuItem);
01166 TH1D::Class()->GetMenuList()->AddFirst(menuItem);
01167 TFrame::Class()->GetMenuList()->AddFirst(menuItem);
01168
01169 menuItem = new TClassMenuItem( TClassMenuItem::kPopupUserFunction,
01170 Roody::Class(),
01171 "YaxisLimits", "YaxisLimits", this, "" );
01172 TH1C::Class()->GetMenuList()->AddFirst(menuItem);
01173 TH1S::Class()->GetMenuList()->AddFirst(menuItem);
01174 TH1I::Class()->GetMenuList()->AddFirst(menuItem);
01175 TH1F::Class()->GetMenuList()->AddFirst(menuItem);
01176 TH1D::Class()->GetMenuList()->AddFirst(menuItem);
01177 TFrame::Class()->GetMenuList()->AddFirst(menuItem);
01178 }
01179
01180 void Roody::XaxisLimits()
01181 {
01182 CanvasLimits *limits = FindCanvasLimits(gPad->GetCanvas()->GetCanvasID());
01183 new TAxisLimitsDialog( gClient->GetRoot(), NULL, 250, 100, limits, this);
01184 }
01185
01186 void Roody::YaxisLimits()
01187 {
01188 CanvasLimits *limits = FindCanvasLimits(gPad->GetCanvas()->GetCanvasID());
01189 new TAxisLimitsDialog( gClient->GetRoot(), NULL, 250, 100, limits, this);
01190 }
01191
01192 void Roody::RedrawPad( TPad *pad )
01193 {
01194 TIter padNext( pad->GetListOfPrimitives() );
01195 TObject *padObject;
01196 std::vector<TH1*> histVec;
01197 while( (padObject=static_cast<TObject*>(padNext())) )
01198 {
01199 if( padObject->InheritsFrom(TH1::Class()) )
01200 {
01201 TH1 *hist = static_cast<TH1*>(padObject);
01202 Color_t color = hist->GetLineColor();
01203 TObjString name( hist->GetName() );
01204 if( ObjectIsOnline(padObject) )
01205 {
01206 TObject *netObject = GetNetFolderObject( name.GetString().Data() );
01207 if( netObject )
01208 {
01209 pad->GetListOfPrimitives()->Remove(hist);
01210 delete hist;
01211 hist = static_cast<TH1*>(netObject);
01212 hist->SetLineColor( color );
01213 MarkObjectAsOnline(hist);
01214 histVec.push_back( hist );
01215 }
01216 }
01217 else
01218 {
01219 TH1 *h = static_cast<TH1*>(hist->Clone(hist->GetName()));
01220 h->SetLineColor( color );
01221 histVec.push_back( h );
01222 }
01223 }
01224 }
01225 pad->Clear();
01226 if( !histVec.empty() )
01227 {
01228 TH1* h = SetCanvasLimits( pad->GetCanvas(), histVec[0] );
01229 h->Draw();
01230 std::vector<TH1*>::const_iterator end = histVec.end();
01231 for( std::vector<TH1*>::const_iterator i=histVec.begin()+1; i!=end; ++i )
01232 {
01233 h = SetCanvasLimits( pad->GetCanvas(), *i );
01234 h->Draw("SAME");
01235 }
01236 }
01237 pad->GetCanvas()->Modified();
01238 pad->GetCanvas()->Update();
01239 }
01240
01241 void Roody::RedrawCanvas()
01242 {
01243 TIter canvasNext( gPad->GetCanvas()->GetListOfPrimitives() );
01244 TObject *canvasObject;
01245 while( (canvasObject=static_cast<TObject*>(canvasNext())) )
01246 {
01247 if( canvasObject->InheritsFrom(TPad::Class()) )
01248 RedrawPad( static_cast<TPad*>(canvasObject) );
01249 else
01250 {
01251 RedrawPad( static_cast<TPad*>(gPad) );
01252 break;
01253 }
01254 }
01255 gPad->GetCanvas()->Modified();
01256 gPad->GetCanvas()->Update();
01257 }
01258
01259 bool Roody::ObjectIsOnline( TObject *obj )
01260 {
01261 if( !obj->InheritsFrom(TH1::Class()) )
01262 {
01263 std::cerr << "Roody::ObjectIsOnline: Object " << (void*)obj << " \"" << obj->GetName()
01264 << "\" is a \"" << obj->ClassName() << "\", not a TH1, aborting!" << std::endl;
01265 abort();
01266 }
01267 TH1 *hist = static_cast<TH1*>(obj);
01268 TIter funcNext( hist->GetListOfFunctions() );
01269 TObject *func;
01270 while( (func=static_cast<TObject*>(funcNext())) )
01271 {
01272 if( func->InheritsFrom(TObjString::Class()) )
01273 {
01274 TObjString *str = static_cast<TObjString*>(func);
01275 if( !strcmp("ONLINE",str->GetString().Data()) )return true;
01276 }
01277 }
01278 return false;
01279 }
01280
01281 void Roody::MarkObjectAsOnline( TObject *obj )
01282 {
01283 if( !ObjectIsOnline(obj) )
01284 static_cast<TH1*>(obj)->GetListOfFunctions()->Add( new TObjString("ONLINE") );
01285 }
01286
01287 CanvasLimits* Roody::FindCanvasLimits(Int_t canvasId)
01288 {
01289 std::vector<CanvasLimits*>::const_iterator end = fCanvasLimitsVector.end();
01290 for( std::vector<CanvasLimits*>::const_iterator i=fCanvasLimitsVector.begin(); i!=end; ++i )
01291 if( (*i)->fCanvasId == canvasId )
01292 return (*i);
01293 return NULL;
01294 }
01295
01296 TH1* Roody::SetCanvasLimits( TCanvas *canvas, TH1 *h )
01297 {
01298 CanvasLimits* limits = FindCanvasLimits(canvas->GetCanvasID());
01299 if (limits)
01300 return limits->ApplyLimits(h);
01301 else
01302 return h;
01303 }
01304
01305 TH1* GetOriginal(TH1*orig,const char*name)
01306 {
01307 char buf[256];
01308 strcpy(buf,name);
01309 char*s = strstr(buf,"_rebin");
01310 if (s)
01311 *s = 0;
01312
01313 TH1*xxx = (TH1*)gROOT->FindObject(buf);
01314 if (!xxx)
01315 return orig;
01316 else
01317 return xxx;
01318 }
01319
01320 TH1* CanvasLimits::ApplyLimits(TH1 *h)
01321 {
01322 const char* name = h->GetName();
01323
01324 if (fRebin > 1)
01325 {
01326 char rebinx[256];
01327 sprintf(rebinx,"_rebin%d_",fRebin);
01328
01329 if (strstr(name,rebinx)!=NULL)
01330 {
01331
01332 }
01333 else
01334 {
01335 h = GetOriginal(h,name);
01336 name = h->GetName();
01337 char buf[256];
01338 sprintf(buf,"%s%s",name,rebinx);
01339 h = h->Rebin(fRebin,buf);
01340 }
01341 }
01342 else
01343 {
01344 if (strstr(name,"_rebin")!=NULL)
01345 {
01346 h = GetOriginal(h,name);
01347 }
01348 }
01349
01350 if (fDoZoomXaxis)
01351 {
01352 h->GetXaxis()->SetRangeUser(fXmin, fXmax);
01353 }
01354
01355 if (fDoZoomYaxis)
01356 {
01357 h->SetMinimum(fYmin);
01358 h->SetMaximum(fYmax);
01359 }
01360
01361 if (fForceUnzoomX)
01362 h->GetXaxis()->UnZoom();
01363
01364 if (fForceUnzoomY)
01365 h->GetYaxis()->UnZoom();
01366
01367 return h;
01368 }
01369
01370 void Roody::AddPeakFind()
01371 {
01372 TClassMenuItem *menuItem = new TClassMenuItem( TClassMenuItem::kPopupUserFunction,
01373 Roody::Class(),
01374 "PeakFind", "PeakFind", this, "" );
01375 TH1C::Class()->GetMenuList()->AddFirst(menuItem);
01376 TH1S::Class()->GetMenuList()->AddFirst(menuItem);
01377 TH1I::Class()->GetMenuList()->AddFirst(menuItem);
01378 TH1F::Class()->GetMenuList()->AddFirst(menuItem);
01379 TH1D::Class()->GetMenuList()->AddFirst(menuItem);
01380 TFrame::Class()->GetMenuList()->AddFirst(menuItem);
01381 }
01382
01383 void Roody::SetDestination( EDrawDestination dest )
01384 {
01385 if( fDrawDestination )fMenuPlot->UnCheckEntry( fDrawDestination );
01386 fDrawDestination = dest;
01387 fMenuPlot->CheckEntry( fDrawDestination );
01388 }
01389
01390 void Roody::SetPad()
01391 {
01392
01393 int currentNumber = gPad->GetNumber();
01394
01395
01396 if( currentNumber > 0 )
01397 {
01398 gPad->GetCanvas()->cd( currentNumber+1 );
01399
01400
01401 if( gPad->GetNumber() == currentNumber )gPad->GetCanvas()->cd(1);
01402
01403 }
01404 }
01405
01406 std::string Roody::GetZoneSetting()
01407 {
01408 std::stringstream str;
01409 str << fZoneColumns << "x" << fZoneRows;
01410 return str.str();
01411 }
01412
01413 TH1 *Roody::GetHist( TPad *pad, TObject *object )
01414 {
01415 if( ObjectIsOnline(object) )
01416 {
01417 TObject *netObject = GetNetFolderObject(object->GetName());
01418 if( netObject )
01419 {
01420 pad->GetListOfPrimitives()->Remove(object);
01421 delete object;
01422 MarkObjectAsOnline(netObject);
01423 return static_cast<TH1*>(netObject);
01424 }
01425 else
01426 return static_cast<TH1*>(object);
01427 }
01428 else
01429 return static_cast<TH1*>(object->Clone(object->GetName()));
01430 }
01431
01432 void Roody::SetupZones( int columns, int rows )
01433 {
01434
01435
01436
01437
01438 fZoneColumns = columns;
01439 fZoneRows = rows;
01440 bool newCanvas = false;
01441 if( !gPad || std::string(gPad->GetCanvas()->GetName()).find("canvas")!=0 )
01442 {
01443 MakeNewCanvas();
01444 newCanvas = true;
01445 }
01446 else
01447 {
01448 fZoneSetting[gPad->GetCanvas()->GetName()] = GetZoneSetting();
01449 fZoneColumns*fZoneRows==1 ? SetDestination(D_PLOT_REPLACE) : SetDestination(D_PLOT_NEXT);
01450 }
01451
01452
01453 std::vector<HistPad*> histPadVec;
01454 TIter canvasNext( gPad->GetCanvas()->GetListOfPrimitives() );
01455 TObject *canvasObject;
01456 while( (canvasObject=static_cast<TObject*>(canvasNext())) )
01457 {
01458 if( canvasObject->InheritsFrom(TH1::Class()) )
01459 {
01460 HistPad *hp = new HistPad;
01461 hp->padNumber = 0;
01462 hp->hist = GetHist( static_cast<TPad*>(gPad), canvasObject );
01463 histPadVec.push_back( hp );
01464 }
01465 else if( canvasObject->InheritsFrom(TPad::Class()) )
01466 {
01467 TPad *pad = static_cast<TPad*>(canvasObject);
01468 TIter padNext( pad->GetListOfPrimitives() );
01469 TObject *padObject;
01470 while( (padObject=static_cast<TObject*>(padNext())) )
01471 {
01472 if( padObject->InheritsFrom(TH1::Class()) )
01473 {
01474 HistPad *hp = new HistPad;
01475 hp->padNumber = pad->GetNumber();
01476 hp->hist = GetHist( pad, padObject );
01477 histPadVec.push_back( hp );
01478 }
01479 }
01480 }
01481 }
01482 if( !newCanvas )
01483 {
01484 gPad->GetCanvas()->cd();
01485 gPad->Clear();
01486 if( columns*rows != 1 )
01487 {
01488 gPad->Divide( columns, rows );
01489 gPad->cd( columns*rows );
01490 }
01491 gPad->GetCanvas()->Modified();
01492 gPad->GetCanvas()->Update();
01493 }
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506 if( histPadVec.empty() )
01507 {
01508 gPad->GetCanvas()->cd( columns*rows );
01509 }
01510 else
01511 {
01512 Int_t histPadNumber = -1;
01513 Int_t padNumber = 0;
01514 std::vector<HistPad*>::const_iterator end = histPadVec.end();
01515 for( std::vector<HistPad*>::const_iterator i=histPadVec.begin(); i!=end; ++i )
01516 {
01517 TH1*h = SetCanvasLimits( gPad->GetCanvas(), (*i)->hist );
01518 if( (*i)->padNumber != histPadNumber )
01519 {
01520 if( ++padNumber > columns*rows )break;
01521 gPad->GetCanvas()->cd( padNumber );
01522 h->Draw();
01523 histPadNumber = (*i)->padNumber;
01524 }
01525 else h->Draw("SAME");
01526 delete *i;
01527 }
01528 gPad->GetCanvas()->Modified();
01529 gPad->GetCanvas()->Update();
01530 }
01531 }
01532
01533 void Roody::SelectPad( Int_t ev, Int_t x, Int_t y, TObject* obj )
01534 {
01535
01536 if( ev==kButton1Down || ev==kButton3Down )
01537 gPad->GetCanvas()->HandleInput( kButton2Down, x, y );
01538 }
01539
01540 void Roody::CleanupCurrentCanvas()
01541 {
01542 gPad->GetCanvas()->cd();
01543 TIter canvasNext( gPad->GetListOfPrimitives() );
01544 TObject *canvasObject;
01545 while( (canvasObject=static_cast<TObject*>(canvasNext())) )
01546 {
01547 if( canvasObject->InheritsFrom(TH1::Class()) )
01548 {
01549 TH1 *h1 = static_cast<TH1*>(canvasObject);
01550 TList *functions = h1->GetListOfFunctions();
01551 TIter histNext( functions );
01552 TObject *histObject = 0;
01553 while( (histObject=static_cast<TObject*>(histNext())) )delete histObject;
01554 functions->Clear();
01555 delete h1;
01556 }
01557 }
01558 }
01559
01560 void Roody::DrawObject( TObject *obj )
01561 {
01562
01563
01564 if( !gPad || fDrawDestination==D_PLOT_NEW ||
01565 std::string(gPad->GetCanvas()->GetName()).find("canvas")!=0 )MakeNewCanvas();
01566
01567 if( fDrawDestination == D_PLOT_NEXT )SetPad();
01568 if( obj->InheritsFrom(TH3::Class()) )
01569 {
01570 TH3 *h = static_cast<TH3*>(obj);
01571 if( fDrawDestination == D_PLOT_REPLACE )CleanupCurrentCanvas();
01572 h->Draw();
01573 }
01574 else if( obj->InheritsFrom(TH2::Class()) )
01575 {
01576 TH2 *h = static_cast<TH2*>(obj);
01577 if( fDrawDestination == D_PLOT_REPLACE )CleanupCurrentCanvas();
01578 h->Draw();
01579
01580
01581 }
01582 else if( obj->InheritsFrom(TH1::Class()) )
01583 {
01584 TH1 *h = static_cast<TH1*>(obj);
01585 h = SetCanvasLimits( gPad->GetCanvas(), h );
01586 if( fDrawDestination == D_PLOT_SAME )
01587 {
01588 TIter padNext( gPad->GetListOfPrimitives() );
01589 TObject *padObject;
01590 Color_t color = 0;
01591 while( (padObject=static_cast<TObject*>(padNext())) )
01592 {
01593 if( padObject->InheritsFrom(TH1::Class()) )
01594 color = static_cast<TH1*>(padObject)->GetLineColor();
01595 }
01596 h->SetLineColor( ++color );
01597 h->Draw("SAME");
01598 }
01599 else
01600 {
01601 if( fDrawDestination == D_PLOT_REPLACE )CleanupCurrentCanvas();
01602 h->Draw();
01603 }
01604 }
01605 else if( obj->InheritsFrom(TCutG::Class()) )
01606 {
01607 TCutG *c = static_cast<TCutG*>(obj);
01608 c->Draw();
01609 }
01610 else
01611 {
01612 std::string s("DrawObject: unsure how to Draw object ");
01613 s += obj->GetName() + std::string(" of type ") + obj->ClassName();
01614 new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
01615 fDrawDestination==D_PLOT_SAME ? obj->Draw("SAME") : obj->Draw();
01616 }
01617 gPad->Modified();
01618 gPad->Update();
01619 }
01620
01621 void Roody::PeakFind()
01622 {
01623 if( fgPeakFindPanel )
01624 fgPeakFindPanel->MapRaised();
01625 else
01626 fgPeakFindPanel = new TPeakFindPanel(gClient->GetRoot(),0,250,220);
01627 }
01628
01629 void Roody::PopupPlot( int x, int y, bool isFolder )
01630 {
01631 if( fPopupMenu )delete fPopupMenu;
01632
01633 bool online = false;
01634 ItemVec::const_iterator end = fTreeItems.end();
01635 for( ItemVec::const_iterator i=fTreeItems.begin(); i!=end; ++i )
01636 {
01637 TObject *object = static_cast<TObject*>((*i)->GetUserData());
01638 if( object && object->InheritsFrom(TObjString::Class()) )
01639 {
01640 online = true;
01641 break;
01642 }
01643 }
01644
01645 fPopupMenu = new TGPopupMenu( gClient->GetRoot() );
01646 fPopupMenu->AddEntry( "New canvas", C_PLOT_NEW );
01647 if( !isFolder && fTreeItems.size()==1 )
01648 {
01649 fPopupMenu->AddEntry( "Current pad", C_PLOT_REPLACE );
01650 fPopupMenu->AddEntry( "Overlay on Current pad", C_PLOT_SAME );
01651 fPopupMenu->AddEntry( "Next pad", C_PLOT_NEXT );
01652 }
01653 fPopupMenu->AddSeparator( static_cast<TGMenuEntry*>(0) );
01654 fPopupMenu->AddEntry( "Add to group", C_ADD_TO_GROUP );
01655 if( online )
01656 {
01657 fPopupMenu->AddSeparator( static_cast<TGMenuEntry*>(0) );
01658 fPopupMenu->AddEntry( "Reset", C_RESET_OBJECT );
01659 }
01660 fPopupMenu->PlaceMenu( x, y, false, true );
01661 fXSave = x;
01662 fYSave = y;
01663 fPopupMenu->Associate( this );
01664 }
01665
01666 void Roody::PopupOnlineMenu( int x, int y )
01667 {
01668 if( fPopupMenu )delete fPopupMenu;
01669 fPopupMenu = new TGPopupMenu( gClient->GetRoot() );
01670 fPopupMenu->AddEntry( "Disconnect online", C_CLOSE_ONLINE );
01671 fPopupMenu->PlaceMenu( x, y, false, true );
01672 fPopupMenu->Associate( this );
01673 }
01674
01675 void Roody::PopupFileMenu( int x, int y )
01676 {
01677 if( fPopupMenu )delete fPopupMenu;
01678 fPopupMenu = new TGPopupMenu( gClient->GetRoot() );
01679 fPopupMenu->AddEntry( "Close file", C_CLOSE_FILE );
01680 fPopupMenu->PlaceMenu( x, y, false, true );
01681 fPopupMenu->Associate( this );
01682 }
01683
01684 void Roody::PopupNewGroup( int x, int y )
01685 {
01686 if( fPopupMenu )delete fPopupMenu;
01687 fPopupMenu = new TGPopupMenu( gClient->GetRoot() );
01688 fPopupMenu->AddEntry( "Make new group", C_NEW_GROUP );
01689 fPopupMenu->PlaceMenu( x, y, false, true );
01690 fPopupMenu->Associate( this );
01691 }
01692
01693 void Roody::PopupGroup( int x, int y )
01694 {
01695 if( fPopupMenu )delete fPopupMenu;
01696 fPopupMenu = new TGPopupMenu( gClient->GetRoot() );
01697 fPopupMenu->AddEntry( "Draw group", C_DRAW_GROUP );
01698 fPopupMenu->AddEntry( "Reset group", C_RESET_GROUP );
01699 fPopupMenu->AddEntry( "Delete group", C_DELETE_GROUP );
01700 fPopupMenu->PlaceMenu( x, y, false, true );
01701 fPopupMenu->Associate( this );
01702 }
01703
01704 void Roody::AddNewGroup()
01705 {
01706 TObjString *objString = new TObjString();
01707 new TGTextDialog( gClient->GetRoot(), this, 100, 100, "Group name: ", "", objString );
01708 if( objString )
01709 {
01710 TString newGroupName( objString->GetString() );
01711 if( newGroupName.Length()>0 && !newGroupName.Contains("-1") )MakeNewGroup( newGroupName.Data() );
01712 delete objString;
01713 }
01714 }
01715
01716 bool Roody::MakeNewGroup( char const *name )
01717 {
01718 if( fFileOnlineContents->FindChildByName(fTreeItemGroups,name) )
01719 {
01720 std::string s("Error in making new group: \"");
01721 s += std::string(name) + "\" already exists";
01722 new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
01723 return false;
01724 }
01725 TGListTreeItem *groupFolder = fFileOnlineContents->AddItem( fTreeItemGroups, name );
01726 fGroupFolders.push_back( groupFolder );
01727 fFileOnlineContents->Resize();
01728 Layout();
01729 fParentDir->cd();
01730 return true;
01731 }
01732
01733 void Roody::PopupAddToGroup()
01734 {
01735 if( fGroupFolders.empty() )
01736 {
01737 std::string s("There are no groups");
01738 new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
01739 return;
01740 }
01741 if( fGroupFolders.size() == 1 )
01742 {
01743
01744
01745
01746 std::size_t nEntries = fTreeItems.size();
01747 for( std::size_t i=0; i<nEntries; ++i )
01748 {
01749 fTreeItemCurrent = fTreeItems[i];
01750 if( fTreeItemCurrent )
01751 {
01752 TObject *object = static_cast<TObject*>(fTreeItemCurrent->GetUserData());
01753 if( object )
01754 {
01755 std::auto_ptr<TString> className( new TString(object->ClassName()) );
01756 if( className->Contains("TH1") || className->Contains("TH2") ||
01757 className->Contains("TH3") )
01758 {
01759 TGListTreeItem *temp = fTreeItemCurrent;
01760 while( strcmp(temp->GetParent()->GetText(),"Offline") )temp = temp->GetParent();
01761 AddHistogramToGroup( 0, object, temp->GetText() );
01762 }
01763 else if( className->Contains("TObjString") )
01764 {
01765 AddHistogramToGroup( 0, object, "online" );
01766 }
01767 }
01768 }
01769 }
01770 return;
01771 }
01772 if( fAddToGroupPopup )delete fAddToGroupPopup;
01773 fAddToGroupPopup = new TGPopupMenu( gClient->GetRoot() );
01774 ItemVec::const_iterator end = fGroupFolders.end();
01775 int id = 99;
01776 for( ItemVec::const_iterator i=fGroupFolders.begin(); i!=end; ++i )
01777 fAddToGroupPopup->AddEntry( (*i)->GetText(), ++id );
01778 fAddToGroupPopup->PlaceMenu( fXSave, fYSave, false, true );
01779 fAddToGroupPopup->Associate( this );
01780 }
01781
01782 void Roody::DeleteGroup()
01783 {
01784
01785
01786
01787
01788 int id = 0;
01789 ItemVec::iterator end = fGroupFolders.end();
01790 for( ItemVec::iterator i=fGroupFolders.begin(); i!=end; ++i, ++id )
01791 {
01792 if( fTreeItemCurrent == *i )
01793 {
01794 std::size_t end = fGroupFolders.size();
01795 fGroupFolders.erase(i);
01796 std::pair<GroupMap::iterator,GroupMap::iterator> p = fGroupHists.equal_range( id );
01797 fGroupHists.erase( p.first, p.second );
01798 for( std::size_t j=id+1; j<end; ++j )
01799 {
01800 p = fGroupHists.equal_range( j );
01801 for( GroupMap::iterator k=p.first; k!=p.second; ++k )
01802 {
01803 GroupItem item = k->second;
01804 fGroupHists.erase( k );
01805 fGroupHists.insert( value_type(j-1,item) );
01806 }
01807 }
01808 break;
01809 }
01810 }
01811 fFileOnlineContents->MDeleteItem( fTreeItemCurrent );
01812 fFileOnlineContents->Resize();
01813 }
01814
01815 void Roody::MakeNewCanvas()
01816 {
01817 std::stringstream ss;
01818 ss << "canvas" << fCanvasCount++;
01819 std::string name( ss.str() );
01820 fCurrentCanvas = new TCanvas( name.c_str(), name.c_str() );
01821
01822 fCanvasLimitsVector.push_back(new CanvasLimits(fCurrentCanvas->GetCanvasID()));
01823
01824 fZoneSetting[name] = GetZoneSetting();
01825
01826 fZoneColumns*fZoneRows==1 ? SetDestination(D_PLOT_REPLACE) : SetDestination(D_PLOT_NEXT);
01827
01828 fCurrentCanvas->cd();
01829
01830 fCurrentCanvas->Clear();
01831 if( fZoneColumns*fZoneRows != 1 )
01832 {
01833 fCurrentCanvas->Divide( fZoneColumns, fZoneRows );
01834
01835 fCurrentCanvas->cd( fZoneColumns*fZoneRows );
01836 }
01837 fCurrentCanvas->Modified();
01838 fCurrentCanvas->Update();
01839
01840 fCurrentCanvas->Connect( "ProcessedEvent(Int_t,Int_t,Int_t,TObject*)", "Roody",
01841 this, "SelectPad(Int_t,Int_t,Int_t,TObject*)" );
01842 }
01843
01844 TCanvas* Roody::MakeGroupCanvas( char const *title, int columns, int rows )
01845 {
01846 TCanvas *canvas = new TCanvas( title, title );
01847
01848 fCanvasLimitsVector.push_back(new CanvasLimits(canvas->GetCanvasID()));
01849
01850 canvas->Clear();
01851 if( columns*rows != 1 )
01852 {
01853 canvas->Divide( columns, rows );
01854 canvas->cd( columns*rows );
01855 }
01856 std::stringstream str;
01857 str << columns << "x" << rows;
01858 fZoneSetting[std::string(title)] = str.str();
01859
01860 canvas->Modified();
01861 canvas->Update();
01862
01863 canvas->Connect( "ProcessedEvent(Int_t,Int_t,Int_t,TObject*)", "Roody",
01864 this, "SelectPad(Int_t,Int_t,Int_t,TObject*)" );
01865 return canvas;
01866 }
01867
01868 void Roody::MakeZoomCanvas()
01869 {
01870 if( fZoomCanvas )delete fZoomCanvas;
01871 fZoomCanvas = new TCanvas( "Zoom Canvas", "Zoom Canvas" );
01872
01873 fCanvasLimitsVector.push_back(new CanvasLimits(fZoomCanvas->GetCanvasID()));
01874
01875 fZoomCanvas->cd();
01876 fZoomCanvas->Clear();
01877 fZoomCanvas->Modified();
01878 fZoomCanvas->Update();
01879
01880 fZoomCanvas->Connect( "ProcessedEvent(Int_t,Int_t,Int_t,TObject*)", "Roody",
01881 this, "SelectPad(Int_t,Int_t,Int_t,TObject*)" );
01882 }
01883
01884 void Roody::DrawItemsOnNewCanvas()
01885 {
01886 std::size_t nItems = fTreeItems.size();
01887 std::size_t columns, rows;
01888 columns = static_cast<std::size_t>(sqrt(static_cast<double>(nItems)));
01889 rows = nItems/columns;
01890 while( rows*columns < nItems )++rows;
01891
01892 fZoneColumns = columns;
01893 fZoneRows = rows;
01894 MakeNewCanvas();
01895 int padNumber = 0;
01896
01897 ItemVec::const_iterator end = fTreeItems.end();
01898 for( ItemVec::const_iterator i=fTreeItems.begin(); i!=end; ++i )
01899 {
01900 TGListTreeItem *item = *i;
01901 if( !item )continue;
01902 gPad->GetCanvas()->cd( ++padNumber );
01903 TObject *object = static_cast<TObject*>(item->GetUserData());
01904 if( object && object->InheritsFrom(TH1::Class()) )
01905 {
01906 TH1 *tmp = static_cast<TH1*>(object);
01907 TH1 *th1 = static_cast<TH1*>( tmp->Clone(tmp->GetName()) );
01908 th1 = SetCanvasLimits( gPad->GetCanvas(), th1 );
01909 th1->Draw();
01910 }
01911 else if( object && object->InheritsFrom(TObjString::Class()) )
01912 {
01913 if( !fSock )
01914 {
01915 std::string s("no online connection, so online items cannot be drawn");
01916 new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
01917 continue;
01918 }
01919 TObject *tmp = GetNetFolderObject( (static_cast<TObjString*>(object))->GetString().Data() );
01920 if( tmp && tmp->InheritsFrom(TH1::Class()) )
01921 {
01922 TH1 *th1 = static_cast<TH1*>(tmp);
01923 MarkObjectAsOnline(th1);
01924 th1 = SetCanvasLimits( gPad->GetCanvas(), th1 );
01925 th1->Draw();
01926 }
01927 }
01928 gPad->Modified();
01929 gPad->Update();
01930 }
01931 }
01932
01933 void Roody::DrawGroup()
01934 {
01935 fTreeItemCurrent = fFileOnlineContents->GetSelected();
01936 int id = -1;
01937 std::size_t end = fGroupFolders.size();
01938 for( std::size_t i=0; i<end; ++i )
01939 {
01940 if( fTreeItemCurrent == fGroupFolders[i] )
01941 {
01942 id = static_cast<int>(i);
01943 break;
01944 }
01945 }
01946 if( id == -1 )
01947 {
01948 new TGMsgBox( gClient->GetRoot(), this, "Error", "unable to find group",
01949 kMBIconExclamation, 0, NULL );
01950 return;
01951 }
01952 int numHists = fGroupHists.count( id );
01953 if( numHists < 1 )
01954 {
01955 new TGMsgBox( gClient->GetRoot(), this, "Error", "group is empty",
01956 kMBIconExclamation, 0, NULL );
01957 return;
01958 }
01959 int columns, rows;
01960 columns = static_cast<int>(sqrt(static_cast<double>(numHists)));
01961 rows = numHists/columns;
01962 while( rows*columns < numHists )++rows;
01963
01964 TVirtualPad *padSave = gPad;
01965
01966
01967
01968
01969 std::string title( "Group canvas: " );
01970 title += std::string( fTreeItemCurrent->GetText() );
01971 TCanvas *canvas = MakeGroupCanvas( title.c_str(), columns, rows );
01972 int padNumber = 0;
01973
01974 std::pair<GroupMap::iterator,GroupMap::iterator> p = fGroupHists.equal_range( id );
01975 for( GroupMap::iterator i=p.first; i!=p.second; ++i )
01976 {
01977 canvas->cd( ++padNumber );
01978 TGListTreeItem *item = i->second.item;
01979 TObject *object = static_cast<TObject*>(item->GetUserData());
01980 std::auto_ptr<TString> className( new TString(object->ClassName()) );
01981 if( className->Contains("TH1") )
01982 {
01983 TH1 *tmp = static_cast<TH1*>(object);
01984 TH1 *th1 = static_cast<TH1*>( tmp->Clone(tmp->GetName()) );
01985 th1 = SetCanvasLimits( canvas, th1 );
01986 th1->Draw();
01987 }
01988 else if( className->Contains("TH2") )
01989 {
01990 TH2 *tmp = static_cast<TH2*>(object);
01991 TH2 *th2 = static_cast<TH2*>( tmp->Clone(tmp->GetName()) );
01992 th2->Draw();
01993 }
01994 else if( className->Contains("TH3") )
01995 {
01996 TH3 *tmp = static_cast<TH3*>(object);
01997 TH3 *th3 = static_cast<TH3*>( tmp->Clone(tmp->GetName()) );
01998 th3->Draw();
01999 }
02000 else if( className->Contains("TObjString") )
02001 {
02002 if( !fSock )
02003 {
02004 new TGMsgBox( gClient->GetRoot(), this,
02005 "Error", "no online connection, so online group items cannot be drawn",
02006 kMBIconExclamation, 0, NULL );
02007 continue;
02008 }
02009 TObjString *oName = new TObjString( (static_cast<TObjString*>(object))->GetString().Data() );
02010 TObject *tmp = GetNetFolderObject( oName->GetString().Data() );
02011 if( tmp && tmp->InheritsFrom(TH1::Class()) )
02012 {
02013 TH1 *h = static_cast<TH1*>(tmp);
02014 h = SetCanvasLimits( canvas, h );
02015 h->Draw();
02016 MarkObjectAsOnline(h);
02017 }
02018 }
02019 gPad->Modified();
02020 gPad->Update();
02021 }
02022 gPad = padSave;
02023 }
02024
02025 void Roody::SetRefreshRate( int newrefresh )
02026 {
02027 fUpdateTimerSec = newrefresh;
02028 StartOnlineTimer();
02029 fSock ? fRefreshButton->SetEnabled(kTRUE) : fRefreshButton->SetEnabled(kFALSE);
02030 if( fUpdateTimerSec > 0 )
02031 {
02032 std::stringstream str;
02033 str << " Pause Refresh (" << fUpdateTimerSec << ") ";
02034 fRefreshButton->SetText( str.str().c_str() );
02035 fRefreshButton->SetToolTipText( "click to PAUSE refresh of online histograms", 250 );
02036 }
02037 else
02038 {
02039 fRefreshButton->SetText( " Refresh NOW " );
02040 fRefreshButton->SetToolTipText( "click to refresh online histograms once right now", 250 );
02041 }
02042 }
02043
02044 void Roody::UncheckAllZones()
02045 {
02046 fMenuZones->UnCheckEntry(M_ZONES_11);
02047 fMenuZones->UnCheckEntry(M_ZONES_12);
02048 fMenuZones->UnCheckEntry(M_ZONES_21);
02049 fMenuZones->UnCheckEntry(M_ZONES_22);
02050 fMenuZones->UnCheckEntry(M_ZONES_33);
02051 fMenuZones->UnCheckEntry(M_ZONES_44);
02052 fMenuZones->UnCheckEntry(M_ZONES_USER);
02053 }
02054
02055 Bool_t Roody::ProcessMessage( Long_t msg, Long_t parm1, Long_t parm2 )
02056 {
02057
02058
02059
02060
02061
02062
02063 switch (GET_MSG(msg))
02064 {
02065 case kC_LISTTREE:
02066 {
02067 switch (GET_SUBMSG(msg))
02068 {
02069 case kCT_ITEMCLICK:
02070 {
02071 switch (parm1)
02072 {
02073 case kButton1:
02074 {
02075
02076 break;
02077 }
02078 case kButton2:
02079 {
02080 break;
02081 }
02082 case kButton3:
02083 {
02084
02085 int x = parm2&0xFFFF;
02086 int y = (parm2&0xFFFF0000)>>16;
02087
02088 fFileOnlineContents->GetSelectedItems( fTreeItems );
02089 std::size_t nEntries = fTreeItems.size();
02090 if( nEntries == 0 )break;
02091 fTreeItemCurrent = fTreeItems[0];
02092
02093 TObject *object = static_cast<TObject*>(fTreeItemCurrent->GetUserData());
02094 if( object )
02095 {
02096 std::auto_ptr<TString> className( new TString(object->ClassName()) );
02097 if( object->InheritsFrom(TH1::Class()) )
02098 {
02099 PopupPlot( x, y );
02100 }
02101 else if( object->InheritsFrom(TObjString::Class()) )
02102 {
02103 PopupPlot( x, y );
02104 }
02105 else if( object->InheritsFrom(TFile::Class()) )
02106 {
02107 fCloseFile = static_cast<TFile*>(object);
02108 PopupFileMenu( x, y );
02109 }
02110 else if( object->InheritsFrom(TSocket::Class()) )
02111 {
02112 if( fSock )PopupOnlineMenu( x, y );
02113 }
02114 }
02115 else if( fTreeItemCurrent == fTreeItemGroups )
02116 {
02117 PopupNewGroup( x, y );
02118 }
02119 else if( fTreeItemCurrent == fTreeItemFiles )
02120 {
02121 OpenFileDialog();
02122 }
02123 else if( fTreeItemCurrent == fTreeItemOnline )
02124 {
02125 if( !fSock )
02126 {
02127 std::auto_ptr<TObjString> os( new TObjString() );
02128 new TGTextDialog( gClient->GetRoot(), this, 100, 100, "&Host name:",
02129 fHostName.Data(), os.get() );
02130 TString s( os.get()->GetString() );
02131 if( !s.Contains("-1") )ConnectServer( s.Data() );
02132 }
02133 }
02134 else
02135 {
02136 bool foundGroupFolder = false;
02137 ItemVec::const_iterator end = fGroupFolders.end();
02138 for( ItemVec::const_iterator i=fGroupFolders.begin(); i!=end; ++i )
02139 {
02140 if( *i == fTreeItemCurrent )
02141 {
02142 PopupGroup( x, y );
02143 foundGroupFolder = true;
02144 break;
02145 }
02146 }
02147 if( !foundGroupFolder )
02148 {
02149 fTreeItems.clear();
02150 GetFolderItems( fTreeItemCurrent );
02151 PopupPlot( x, y, true );
02152 }
02153 }
02154 break;
02155 }
02156 default:
02157 {
02158 break;
02159 }
02160 }
02161 break;
02162 }
02163 case kCT_ITEMDBLCLICK:
02164 {
02165 PlotItem();
02166 break;
02167 }
02168 default:
02169 break;
02170 }
02171 break;
02172 }
02173 case kC_COMMAND:
02174 {
02175 switch (GET_SUBMSG(msg))
02176 {
02177 case kCM_BUTTON:
02178 {
02179 switch (parm1)
02180 {
02181 case M_REFRESH_BUTTON:
02182 {
02183 if( fSock )
02184 {
02185 if( fUpdateTimerSec > 0 )
02186 {
02187 if( fRefreshButton->GetString().BeginsWith(" Pause") )
02188 {
02189 fUpdateTimer->Stop();
02190 std::stringstream str;
02191 str << " Restart Refresh (" << fUpdateTimerSec << ") ";
02192 fRefreshButton->SetText( str.str().c_str() );
02193 fRefreshButton->SetToolTipText( "click to RESTART refresh of online histograms", 250 );
02194 }
02195 else
02196 {
02197 fUpdateTimer->Start();
02198 std::stringstream str;
02199 str << " Pause Refresh (" << fUpdateTimerSec << ") ";
02200 fRefreshButton->SetText( str.str().c_str() );
02201 fRefreshButton->SetToolTipText( "click to PAUSE refresh of online histograms", 250 );
02202 }
02203 }
02204 else
02205 {
02206 fUpdateTimerSec = 1;
02207 UpdateHistograms();
02208 fUpdateTimerSec = 0;
02209 }
02210 }
02211 break;
02212 }
02213 default:
02214 break;
02215 }
02216 break;
02217 }
02218 case kCM_MENUSELECT:
02219 {
02220 break;
02221 }
02222 case kCM_MENU:
02223 {
02224 switch (parm1)
02225 {
02226 case M_FILE_OPEN:
02227 {
02228 fStatusBar->SetText("Opening ...");
02229 OpenFileDialog();
02230 fStatusBar->SetText(" ");
02231 break;
02232 }
02233 case M_FILE_ONLINE:
02234 {
02235 if( fSock )
02236 {
02237 new TGMsgBox( gClient->GetRoot(), this,
02238 "Error", "Online connection already made",
02239 kMBIconExclamation, 0, NULL );
02240 }
02241 else
02242 {
02243 std::auto_ptr<TObjString> os( new TObjString() );
02244 new TGTextDialog( gClient->GetRoot(), this, 100, 100, "&Host name:",
02245 fHostName.Data(), os.get() );
02246 TString s( os.get()->GetString() );
02247 if( !s.Contains("-1") )ConnectServer( s.Data() );
02248 }
02249 break;
02250 }
02251 case M_FILE_SAVE_DEFAULT:
02252 {
02253 TString savefileName = "default.xml";
02254 fStatusBar->SetText("Saving session: " + savefileName);
02255 SaveFile( savefileName.Data() );
02256 break;
02257 }
02258 case M_FILE_SAVE:
02259 {
02260 OpenSaveDialog();
02261 break;
02262 }
02263 case M_FILE_RESTORE:
02264 {
02265 OpenRestoreDialog();
02266 break;
02267 }
02268 case M_FILE_EXIT:
02269 {
02270 CloseWindow();
02271 break;
02272 }
02273 case M_HELP_ABOUT:
02274 {
02275 new TGMsgBox( gClient->GetRoot(), this, "About Roody",
02276 "Roody is an application based solely on CERN-ROOT for histogram display.\nIt is meant for display of .root files and .hbook files.\nRunning this application in conjunction with either the Midas or ROME analyzer\nwill allow you to visualize online data retrieved through a socket port.\n\nThe current version of Roody is 1.7", kMBIconQuestion, kMBOk, NULL );
02277 break;
02278 }
02279 case M_HELP_CONTENTS:
02280 {
02281 fStatusBar->SetText("HELP CONTENTS -- Not yet available");
02282 std::cout << "HELP CONTENTS -- Not yet available" << std::endl;
02283 break;
02284 }
02285 case M_REFRESH_OFF:
02286 {
02287 SetRefreshRate(0);
02288 break;
02289 }
02290 case M_REFRESH_NOW:
02291 {
02292 int tmp = fUpdateTimerSec;
02293 fUpdateTimerSec = 1;
02294 UpdateHistograms();
02295 fUpdateTimerSec = tmp;
02296 break;
02297 }
02298 case M_REFRESH_1SEC:
02299 {
02300 SetRefreshRate(1);
02301 break;
02302 }
02303 case M_REFRESH_3SEC:
02304 {
02305 SetRefreshRate(3);
02306 break;
02307 }
02308 case M_REFRESH_5SEC:
02309 {
02310 SetRefreshRate(5);
02311 break;
02312 }
02313 case M_REFRESH_10SEC:
02314 {
02315 SetRefreshRate(10);
02316 break;
02317 }
02318 case M_REFRESH_DIALOG:
02319 {
02320 OpenRefreshDialog();
02321 break;
02322 }
02323 case M_ZONES_11:
02324 {
02325 UncheckAllZones();
02326 fMenuZones->CheckEntry(M_ZONES_11);
02327 SetupZones( 1, 1 );
02328 break;
02329 }
02330 case M_ZONES_12:
02331 {
02332 UncheckAllZones();
02333 fMenuZones->CheckEntry(M_ZONES_12);
02334 SetupZones( 1, 2 );
02335 break;
02336 }
02337 case M_ZONES_21:
02338 {
02339 UncheckAllZones();
02340 fMenuZones->CheckEntry(M_ZONES_21);
02341 SetupZones( 2, 1 );
02342 break;
02343 }
02344 case M_ZONES_22:
02345 {
02346 UncheckAllZones();
02347 fMenuZones->CheckEntry(M_ZONES_22);
02348 SetupZones( 2, 2 );
02349 break;
02350 }
02351 case M_ZONES_33:
02352 {
02353 UncheckAllZones();
02354 fMenuZones->CheckEntry(M_ZONES_33);
02355 SetupZones( 3, 3 );
02356 break;
02357 }
02358 case M_ZONES_44:
02359 {
02360 UncheckAllZones();
02361 fMenuZones->CheckEntry(M_ZONES_44);
02362 SetupZones( 4, 4 );
02363 break;
02364 }
02365 case M_ZONES_USER:
02366 {
02367 std::string name( fMenuZones->GetEntry(M_ZONES_USER)->GetName() );
02368 if( name.find("user") == 0 )OpenZoneDialog();
02369 else
02370 {
02371 std::size_t x = name.find("x");
02372 int cols, rows;
02373 StringTo<int>( cols, name.substr(0,x), std::dec );
02374 StringTo<int>( rows, name.substr(x+1,name.size()-x-1), std::dec );
02375 SetupZones( cols, rows );
02376 }
02377 SetupZonesMenu();
02378 break;
02379 }
02380 case M_ZONES_DIALOG:
02381 {
02382 OpenZoneDialog();
02383 SetupZonesMenu();
02384 break;
02385 }
02386 case M_PLOT_NEW:
02387 SetDestination(D_PLOT_NEW);
02388 break;
02389 case M_PLOT_SAME:
02390 SetDestination(D_PLOT_SAME);
02391 break;
02392 case M_PLOT_REPLACE:
02393 SetDestination(D_PLOT_REPLACE);
02394 break;
02395 case M_PLOT_NEXT:
02396 SetDestination(D_PLOT_NEXT);
02397 break;
02398
02399 case C_PLOT_NEW:
02400 DrawItemsOnNewCanvas();
02401 break;
02402 case C_PLOT_SAME:
02403 fDrawDestination = D_PLOT_SAME;
02404 PlotItem();
02405 break;
02406 case C_PLOT_REPLACE:
02407 fDrawDestination = D_PLOT_REPLACE;
02408 PlotItem();
02409 break;
02410 case C_PLOT_NEXT:
02411 fDrawDestination = D_PLOT_NEXT;
02412 PlotItem();
02413 break;
02414
02415 case C_CLOSE_FILE:
02416 CloseFile();
02417 break;
02418 case C_CLOSE_ONLINE:
02419 CloseOnline();
02420 break;
02421
02422 case C_NEW_GROUP:
02423 AddNewGroup();
02424 break;
02425 case C_DRAW_GROUP:
02426 DrawGroup();
02427 break;
02428 case C_DELETE_GROUP:
02429
02430 DeleteGroup();
02431 break;
02432 case C_ADD_TO_GROUP:
02433 PopupAddToGroup();
02434 break;
02435 case C_RESET_GROUP:
02436 fTreeItems.clear();
02437 GetFolderItems( fTreeItemCurrent );
02438 ResetMultiple();
02439 break;
02440 case C_RESET_OBJECT:
02441 ResetMultiple();
02442 break;
02443
02444 case M_RESET_ALL:
02445
02446
02447
02448 ResetAll();
02449 break;
02450
02451 default:
02452 {
02453 int id = parm1-100;
02454 if( id>=0 && id<static_cast<int>(fGroupFolders.size()) )
02455 {
02456 std::size_t nEntries = fTreeItems.size();
02457 for( std::size_t i=0; i<nEntries; ++i )
02458 {
02459 fTreeItemCurrent = fTreeItems[i];
02460 if( fTreeItemCurrent )
02461 {
02462 TObject *object = static_cast<TObject*>(fTreeItemCurrent->GetUserData());
02463 if( object )
02464 {
02465 std::auto_ptr<TString> className( new TString(object->ClassName()) );
02466 if( className->Contains("TH1") || className->Contains("TH2") ||
02467 className->Contains("TH3") )
02468 {
02469 TGListTreeItem *temp = fTreeItemCurrent;
02470 while( strcmp(temp->GetParent()->GetText(),"Offline") )temp = temp->GetParent();
02471 AddHistogramToGroup( id, object, temp->GetText() );
02472 }
02473 else if( className->Contains("TObjString") )
02474 {
02475 AddHistogramToGroup( id, object, "online" );
02476 }
02477 }
02478 }
02479 }
02480 }
02481 else
02482 {
02483 new TGMsgBox( gClient->GetRoot(), this,
02484 "Error", "Unimplemented menu command", kMBIconExclamation, 0, NULL );
02485 }
02486 break;
02487 }
02488 }
02489 break;
02490 }
02491 default:
02492 break;
02493 }
02494 break;
02495 }
02496 }
02497 return kTRUE;
02498 }
02499
02500 bool Roody::AddHistogramToGroup( int id, TObject *object, char const *source )
02501 {
02502 TGListTreeItem *itemFound = fFileOnlineContents->FindChildByData( fGroupFolders[id], (void*)object );
02503 if( !itemFound )
02504 {
02505 GroupItem groupItem;
02506 groupItem.source = std::string( source );
02507 fFileOnlineContents->AddItem( fGroupFolders[id],
02508 object->GetName(),
02509 (void*)object,
02510 gClient->GetPicture("h1_t.xpm"),
02511 gClient->GetPicture("h1_t.xpm") );
02512 fFileOnlineContents->Resize();
02513 Layout();
02514
02515 fTreeItemCurrent = fFileOnlineContents->FindChildByData( fGroupFolders[id], (void*)object );
02516 groupItem.item = fTreeItemCurrent;
02517 fGroupHists.insert( value_type(id,groupItem) );
02518 }
02519 return true;
02520 }
02521
02522 void Roody::CloseOnline()
02523 {
02524 fSock->Close();
02525 delete fSock;
02526 fSock = 0;
02527 fFileOnlineContents->MDeleteItem(
02528 fFileOnlineContents->FindChildByName(fTreeItemOnline,(fHostName+":"+fPortName).Data()) );
02529 fFileOnlineContents->Resize();
02530 Layout();
02531 fStatusBar->SetText( "Socket disconnected" );
02532 fRefreshButton->SetEnabled( kFALSE );
02533 }
02534
02535 void Roody::CloseFile()
02536 {
02537 std::string filename( fTreeItemCurrent->GetText() );
02538
02539 fFileList->Remove( fCloseFile );
02540 fCloseFile->Close();
02541 delete fCloseFile;
02542 fFileOnlineContents->MDeleteItem( fTreeItemCurrent );
02543 fFileOnlineContents->Resize();
02544 Layout();
02545
02546 std::size_t end = fGroupFolders.size();
02547 for( std::size_t id=0; id<end; ++id )
02548 {
02549 std::pair<GroupMap::iterator,GroupMap::iterator> p = fGroupHists.equal_range( id );
02550 for( GroupMap::iterator k=p.first; k!=p.second; ++k )
02551 {
02552 if( k->second.source == filename )
02553 {
02554 fGroupHists.erase( k );
02555 fFileOnlineContents->MDeleteItem( k->second.item );
02556 }
02557 }
02558 }
02559 fFileOnlineContents->Resize();
02560 Layout();
02561 }
02562
02563 void Roody::GetFolderItems( TGListTreeItem *item )
02564 {
02565
02566
02567
02568 TGListTreeItem *firstChild = item->GetFirstChild();
02569 if( firstChild )GetItemsRecursive( firstChild );
02570 if( item->GetUserData() &&
02571 find(fTreeItems.begin(),fTreeItems.end(),item) == fTreeItems.end() )
02572 fTreeItems.push_back( item );
02573 }
02574
02575 void Roody::GetItemsRecursive( TGListTreeItem *item )
02576 {
02577
02578
02579
02580 while( item )
02581 {
02582 TGListTreeItem *firstChild = item->GetFirstChild();
02583 if( firstChild )GetItemsRecursive( firstChild );
02584 if( item->GetUserData() &&
02585 find(fTreeItems.begin(),fTreeItems.end(),item) == fTreeItems.end() )
02586 fTreeItems.push_back( item );
02587 item = item->GetNextSibling();
02588 }
02589 }
02590
02591 void Roody::ResetAll()
02592 {
02593 if( !fSock )return;
02594 TNetFolder netFolder( "histos", "online histos", fSock );
02595 netFolder.ExecuteCommand( "gAnalyzer->ResetAllHistos()" );
02596 }
02597
02598 void Roody::ResetMultiple()
02599 {
02600
02601
02602
02603 ItemVec::const_iterator end = fTreeItems.end();
02604 for( ItemVec::const_iterator i=fTreeItems.begin(); i!=end; ++i )
02605 {
02606 if( *i )ResetObject( static_cast<TObject*>((*i)->GetUserData()) );
02607 }
02608 }
02609
02610 void Roody::ResetObject( TObject *object )
02611 {
02612 if( !fSock )return;
02613 if( !object )return;
02614 std::auto_ptr<TString> className( new TString(object->ClassName()) );
02615 if( className->Contains("TObjString") )
02616 {
02617 TNetFolder netFolder( "histos", "online histos", fSock );
02618 std::string s("gAnalyzer->GetHisto(\"");
02619 std::string path(
02620 netFolder.FindFullPathName( static_cast<TObjString*>(object)->GetString().Data() ) );
02621 if( path.substr(0,2) == "//" )path.erase(0,2);
02622 s += path + "\")->Reset()";
02623 netFolder.ExecuteCommand( s.c_str() );
02624
02625
02626
02627
02628
02629
02630 }
02631 }
02632
02633 void Roody::PlotItem()
02634 {
02635 TGListTreeItem *item = fFileOnlineContents->GetSelected();
02636 if( !item )return;
02637 TObject *object = static_cast<TObject*>(item->GetUserData());
02638 if( !object )return;
02639 if( object->InheritsFrom(TH1::Class()) )
02640 {
02641
02642
02643
02644 TH1 *tmp = static_cast<TH1*>(object);
02645 DrawObject( tmp->Clone(tmp->GetName()) );
02646 }
02647 else if( object->InheritsFrom(TTree::Class()) )
02648 {
02649 static_cast<TTree*>(object)->StartViewer();
02650 }
02651 else if( object->InheritsFrom(TNtuple::Class()) )
02652 {
02653 static_cast<TNtuple*>(object)->StartViewer();
02654 }
02655 else if( object->InheritsFrom(TCanvas::Class()) )
02656 {
02657 static_cast<TCanvas*>(object)->Draw();
02658 }
02659 else if( object->InheritsFrom(TFile::Class()) )
02660 {
02661 DisplayFile( item );
02662 }
02663 #ifdef HAVE_HBOOK
02664 else if( object->InheritsFrom(THbookFile::Class()) )
02665 {
02666 DisplayFile( item );
02667 }
02668 #endif
02669 else if( object->InheritsFrom(TSocket::Class()) )
02670 {
02671 GetHistList( item );
02672 }
02673 else if( object->InheritsFrom(TObjString::Class()) )
02674 {
02675 DrawOnlineObject( static_cast<TObjString*>(object) );
02676 }
02677 else if( object->InheritsFrom(TCutG::Class()) )
02678 {
02679 DrawObject( object );
02680 }
02681 Layout();
02682 }
02683
02684 void Roody::CloseWindow()
02685 {
02686 gApplication->Terminate(0);
02687 }
02688
02689 void Roody::OpenFileDialog()
02690 {
02691 fFileInfo.fFilename = 0;
02692 #ifdef HAVE_HBOOK
02693 char const *fileTypes[] = {"Root files","*.root","Hbook files","*.hbook",0,0};
02694 #else
02695 char const *fileTypes[] = {"Root files","*.root",0,0};
02696 #endif
02697 fFileInfo.fFileTypes = fileTypes;
02698 new TGFileDialog( fClient->GetRoot(), this, kFDOpen, &fFileInfo );
02699 if( fFileInfo.fFilename )
02700 {
02701 if( TString(fFileInfo.fFilename).Contains(".root") )OpenRootFile( fFileInfo.fFilename );
02702 #ifdef HAVE_HBOOK
02703 else OpenHbookFile( fFileInfo.fFilename );
02704 #endif
02705 }
02706 else
02707 {
02708 fStatusBar->SetText("NO FILE SELECTED");
02709 }
02710 }
02711
02712 bool Roody::OpenRootFile( char const *filename )
02713 {
02714 if( fFileOnlineContents->FindChildByName(fTreeItemFiles,filename) )
02715 {
02716 std::string s("Error in loading file: \"");
02717 s += std::string(filename) + "\" is already loaded";
02718 new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
02719 return true;
02720 }
02721 fFileInfo.fFilename = const_cast<char*>(filename);
02722 fCurrentFile = new TFile( filename, "READ" );
02723 if( !fCurrentFile )
02724 {
02725 new TGMsgBox( gClient->GetRoot(), this, "Error", "Error in loading file: could not allocate TFile object",
02726 kMBIconExclamation, 0, NULL );
02727 fCurrentFile = 0;
02728 return true;
02729 }
02730 if( fCurrentFile->IsZombie() )
02731 {
02732 std::string s("Error in loading file: \"");
02733 s += std::string(filename) + "\" is not a root file or the file doesn't exist";
02734 new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
02735 delete fCurrentFile;
02736 fCurrentFile = 0;
02737 return true;
02738 }
02739 fOpeningFile = true;
02740 fFileList->AddLast( fCurrentFile );
02741 AddFileEntryTreeView( fCurrentFile );
02742 fParentDir->cd();
02743 return false;
02744 }
02745
02746 #ifdef HAVE_HBOOK
02747 bool Roody::OpenHbookFile( char const *filename )
02748 {
02749 fFileInfo.fFilename = const_cast<char*>(filename);
02750 fCurrentHbook = new THbookFile( filename );
02751 if( !fCurrentFile )
02752 {
02753 std::string s("Error in loading file: \"");
02754 s += std::string(filename) + "\" could not allocate THbookFile object";
02755 new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
02756 fCurrentHbook = 0;
02757 return true;
02758 }
02759 if( !fCurrentHbook->IsOpen() )
02760 {
02761 std::string s("Error in loading file: \"");
02762 s += std::string(filename) + "\" is not an hbook file or the file doesn't exist";
02763 new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
02764 delete fCurrentHbook;
02765 fCurrentHbook = 0;
02766 return true;
02767 }
02768 if( fFileOnlineContents->FindChildByName(fTreeItemFiles,filename) )
02769 {
02770 std::string s("Error in loading file: \"");
02771 s += std::string(filename) + "\" is already loaded";
02772 new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
02773 delete fCurrentHbook;
02774 fCurrentHbook = 0;
02775 return true;
02776 }
02777 fFileList->AddLast( fCurrentHbook );
02778 AddFileEntryTreeView( fCurrentHbook );
02779 fParentDir->cd();
02780 return false;
02781 }
02782 #endif
02783
02784 void Roody::AddFileEntryTreeView( TFile *file )
02785 {
02786 fFileOnlineContents->AddItem( fTreeItemFiles,
02787 fFileInfo.fFilename,(void*)file,
02788 gClient->GetPicture("rootdb_t.xpm"),
02789 gClient->GetPicture("rootdb_t.xpm") );
02790 fTreeItemCurrent = fFileOnlineContents->FindChildByName( fTreeItemFiles, fFileInfo.fFilename );
02791 fFileOnlineContents->OpenItem( fTreeItemFiles );
02792 DisplayFile( fTreeItemCurrent );
02793 fFileOnlineContents->OpenItem( fTreeItemCurrent );
02794 fFileOnlineContents->Resize();
02795 Layout();
02796 }
02797
02798 #ifdef HAVE_HBOOK
02799 void Roody::AddFileEntryTreeView( THbookFile *file )
02800 {
02801 fFileOnlineContents->AddItem( fTreeItemFiles,
02802 fFileInfo.fFilename,(void*)file,
02803 gClient->GetPicture("rootdb_t.xpm"),
02804 gClient->GetPicture("rootdb_t.xpm") );
02805 fTreeItemCurrent = fFileOnlineContents->FindChildByName( fTreeItemFiles, fFileInfo.fFilename );
02806 fFileOnlineContents->OpenItem( fTreeItemFiles );
02807 DisplayFile( fTreeItemCurrent );
02808 fFileOnlineContents->OpenItem( fTreeItemCurrent );
02809 fFileOnlineContents->Resize();
02810 Layout();
02811 }
02812 #endif
02813
02814 void Roody::DisplayFile( TGListTreeItem *item )
02815 {
02816 TObject *tmp = static_cast<TObject*>(item->GetUserData());
02817 if( tmp->InheritsFrom(TFile::Class()) )DisplayFile( static_cast<TFile*>(tmp), item );
02818 #ifdef HAVE_HBOOK
02819 else if( tmp->InheritsFrom(THbookFile::Class()) )DisplayFile( static_cast<THbookFile*>(tmp), item );
02820 #endif
02821 }
02822
02823 #ifdef HAVE_HBOOK
02824 class MyTHbookKey: public THbookKey
02825 {
02826 public:
02827 int GetID() const { return fID; };
02828 };
02829 #endif
02830
02831 #ifdef HAVE_HBOOK
02832 void Roody::DisplayFile( THbookFile *file, TGListTreeItem *item )
02833 {
02834 fCurrentHbook = file;
02835 TIter next( file->GetListOfKeys() );
02836 MyTHbookKey *key;
02837 while( (key=static_cast<MyTHbookKey*>(next())) )
02838 {
02839 TObject *obj;
02840 if( (obj=file->Get( key->GetID())) )DisplayObject( obj, item, "" );
02841 Layout();
02842 }
02843 fFileOnlineCanvas->Layout();
02844 }
02845 #endif
02846
02847 void Roody::DisplayFile( TFile *file, TGListTreeItem *item )
02848 {
02849
02850
02851
02852
02853
02854
02855 fCurrentFile = file;
02856
02857 TString runNumber( GetRunNumber(file->GetName()) );
02858
02859
02860
02861
02862 TIter next( file->GetListOfKeys() );
02863 TKey *key = 0;
02864 Int_t nKeys = file->GetNkeys();
02865 if( nKeys > 1000 )
02866 {
02867 if( fOpeningFile )
02868 {
02869 Int_t nFolders = nKeys/250;
02870 if( nFolders*250 < nKeys )++nFolders;
02871 for( Int_t i=0; i<nFolders; ++i )
02872 {
02873 int start = i*250 + 1;
02874 int end = std::min(nKeys,(i+1)*250);
02875 std::string id1, id2;
02876 TGListTreeItem *groupFolder = fFileOnlineContents->AddItem( fTreeItemCurrent, " " );
02877 for( int j=start; j<=end; ++j )
02878 {
02879 TString hname = static_cast<TKey*>(next())->GetName();
02880 TObject *obj = file->Get( hname.Data() );
02881 if( obj )
02882 {
02883 DisplayObject( obj, groupFolder, runNumber.Data() );
02884 if( j == start )id1 = obj->GetName();
02885 if( j == end )id2 = obj->GetName();
02886 }
02887 }
02888 std::string name( id1 + " - " + id2 );
02889 groupFolder->Rename( name.c_str() );
02890 }
02891 fOpeningFile = false;
02892 }
02893 fFileOnlineContents->Resize();
02894 Layout();
02895 fParentDir->cd();
02896 }
02897 else
02898 {
02899 while( (key=static_cast<TKey*>(next())) )
02900 {
02901 TString name = key->GetName();
02902 TObject *obj = file->Get( name.Data() );
02903 if( obj )DisplayObject( obj, item, runNumber.Data() );
02904 Layout();
02905 }
02906 }
02907 fFileOnlineCanvas->Layout();
02908 }
02909
02910 TString Roody::GetRunNumber( char const *filename )
02911 {
02912 int end = strlen( filename );
02913 while( --end >= 0 )
02914 {
02915 if( filename[end] <= '9' && filename[end] >= '0' )break;
02916 }
02917 int begin = end;
02918 while( --begin >= 0 )
02919 {
02920 if( filename[begin] < '0' || filename[begin] > '9' )break;
02921 }
02922 ++begin;
02923 int len = end-begin+1;
02924 return TString( filename+begin, len );
02925 }
02926
02927 TObject *Roody::SearchDirectory( TDirectory *tdir, char const *histname )
02928 {
02929
02930
02931 TObject *obj = 0;
02932 TIter next( tdir->GetList() );
02933 while( (obj=next()) )
02934 {
02935 if( obj->InheritsFrom(TDirectory::Class()) )
02936 {
02937 if( (obj=SearchDirectory(static_cast<TDirectory*>(obj),histname)) )break;
02938 }
02939 if( TString(obj->GetName()) == TString(histname) )break;
02940 }
02941 return obj;
02942 }
02943
02944 void Roody::DisplayFile( TDirectory *tdir, TGListTreeItem *item )
02945 {
02946
02947
02948
02949 TIter next( tdir->GetListOfKeys() );
02950 TKey *key;
02951 while( (key=static_cast<TKey*>(next())) )
02952 {
02953 TObject *obj = tdir->Get( key->GetName() );
02954 if( obj )DisplayObject(obj,item,"");
02955 Layout();
02956 }
02957 fFileOnlineCanvas->Layout();
02958 }
02959
02960 void Roody::DisplayObject( TObject *obj, TGListTreeItem *item, char const *rn )
02961 {
02962 std::string className( obj->ClassName() );
02963 std::string name( obj->GetName() );
02964 std::string title( obj->GetTitle() );
02965 std::string itemDescription( name );
02966 std::string runNumber( rn );
02967 std::string file("file:");
02968 file += fCurrentFile->GetName();
02969
02970
02971
02972
02973
02974
02975
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987
02988
02989
02990
02991
02992
02993
02994
02995
02996
02997
02998
02999
03000
03001
03002
03003
03004
03005
03006
03007
03008
03009
03010
03011
03012 if( className.find("TH1") != className.npos )
03013 {
03014 if( title.find("Run#") == title.npos &&
03015 runNumber.find_first_not_of(" ") != runNumber.npos )
03016 {
03017 std::string s( title );
03018 s += " Run# ";
03019 s += runNumber;
03020 static_cast<TH1*>(obj)->SetTitle( s.c_str() );
03021 }
03022 if( name != title )
03023 {
03024 itemDescription += " ";
03025 itemDescription += title;
03026 }
03027 fFileOnlineContents->AddItem( item, itemDescription.c_str(),
03028 (void*)obj,
03029 gClient->GetPicture("h1_t.xpm"),
03030 gClient->GetPicture("h1_t.xpm") );
03031
03032
03033
03034
03035 static_cast<TH1*>(obj)->GetListOfFunctions()->Add( new TObjString(file.c_str()) );
03036 }
03037 else if( className.find("TH2") != className.npos )
03038 {
03039 if( title.find("Run#") == title.npos &&
03040 runNumber.find_first_not_of(" ") != runNumber.npos )
03041 {
03042 std::string s( title );
03043 s += " Run# ";
03044 s += runNumber;
03045 static_cast<TH2*>(obj)->SetTitle( s.c_str() );
03046 }
03047 if( name != title )
03048 {
03049 itemDescription += " ";
03050 itemDescription += title;
03051 }
03052 fFileOnlineContents->AddItem( item, itemDescription.c_str(),
03053 (void*)obj,
03054 gClient->GetPicture("h2_t.xpm"),
03055 gClient->GetPicture("h2_t.xpm") );
03056
03057
03058
03059
03060 static_cast<TH1*>(obj)->GetListOfFunctions()->Add( new TObjString(file.c_str()) );
03061 }
03062 else if( className.find("TH3") != className.npos )
03063 {
03064 if( title.find("Run#") == title.npos &&
03065 runNumber.find_first_not_of(" ") != runNumber.npos )
03066 {
03067 std::string s( title );
03068 s += " Run# ";
03069 s += runNumber;
03070 static_cast<TH3*>(obj)->SetTitle( s.c_str() );
03071 }
03072 if( name != title )
03073 {
03074 itemDescription += " ";
03075 itemDescription += title;
03076 }
03077 fFileOnlineContents->AddItem( item, itemDescription.c_str(),
03078 (void*)obj,
03079 gClient->GetPicture("h3_t.xpm"),
03080 gClient->GetPicture("h3_t.xpm") );
03081
03082
03083
03084
03085 static_cast<TH1*>(obj)->GetListOfFunctions()->Add( new TObjString(file.c_str()) );
03086 }
03087 else if( className.find("Folder") != className.npos )
03088 {
03089 TGListTreeItem *itemFound = fFileOnlineContents->FindChildByName( item, name.c_str() );
03090 if( !itemFound )
03091 {
03092 TGListTreeItem *folderItem = fFileOnlineContents->AddItem( item, name.c_str() );
03093 TCollection *folderList = static_cast<TFolder*>(obj)->GetListOfFolders();
03094 TIterator *iterator = folderList->MakeIterator();
03095 TObject *next = 0;
03096 while ( (next=iterator->Next()) )DisplayObject( next, folderItem, runNumber.c_str() );
03097 }
03098 }
03099 else if( className.find("Tree") != className.npos )
03100 fFileOnlineContents->AddItem( item, name.c_str(),
03101 (void*)obj,
03102 gClient->GetPicture("tree_t.xpm"),
03103 gClient->GetPicture("tree_t.xpm") );
03104 else if( className.find("Ntuple") != className.npos )
03105 fFileOnlineContents->AddItem( item, name.c_str(),
03106 (void*)obj,
03107 gClient->GetPicture("ntuple_t.xpm"),
03108 gClient->GetPicture("ntuple_t.xpm") );
03109 else if( className.find("Profile") != className.npos )
03110 {
03111 if( className.find("2D") != className.npos )
03112 fFileOnlineContents->AddItem( item, name.c_str(),
03113 (void*)obj,
03114 gClient->GetPicture("h2_t.xpm"),
03115 gClient->GetPicture("h2_t.xpm") );
03116 else
03117 fFileOnlineContents->AddItem( item, name.c_str(),
03118 (void*)obj,
03119 gClient->GetPicture("profile_t.xpm"),
03120 gClient->GetPicture("profile_t.xpm") );
03121 }
03122 else if( className.find("Directory") != className.npos )
03123 {
03124 TDirectory *d = static_cast<TDirectory *>(fCurrentFile->Get(name.c_str()));
03125 TGListTreeItem *folderItem = fFileOnlineContents->AddItem( item, name.c_str() );
03126 DisplayFile(d,folderItem);
03127 }
03128 else if( className.find("TCanvas") != className.npos )
03129 {
03130 fFileOnlineContents->AddItem( item, name.c_str(),
03131 (void*)obj,
03132 gClient->GetPicture("h1_t.xpm"),
03133 gClient->GetPicture("h1_t.xpm") );
03134 }
03135 else if( className.find("TCutG") != className.npos )
03136 {
03137 fFileOnlineContents->AddItem( item, name.c_str(),
03138 (void*)obj,
03139 gClient->GetPicture("cut_t.xpm"),
03140 gClient->GetPicture("cut_t.xpm") );
03141 }
03142 else
03143 {
03144 fFileOnlineContents->AddItem( item, name.c_str(),
03145 (void*)obj,
03146 gClient->GetPicture("diamond.xpm"),
03147 gClient->GetPicture("diamond.xpm") );
03148 }
03149 }
03150
03151 void Roody::ConnectServer( char const *host, Bool_t displayMsgBox )
03152 {
03153 Int_t port = 9090;
03154 std::string hostString( host );
03155 std::string hostname( host );
03156 std::string portname( "9090" );
03157 std::size_t colonLoc;
03158 if( (colonLoc=hostString.find(":")) != hostString.npos )
03159 {
03160 if( !colonLoc )
03161 {
03162 new TGMsgBox( gClient->GetRoot(), this, "Error", "A host name must be provided", kMBIconExclamation, 0, NULL );
03163 return;
03164 }
03165 hostname = hostString.substr( 0, colonLoc );
03166 portname = hostString.substr( colonLoc+1, hostString.size()-colonLoc-1 );
03167 port = 0;
03168 std::size_t portLen = portname.size();
03169 for( std::size_t i=0; i<portLen; ++i )
03170 {
03171 if( (static_cast<int>(portname[i]))>47 && static_cast<int>(portname[i])<58 )
03172 {
03173
03174 port *= 10;
03175 port += static_cast<int>(portname[i]) - 48;
03176 }
03177 }
03178 if( port == 0 )
03179 {
03180 port = 9090;
03181 portname = std::string("9090");
03182 }
03183 }
03184 std::string s( hostname+":"+portname );
03185 if( fFileOnlineContents->FindChildByName(fTreeItemOnline,s.c_str()) )
03186 {
03187 fStatusBar->SetText( TString("Already connected to ")+TString(s.c_str()) );
03188 return;
03189 }
03190 fSock = new TSocket( hostname.c_str(), port );
03191 if( !fSock || !fSock->IsValid() )
03192 {
03193 delete fSock;
03194 fSock = 0;
03195 if( displayMsgBox )
03196 {
03197 TString s("Cannot connect to Midas server on host ");
03198 s += TString(hostname.c_str()) + TString(", port ") + TString(portname.c_str());
03199 fStatusBar->SetText( s );
03200 new TGMsgBox( gClient->GetRoot(), this, "Error", s.Data(),
03201 kMBIconExclamation, 0, NULL );
03202 }
03203 }
03204 else
03205 {
03206 fHostName = TString( hostname.c_str() );
03207 fPortName = TString( portname.c_str() );
03208 fStatusBar->SetText( TString("Connected to ")+fHostName+TString(":")+fPortName );
03209 AddOnlineEntryTreeView();
03210 fRefreshButton->SetEnabled(kTRUE);
03211 if( fUpdateTimerSec > 0 )
03212 {
03213 std::stringstream str;
03214 str << " Pause Refresh (" << fUpdateTimerSec << ") ";
03215 fRefreshButton->SetText( str.str().c_str() );
03216 fRefreshButton->SetToolTipText( "click to PAUSE refresh of online histograms", 250 );
03217 }
03218 else
03219 {
03220 fRefreshButton->SetText( " Refresh NOW " );
03221 fRefreshButton->SetToolTipText( "click to refresh online histograms once right now", 250 );
03222 }
03223 }
03224 }
03225
03226 void Roody::AddOnlineEntryTreeView()
03227 {
03228 TString s( fHostName + TString(":") + fPortName );
03229 fFileOnlineContents->AddItem( fTreeItemOnline, s.Data(), (void*)fSock );
03230 fTreeItemCurrent = fFileOnlineContents->FindChildByName( fTreeItemOnline, s.Data() );
03231 fFileOnlineContents->OpenItem( fTreeItemOnline );
03232 GetHistList( fTreeItemCurrent );
03233 fFileOnlineContents->OpenItem( fTreeItemCurrent );
03234 fFileOnlineContents->Resize();
03235 Layout();
03236 }
03237
03238 TObjArray* Roody::GetHistList( TSocket *sock )
03239 {
03240 TObjArray *tmp = 0;
03241 TMessage *m;
03242 if( sock && sock->IsValid() )
03243 {
03244 sock->Send("LIST");
03245 if( sock->Recv(m) )
03246 {
03247 tmp = static_cast<TObjArray*>(m->ReadObject(m->GetClass()));
03248 delete m;
03249 }
03250 }
03251 return tmp;
03252 }
03253
03254 void Roody::GetHistList( TGListTreeItem *item, char const *folderName )
03255 {
03256 if( !fSock )return;
03257 TNetFolder *netFolder = new TNetFolder( folderName, "online histos", fSock );
03258 if( !netFolder )
03259 {
03260 new TGMsgBox( gClient->GetRoot(), this, "Error", "TNetFolder not made", kMBIconExclamation, 0, NULL );
03261 return;
03262 }
03263 TObjArray *fNames = netFolder->GetListOfFolders();
03264 if( !fNames )
03265 {
03266 new TGMsgBox( gClient->GetRoot(), this, "Error", "list of folders not made", kMBIconExclamation, 0, NULL );
03267 return;
03268 }
03269 int nNames = fNames->GetLast();
03270 if( fHistNames )delete fHistNames;
03271 fHistNames = new TObjArray( fNames->GetLast()+1 );
03272 while( item->GetFirstChild() )
03273 {
03274 delete static_cast<TObject*>(item->GetFirstChild()->GetUserData());
03275
03276 fFileOnlineContents->MDeleteItem( item->GetFirstChild() );
03277 }
03278 for( int i=0; i<=nNames; ++i )
03279 {
03280 TObjString *oName = static_cast<TObjString*>(fNames->At(i));
03281 std::string name( oName->GetString().Data() );
03282 TGListTreeItem *found = fFileOnlineContents->FindChildByName( item, name.c_str() );
03283 TObject *object = netFolder->FindObjectAny( name.c_str() );
03284 if( !object )
03285 {
03286 std::string s("object \"");
03287 s += name + "\" not found in net folder \"" + folderName + "\"";
03288 new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
03289 return;
03290 }
03291 std::string title( object->GetTitle() );
03292 std::string itemDescription( name );
03293 if( name != title )
03294 {
03295 itemDescription += std::string(" ");
03296 itemDescription += title;
03297 }
03298 TString *type = new TString(object->ClassName());
03299 if( type && type->Contains("TH1") && !found )
03300 {
03301 fFileOnlineContents->AddItem( item, itemDescription.c_str(),
03302 (void*)new TObjString(name.c_str()),
03303 gClient->GetPicture("h1_t.xpm"),
03304 gClient->GetPicture("h1_t.xpm") );
03305 }
03306 else if( type && type->Contains("TH2") && !found )
03307 {
03308 fFileOnlineContents->AddItem( item, itemDescription.c_str(),
03309 (void*)new TObjString(name.c_str()),
03310 gClient->GetPicture("h2_t.xpm"),
03311 gClient->GetPicture("h2_t.xpm") );
03312 }
03313 else if( type && type->Contains("TH3") && !found )
03314 {
03315 fFileOnlineContents->AddItem( item, itemDescription.c_str(),
03316 (void*)new TObjString(name.c_str()),
03317 gClient->GetPicture("h3_t.xpm"),
03318 gClient->GetPicture("h3_t.xpm") );
03319 }
03320 else if( type && type->Contains("TProfile") && !found )
03321 {
03322 if( type->Contains("2D") )
03323 fFileOnlineContents->AddItem( item, itemDescription.c_str(),
03324 (void*)new TObjString(name.c_str()),
03325 gClient->GetPicture("h2_t.xpm"),
03326 gClient->GetPicture("h2_t.xpm") );
03327 else
03328 fFileOnlineContents->AddItem( item, itemDescription.c_str(),
03329 (void*)new TObjString(name.c_str()),
03330 gClient->GetPicture("profile_t.xpm"),
03331 gClient->GetPicture("profile_t.xpm") );
03332 }
03333 else if( type && type->Contains("TCutG") && !found )
03334 {
03335 fFileOnlineContents->AddItem( item, itemDescription.c_str(),
03336 (void*)new TObjString(name.c_str()),
03337 gClient->GetPicture("cut_t.xpm"),
03338 gClient->GetPicture("cut_t.xpm") );
03339 }
03340 else if( type && type->Contains("Folder") && !found )
03341 {
03342 TGListTreeItem *folderItem = fFileOnlineContents->AddItem( item, name.c_str() );
03343 GetHistList( folderItem, name.c_str() );
03344 }
03345 else if( type && !found )
03346 {
03347 std::cout << "Unexpected Type: " << type->Data() << std::endl;
03348 }
03349 if( type )delete type;
03350 }
03351 delete netFolder;
03352 delete fNames;
03353 fFileOnlineContents->Resize();
03354 }
03355
03356 TObject *Roody::GetNetFolderObject( char const *itemName, char const *folderName )
03357 {
03358 TNetFolder netFolder( folderName, "online histos", fSock );
03359 TObject *object = netFolder.FindObjectAny( itemName );
03360 if( !object )
03361 {
03362 TObjArray *names = 0;
03363 if( (names=netFolder.GetListOfFolders()) )
03364 {
03365 int nNames = names->GetLast();
03366 for( int i=0; i<=nNames; ++i )
03367 {
03368 char const *folderName = static_cast<TObjString*>(names->At(i))->GetString().Data();
03369 if( TString(names->At(i)->ClassName()).Contains("TNetFolder") )
03370 {
03371 object = GetNetFolderObject( itemName, folderName );
03372 if( object )break;
03373 }
03374 }
03375 }
03376 }
03377 return object;
03378 }
03379
03380 void Roody::DrawOnlineObject( TObjString *objString )
03381 {
03382 TObject *object = GetNetFolderObject( objString->GetString().Data() );
03383 if( !object )return;
03384 if( object->InheritsFrom(TH1::Class()) )
03385 {
03386 MarkObjectAsOnline(object);
03387 DrawObject( object );
03388 }
03389 else if( object->InheritsFrom(TCutG::Class()) )
03390 {
03391 DrawObject( object );
03392 }
03393 else
03394 {
03395 std::cout << "DrawOnlineObject: encountered a " << object->ClassName()
03396 << ", this was unexpected" << std::endl;
03397 }
03398 }
03399
03400 void Roody::StartOnlineTimer()
03401 {
03402 fMenuRefresh->UnCheckEntry(M_REFRESH_OFF);
03403 fMenuRefresh->UnCheckEntry(M_REFRESH_NOW);
03404 fMenuRefresh->UnCheckEntry(M_REFRESH_1SEC);
03405 fMenuRefresh->UnCheckEntry(M_REFRESH_3SEC);
03406 fMenuRefresh->UnCheckEntry(M_REFRESH_5SEC);
03407 fMenuRefresh->UnCheckEntry(M_REFRESH_10SEC);
03408 if( fUpdateTimerSec > 0 )
03409 {
03410 fUpdateTimer->SetTime(fUpdateTimerSec*1000);
03411 fUpdateTimer->Start();
03412 switch( fUpdateTimerSec )
03413 {
03414 case 1: fMenuRefresh->CheckEntry( M_REFRESH_1SEC ); break;
03415 case 3: fMenuRefresh->CheckEntry( M_REFRESH_3SEC ); break;
03416 case 5: fMenuRefresh->CheckEntry( M_REFRESH_5SEC ); break;
03417 case 10: fMenuRefresh->CheckEntry( M_REFRESH_10SEC ); break;
03418 }
03419 }
03420 else
03421 {
03422 fMenuRefresh->CheckEntry( M_REFRESH_OFF );
03423 fUpdateTimer->Stop();
03424 }
03425 }
03426
03427 void Roody::UpdateHistograms()
03428 {
03429 if( fSock )
03430 {
03431 fUpdateTimer->Stop();
03432 if( fSock->GetLocalPort() == -1 )
03433 {
03434 CloseOnline();
03435 fOnlineAborted = kTRUE;
03436 fUpdateTimer->SetTime(1000);
03437 fUpdateTimer->Start();
03438 }
03439 else
03440 {
03441 if( fUpdateTimerSec > 0 )
03442 {
03443 TIter next( gROOT->GetListOfCanvases() );
03444 TCanvas *canvas;
03445 while( (canvas=static_cast<TCanvas*>(next())) )UpdateHistograms( static_cast<TPad*>(canvas) );
03446 }
03447 }
03448 fUpdateTimer->Start();
03449 }
03450 else
03451 {
03452 if( fOnlineAborted )
03453 {
03454 ConnectServer( (fHostName+":"+fPortName).Data(), kFALSE );
03455 if( fSock )
03456 {
03457 fOnlineAborted = kFALSE;
03458 StartOnlineTimer();
03459 }
03460 }
03461 }
03462 }
03463
03464 void Roody::UpdateHistograms( TPad *pad )
03465 {
03466
03467 TIter padNext( pad->GetListOfPrimitives() );
03468 std::vector<TH1*> histVec;
03469 TObject *padObject;
03470 bool first = true;
03471 while( (padObject=static_cast<TObject*>(padNext())) )
03472 {
03473 if( padObject && padObject->InheritsFrom(TPad::Class()) )
03474 {
03475 UpdateHistograms( static_cast<TPad*>(padObject) );
03476 }
03477 else if( padObject && padObject->InheritsFrom(TH1::Class()) )
03478 {
03479 TH1 *hist = static_cast<TH1*>(padObject);
03480 if( ObjectIsOnline(padObject) )
03481 {
03482 TObject *netObject = GetNetFolderObject(padObject->GetName());
03483 if( !netObject )return;
03484
03485
03486
03487
03488
03489 Int_t xfirst = hist->GetXaxis()->GetFirst();
03490 Int_t xlast = hist->GetXaxis()->GetLast();
03491
03492 Color_t color = hist->GetLineColor();
03493 pad->GetListOfPrimitives()->Remove( static_cast<TObject*>(hist) );
03494 delete hist;
03495
03496 hist = static_cast<TH1*>(netObject);
03497 hist->SetLineColor( color );
03498 if( first )
03499 {
03500 first = false;
03501
03502
03503
03504 hist->GetXaxis()->SetRange( xfirst, xlast );
03505
03506
03507
03508 CanvasLimits *limits = FindCanvasLimits(pad->GetCanvas()->GetCanvasID());
03509 if (limits)
03510 limits->ApplyLimits(hist);
03511 }
03512 MarkObjectAsOnline(hist);
03513 histVec.push_back( hist );
03514 }
03515 }
03516 }
03517 if( histVec.empty() )return;
03518 gPad = pad;
03519 TH1* h = SetCanvasLimits( pad->GetCanvas(), histVec[0] );
03520 h->Draw();
03521 std::vector<TH1*>::const_iterator end = histVec.end();
03522 for( std::vector<TH1*>::const_iterator i=histVec.begin()+1; i!=end; ++i )
03523 {
03524 h = SetCanvasLimits(pad->GetCanvas(),(*i));
03525 h->Draw("SAME");
03526 }
03527 pad->GetCanvas()->Modified();
03528 pad->GetCanvas()->Update();
03529 }
03530
03531 void Roody::OpenRefreshDialog()
03532 {
03533 std::auto_ptr<TObjString> objString(new TObjString());
03534 new TGTextDialog( gClient->GetRoot(), this, 100, 100,
03535 "Refresh time in seconds: ", "", objString.get() );
03536 TString refreshString = objString->GetString();
03537 if( refreshString.Contains("-1") )fStatusBar->SetText( "Refresh not changed");
03538 else SetRefreshRate(atoi(refreshString.Data()));
03539 }
03540
03541 void Roody::OpenZoneDialog()
03542 {
03543 std::auto_ptr<TObjString> objString( new TObjString() );
03544 new TGTextDialog( gClient->GetRoot(), this, 100, 100,
03545 "Zone Setting: (columns x rows, e.g. 2x2): ", "", objString.get() );
03546 TString zoneString = objString->GetString();
03547 if( zoneString.Contains("-1") )
03548 {
03549 fStatusBar->SetText( "Zone status not changed");
03550 return;
03551 }
03552 int columns, rows;
03553 std::string s( zoneString.Data() );
03554 std::size_t x = s.find("x");
03555 if( x == s.npos )
03556 {
03557 columns = 1;
03558 rows = 1;
03559 }
03560 else
03561 {
03562 if( !StringTo<int>(columns,s.substr(0,x),std::dec) )
03563 {
03564 columns = 1;
03565 std::string err( "invalid number of columns: \"" );
03566 err += s.substr(0,x) + "\"\n" + "columns set to 1\n";
03567 new TGMsgBox( gClient->GetRoot(), this, "Error", err.c_str(), kMBIconExclamation, 0, NULL );
03568 }
03569 if( !StringTo<int>(rows,s.substr(x+1,s.size()-x-1),std::dec) )
03570 {
03571 rows = 1;
03572 std::string err( "invalid number of rows: \"" );
03573 err += s.substr(x+1,s.size()-x-1) + "\"\n" + "rows set to 1\n";
03574 new TGMsgBox( gClient->GetRoot(), this, "Error", err.c_str(), kMBIconExclamation, 0, NULL );
03575 }
03576 }
03577
03578
03579
03580
03581 SetupZones( columns, rows );
03582 SetupZonesMenu();
03583 }
03584
03585 void Roody::OpenSaveDialog()
03586 {
03587 fFileInfo.fFilename = 0;
03588 char const *fileTypes[] = {"Save file","*.xml","Any file","*",0,0};
03589 fFileInfo.fFileTypes = fileTypes;
03590
03591
03592
03593 new TGFileDialog( fClient->GetRoot(), this, kFDOpen, &fFileInfo);
03594 TString savefileName = fFileInfo.fFilename;
03595 if( savefileName.Contains("-1") )
03596 {
03597 fStatusBar->SetText( "NO FILE SELECTED" );
03598 }
03599 else
03600 {
03601 if( !savefileName.Contains(".xml") )savefileName += ".xml";
03602 fStatusBar->SetText("Saving session: " + savefileName);
03603 SaveFile( savefileName.Data() );
03604 }
03605 }
03606
03607 void Roody::OpenRestoreDialog()
03608 {
03609 fFileInfo.fFilename = 0;
03610 char const *fileTypes[] = {"Save file","*.xml","Any file","*",0,0};
03611 fFileInfo.fFileTypes = fileTypes;
03612 new TGFileDialog( fClient->GetRoot(), this, kFDOpen, &fFileInfo );
03613 if( fFileInfo.fFilename )
03614 {
03615 RestoreFile( fFileInfo.fFilename );
03616 }
03617 else
03618 {
03619 fStatusBar->SetText( "NO FILE SELECTED" );
03620 }
03621 }
03622
03623