When I draw a THStack with log scale, it appears the histograms are drawn in the wrong order. I expect the histogram with the largest integral to appear on the top of the stack. This doesn’t seem to be the case in the attached picture. Is there anything that can cause this? An example of a plot where this is happening is attached.
Yes, in the past I assumed it was sorting them, but I guess this isn’t the case. Is there some way to sort the histograms after adding them to the THStack? I don’t see anything in the reference page.
They are not sorted. They are displayed in the order you entered them in the stack.
Also “sorting” them would be kind of difficult … what would be the criteria to sort them ? we can think of many …
Why not copy the std::sort() practice? You can sort with a function object, struct, etc. It looks like the histograms are stored in a linked list so this would be easy functionality to add.
TList claims to have a sorting function, but it looks like it just sorts based on the names of the objects. Looking at the TList::Sort (Bool_t order=kSortAscending) function, it doesn’t appear to have a way to specify the comparison function.
This problem is looks like it wasn’t resolved here:
Actually, I’d suggest to keep your histograms in a std::vector and sort that before adding the histograms to the stack. It seems simpler to me to use standard C++ tools than to check how to sort the internal stack list (is that even legal?).
#include <TH1F.h>
#include <THStack.h>
#include <algorithm>
#include <vector>
void xxx() {
// create two "random" histograms
auto h1 = new TH1F("h1", "h1", 10, 0, 10);
h1->Fill(1, 5);
h1->Fill(2, 1);
h1->SetLineColor(kRed);
auto h2 = new TH1F("h2", "h2", 10, 0, 10);
h2->Fill(1, 1);
h2->Fill(2, 10);
h2->SetLineColor(kBlue);
std::vector<TH1 *> v = {h1, h2};
// sort by "smallest integral first"
std::sort(v.begin(), v.end(),
[](TH1 *a, TH1 *b) { return a->Integral() < b->Integral(); });
auto stack = new THStack("Stack", "title");
for (auto h : v)
stack->Add(h);
stack->Draw("hist");
}
Thanks for the suggestion. Currently this seems like the only choice, but as a container I think THStack should have a sort function. I’m new to ROOT, is there someone responsible for fixing this?
I disagree. Containers should NOT have their own general purpose functions. See the STL design. std::vector doesn’t have its own sorting function nor does std::list have it.
Perhaps I should have said “sort functionality” to be more clear. Is THStack iterable? It doesn’t look like it is, since it seems like it would have to inherit from TCollection.
THStack is missing most of these, including begin() and end() (as far as I can tell). Would you agree that as a container, THStack should have these functions?
Well, you can iterate over the stack: just iterate over stack->GetHists(). On the other hand, a linked list is certainly not random access, i.e. the corresponding iterator doesn’t have the random_access_iterator_tag and thus you can’t use std::sort anyway.
It is just a bad idea to give all classes you can think of wide interfaces. Keep them short instead.
By saying “STL design” I meant the design as such, more in the sense of Stepanov’s ideas, not so much the begin and end functions of modern C++.