#include #include "TH2Viewer.h" #include "TStyle.h" #include "TROOT.h" #include "TH1F.h" #include "TH2.h" #include "TCanvas.h" #include "TRootEmbeddedCanvas.h" #include "TGStatusBar.h" #include "TGNumberEntry.h" #include "TGButton.h" #include "TGLabel.h" #include "TGSlider.h" #include "TGDoubleSlider.h" #include "TMath.h" #include "TFrame.h" #include "TBox.h" #include using std::cout; using std::endl; const UInt_t kWidth=800; /// h2s) : TGMainFrame(gClient->GetRoot(), 100, 100), fCanvas2(NULL), fCanvasX(NULL), fCanvasY(NULL), fH2(h2s), fBorderBox(new TBox()), fCurrent2(-1), fCurrentX(-1), fCurrentY(-1) { const UShort_t size = fH2.size(); if(!size) return; const UShort_t nX = fH2[0]->GetNbinsX(); const UShort_t nY = fH2[1]->GetNbinsY(); for(auto h2 : fH2) { if(h2->GetNbinsX()!=nX || h2->GetNbinsY()!=nY) return; } fHx.resize(fH2.size()); fHy.resize(fH2.size()); for(UShort_t i=0;iSetCanvasPreferGL();//NEEDED for fast drawing. gStyle->SetOptStat(0); gStyle->SetNumberContours(255);//2D gStyle->SetPadTopMargin(0.05); gStyle->SetPadRightMargin(0.05); gStyle->SetPadBottomMargin(0.05); gStyle->SetPadLeftMargin(0.05); fBorderBox->SetFillStyle(0); fBorderBox->SetFillColor(0); fBorderBox->SetLineWidth(3); fBorderBox->SetLineStyle(2); fBorderBox->SetLineColor(6); fVertical = new TGVerticalFrame(this); fRow1 = new TGHorizontalFrame(fVertical); fRow2 = new TGHorizontalFrame(fVertical); //Create Canvas fCanvas2 = new TRootEmbeddedCanvas(kCanvas2Name,fRow1,kWidth,kHeight); //~ fCanvas2->GetCanvas()->Connect("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)", "TH2Viewer", //~ this, "CaptureEvent(Int_t,Int_t,Int_t,TObject*)"); fRow1->AddFrame(fCanvas2, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2)); fCanvasY = new TRootEmbeddedCanvas(kCanvasyName,fRow1,kWidth,kHeight); //~ fCanvasY->GetCanvas()->Connect("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)", "TH2Viewer", //~ this, "CaptureEvent(Int_t,Int_t,Int_t,TObject*)"); fRow1->AddFrame(fCanvasY, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2)); fCanvasX = new TRootEmbeddedCanvas(kCanvasxName,fRow2,kWidth,kHeight); //~ fCanvasY->GetCanvas()->Connect("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)", "TH2Viewer", //~ this, "CaptureEvent(Int_t,Int_t,Int_t,TObject*)"); fRow2->AddFrame(fCanvasX, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2)); //~ TH1D *haxis1 = new TH1D("h", "h", 100, 0, 500); //~ TPad *pad1; //~ TPad *pad2; //~ TPad *pad3; //~ TPad *pad4; //~ pad1 = new TPad("pad1","pad1",0,0.3,1,1); //~ pad2 = new TPad("pad2","pad2",0,0,1,0.3); //~ pad3 = new TPad("pad3","pad3",0,0.3,1,1); //~ pad4 = new TPad("pad4","pad4",0,0,1,0.3); //~ //Event status bar below Canvas //~ Int_t parts[] = {45, 15, 10, 30}; //~ fStatusBar = new TGStatusBar(this, 2, 2, kVerticalFrame); //~ fStatusBar->SetParts(parts, 4); //~ fStatusBar->Draw3DCorner(kFALSE); //~ AddFrame(fStatusBar, new TGLayoutHints(kLHintsExpandX, 2, 2, 2, 2)); fHistList = new TGVerticalFrame(fRow2); for(UShort_t i=0;iGetColor(CColorTable[i%11])->GetPixel()); TGRadioButton* rb = new TGRadioButton(histline, "", i); //rb->SetState(kButtonDown); rb->Connect("Clicked()", "TH2Viewer", this, "DoRadio()"); histline->AddFrame(rb, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2)); fSelect2.push_back(rb); TGCheckButton* cb = new TGCheckButton(histline,new TGHotString(fH2[i]->GetTitle()),-1); //cb->SetState(kButtonDown); cb->Connect("Clicked()", "TH2Viewer", this, "RedrawX()"); cb->Connect("Clicked()", "TH2Viewer", this, "RedrawY()"); histline->AddFrame(cb, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));//padleft, padright, padtop, padbottom fSelect1.push_back(cb); fHistList->AddFrame(histline, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2)); } fBorderX = new TextedDoubleSlider(fHistList, 190, kDoubleScaleBoth, 0, kHorizontalFrame, fHistList->GetBackground(), 0, nX-1, 0, nX-1, kFALSE, "X borders"); fHistList->AddFrame(fBorderX, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2)); fBorderX->GetSlider()->Connect("PositionChanged()","TH2Viewer",this,"RedrawY()"); fBorderX->GetSlider()->Connect("PositionChanged()","TH2Viewer",this,"RedrawBorderBox()"); fBorderY = new TextedDoubleSlider(fHistList, 190, kDoubleScaleBoth, 0, kHorizontalFrame, fHistList->GetBackground(), 0, nY-1, 0, nY-1, kFALSE, "Y borders"); fHistList->AddFrame(fBorderY, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2)); fBorderY->GetSlider()->Connect("PositionChanged()","TH2Viewer",this,"RedrawX()"); fBorderY->GetSlider()->Connect("PositionChanged()","TH2Viewer",this,"RedrawBorderBox()"); fZoomX = new TextedDoubleSlider(fHistList, 190, kDoubleScaleBoth, 0, kHorizontalFrame, fHistList->GetBackground(), 0, nX-1, 0, nX-1, kFALSE, "X zoom"); fHistList->AddFrame(fZoomX, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2)); fZoomX->GetSlider()->Connect("PositionChanged()","TH2Viewer",this,"ZoomX()"); fZoomY = new TextedDoubleSlider(fHistList, 190, kDoubleScaleBoth, 0, kHorizontalFrame, fHistList->GetBackground(), 0, nY-1, 0, nY-1, kFALSE, "Y zoom"); fHistList->AddFrame(fZoomY, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2)); fZoomY->GetSlider()->Connect("PositionChanged()","TH2Viewer",this,"ZoomY()"); fRow2->AddFrame(fHistList, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2)); fVertical->AddFrame(fRow1, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2)); fVertical->AddFrame(fRow2, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2)); AddFrame(fVertical, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2)); //Map all windows SetWindowName("TH2Viewer"); MapSubwindows(); Resize(GetDefaultSize()); MapWindow(); } TH2Viewer::~TH2Viewer() { } void TH2Viewer::CloseWindow() { // Called when window is closed via the window manager. delete this; } /* void TH2Viewer::CaptureEvent(Int_t event, Int_t px, Int_t py, TObject *sel) { // Writes the event status in the status bar parts fStatusBar->SetText(sel->GetTitle(),0); fStatusBar->SetText(sel->GetName(),1); if (event == kKeyPress) { fStatusBar->SetText(Form("%c", (char) px),2); fStatusBar->SetText(Form("0x%x", py),3); } else { fStatusBar->SetText(Form("%d,%d", px, py),2); fStatusBar->SetText(sel->GetObjectInfo(px,py),3); } //~ if(event==kWheelUp && !(TString(sel->IsA()->GetName())=="TAxis") && !(TString(sel->IsA()->GetName())=="TH2I"))//not when zooming axis //~ { //~ ReadNextPulse(); //~ fCanvas->GetCanvas()->Update(); //~ } //~ else if(event==kWheelDown && !(TString(sel->IsA()->GetName())=="TAxis") && !(TString(sel->IsA()->GetName())=="TH2I"))//not when zooming axis //~ { //~ ReadPreviousPulse(); //~ fCanvas->GetCanvas()->Update(); //~ } //~ else }*/ void TH2Viewer::DoRadio() { // Handle radio buttons. TGButton *btn = (TGButton *) gTQSender; Int_t id = btn->WidgetId(); for (UShort_t i = 0; i < fSelect2.size(); i++) { if (fSelect2[i]->WidgetId() != id) fSelect2[i]->SetState(kButtonUp); } Redraw2D(id); } void TH2Viewer::Redraw2D(const UShort_t id) { if(id>=fH2.size()) return; TCanvas* c = fCanvas2->GetCanvas(); c->cd(); fH2[id]->Draw("COLZ"); fCurrent2 = id; RedrawBorderBox(); c->Modified(); c->Update(); } void TH2Viewer::RedrawBorderBox() { if(fCurrent2>=0&&fCurrent2<(Short_t)fH2.size()) { TCanvas* c = fCanvas2->GetCanvas(); c->cd(); TH2* h2 = fH2[fCurrent2]; fBorderBox->SetX1(h2->GetXaxis()->GetBinLowEdge(fBorderX->GetMinNumberEntry()->GetNumber()+1)); fBorderBox->SetX2(h2->GetXaxis()->GetBinLowEdge(fBorderX->GetMaxNumberEntry()->GetNumber()+2)); fBorderBox->SetY1(h2->GetYaxis()->GetBinLowEdge(fBorderY->GetMinNumberEntry()->GetNumber()+1)); fBorderBox->SetY2(h2->GetYaxis()->GetBinLowEdge(fBorderY->GetMaxNumberEntry()->GetNumber()+2)); fBorderBox->Draw(); } } void TH2Viewer::RedrawX() { TCanvas* c = fCanvasX->GetCanvas(); c->cd(); bool first = true; for(UShort_t i=0;iGetState() == kButtonDown) { h = fH2[i]->ProjectionX((TString)fH2[i]->GetName()+"_px",fBorderY->GetMinNumberEntry()->GetNumber()+1,fBorderY->GetMaxNumberEntry()->GetNumber()+1); h->SetLineColor(CColorTable[i%11]); h->Draw(first?"":"same"); if(first) fCurrentX = i; first = false; } fHx[i]=h; } ZoomX(); c->Modified(); c->Update(); } void TH2Viewer::ZoomX() { if(fCurrent2>=0&&fCurrent2<(Short_t)fH2.size()) { fH2[fCurrent2]->GetXaxis()->SetRange(fZoomX->GetMinNumberEntry()->GetNumber()+1,fZoomX->GetMaxNumberEntry()->GetNumber()+1); fCanvas2->GetCanvas()->Modified(); fCanvas2->GetCanvas()->Update(); } if(fCurrentX>=0&&fCurrentX<(Short_t)fHx.size()) { fHx[fCurrentX]->GetXaxis()->SetRange(fZoomX->GetMinNumberEntry()->GetNumber()+1,fZoomX->GetMaxNumberEntry()->GetNumber()+1); fCanvasX->GetCanvas()->Modified(); fCanvasX->GetCanvas()->Update(); } } void TH2Viewer::RedrawY() { TCanvas* c = fCanvasY->GetCanvas(); c->cd(); bool first = true; for(UShort_t i=0;iGetState() == kButtonDown) { h = fH2[i]->ProjectionY((TString)fH2[i]->GetName()+"_py",fBorderX->GetMinNumberEntry()->GetNumber()+1,fBorderX->GetMaxNumberEntry()->GetNumber()+1); h->SetLineColor(CColorTable[i%11]); h->Draw(first?"":"same"); if(first) fCurrentY = i; first = false; } fHy[i]=h; } ZoomY(); c->Modified(); c->Update(); } void TH2Viewer::ZoomY() { if(fCurrent2>=0&&fCurrent2<(Short_t)fH2.size()) { fH2[fCurrent2]->GetYaxis()->SetRange(fZoomY->GetMinNumberEntry()->GetNumber()+1,fZoomY->GetMaxNumberEntry()->GetNumber()+1); fCanvas2->GetCanvas()->Modified(); fCanvas2->GetCanvas()->Update(); } if(fCurrentY>=0&&fCurrentY<(Short_t)fHy.size()) { fHy[fCurrentY]->GetXaxis()->SetRange(fZoomY->GetMinNumberEntry()->GetNumber()+1,fZoomY->GetMaxNumberEntry()->GetNumber()+1); fCanvasY->GetCanvas()->Modified(); fCanvasY->GetCanvas()->Update(); } } TextedHSlider::TextedHSlider(const TGWindow* p, UInt_t w, UInt_t type, Int_t id, UInt_t options, Pixel_t back, const Double_t start, const Double_t end, const Double_t position, Bool_t isReal) { if(!isReal) { fSlider = new TGHSlider(p,w,type,id,options,back); fSlider->SetRange(start,end); fSlider->SetPosition(position); fSlider->Connect("PositionChanged(Int_t)", "TextedHSlider", this, "MoveNumber(Int_t)"); if(start>=0) { fNumber = new TGNumberEntry(p,start,TMath::Log(end)/TMath::Log(10), 0, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, start, end); } else { fNumber = new TGNumberEntry(p,start,TMath::Log(end)/TMath::Log(10), 0, TGNumberFormat::kNESInteger, TGNumberFormat::kNEAAnyNumber, TGNumberFormat::kNELLimitMinMax, start, end); } fNumber->SetNumber(position); fNumber->Connect("ValueSet(Long_t)", "TextedHSlider", this, "MoveSlider()"); } else { fSlider = new TGHSlider(p,w,type,id,options,back); fSlider->SetRange(start*1000,end*1000); fSlider->SetPosition(position*1000); fSlider->Connect("PositionChanged(Int_t)", "TextedHSlider", this, "MoveRealThreeNumber(Int_t)"); fNumber = new TGNumberEntry(p,start,5, 0, TGNumberFormat::kNESRealThree, TGNumberFormat::kNEAAnyNumber, TGNumberFormat::kNELLimitMinMax, start, end); fNumber->SetNumber(position); fNumber->Connect("ValueSet(Long_t)", "TextedHSlider", this, "MoveRealThreeSlider()"); } } TextedHSlider::~TextedHSlider() { } TGHSlider* TextedHSlider::GetSlider() { return fSlider; } TGNumberEntry* TextedHSlider::GetNumberEntry() { return fNumber; } void TextedHSlider::MoveSlider() { fSlider->SetPosition(fNumber->GetNumber()); fSlider->PositionChanged(fNumber->GetNumber()); } void TextedHSlider::MoveRealThreeSlider() { fSlider->SetPosition(TMath::Nint(fNumber->GetNumber()*1000)); fSlider->PositionChanged(TMath::Nint(fNumber->GetNumber()*1000)); } void TextedHSlider::MoveNumber(Int_t pos) { fNumber->SetNumber(pos); //DO not emit signal, otherwise infinite loop } void TextedHSlider::MoveRealThreeNumber(Int_t pos) { fNumber->SetNumber(pos/1000.); //DO not emit signal, otherwise infinite loop } TextedDoubleSlider::TextedDoubleSlider(TGVerticalFrame* const p, UInt_t w, UInt_t type, Int_t id, UInt_t options, Pixel_t back, const Double_t start, const Double_t end, const Double_t minPosition, const Double_t maxPosition, Bool_t isReal, const TString label) : TGHorizontalFrame(p), fLabel(nullptr) { if(label) { fLabel = new TGLabel(this,label); fLabel->ChangeOptions(fLabel->GetOptions() | kFixedSize); fLabel->Resize(75, 20); AddFrame(fLabel, new TGLayoutHints(kLHintsNormal,2,2,1,1)); } if(!isReal) { fSlider = new TGDoubleHSlider(this,w,type,id,options,back); fSlider->SetRange(start,end); fSlider->SetPosition(minPosition,maxPosition); fSlider->Connect("PositionChanged()", "TextedDoubleSlider", this, "MoveNumbers()"); if(start>=0) { fMinNumber = new TGNumberEntry(this,start,TMath::Log(end)/TMath::Log(10), 0, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, start, end); fMaxNumber = new TGNumberEntry(this,start,TMath::Log(end)/TMath::Log(10), 0, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, start, end); } else { fMinNumber = new TGNumberEntry(this,start,TMath::Log(end)/TMath::Log(10), 0, TGNumberFormat::kNESInteger, TGNumberFormat::kNEAAnyNumber, TGNumberFormat::kNELLimitMinMax, start, end); fMaxNumber = new TGNumberEntry(this,start,TMath::Log(end)/TMath::Log(10), 0, TGNumberFormat::kNESInteger, TGNumberFormat::kNEAAnyNumber, TGNumberFormat::kNELLimitMinMax, start, end); } fMinNumber->SetNumber(minPosition); fMaxNumber->SetNumber(maxPosition); fMinNumber->Connect("ValueSet(Long_t)", "TextedDoubleSlider", this, "MoveSlider()"); fMaxNumber->Connect("ValueSet(Long_t)", "TextedDoubleSlider", this, "MoveSlider()"); } else { fSlider = new TGDoubleHSlider(this,w,type,id,options,back); fSlider->SetRange(start*1000,end*1000); fSlider->SetPosition(minPosition*1000,maxPosition*1000); fSlider->Connect("PositionChanged()", "TextedDoubleSlider", this, "MoveRealThreeNumbers()"); fMinNumber = new TGNumberEntry(this,start,5, 0, TGNumberFormat::kNESRealThree, TGNumberFormat::kNEAAnyNumber, TGNumberFormat::kNELLimitMinMax, start, end); fMinNumber->SetNumber(minPosition); fMinNumber->Connect("ValueSet(Long_t)", "TextedDoubleSlider", this, "MoveRealThreeSlider()"); fMaxNumber = new TGNumberEntry(this,start,5, 0, TGNumberFormat::kNESRealThree, TGNumberFormat::kNEAAnyNumber, TGNumberFormat::kNELLimitMinMax, start, end); fMaxNumber->SetNumber(maxPosition); fMaxNumber->Connect("ValueSet(Long_t)", "TextedDoubleSlider", this, "MoveRealThreeSlider()"); } GetMinNumberEntry()->Resize(75,22); GetMaxNumberEntry()->Resize(75,22); AddFrame(GetMinNumberEntry(), new TGLayoutHints(kLHintsTop , 2, 2, 1, 1)); AddFrame(GetSlider(), new TGLayoutHints(kLHintsTop | kLHintsExpandX, 2, 2, 1, 1)); AddFrame(GetMaxNumberEntry(), new TGLayoutHints(kLHintsTop , 2, 2, 1, 1)); } TextedDoubleSlider::~TextedDoubleSlider() { } TGDoubleSlider* TextedDoubleSlider::GetSlider() { return fSlider; } TGNumberEntry* TextedDoubleSlider::GetMinNumberEntry() { return fMinNumber; } TGNumberEntry* TextedDoubleSlider::GetMaxNumberEntry() { return fMaxNumber; } void TextedDoubleSlider::MoveSlider() { if(fMinNumber->GetNumber()>fMaxNumber->GetNumber()) { const double aux = fMinNumber->GetNumber(); fMinNumber->SetNumber(fMaxNumber->GetNumber()); fMaxNumber->SetNumber(aux); } fSlider->SetPosition(fMinNumber->GetNumber(),fMaxNumber->GetNumber()); fSlider->PositionChanged(); } void TextedDoubleSlider::MoveRealThreeSlider() { fSlider->SetPosition(TMath::Nint(fMinNumber->GetNumber()*1000),TMath::Nint(fMaxNumber->GetNumber()*1000)); fSlider->PositionChanged(); } void TextedDoubleSlider::MoveNumbers() { fMinNumber->SetNumber(fSlider->GetMinPosition()); fMaxNumber->SetNumber(fSlider->GetMaxPosition()); //DO not emit signal, otherwise infinite loop } void TextedDoubleSlider::MoveRealThreeNumbers() { fMinNumber->SetNumber(fSlider->GetMinPosition()/1000.); fMaxNumber->SetNumber(fSlider->GetMaxPosition()/1000.); //DO not emit signal, otherwise infinite loop }