Updating using gPad->Modified() and gPad->Update()

This code used to work, a few years ago. But I have updated my OS and my ROOT in the meantime, and it doesn’t work now. I am running Mac OS 10.11.6, and my ROOT is 6.10/08.

The routine called mczipsteps should run a simple simulation and update the two histograms in the canvas called “results” after each step of the simulation. But it doesn’t do that anymore; it waits (and the spinning beachball comes up) until the macro is finished and then I only see the final histograms.

I hope someone can help me to understand how to fix this.

Try something like mczipsteps(0.1,10) to see what happens.

void mczipsteps(Float_t eot, Int_t nTries) {

  int iseed=221137;      // random number seed //
  int N;                 // number of links, = Nbins-1 //
  float Prel;            // relative probability (Boltzmann factor) //
  float R;               // random number //
  float s;               // current state label //
  float snext;           // possible next state //
  
  // The number of bins is one more than the number of links.//

  const int Nbins=11;  

  TCanvas *results = new TCanvas("results","Frequency Distribution",600,40,800,600);

  TH1F *sfreq = new TH1F("sfreq","",Nbins,0.,Nbins);
  TH1F *slocation = new TH1F("slocation","",Nbins,0.,Nbins);

  results->Divide(2,1);
  sfreq->SetMinimum(0.0);
  sfreq->SetStats(1);
  sfreq->SetFillColor(2);
  slocation->SetMinimum(0.0);
  slocation->SetMaximum(10.0);
  slocation->SetStats(0);
  slocation->SetFillColor(1);

  N=Nbins-1;      // This is the number of links.//
  Prel=exp(-eot);
  gRandom->SetSeed(iseed);
  s=0;
  
  sfreq->Reset();  // clears the histogram //
  results->cd(1);
  sfreq->Draw("HIST");  // draws the histogram in the canvas //
  slocation->Reset();
  results->cd(2);
  slocation->Draw("HIST");
  results->Update();


  for (int j=0; j<nTries; j++) {

    // increment the histo at present location //

    sfreq->Fill(s);
    slocation->Reset();
    slocation->Fill(s);
    results->cd(1);
    gPad->Modified();
    gPad->Update();
    results->cd(2);
    gPad->Modified();
    gPad->Update();
//    results->Update();
    
    // choose a possible next value of s //

    R=gRandom->Uniform();
    if (R < 0.5) {snext = s+1;}
    else {snext = s-1;}
   

    // now decide what to do //

    if (snext < s) {s=snext;}    // always take a lower value //
    else {           // for larger values, check the Boltzmann factor //
        R=gRandom->Uniform();
      if (R < Prel) {s=snext;}
    }


    // check the boundaries //

    if (s < 0) {s=0;}
    if (s > N) {s=N;}

  }

  sfreq->Fill(s);
  results->cd(1);
  gPad->Modified();
  gPad->Update();
  results->cd(2);
  gPad->Modified();
  gPad->Update();
//  results->Update();
  
}

Maybe you are facing a bug with the Cocoa version on Mac which was discovered some time ago.
After each “Update”, try to add gSystem->ProcessEvents(); (executed once or two times).

BTW. When you post “source code” or “output” here, do remember to enclose them into two lines which contain just three characters ``` (see how your post has been edited above).

1 Like

Thank you, that solved the problem! I added a single gSystem->ProcessEvents() after all the Updates in the core of the loop, and now the code works the same as previously. I am very grateful.

It’s not a bug. Before any paint event can be delivered to ROOT QuartzView’s -drawRect: (or even a window shown on screen) - the application must dispatch such event(s). If you are sitting in a tight loop - too bad for you and your instance of NSApplication. Do not use blocking calls/loops etc. but if you do - give TMacOSSystem a chance to process events. ROOT Cocoa is a single process, there is no separate X11 server running at the same time (while there is a Quartz Window Server running, the interaction between Cocoa application and this server is different).

1 Like

My biggest concern here is that the functionality of ROOT’s display changes depending on the back-end you are using. Those programming for X11 will have not working code on Cocoa and those developing on Cocoa will have extraneous calls in X11 (that some X11 may try to remove in further development). The solution seems to me to launch another thread to contain the Cocoa process so it acts more like the X11 server.

I am not sure this is possible. Timur is the expert in that area (he did the work) and will be able to comment on that.

@tpochep : stupid question: Can we call gSystem->ProcessEvents(); in gPad->Update() in case of Cocoa ?

Can we call gSystem->ProcessEvents()

No, Olivier, I think this will end up in a recursion + a bad even if not recursive.

The solution seems to me to launch another thread to contain the Cocoa process so it acts more like the X11 server.

Then you don’t need ROOT + Cocoa - use XQuartz and ROOT build with X11 back-end. Cocoa GUI/application can only work in a main thread. One day something will change in XQuartz/ROOT and you’ll end up with the same problem - a blocking loop preventing XFlush from getting called and a frozen UI.

Instructing our end user’s how they should build ROOT is not acceptable or reliable. In addition, forcing another dependency is not good. Seems that we will have to stick with extra call to gSystem::ProcessEvents().

Hmm, whatever :slight_smile: Whoever they are.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.