Avoiding screen flicker: Does ROOT have blitting capability?

I use the following code to make a movie of how some data evolves with time: pmvz is a TTree * and size and step are typically a few thousand for(int i=0;i<steps;i++) { pmvz->Draw("y:x>>h(20,-800,800,20,-800,800)","","",size,start); gPad->Modified(); gPad->Update(); gSystem->Sleep(sleep); gSystem->ProcessEvents(); start += step; } The display is updated at a decent frame rate - typically 25/second. However, the display flickers - even if step is set to 0. (only the data flicker, not the axes) Is there a double buffering option available that would make this flickering go away? Thanks!

I am using root version 5.06/0 on windows XP w/ gdk

Ed Oltman

Hi Ed,

TCanvas::SetDoubleBuffer(Int_t mode)
TPad::SetDoubleBuffer(Int_t mode)

But this is probably not the problem (I think double buffering is the default).

Ususal question : could you provide a short macro showing the problem ?
i.e. in guitest, filling histos doesn’t show this behavior.

Cheers,
Bertrand.

Hi Bertrand,
The attached script + root file demonstrates the flicker effect, Extract both, then type .x flick.cpp from root prompt. Note: type .x flick(2000,0) - this displays the exact same data over and over again - data flickers but axes don’t. Thanks
Ed
flick.cpp (489 Bytes)
flicker.root (307 KB)

Hi Ed,

Please find your modified macro in attachment (thanks to Olivier).

Cheers,
Bertrand.
flick.cpp (601 Bytes)

Betrand, Olivier,
Thats an interesting solution - thank you for your prompt suggestion. I really want to look at the data unbinned - 20 x 20 bins is way too coarse - My origional projectionpmvz->Draw("y:x>>h(20,-800,800,20,-800,800)","","",size,start); leaves the data unbinned - I could specify h(1,-800,800,1,800,800) and it looks the same.

I’m wondering if there is another solution. Is there an easy way to convert the canvases to .GIFs and then play then back? Or drawing a TGraph and removing the old points and adding new points? Thanks.

Ed

Hi Ed,

You can save in several gifs, and then make an animation :

Cheers,
Bertrand.

Does root provide mechanism for creating animations?

No, but I thing a small application exists to create animated GIF from list of GIFs (from command line).

Hi Ed,

I think I found what you want:

void flick(int size=2000,int step=1000,int sleep=0)  
{  
   TFile *f = new TFile("flicker.root");  
   TTree *pmvz = (TTree *)f->Get("pt");  
   int total = pmvz->GetEntries();  
   int steps = step > 0 ? total/step : 100;  
   int start = 0;  
   for(int i=0;i<steps;i++)  
   {  
      if(i==0) {
         pmvz->Draw("y:x>>h(20,-800,800,20,-800,800)","","",size,start);      
      } else {
         pmvz->Draw("y:x>>h(20,-800,800,20,-800,800)","","same",size,start);
      }
      gPad->Modified();  
      gPad->Update();  
      gSystem->Sleep(sleep);  
      gSystem->ProcessEvents();  
      start += step;  
   }  
}

Olivier
This is flicker free - thats good! The problem is, its cumulative - What I want is a moving window of size records.
Ed

Olivier,
You gave me an idea: erase the old points by drawing them with the background color!:void flick(int size=2000,int step=1000,int sleep=0) { TFile *f = new TFile("flicker.root"); TTree *pmvz = (TTree *)f->Get("pt"); int total = pmvz->GetEntries(); int steps = step > 0 ? total/step : 100; int start = 0; int color; for(int i=0;i<steps;i++) { if(i==0) { pmvz->Draw("y:x>>h(20,-800,800,20,-800,800)","","",size,start); } else { pmvz->SetMarkerColor(color); pmvz->Draw("y:x","","same",step,start-step); pmvz->SetMarkerColor(1); pmvz->Draw("y:x","","same",size-step,start-step+size); } gPad->Modified(); if (i==0) { TFrame *pf = (TFrame *)gPad->FindObject("TFrame"); color = pf->GetFillColor(); } gPad->Update(); gSystem->Sleep(sleep); gSystem->ProcessEvents(); start += step; } }
Thank you (and Bertrand) for the help! Its slower, but I can probably fix that by not jumping around so much in the TTree…

