How to change the position of axes of a graph

Hello everyone,

I’m trying to make a graph and I want it to go below the X axis. Unfortunately, it seems that root automatically arranges the axes so that the graph is always contained inside the box. Here is an image of my graph:


I want it so that X axis start at Y=0 and vice versa. Of course, Y axis should go below too. How can I achieve this?

Example:
image
©Erhan Gülmez, Bogazici University, Istanbul, Turkey

I’ve read that topic before posting and either I’m missing something or it just changes the ranges of the axes. If i’m missing something would you point out what it is? I’ve also added the graph visual that I’m trying to get.

TGaxis

I’ve tried that too and could set another axis at my preferred position but couldn’t get rid of the original axis.

There are examples in the TGaxis class reference that show how one can use the TPad::Range to set a world coordinate system for a pad (search for “Range”).

Try also: grep -r '>Range(' ${ROOTSYS}/t[eu]*

I couldn’t figure it out from there either but I haven’t given up yet :slight_smile:
Thanks for your time.

Maybe @couet has a better idea.

{
  // create the graph
  Double_t x[3] = {0., 400., 2700.};
  Double_t y[3] = {2.3, -0.1, -0.4};
  TGraph *g = new TGraph(3, x, y);
  Double_t xmin = -300., xmax = 3100.; // x-axis range
  Double_t ymin = -0.7, ymax = 2.6; // y-axis range
  // create and draw the canvas
  TCanvas *c = new TCanvas("c", "c");
  Double_t r = Double_t(c->GetWw()) / Double_t(c->GetWh()); // aspect ratio
  Double_t ml = 0.05; // (bottom, top, left, right) margin length (percentage)
  Double_t al = 0.04; // arrow length (percentage of the pad height)
  Double_t dx = (xmax - xmin) / (1. - 2. * ml - al / r);
  Double_t dy = (ymax - ymin) / (1. - 2. * ml - al);
  c->Range(xmin - dx * ml, ymin - dy * ml,
           xmax + dx * (ml + al / r), ymax + dy * (ml + al));
  // draw the graph
  g->Draw("L*");
  // create and draw the x-axis
  TGaxis *ax = new TGaxis(xmin, 0., xmax, 0., xmin, xmax, 510, "-+S");
  ax->SetTickLength(al * r / 4.);
  ax->ChangeLabel(1, -1, -1, -1, -1, -1, " "); // remove "0"
  ax->SetLabelOffset(-0.075);
  ax->SetTitle("Retarding Potential");
  ax->SetTitleOffset(-1.5);
  ax->Draw();
  TArrow *axa = new TArrow(xmax, 0., xmax + dx * al / r, 0., al, "|>");
  axa->SetAngle(30);
  axa->Draw();
  // create and draw the y-axis
  TGaxis *ay = new TGaxis(0., ymin, 0., ymax, ymin, ymax, 510, "-+S");
  ay->SetTickLength(al / 4.);
  ay->ChangeLabel(2, -1, -1, -1, -1, -1, " "); // remove "0"
  ay->SetTitle("Photocell current");
  ay->SetTitleOffset(-1.3);
  ay->Draw();
  TArrow *aya = new TArrow(0., ymax, 0., ymax + dy * al, al, "|>");
  aya->SetAngle(30);
  aya->Draw();
}

Thank you kindly, I had done something like this:

{
    TGraphErrors *gr = new TGraphErrors("data.txt");

    TCanvas *c1 = new TCanvas();
    c1->SetFrameLineColor(0);


    TGaxis *axis1 = new TGaxis(0, 0, 3000, 0, 0, 3000, 506, "");
    axis1->SetLabelSize(0.03);
    axis1->SetLabelOffset(-0.06);
    axis1->SetLabelFont(42);
    axis1->SetTitle("Retarding Potential(mV)");
    axis1->SetTitleSize(0.036);
    axis1->SetTitleFont(62);
    axis1->SetTickLength(10);
    axis1->ChangeLabel(1,-1,0,-1,-1,-1,-1);


    gr->SetMarkerStyle(kDot);
    
    gr->GetXaxis()->SetRangeUser(0, 3000);
    gr->GetXaxis()->SetAxisColor(0);

    gr->GetYaxis()->SetRangeUser(-0.5, 2.5);
    gr->GetYaxis()->SetTitle("Photocell Current(mA)");
    gr->GetYaxis()->SetTitleSize(0.036);
    gr->GetYaxis()->SetTitleFont(62);
    
    
    gr->Draw("APL");
    axis1->Draw();
}

