30using ServerLists = std::map<DataKey, std::vector<DataKey>>;
38 std::vector<RooAbsArg *> prodPdfs;
47 prodPdfs.push_back(node);
51 for (
RooAbsArg *server : node->servers()) {
52 _serverLists[node].push_back(server);
54 _constraints.insert(server);
58 for (
auto &item : _serverLists) {
59 auto &
l = item.second;
60 std::sort(
l.begin(),
l.end());
61 l.erase(std::unique(
l.begin(),
l.end()),
l.end());
66 std::size_t actualPdfIdx = 0;
67 std::size_t nNonConstraint = 0;
68 for (std::size_t i = 0; i < prodPdf->pdfList().
size(); ++i) {
75 bool isProbablyConstraint = std::string(pdf.
GetName()).find(
"onstrain") != std::string::npos;
77 if (_constraints.find(&pdf) == _constraints.end() && !isProbablyConstraint) {
82 if (nNonConstraint != prodPdf->pdfList().size()) {
83 if (nNonConstraint != 1) {
84 throw std::runtime_error(
"A RooProdPdf that multiplies a pdf with constraints should contain only one "
85 "pdf that is not a constraint!");
87 _prodPdfsWithConstraints[prodPdf] = actualPdfIdx;
95 std::pair<DataKey, DataKey> p{arg, testArg};
97 auto found = _results.find(p);
98 if (found != _results.end())
104 auto const &serverList = _serverLists.at(arg);
107 auto foundServer = std::find(serverList.begin(), serverList.end(), testArg);
108 if (foundServer != serverList.end()) {
109 _results.emplace(p,
true);
114 for (
auto const &server : serverList) {
115 bool t = dependsOn(server, testArg);
116 _results.emplace(std::pair<DataKey, DataKey>{server, testArg}, t);
122 _results.emplace(p,
false);
126 bool isConstraint(
DataKey key)
const
128 auto found = _constraints.find(key);
129 return found != _constraints.end();
132 std::unordered_map<RooAbsArg *, std::size_t>
const &prodPdfsWithConstraints()
const
134 return _prodPdfsWithConstraints;
138 std::unordered_set<DataKey> _constraints;
139 std::unordered_map<RooAbsArg *, std::size_t> _prodPdfsWithConstraints;
140 ServerLists _serverLists;
141 std::map<std::pair<DataKey, DataKey>,
bool> _results;
145 std::unordered_map<DataKey, RooArgSet *> &normSets, GraphChecker
const &checker)
147 if (normSets.find(&arg) != normSets.end())
153 if (
dynamic_cast<RooAbsPdf const *
>(&arg)) {
154 normSets.insert({&arg,
new RooArgSet{normSet}});
159 for (
const auto server : arg.servers()) {
161 if (!server->isValueServer(arg)) {
169 if (!
dynamic_cast<RooConstraintSum const *
>(&arg) && checker.isConstraint(server)) {
175 differentSet->sort();
178 auto &serverNormSet = differentSet ? *differentSet : normSet;
182 auto found = normSets.
find(server);
183 if (found != normSets.end()) {
184 if (found->second->size() != serverNormSet.size() || !serverNormSet.hasSameLayout(*found->second)) {
185 std::stringstream ss;
186 ss << server->IsA()->
GetName() <<
"::" << server->GetName()
187 <<
" is requested to be evaluated with two different normalization sets in the same model!";
188 ss <<
" This is not supported yet. The conflicting norm sets are:\n RooArgSet";
189 serverNormSet.printValue(ss);
190 ss <<
" requested by " << arg.IsA()->
GetName() <<
"::" << arg.
GetName() <<
"\n RooArgSet";
191 found->second->printValue(ss);
192 ss <<
" first requested by other client";
193 auto errMsg = ss.str();
194 oocoutE(server, Minimization) << errMsg << std::endl;
195 throw std::runtime_error(errMsg);
200 treeNodeServerListAndNormSets(*server, list, serverNormSet, normSets, checker);
205std::vector<std::unique_ptr<RooAbsArg>> unfoldIntegrals(
RooAbsArg const &topNode,
RooArgSet const &normSet,
206 std::unordered_map<DataKey, RooArgSet *> &normSets,
209 std::vector<std::unique_ptr<RooAbsArg>> newNodes;
215 GraphChecker checker{topNode};
220 normSetSorted.
sort();
221 treeNodeServerListAndNormSets(topNode, nodes, normSetSorted, normSets, checker);
224 for (
auto &item : normSets) {
225 if (!item.second || item.second->empty())
228 for (
auto *narg : *item.second) {
229 if (checker.dependsOn(item.first, narg))
234 actualNormSet->
add(*nodes.
find(*narg));
237 item.second = actualNormSet;
242 const std::string attrib = std::string(
"ORIGNAME:") + oldArg.GetName();
250 for (
auto *client : oldArg.clients()) {
251 originalClients.
add(*client);
253 for (
auto *client : originalClients) {
258 client->redirectServers(newServerList,
false,
true);
260 replacedArgs.
add(oldArg);
267 if (
auto prodPdf =
dynamic_cast<RooProdPdf *
>(node)) {
268 auto found = checker.prodPdfsWithConstraints().find(prodPdf);
269 if (found != checker.prodPdfsWithConstraints().end()) {
270 replaceArg(prodPdf->pdfList()[found->second], *prodPdf);
278 if (
auto pdf =
dynamic_cast<RooAbsPdf *
>(node)) {
279 RooArgSet const &currNormSet = *normSets.at(pdf);
281 if (currNormSet.
empty())
288 pdf->getVal(currNormSet);
293 auto normalizedPdf = std::make_unique<RooNormalizedPdf>(*pdf, currNormSet);
295 replaceArg(*normalizedPdf, *pdf);
297 newNodes.emplace_back(std::move(normalizedPdf));
311 if (
auto const &replacedArgName = normalizedPdf->getStringAttribute(
"_replaced_arg")) {
313 auto pdf = &replacedArgs[replacedArgName];
315 pdf->
setAttribute((std::string(
"ORIGNAME:") + normalizedPdf->GetName()).c_str());
318 for (
auto *client : normalizedPdf->clients()) {
322 pdf->
setAttribute((std::string(
"ORIGNAME:") + normalizedPdf->GetName()).c_str(),
false);
324 normalizedPdf->setStringAttribute(
"_replaced_arg",
nullptr);
352 : _topNodeWrapper{std::make_unique<
RooAddition>(
"_dummy",
"_dummy",
RooArgList{topNode})}, _normSetWasEmpty{
356 for (std::unique_ptr<RooAbsArg> &
arg : ownedArgs) {
366 if (_normSetWasEmpty)
369 foldIntegrals(*_topNodeWrapper, _replacedArgs);
371 for (
auto &item : _normSets) {
ROOT::RRangeCast< T, false, Range_t > static_range_cast(Range_t &&coll)
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
RooAbsArg is the common abstract base class for objects that represent a value and a "shape" in RooFi...
Bool_t redirectServers(const RooAbsCollection &newServerList, Bool_t mustReplaceAll=kFALSE, Bool_t nameChange=kFALSE, Bool_t isRecursionStep=kFALSE)
Replace all direct servers of this object with the new servers in newServerList.
void setStringAttribute(const Text_t *key, const Text_t *value)
Associate string 'value' to this object under key 'key'.
virtual Bool_t isFundamental() const
Is this object a fundamental type that can be added to a dataset? Fundamental-type subclasses overrid...
void treeNodeServerList(RooAbsCollection *list, const RooAbsArg *arg=0, Bool_t doBranch=kTRUE, Bool_t doLeaf=kTRUE, Bool_t valueOnly=kFALSE, Bool_t recurseNonDerived=kFALSE) const
Fill supplied list with nodes of the arg tree, following all server links, starting with ourself as t...
void setAttribute(const Text_t *name, Bool_t value=kTRUE)
Set (default) or clear a named boolean attribute of this object.
virtual Bool_t isDerived() const
Does value or shape of this arg depend on any other arg?
virtual std::unique_ptr< RooArgSet > fillNormSetForServer(RooArgSet const &normSet, RooAbsArg const &server) const
Fills a RooArgSet to be used as the normalization set for a server, given a normalization set for thi...
RooAbsCachedPdf is the abstract base class for p.d.f.s that need or want to cache their evaluate() ou...
RooAbsCollection is an abstract container object that can hold multiple RooAbsArg objects.
void sort(Bool_t reverse=false)
Sort collection using std::sort and name comparison.
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
RooAbsArg * find(const char *name) const
Find object with given name in list.
RooAddition calculates the sum of a set of RooAbsReal terms, or when constructed with two sets,...
const RooArgList & list() const
RooArgList is a container object that can hold multiple RooAbsArg objects.
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Bool_t containsInstance(const RooAbsArg &var) const override
Check if this exact instance is in this collection.
RooConstraintSum calculates the sum of the -(log) likelihoods of a set of RooAbsPfs that represent co...
To use as a key type for RooFit data maps and containers.
std::unique_ptr< RooAbsArg > _topNodeWrapper
~NormalizationIntegralUnfolder()
NormalizationIntegralUnfolder(RooAbsArg const &topNode, RooArgSet const &normSet)
std::unordered_map< RooFit::Detail::DataKey, RooArgSet * > _normSets
RooProdPdf is an efficient implementation of a product of PDFs of the form.
virtual const char * GetName() const
Returns name of object.