Displaying histograms from standalone code

I’ve got a series of TFile’s with some histograms in them, and I need to look at the histograms one by one. Rather than use CINT to open up each TFile individually to look at the histogram, it would be nice if I could just have some C code that would open each file in a directory and display the histogram in that file.

I tried the following code as a warm up:

int main(int argc, char** argv)
{
TFile f(argv[1]);
TH1D* hist = (TH1D*)f.Get(“XX1vsD”);
hist->Draw();

    while(true)
    {
    }

}

That is supposed to just open the file specified on the command line, load the histogram, and display it. Instead, it tells me this:

TCanvas::MakeDefCanvas: created default TCanvas with name c1

…which is normal, but no canvas ever opens up.

The TFile and TH1D in it are healthy and named properly. I can open the histogram in CINT and play with it as needed. I can also add a line to the above program, asking it to compute the mean or something, and it does so appropriate. So, the histogram is loading properly. The only problem is how to display it.

This is within Cygwin, and X-Windows is running.

Can someone please advise me on what to do?

Thanks!

Hi,

a TApplication object is missing; do app.Run() instead of while(1). See the Users Guide chapter on how to create your own applications.

Cheers, Axel.

Thanks Axel.

I’ve spent a long while now looking through the ROOT documentation, and haven’t found a whole lot on TApplication. In fact, the index only lists it on a couple of pages, neither of which is terribly informative.

Your suggestion works to display a single histogram, but I’m interested in displaying a series of histograms from different files after some simple user input (mouse click, hitting enter, whatever). It seems like I need to do some basic event handling with TApplication.

It would be nice if there were some way to display canvases without having to do TApplication::Run(). Then, I could just do something like:

char trash;
for (int i = 1; i < argc; i++)
{
cin >> trash;

… process file argv[i]

}

This would then advance to the next file every time the user hits a key, and would be quite simple. The documentation is slightly suggestive that TGApplication might be workable for this, but it gives me a seg fault. I also tried letting the code go into TApplication::Run() and then overloading what appear to be TApplication’s event handlers for simple input like:

void TApplication::ReturnPressed(char* text)
{
cout << “return pressed” << endl;
}

where the ‘cout’ would be replaced by the file processing of interest in a real application.

Nothing has worked so far, and the documentation seems lacking. Any suggestions would be greatly appreciated.

Hi,

if you have a vector<TH1*> hists, you can do (after creating a TApplication) for (int ih=0; ih<hists.size(); ++ih) { hists[ih]->Draw(); gPad->WaitPrimitive(); }The users guide does not dwell too much in issues with stand-alone application to encourage people to use ACLiC instead.

Axel.

Will ACLiC let me do BASH-like wildcards to pass arguments via ‘argv’ or similar? In other words, on the command line I can just do:

./myapp files*

And if BASH finds N files beginning with ‘files’, it will automatically pass them all to the application via argv, so that argc will be N+1.

Thanks Axel, the gPad->WaitPrimitive works fantastically!

Hi,
no, you’re right - that’s a drawback of not using a shell and thus of not using a binary. What I usually do is call ROOT with the list of files, e.g. something like root -l myScript.C+(".root") (where you’ll need to escape and quote stuff depending on your shell) - which means "start root, compile myScript.C, run the function myScript(const char) and pass it the list of root files".
Axel.