#include "TProfile3D.h"
#include "THashList.h"
#include "TMath.h"
#include "THLimitsFinder.h"
#include "Riostream.h"
#include "TVirtualPad.h"
#include "TError.h"
#include "TClass.h"
Bool_t TProfile3D::fgApproximate = kFALSE;
ClassImp(TProfile3D)
TProfile3D::TProfile3D() : TH3D()
{
fTsumwt = fTsumwt2 = 0;
fScaling = kFALSE;
}
TProfile3D::~TProfile3D()
{
}
TProfile3D::TProfile3D(const char *name,const char *title,Int_t nx,Double_t xlow,Double_t xup,Int_t ny,Double_t ylow,Double_t yup,Int_t nz, Double_t zlow,Double_t zup,Option_t *option)
: TH3D(name,title,nx,xlow,xup,ny,ylow,yup,nz,zlow,zup)
{
BuildOptions(0,0,option);
if (xlow >= xup || ylow >= yup || zlow >= zup) SetBuffer(fgBufferSize);
}
TProfile3D::TProfile3D(const char *name,const char *title,Int_t nx,const Double_t *xbins,Int_t ny,const Double_t *ybins,Int_t nz,const Double_t *zbins,Option_t *option)
: TH3D(name,title,nx,xbins,ny,ybins,nz,zbins)
{
BuildOptions(0,0,option);
}
void TProfile3D::BuildOptions(Double_t tmin, Double_t tmax, Option_t *option)
{
SetErrorOption(option);
fBinEntries.Set(fNcells);
Sumw2();
fTmin = tmin;
fTmax = tmax;
fScaling = kFALSE;
fTsumwt = fTsumwt2 = 0;
}
TProfile3D::TProfile3D(const TProfile3D &profile) : TH3D()
{
((TProfile3D&)profile).Copy(*this);
}
void TProfile3D::Add(TF1 *, Double_t , Option_t*)
{
Error("Add","Function not implemented for TProfile3D");
return;
}
void TProfile3D::Add(const TH1 *h1, Double_t c1)
{
if (!h1) {
Error("Add","Attempt to add a non-existing profile");
return;
}
if (!h1->InheritsFrom("TProfile3D")) {
Error("Add","Attempt to add a non-profile2D object");
return;
}
TProfile3D *p1 = (TProfile3D*)h1;
Int_t nx = GetNbinsX();
if (nx != p1->GetNbinsX()) {
Error("Add","Attempt to add profiles with different number of bins");
return;
}
Int_t ny = GetNbinsY();
if (ny != p1->GetNbinsY()) {
Error("Add","Attempt to add profiles with different number of bins");
return;
}
Int_t nz = GetNbinsZ();
if (nz != p1->GetNbinsZ()) {
Error("Add","Attempt to add profiles with different number of bins");
return;
}
Double_t ac1 = TMath::Abs(c1);
fEntries += ac1*p1->GetEntries();
fTsumw += ac1*p1->fTsumw;
fTsumw2 += c1*c1*p1->fTsumw2;
fTsumwx += ac1*p1->fTsumwx;
fTsumwx2 += ac1*p1->fTsumwx2;
fTsumwy += ac1*p1->fTsumwy;
fTsumwy2 += ac1*p1->fTsumwy2;
fTsumwxy += ac1*p1->fTsumwxy;
fTsumwz += ac1*p1->fTsumwz;
fTsumwz2 += ac1*p1->fTsumwz2;
fTsumwxz += ac1*p1->fTsumwxz;
fTsumwyz += ac1*p1->fTsumwyz;
fTsumwt += ac1*p1->fTsumwt;
fTsumwt2 += ac1*p1->fTsumwt2;
Int_t bin,binx,biny,binz;
Double_t *cu1 = p1->GetW();
Double_t *er1 = p1->GetW2();
Double_t *en1 = p1->GetB();
for (binx =0;binx<=nx+1;binx++) {
for (biny =0;biny<=ny+1;biny++) {
for (binz =0;binz<=nz+1;binz++) {
bin = GetBin(binx,biny,binz);
fArray[bin] += c1*cu1[bin];
fSumw2.fArray[bin] += ac1*er1[bin];
fBinEntries.fArray[bin] += ac1*en1[bin];
}
}
}
}
void TProfile3D::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("TProfile3D")) {
Error("Add","Attempt to add a non-profile3D object");
return;
}
TProfile3D *p1 = (TProfile3D*)h1;
if (!h2->InheritsFrom("TProfile3D")) {
Error("Add","Attempt to add a non-profile3D object");
return;
}
TProfile3D *p2 = (TProfile3D*)h2;
Int_t nx = GetNbinsX();
if (nx != p1->GetNbinsX() || nx != p2->GetNbinsX()) {
Error("Add","Attempt to add profiles with different number of bins");
return;
}
Int_t ny = GetNbinsY();
if (ny != p1->GetNbinsY() || ny != p2->GetNbinsY()) {
Error("Add","Attempt to add profiles with different number of bins");
return;
}
Int_t nz = GetNbinsZ();
if (nz != p1->GetNbinsZ() || nz != p2->GetNbinsZ()) {
Error("Add","Attempt to add profiles with different number of bins");
return;
}
Double_t ac1 = TMath::Abs(c1);
Double_t ac2 = TMath::Abs(c2);
fEntries = ac1*p1->GetEntries() + ac2*p2->GetEntries();
fTsumw = ac1*p1->fTsumw + ac2*p2->fTsumw;
fTsumw2 = c1*c1*p1->fTsumw2 + c2*c2*p2->fTsumw2;
fTsumwx = ac1*p1->fTsumwx + ac2*p2->fTsumwx;
fTsumwx2 = ac1*p1->fTsumwx2 + ac2*p2->fTsumwx2;
fTsumwy = ac1*p1->fTsumwy + ac2*p2->fTsumwy;
fTsumwy2 = ac1*p1->fTsumwy2 + ac2*p2->fTsumwy2;
fTsumwxy = ac1*p1->fTsumwxy + ac2*p2->fTsumwxy;
fTsumwz = ac1*p1->fTsumwz + ac2*p2->fTsumwz;
fTsumwz2 = ac1*p1->fTsumwz2 + ac2*p2->fTsumwz2;
fTsumwxz = ac1*p1->fTsumwxz + ac2*p2->fTsumwxz;
fTsumwyz = ac1*p1->fTsumwyz + ac2*p2->fTsumwyz;
fTsumwt = ac1*p1->fTsumwt + ac2*p2->fTsumwt;
fTsumwt2 = ac1*p1->fTsumwt2 + ac2*p2->fTsumwt2;
Int_t bin,binx,biny,binz;
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();
for (binx =0;binx<=nx+1;binx++) {
for (biny =0;biny<=ny+1;biny++) {
for (binz =0;binz<=nz+1;binz++) {
bin = GetBin(binx,biny,binz);
fArray[bin] = c1*cu1[bin] + c2*cu2[bin];
if (fScaling) {
fSumw2.fArray[bin] = ac1*ac1*er1[bin] + ac2*ac2*er2[bin];
fBinEntries.fArray[bin] = en1[bin];
} else {
fSumw2.fArray[bin] = ac1*er1[bin] + ac2*er2[bin];
fBinEntries.fArray[bin] = ac1*en1[bin] + ac2*en2[bin];
}
}
}
}
}
void TProfile3D::Approximate(Bool_t approx)
{
fgApproximate = approx;
}
Int_t TProfile3D::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();
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;
Double_t zmin = fBuffer[4];
Double_t zmax = zmin;
for (Int_t i=1;i<nbentries;i++) {
Double_t x = fBuffer[5*i+2];
if (x < xmin) xmin = x;
if (x > xmax) xmax = x;
Double_t y = fBuffer[5*i+3];
if (y < ymin) ymin = y;
if (y > ymax) ymax = y;
Double_t z = fBuffer[5*i+4];
if (z < zmin) zmin = z;
if (z > zmax) zmax = z;
}
if (fXaxis.GetXmax() <= fXaxis.GetXmin() || fYaxis.GetXmax() <= fYaxis.GetXmin() || fZaxis.GetXmax() <= fZaxis.GetXmin()) {
THLimitsFinder::GetLimitsFinder()->FindGoodLimits(this,xmin,xmax,ymin,ymax,zmin,zmax);
} 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);
if (zmin < fZaxis.GetXmin()) RebinAxis(zmin,&fZaxis);
if (zmax >= fZaxis.GetXmax()) RebinAxis(zmax,&fZaxis);
fBuffer = buffer;
fBufferSize = keep;
}
}
fBuffer = 0;
for (Int_t i=0;i<nbentries;i++) {
Fill(buffer[5*i+2],buffer[5*i+3],buffer[5*i+4],buffer[5*i+5],buffer[5*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 TProfile3D::BufferFill(Double_t x, Double_t y, Double_t z, Double_t t, 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();
fBuffer = buffer;
}
}
if (5*nbentries+5 >= fBufferSize) {
BufferEmpty(1);
return Fill(x,y,z,t,w);
}
fBuffer[5*nbentries+1] = w;
fBuffer[5*nbentries+2] = x;
fBuffer[5*nbentries+3] = y;
fBuffer[5*nbentries+4] = z;
fBuffer[5*nbentries+5] = t;
fBuffer[0] += 1;
return -2;
}
void TProfile3D::Copy(TObject &obj) const
{
TH3D::Copy(((TProfile3D&)obj));
fBinEntries.Copy(((TProfile3D&)obj).fBinEntries);
for (int bin=0;bin<fNcells;bin++) {
((TProfile3D&)obj).fArray[bin] = fArray[bin];
((TProfile3D&)obj).fSumw2.fArray[bin] = fSumw2.fArray[bin];
}
((TProfile3D&)obj).fTmin = fTmin;
((TProfile3D&)obj).fTmax = fTmax;
((TProfile3D&)obj).fScaling = fScaling;
((TProfile3D&)obj).fErrorMode = fErrorMode;
((TProfile3D&)obj).fTsumwt = fTsumwt;
((TProfile3D&)obj).fTsumwt2 = fTsumwt2;
}
void TProfile3D::Divide(TF1 *, Double_t )
{
Error("Divide","Function not implemented for TProfile3D");
return;
}
void TProfile3D::Divide(const TH1 *h1)
{
if (!h1) {
Error("Divide","Attempt to divide a non-existing profile2D");
return;
}
if (!h1->InheritsFrom("TProfile3D")) {
Error("Divide","Attempt to divide a non-profile2D object");
return;
}
TProfile3D *p1 = (TProfile3D*)h1;
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;
}
Int_t nz = GetNbinsZ();
if (nz != p1->GetNbinsZ()) {
Error("Divide","Attempt to divide profiles with different number of bins");
return;
}
fEntries = fTsumw = fTsumw2 = fTsumwx = fTsumwx2 = 0;
Int_t bin,binx,biny,binz;
Double_t *cu1 = p1->GetW();
Double_t *er1 = p1->GetW2();
Double_t *en1 = p1->GetB();
Double_t c0,c1,w,u,x,y,z;
for (binx =0;binx<=nx+1;binx++) {
for (biny =0;biny<=ny+1;biny++) {
for (binz =0;binz<=nz+1;binz++) {
bin = GetBin(binx,biny,binz);
c0 = fArray[bin];
c1 = cu1[bin];
if (c1) w = c0/c1;
else w = 0;
fArray[bin] = w;
u = TMath::Abs(w);
x = fXaxis.GetBinCenter(binx);
y = fYaxis.GetBinCenter(biny);
z = fZaxis.GetBinCenter(binz);
fEntries++;
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;
fTsumwz2 += u*z;
fTsumwxz += u*x*z;
fTsumwyz += u*y*z;
fTsumwt += u;
fTsumwt2 += u*u;
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];
}
}
}
}
void TProfile3D::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("TProfile3D")) {
Error("Divide","Attempt to divide a non-profile2D object");
return;
}
TProfile3D *p1 = (TProfile3D*)h1;
if (!h2->InheritsFrom("TProfile3D")) {
Error("Divide","Attempt to divide a non-profile2D object");
return;
}
TProfile3D *p2 = (TProfile3D*)h2;
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;
}
Int_t nz = GetNbinsZ();
if (nz != p1->GetNbinsZ() || nz != p2->GetNbinsZ()) {
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,binz;
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,u,x,y,z,ac1,ac2;
ac1 = TMath::Abs(c1);
ac2 = TMath::Abs(c2);
for (binx =0;binx<=nx+1;binx++) {
for (biny =0;biny<=ny+1;biny++) {
for (binz =0;binz<=nz+1;binz++) {
bin = GetBin(binx,biny,binz);
b1 = cu1[bin];
b2 = cu2[bin];
if (b2) w = c1*b1/(c2*b2);
else w = 0;
fArray[bin] = w;
u = TMath::Abs(w);
x = fXaxis.GetBinCenter(binx);
y = fYaxis.GetBinCenter(biny);
z = fZaxis.GetBinCenter(biny);
fEntries++;
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;
fTsumwxz += u*x*z;
fTsumwyz += u*y*z;
fTsumwt += u;
fTsumwt2 += u*u;
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 *TProfile3D::DrawCopy(Option_t *option) const
{
TString opt = option;
opt.ToLower();
if (gPad && !opt.Contains("same")) gPad->Clear();
TProfile3D *newpf = new TProfile3D();
Copy(*newpf);
newpf->SetDirectory(0);
newpf->SetBit(kCanDelete);
newpf->AppendPad(option);
return newpf;
}
Int_t TProfile3D::Fill(Double_t x, Double_t y, Double_t z, Double_t t)
{
if (fBuffer) return BufferFill(x,y,z,t,1);
Int_t bin,binx,biny,binz;
if (fTmin != fTmax) {
if (t <fTmin || t> fTmax) return -1;
}
fEntries++;
binx =fXaxis.FindBin(x);
biny =fYaxis.FindBin(y);
binz =fZaxis.FindBin(z);
bin = GetBin(binx,biny,binz);
AddBinContent(bin, t);
fSumw2.fArray[bin] += (Double_t)t*t;
fBinEntries.fArray[bin] += 1;
if (binx == 0 || binx > fXaxis.GetNbins()) {
if (!fgStatOverflows) return -1;
}
if (biny == 0 || biny > fYaxis.GetNbins()) {
if (!fgStatOverflows) return -1;
}
if (binz == 0 || binz > fZaxis.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;
fTsumwxz += x*z;
fTsumwyz += y*z;
fTsumwt += t;
fTsumwt2 += t*t;
return bin;
}
Int_t TProfile3D::Fill(Double_t x, Double_t y, Double_t z, Double_t t, Double_t w)
{
if (fBuffer) return BufferFill(x,y,z,t,w);
Int_t bin,binx,biny,binz;
if (fTmin != fTmax) {
if (t <fTmin || z> fTmax) return -1;
}
Double_t u= (w > 0 ? w : -w);
fEntries++;
binx =fXaxis.FindBin(x);
biny =fYaxis.FindBin(y);
binz =fZaxis.FindBin(z);
bin = GetBin(binx,biny,binz);
AddBinContent(bin, u*t);
fSumw2.fArray[bin] += u*t*t;
fBinEntries.fArray[bin] += u;
if (binx == 0 || binx > fXaxis.GetNbins()) {
if (!fgStatOverflows) return -1;
}
if (biny == 0 || biny > fYaxis.GetNbins()) {
if (!fgStatOverflows) return -1;
}
if (binz == 0 || binz > fZaxis.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;
fTsumwxz += u*x*z;
fTsumwyz += u*y*z;
fTsumwt += u*t;
fTsumwt2 += u*t*t;
return bin;
}
Double_t TProfile3D::GetBinContent(Int_t bin) const
{
if (fBuffer) ((TProfile3D*)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 TProfile3D::GetBinEntries(Int_t bin) const
{
if (fBuffer) ((TProfile3D*)this)->BufferEmpty();
if (bin < 0 || bin >= fNcells) return 0;
return fBinEntries.fArray[bin];
}
Double_t TProfile3D::GetBinError(Int_t bin) const
{
if (fBuffer) ((TProfile3D*)this)->BufferEmpty();
if (bin < 0 || bin >= fNcells) return 0;
Double_t cont = fArray[bin];
Double_t sum = fBinEntries.fArray[bin];
Double_t err2 = fSumw2.fArray[bin];
if (sum == 0) return 0;
Double_t eprim;
Double_t contsum = cont/sum;
Double_t eprim2 = TMath::Abs(err2/sum - contsum*contsum);
eprim = TMath::Sqrt(eprim2);
Double_t test = 1;
if (err2 != 0 && sum < 5) test = eprim2*sum/err2;
if (fgApproximate && fNcells <=1000404 && (test < 1.e-4 || eprim2 < 1e-6)) {
Double_t scont, ssum, serr2;
scont = ssum = serr2 = 0;
for (Int_t i=1;i<fNcells;i++) {
if (fSumw2.fArray[i] <= 0) continue;
scont += fArray[i];
ssum += fBinEntries.fArray[i];
serr2 += fSumw2.fArray[i];
}
Double_t scontsum = scont/ssum;
Double_t seprim2 = TMath::Abs(serr2/ssum - scontsum*scontsum);
eprim = TMath::Sqrt(seprim2);
}
if (fErrorMode == kERRORMEAN) return eprim/TMath::Sqrt(sum);
else if (fErrorMode == kERRORSPREAD) return eprim;
else if (fErrorMode == kERRORSPREADI) {
if (eprim != 0) return eprim/TMath::Sqrt(sum);
return 1/TMath::Sqrt(12*sum);
}
else if (fErrorMode == kERRORSPREADG) {
return eprim/TMath::Sqrt(sum);
}
else return eprim;
}
Option_t *TProfile3D::GetErrorOption() const
{
if (fErrorMode == kERRORSPREAD) return "s";
if (fErrorMode == kERRORSPREADI) return "i";
if (fErrorMode == kERRORSPREADG) return "g";
return "";
}
void TProfile3D::GetStats(Double_t *stats) const
{
if (fBuffer) ((TProfile3D*)this)->BufferEmpty();
if (fTsumw == 0 || fXaxis.TestBit(TAxis::kAxisRange) || fYaxis.TestBit(TAxis::kAxisRange)) {
Int_t bin, binx, biny,binz;
Double_t w;
Double_t x,y,z;
for (bin=0;bin<kNstat;bin++) stats[bin] = 0;
if (!fBinEntries.fArray) return;
for (binz=fZaxis.GetFirst();binz<=fZaxis.GetLast();binz++) {
z = fZaxis.GetBinCenter(binz);
for (biny=fYaxis.GetFirst();biny<=fYaxis.GetLast();biny++) {
y = fYaxis.GetBinCenter(biny);
for (binx=fXaxis.GetFirst();binx<=fXaxis.GetLast();binx++) {
bin = GetBin(binx,biny,binz);
w = fBinEntries.fArray[bin];
x = fXaxis.GetBinCenter(binx);
stats[0] += w;
stats[1] += w*w;
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] += w*z;
stats[8] += w*z*z;
stats[9] += w*x*z;
stats[10] += w*y*z;
stats[11] += fArray[bin];
stats[12] += 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;
stats[9] = fTsumwxz;
stats[10] = fTsumwyz;
stats[11] = fTsumwt;
stats[12] = fTsumwt2;
}
}
Long64_t TProfile3D::Merge(TCollection *li)
{
if (!li) return 0;
if (li->IsEmpty()) return (Int_t) GetEntries();
TList inlist;
TH1* hclone = (TH1*)Clone("FirstClone");
R__ASSERT(hclone);
BufferEmpty(1);
Reset();
SetEntries(0);
inlist.Add(hclone);
inlist.AddAll(li);
TAxis newXAxis;
TAxis newYAxis;
TAxis newZAxis;
Bool_t initialLimitsFound = kFALSE;
Bool_t same = kTRUE;
Bool_t allHaveLimits = kTRUE;
TIter next(&inlist);
while (TObject *o = next()) {
TProfile3D* h = dynamic_cast<TProfile3D*> (o);
if (!h) {
Error("Add","Attempt to add object of class: %s to a %s",
o->ClassName(),this->ClassName());
return -1;
}
Bool_t hasLimits = h->GetXaxis()->GetXmin() < h->GetXaxis()->GetXmax();
allHaveLimits = allHaveLimits && hasLimits;
if (hasLimits) {
h->BufferEmpty();
if (!initialLimitsFound) {
initialLimitsFound = kTRUE;
newXAxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(),
h->GetXaxis()->GetXmax());
newYAxis.Set(h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(),
h->GetYaxis()->GetXmax());
newZAxis.Set(h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXmin(),
h->GetZaxis()->GetXmax());
}
else {
if (!RecomputeAxisLimits(newXAxis, *(h->GetXaxis()))) {
Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
"first: (%d, %f, %f), second: (%d, %f, %f)",
newXAxis.GetNbins(), newXAxis.GetXmin(), newXAxis.GetXmax(),
h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(),
h->GetXaxis()->GetXmax());
}
if (!RecomputeAxisLimits(newYAxis, *(h->GetYaxis()))) {
Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
"first: (%d, %f, %f), second: (%d, %f, %f)",
newYAxis.GetNbins(), newYAxis.GetXmin(), newYAxis.GetXmax(),
h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(),
h->GetYaxis()->GetXmax());
}
if (!RecomputeAxisLimits(newZAxis, *(h->GetZaxis()))) {
Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
"first: (%d, %f, %f), second: (%d, %f, %f)",
newZAxis.GetNbins(), newZAxis.GetXmin(), newZAxis.GetXmax(),
h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXmin(),
h->GetZaxis()->GetXmax());
}
}
}
}
next.Reset();
same = same && SameLimitsAndNBins(newXAxis, *GetXaxis())
&& SameLimitsAndNBins(newYAxis, *GetYaxis())
&& SameLimitsAndNBins(newZAxis, *GetZaxis());
if (!same && initialLimitsFound)
SetBins(newXAxis.GetNbins(), newXAxis.GetXmin(), newXAxis.GetXmax(),
newYAxis.GetNbins(), newYAxis.GetXmin(), newYAxis.GetXmax(),
newZAxis.GetNbins(), newZAxis.GetXmin(), newZAxis.GetXmax());
if (!allHaveLimits) {
while (TProfile3D* h = dynamic_cast<TProfile3D*> (next())) {
if (h->GetXaxis()->GetXmin() >= h->GetXaxis()->GetXmax() && h->fBuffer) {
Int_t nbentries = (Int_t)h->fBuffer[0];
for (Int_t i = 0; i < nbentries; i++)
Fill(h->fBuffer[5*i + 2], h->fBuffer[5*i + 3],
h->fBuffer[5*i + 4], h->fBuffer[5*i + 5], h->fBuffer[5*i + 1]);
}
}
if (!initialLimitsFound)
return (Int_t) GetEntries();
next.Reset();
}
Double_t stats[kNstat], totstats[kNstat];
for (Int_t i=0;i<kNstat;i++) {totstats[i] = stats[i] = 0;}
GetStats(totstats);
Double_t nentries = GetEntries();
Int_t binx, biny, binz, ix, iy, iz, nx, ny, nz, bin, ibin;
Int_t nbix = fXaxis.GetNbins();
Int_t nbiy = fYaxis.GetNbins();
Bool_t canRebin=TestBit(kCanRebin);
ResetBit(kCanRebin);
while (TProfile3D* h=(TProfile3D*)next()) {
if (h->GetXaxis()->GetXmin() < h->GetXaxis()->GetXmax()) {
h->GetStats(stats);
for (Int_t i = 0; i < kNstat; i++)
totstats[i] += stats[i];
nentries += h->GetEntries();
nx = h->GetXaxis()->GetNbins();
ny = h->GetYaxis()->GetNbins();
nz = h->GetZaxis()->GetNbins();
for (binz = 0; binz <= nz + 1; binz++) {
iz = fZaxis.FindBin(h->GetZaxis()->GetBinCenter(binz));
for (biny = 0; biny <= ny + 1; biny++) {
iy = fYaxis.FindBin(h->GetYaxis()->GetBinCenter(biny));
for (binx = 0; binx <= nx + 1; binx++) {
ix = fXaxis.FindBin(h->GetXaxis()->GetBinCenter(binx));
bin = binx +(nx+2)*(biny + (ny+2)*binz);
ibin = ix +(nbix+2)*(iy + (nbiy+2)*iz);
if ((!same) && (binx == 0 || binx == nx + 1
|| biny == 0 || biny == ny + 1
|| binz == 0 || binz == nz + 1)) {
if (h->GetW()[bin] != 0) {
Error("Merge", "Cannot merge histograms - the histograms have"
" different limits and undeflows/overflows are present."
" The initial histogram is now broken!");
return -1;
}
}
fArray[ibin] += h->GetW()[bin];
fSumw2.fArray[ibin] += h->GetW2()[bin];
fBinEntries.fArray[ibin] += h->GetB()[bin];
}
}
}
fEntries += h->GetEntries();
fTsumw += h->fTsumw;
fTsumw2 += h->fTsumw2;
fTsumwx += h->fTsumwx;
fTsumwx2 += h->fTsumwx2;
fTsumwy += h->fTsumwy;
fTsumwy2 += h->fTsumwy2;
fTsumwxy += h->fTsumwxy;
fTsumwz += h->fTsumwz;
fTsumwz2 += h->fTsumwz2;
fTsumwxz += h->fTsumwxz;
fTsumwyz += h->fTsumwyz;
fTsumwt += h->fTsumwt;
fTsumwt2 += h->fTsumwt2;
}
}
if (canRebin) SetBit(kCanRebin);
PutStats(totstats);
SetEntries(nentries);
inlist.Remove(hclone);
delete hclone;
return (Long64_t)nentries;
}
void TProfile3D::Multiply(TF1 *, Double_t )
{
Error("Multiply","Function not implemented for TProfile3D");
return;
}
void TProfile3D::Multiply(const TH1 *)
{
Error("Multiply","Multiplication of profile2D histograms not implemented");
}
void TProfile3D::Multiply(const TH1 *, const TH1 *, Double_t, Double_t, Option_t *)
{
Error("Multiply","Multiplication of profile2D histograms not implemented");
}
TH3D *TProfile3D::ProjectionXYZ(const char *name, Option_t *option) const
{
TString opt = option;
opt.ToLower();
Int_t nx = fXaxis.GetNbins();
Int_t ny = fYaxis.GetNbins();
Int_t nz = fZaxis.GetNbins();
char *pname = (char*)name;
if (strcmp(name,"_px") == 0) {
Int_t nch = strlen(GetName()) + 4;
pname = new char[nch];
sprintf(pname,"%s%s",GetName(),name);
}
TH3D *h1 = new TH3D(pname,GetTitle(),nx,fXaxis.GetXmin(),fXaxis.GetXmax(),ny,fYaxis.GetXmin(),fYaxis.GetXmax(),nz,fZaxis.GetXmin(),fZaxis.GetXmax());
Bool_t computeErrors = kFALSE;
Bool_t cequalErrors = kFALSE;
Bool_t binEntries = kFALSE;
if (opt.Contains("b")) binEntries = kTRUE;
if (opt.Contains("e")) computeErrors = kTRUE;
if (opt.Contains("c=e")) {cequalErrors = kTRUE; computeErrors=kFALSE;}
if (computeErrors) h1->Sumw2();
if (pname != name) delete [] pname;
Int_t bin,binx,biny,binz;
Double_t cont,err;
for (binx =0;binx<=nx+1;binx++) {
for (biny =0;biny<=ny+1;biny++) {
for (binz =0;binz<=nz+1;binz++) {
bin = GetBin(binx,biny,binz);
if (binEntries) cont = GetBinEntries(bin);
else cont = GetBinContent(bin);
err = GetBinError(bin);
if (cequalErrors) h1->SetBinContent(binx,biny,binz, err);
else h1->SetBinContent(binx,biny,binz,cont);
if (computeErrors) h1->SetBinError(binx,biny,binz,err);
}
}
}
h1->SetEntries(fEntries);
return h1;
}
void TProfile3D::PutStats(Double_t *stats)
{
TH3::PutStats(stats);
fTsumwt = stats[11];
fTsumwt2 = stats[12];
}
void TProfile3D::Reset(Option_t *option)
{
TH3D::Reset(option);
fBinEntries.Reset();
TString opt = option;
opt.ToUpper();
if (opt.Contains("ICE")) return;
fTsumwt = fTsumwt2 = 0;
}
void TProfile3D::RebinAxis(Double_t x, TAxis *axis)
{
if (!TestBit(kCanRebin)) return;
if (axis->GetXmin() >= axis->GetXmax()) return;
if (axis->GetNbins() <= 0) return;
Double_t xmin, xmax;
if (!FindNewAxisLimits(axis, x, xmin, xmax))
return;
TProfile3D *hold = (TProfile3D*)Clone();
hold->SetDirectory(0);
axis->SetLimits(xmin,xmax);
Int_t nbinsx = fXaxis.GetNbins();
Int_t nbinsy = fYaxis.GetNbins();
Int_t nbinsz = fZaxis.GetNbins();
Reset("ICE");
Double_t bx,by,bz;
Int_t ix, iy, iz, binx, biny, binz;
for (binz=1;binz<=nbinsz;binz++) {
bz = hold->GetZaxis()->GetBinCenter(binz);
iz = fZaxis.FindFixBin(bz);
for (biny=1;biny<=nbinsy;biny++) {
by = hold->GetYaxis()->GetBinCenter(biny);
iy = fYaxis.FindFixBin(by);
for (binx=1;binx<=nbinsx;binx++) {
bx = hold->GetXaxis()->GetBinCenter(binx);
ix = fXaxis.FindFixBin(bx);
Int_t sourceBin = hold->GetBin(binx,biny,binz);
Int_t destinationBin = GetBin(ix,iy,iz);
AddBinContent(destinationBin, hold->fArray[sourceBin]);
fBinEntries.fArray[destinationBin] += hold->fBinEntries.fArray[sourceBin];
fSumw2.fArray[destinationBin] += hold->fSumw2.fArray[sourceBin];
}
}
}
fTsumwt = hold->fTsumwt;
fTsumwt2 = hold->fTsumwt2;
delete hold;
}
void TProfile3D::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 << "," << GetZaxis()->GetNbins();
out << "," << GetZaxis()->GetXmin()
<< "," << GetZaxis()->GetXmax();
out << "," << fTmin
<< "," << fTmax;
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, option);
}
void TProfile3D::Scale(Double_t c1, Option_t *)
{
Double_t ent = fEntries;
fScaling = kTRUE;
Add(this,this,c1,0);
fScaling = kFALSE;
fEntries = ent;
}
void TProfile3D::SetBinEntries(Int_t bin, Double_t w)
{
if (bin < 0 || bin >= fNcells) return;
fBinEntries.fArray[bin] = w;
}
void TProfile3D::SetBins(Int_t nx, Double_t xmin, Double_t xmax, Int_t ny, Double_t ymin, Double_t ymax, Int_t nz, Double_t zmin, Double_t zmax)
{
fXaxis.Set(nx,xmin,xmax);
fYaxis.Set(ny,ymin,ymax);
fZaxis.Set(ny,zmin,zmax);
fNcells = (nx+2)*(ny+2)*(nz+2);
fBinEntries.Set(fNcells);
fSumw2.Set(fNcells);
}
void TProfile3D::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 + 5*buffersize;
fBuffer = new Double_t[fBufferSize];
memset(fBuffer,0,8*fBufferSize);
}
void TProfile3D::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;
}
Last change: Fri Nov 28 16:56:45 2008
Last generated: 2008-11-28 16:56
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.