Basically, I set the manually created TGaxis’ and the original one’s ranges the same and then made the original one invisible with SetAxisColor(0). Also did the same for the FrameLineColor(0) for canvas.

I also tried creating the axis first and drawing the graph without the “A” option but wasn’t able to get any visual. Now I realize that I drew only the x-axis, is that why the graph wasn’t shown? If not, where did you “relate” the axes and graph?

Thank you again for taking the time to write this, I’ll learn a lot by analyzing it.

Yes that’s the way to proceed. I have the following example in my collection of macro. It is similar.

{
   TCanvas *c = new TCanvas("c","c",0,0,500,500);
   c->Draw();
   c->Range(-11,-11,11,11);

   TF1 *f = new TF1("f","x*x",-10,10);
   f->SetLineWidth(1);
   f->SetLineColor(kRed);
   f->Draw("same");

   TGaxis *ox = new TGaxis(-10,0,10,0,-10,10,510,"+-S");
   ox->SetTickSize(0.009);
   ox->SetLabelFont(42);
   ox->SetLabelSize(0.025);
   ox->Draw();
   TGaxis *oxg = new TGaxis(-10,-10,10,-10,-10,10,510,"SWB");
   oxg->SetLabelSize(0.);
   oxg->SetTickSize(0.);
   oxg->SetGridLength(0.9);
   oxg->Draw();

   TGaxis *oy = new TGaxis(0,-10,0,10,-10,10,510,"+-S");
   oy->SetTickSize(0.009);
   oy->SetLabelFont(42);
   oy->SetLabelSize(0.025);
   oy->Draw();
   TGaxis *oyg = new TGaxis(-10,-10,-10,10,-10,10,510,"SWB");
   oyg->SetLabelSize(0.);
   oyg->SetTickSize(0.);
   oyg->SetGridLength(0.9);
   oyg->Draw();
}

@couet Maybe you could extend the TGaxis so that nice “arrows” could be added on its ends (i.e., “<-”, “->”, “<|-”, “-|>”).

Yes It might be simple to do, by importing axis body drawing of the following macro into Axis body painting

{
   auto c = new TCanvas("c","c",0,0,500,500);
   c->Draw();
   c->Range(-11,-11,11,11);

   auto f = new TF1("f","x*x",-10,10);
   f->SetLineWidth(1);
   f->SetLineColor(kRed);
   f->Draw("same");

   // Draw Axis tick marks and labels
   auto ox = new TGaxis(-10,0,10,0,-10,10,510,"+-SB");
   ox->SetTickSize(0.009);
   ox->SetLabelFont(42);
   ox->SetLabelSize(0.025);
   ox->Draw();
   auto oy = new TGaxis(0,-10,0,10,-10,10,510,"+-SB");
   oy->SetTickSize(0.009);
   oy->SetLabelFont(42);
   oy->SetLabelSize(0.025);
   oy->Draw();

   // Draw axis body with arrow.
   auto oxa = new TArrow(-10,0,10,0);
   oxa->Draw();
   auto oya = new TArrow(0,-10,0,10);
   oya->Draw();

   // Draw grid.
   auto oxg = new TGaxis(-10,-10,10,-10,-10,10,510,"SWB");
   oxg->SetLabelSize(0.);
   oxg->SetTickSize(0.);
   oxg->SetGridLength(0.9);
   oxg->Draw();
   auto oyg = new TGaxis(-10,-10,-10,10,-10,10,510,"SWB");
   oyg->SetLabelSize(0.);
   oyg->SetTickSize(0.);
   oyg->SetGridLength(0.9);
   oyg->Draw();
}

I guess people would appreciate something prettier (e.g., nice “arrows” could be added outside the axis limits).

Yes, I was just pointing the fact the Axis body drawing can be (easily) improved.

PR → Arrow on axis by couet · Pull Request #11645 · root-project/root · GitHub

PR is merged.