Ed

Well, the above solution appears to work for a small TTree, but if I try to animate a large file (>1E6 or so), the frame rate decays quickly…
Ed

Try (the point is to reuse an existing histogram by ‘resetting it’)

void flick(int size=2000,int step=1000,int sleep=0) { TFile *f = new TFile("flicker.root"); TTree *pmvz = (TTree *)f->Get("pt"); int total = pmvz->GetEntries(); int steps = step > 0 ? total/step : 100; int start = 0; for(int i=0;i<steps;i++) { if(i==0) { pmvz->Draw("y:x>>h(20,-800,800,20,-800,800)","","",size,start); } else { h.Reset(); pmvz->Draw("y:x>>h(20,-800,800,20,-800,800)","","goff",size,start); } gPad->Modified(); gPad->Update(); gSystem->Sleep(sleep); gSystem->ProcessEvents(); start += step; } } Cheers,
Philippe

I had to modify the script slightly to make it run - here’s the change: if(i==0) { pmvz->Draw("y:x>>h(20,-800,800,20,-800,800)","","",size,start); } else { TH2F *h = (TH2F *)gPad->FindObject("h"); h->Reset(); pmvz->Draw("y:x>>h(20,-800,800,20,-800,800)","","goff",size,start); } but it does not work - draws the first frame, but it never updates. I thougt “goff” means produces no graphics output

Ed[/code]

BTW, to make animated GIF from several GIFs, see for example :

lcdf.org/~eddietwo/gifsicle/

HTH,
Cheers, Bertrand.

See an example of animation in tutorial hsumanim.C

Rene

Hi,

You main issue is the fact that"y:x>>h(20,-800,800,20,-800,800)"explicitly means to recreate the histogram h (rendering my attempt to re-use the same object:).void flick(int size=2000,int step=1000,int sleep=0) { TFile *f = new TFile("flicker.root"); TTree *pmvz = (TTree *)f->Get("pt"); int total = pmvz->GetEntries(); int steps = step > 0 ? total/step : 100; int start = 0; TH2D *h = new TH2D("h","h",20,-800,800,20,-800,800); for(int i=0;i<steps;i++) { if(i==0) { pmvz->Draw("y:x>>h","","",size,start); } else { h.Reset(); pmvz->Draw("y:x>>h","","goff",size,start); } gPad->Modified(); gPad->Update(); gSystem->Sleep(sleep); gSystem->ProcessEvents(); start += step; } }Since we re-use the same histogram and it is draw the first time (and never removed from the canvas), we do not need to redraw it every event.

Cheers,
Philippe.

Hi Phillipe,
That method, as was the one with the “box” option, produces binning artifacts. If I increase the number of bins, the frame rate goes way down…
Ed

[quote] That method, as was the one with the “box” option, produces binning artifacts. If I increase the number of bins, the frame rate goes way down…
[/quote]As the number of bins increases, the number of points to be drawn increase, doesn’t it? Unless you data is cumulative (in which case, you could simply create a new histo per ‘frame’ and draw with 'same"). Also if you know that there is some known overlap between ‘frame’ you could divide in a fixed number of histogram corresponding to each portion and rotate between them (reducing the number of point needing to be drawn each time).

Cheers,
Philippe.

Hi Philippe

If I try to reuse the same histogram (create the histogram h first, then pmvz->Draw(“y:x>>h”,"",“goff”) into that same histogram) the resulting display has binning artifacts. To make the binning artifacts go away, I need to make the number of bins quite large - thats slows everything down. If I project into a fresh histogram each time (pmvz->Draw(“y:x>>h(…)”) I get no binning artifacts - regardless of how many bins h has - BUT I get the flicker. In both cases, I have the same number of points drawn per frame: So, No, as the number of bins increases, the number of points displayed stays the same.

I tried to utilize the fact that there are overlaps between frames - see my earlier post - this worked fine for the 100k ttree I posted, but for real data (millions of records) the frame rate rapidly decayed to something unusable.

Ed

PS I have made a “gif movie” using gifcicle - I must create a gif per frame, and sew them together with gifcicle. IS it possible to display the resulting animated gif on my TCanvas? Or is it necessary to spawn an external viewer…