Suggestion: TGraph to read various columns of a text file

Hi Rooters.
I think It would be nice if the

constructor will be extended to read any columns in a space-delimited file as the x and y of the TGraph points.
i.e. something like (format field will have to be extended)
TGraph* Aparameter = new TGraph(“fitresults.txt”, “x=1, y=2”);
TGraph* Bparameter = new TGraph(“fitresults.txt”, “x=1, y=3”);
TGraph* Cparameter = new TGraph(“fitresults.txt”, “x=1, y=4”);
ect’…
(or is there a way to do it already?:roll:)

p.s. oops … now i see that it was DO NOT put feature requests in this thread. I’m sorry :slight_smile:

I thinks that’s a bad idea. If you can simply do the same things without special-case constructor, you’d better do it and do not restrict user with your logic (it’s clear and obvious for you, but not for me, for example). 1. I do not like a-la printf parameters, it’s easy to do something bad and wrong, and I prefer to use C++ standard library with overloaded ‘>>’ ‘<<’ operators. ROOT does not use exceptions (in fact it does, but restrictedly) so, if your file does not exist how can I check, that TGraph is not in good state? Should we use IsZombie() or something like this? But if you open file and read data in YOUR code, you can do any checks you want. 3. What if I want to read only several lines from this file, not all file? 4. What if I want to filter the input data? 5. Should we complicate and compicate such primitive tasks? I think - NO.
What if someone else wants to fill TGraph from some other sources? Should we add more constructors? I think - NO.
Do you notice, that standard C++ containers do not have ctors to fill container from file? (well, except specific istream iterators, but this is simply iterator, container knows nothing about files - thanks to templates here)

We had already several requests along your line and I agree that a simple user interface (like the one you propose or similar) will simplify the life and avoid writing cryptic code with sscanf or C++ operators.
Since your request does not imply any changes in the UI, it is quite simple to implement. I put it on our todo list.

Rene

well err… ok…
however… it is just a very small extention of a constructor that already exist and do (almost) this job. Hence, all the points you mentioned can be said just as much for the existing constructor…
I coded it already separately ofcourse :slight_smile:

brun: Nice to hear.
As you said, I also think it would enhance TGraph(Errors) and as you said, easy to implement.
Until I coded a similar thing, I used matlab or gnuplot to read multicolumn files. After the upgrade, I would be able to do this with a single line in ROOT, which is nice.

1 Like

Note that you can also use a TNtuple/TNtupleD to read a file with multiple columns and make plots using combinations of any of these columns.

Rene

1 Like

Rene,

I could not agree more with tpochep . This is a bad idea.
The user should process his data BEFORE making a TGraph object.

Adding all these options through different constructors makes the
whole user experience inconsistent . Why for instance does
this option not exist in the histogram classes .

TGraph in particular is becoming an example of “listening to users”:
Why do we have constructors with Double_t* and TVectorD while
a simple call to v.GetMatrixArray() would do the job …

Eddy

Eddy,

I disagree with you and Timur. The request from NuBeMet does not require a new constructor. Try to think to the lines of code necessary to implement this functionality. It is a detail for ROOT, but more complex for a user who expects one single line to build his/her graph from a text file, and this is frequent. By the way send me the lines of code to implement the requested functionality and you will be surprised ::slight_smile:
I agree with you that we added too many constructors in TGraph and TH1 to accept vectors or matrices in input. This was certainly an overkill since as you say, it is trivial to pass the corresponding info into the existing constructors.

Rene

Rene,

You obviously wrote those lines and did hide them inside the TGraph
constructor. It would be more useful to supply a function or class
that can do manipulations with a text file, extract rows /colums .

This could than be used to input data intp TGraph, TH, TMatrix …

Eddy,

The code already in the TGraph constructor is only able to read the 2 first columns of a text file. Providing the functionality requested by NuBeMet requires an extended logic. You and Timur seemed to imply that this type of code is trivial and should be a simple user task. I simply was asking this code from you ::slight_smile:
It is more user friendly to provide this functionality in the constructor.
A ReadFile method (like in several other classes) could also be implemented, of course, but the point was not to extend the existing UI.

Rene

[quote=“brun”]Eddy,

The code already in the TGraph constructor is only able to read the 2 first columns of a text file. Providing the functionality requested by NuBeMet requires an extended logic. You and Timur seemed to imply that this type of code is trivial and should be a simple user task. I simply was asking this code from you ::slight_smile:
Rene[/quote]
Yes, it’s trivial in each concrete case, if you know your data and know exactly, what you want. But how to write the generic code which will process each possible option?

