#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 "TPaletteAxis.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), fBorderBoxX(new TBox()), fBorderBoxY(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.07); gStyle->SetPadBottomMargin(0.07); gStyle->SetPadLeftMargin(0.07); fBorderBoxX->SetFillStyle(0); fBorderBoxX->SetFillColor(0); fBorderBoxX->SetLineWidth(3); fBorderBoxX->SetLineStyle(2); fBorderBoxX->SetLineColor(6); fBorderBoxX->SetY1(fH2[0]->GetYaxis()->GetBinLowEdge(1)); fBorderBoxX->SetY2(fH2[0]->GetYaxis()->GetBinLowEdge(nY+1)); fBorderBoxY->SetFillStyle(0); fBorderBoxY->SetFillColor(0); fBorderBoxY->SetLineWidth(3); fBorderBoxY->SetLineStyle(2); fBorderBoxY->SetLineColor(6); fBorderBoxY->SetX1(fH2[0]->GetXaxis()->GetBinLowEdge(1)); fBorderBoxY->SetX2(fH2[0]->GetXaxis()->GetBinLowEdge(nX+1)); 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)); //~ //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,"RedrawBorderBoxX()"); 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,"RedrawBorderBoxY()"); 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) { if (event == kButton1Down) { //Switch to next TH2 histogram fSelect2[(fCurrent2+1)%fSelect2.size()]->SetState(kButtonDown,kTRUE);//emit } else if(event==kWheelUp)// && !(TString(sel->IsA()->GetName())=="TAxis") && !(TString(sel->IsA()->GetName())=="TH2I"))//not when zooming axis { fH2[fCurrent2]->GetZaxis()->SetRangeUser(0,fH2[fCurrent2]->GetMaximum()*0.9); TCanvas* c = fCanvas2->GetCanvas(); c->SetEditable(kTRUE); c->Modified(); c->SetEditable(kFALSE); c->Update(); } else if(event==kWheelDown)// && !(TString(sel->IsA()->GetName())=="TAxis") && !(TString(sel->IsA()->GetName())=="TH2I"))//not when zooming axis { fH2[fCurrent2]->GetZaxis()->SetRangeUser(0,fH2[fCurrent2]->GetMaximum()/0.9); TCanvas* c = fCanvas2->GetCanvas(); c->SetEditable(kTRUE); c->Modified(); c->SetEditable(kFALSE); c->Update(); } // 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); } */ } 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(); c->SetEditable(kTRUE); fH2[id]->Draw("COLZ"); fCurrent2 = id; c->SetEditable(kFALSE); RedrawBorderBoxX(); RedrawBorderBoxY(); ZoomX(); ZoomY(); //MovePalette(); } void TH2Viewer::MovePalette() { TCanvas* c = fCanvas2->GetCanvas(); c->SetEditable(kTRUE); TPaletteAxis *palette = (TPaletteAxis*)fH2[fCurrent2]->GetListOfFunctions()->FindObject("palette"); palette->SetX1NDC(0.86); palette->SetX2NDC(0.87); c->Modified(); c->SetEditable(kFALSE); c->Update(); } void TH2Viewer::RedrawBorderBoxX() { if(fCurrent2>=0&&fCurrent2<(Short_t)fH2.size()) { TCanvas* c = fCanvas2->GetCanvas(); c->cd(); c->SetEditable(kTRUE); TH2* h2 = fH2[fCurrent2]; fBorderBoxX->SetX1(h2->GetXaxis()->GetBinLowEdge(fBorderX->GetMinNumberEntry()->GetNumber()+1)); fBorderBoxX->SetX2(h2->GetXaxis()->GetBinLowEdge(fBorderX->GetMaxNumberEntry()->GetNumber()+2)); fBorderBoxX->Draw(); c->Modified(); c->SetEditable(kFALSE); c->Update(); } } void TH2Viewer::RedrawBorderBoxY() { if(fCurrent2>=0&&fCurrent2<(Short_t)fH2.size()) { TCanvas* c = fCanvas2->GetCanvas(); c->cd(); c->SetEditable(kTRUE); TH2* h2 = fH2[fCurrent2]; fBorderBoxY->SetY1(h2->GetYaxis()->GetBinLowEdge(fBorderY->GetMinNumberEntry()->GetNumber()+1)); fBorderBoxY->SetY2(h2->GetYaxis()->GetBinLowEdge(fBorderY->GetMaxNumberEntry()->GetNumber()+2)); fBorderBoxY->Draw(); c->Modified(); c->SetEditable(kFALSE); c->Update(); } } 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->SetTitle((TString)"Y ["+std::to_string(fBorderY->GetMinNumberEntry()->GetNumber()+1)+":"+std::to_string(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->SetTitle((TString)"X ["+std::to_string(fBorderX->GetMinNumberEntry()->GetNumber()+1)+":"+std::to_string(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(); } } void TH2Viewer::ReplaceData(std::vector newData, const UShort_t xbins, const UShort_t ybins) { if(!fH2.size()) return; if(fH2.size()!=newData.size()) return; const UShort_t nX = fH2[0]->GetNbinsX(); if(nX!=xbins) return; const UShort_t nY = fH2[1]->GetNbinsY(); if(nY!=ybins) return; for(UShort_t i=0;iSetBinContent(j+1,k+1,newData[i][j*nX+k]); } } } } 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 }