#include <string.h>
#include "Riostream.h"
#include "TROOT.h"
#include "TGraphErrors.h"
#include "TStyle.h"
#include "TMath.h"
#include "TArrow.h"
#include "TBox.h"
#include "TVirtualPad.h"
#include "TH1.h"
#include "TF1.h"
#include "TVector.h"
#include "TVectorD.h"
#include "TStyle.h"
#include "TClass.h"
#include "TSystem.h"
#include <string>
ClassImp(TGraphErrors)
TGraphErrors::TGraphErrors(): TGraph()
{
if (!CtorAllocate()) return;
}
TGraphErrors::TGraphErrors(Int_t n)
: TGraph(n)
{
if (!CtorAllocate()) return;
FillZero(0, fNpoints);
}
TGraphErrors::TGraphErrors(Int_t n, const Float_t *x, const Float_t *y, const Float_t *ex, const Float_t *ey)
: TGraph(n, x, y)
{
if (!CtorAllocate()) return;
for (Int_t i = 0; i < n; i++) {
if (ex) fEX[i] = ex[i];
else fEX[i] = 0;
if (ey) fEY[i] = ey[i];
else fEY[i] = 0;
}
}
TGraphErrors::TGraphErrors(Int_t n, const Double_t *x, const Double_t *y, const Double_t *ex, const Double_t *ey)
: TGraph(n, x, y)
{
if (!CtorAllocate()) return;
n = sizeof(Double_t) * fNpoints;
if (ex) memcpy(fEX, ex, n);
else memset(fEX, 0, n);
if (ey) memcpy(fEY, ey, n);
else memset(fEY, 0, n);
}
TGraphErrors::TGraphErrors(const TVectorF &vx, const TVectorF &vy, const TVectorF &vex, const TVectorF &vey)
: TGraph()
{
fNpoints = TMath::Min(vx.GetNrows(), vy.GetNrows());
if (!TGraph::CtorAllocate()) return;
if (!CtorAllocate()) return;
Int_t ivxlow = vx.GetLwb();
Int_t ivylow = vy.GetLwb();
Int_t ivexlow = vex.GetLwb();
Int_t iveylow = vey.GetLwb();
for (Int_t i = 0; i < fNpoints; i++) {
fX[i] = vx(i + ivxlow);
fY[i] = vy(i + ivylow);
fEX[i] = vex(i + ivexlow);
fEY[i] = vey(i + iveylow);
}
}
TGraphErrors::TGraphErrors(const TVectorD &vx, const TVectorD &vy, const TVectorD &vex, const TVectorD &vey)
: TGraph()
{
fNpoints = TMath::Min(vx.GetNrows(), vy.GetNrows());
if (!TGraph::CtorAllocate()) return;
if (!CtorAllocate()) return;
Int_t ivxlow = vx.GetLwb();
Int_t ivylow = vy.GetLwb();
Int_t ivexlow = vex.GetLwb();
Int_t iveylow = vey.GetLwb();
for (Int_t i = 0; i < fNpoints; i++) {
fX[i] = vx(i + ivxlow);
fY[i] = vy(i + ivylow);
fEX[i] = vex(i + ivexlow);
fEY[i] = vey(i + iveylow);
}
}
TGraphErrors::TGraphErrors(const TGraphErrors &gr)
: TGraph(gr)
{
if (!CtorAllocate()) return;
Int_t n = sizeof(Double_t) * fNpoints;
memcpy(fEX, gr.fEX, n);
memcpy(fEY, gr.fEY, n);
}
TGraphErrors& TGraphErrors::operator=(const TGraphErrors &gr)
{
if (this != &gr) {
TGraph::operator=(gr);
if (!CtorAllocate()) return *this;
Int_t n = sizeof(Double_t) * fNpoints;
memcpy(fEX, gr.fEX, n);
memcpy(fEY, gr.fEY, n);
}
return *this;
}
TGraphErrors::TGraphErrors(const TH1 *h)
: TGraph(h)
{
if (!CtorAllocate()) return;
for (Int_t i = 0; i < fNpoints; i++) {
fEX[i] = h->GetBinWidth(i + 1) * gStyle->GetErrorX();
fEY[i] = h->GetBinError(i + 1);
}
}
TGraphErrors::TGraphErrors(const char *filename, const char *format, Option_t *option)
: TGraph(100)
{
if (!CtorAllocate()) return;
Double_t x, y, ex, ey;
TString fname = filename;
gSystem->ExpandPathName(fname);
ifstream infile(fname.Data());
if (!infile.good()) {
MakeZombie();
Error("TGraphErrors", "Cannot open file: %s, TGraphErrors is Zombie", filename);
fNpoints = 0;
return;
}
std::string line;
Int_t np = 0;
if (strcmp(option, "") == 0) {
Int_t ncol = CalculateScanfFields(format);
Int_t res;
while (std::getline(infile, line, '\n')) {
ex = ey = 0;
if (ncol < 3) {
res = sscanf(line.c_str(), format, &x, &y);
} else if (ncol < 4) {
res = sscanf(line.c_str(), format, &x, &y, &ey);
} else {
res = sscanf(line.c_str(), format, &x, &y, &ex, &ey);
}
if (res < 2) {
continue;
}
SetPoint(np, x, y);
SetPointError(np, ex, ey);
np++;
}
Set(np);
} else {
TString format_ = TString(format) ;
format_.ReplaceAll(" ", "") ;
format_.ReplaceAll("\t", "") ;
format_.ReplaceAll("lg", "") ;
format_.ReplaceAll("s", "") ;
format_.ReplaceAll("%*", "0") ;
format_.ReplaceAll("%", "1") ;
if (!format_.IsDigit()) {
Error("TGraphErrors", "Incorrect input format! Allowed format tags are {\"%%lg\",\"%%*lg\" or \"%%*s\"}");
return ;
}
Int_t ntokens = format_.Length() ;
if (ntokens < 2) {
Error("TGraphErrors", "Incorrect input format! Only %d tag(s) in format whereas at least 2 \"%%lg\" tags are expected!", ntokens);
return ;
}
Int_t ntokensToBeSaved = 0 ;
Bool_t * isTokenToBeSaved = new Bool_t [ntokens] ;
for (Int_t idx = 0; idx < ntokens; idx++) {
isTokenToBeSaved[idx] = TString::Format("%c", format_[idx]).Atoi() ;
if (isTokenToBeSaved[idx] == 1) {
ntokensToBeSaved++ ;
}
}
if (ntokens >= 2 && (ntokensToBeSaved < 2 || ntokensToBeSaved > 4)) {
Error("TGraphErrors", "Incorrect input format! There are %d \"%%lg\" tag(s) in format whereas 2,3 or 4 are expected!", ntokensToBeSaved);
return ;
}
Bool_t isLineToBeSkipped = kFALSE ;
char * token = NULL ;
TString token_str = "" ;
Int_t token_idx = 0 ;
Double_t * value = new Double_t [4] ;
for (Int_t k = 0; k < 4; k++) {
value[k] = 0. ;
}
Int_t value_idx = 0 ;
while (std::getline(infile, line, '\n')) {
if (line != "") {
token = strtok(const_cast<char*>(line.c_str()), option) ;
while (token != NULL && value_idx < ntokensToBeSaved) {
if (isTokenToBeSaved[token_idx]) {
token_str = TString(token) ;
token_str.ReplaceAll("\t", "") ;
if (!token_str.IsFloat()) {
isLineToBeSkipped = kTRUE ;
break ;
} else {
value[value_idx] = token_str.Atof() ;
value_idx++ ;
}
}
token = strtok(NULL, option) ;
token_idx++ ;
}
if (!isLineToBeSkipped && value_idx > 1) {
x = value[0] ;
y = value[1] ;
ex = value[2] ;
ey = value[3] ;
SetPoint(np, x, y) ;
SetPointError(np, ex, ey);
np++ ;
}
}
isLineToBeSkipped = kFALSE ;
token = NULL ;
token_idx = 0 ;
value_idx = 0 ;
}
Set(np) ;
delete [] isTokenToBeSaved ;
delete [] value ;
delete token ;
}
infile.close();
}
TGraphErrors::~TGraphErrors()
{
delete [] fEX;
delete [] fEY;
}
void TGraphErrors::Apply(TF1 *f)
{
Double_t x, y, ex, ey;
if (fHistogram) {
delete fHistogram;
fHistogram = 0;
}
for (Int_t i = 0; i < GetN(); i++) {
GetPoint(i, x, y);
ex = GetErrorX(i);
ey = GetErrorY(i);
SetPoint(i, x, f->Eval(x, y));
SetPointError(i, ex, TMath::Abs(f->Eval(x, y + ey) - f->Eval(x, y - ey)) / 2.);
}
if (gPad) gPad->Modified();
}
Int_t TGraphErrors::CalculateScanfFields(const char *fmt)
{
Int_t fields = 0;
while ((fmt = strchr(fmt, '%'))) {
Bool_t skip = kFALSE;
while (*(++fmt)) {
if ('[' == *fmt) {
if (*++fmt && '^' == *fmt) ++fmt;
if (*++fmt && ']' == *fmt) ++fmt;
while (*fmt && *fmt != ']')
++fmt;
if (!skip) ++fields;
break;
}
if ('%' == *fmt) break;
if ('*' == *fmt) {
skip = kTRUE;
} else if (strchr("dDiouxXxfegEscpn", *fmt)) {
if (!skip) ++fields;
break;
}
}
}
return fields;
}
void TGraphErrors::ComputeRange(Double_t &xmin, Double_t &ymin, Double_t &xmax, Double_t &ymax) const
{
TGraph::ComputeRange(xmin, ymin, xmax, ymax);
for (Int_t i = 0; i < fNpoints; i++) {
if (fX[i] - fEX[i] < xmin) {
if (gPad && gPad->GetLogx()) {
if (fEX[i] < fX[i]) xmin = fX[i] - fEX[i];
else xmin = TMath::Min(xmin, fX[i] / 3);
} else {
xmin = fX[i] - fEX[i];
}
}
if (fX[i] + fEX[i] > xmax) xmax = fX[i] + fEX[i];
if (fY[i] - fEY[i] < ymin) {
if (gPad && gPad->GetLogy()) {
if (fEY[i] < fY[i]) ymin = fY[i] - fEY[i];
else ymin = TMath::Min(ymin, fY[i] / 3);
} else {
ymin = fY[i] - fEY[i];
}
}
if (fY[i] + fEY[i] > ymax) ymax = fY[i] + fEY[i];
}
}
void TGraphErrors::CopyAndRelease(Double_t **newarrays,
Int_t ibegin, Int_t iend, Int_t obegin)
{
CopyPoints(newarrays, ibegin, iend, obegin);
if (newarrays) {
delete[] fX;
fX = newarrays[2];
delete[] fY;
fY = newarrays[3];
delete[] fEX;
fEX = newarrays[0];
delete[] fEY;
fEY = newarrays[1];
delete[] newarrays;
}
}
Bool_t TGraphErrors::CopyPoints(Double_t **arrays, Int_t ibegin, Int_t iend,
Int_t obegin)
{
if (TGraph::CopyPoints(arrays ? arrays + 2 : 0, ibegin, iend, obegin)) {
Int_t n = (iend - ibegin) * sizeof(Double_t);
if (arrays) {
memmove(&arrays[0][obegin], &fEX[ibegin], n);
memmove(&arrays[1][obegin], &fEY[ibegin], n);
} else {
memmove(&fEX[obegin], &fEX[ibegin], n);
memmove(&fEY[obegin], &fEY[ibegin], n);
}
return kTRUE;
} else {
return kFALSE;
}
}
Bool_t TGraphErrors::CtorAllocate()
{
if (!fNpoints) {
fEX = fEY = 0;
return kFALSE;
} else {
fEX = new Double_t[fMaxSize];
fEY = new Double_t[fMaxSize];
}
return kTRUE;
}
void TGraphErrors::FillZero(Int_t begin, Int_t end, Bool_t from_ctor)
{
if (!from_ctor) {
TGraph::FillZero(begin, end, from_ctor);
}
Int_t n = (end - begin) * sizeof(Double_t);
memset(fEX + begin, 0, n);
memset(fEY + begin, 0, n);
}
Double_t TGraphErrors::GetErrorX(Int_t i) const
{
if (i < 0 || i >= fNpoints) return -1;
if (fEX) return fEX[i];
return -1;
}
Double_t TGraphErrors::GetErrorY(Int_t i) const
{
if (i < 0 || i >= fNpoints) return -1;
if (fEY) return fEY[i];
return -1;
}
Double_t TGraphErrors::GetErrorXhigh(Int_t i) const
{
if (i < 0 || i >= fNpoints) return -1;
if (fEX) return fEX[i];
return -1;
}
Double_t TGraphErrors::GetErrorXlow(Int_t i) const
{
if (i < 0 || i >= fNpoints) return -1;
if (fEX) return fEX[i];
return -1;
}
Double_t TGraphErrors::GetErrorYhigh(Int_t i) const
{
if (i < 0 || i >= fNpoints) return -1;
if (fEY) return fEY[i];
return -1;
}
Double_t TGraphErrors::GetErrorYlow(Int_t i) const
{
if (i < 0 || i >= fNpoints) return -1;
if (fEY) return fEY[i];
return -1;
}
void TGraphErrors::Print(Option_t *) const
{
for (Int_t i = 0; i < fNpoints; i++) {
printf("x[%d]=%g, y[%d]=%g, ex[%d]=%g, ey[%d]=%g\n", i, fX[i], i, fY[i], i, fEX[i], i, fEY[i]);
}
}
void TGraphErrors::SavePrimitive(ostream &out, Option_t *option )
{
char quote = '"';
out << " " << endl;
if (gROOT->ClassSaved(TGraphErrors::Class())) {
out << " ";
} else {
out << " TGraphErrors *";
}
out << "gre = new TGraphErrors(" << fNpoints << ");" << endl;
out << " gre->SetName(" << quote << GetName() << quote << ");" << endl;
out << " gre->SetTitle(" << quote << GetTitle() << quote << ");" << endl;
SaveFillAttributes(out, "gre", 0, 1001);
SaveLineAttributes(out, "gre", 1, 1, 1);
SaveMarkerAttributes(out, "gre", 1, 1, 1);
for (Int_t i = 0; i < fNpoints; i++) {
out << " gre->SetPoint(" << i << "," << fX[i] << "," << fY[i] << ");" << endl;
out << " gre->SetPointError(" << i << "," << fEX[i] << "," << fEY[i] << ");" << endl;
}
static Int_t frameNumber = 0;
if (fHistogram) {
frameNumber++;
TString hname = fHistogram->GetName();
hname += frameNumber;
fHistogram->SetName(Form("Graph_%s", hname.Data()));
fHistogram->SavePrimitive(out, "nodraw");
out << " gre->SetHistogram(" << fHistogram->GetName() << ");" << endl;
out << " " << endl;
}
TIter next(fFunctions);
TObject *obj;
while ((obj = next())) {
obj->SavePrimitive(out, "nodraw");
if (obj->InheritsFrom("TPaveStats")) {
out << " gre->GetListOfFunctions()->Add(ptstats);" << endl;
out << " ptstats->SetParent(gre->GetListOfFunctions());" << endl;
} else {
out << " gre->GetListOfFunctions()->Add(" << obj->GetName() << ");" << endl;
}
}
const char *l = strstr(option, "multigraph");
if (l) {
out << " multigraph->Add(gre," << quote << l + 10 << quote << ");" << endl;
} else {
out << " gre->Draw(" << quote << option << quote << ");" << endl;
}
}
void TGraphErrors::SetPointError(Double_t ex, Double_t ey)
{
Int_t px = gPad->GetEventX();
Int_t py = gPad->GetEventY();
Int_t ipoint = -2;
Int_t i;
for (i = 0; i < fNpoints; i++) {
Int_t dpx = px - gPad->XtoAbsPixel(gPad->XtoPad(fX[i]));
Int_t dpy = py - gPad->YtoAbsPixel(gPad->YtoPad(fY[i]));
if (dpx * dpx + dpy * dpy < 25) {
ipoint = i;
break;
}
}
if (ipoint == -2) return;
fEX[ipoint] = ex;
fEY[ipoint] = ey;
gPad->Modified();
}
void TGraphErrors::SetPointError(Int_t i, Double_t ex, Double_t ey)
{
if (i < 0) return;
if (i >= fNpoints) {
TGraphErrors::SetPoint(i, 0, 0);
}
fEX[i] = ex;
fEY[i] = ey;
}
void TGraphErrors::Streamer(TBuffer &b)
{
if (b.IsReading()) {
UInt_t R__s, R__c;
Version_t R__v = b.ReadVersion(&R__s, &R__c);
if (R__v > 2) {
b.ReadClassBuffer(TGraphErrors::Class(), this, R__v, R__s, R__c);
return;
}
TGraph::Streamer(b);
fEX = new Double_t[fNpoints];
fEY = new Double_t[fNpoints];
if (R__v < 2) {
Float_t *ex = new Float_t[fNpoints];
Float_t *ey = new Float_t[fNpoints];
b.ReadFastArray(ex, fNpoints);
b.ReadFastArray(ey, fNpoints);
for (Int_t i = 0; i < fNpoints; i++) {
fEX[i] = ex[i];
fEY[i] = ey[i];
}
delete [] ey;
delete [] ex;
} else {
b.ReadFastArray(fEX, fNpoints);
b.ReadFastArray(fEY, fNpoints);
}
b.CheckByteCount(R__s, R__c, TGraphErrors::IsA());
} else {
b.WriteClassBuffer(TGraphErrors::Class(), this);
}
}
void TGraphErrors::SwapPoints(Int_t pos1, Int_t pos2)
{
SwapValues(fEX, pos1, pos2);
SwapValues(fEY, pos1, pos2);
TGraph::SwapPoints(pos1, pos2);
}