-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[python][UHI] Implement Slicing in TH1 and adapt the UHI backend and tests #18735
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
8f118cc
to
9e29340
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know I wasn't a requested reviewer but I have a couple of comments :)
hist/hist/inc/TH1.h
Outdated
auto setSliceContents = [&](auto... binEdges) { | ||
ROOT::Internal::SetSliceContent(*hSlice, sliceContents, binEdges...); | ||
}; | ||
caller(setSliceContents, shiftedBins); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this whole arrangement with variadic templated arguments is really hard to understand and I'm wondering if it can be simplified on the C++ side (at the cost of some increased complexity in the pythonization).
As far as I understand, args
are always expected to be int
, so this function should probably take a vector
or a span
thereof rather than being variadic.
Also, since this is quite a long function I would add a doc comment explaining what it does.
hist/hist/inc/TH1.h
Outdated
} | ||
|
||
// Create a new histogram of the same type as this | ||
std::unique_ptr<TH1> hSlice(static_cast<TH1*>(IsA()->GetNew()(nullptr))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does GetNew()(nullptr)
do? I guess it calls the default constructor of the class? Maybe a note would be useful, since unfortunately the typedef of NewFunc_t
doesn't bother explaining...
hist/hist/inc/TH1.h
Outdated
: hSlice->GetBin(fXaxis.GetNbins() + 1, fYaxis.GetNbins() + 1, fZaxis.GetNbins() + 1); | ||
hSlice->SetBinContent(overflowBin, overflowContent); | ||
|
||
return hSlice.release(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we releasing the pointer here? I get this is meant to be called by Python, but if someone calls this from C++ and doesn't manually delete the histogram they would be leaking it silently.
Would it maybe be better to return the unique_ptr and then call SetOwner
from python explicitly?
Test Results 18 files 18 suites 3d 20h 26m 55s ⏱️ For more details on these failures, see this check. Results for commit 33d1f1a. ♻️ This comment has been updated with latest results. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you a lot for this prompt effort to improve the implementation according to bleeding edge testing! I have a few quick remarks for a first iteration of the review
template <size_t Dim> | ||
void SetSliceContent(const std::variant<std::vector<Double_t>, Double_t> &input, const std::vector<Int_t>& args) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe also the Dim
template argument here could be just converted to an integer parameter to the function?
hist/hist/src/TH1.cxx
Outdated
} | ||
|
||
// Create a new histogram of the same type as this | ||
std::unique_ptr<TH1> hSlice(static_cast<TH1*>(IsA()->GetNew()(nullptr))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would just call a function like
template <typename T>
std::unique_ptr<TH1> createHistoDefault(const T &histo){
TDirectory::TContext ctxt{nullptr};
return std::make_unique<T>();
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that creating the new histogram without attaching it to gDirectory is important
hist/hist/src/TH1.cxx
Outdated
: hSlice->GetBin(fXaxis.GetNbins() + 1, fYaxis.GetNbins() + 1, fZaxis.GetNbins() + 1); | ||
hSlice->SetBinContent(overflowBin, overflowContent); | ||
|
||
return hSlice.release(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also don't understand why we need to release the pointer here, can't we just return a unique_ptr?
friend auto ROOT::Internal::Slice(const T &histo, std::vector<Int_t>& args); | ||
|
||
template <size_t Dim> | ||
void SetSliceContent(const std::variant<std::vector<Double_t>, Double_t> &input, const std::vector<Int_t>& args) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you comment on the need for the std::variant
parameter? It is not immediately clear to me, sorry.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is to either set the slice with a vector or a scalar,, in principle I could only keep the vector parameter and then construct the std vector from the scalar on the python side...
This Pull request:
Changes or fixes:
Previously, slicing was implemented at the pythonization level: when slicing a histogram, the values within the specified slice were kept and the ones outside were set to 0, without resizing the sliced axis (leading to inconsistencies..).
This PR implements the slicing logic in
TH1
directly, adapting the pythonizations to make use of the new internal functions.Other changes are made to enhance the interface and fully comply with the UHI specifications, improvements can be summarized here:
h[0:2, 0:2] = np.array([[42], [3]])
).Checklist: