Passing a histogram from a function

In an attempt to make a root program that is actuall capable of more than a single task, I first struggled to get a function that would take a string from the user and open an ASCII file with that name and extract the data into a TH1D, which it would return a pointer to. Only then did I realize that for every time I ran the function from the Root console was a huge number of pointers to the same histogram. Since there appears to be no way to pass a histogram instead of a pointer to one (is this true?) I decided to simply copy the histogram created by my function to a new TH1D. As far as I can tell the syntax looks like this:

old_h->Copy(new_h);

However, no matter how I declare new_h it starts throwing errors like crazy every time I call the Copy function. old_h seems to work fine in every other way. What am I missing? Is this ordeal even necessary, or is there a better way to get a function that can be used multiple times to generate multiple, different histograms?

Hi,
it’s not entirely clear to me what you’re trying to do, and what your problem is. myFill fills a histogram you pass as an argument (by pointer - you don’t want to copy histograms all the time), and manageHists manages with a vector of histograms. The name of each histo is entered at the prompt.

[code]#include “TH1.h”
#include “TRandom.h”
#include “THashList.h”
#include “TROOT.h”
#include “TCanvas.h”
#include
#include

void myFill(TH1* hist) { hist->Fill(gRandom->Rndm()); }
void manageHistos() {
THashList histos;
std::cout << “Enter histo names, one per line. Enter a line “.” to end:”
<< std::endl;
while (1) {
std::string name;
getline(std::cin, name);
if (name==".") break;

// if there is a histo with the same name already then better delete it!
TObject* hOld=histos.FindObject(name.c_str());
if (hOld) {
   std::cout << "Cannot have multiple histograms with the same name!"
             << std::endl;
   histos.Remove(hOld);
}
// now chekc whether ROOT already has a histo with this name
// ( e.g. from a previous run of this macro)
hOld=gROOT->FindObject(name.c_str());
if (hOld && hOld->InheritsFrom(TH1::Class()))
   delete hOld;
histos.Add(new TH1F(name.c_str(), name.c_str(), 10, 0., 1.));
myFill((TH1*)histos.Last());

}
TCanvas* canv=new TCanvas(“histoC”,“all histograms”);
canv->Divide(2, (histos.GetSize()+1)/2);
for (Int_t iHist=0; iHist<histos.GetSize(); iHist++) {
canv->cd(iHist+1);
histos.At(iHist)->Draw();
}
}[/code]As you can see, it reads the names from the standard input, creates a histogram, and passes it to another method, which does things with that histogram. If this doesn’t answer your question please clarify what you’re trying to do.
Axel.

Sorry about my lack of clarity. Basically, I have a directory of ASCII files containing some data and I want to put each in a seperate histogram with which I can do whatever I need to do. Right now, I have a function that takes a filename, opens the file, and makes a TH1D histogram out of the data from the file, and returns a pointer to that histo. This works great if I have only one histogram, but I have a directory full of them. What I want is a way to be able to run the exact same function, passing it a different filename each time, however many times I need until I have a histogram for every ASCII file of data, but the way things are now I’d have to have a seperate function for each ASCII file or all I’ll get are a bunch of pointers to the same histogram.

Hi,
this will do it:[code]TH1* histReader(const char* filename) {
std::ifstream inputfile(filename);
const char* name=Form(“hist%s”,filename);
TH1* h=new TH1(name, name, 10, 0., 1.);
// read file, fill h

return h;
}

void readAllHists() {
std::liststd::string filenames;
// put all filenames into filenames

std::list<TH1*> histos;
for (std::liststd::string iFilename=filenames.begin();
iFilename!=filenames.end(); iFilename++) {
new TCanvas(Form(“canv%s”,iFilename->c_str());
histos.push_back(histReader(filename.c_str()));
histos.back()->Draw();
}
}[/code]
Axel.