TExec issue for joint histograms

Hello @couet

I am using ROOT 6.34.02 on macOS, and I try to use TExec across pads to jointly refresh my histograms. I would like to modify my histograms detecting axis changes. For that, I tried to modify either subpad1, subpad2, or event refresh the main canvas, but without success. (i.e. drawing the TExec in c, c_1 or c_2)

Would you have any idea how to fix that ? :confounded_face:
I somehow need a final click to refresh as the following lines doesn’t seems to have any effect in the context of TExec.

gPad->GetCanvas()->Modified();
gPad->GetCanvas()->RedrawAxis();
gPad->GetCanvas()->Update();
c->cd(1);
ex->Draw();
c->cd(2);
ex->Draw();

drawing in c seems to be ‘desynchronized’ (only refreshing once).

c->cd();
ex->Draw();

Here is a minimal reproducer.

int gLabelCounter1 = 1;
int gLabelCounter2 = 1;

// Code to be run by TExec
void ExecChangeLabel() {

   auto* h = (TH1*) gPad->GetCanvas()->FindObject("h");
   if(h) {
      TString label = Form("CHANGED (%d)", gLabelCounter1++);
      for(int i = 0; i < h->GetXaxis()->GetNlabels(); ++i) {
         h->GetXaxis()->ChangeLabel(i+1, -1, -1, -1, -1, -1, i == 1 ? label : " ");
      }
   }

   auto* h2 = (TH1*) gPad->GetCanvas()->FindObject("h2");
   if(h2) {
      TString label2 = Form("CHANGED (%d)", gLabelCounter2++);
      for(int i = 0; i < h2->GetXaxis()->GetNlabels(); ++i) {
         h2->GetXaxis()->ChangeLabel(i+1, -1, -1, -1, -1, -1, i == 1 ? label2 : " ");
      }
   }

   std::cout << gPad->GetCanvas()->GetName() << ": Changed labels on histograms." << std::endl;
   gPad->GetCanvas()->Modified();
   gPad->GetCanvas()->RedrawAxis();
   gPad->GetCanvas()->Update();
}

// Main canvas + histogram + exec
void Reproducer() {

   TCanvas* c = new TCanvas("c", "Label Counter Test", 800, 600);

   c->Divide(2,2);
   
   TH1F* h = new TH1F("h", "Histogram", 10, 0, 10);
   c->cd(1);
   h->FillRandom("gaus", 1000);
   h->Draw();

   TH1F* h2 = new TH1F("h2", "Histogram", 10, 0, 10);
   c->cd(2);
   h2->FillRandom("gaus", 1000);
   h2->Draw();

   TExec* ex = new TExec("exec", "ExecChangeLabel();");
   
   c->cd();
   ex->Draw();

   c->cd(1);
   ex->Draw();

   c->cd(2);
   ex->Draw();
}

Best regards,
Marco

may be something like that:

int gLabelCounter1 = 1;
int gLabelCounter2 = 1;
TCanvas* c ;

// Code to be run by TExec
void ExecChangeLabel() {
   TPad* p = nullptr;
   TObject *obj;
   TIter next(c->GetListOfPrimitives());
   while ((obj = (TObject *)next())) {
      if (obj->InheritsFrom(TPad::Class())) {
         p = (TPad*)(obj);
         auto* h1 = (TH1*) p->FindObject("h1");
         if(h1) {
            TString label = Form("CHANGED (%d)", gLabelCounter1++);
            for(int i = 0; i < h1->GetXaxis()->GetNlabels(); ++i) {
               h1->GetXaxis()->ChangeLabel(i+1, -1, -1, -1, -1, -1, i == 1 ? label : " ");
            }
         }
         auto* h2 = (TH1*) p->GetCanvas()->FindObject("h2");
         if(h2) {
            TString label2 = Form("CHANGED (%d)", gLabelCounter2++);
            for(int i = 0; i < h2->GetXaxis()->GetNlabels(); ++i) {
               h2->GetXaxis()->ChangeLabel(i+1, -1, -1, -1, -1, -1, i == 1 ? label2 : " ");
            }
         }
         p->ModifiedUpdate();
      }
   }
}

// Main canvas + histogram + exec
void Reproducer() {

   c = new TCanvas("c", "Label Counter Test", 800, 600);

   c->Divide(2,1);

   TExec* ex = new TExec("exec", "ExecChangeLabel();");

   TH1F* h = new TH1F("h1", "Histogram", 10, 0, 10);
   c->cd(1);
   h->FillRandom("gaus", 1000);
   h->Draw();
   ex->Draw();

   TH1F* h2 = new TH1F("h2", "Histogram", 10, 0, 10);
   c->cd(2);
   h2->FillRandom("gaus", 1000);
   h2->Draw();
   ex->Draw();
   gPad->ModifiedUpdate();
}
1 Like

Fantastic! It works great.
I don’t get the difference yet, but I am definitely going to check that today.

Thank you so much for your great advices

1 Like