Synchronus graph display

Hi,

Couple of questions around display of graphs

  1. When I draw a graph on a pad, it seems to include some empty space to the left and right of the actual data range on the x-axis. What do I do to display the graph exactly from xmin to xmax as specified in the data range supplied to the graph?

2)I have to display a set of graphs/multigraphs on a screen such that their x axis always display the same range. This should also hold when one of the axis is zoomed. But when i call setRange with same bin numbers on all these axis, they seem to be displayed slightly differently, the ticks do not remain aligned. I supply the same set of x axis values to all these graphs/multigraphs. Any solution?

Thanks in Advance.

Arin

{
   c1 = new TCanvas("c1","2 Graphs",200,10,700,500);
   const Int_t n = 20;
   Double_t x[n], y[n];
   for (Int_t i=0;i<n;i++) {
      x[i] = i*0.15;
      y[i] = 10*sin(x[i]+0.2);
   }
   g = new TGraph(n,x,y);
   g->SetMarkerStyle(3);
   g->Draw("ACP");

   Double_t x1 = TMath::MinElement(g->GetN(), g->GetX());
   Double_t x2 = TMath::MaxElement(g->GetN(), g->GetX());
   g->GetXaxis()->SetLimits(x1, x2);
}

You can also define the axis you need use:

gPad->DrawFrame(…) (see root.cern.ch/root/html/TPad.html#TPad:DrawFrame)

And the you draw your graphs without the option “A”.

You can also use DrawFrame to solve your previous problem.

Hi,

Thanks for the previous answers.
Related question…
After I display a set of TMultiGraphs each inside a sub-pad under the main canvas, i need to show the y axis values of the constituent graphs in some pavelabels on mouse movement. The Y values should correspond to the x position of the mouse. I use the following piece of code to translate the pixel position to X values on the axis…

[color=#0000BF][size=85]Double_t ratio, xVal;
ratio = (AbsPixeltoX(pixelX) - GetUxmin())/(GetUxmax() - GetUxmin());
xVal = GetUxmin() +ratio*(GetUxmax() - GetUxmin());[/size][/color]

Now the following piece of code doesnt seem to work to get the Y values on each graph inside the multigraphs

[color=#0000BF][size=85]Int_t bin = multiGraph->GetXaxis()->FindFixBin(xVal);
//repeat for each graph inside the multiGraph, but this returns 0
graph->GetHistogram()->GetBinContent(bin)[/size][/color]
The following two statements return a vlaue of 1

[size=85][color=#0000BF]graph->GetHistogram()->GetMinimumBin()
graph->GetHistogram()->GetMaximumBin()[/color][/size]

What am I doing wrong?
I tried graph->Eval(xVal) but that seems to be a time consuming calculation and consumes some serious CPU bandwidth if the graphs have a lot of data.

Can you send a small macro reproducing this behavior ?

Well, I am attaching a smaller version of my program here, maybe i’m doing something wrong in the bigger picture. Compiling and running CreateDisplay() from the prompt will show what im trying to do…

Might I draw your attention to the following function in the class TCustomCanvas. Here if I use
[color=#0000BF][size=85]TString Label = TString(gr->GetName())+ (TString(" : “)+= ([b]gr->GetHistogram()->GetBinContent/b));[/size][/color]
instead of
[color=#0000BF][size=85]TString Label = TString(gr->GetName())+ (TString(” : ")+= ([b]gr->Eval/b));[/size][/color]
, I get all zeros in the display.

[size=85][color=#0000BF]void ExecuteMouseMotionEvent(Double_t xVal)
{
TIter next(GetListOfPrimitives());
TPad* childPad=NULL;
while (childPad = dynamic_cast<TPad*>(next()))
{
TMultiGraph * multiGraph = dynamic_cast<TMultiGraph*>(childPad->FindObject(“TMultiGraph”));
Int_t bin = multiGraph->GetXaxis()->FindFixBin(xVal);
if(multiGraph)
{
TList * listOfGraphs = multiGraph->GetListOfGraphs();
TIter next(listOfGraphs);
TGraph* gr = NULL;
while ( gr = dynamic_cast<TGraph*>(next()) )
{
TPair* pair = dynamic_cast<TPair*>(fGraphtoPaveLabelMap->FindObject(gr));
if(pair)
{
TPaveLabel* paveLabel = dynamic_cast<TPaveLabel*>(pair->Value());
if(paveLabel)
{
TString Label = TString(gr->GetName())+ (TString(" : “)+= (gr->Eval(xVal)));
// TString Label = TString(gr->GetName())+ (TString(” : “)+= (gr->GetHistogram()->GetBinContent(bin)));
// TString Label = TString(gr->GetName())+ (TString(” : ")+= (multiGraph->GetHistogram()->GetBinContent(bin)));
paveLabel->SetLabel(Label.Data());
}
}
}
}
}
Modified(kTRUE);
Update();
}[/color][/size]
test.c (11.7 KB)

graph->GetHistogram()->GetMinimumBin()
graph->GetHistogram()->GetMaximumBin()

After having drawn the graph do gPad->Update() to make sure the underlying histogram has been created.

Tried this, didnt have any effect.
Apologies for piling up the big program on you earlier, I did it to be on the safe side so as to not omit anything. Basically the program compiles a set of multigraphs(a set of graphs inside each), that display time series data. X axis represents time series of course and is zoomable by a mouse drag accross any one of the axis.
Quite puzzling that gr->GetHistogram()->GetBinContent(bin) returns 0 all the time, even though the graphs are being displayed correctly as part of their multigraphs.

Any further advice?

graph->GetHistogram()->GetMinimumBin()
graph->GetHistogram()->GetMaximumBin()

Actually this cannot work on TMultigraph because the histogram you get, when you call GetHistogram() on a TMultigraph, is empty. It is just there to define the frame.

Well if you look at the things I tried, I tried it also by retrieving the graphs from the multigraph(bold underlined below), GetBinContent seems to return 0 even for the graphs…

[color=#000080][size=85]TString Label = TString(gr->GetName())+ (TString(" : “)+= (gr->Eval(xVal)));
// TString Label = TString(gr->GetName())+ (TString(" : ")+= (gr->GetHistogram()->GetBinContent(bin)));
// TString Label = TString(gr->GetName())+ (TString(” : ")+= (multiGraph->GetHistogram()->GetBinContent(bin)));[/size][/color]

When graphs are in a TMultigraph there no histogram created for each of them, but only a global one for the whole multigraph. And even if you plot a graph alone, the histogram created in background is there to draw the axis only and is empty as the following example demonstrates it:

{
   TCanvas *c1 = new TCanvas("c1","A Simple Graph Example",200,10,700,500);
   const Int_t n = 20;
   Double_t x[n], y[n];
   for (Int_t i=0;i<n;i++) {
     x[i] = i*0.1;
     y[i] = 10*sin(x[i]+0.2)-5;
   }
   gr = new TGraph(n,x,y);
   gr->Draw("A*");
   gPad->Update();
   gr->GetHistogram()->Draw("SAME HIST");
}

OK… But in that case the trial with the multigraph should have returned something? Even that shows zeros…

[color=#000080][size=85]// TString Label = TString(gr->GetName())+ (TString(" : ")+= (multiGraph->GetHistogram()->GetBinContent(bin)));[/size][/color]

Related question… A multigraph->GetHistogram() returns a TH1F, but a TH1F can represent y axis values for only one graph right? What happens when there are multiple graphs present in the multigraph…
I am probably missing some piece of the picture here…

Thanks for your patience.

multiGraph->GetHistogram()->GetBinContent(bin)

The histogram is empty so according to the definition of the function here:
root.cern.ch/root/html/TH1.html# … MinimumBin
returning 1 in fine as all the bins are equal to 0

Yes you are. I the case of TMultigraph one single histogram is computed for all the graphs is a such way that all the graphs fits in the range. Thats the idea of TMultigraph

Okay.
my original problem remains unsolved though… allow me to re-phrase it.
Lets say I have a pointer to a pad on which a multigraph has been drawn with several graphs inside it. Given a mouse pixel X location would I be able to determine the correponding Y values of each of those graphs?

you will have to loop on all the TGraph inside the TMultigraph and call Eval() at the X position from each of them.