For example (only 3 variants):

  1. Errors. I want to open file “file1.dat”, if it cannot be opened - open file “file2.dat” or “file3.dat”? If none of them can be opened, I know that exactly in my code and can do something before (instead of) creating TGraph.
  2. Errors. May be, file is broken:

x y z
1 2 3
4 5 6
7

No values for y and z in last line. I can catch such error and do what I want: 1) Use correct lines I’ve read and create TGraph 2) Show error message, describing situation and return.
3. If I want filtering - not all data should be in TGraph, but only some lines.
How to specify this generically?

And we can add more and more options and they will make your constructor a bit monstrous, I guess.

Well, as soon as it’s already in ROOT, it’s late to discuss :slight_smile:

Timur,

You are just reinforcing my point and I also notice that you did not send yet the few lines of code that you claimed trivial to read the most simple case (eg a text file with 5 columns and you want to assign column I to X and column J to Y (with I,J in [1,5]) ::slight_smile:
We have several requests for this simple functionality. And this is implemented in several analysis tools. We will add this to the TGraph existing constructor from a file.

Rene

Just adding my point of view :slight_smile: :

May be a more general class allowing to read an ASCII file would be more useful. Something like: TASCIIFileReader( filename, option, x, y, z, …);
like that you can then feed any class having vectors as input, not only TGraph but also TGraph2D etc …

That’s just a suggestion.

Hi Oliver,

That is exactly what I tried to suggest a couple of emails above …

Forget this option. It cannot work. You do not know a priori the number of lines. The master function has to interact with the logic reading the lines.
Well, may be it would have been much faster to implement the few lines of code rather than this thread ::slight_smile:
I am still waiting from Eddy and Timur what is claimed to be trivial ::slight_smile:

Rene

[quote]Timur,
You are just reinforcing my point and I also notice that you did not send yet the few lines of code that you claimed trivial to read the most simple case (eg a text file with 5 columns and you want to assign column I to X and column J to Y (with I,J in [1,5]) ::slight_smile:
We have several requests for this simple functionality. And this is implemented in several analysis tools. We will add this to the TGraph existing constructor from a file.
Rene[/quote]

Do you mean 1) I can select i == 3 and j == 4 or you want 2) generic code with arbitrary values for I and J ? If 2) - it means you want me to write your constructor :slight_smile:) I’ll write it, but only if you promise me solve (== write program) my task with your TGraph ctor approach after that.

[quote]Forget this option. It cannot work. You do not know a priori the number of lines. The master function has to interact with the logic reading the lines.
Well, may be it would have been much faster to implement the few lines of code rather than this thread ::slight_smile:
I am still waiting from Eddy and Timur what is claimed to be trivial ::slight_smile:

Rene[/quote]

Number of lines (if I understand you correctly) is not a problem if you know the content of a line:
//name(string) x(double) y(double) somethingelse(double)
std::ifstream inputFile(“some.dat”);
std::vector xs, ys;
std::string dummyName(20, ’ ');
double dummy = 0., x = 0., y = 0.;

inputFile>>dummyName>>x>>y>>dummy;
while(inputFile)
{
xs.push_back(x);
ys.push_back(y);
inputFile>>dummyName>>x>>y>>dummy;
}

if(xs.size())
{
TGraph gr(xs.size(), &xs[0], &ys[0]);
///
///
}

A more efficient version that does not require twice the data is already in the TGraph constructor. Read again my mail above and the original request.

Rene

[quote=“brun”]A more efficient version that does not require twice the data is already in the TGraph constructor. Read again my mail above and the original request.

Rene[/quote]

Sorry, I do not understand your “more efficient”. YOU ALREADY have several versions like TGraph(Int_t n, Float_t * xSrc, Float_t * ySrc), do you think, that memory pointed by xSrc and ySrc comes from air? Or you allocate it somewhere? Do you copy this data in TGraph ctor or use it directly? My code sample is the same.

Or do you mean that std::vector reallocates data each time in push_back? That’s simply not true.

Timur, PLEASE PLEASE!
We already have a TGraph constructor reading from a file.
The only thing that is requires is to implement an option in the already existing argument option such that instead of reading (by default) the 2 first columns, one can read column I into x and column J into Y.
THIS LOOKS SO SIMPLE !!!

Rene