#include "TProfile2D.h"
#include "TMath.h"
#include "THLimitsFinder.h"
#include "Riostream.h"
#include "TVirtualPad.h"
#include "TError.h"
#include "TClass.h"
#include "TProfileHelper.h"
Bool_t TProfile2D::fgApproximate = kFALSE;
ClassImp(TProfile2D)
TProfile2D::TProfile2D() : TH2D()
{
fTsumwz = fTsumwz2 = 0;
fScaling = kFALSE;
BuildOptions(0,0,"");
}
TProfile2D::~TProfile2D()
{
}
TProfile2D::TProfile2D(const char *name,const char *title,Int_t nx,Double_t xlow,Double_t xup,Int_t ny,Double_t ylow,Double_t yup,Option_t *option)
: TH2D(name,title,nx,xlow,xup,ny,ylow,yup)
{
BuildOptions(0,0,option);
if (xlow >= xup || ylow >= yup) SetBuffer(fgBufferSize);
}
TProfile2D::TProfile2D(const char *name,const char *title,Int_t nx,const Double_t *xbins,Int_t ny,Double_t ylow,Double_t yup,Option_t *option)
: TH2D(name,title,nx,xbins,ny,ylow,yup)
{
BuildOptions(0,0,option);
}
TProfile2D::TProfile2D(const char *name,const char *title,Int_t nx,Double_t xlow,Double_t xup,Int_t ny,const Double_t *ybins,Option_t *option)
: TH2D(name,title,nx,xlow,xup,ny,ybins)
{
BuildOptions(0,0,option);
}
TProfile2D::TProfile2D(const char *name,const char *title,Int_t nx,const Double_t *xbins,Int_t ny,const Double_t *ybins,Option_t *option)
: TH2D(name,title,nx,xbins,ny,ybins)
{
BuildOptions(0,0,option);
}
TProfile2D::TProfile2D(const char *name,const char *title,Int_t nx,Double_t xlow,Double_t xup,Int_t ny, Double_t ylow,Double_t yup,Double_t zlow,Double_t zup,Option_t *option)
: TH2D(name,title,nx,xlow,xup,ny,ylow,yup)
{
BuildOptions(zlow,zup,option);
if (xlow >= xup || ylow >= yup) SetBuffer(fgBufferSize);
}
void TProfile2D::BuildOptions(Double_t zmin, Double_t zmax, Option_t *option)
{
SetErrorOption(option);
fBinEntries.Set(fNcells);
TH1::Sumw2();
if (fgDefaultSumw2) Sumw2();
fZmin = zmin;
fZmax = zmax;
fScaling = kFALSE;
fTsumwz = fTsumwz2 = 0;
}
TProfile2D::TProfile2D(const TProfile2D &profile) : TH2D()
{
((TProfile2D&)profile).Copy(*this);
}
void TProfile2D::Add(TF1 *, Double_t , Option_t*)
{
Error("Add","Function not implemented for TProfile2D");
return;
}
void TProfile2D::Add(const TH1 *h1, Double_t c1)
{
if (!h1) {
Error("Add","Attempt to add a non-existing profile");
return;
}
if (!h1->InheritsFrom(TProfile2D::Class())) {
Error("Add","Attempt to add a non-profile2D object");
return;
}
TProfileHelper::Add(this, this, h1, 1, c1);
}
void TProfile2D::Add(const TH1 *h1, const TH1 *h2, Double_t c1, Double_t c2)
{
if (!h1 || !h2) {
Error("Add","Attempt to add a non-existing profile");
return;
}
if (!h1->InheritsFrom(TProfile2D::Class())) {
Error("Add","Attempt to add a non-profile2D object");
return;
}
if (!h2->InheritsFrom(TProfile2D::Class())) {
Error("Add","Attempt to add a non-profile2D object");
return;
}
TProfileHelper::Add(this, h1, h2, c1, c2);
}
void TProfile2D::Approximate(Bool_t approx)
{
fgApproximate = approx;
}
Int_t TProfile2D::BufferEmpty(Int_t action)
{
if (!fBuffer) return 0;
Int_t nbentries = (Int_t)fBuffer[0];
if (!nbentries) return 0;
Double_t *buffer = fBuffer;
if (nbentries < 0) {
if (action == 0) return 0;
nbentries = -nbentries;
fBuffer=0;
Reset("ICES");
fBuffer = buffer;
}
if (TestBit(kCanRebin) || fXaxis.GetXmax() <= fXaxis.GetXmin() || fYaxis.GetXmax() <= fYaxis.GetXmin()) {
Double_t xmin = fBuffer[2];
Double_t xmax = xmin;
Double_t ymin = fBuffer[3];
Double_t ymax = ymin;
for (Int_t i=1;i<nbentries;i++) {
Double_t x = fBuffer[4*i+2];
if (x < xmin) xmin = x;
if (x > xmax) xmax = x;
Double_t y = fBuffer[4*i+3];
if (y < ymin) ymin = y;
if (y > ymax) ymax = y;
}
if (fXaxis.GetXmax() <= fXaxis.GetXmin() || fYaxis.GetXmax() <= fYaxis.GetXmin()) {
THLimitsFinder::GetLimitsFinder()->FindGoodLimits(this,xmin,xmax,ymin,ymax);
} else {
fBuffer = 0;
Int_t keep = fBufferSize; fBufferSize = 0;
if (xmin < fXaxis.GetXmin()) RebinAxis(xmin,&fXaxis);
if (xmax >= fXaxis.GetXmax()) RebinAxis(xmax,&fXaxis);
if (ymin < fYaxis.GetXmin()) RebinAxis(ymin,&fYaxis);
if (ymax >= fYaxis.GetXmax()) RebinAxis(ymax,&fYaxis);
fBuffer = buffer;
fBufferSize = keep;
}
}
fBuffer = 0;
for (Int_t i=0;i<nbentries;i++) {
Fill(buffer[4*i+2],buffer[4*i+3],buffer[4*i+4],buffer[4*i+1]);
}
fBuffer = buffer;
if (action > 0) { delete [] fBuffer; fBuffer = 0; fBufferSize = 0;}
else {
if (nbentries == (Int_t)fEntries) fBuffer[0] = -nbentries;
else fBuffer[0] = 0;
}
return nbentries;
}
Int_t TProfile2D::BufferFill(Double_t x, Double_t y, Double_t z, Double_t w)
{
if (!fBuffer) return -3;
Int_t nbentries = (Int_t)fBuffer[0];
if (nbentries < 0) {
nbentries = -nbentries;
fBuffer[0] = nbentries;
if (fEntries > 0) {
Double_t *buffer = fBuffer; fBuffer=0;
Reset("ICES");
fBuffer = buffer;
}
}
if (4*nbentries+4 >= fBufferSize) {
BufferEmpty(1);
return Fill(x,y,z,w);
}
fBuffer[4*nbentries+1] = w;
fBuffer[4*nbentries+2] = x;
fBuffer[4*nbentries+3] = y;
fBuffer[4*nbentries+4] = z;
fBuffer[0] += 1;
return -2;
}
void TProfile2D::Copy(TObject &obj) const
{
TH2D::Copy(((TProfile2D&)obj));
fBinEntries.Copy(((TProfile2D&)obj).fBinEntries);
fBinSumw2.Copy(((TProfile2D&)obj).fBinSumw2);
for (int bin=0;bin<fNcells;bin++) {
((TProfile2D&)obj).fArray[bin] = fArray[bin];
((TProfile2D&)obj).fSumw2.fArray[bin] = fSumw2.fArray[bin];
}
((TProfile2D&)obj).fZmin = fZmin;
((TProfile2D&)obj).fZmax = fZmax;
((TProfile2D&)obj).fScaling = fScaling;
((TProfile2D&)obj).fErrorMode = fErrorMode;
((TProfile2D&)obj).fTsumwz = fTsumwz;
((TProfile2D&)obj).fTsumwz2 = fTsumwz2;
}
void TProfile2D::Divide(TF1 *, Double_t )
{
Error("Divide","Function not implemented for TProfile2D");
return;
}
void TProfile2D::Divide(const TH1 *h1)
{
if (!h1) {
Error("Divide","Attempt to divide a non-existing profile2D");
return;
}
if (!h1->InheritsFrom(TProfile2D::Class())) {
Error("Divide","Attempt to divide a non-profile2D object");
return;
}
TProfile2D *p1 = (TProfile2D*)h1;
if (fBuffer) BufferEmpty(1);
Int_t nx = GetNbinsX();
if (nx != p1->GetNbinsX()) {
Error("Divide","Attempt to divide profiles with different number of bins");
return;
}
Int_t ny = GetNbinsY();
if (ny != p1->GetNbinsY()) {
Error("Divide","Attempt to divide profiles with different number of bins");
return;
}
fEntries = fTsumw = fTsumw2 = fTsumwx = fTsumwx2 = 0;
Int_t bin,binx,biny;
Double_t *cu1 = p1->GetW();
Double_t *er1 = p1->GetW2();
Double_t *en1 = p1->GetB();
Double_t c0,c1,w,z,x,y;
for (binx =0;binx<=nx+1;binx++) {
for (biny =0;biny<=ny+1;biny++) {
bin = biny*(fXaxis.GetNbins()+2) + binx;
c0 = fArray[bin];
c1 = cu1[bin];
if (c1) w = c0/c1;
else w = 0;
fArray[bin] = w;
z = TMath::Abs(w);
x = fXaxis.GetBinCenter(binx);
y = fYaxis.GetBinCenter(biny);
fEntries++;
fTsumw += z;
fTsumw2 += z*z;
fTsumwx += z*x;
fTsumwx2 += z*x*x;
fTsumwy += z*y;
fTsumwy2 += z*y*y;
fTsumwxy += z*x*y;
fTsumwz += z;
fTsumwz2 += z*z;
Double_t e0 = fSumw2.fArray[bin];
Double_t e1 = er1[bin];
Double_t c12= c1*c1;
if (!c1) fSumw2.fArray[bin] = 0;
else fSumw2.fArray[bin] = (e0*c1*c1 + e1*c0*c0)/(c12*c12);
if (!en1[bin]) fBinEntries.fArray[bin] = 0;
else fBinEntries.fArray[bin] /= en1[bin];
}
}
if (fBinSumw2.fN) {
Warning("Divide","Cannot preserve during the division of profiles the sum of bin weight square");
fBinSumw2 = TArrayD();
}
}
void TProfile2D::Divide(const TH1 *h1, const TH1 *h2, Double_t c1, Double_t c2, Option_t *option)
{
TString opt = option;
opt.ToLower();
Bool_t binomial = kFALSE;
if (opt.Contains("b")) binomial = kTRUE;
if (!h1 || !h2) {
Error("Divide","Attempt to divide a non-existing profile2D");
return;
}
if (!h1->InheritsFrom(TProfile2D::Class())) {
Error("Divide","Attempt to divide a non-profile2D object");
return;
}
TProfile2D *p1 = (TProfile2D*)h1;
if (!h2->InheritsFrom(TProfile2D::Class())) {
Error("Divide","Attempt to divide a non-profile2D object");
return;
}
TProfile2D *p2 = (TProfile2D*)h2;
if (fBuffer) BufferEmpty(1);
Int_t nx = GetNbinsX();
if (nx != p1->GetNbinsX() || nx != p2->GetNbinsX()) {
Error("Divide","Attempt to divide profiles with different number of bins");
return;
}
Int_t ny = GetNbinsY();
if (ny != p1->GetNbinsY() || ny != p2->GetNbinsY()) {
Error("Divide","Attempt to divide profiles with different number of bins");
return;
}
if (!c2) {
Error("Divide","Coefficient of dividing profile cannot be zero");
return;
}
fEntries = fTsumw = fTsumw2 = fTsumwx = fTsumwx2 = 0;
Int_t bin,binx,biny;
Double_t *cu1 = p1->GetW();
Double_t *cu2 = p2->GetW();
Double_t *er1 = p1->GetW2();
Double_t *er2 = p2->GetW2();
Double_t *en1 = p1->GetB();
Double_t *en2 = p2->GetB();
Double_t b1,b2,w,z,x,y,ac1,ac2;
ac1 = TMath::Abs(c1);
ac2 = TMath::Abs(c2);
for (binx =0;binx<=nx+1;binx++) {
for (biny =0;biny<=ny+1;biny++) {
bin = biny*(fXaxis.GetNbins()+2) + binx;
b1 = cu1[bin];
b2 = cu2[bin];
if (b2) w = c1*b1/(c2*b2);
else w = 0;
fArray[bin] = w;
z = TMath::Abs(w);
x = fXaxis.GetBinCenter(binx);
y = fYaxis.GetBinCenter(biny);
fEntries++;
fTsumw += z;
fTsumw2 += z*z;
fTsumwx += z*x;
fTsumwx2 += z*x*x;
fTsumwy += z*y;
fTsumwy2 += z*y*y;
fTsumwxy += z*x*y;
fTsumwz += z;
fTsumwz2 += z*z;
Double_t e1 = er1[bin];
Double_t e2 = er2[bin];
Double_t b22= b2*b2*TMath::Abs(c2);
if (!b2) fSumw2.fArray[bin] = 0;
else {
if (binomial) {
fSumw2.fArray[bin] = TMath::Abs(w*(1-w)/(c2*b2));
} else {
fSumw2.fArray[bin] = ac1*ac2*(e1*b2*b2 + e2*b1*b1)/(b22*b22);
}
}
if (!en2[bin]) fBinEntries.fArray[bin] = 0;
else fBinEntries.fArray[bin] = en1[bin]/en2[bin];
}
}
}
TH1 *TProfile2D::DrawCopy(Option_t *option) const
{
TString opt = option;
opt.ToLower();
if (gPad && !opt.Contains("same")) gPad->Clear();
TProfile2D *newpf = (TProfile2D*)Clone();
newpf->SetDirectory(0);
newpf->SetBit(kCanDelete);
newpf->AppendPad(option);
return newpf;
}
Int_t TProfile2D::Fill(Double_t x, Double_t y, Double_t z)
{
if (fBuffer) return BufferFill(x,y,z,1);
Int_t bin,binx,biny;
if (fZmin != fZmax) {
if (z <fZmin || z> fZmax || TMath::IsNaN(z) ) return -1;
}
fEntries++;
binx =fXaxis.FindBin(x);
biny =fYaxis.FindBin(y);
if (binx <0 || biny <0) return -1;
bin = GetBin(binx, biny);
fArray[bin] += z;
fSumw2.fArray[bin] += z*z;
fBinEntries.fArray[bin] += 1;
if (fBinSumw2.fN) fBinSumw2.fArray[bin] += 1;
if (binx == 0 || binx > fXaxis.GetNbins()) {
if (!fgStatOverflows) return -1;
}
if (biny == 0 || biny > fYaxis.GetNbins()) {
if (!fgStatOverflows) return -1;
}
++fTsumw;
++fTsumw2;
fTsumwx += x;
fTsumwx2 += x*x;
fTsumwy += y;
fTsumwy2 += y*y;
fTsumwxy += x*y;
fTsumwz += z;
fTsumwz2 += z*z;
return bin;
}
Int_t TProfile2D::Fill(Double_t x, const char *namey, Double_t z)
{
Int_t bin,binx,biny;
if (fZmin != fZmax) {
if (z <fZmin || z> fZmax || TMath::IsNaN(z)) return -1;
}
fEntries++;
binx =fXaxis.FindBin(x);
biny =fYaxis.FindBin(namey);
if (binx <0 || biny <0) return -1;
bin = biny*(fXaxis.GetNbins()+2) + binx;
AddBinContent(bin, z);
fSumw2.fArray[bin] += (Double_t)z*z;
fBinEntries.fArray[bin] += 1;
if (fBinSumw2.fN) fBinSumw2.fArray[bin] += 1;
if (binx == 0 || binx > fXaxis.GetNbins()) {
if (!fgStatOverflows) return -1;
}
if (biny == 0 || biny > fYaxis.GetNbins()) return -1;
Double_t y = fYaxis.GetBinCenter(biny);
++fTsumw;
++fTsumw2;
fTsumwx += x;
fTsumwx2 += x*x;
fTsumwy += y;
fTsumwy2 += y*y;
fTsumwxy += x*y;
fTsumwz += z;
fTsumwz2 += z*z;
return bin;
}
Int_t TProfile2D::Fill(const char *namex, const char *namey, Double_t z)
{
Int_t bin,binx,biny;
if (fZmin != fZmax) {
if (z <fZmin || z> fZmax || TMath::IsNaN(z) ) return -1;
}
fEntries++;
binx =fXaxis.FindBin(namex);
biny =fYaxis.FindBin(namey);
if (binx <0 || biny <0) return -1;
bin = biny*(fXaxis.GetNbins()+2) + binx;
AddBinContent(bin, z);
fSumw2.fArray[bin] += (Double_t)z*z;
fBinEntries.fArray[bin] += 1;
if (fBinSumw2.fN) fBinSumw2.fArray[bin] += 1;
if (binx == 0 || binx > fXaxis.GetNbins()) return -1;
if (biny == 0 || biny > fYaxis.GetNbins()) return -1;
Double_t x = fYaxis.GetBinCenter(binx);
Double_t y = fYaxis.GetBinCenter(biny);
++fTsumw;
++fTsumw2;
fTsumwx += x;
fTsumwx2 += x*x;
fTsumwy += y;
fTsumwy2 += y*y;
fTsumwxy += x*y;
fTsumwz += z;
fTsumwz2 += z*z;
return bin;
}
Int_t TProfile2D::Fill(const char *namex, Double_t y, Double_t z)
{
Int_t bin,binx,biny;
if (fZmin != fZmax) {
if (z <fZmin || z> fZmax || TMath::IsNaN(z)) return -1;
}
fEntries++;
binx =fXaxis.FindBin(namex);
biny =fYaxis.FindBin(y);
if (binx <0 || biny <0) return -1;
bin = biny*(fXaxis.GetNbins()+2) + binx;
AddBinContent(bin, z);
fSumw2.fArray[bin] += (Double_t)z*z;
fBinEntries.fArray[bin] += 1;
if (fBinSumw2.fN) fBinSumw2.fArray[bin] += 1;
if (binx == 0 || binx > fXaxis.GetNbins()) return -1;
if (biny == 0 || biny > fYaxis.GetNbins()) {
if (!fgStatOverflows) return -1;
}
Double_t x = fYaxis.GetBinCenter(binx);
++fTsumw;
++fTsumw2;
fTsumwx += x;
fTsumwx2 += x*x;
fTsumwy += y;
fTsumwy2 += y*y;
fTsumwxy += x*y;
fTsumwz += z;
fTsumwz2 += z*z;
return bin;
}
Int_t TProfile2D::Fill(Double_t x, Double_t y, Double_t z, Double_t w)
{
if (fBuffer) return BufferFill(x,y,z,w);
Int_t bin,binx,biny;
if (fZmin != fZmax) {
if (z <fZmin || z> fZmax || TMath::IsNaN(z)) return -1;
}
Double_t u= w;
fEntries++;
binx =fXaxis.FindBin(x);
biny =fYaxis.FindBin(y);
if (binx <0 || biny <0) return -1;
bin = biny*(fXaxis.GetNbins()+2) + binx;
AddBinContent(bin, u*z);
fSumw2.fArray[bin] += u*z*z;
fBinEntries.fArray[bin] += u;
if (fBinSumw2.fN) fBinSumw2.fArray[bin] += u*u;
if (binx == 0 || binx > fXaxis.GetNbins()) {
if (!fgStatOverflows) return -1;
}
if (biny == 0 || biny > fYaxis.GetNbins()) {
if (!fgStatOverflows) return -1;
}
fTsumw += u;
fTsumw2 += u*u;
fTsumwx += u*x;
fTsumwx2 += u*x*x;
fTsumwy += u*y;
fTsumwy2 += u*y*y;
fTsumwxy += u*x*y;
fTsumwz += u*z;
fTsumwz2 += u*z*z;
return bin;
}
Double_t TProfile2D::GetBinContent(Int_t bin) const
{
if (fBuffer) ((TProfile2D*)this)->BufferEmpty();
if (bin < 0 || bin >= fNcells) return 0;
if (fBinEntries.fArray[bin] == 0) return 0;
if (!fArray) return 0;
return fArray[bin]/fBinEntries.fArray[bin];
}
Double_t TProfile2D::GetBinEntries(Int_t bin) const
{
if (fBuffer) ((TProfile2D*)this)->BufferEmpty();
if (bin < 0 || bin >= fNcells) return 0;
return fBinEntries.fArray[bin];
}
Double_t TProfile2D::GetBinEffectiveEntries(Int_t bin)
{
return TProfileHelper::GetBinEffectiveEntries(this, bin);
}
Double_t TProfile2D::GetBinError(Int_t bin) const
{
return TProfileHelper::GetBinError((TProfile2D*)this, bin);
}
Option_t *TProfile2D::GetErrorOption() const
{
if (fErrorMode == kERRORSPREAD) return "s";
if (fErrorMode == kERRORSPREADI) return "i";
if (fErrorMode == kERRORSPREADG) return "g";
return "";
}
void TProfile2D::GetStats(Double_t *stats) const
{
if (fBuffer) ((TProfile2D*)this)->BufferEmpty();
if (fTsumw == 0 || fXaxis.TestBit(TAxis::kAxisRange) || fYaxis.TestBit(TAxis::kAxisRange)) {
Int_t bin, binx, biny;
Double_t w, w2;
Double_t x,y;
for (bin=0;bin<9;bin++) stats[bin] = 0;
if (!fBinEntries.fArray) return;
Int_t firstBinX = fXaxis.GetFirst();
Int_t lastBinX = fXaxis.GetLast();
Int_t firstBinY = fYaxis.GetFirst();
Int_t lastBinY = fYaxis.GetLast();
if (fgStatOverflows) {
if ( !fXaxis.TestBit(TAxis::kAxisRange) ) {
if (firstBinX == 1) firstBinX = 0;
if (lastBinX == fXaxis.GetNbins() ) lastBinX += 1;
}
if ( !fYaxis.TestBit(TAxis::kAxisRange) ) {
if (firstBinY == 1) firstBinY = 0;
if (lastBinY == fYaxis.GetNbins() ) lastBinY += 1;
}
}
for (biny = firstBinY; biny <= lastBinY; biny++) {
y = fYaxis.GetBinCenter(biny);
for (binx = firstBinX; binx <= lastBinX; binx++) {
bin = GetBin(binx,biny);
w = fBinEntries.fArray[bin];
w2 = (fBinSumw2.fN ? fBinSumw2.fArray[bin] : w );
x = fXaxis.GetBinCenter(binx);
stats[0] += w;
stats[1] += w2;
stats[2] += w*x;
stats[3] += w*x*x;
stats[4] += w*y;
stats[5] += w*y*y;
stats[6] += w*x*y;
stats[7] += fArray[bin];
stats[8] += fSumw2.fArray[bin];
}
}
} else {
stats[0] = fTsumw;
stats[1] = fTsumw2;
stats[2] = fTsumwx;
stats[3] = fTsumwx2;
stats[4] = fTsumwy;
stats[5] = fTsumwy2;
stats[6] = fTsumwxy;
stats[7] = fTsumwz;
stats[8] = fTsumwz2;
}
}
void TProfile2D::LabelsDeflate(Option_t *ax)
{
TProfileHelper::LabelsDeflate(this, ax);
}
void TProfile2D::LabelsInflate(Option_t *ax)
{
TProfileHelper::LabelsInflate(this, ax);
}
void TProfile2D::LabelsOption(Option_t *option, Option_t *ax)
{
TAxis *axis = GetXaxis();
if (ax[0] == 'y' || ax[0] == 'Y') axis = GetYaxis();
THashList *labels = axis->GetLabels();
if (!labels) {
Warning("LabelsOption","Cannot sort. No labels");
return;
}
TString opt = option;
opt.ToLower();
if (opt.Contains("h")) {
axis->SetBit(TAxis::kLabelsHori);
axis->ResetBit(TAxis::kLabelsVert);
axis->ResetBit(TAxis::kLabelsDown);
axis->ResetBit(TAxis::kLabelsUp);
}
if (opt.Contains("v")) {
axis->SetBit(TAxis::kLabelsVert);
axis->ResetBit(TAxis::kLabelsHori);
axis->ResetBit(TAxis::kLabelsDown);
axis->ResetBit(TAxis::kLabelsUp);
}
if (opt.Contains("u")) {
axis->SetBit(TAxis::kLabelsUp);
axis->ResetBit(TAxis::kLabelsVert);
axis->ResetBit(TAxis::kLabelsDown);
axis->ResetBit(TAxis::kLabelsHori);
}
if (opt.Contains("d")) {
axis->SetBit(TAxis::kLabelsDown);
axis->ResetBit(TAxis::kLabelsVert);
axis->ResetBit(TAxis::kLabelsHori);
axis->ResetBit(TAxis::kLabelsUp);
}
Int_t sort = -1;
if (opt.Contains("a")) sort = 0;
if (opt.Contains(">")) sort = 1;
if (opt.Contains("<")) sort = 2;
if (sort < 0) return;
Int_t nx = fXaxis.GetNbins()+2;
Int_t ny = fYaxis.GetNbins()+2;
Int_t n = TMath::Min(axis->GetNbins(), labels->GetSize());
Int_t *a = new Int_t[n+2];
Int_t i,j,k,bin;
Double_t *sumw = new Double_t[nx*ny];
Double_t *errors = new Double_t[nx*ny];
Double_t *ent = new Double_t[nx*ny];
THashList *labold = new THashList(labels->GetSize(),1);
TIter nextold(labels);
TObject *obj;
while ((obj=nextold())) {
labold->Add(obj);
}
labels->Clear();
if (sort > 0) {
Double_t *pcont = new Double_t[n+2];
for (i=0;i<=n;i++) pcont[i] = 0;
for (i=1;i<nx;i++) {
for (j=1;j<ny;j++) {
bin = i+nx*j;
sumw[bin] = fArray[bin];
errors[bin] = fSumw2.fArray[bin];
ent[bin] = fBinEntries.fArray[bin];
if (axis == GetXaxis()) k = i;
else k = j;
if (fBinEntries.fArray[bin] != 0) pcont[k-1] += fArray[bin]/fBinEntries.fArray[bin];
}
}
if (sort ==1) TMath::Sort(n,pcont,a,kTRUE);
else TMath::Sort(n,pcont,a,kFALSE);
delete [] pcont;
for (i=0;i<n;i++) {
obj = labold->At(a[i]);
labels->Add(obj);
obj->SetUniqueID(i+1);
}
for (i=1;i<nx;i++) {
for (j=1;j<ny;j++) {
bin = i+nx*j;
if (axis == GetXaxis()) {
fArray[bin] = sumw[a[i-1]+1+nx*j];
fSumw2.fArray[bin] = errors[a[i-1]+1+nx*j];
fBinEntries.fArray[bin] = ent[a[i-1]+1+nx*j];
} else {
fArray[bin] = sumw[i+nx*(a[j-1]+1)];
fSumw2.fArray[bin] = errors[i+nx*(a[j-1]+1)];
fBinEntries.fArray[bin] = ent[i+nx*(a[j-1]+1)];
}
}
}
} else {
const UInt_t kUsed = 1<<18;
TObject *objk=0;
a[0] = 0;
a[n+1] = n+1;
for (i=1;i<=n;i++) {
const char *label = "zzzzzzzzzzzz";
for (j=1;j<=n;j++) {
obj = labold->At(j-1);
if (!obj) continue;
if (obj->TestBit(kUsed)) continue;
if (strcmp(label,obj->GetName()) < 0) continue;
objk = obj;
a[i] = j;
label = obj->GetName();
}
if (objk) {
objk->SetUniqueID(i);
labels->Add(objk);
objk->SetBit(kUsed);
}
}
for (i=1;i<=n;i++) {
obj = labels->At(i-1);
if (!obj) continue;
obj->ResetBit(kUsed);
}
for (i=0;i<nx;i++) {
for (j=0;j<ny;j++) {
bin = i+nx*j;
sumw[bin] = fArray[bin];
errors[bin] = fSumw2.fArray[bin];
ent[bin] = fBinEntries.fArray[bin];
}
}
for (i=0;i<nx;i++) {
for (j=0;j<ny;j++) {
bin = i+nx*j;
if (axis == GetXaxis()) {
fArray[bin] = sumw[a[i]+nx*j];
fSumw2.fArray[bin] = errors[a[i]+nx*j];
fBinEntries.fArray[bin] = ent[a[i]+nx*j];
} else {
fArray[bin] = sumw[i+nx*a[j]];
fSumw2.fArray[bin] = errors[i+nx*a[j]];
fBinEntries.fArray[bin] = ent[i+nx*a[j]];
}
}
}
}
delete labold;
if (a) delete [] a;
if (sumw) delete [] sumw;
if (errors) delete [] errors;
if (ent) delete [] ent;
}
Long64_t TProfile2D::Merge(TCollection *li)
{
return TProfileHelper::Merge(this, li);
}
void TProfile2D::Multiply(TF1 *, Double_t )
{
Error("Multiply","Function not implemented for TProfile2D");
return;
}
void TProfile2D::Multiply(const TH1 *)
{
Error("Multiply","Multiplication of profile2D histograms not implemented");
}
void TProfile2D::Multiply(const TH1 *, const TH1 *, Double_t, Double_t, Option_t *)
{
Error("Multiply","Multiplication of profile2D histograms not implemented");
}
TH2D *TProfile2D::ProjectionXY(const char *name, Option_t *option) const
{
TString opt = option;
opt.ToLower();
Int_t nx = fXaxis.GetNbins();
Int_t ny = fYaxis.GetNbins();
char *pname = (char*)name;
if (strcmp(name,"_px") == 0) {
Int_t nch = strlen(GetName()) + 4;
pname = new char[nch];
snprintf(pname,nch,"%s%s",GetName(),name);
}
TH2D *h1 = new TH2D(pname,GetTitle(),nx,fXaxis.GetXmin(),fXaxis.GetXmax(),ny,fYaxis.GetXmin(),fYaxis.GetXmax());
Bool_t computeErrors = kFALSE;
Bool_t cequalErrors = kFALSE;
Bool_t binEntries = kFALSE;
Bool_t binWeight = kFALSE;
if (opt.Contains("b")) binEntries = kTRUE;
if (opt.Contains("e")) computeErrors = kTRUE;
if (opt.Contains("w")) binWeight = kTRUE;
if (opt.Contains("c=e")) {cequalErrors = kTRUE; computeErrors=kFALSE;}
if (computeErrors || binWeight ) h1->Sumw2();
if (pname != name) delete [] pname;
Int_t bin,binx, biny;
Double_t cont;
for (binx =0;binx<=nx+1;binx++) {
for (biny =0;biny<=ny+1;biny++) {
bin = GetBin(binx,biny);
if (binEntries) cont = GetBinEntries(bin);
else if (cequalErrors) cont = GetBinError(bin);
else if (binWeight) cont = GetBinContent(bin) * GetBinEntries(bin);
else cont = GetBinContent(bin);
h1->SetBinContent(bin ,cont);
if (computeErrors ) h1->SetBinError(bin , GetBinError(bin) );
if (binWeight) h1->SetBinError(bin , TMath::Sqrt(fSumw2.fArray[bin] ) );
if (binEntries && h1->GetSumw2() ) {
Double_t err2;
if (fBinSumw2.fN)
err2 = fBinSumw2.fArray[bin];
else
err2 = cont;
h1->SetBinError(bin, TMath::Sqrt(err2 ) );
}
}
}
h1->SetEntries(fEntries);
return h1;
}
void TProfile2D::PutStats(Double_t *stats)
{
fTsumw = stats[0];
fTsumw2 = stats[1];
fTsumwx = stats[2];
fTsumwx2 = stats[3];
fTsumwy = stats[4];
fTsumwy2 = stats[5];
fTsumwxy = stats[6];
fTsumwz = stats[7];
fTsumwz2 = stats[8];
}
void TProfile2D::Reset(Option_t *option)
{
TH2D::Reset(option);
fBinEntries.Reset();
fBinSumw2.Reset();
TString opt = option;
opt.ToUpper();
if (opt.Contains("ICE") && !opt.Contains("S")) return;
fTsumwz = fTsumwz2 = 0;
}
void TProfile2D::RebinAxis(Double_t x, TAxis *axis)
{
TProfile2D* hold = TProfileHelper::RebinAxis(this, x, axis);
if ( hold ) {
fTsumwz = hold->fTsumwz;
fTsumwz2 = hold->fTsumwz2;
delete hold;
}
}
TProfile2D * TProfile2D::Rebin2D(Int_t nxgroup ,Int_t nygroup,const char * newname ) {
if((nxgroup != 1) || (nygroup != 1)){
Int_t nxbins = fXaxis.GetNbins();
Int_t nybins = fYaxis.GetNbins();
Double_t xmin = fXaxis.GetXmin();
Double_t xmax = fXaxis.GetXmax();
Double_t ymin = fYaxis.GetXmin();
Double_t ymax = fYaxis.GetXmax();
if ((nxgroup <= 0) || (nxgroup > nxbins)) {
Error("Rebin", "Illegal value of nxgroup=%d",nxgroup);
return 0;
}
if ((nygroup <= 0) || (nygroup > nybins)) {
Error("Rebin", "Illegal value of nygroup=%d",nygroup);
return 0;
}
Int_t newxbins = nxbins/nxgroup;
Int_t newybins = nybins/nygroup;
if(newxbins*nxgroup != nxbins) {
Warning("Rebin", "nxgroup=%d should be an exact divider of nxbins=%d",nxgroup,nxbins);
}
if(newybins*nygroup != nybins) {
Warning("Rebin", "nygroup=%d should be an exact divider of nybins=%d",nygroup,nybins);
}
Double_t *oldBins = new Double_t[(nxbins+2)*(nybins+2)];
Double_t *oldCount = new Double_t[(nxbins+2)*(nybins+2)];
Double_t *oldErrors = new Double_t[(nxbins+2)*(nybins+2)];
Double_t *oldBinw2 = (fBinSumw2.fN ? new Double_t[(nxbins+2)*(nybins+2)] : 0 );
Double_t *cu1 = GetW();
Double_t *er1 = GetW2();
Double_t *en1 = GetB();
Double_t *ew1 = GetB2();
for(Int_t ibin=0; ibin < (nxbins+2)*(nybins+2); ibin++){
oldBins[ibin] = cu1[ibin];
oldCount[ibin] = en1[ibin];
oldErrors[ibin] = er1[ibin];
if (ew1 && fBinSumw2.fN) oldBinw2[ibin] = ew1[ibin];
}
TProfile2D *hnew = this;
if(newname && strlen(newname) > 0) {
hnew = (TProfile2D*)Clone(newname);
}
if(newxbins*nxgroup != nxbins) {
xmax = fXaxis.GetBinUpEdge(newxbins*nxgroup);
hnew->fTsumw = 0;
}
if(newybins*nygroup != nybins) {
ymax = fYaxis.GetBinUpEdge(newybins*nygroup);
hnew->fTsumw = 0;
}
if((fXaxis.GetXbins()->GetSize() > 0) || (fYaxis.GetXbins()->GetSize() > 0)){
Double_t* xbins = new Double_t[newxbins+1];
Double_t* ybins = new Double_t[newybins+1];
for(Int_t i=0; i < newxbins+1; i++)
xbins[i] = fXaxis.GetBinLowEdge(1+i*nxgroup);
for(Int_t j=0; j < newybins+1; j++)
ybins[j] = fYaxis.GetBinLowEdge(1+j*nygroup);
hnew->SetBins(newxbins,xbins,newybins,ybins);
delete [] xbins;
delete [] ybins;
}
else{
hnew->SetBins(newxbins,xmin,xmax,newybins,ymin,ymax);
}
Double_t *cu2 = hnew->GetW();
Double_t *er2 = hnew->GetW2();
Double_t *en2 = hnew->GetB();
Double_t *ew2 = hnew->GetB2();
Double_t binContent, binCount, binError, binSumw2;
Int_t oldxbin = 1;
Int_t oldybin = 1;
Int_t bin;
for(Int_t xbin = 1; xbin <= newxbins; xbin++){
oldybin = 1;
for(Int_t ybin = 1; ybin <= newybins; ybin++){
binContent = 0;
binCount = 0;
binError = 0;
binSumw2 = 0;
for(Int_t i=0; i < nxgroup; i++){
if(oldxbin + i > nxbins) break;
for(Int_t j=0; j < nygroup; j++){
if(oldybin + j > nybins) break;
bin = oldxbin + i + (nxbins+2)*(oldybin+j);
binContent += oldBins[bin];
binCount += oldCount[bin];
binError += oldErrors[bin];
if(fBinSumw2.fN) binSumw2 += oldBinw2[bin];
}
}
bin = xbin + (newxbins + 2)*ybin;
cu2[bin] = binContent;
er2[bin] = binError;
en2[bin] = binCount;
if(fBinSumw2.fN) ew2[bin] = binSumw2;
oldybin += nygroup;
}
oldxbin += nxgroup;
}
cu2[0] = oldBins[0];
er2[0] = oldErrors[0];
en2[0] = oldCount[0];
if(fBinSumw2.fN) ew2[0] = oldBinw2[0];
binContent = 0;
binCount = 0;
binError = 0;
binSumw2 = 0;
for(Int_t i=oldxbin; i <= nxbins+1; i++){
for(Int_t j=oldybin; j <= nybins+1; j++){
bin = i + (nxbins+2)*j;
binContent += oldBins[bin];
binCount += oldCount[bin];
binError += oldErrors[bin];
if(fBinSumw2.fN) binSumw2 += oldBinw2[bin];
}
}
bin = (newxbins+2)*(newybins+2)-1;
cu2[bin] = binContent;
er2[bin] = binError;
en2[bin] = binCount;
if(fBinSumw2.fN) ew2[bin] = binSumw2;
binContent = 0;
binCount = 0;
binError = 0;
binSumw2 = 0;
for(Int_t i=oldxbin; i <= nxbins+1; i++){
bin = i;
binContent += oldBins[bin];
binCount += oldCount[bin];
binError += oldErrors[bin];
if(fBinSumw2.fN) binSumw2 += oldBinw2[bin];
}
bin = newxbins + 1;
cu2[bin] = binContent;
er2[bin] = binError;
en2[bin] = binCount;
if(fBinSumw2.fN) ew2[bin] = binSumw2;
binContent = 0;
binCount = 0;
binError = 0;
binSumw2 = 0;
for(Int_t i=oldybin; i <= nybins+1; i++){
bin = i*(nxbins + 2);
binContent += oldBins[bin];
binCount += oldCount[bin];
binError += oldErrors[bin];
if(fBinSumw2.fN) binSumw2 += oldBinw2[bin];
}
bin = (newxbins + 2)*(newybins + 1);
cu2[bin] = binContent;
er2[bin] = binError;
en2[bin] = binCount;
if(fBinSumw2.fN) ew2[bin] = binSumw2;
Double_t binContentuf, binCountuf, binErroruf, binSumw2uf;
Double_t binContentof, binCountof, binErrorof, binSumw2of;
Int_t ufbin, ofbin;
Int_t oldxbin2 = 1;
for(Int_t xbin = 1; xbin <= newxbins; xbin++){
binContentuf = 0;
binCountuf = 0;
binErroruf = 0;
binSumw2uf = 0;
binContentof = 0;
binCountof = 0;
binErrorof = 0;
binSumw2of = 0;
for(Int_t i = 0; i < nxgroup; i++){
ufbin = (oldxbin2 + i);
binContentuf += oldBins[ufbin];
binCountuf += oldCount[ufbin];
binErroruf += oldErrors[ufbin];
if(fBinSumw2.fN) binSumw2uf += oldBinw2[ufbin];
for(Int_t j = oldybin; j <= nybins+1; j++)
{
ofbin = ufbin + j*(nxbins + 2);
binContentof += oldBins[ofbin];
binCountof += oldCount[ofbin];
binErrorof += oldErrors[ofbin];
if(fBinSumw2.fN) binSumw2of += oldBinw2[ofbin];
}
}
ufbin = xbin;
ofbin = ufbin + (newybins + 1)*(newxbins + 2);
cu2[ufbin] = binContentuf;
er2[ufbin] = binErroruf;
en2[ufbin] = binCountuf;
if(fBinSumw2.fN) ew2[ufbin] = binSumw2uf;
cu2[ofbin] = binContentof;
er2[ofbin] = binErrorof;
en2[ofbin] = binCountof;
if(fBinSumw2.fN) ew2[ofbin] = binSumw2of;
oldxbin2 += nxgroup;
}
Int_t oldybin2 = 1;
for(Int_t ybin = 1; ybin <= newybins; ybin++){
binContentuf = 0;
binCountuf = 0;
binErroruf = 0;
binSumw2uf = 0;
binContentof = 0;
binCountof = 0;
binErrorof = 0;
binSumw2of = 0;
for(Int_t i = 0; i < nygroup; i++){
ufbin = (oldybin2 + i)*(nxbins+2);
binContentuf += oldBins[ufbin];
binCountuf += oldCount[ufbin];
binErroruf += oldErrors[ufbin];
if(fBinSumw2.fN) binSumw2uf += oldBinw2[ufbin];
for(Int_t j = oldxbin; j <= nxbins+1; j++)
{
ofbin = j + ufbin;
binContentof += oldBins[ofbin];
binCountof += oldCount[ofbin];
binErrorof += oldErrors[ofbin];
if(fBinSumw2.fN) binSumw2of += oldBinw2[ofbin];
}
}
ufbin = ybin * (newxbins + 2);
ofbin = newxbins + 1 + ufbin;
cu2[ufbin] = binContentuf;
er2[ufbin] = binErroruf;
en2[ufbin] = binCountuf;
if(fBinSumw2.fN) ew2[ufbin] = binSumw2uf;
cu2[ofbin] = binContentof;
er2[ofbin] = binErrorof;
en2[ofbin] = binCountof;
if(fBinSumw2.fN) ew2[ofbin] = binSumw2of;
oldybin2 += nygroup;
}
delete [] oldBins;
delete [] oldCount;
delete [] oldErrors;
if (oldBinw2) delete [] oldBinw2;
return hnew;
}
else{
if((newname) && (strlen(newname) > 0))
return (TProfile2D*)Clone(newname);
else
return this;
}
}
TProfile2D * TProfile2D::RebinX(Int_t ngroup,const char * newname ) {
return Rebin2D(ngroup,1,newname);
}
TProfile2D * TProfile2D::RebinY(Int_t ngroup,const char * newname ) {
return Rebin2D(1,ngroup,newname);
}
void TProfile2D::SavePrimitive(ostream &out, Option_t *option )
{
char quote = '"';
out <<" "<<endl;
out <<" "<<ClassName()<<" *";
out << GetName() << " = new " << ClassName() << "(" << quote
<< GetName() << quote << "," << quote<< GetTitle() << quote
<< "," << GetXaxis()->GetNbins();
out << "," << GetXaxis()->GetXmin()
<< "," << GetXaxis()->GetXmax();
out << "," << GetYaxis()->GetNbins();
out << "," << GetYaxis()->GetXmin()
<< "," << GetYaxis()->GetXmax();
out << "," << fZmin
<< "," << fZmax;
out << ");" << endl;
Int_t bin;
for (bin=0;bin<fNcells;bin++) {
Double_t bi = GetBinEntries(bin);
if (bi) {
out<<" "<<GetName()<<"->SetBinEntries("<<bin<<","<<bi<<");"<<endl;
}
}
for (bin=0;bin<fNcells;bin++) {
Double_t bc = fArray[bin];
if (bc) {
out<<" "<<GetName()<<"->SetBinContent("<<bin<<","<<bc<<");"<<endl;
}
}
if (fSumw2.fN) {
for (bin=0;bin<fNcells;bin++) {
Double_t be = TMath::Sqrt(fSumw2.fArray[bin]);
if (be) {
out<<" "<<GetName()<<"->SetBinError("<<bin<<","<<be<<");"<<endl;
}
}
}
TH1::SavePrimitiveHelp(out, GetName(), option);
}
void TProfile2D::Scale(Double_t c1, Option_t * option)
{
TProfileHelper::Scale(this, c1, option);
}
void TProfile2D::SetBinEntries(Int_t bin, Double_t w)
{
if (bin < 0 || bin >= fNcells) return;
fBinEntries.fArray[bin] = w;
}
void TProfile2D::SetBins(Int_t nx, Double_t xmin, Double_t xmax, Int_t ny, Double_t ymin, Double_t ymax)
{
fXaxis.Set(nx,xmin,xmax);
fYaxis.Set(ny,ymin,ymax);
fNcells = (nx+2)*(ny+2);
SetBinsLength(fNcells);
fBinEntries.Set(fNcells);
fSumw2.Set(fNcells);
if (fBinSumw2.fN) fBinSumw2.Set(fNcells);
}
void TProfile2D::SetBuffer(Int_t buffersize, Option_t *)
{
if (fBuffer) {
BufferEmpty();
delete [] fBuffer;
fBuffer = 0;
}
if (buffersize <= 0) {
fBufferSize = 0;
return;
}
if (buffersize < 100) buffersize = 100;
fBufferSize = 1 + 4*buffersize;
fBuffer = new Double_t[fBufferSize];
memset(fBuffer,0,8*fBufferSize);
}
void TProfile2D::SetErrorOption(Option_t *option)
{
TString opt = option;
opt.ToLower();
fErrorMode = kERRORMEAN;
if (opt.Contains("s")) fErrorMode = kERRORSPREAD;
if (opt.Contains("i")) fErrorMode = kERRORSPREADI;
if (opt.Contains("g")) fErrorMode = kERRORSPREADG;
}
void TProfile2D::Streamer(TBuffer &R__b)
{
if (R__b.IsReading()) {
UInt_t R__s, R__c;
Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
if (R__v > 2) {
R__b.ReadClassBuffer(TProfile2D::Class(), this, R__v, R__s, R__c);
return;
}
TH2D::Streamer(R__b);
fBinEntries.Streamer(R__b);
Int_t errorMode;
R__b >> errorMode;
fErrorMode = (EErrorType)errorMode;
if (R__v < 2) {
Float_t zmin,zmax;
R__b >> zmin; fZmin = zmin;
R__b >> zmax; fZmax = zmax;
} else {
R__b >> fZmin;
R__b >> fZmax;
}
R__b.CheckByteCount(R__s, R__c, TProfile2D::IsA());
} else {
R__b.WriteClassBuffer(TProfile2D::Class(),this);
}
}
void TProfile2D::Sumw2()
{
TProfileHelper::Sumw2(this);
}