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
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)
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.
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…
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
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.
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).
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…