Dear All –
I have my algo providing me with vectors of 3600 values, that make up 60x60 pixels with values that are small additive portions of my final 360 x 360 image. Is there any elegant and most importantly, fast way to make a TH2D out of it?
Clearly, nested looping over rows/columns is not awesome, especially if I am running millions of repetitions to accumulate these, because then I place those pixels into a much bigger final TH2D.
Another option perhaps would be to keep results as vectors, then write a function that would insert those into that larger final vector… and then do TH2D out of that final larfe vector and display it in the very end.
There isn’t much to show for a code template. It is a Eigen::VectorXd and a TH2D* that I fill in the nested loop. Anything prettier than that?
Any advice is much appreciated!
Please read tips for efficient and successful posting and posting code
ROOT Version: 6.20/02
Not sure I completely understand the problem - but the underlying storage of a
TH2D is a
TArrayD see the inheritance diagram for ROOT: TH2D Class Reference
Maybe you want to just copy the stripes of the 60x60 array over into the larger array? You can use
FindFixBin() to determine the stripe’s start index.
Thank you very much Axel!
I think you get exactly to the point of the problem. If you could rub by nose into an example that would be awesome!
I am doing some image reconstruction.
… so my algorithm does the following:
- I have a big image that consists of about few millions of small localized phenomena I am reconstructing and trying to accumulate in that big image as result. Cranking out matrices for 360 x 360 image (and in future it will be in fact 1200 x 1200) is impossible and would be insane slow.
- It deploys a small “patch” in the approximate location and solves the imaging problem in small patch.
- returns the vector of pixels that are in sequence rows of the square small image.
- returns the center point X,Y of where that small patch should go into the big picture (so I find corresponding bins and add the contents into the proper bins of the big picture.
So I need that work quicker… filling histograms in the loop seems insane and super slow if I already get vector as answer from my linear algebra solution.
Also, is there a way to fill TH2… by rows (columns) instead of looping over every single bin?
The best I can come up with is to memcpy each line in the “patch”. If you need to actually add patches then memcpy doesn’t work and you’ll have to iterate over the
TArrayD elements and add.
The trick of working on lines / rows / columns / whatever you want to call them of your patches is that you can calculate the start bin once and rely on the fact the bins are consecutive (if you take the right dimension of your patch!).
Thank you Axel!
I am doing by rows now, similar to what you had suggested. We do have the patch defined quite well as well as to where we want it to go every time. It is faster but not too much.
Boost histogram lib seems to be gaining on ROOT implementation. We are experimenting with it and its very raw… but encouraging speed.
Thank you, I will mark this as Solved!
Yup, we’re addressing the lessons learned from
TH1F and friends with
RHist, but it’s work in progress and will be for at least 2021. boost histograms are not targeted to HEP and our use of histograms - good if they work for you!
@Axel, I would like to vote for adding support for Boost histograms in ROOT.
Some time ago, I have been asked if one could drop explicit ROOT dependency from some MC generator. As histogramming was still needed, a proposal was to use Boost histograms (in the MC generator). Once the events have been generated, the problem was that the analysis (outside of the MC generator) would need ROOT. So, a way to “import” / “export” Boost histograms in ROOT would be needed.
We ended up doing the following. Maybe someone else will benefit. Works way faster than one-by-one two loops,
TH2D *h_phi_p = new TH2D("h_phi_p", "Phi_p", 60, -15., 15., 60, -15., 15.);
for(size_t i = 0; i < vars.pvector->size(); ++i)
int col = ( (*vars.pvector)[i] - 60*trunc( (*vars.pvector)[i] / 60 ) );
int row = trunc( (*vars.pvector)[i] / 60 );
h_phi_p->SetBinContent(col+1, row+1, (*vars.values_pvector)( i ));