Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Loading...
Searching...
No Matches
RooLagrangianMorphFunc.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooLagrangianMorphing *
4 * @(#)root/roofit:$Id$
5 * Authors: *
6 * Lydia Brenner (lbrenner@cern.ch), Carsten Burgard (cburgard@cern.ch) *
7 * Katharina Ecker (kecker@cern.ch), Adam Kaluza (akaluza@cern.ch) *
8 * *
9 * Copyright (c) 2000-2005, Regents of the University of California *
10 * and Stanford University. All rights reserved. *
11 * *
12 * Redistribution and use in source and binary forms, *
13 * with or without modification, are permitted according to the terms *
14 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15 *****************************************************************************/
16
17/** \class RooLagrangianMorphFunc
18 \ingroup Roofit
19Class RooLagrangianMorphing is a implementation of the method of Effective
20Lagrangian Morphing, described in ATL-PHYS-PUB-2015-047.
21Effective Lagrangian Morphing is a method to construct a continuous signal
22model in the coupling parameter space. Basic assumption is that shape and
23cross section of a physical distribution is proportional to it's
24squared matrix element.
25The signal model is constructed by a weighted sum over N input distributions.
26The calculation of the weights is based on Matrix Elements evaluated for the
27different input scenarios.
28The number of input files depends on the number of couplings in production
29and decay vertices, and also whether the decay and production vertices
30describe the same process or not.
31**/
32
33// uncomment to force UBLAS multiprecision matrices
34// #define USE_UBLAS 1
35// #undef USE_UBLAS
36
37#include "Riostream.h"
38
39#include "RooAbsCollection.h"
40#include "RooArgList.h"
41#include "RooArgProxy.h"
42#include "RooArgSet.h"
43#include "RooBinning.h"
44#include "RooDataHist.h"
45#include "RooFormulaVar.h"
46#include "RooHistFunc.h"
49#include "RooParamHistFunc.h"
50#include "RooProduct.h"
51#include "RooRealVar.h"
52#include "RooWorkspace.h"
53#include "RooFactoryWSTool.h"
54
55#include "ROOT/StringUtils.hxx"
56#include "TFile.h"
57#include "TFolder.h"
58#include "TH1.h"
59#include "TMap.h"
60#include "TParameter.h"
61#include "TRandom3.h"
62
63#include <algorithm>
64#include <array>
65#include <cmath>
66#include <cstddef>
67#include <iostream>
68#include <limits>
69#include <map>
70#include <memory>
71#include <sstream>
72#include <stdexcept>
73#include <type_traits>
74#include <typeinfo>
75
76using std::string, std::make_unique, std::vector;
77
78
79//#define _DEBUG_
80
81///////////////////////////////////////////////////////////////////////////////
82// PREPROCESSOR MAGIC /////////////////////////////////////////////////////////
83///////////////////////////////////////////////////////////////////////////////
84
85// various preprocessor helpers
86#define NaN std::numeric_limits<double>::quiet_NaN()
87
88constexpr static double morphLargestWeight = 10e7;
89constexpr static double morphUnityDeviation = 10e-6;
90
91///////////////////////////////////////////////////////////////////////////////
92// TEMPLATE MAGIC /////////////////////////////////////////////////////////////
93///////////////////////////////////////////////////////////////////////////////
94
95template <typename Test, template <typename...> class Ref>
96struct is_specialization : std::false_type {
97};
98
99template <template <typename...> class Ref, typename... Args>
100struct is_specialization<Ref<Args...>, Ref> : std::true_type {
101};
102
103///////////////////////////////////////////////////////////////////////////////
104// LINEAR ALGEBRA HELPERS /////////////////////////////////////////////////////
105///////////////////////////////////////////////////////////////////////////////
106
107////////////////////////////////////////////////////////////////////////////////
108/// retrieve the size of a square matrix
109
110template <class MatrixT>
111inline size_t size(const MatrixT &matrix);
112template <>
113inline size_t size<TMatrixD>(const TMatrixD &mat)
114{
115 return mat.GetNrows();
116}
117
118////////////////////////////////////////////////////////////////////////////////
119/// write a matrix to a stream
120
121template <class MatrixT>
122void writeMatrixToStreamT(const MatrixT &matrix, std::ostream &stream)
123{
124 if (!stream.good()) {
125 return;
126 }
127 for (size_t i = 0; i < size(matrix); ++i) {
128 for (size_t j = 0; j < size(matrix); ++j) {
129#ifdef USE_UBLAS
130 stream << std::setprecision(RooFit::SuperFloatPrecision::digits10) << matrix(i, j) << "\t";
131#else
132 stream << matrix(i, j) << "\t";
133#endif
134 }
135 stream << std::endl;
136 }
137}
138
139////////////////////////////////////////////////////////////////////////////////
140/// write a matrix to a text file
141
142template <class MatrixT>
143inline void writeMatrixToFileT(const MatrixT &matrix, const char *fname)
144{
145 std::ofstream of(fname);
146 if (!of.good()) {
147 std::cerr << "unable to read file '" << fname << "'!" << std::endl;
148 }
150 of.close();
151}
152
153#ifdef USE_UBLAS
154
155// boost includes
156#pragma GCC diagnostic push
157#pragma GCC diagnostic ignored "-Wshadow"
158#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
159#include <boost/numeric/ublas/io.hpp>
160#include <boost/numeric/ublas/lu.hpp>
161#include <boost/numeric/ublas/matrix.hpp>
162#include <boost/numeric/ublas/matrix_expression.hpp>
163#include <boost/numeric/ublas/symmetric.hpp> //inc diag
164#include <boost/numeric/ublas/triangular.hpp>
165#include <boost/operators.hpp>
166
167#pragma GCC diagnostic pop
168
169typedef boost::numeric::ublas::matrix<RooFit::SuperFloat> Matrix;
170
171////////////////////////////////////////////////////////////////////////////////
172/// write a matrix
173
174inline void printMatrix(const Matrix &mat)
175{
176 for (size_t i = 0; i < mat.size1(); ++i) {
177 for (size_t j = 0; j < mat.size2(); ++j) {
178 std::cout << std::setprecision(RooFit::SuperFloatPrecision::digits10) << mat(i, j) << " ,\t";
179 }
180 std::cout << std::endl;
181 }
182}
183
184////////////////////////////////////////////////////////////////////////////////
185/// retrieve the size of a square matrix
186
187template <>
188inline size_t size<Matrix>(const Matrix &matrix)
189{
190 return matrix.size1();
191}
192
193////////////////////////////////////////////////////////////////////////////////
194/// create a new diagonal matrix of size n
195
196inline Matrix diagMatrix(size_t n)
197{
198 return boost::numeric::ublas::identity_matrix<RooFit::SuperFloat>(n);
199}
200
201////////////////////////////////////////////////////////////////////////////////
202/// convert a matrix into a TMatrixD
203
204inline TMatrixD makeRootMatrix(const Matrix &in)
205{
206 size_t n = size(in);
207 TMatrixD mat(n, n);
208 for (size_t i = 0; i < n; ++i) {
209 for (size_t j = 0; j < n; ++j) {
210 mat(i, j) = double(in(i, j));
211 }
212 }
213 return mat;
214}
215
216////////////////////////////////////////////////////////////////////////////////
217/// convert a TMatrixD into a matrix
218
219inline Matrix makeSuperMatrix(const TMatrixD &in)
220{
221 size_t n = in.GetNrows();
222 Matrix mat(n, n);
223 for (size_t i = 0; i < n; ++i) {
224 for (size_t j = 0; j < n; ++j) {
225 mat(i, j) = double(in(i, j));
226 }
227 }
228 return mat;
229}
230
231inline Matrix operator+=(const Matrix &rhs)
232{
233 return add(rhs);
234}
235inline Matrix operator*(const Matrix &m, const Matrix &otherM)
236{
237 return prod(m, otherM);
238}
239
240////////////////////////////////////////////////////////////////////////////////
241/// calculate the inverse of a matrix, returning the condition
242
244{
245 boost::numeric::ublas::permutation_matrix<size_t> pm(size(matrix));
248 try {
249 int res = lu_factorize(lu, pm);
250 if (res != 0) {
251 std::stringstream ss;
253 cxcoutP(Eval) << ss.str << std::endl;
254 }
255 // back-substitute to get the inverse
257 } catch (boost::numeric::ublas::internal_logic &error) {
258 // coutE(Eval) << "boost::numeric::ublas error: matrix is not invertible!"
259 // << std::endl;
260 }
263 return condition;
264}
265
266#else
267
268#include "TDecompLU.h"
270
271////////////////////////////////////////////////////////////////////////////////
272/// convert a matrix into a TMatrixD
273
275{
276 return TMatrixD(in);
277}
278
279////////////////////////////////////////////////////////////////////////////////
280/// convert a TMatrixD into a Matrix
281
283{
284 return in;
285}
286
287////////////////////////////////////////////////////////////////////////////////
288/// create a new diagonal matrix of size n
289
290inline Matrix diagMatrix(size_t n)
291{
292 TMatrixD mat(n, n);
293 mat.UnitMatrix();
294 return mat;
295}
296
297////////////////////////////////////////////////////////////////////////////////
298/// write a matrix
299
300inline void printMatrix(const TMatrixD &mat)
301{
302 writeMatrixToStreamT(mat, std::cout);
303}
304
305////////////////////////////////////////////////////////////////////////////////
306// calculate the inverse of a matrix, returning the condition
307
308inline double invertMatrix(const Matrix &matrix, Matrix &inverse)
309{
311 bool status = lu.Invert(inverse);
312 // check if the matrix is invertible
313 if (!status) {
314 std::cerr << " matrix is not invertible!" << std::endl;
315 }
316 double condition = lu.GetCondition();
317 const size_t n = size(inverse);
318 // sanitize numeric problems
319 for (size_t i = 0; i < n; ++i) {
320 for (size_t j = 0; j < n; ++j) {
321 if (std::abs(inverse(i, j)) < 1e-9)
322 inverse(i, j) = 0;
323 }
324 }
325 return condition;
326}
327#endif
328
329/////////////////////////////////////////////////////////////////////////////////
330// LOCAL FUNCTIONS AND DEFINITIONS
331// //////////////////////////////////////////////
332/////////////////////////////////////////////////////////////////////////////////
333/// anonymous namespace to prohibit use of these functions outside the class
334/// itself
335namespace {
336///////////////////////////////////////////////////////////////////////////////
337// HELPERS ////////////////////////////////////////////////////////////////////
338///////////////////////////////////////////////////////////////////////////////
339
340typedef std::vector<std::vector<bool>> FeynmanDiagram;
341typedef std::vector<std::vector<int>> MorphFuncPattern;
342typedef std::map<int, std::unique_ptr<RooAbsReal>> FormulaList;
343
344///////////////////////////////////////////////////////////////////////////////
345/// (-?-)
346
347inline TString makeValidName(std::string const& input)
348{
349 TString retval(input.c_str());
350 retval.ReplaceAll("/", "_");
351 retval.ReplaceAll("^", "");
352 retval.ReplaceAll("*", "X");
353 retval.ReplaceAll("[", "");
354 retval.ReplaceAll("]", "");
355 return retval;
356}
357
358//////////////////////////////////////////////////////////////////////////////
359/// concatenate the names of objects in a collection to a single string
360
361template <class List>
362std::string concatNames(const List &c, const char *sep)
363{
364 std::stringstream ss;
365 bool first = true;
366 for (auto itr : c) {
367 if (!first)
368 ss << sep;
369 ss << itr->GetName();
370 first = false;
371 }
372 return ss.str();
373}
374
375///////////////////////////////////////////////////////////////////////////////
376/// this is a workaround for the missing implicit conversion from
377/// SuperFloat<>double
378
379template <class A, class B>
380inline void assignElement(A &a, const B &b)
381{
382 a = static_cast<A>(b);
383}
384///////////////////////////////////////////////////////////////////////////////
385// read a matrix from a stream
386
387template <class MatrixT>
388inline MatrixT readMatrixFromStreamT(std::istream &stream)
389{
390 std::vector<std::vector<RooFit::SuperFloat>> matrix;
391 std::vector<RooFit::SuperFloat> line;
392 while (!stream.eof()) {
393 if (stream.peek() == '\n') {
394 stream.get();
395 stream.peek();
396 continue;
397 }
399 stream >> val;
400 line.push_back(val);
401 while (stream.peek() == ' ' || stream.peek() == '\t') {
402 stream.get();
403 }
404 if (stream.peek() == '\n') {
405 matrix.push_back(line);
406 line.clear();
407 }
408 }
409 MatrixT retval(matrix.size(), matrix.size());
410 for (size_t i = 0; i < matrix.size(); ++i) {
411 if (matrix[i].size() != matrix.size()) {
412 std::cerr << "matrix read from stream doesn't seem to be square!" << std::endl;
413 }
414 for (size_t j = 0; j < matrix[i].size(); ++j) {
415 assignElement(retval(i, j), matrix[i][j]);
416 }
417 }
418 return retval;
419}
420
421///////////////////////////////////////////////////////////////////////////////
422/// read a matrix from a text file
423
424template <class MatrixT>
425inline MatrixT readMatrixFromFileT(const char *fname)
426{
427 std::ifstream in(fname);
428 if (!in.good()) {
429 std::cerr << "unable to read file '" << fname << "'!" << std::endl;
430 }
432 in.close();
433 return mat;
434}
435
436///////////////////////////////////////////////////////////////////////////////
437/// convert a TH1* param hist into the corresponding ParamSet object
438
439template <class T>
440void readValues(std::map<const std::string, T> &myMap, TH1 *h_pc)
441{
442 if (h_pc) {
443 // loop over all bins of the param_card histogram
444 for (int ibx = 1; ibx <= h_pc->GetNbinsX(); ++ibx) {
445 // read the value of one parameter
446 const std::string s_coup(h_pc->GetXaxis()->GetBinLabel(ibx));
447 double coup_val = h_pc->GetBinContent(ibx);
448 // add it to the map
449 if (!s_coup.empty()) {
450 myMap[s_coup] = T(coup_val);
451 }
452 }
453 }
454}
455
456///////////////////////////////////////////////////////////////////////////////
457/// Set up folder ownership over its children, and treat likewise any subfolders.
458/// @param theFolder: folder to update. Assumed to be a valid pointer
460{
461 theFolder->SetOwner();
462 // And also need to set up ownership for nested folders
463 auto subdirs = theFolder->GetListOfFolders();
464 for (auto *subdir : *subdirs) {
465 auto thisfolder = dynamic_cast<TFolder *>(subdir);
466 if (thisfolder) {
467 // no explicit deletion here, will be handled by parent
469 }
470 }
471}
472
473///////////////////////////////////////////////////////////////////////////////
474/// Load a TFolder from a file while ensuring it owns its content.
475/// This avoids memory leaks. Note that when fetching objects
476/// from this folder, you need to clone them to prevent deletion.
477/// Also recursively updates nested subfolders accordingly
478/// @param inFile: Input file to read - assumed to be a valid pointer
479/// @param folderName: Name of the folder to read from the file
480/// @return a unique_ptr to the folder. Nullptr if not found.
481std::unique_ptr<TFolder> readOwningFolderFromFile(TDirectory *inFile, const std::string &folderName)
482{
483 std::unique_ptr<TFolder> theFolder(inFile->Get<TFolder>(folderName.c_str()));
484 if (!theFolder) {
485 std::cerr << "Error: unable to access data from folder '" << folderName << "' from file '" << inFile->GetName()
486 << "'!" << std::endl;
487 return nullptr;
488 }
490 return theFolder;
491}
492
493///////////////////////////////////////////////////////////////////////////////
494/// Helper to load a single object from a file-resident TFolder, while
495/// avoiding memory leaks.
496/// @tparam AObjType Type of object to load.
497/// @param inFile input file to load from. Expected to be a valid pointer
498/// @param folderName Name of the TFolder to load from the file
499/// @param objName Name of the object to load
500/// @param notFoundError If set, print a detailed error if we didn't find something
501/// @return Returns a pointer to a clone of the loaded object. Ownership assigned to the caller.
502template <class AObjType>
503std::unique_ptr<AObjType> loadFromFileResidentFolder(TDirectory *inFile, const std::string &folderName,
504 const std::string &objName, bool notFoundError = true)
505{
507 if (!folder) {
508 return nullptr;
509 }
510 AObjType *loadedObject = dynamic_cast<AObjType *>(folder->FindObject(objName.c_str()));
511 if (!loadedObject) {
512 if (notFoundError) {
513 std::stringstream errstr;
514 errstr << "Error: unable to retrieve object '" << objName << "' from folder '" << folderName
515 << "'. contents are:";
516 TIter next(folder->GetListOfFolders()->begin());
517 TFolder *f;
518 while ((f = static_cast<TFolder *>(next()))) {
519 errstr << " " << f->GetName();
520 }
521 std::cerr << errstr.str() << std::endl;
522 }
523 return nullptr;
524 }
525 // replace the loaded object by a clone, as the loaded folder will delete the original
526 // can use a static_cast - confirmed validity by initial cast above.
527 return std::unique_ptr<AObjType>{static_cast<AObjType *>(loadedObject->Clone())};
528}
529
530///////////////////////////////////////////////////////////////////////////////
531/// retrieve a ParamSet from a certain subfolder 'name' of the file
532
533template <class T>
534void readValues(std::map<const std::string, T> &myMap, TDirectory *file, const std::string &name,
535 const std::string &key = "param_card", bool notFoundError = true)
536{
538 readValues(myMap, h_pc.get());
539}
540
541///////////////////////////////////////////////////////////////////////////////
542/// retrieve the param_hists file and return a map of the parameter values
543/// by providing a list of names, only the param_hists of those subfolders are
544/// read leaving the list empty is interpreted as meaning 'read everything'
545
546template <class T>
547void readValues(std::map<const std::string, std::map<const std::string, T>> &inputParameters, TDirectory *f,
548 const std::vector<std::string> &names, const std::string &key = "param_card", bool notFoundError = true)
549{
550 inputParameters.clear();
551 // if the list of names is empty, we assume that this means 'all'
552 // loop over all folders in the file
553 for (size_t i = 0; i < names.size(); i++) {
554 const std::string name(names[i]);
555 // actually read an individual param_hist
557 }
558
559 // now the map is filled with all parameter values found for all samples
560}
561
562///////////////////////////////////////////////////////////////////////////////
563/// open the file and return a file pointer
564
565inline TDirectory *openFile(const std::string &filename)
566{
567 if (filename.empty()) {
568 return gDirectory;
569 } else {
570 TFile *file = TFile::Open(filename.c_str(), "READ");
571 if (!file || !file->IsOpen()) {
572 if (file)
573 delete file;
574 std::cerr << "could not open file '" << filename << "'!" << std::endl;
575 }
576 return file;
577 }
578}
579
580///////////////////////////////////////////////////////////////////////////////
581/// open the file and return a file pointer
582
583inline void closeFile(TDirectory *d)
584{
585 TFile *f = dynamic_cast<TFile *>(d);
586 if (f) {
587 f->Close();
588 delete f;
589 d = nullptr;
590 }
591}
592
593///////////////////////////////////////////////////////////////////////////////
594/// extract the operators from a single coupling
595template <class T2>
596inline void extractServers(const RooAbsArg &coupling, T2 &operators)
597{
598 int nservers = 0;
599 for (const auto server : coupling.servers()) {
601 nservers++;
602 }
603 if (nservers == 0) {
604 operators.add(coupling);
605 }
606}
607
608///////////////////////////////////////////////////////////////////////////////
609/// extract the operators from a list of couplings
610
612inline void extractOperators(const T1 &couplings, T2 &operators)
613{
614 // std::coutD(InputArguments) << "extracting operators from
615 // "<<couplings.size()<<" couplings" << std::endl;
616 for (auto itr : couplings) {
618 }
619}
620
621///////////////////////////////////////////////////////////////////////////////
622/// extract the operators from a list of vertices
623
625inline void extractOperators(const T1 &vec, T2 &operators)
626{
627 for (const auto &v : vec) {
629 }
630}
631
632///////////////////////////////////////////////////////////////////////////////
633/// extract the couplings from a given set and copy them to a new one
634
635template <class T1, class T2>
636inline void extractCouplings(const T1 &inCouplings, T2 &outCouplings)
637{
638 for (auto itr : inCouplings) {
639 if (!outCouplings.find(itr->GetName())) {
640 // std::coutD(InputArguments) << "adding parameter "<< obj->GetName() <<
641 // std::endl;
642 outCouplings.add(*itr);
643 }
644 }
645}
646
647////////////////////////////////////////////////////////////////////////////////
648/// set parameter values first set all values to defaultVal (if value not
649/// present in param_card then it should be 0)
650
651inline bool setParam(RooRealVar *p, double val, bool force)
652{
653 bool ok = true;
654 if (val > p->getMax()) {
655 if (force) {
656 p->setMax(val);
657 } else {
658 std::cerr << ": parameter " << p->GetName() << " out of bounds: " << val << " > " << p->getMax() << std::endl;
659 ok = false;
660 }
661 } else if (val < p->getMin()) {
662 if (force) {
663 p->setMin(val);
664 } else {
665 std::cerr << ": parameter " << p->GetName() << " out of bounds: " << val << " < " << p->getMin() << std::endl;
666 ok = false;
667 }
668 }
669 if (ok)
670 p->setVal(val);
671 return ok;
672}
673
674////////////////////////////////////////////////////////////////////////////////
675/// set parameter values first set all values to defaultVal (if value not
676/// present in param_card then it should be 0)
677
678template <class T1, class T2>
679inline bool setParams(const T2 &args, T1 val)
680{
681 for (auto itr : args) {
682 RooRealVar *param = dynamic_cast<RooRealVar *>(itr);
683 if (!param)
684 continue;
685 setParam(param, val, true);
686 }
687 return true;
688}
689
690////////////////////////////////////////////////////////////////////////////////
691/// set parameter values first set all values to defaultVal (if value not
692/// present in param_card then it should be 0)
693
694template <class T1, class T2>
695inline bool
696setParams(const std::map<const std::string, T1> &point, const T2 &args, bool force = false, T1 defaultVal = 0)
697{
698 bool ok = true;
699 for (auto itr : args) {
700 RooRealVar *param = dynamic_cast<RooRealVar *>(itr);
701 if (!param || param->isConstant())
702 continue;
703 ok = setParam(param, defaultVal, force) && ok;
704 }
705 // set all parameters to the values in the param_card histogram
706 for (auto paramit : point) {
707 // loop over all the parameters
708 const std::string param(paramit.first);
709 // retrieve them from the map
710 RooRealVar *p = dynamic_cast<RooRealVar *>(args.find(param.c_str()));
711 if (!p)
712 continue;
713 // set them to their nominal value
714 ok = setParam(p, paramit.second, force) && ok;
715 }
716 return ok;
717}
718
719////////////////////////////////////////////////////////////////////////////////
720/// set parameter values first set all values to defaultVal (if value not
721/// present in param_card then it should be 0)
722
723template <class T>
724inline bool setParams(TH1 *hist, const T &args, bool force = false)
725{
726 bool ok = true;
727
728 for (auto itr : args) {
729 RooRealVar *param = dynamic_cast<RooRealVar *>(itr);
730 if (!param)
731 continue;
732 ok = setParam(param, 0., force) && ok;
733 }
734
735 // set all parameters to the values in the param_card histogram
736 TAxis *ax = hist->GetXaxis();
737 for (int i = 1; i <= ax->GetNbins(); ++i) {
738 // loop over all the parameters
739 RooRealVar *p = dynamic_cast<RooRealVar *>(args.find(ax->GetBinLabel(i)));
740 if (!p)
741 continue;
742 // set them to their nominal value
743 ok = setParam(p, hist->GetBinContent(i), force) && ok;
744 }
745 return ok;
746}
747
748////////////////////////////////////////////////////////////////////////////////
749/// create a set of parameters
750
751template <class T>
752inline RooLagrangianMorphFunc::ParamSet getParams(const T &parameters)
753{
755 for (auto itr : parameters) {
756 RooRealVar *param = dynamic_cast<RooRealVar *>(itr);
757 if (!param)
758 continue;
759 retval[param->GetName()] = param->getVal();
760 }
761 return retval;
762}
763
764////////////////////////////////////////////////////////////////////////////////
765/// collect the histograms from the input file and convert them to RooFit
766/// objects
767
768void collectHistograms(const char *name, TDirectory *file, std::map<std::string, int> &list_hf, RooArgList &physics,
769 RooRealVar &var, const std::string &varname,
771{
772 bool binningOK = false;
773 for (auto sampleit : inputParameters) {
774 const std::string sample(sampleit.first);
775 auto hist = loadFromFileResidentFolder<TH1>(file, sample, varname, true);
776 if (!hist)
777 return;
778
779 if (normalize) {
780 hist->Scale(1. / hist->Integral());
781 }
782
783 auto it = list_hf.find(sample);
784 if (it != list_hf.end()) {
785 RooHistFunc *hf = static_cast<RooHistFunc *>(physics.at(it->second));
786 hf->setValueDirty();
787 // commenting out To-be-resolved
788 // RooDataHist* dh = &(hf->dataHist());
789 // RooLagrangianMorphFunc::setDataHistogram(hist,&var,dh);
790 // RooArgSet vars;
791 // vars.add(var);
792 // dh->importTH1(vars,*hist,1.,false);
793 } else {
794 if (!binningOK) {
795 int n = hist->GetNbinsX();
796 std::vector<double> bins;
797 for (int i = 1; i < n + 1; ++i) {
798 bins.push_back(hist->GetBinLowEdge(i));
799 }
800 bins.push_back(hist->GetBinLowEdge(n) + hist->GetBinWidth(n));
801 var.setBinning(RooBinning(n, &(bins[0])));
802 }
803
804 // generate the mean value
805 TString histname = makeValidName("dh_" + sample + "_" + name);
806 TString funcname = makeValidName("phys_" + sample + "_" + name);
807 RooArgSet vars;
808 vars.add(var);
809
810 auto dh = std::make_unique<RooDataHist>(histname.Data(), histname.Data(), vars, hist.get());
811 // add it to the list
812 auto hf = std::make_unique<RooHistFunc>(funcname.Data(), funcname.Data(), var, std::move(dh));
813 int idx = physics.size();
814 list_hf[sample] = idx;
815 physics.addOwned(std::move(hf));
816 }
817 // std::cout << "found histogram " << hist->GetName() << " with integral "
818 // << hist->Integral() << std::endl;
819 }
820}
821
822////////////////////////////////////////////////////////////////////////////////
823/// collect the RooAbsReal objects from the input directory
824
825void collectRooAbsReal(const char * /*name*/, TDirectory *file, std::map<std::string, int> &list_hf,
826 RooArgList &physics, const std::string &varname,
828{
829 for (auto sampleit : inputParameters) {
830 const std::string sample(sampleit.first);
832 if (!obj)
833 return;
834 auto it = list_hf.find(sample);
835 if (it == list_hf.end()) {
836 int idx = physics.size();
837 list_hf[sample] = idx;
838 physics.addOwned(std::move(obj));
839 }
840 }
841}
842
843////////////////////////////////////////////////////////////////////////////////
844/// collect the TParameter objects from the input file and convert them to
845/// RooFit objects
846
847template <class T>
848void collectCrosssections(const char *name, TDirectory *file, std::map<std::string, int> &list_xs, RooArgList &physics,
850{
851 for (auto sampleit : inputParameters) {
852 const std::string sample(sampleit.first);
853 auto obj = loadFromFileResidentFolder<TObject>(file, sample, varname, false);
854 TParameter<T> *xsection = nullptr;
855 TParameter<T> *error = nullptr;
856 TParameter<T> *p = dynamic_cast<TParameter<T> *>(obj.get());
857 if (p) {
858 xsection = p;
859 }
860 TPair *pair = dynamic_cast<TPair *>(obj.get());
861 if (pair) {
862 xsection = dynamic_cast<TParameter<T> *>(pair->Key());
863 error = dynamic_cast<TParameter<T> *>(pair->Value());
864 }
865 if (!xsection) {
866 std::stringstream errstr;
867 errstr << "Error: unable to retrieve cross section '" << varname << "' from folder '" << sample;
868 return;
869 }
870
871 auto it = list_xs.find(sample);
872 RooRealVar *xs;
873 if (it != list_xs.end()) {
874 xs = static_cast<RooRealVar *>(physics.at(it->second));
875 xs->setVal(xsection->GetVal());
876 } else {
877 std::string objname = "phys_" + std::string(name) + "_" + sample;
878 auto xsOwner = std::make_unique<RooRealVar>(objname.c_str(), objname.c_str(), xsection->GetVal());
879 xs = xsOwner.get();
880 xs->setConstant(true);
881 int idx = physics.size();
882 list_xs[sample] = idx;
883 physics.addOwned(std::move(xsOwner));
884 assert(physics.at(idx) == xs);
885 }
886 if (error) {
887 xs->setError(error->GetVal());
888 }
889 }
890}
891
892////////////////////////////////////////////////////////////////////////////////
893/// collect the TPair<TParameter,TParameter> objects from the input file and
894/// convert them to RooFit objects
895
896void collectCrosssectionsTPair(const char *name, TDirectory *file, std::map<std::string, int> &list_xs,
897 RooArgList &physics, const std::string &varname, const std::string &basefolder,
899{
900 auto pair = loadFromFileResidentFolder<TPair>(file, basefolder, varname, false);
901 if (!pair)
902 return;
903 if (dynamic_cast<TParameter<double> *>(pair->Key())) {
905 } else if (dynamic_cast<TParameter<float> *>(pair->Key())) {
907 } else {
908 std::cerr << "cannot morph objects of class 'TPair' if parameter is not "
909 "double or float!"
910 << std::endl;
911 }
912}
913
914///////////////////////////////////////////////////////////////////////////////
915// FORMULA CALCULATION ////////////////////////////////////////////////////////
916///////////////////////////////////////////////////////////////////////////////
917///////////////////////////////////////////////////////////////////////////////
918
919////////////////////////////////////////////////////////////////////////////////
920/// recursive function to determine polynomials
921
923 int vertexid, bool first)
924{
925 if (vertexid > 0) {
926 for (size_t i = 0; i < diagram[vertexid - 1].size(); ++i) {
927 if (!diagram[vertexid - 1][i])
928 continue;
929 std::vector<int> newterm(term);
930 newterm[i]++;
931 if (first) {
933 } else {
935 }
936 }
937 } else {
938 bool found = false;
939 for (size_t i = 0; i < morphfunc.size(); ++i) {
940 bool thisfound = true;
941 for (size_t j = 0; j < morphfunc[i].size(); ++j) {
942 if (morphfunc[i][j] != term[j]) {
943 thisfound = false;
944 break;
945 }
946 }
947 if (thisfound) {
948 found = true;
949 break;
950 }
951 }
952 if (!found) {
953 morphfunc.push_back(term);
954 }
955 }
956}
957
958////////////////////////////////////////////////////////////////////////////////
959/// calculate the morphing function pattern based on a vertex map
960
962{
963 int nvtx(diagram.size());
964 std::vector<int> term(diagram[0].size(), 0);
965
967}
968
969////////////////////////////////////////////////////////////////////////////////
970/// build a vertex map based on vertices and couplings appearing
971
972template <class List>
973inline void fillFeynmanDiagram(FeynmanDiagram &diagram, const std::vector<List *> &vertices, RooArgList &couplings)
974{
975 const int ncouplings = couplings.size();
976 // std::cout << "Number of couplings " << ncouplings << std::endl;
977 for (auto const &vertex : vertices) {
978 std::vector<bool> vertexCouplings(ncouplings, false);
979 int idx = -1;
981 for (auto citr : couplings) {
982 coupling = dynamic_cast<RooAbsReal *>(citr);
983 idx++;
984 if (!coupling) {
985 std::cerr << "encountered invalid list of couplings in vertex!" << std::endl;
986 return;
987 }
988 if (vertex->find(coupling->GetName())) {
989 vertexCouplings[idx] = true;
990 }
991 }
992 diagram.push_back(vertexCouplings);
993 }
994}
995
996////////////////////////////////////////////////////////////////////////////////
997/// fill the matrix of coefficients
998
999template <class MatrixT, class T1, class T2>
1001 const T1 &args, const RooLagrangianMorphFunc::FlagMap &flagValues, const T2 &flags)
1002{
1003 const size_t dim = inputParameters.size();
1004 MatrixT matrix(dim, dim);
1005 int row = 0;
1006 for (auto sampleit : inputParameters) {
1007 const std::string sample(sampleit.first);
1008 // set all vars to value stored in input file
1009 if (!setParams<double>(sampleit.second, args, true, 0)) {
1010 std::cout << "unable to set parameters for sample " << sample << "!" << std::endl;
1011 }
1012 auto flagit = flagValues.find(sample);
1013 if (flagit != flagValues.end() && !setParams<int>(flagit->second, flags, true, 1)) {
1014 std::cout << "unable to set parameters for sample " << sample << "!" << std::endl;
1015 }
1016 // loop over all the formulas
1017 int col = 0;
1018 for (auto const &formula : formulas) {
1019 if (!formula.second) {
1020 std::cerr << "Error: invalid formula encountered!" << std::endl;
1021 }
1022 matrix(row, col) = formula.second->getVal();
1023 col++;
1024 }
1025 row++;
1026 }
1027 return matrix;
1028}
1029
1030////////////////////////////////////////////////////////////////////////////////
1031/// check if the matrix is square
1032
1033inline void checkMatrix(const RooLagrangianMorphFunc::ParamMap &inputParameters, const FormulaList &formulas)
1034{
1035 if (inputParameters.size() != formulas.size()) {
1036 std::stringstream ss;
1037 ss << "matrix is not square, consistency check failed: " << inputParameters.size() << " samples, "
1038 << formulas.size() << " expressions:" << std::endl;
1039 ss << "formulas: " << std::endl;
1040 for (auto const &formula : formulas) {
1041 ss << formula.second->GetTitle() << std::endl;
1042 }
1043 ss << "samples: " << std::endl;
1044 for (auto sample : inputParameters) {
1045 ss << sample.first << std::endl;
1046 }
1047 std::cerr << ss.str() << std::endl;
1048 }
1049}
1050
1051////////////////////////////////////////////////////////////////////////////////
1052/// check if the entries in the inverted matrix are sensible
1053
1054inline void inverseSanity(const Matrix &matrix, const Matrix &inverse, double &unityDeviation, double &largestWeight)
1055{
1057
1058 unityDeviation = 0.;
1059 largestWeight = 0.;
1060 const size_t dim = size(unity);
1061 for (size_t i = 0; i < dim; ++i) {
1062 for (size_t j = 0; j < dim; ++j) {
1063 if (inverse(i, j) > largestWeight) {
1065 }
1066 if (std::abs(unity(i, j) - static_cast<int>(i == j)) > unityDeviation) {
1067 unityDeviation = std::abs((double)unity(i, j)) - static_cast<int>(i == j);
1068 }
1069 }
1070 }
1071}
1072
1073////////////////////////////////////////////////////////////////////////////////
1074/// check for name conflicts between the input samples and an argument set
1075template <class List>
1077{
1078 for (auto sampleit : inputParameters) {
1079 const std::string sample(sampleit.first);
1080 RooAbsArg *arg = args.find(sample.c_str());
1081 if (arg) {
1082 std::cerr << "detected name conflict: cannot use sample '" << sample
1083 << "' - a parameter with the same name of type '" << arg->ClassName() << "' is present in set '"
1084 << args.GetName() << "'!" << std::endl;
1085 }
1086 }
1087}
1088
1089////////////////////////////////////////////////////////////////////////////////
1090/// build the formulas corresponding to the given set of input files and
1091/// the physics process
1092
1095 const RooArgList &couplings, const RooArgList &flags,
1096 const std::vector<std::vector<std::string>> &nonInterfering)
1097{
1098 // example vbf hww:
1099 // Operators kSM, kHww, kAww, kHdwR,kHzz, kAzz
1100 // std::vector<bool> vertexProd = {true, true, true, true, true, true };
1101 // std::vector<bool> vertexDecay = {true, true, true, true, false,false};
1102 // diagram.push_back(vertexProd);
1103 // diagram.push_back(vertexDecay);
1104
1105 const int ncouplings = couplings.size();
1106 std::vector<bool> couplingsZero(ncouplings, true);
1107 std::map<TString, bool> flagsZero;
1108
1110 extractOperators(couplings, operators);
1111 size_t nOps = operators.size();
1112
1113 for (auto sampleit : inputParameters) {
1114 const std::string sample(sampleit.first);
1115 if (!setParams(sampleit.second, operators, true)) {
1116 std::cerr << "unable to set parameters for sample '" << sample << "'!" << std::endl;
1117 }
1118
1119 if (nOps != (operators.size())) {
1120 std::cerr << "internal error, number of operators inconsistent!" << std::endl;
1121 }
1122
1124 int idx = 0;
1125
1126 for (auto itr1 : couplings) {
1127 obj0 = dynamic_cast<RooAbsReal *>(itr1);
1128 if (obj0->getVal() != 0) {
1129 couplingsZero[idx] = false;
1130 }
1131 idx++;
1132 }
1133 }
1134
1135 for (auto itr2 : flags) {
1136 auto obj1 = dynamic_cast<RooAbsReal *>(itr2);
1137 int nZero = 0;
1138 int nNonZero = 0;
1139 for (auto sampleit : inputFlags) {
1140 const auto &flag = sampleit.second.find(obj1->GetName());
1141 if (flag != sampleit.second.end()) {
1142 if (flag->second == 0.) {
1143 nZero++;
1144 } else {
1145 nNonZero++;
1146 }
1147 }
1148 }
1149 if (nZero > 0 && nNonZero == 0) {
1150 flagsZero[obj1->GetName()] = true;
1151 } else {
1152 flagsZero[obj1->GetName()] = false;
1153 }
1154 }
1155
1156 FormulaList formulas;
1157 for (size_t i = 0; i < morphfunc.size(); ++i) {
1158 RooArgList ss;
1159 bool isZero = false;
1160 std::string reason;
1161 // check if this is a blacklisted interference term
1162 for (const auto &group : nonInterfering) {
1163 int nInterferingOperators = 0;
1164 for (size_t j = 0; j < morphfunc[i].size(); ++j) {
1165 if (morphfunc[i][j] % 2 == 0)
1166 continue; // even exponents are not interference terms
1167 // if the coupling is part of a "pairwise non-interfering group"
1168 if (std::find(group.begin(), group.end(), couplings.at(j)->GetName()) != group.end()) {
1170 }
1171 }
1172 if (nInterferingOperators > 1) {
1173 isZero = true;
1174 reason = "blacklisted interference term!";
1175 }
1176 }
1177 int nNP = 0;
1178 if (!isZero) {
1179 // prepare the term
1180 for (size_t j = 0; j < morphfunc[i].size(); ++j) {
1181 const int exponent = morphfunc[i][j];
1182 if (exponent == 0)
1183 continue;
1184 RooAbsReal *coupling = dynamic_cast<RooAbsReal *>(couplings.at(j));
1185 for (int k = 0; k < exponent; ++k) {
1186 ss.add(*coupling);
1187 if (coupling->getAttribute("NewPhysics")) {
1188 nNP++;
1189 }
1190 }
1191 std::string cname(coupling->GetName());
1192 if (coupling->getAttribute("LO") && exponent > 1) {
1193 isZero = true;
1194 reason = "coupling " + cname + " was listed as leading-order-only";
1195 }
1196 // mark the term as zero if any of the couplings are zero
1197 if (!isZero && couplingsZero[j]) {
1198 isZero = true;
1199 reason = "coupling " + cname + " is zero!";
1200 }
1201 }
1202 }
1203 // check and apply flags
1204 bool removedByFlag = false;
1205
1206 for (auto itr : flags) {
1207 auto obj = dynamic_cast<RooAbsReal *>(itr);
1208 if (!obj)
1209 continue;
1210 TString sval(obj->getStringAttribute("NewPhysics"));
1211 int val = atoi(sval);
1212 if (val == nNP) {
1213 if (flagsZero.find(obj->GetName()) != flagsZero.end() && flagsZero.at(obj->GetName())) {
1214 removedByFlag = true;
1215 reason = "flag " + std::string(obj->GetName()) + " is zero";
1216 }
1217 ss.add(*obj);
1218 }
1219 }
1220
1221 // create and add the formula
1222 if (!isZero && !removedByFlag) {
1223 // build the name
1224 const auto name = std::string(mfname) + "_pol" + std::to_string(i);
1225 formulas[i] = std::make_unique<RooProduct>(name.c_str(), ::concatNames(ss, " * ").c_str(), ss);
1226 }
1227 }
1228 return formulas;
1229}
1230
1231////////////////////////////////////////////////////////////////////////////////
1232/// create the weight formulas required for the morphing
1233
1234FormulaList createFormulas(const char *name, const RooLagrangianMorphFunc::ParamMap &inputs,
1236 const std::vector<std::vector<RooArgList *>> &diagrams, RooArgList &couplings,
1237 const RooArgList &flags, const std::vector<std::vector<std::string>> &nonInterfering)
1238{
1240
1241 for (const auto &vertices : diagrams) {
1243 ::fillFeynmanDiagram(d, vertices, couplings);
1245 }
1246 FormulaList retval = buildFormulas(name, inputs, inputFlags, morphfuncpattern, couplings, flags, nonInterfering);
1247 if (retval.empty()) {
1248 std::stringstream errorMsgStream;
1250 << "no formulas are non-zero, check if any if your couplings is floating and missing from your param_cards!"
1251 << std::endl;
1252 const auto errorMsg = errorMsgStream.str();
1253 throw std::runtime_error(errorMsg);
1254 }
1256 return retval;
1257}
1258
1259////////////////////////////////////////////////////////////////////////////////
1260/// build the sample weights required for the input templates
1261//
1262template <class T1>
1263inline void buildSampleWeights(T1 &weights, const char *fname, const RooLagrangianMorphFunc::ParamMap &inputParameters,
1264 FormulaList &formulas, const Matrix &inverse)
1265{
1266 int sampleidx = 0;
1267
1268 for (auto sampleit : inputParameters) {
1269 const std::string sample(sampleit.first);
1270 std::stringstream title;
1272 if (fname) {
1273 name_full.Append("_");
1274 name_full.Append(fname);
1275 name_full.Prepend("w_");
1276 }
1277
1278 int formulaidx = 0;
1279 // build the formula with the correct normalization
1280 auto sampleformula = std::make_unique<RooLinearCombination>(name_full.Data());
1281 for (auto const &formulait : formulas) {
1283 sampleformula->add(val, formulait.second.get());
1284 formulaidx++;
1285 }
1286 weights.addOwned(std::move(sampleformula));
1287 sampleidx++;
1288 }
1289}
1290
1291inline std::map<std::string, std::string>
1293 const Matrix &inverse)
1294{
1295 int sampleidx = 0;
1296 std::map<std::string, std::string> weights;
1297 for (auto sampleit : inputParameters) {
1298 const std::string sample(sampleit.first);
1299 std::stringstream str;
1300 int formulaidx = 0;
1301 // build the formula with the correct normalization
1302 for (auto const &formulait : formulas) {
1303 double val(inverse(formulaidx, sampleidx));
1304 if (val != 0.) {
1305 if (formulaidx > 0 && val > 0)
1306 str << " + ";
1307 str << val << "*(" << formulait.second->GetTitle() << ")";
1308 }
1309 formulaidx++;
1310 }
1311 weights[sample] = str.str();
1312 sampleidx++;
1313 }
1314 return weights;
1315}
1316} // namespace
1317
1318///////////////////////////////////////////////////////////////////////////////
1319// CacheElem magic ////////////////////////////////////////////////////////////
1320///////////////////////////////////////////////////////////////////////////////
1321
1323public:
1324 std::unique_ptr<RooRealSumFunc> _sumFunc = nullptr;
1326
1327 FormulaList _formulas;
1329
1333
1336
1337 //////////////////////////////////////////////////////////////////////////////
1338 /// retrieve the list of contained args
1339
1341 {
1342 RooArgList args(*_sumFunc);
1343 args.add(_weights);
1344 args.add(_couplings);
1345 for (auto const &it : _formulas) {
1346 args.add(*(it.second));
1347 }
1348 return args;
1349 }
1350
1351 //////////////////////////////////////////////////////////////////////////////
1352 /// create the basic objects required for the morphing
1353
1356 const std::vector<std::vector<RooListProxy *>> &diagramProxyList,
1357 const std::vector<std::vector<std::string>> &nonInterfering, const RooArgList &flags)
1358 {
1360 std::vector<std::vector<RooArgList *>> diagrams;
1361 for (const auto &diagram : diagramProxyList) {
1362 diagrams.emplace_back();
1363 for (RooArgList *vertex : diagram) {
1365 diagrams.back().emplace_back(vertex);
1366 }
1367 }
1370 }
1371
1372 //////////////////////////////////////////////////////////////////////////////
1373 /// build and invert the morphing matrix
1374 template <class List>
1376 const RooLagrangianMorphFunc::FlagMap &inputFlags, const List &flags)
1377 {
1381 if (size(matrix) < 1) {
1382 std::cerr << "input matrix is empty, please provide suitable input samples!" << std::endl;
1383 }
1385
1387 double unityDeviation;
1388 double largestWeight;
1390 bool weightwarning(largestWeight > morphLargestWeight ? true : false);
1391 bool unitywarning(unityDeviation > morphUnityDeviation ? true : false);
1392
1393 if (false) {
1394 if (unitywarning) {
1395 oocxcoutW((TObject *)nullptr, Eval) << "Warning: The matrix inversion seems to be unstable. This can "
1396 "be a result to input samples that are not sufficiently "
1397 "different to provide any morphing power."
1398 << std::endl;
1399 } else if (weightwarning) {
1400 oocxcoutW((TObject *)nullptr, Eval) << "Warning: Some weights are excessively large. This can be a "
1401 "result to input samples that are not sufficiently different to "
1402 "provide any morphing power."
1403 << std::endl;
1404 }
1405 oocxcoutW((TObject *)nullptr, Eval) << " Please consider the couplings "
1406 "encoded in your samples to cross-check:"
1407 << std::endl;
1408 for (auto sampleit : inputParameters) {
1409 const std::string sample(sampleit.first);
1410 oocxcoutW((TObject *)nullptr, Eval) << " " << sample << ": ";
1411 // set all vars to value stored in input file
1412 setParams(sampleit.second, operators, true);
1413 bool first = true;
1414 RooAbsReal *obj;
1415
1416 for (auto itr : _couplings) {
1417 obj = dynamic_cast<RooAbsReal *>(itr);
1418 if (!first)
1419 std::cerr << ", ";
1420 oocxcoutW((TObject *)nullptr, Eval) << obj->GetName() << "=" << obj->getVal();
1421 first = false;
1422 }
1423 oocxcoutW((TObject *)nullptr, Eval) << std::endl;
1424 }
1425 }
1426#ifndef USE_UBLAS
1427 _matrix.ResizeTo(matrix.GetNrows(), matrix.GetNrows());
1428 _inverse.ResizeTo(matrix.GetNrows(), matrix.GetNrows());
1429#endif
1430 _matrix = matrix;
1431 _inverse = inverse;
1433 }
1434
1435 ////////////////////////////////////////////////////////////////////////////////
1436 /// build the final morphing function
1437
1439 const std::map<std::string, int> &storage, const RooArgList &physics,
1440 bool allowNegativeYields, RooRealVar *observable, RooRealVar *binWidth)
1441 {
1442 if (!binWidth) {
1443 std::cerr << "invalid bin width given!" << std::endl;
1444 return;
1445 }
1446 if (!observable) {
1447 std::cerr << "invalid observable given!" << std::endl;
1448 return;
1449 }
1450
1453
1454 // retrieve the weights
1456
1457 // build the products of element and weight for each sample
1458 size_t i = 0;
1461 for (auto sampleit : inputParameters) {
1462 // for now, we assume all the lists are nicely ordered
1464
1465 RooAbsReal *obj = static_cast<RooAbsReal *>(physics.at(storage.at(prodname.Data())));
1466
1467 if (!obj) {
1468 std::cerr << "unable to access physics object for " << prodname << std::endl;
1469 return;
1470 }
1471
1472 RooAbsReal *weight = static_cast<RooAbsReal *>(_weights.at(i));
1473
1474 if (!weight) {
1475 std::cerr << "unable to access weight object for " << prodname << std::endl;
1476 return;
1477 }
1478 prodname.Append("_");
1479 prodname.Append(name);
1480 RooArgList prodElems(*weight, *obj);
1481
1482 allowNegativeYields = true;
1483 auto prod = std::make_unique<RooProduct>(prodname, prodname, prodElems);
1484 if (!allowNegativeYields) {
1485 auto maxname = std::string(prodname) + "_max0";
1486 RooArgSet prodset(*prod);
1487
1488 auto max = std::make_unique<RooFormulaVar>(maxname.c_str(), "max(0," + prodname + ")", prodset);
1489 max->addOwnedComponents(std::move(prod));
1490 sumElements.addOwned(std::move(max));
1491 } else {
1492 sumElements.addOwned(std::move(prod));
1493 }
1494 scaleElements.add(*(binWidth));
1495 i++;
1496 }
1497
1498 // put everything together
1499 _sumFunc = make_unique<RooRealSumFunc>((std::string(name) + "_morphfunc").c_str(), name, sumElements, scaleElements);
1500
1501 if (!observable)
1502 std::cerr << "unable to access observable" << std::endl;
1503 _sumFunc->addServer(*observable);
1504 if (!binWidth)
1505 std::cerr << "unable to access bin width" << std::endl;
1506 _sumFunc->addServer(*binWidth);
1507 if (operators.empty())
1508 std::cerr << "no operators listed" << std::endl;
1509 _sumFunc->addServerList(operators);
1510 if (_weights.empty())
1511 std::cerr << "unable to access weight objects" << std::endl;
1512 _sumFunc->addOwnedComponents(std::move(sumElements));
1513 _sumFunc->addServerList(sumElements);
1514 _sumFunc->addServerList(scaleElements);
1515
1516#ifdef USE_UBLAS
1517 std::cout.precision(std::numeric_limits<double>::digits);
1518#endif
1519 }
1520 //////////////////////////////////////////////////////////////////////////////
1521 /// create all the temporary objects required by the class
1522
1524 {
1525 std::string obsName = func->getObservable()->GetName();
1527
1529
1530 cache->createComponents(func->_config.paramCards, func->_config.flagValues, func->GetName(), func->_diagrams,
1531 func->_nonInterfering, func->_flags);
1532
1533 cache->buildMatrix(func->_config.paramCards, func->_config.flagValues, func->_flags);
1534 if (obsName.empty()) {
1535 std::cerr << "Matrix inversion succeeded, but no observable was "
1536 "supplied. quitting..."
1537 << std::endl;
1538 return cache;
1539 }
1540
1541 oocxcoutP((TObject *)nullptr, ObjectHandling) << "observable: " << func->getObservable()->GetName() << std::endl;
1542 oocxcoutP((TObject *)nullptr, ObjectHandling) << "binWidth: " << func->getBinWidth()->GetName() << std::endl;
1543
1544 setParams(func->_flags, 1);
1545 cache->buildMorphingFunction(func->GetName(), func->_config.paramCards, func->_sampleMap, func->_physics,
1546 func->_config.allowNegativeYields, func->getObservable(), func->getBinWidth());
1547 setParams(values, func->_operators, true);
1548 setParams(func->_flags, 1);
1549 return cache;
1550 }
1551
1552 //////////////////////////////////////////////////////////////////////////////
1553 /// create all the temporary objects required by the class
1554 /// function variant with precomputed inverse matrix
1555
1557 {
1559
1561
1562 cache->createComponents(func->_config.paramCards, func->_config.flagValues, func->GetName(), func->_diagrams,
1563 func->_nonInterfering, func->_flags);
1564
1565#ifndef USE_UBLAS
1566 cache->_inverse.ResizeTo(inverse.GetNrows(), inverse.GetNrows());
1567#endif
1568 cache->_inverse = inverse;
1569 cache->_condition = NaN;
1570
1571 setParams(func->_flags, 1);
1572 cache->buildMorphingFunction(func->GetName(), func->_config.paramCards, func->_sampleMap, func->_physics,
1573 func->_config.allowNegativeYields, func->getObservable(), func->getBinWidth());
1574 setParams(values, func->_operators, true);
1575 setParams(func->_flags, 1);
1576 return cache;
1577 }
1578};
1579
1580///////////////////////////////////////////////////////////////////////////////
1581// Class Implementation ///////////////////////////////////////////////////////
1582///////////////////////////////////////////////////////////////////////////////
1583
1584////////////////////////////////////////////////////////////////////////////////
1585/// write a matrix to a file
1586
1591
1592////////////////////////////////////////////////////////////////////////////////
1593/// write a matrix to a stream
1594
1596{
1598}
1599
1600////////////////////////////////////////////////////////////////////////////////
1601/// read a matrix from a text file
1602
1607
1608////////////////////////////////////////////////////////////////////////////////
1609/// read a matrix from a stream
1610
1615
1616////////////////////////////////////////////////////////////////////////////////
1617/// setup observable, recycle existing observable if defined
1618
1620{
1621 // cxcoutP(ObjectHandling) << "setting up observable" << std::endl;
1622 RooRealVar *obs = nullptr;
1623 bool obsExists(false);
1624 if (_observables.at(0) != nullptr) {
1625 obs = static_cast<RooRealVar *>(_observables.at(0));
1626 obsExists = true;
1627 }
1628
1629 if (mode && mode->InheritsFrom(RooHistFunc::Class())) {
1630 obs = static_cast<RooRealVar *>(dynamic_cast<RooHistFunc *>(inputExample)->getHistObsList().first());
1631 obsExists = true;
1632 _observables.add(*obs);
1633 } else if (mode && mode->InheritsFrom(RooParamHistFunc::Class())) {
1634 obs = static_cast<RooRealVar *>(dynamic_cast<RooParamHistFunc *>(inputExample)->paramList().first());
1635 obsExists = true;
1636 _observables.add(*obs);
1637 }
1638
1639 // Note: "found!" will be printed if s2 is a substring of s1, both s1 and s2
1640 // are of type std::string. s1.find(s2)
1641 // obtain the observable
1642 if (!obsExists) {
1643 if (mode && mode->InheritsFrom(TH1::Class())) {
1644 TH1 *hist = static_cast<TH1 *>(inputExample);
1645 auto obsOwner =
1646 std::make_unique<RooRealVar>(obsname, obsname, hist->GetXaxis()->GetXmin(), hist->GetXaxis()->GetXmax());
1647 obs = obsOwner.get();
1648 addOwnedComponents(std::move(obsOwner));
1649 obs->setBins(hist->GetNbinsX());
1650 } else {
1651 auto obsOwner = std::make_unique<RooRealVar>(obsname, obsname, 0, 1);
1652 obs = obsOwner.get();
1653 addOwnedComponents(std::move(obsOwner));
1654 obs->setBins(1);
1655 }
1656 _observables.add(*obs);
1657 } else {
1658 if (strcmp(obsname, obs->GetName()) != 0) {
1659 coutW(ObjectHandling) << " name of existing observable " << _observables.at(0)->GetName()
1660 << " does not match expected name " << obsname << std::endl;
1661 }
1662 }
1663
1664 TString sbw = TString::Format("binWidth_%s", makeValidName(obs->GetName()).Data());
1665 auto binWidth = std::make_unique<RooRealVar>(sbw.Data(), sbw.Data(), 1.);
1666 double bw = obs->numBins() / (obs->getMax() - obs->getMin());
1667 binWidth->setVal(bw);
1668 binWidth->setConstant(true);
1669 _binWidths.addOwned(std::move(binWidth));
1670
1671 return obs;
1672}
1673
1674//#ifndef USE_MULTIPRECISION_LC
1675//#pragma GCC diagnostic push
1676//#pragma GCC diagnostic ignored "-Wunused-parameter"
1677//#endif
1678
1679////////////////////////////////////////////////////////////////////////////////
1680/// update sample weight (-?-)
1681
1683{
1684 //#ifdef USE_MULTIPRECISION_LC
1685 int sampleidx = 0;
1686 auto cache = this->getCache();
1687 const size_t n(size(cache->_inverse));
1688 for (auto sampleit : _config.paramCards) {
1689 const std::string sample(sampleit.first);
1690 // build the formula with the correct normalization
1691 RooLinearCombination *sampleformula = dynamic_cast<RooLinearCombination *>(this->getSampleWeight(sample.c_str()));
1692 if (!sampleformula) {
1693 coutE(ObjectHandling) << Form("unable to access formula for sample '%s'!", sample.c_str()) << std::endl;
1694 return;
1695 }
1696 cxcoutP(ObjectHandling) << "updating formula for sample '" << sample << "'" << std::endl;
1697 for (size_t formulaidx = 0; formulaidx < n; ++formulaidx) {
1698 const RooFit::SuperFloat val(cache->_inverse(formulaidx, sampleidx));
1699#ifdef USE_UBLAS
1700 if (val != val) {
1701#else
1702 if (std::isnan(val)) {
1703#endif
1704 coutE(ObjectHandling) << "refusing to propagate NaN!" << std::endl;
1705 }
1706 cxcoutP(ObjectHandling) << " " << formulaidx << ":" << sampleformula->getCoefficient(formulaidx) << " -> "
1707 << val << std::endl;
1708 sampleformula->setCoefficient(formulaidx, val);
1709 assert(sampleformula->getCoefficient(formulaidx) == val);
1710 }
1711 sampleformula->setValueDirty();
1712 ++sampleidx;
1713 }
1714 //#else
1715 // ERROR("updating sample weights currently not possible without boost!");
1716 //#endif
1717}
1718//#ifndef USE_MULTIPRECISION_LC
1719//#pragma GCC diagnostic pop
1720//#endif
1721
1722////////////////////////////////////////////////////////////////////////////////
1723/// read the parameters from the input file
1724
1730
1731////////////////////////////////////////////////////////////////////////////////
1732/// retrieve the physics inputs
1733
1735{
1736 std::string obsName;
1737 if (_config.observable) {
1739 if (_config.observableName.empty()) {
1741 } else {
1743 }
1744 } else {
1746 }
1747
1748 cxcoutP(InputArguments) << "initializing physics inputs from file " << file->GetName() << " with object name(s) '"
1749 << obsName << "'" << std::endl;
1750 auto folderNames = _config.folderNames;
1751 auto obj = loadFromFileResidentFolder<TObject>(file, folderNames.front(), obsName, true);
1752 if (!obj) {
1753 std::cerr << "unable to locate object '" << obsName << "' in folder '" << folderNames.front() << "'!"
1754 << std::endl;
1755 return;
1756 }
1757 std::string classname = obj->ClassName();
1758 TClass *mode = TClass::GetClass(obj->ClassName());
1759 this->setupObservable(obsName.c_str(), mode, obj.get());
1760
1761 if (classname.find("TH1") != std::string::npos) {
1762 collectHistograms(this->GetName(), file, _sampleMap, _physics, *static_cast<RooRealVar *>(_observables.at(0)),
1764 } else if (classname.find("RooHistFunc") != std::string::npos ||
1765 classname.find("RooParamHistFunc") != std::string::npos ||
1766 classname.find("PiecewiseInterpolation") != std::string::npos) {
1768 } else if (classname.find("TParameter<double>") != std::string::npos) {
1770 } else if (classname.find("TParameter<float>") != std::string::npos) {
1772 } else if (classname.find("TPair") != std::string::npos) {
1773 collectCrosssectionsTPair(this->GetName(), file, _sampleMap, _physics, obsName, folderNames[0],
1775 } else {
1776 std::cerr << "cannot morph objects of class '" << mode->GetName() << "'!" << std::endl;
1777 }
1778}
1779
1780////////////////////////////////////////////////////////////////////////////////
1781/// print all the parameters and their values in the given sample to the console
1782
1784{
1785 for (const auto &param : _config.paramCards.at(samplename)) {
1786 if (this->hasParameter(param.first.c_str())) {
1787 std::cout << param.first << " = " << param.second;
1788 if (this->isParameterConstant(param.first.c_str()))
1789 std::cout << " (const)";
1790 std::cout << std::endl;
1791 }
1792 }
1793}
1794
1795////////////////////////////////////////////////////////////////////////////////
1796/// print all the known samples to the console
1797
1799{
1800 // print all the known samples to the console
1801 for (auto folder : _config.folderNames) {
1802 std::cout << folder << std::endl;
1803 }
1804}
1805
1806////////////////////////////////////////////////////////////////////////////////
1807/// print the current physics values
1808
1810{
1811 for (const auto &sample : _sampleMap) {
1812 RooAbsArg *phys = _physics.at(sample.second);
1813 if (!phys)
1814 continue;
1815 phys->Print();
1816 }
1817}
1818
1819////////////////////////////////////////////////////////////////////////////////
1820/// constructor with proper arguments
1821
1822RooLagrangianMorphFunc::RooLagrangianMorphFunc(const char *name, const char *title, const Config &config)
1823 : RooAbsReal(name, title), _cacheMgr(this, 10, true, true), _physics("physics", "physics", this),
1824 _operators("operators", "set of operators", this), _observables("observables", "morphing observables", this),
1825 _binWidths("binWidths", "set of binWidth objects", this), _flags("flags", "flags", this), _config(config)
1826{
1827 this->init();
1829 this->setup(false);
1830
1832}
1833
1834////////////////////////////////////////////////////////////////////////////////
1835/// setup this instance with the given set of operators and vertices
1836/// if own=true, the class will own the operators template `<class Base>`
1837
1839{
1840 if (!_config.couplings.empty()) {
1842 std::vector<RooListProxy *> vertices;
1844 vertices.push_back(new RooListProxy("!couplings", "set of couplings in the vertex", this, true, false));
1845 if (own) {
1846 _operators.addOwned(std::move(operators));
1847 vertices[0]->addOwned(_config.couplings);
1848 } else {
1850 vertices[0]->add(_config.couplings);
1851 }
1852 _diagrams.push_back(vertices);
1853 }
1854
1856 std::vector<RooListProxy *> vertices;
1858 cxcoutP(InputArguments) << "prod/dec couplings provided" << std::endl;
1861 vertices.push_back(
1862 new RooListProxy("!production", "set of couplings in the production vertex", this, true, false));
1863 vertices.push_back(new RooListProxy("!decay", "set of couplings in the decay vertex", this, true, false));
1864 if (own) {
1865 _operators.addOwned(std::move(operators));
1866 vertices[0]->addOwned(_config.prodCouplings);
1867 vertices[1]->addOwned(_config.decCouplings);
1868 } else {
1869 cxcoutP(InputArguments) << "adding non-own operators" << std::endl;
1871 vertices[0]->add(_config.prodCouplings);
1872 vertices[1]->add(_config.decCouplings);
1873 }
1874 _diagrams.push_back(vertices);
1875 }
1876}
1877
1878////////////////////////////////////////////////////////////////////////////////
1879/// disable interference between terms
1880
1881void RooLagrangianMorphFunc::disableInterference(const std::vector<const char *> &nonInterfering)
1882{
1883 // disable interference between the listed operators
1884 std::stringstream name;
1885 name << "noInterference";
1886 for (auto c : nonInterfering) {
1887 name << c;
1888 }
1889 _nonInterfering.emplace_back();
1890 for (auto c : nonInterfering) {
1891 _nonInterfering.back().emplace_back(c);
1892 }
1893}
1894
1895////////////////////////////////////////////////////////////////////////////////
1896/// disable interference between terms
1897
1898void RooLagrangianMorphFunc::disableInterferences(const std::vector<std::vector<const char *>> &nonInterfering)
1899{
1900 // disable interferences between the listed groups of operators
1901 for (size_t i = 0; i < nonInterfering.size(); ++i) {
1902 this->disableInterference(nonInterfering[i]);
1903 }
1904}
1905
1906////////////////////////////////////////////////////////////////////////////////
1907/// initialise inputs required for the morphing function
1908
1910{
1911 std::string filename = _config.fileName;
1912 TDirectory *file = openFile(filename);
1913 if (!file) {
1914 coutE(InputArguments) << "unable to open file '" << filename << "'!" << std::endl;
1915 return;
1916 }
1917 this->readParameters(file);
1919 this->collectInputs(file);
1920 closeFile(file);
1921 auto nNP0 = std::make_unique<RooRealVar>("nNP0", "nNP0", 1., 0, 1.);
1922 nNP0->setStringAttribute("NewPhysics", "0");
1923 nNP0->setConstant(true);
1924 _flags.addOwned(std::move(nNP0));
1925 auto nNP1 = std::make_unique<RooRealVar>("nNP1", "nNP1", 1., 0, 1.);
1926 nNP1->setStringAttribute("NewPhysics", "1");
1927 nNP1->setConstant(true);
1928 _flags.addOwned(std::move(nNP1));
1929 auto nNP2 = std::make_unique<RooRealVar>("nNP2", "nNP2", 1., 0, 1.);
1930 nNP2->setStringAttribute("NewPhysics", "2");
1931 nNP2->setConstant(true);
1932 _flags.addOwned(std::move(nNP2));
1933 auto nNP3 = std::make_unique<RooRealVar>("nNP3", "nNP3", 1., 0, 1.);
1934 nNP3->setStringAttribute("NewPhysics", "3");
1935 nNP3->setConstant(true);
1936 _flags.addOwned(std::move(nNP3));
1937 auto nNP4 = std::make_unique<RooRealVar>("nNP4", "nNP4", 1., 0, 1.);
1938 nNP4->setStringAttribute("NewPhysics", "4");
1939 nNP4->setConstant(true);
1940 _flags.addOwned(std::move(nNP4));
1941}
1942
1943////////////////////////////////////////////////////////////////////////////////
1944/// copy constructor
1945
1947 : RooAbsReal(other, name), _cacheMgr(other._cacheMgr, this), _scale(other._scale), _sampleMap(other._sampleMap),
1948 _physics(other._physics.GetName(), this, other._physics),
1949 _operators(other._operators.GetName(), this, other._operators),
1950 _observables(other._observables.GetName(), this, other._observables),
1951 _binWidths(other._binWidths.GetName(), this, other._binWidths), _flags{other._flags.GetName(), this, other._flags},
1952 _config(other._config)
1953{
1954 for (size_t j = 0; j < other._diagrams.size(); ++j) {
1955 std::vector<RooListProxy *> diagram;
1956 for (size_t i = 0; i < other._diagrams[j].size(); ++i) {
1957 RooListProxy *list = new RooListProxy(other._diagrams[j][i]->GetName(), this, *(other._diagrams[j][i]));
1958 diagram.push_back(list);
1959 }
1960 _diagrams.push_back(diagram);
1961 }
1963}
1964
1965////////////////////////////////////////////////////////////////////////////////
1966/// set energy scale of the EFT expansion
1967
1969{
1970 _scale = val;
1971}
1972
1973////////////////////////////////////////////////////////////////////////////////
1974/// get energy scale of the EFT expansion
1975
1977{
1978 return _scale;
1979}
1980
1981////////////////////////////////////////////////////////////////////////////////
1982// default constructor
1983
1985 : _cacheMgr(this, 10, true, true), _operators("operators", "set of operators", this, true, false),
1986 _observables("observable", "morphing observable", this, true, false),
1987 _binWidths("binWidths", "set of bin width objects", this, true, false)
1988{
1990}
1991
1992////////////////////////////////////////////////////////////////////////////////
1993/// default destructor
1994
1996{
1997 for (auto const &diagram : _diagrams) {
1998 for (RooListProxy *vertex : diagram) {
1999 delete vertex;
2000 }
2001 }
2003}
2004
2005////////////////////////////////////////////////////////////////////////////////
2006/// calculate the number of samples needed to morph a bivertex, 2-2 physics
2007/// process
2008
2010{
2012 std::vector<bool> prod;
2013 std::vector<bool> dec;
2014 for (int i = 0; i < nboth; ++i) {
2015 prod.push_back(true);
2016 dec.push_back(true);
2017 }
2018 for (int i = 0; i < nprod; ++i) {
2019 prod.push_back(true);
2020 dec.push_back(false);
2021 }
2022 for (int i = 0; i < ndec; ++i) {
2023 prod.push_back(false);
2024 dec.push_back(true);
2025 }
2026 diagram.push_back(prod);
2027 diagram.push_back(dec);
2030 return morphfuncpattern.size();
2031}
2032
2033////////////////////////////////////////////////////////////////////////////////
2034/// calculate the number of samples needed to morph a certain physics process
2035
2036int RooLagrangianMorphFunc::countSamples(std::vector<RooArgList *> &vertices)
2037{
2039 RooArgList couplings;
2040 for (auto vertex : vertices) {
2042 extractCouplings(*vertex, couplings);
2043 }
2045 ::fillFeynmanDiagram(diagram, vertices, couplings);
2048 return morphfuncpattern.size();
2049}
2050
2051////////////////////////////////////////////////////////////////////////////////
2052/// create only the weight formulas. static function for external usage.
2053
2054std::map<std::string, std::string>
2056 const std::vector<std::vector<std::string>> &vertices_str)
2057{
2058 std::stack<RooArgList> ownedVertices;
2059 std::vector<RooArgList *> vertices;
2060 RooArgList couplings;
2061 for (const auto &vtx : vertices_str) {
2062 ownedVertices.emplace();
2063 auto &vertex = ownedVertices.top();
2064 for (const auto &c : vtx) {
2065 auto coupling = static_cast<RooRealVar *>(couplings.find(c.c_str()));
2066 if (!coupling) {
2067 auto couplingOwner = std::make_unique<RooRealVar>(c.c_str(), c.c_str(), 1., 0., 10.);
2068 coupling = couplingOwner.get();
2069 couplings.addOwned(std::move(couplingOwner));
2070 }
2071 vertex.add(*coupling);
2072 }
2073 vertices.push_back(&vertex);
2074 }
2075 auto retval = RooLagrangianMorphFunc::createWeightStrings(inputs, vertices, couplings);
2076 return retval;
2077}
2078
2079////////////////////////////////////////////////////////////////////////////////
2080/// create only the weight formulas. static function for external usage.
2081
2082std::map<std::string, std::string>
2084 const std::vector<RooArgList *> &vertices, RooArgList &couplings)
2085{
2086 return createWeightStrings(inputs, vertices, couplings, {}, {}, {});
2087}
2088
2089////////////////////////////////////////////////////////////////////////////////
2090/// create only the weight formulas. static function for external usage.
2091
2092std::map<std::string, std::string>
2094 const std::vector<RooArgList *> &vertices, RooArgList &couplings,
2095 const RooLagrangianMorphFunc::FlagMap &flagValues, const RooArgList &flags,
2096 const std::vector<std::vector<std::string>> &nonInterfering)
2097{
2098 FormulaList formulas = ::createFormulas("", inputs, flagValues, {vertices}, couplings, flags, nonInterfering);
2100 extractOperators(couplings, operators);
2102 if (size(matrix) < 1) {
2103 std::cerr << "input matrix is empty, please provide suitable input samples!" << std::endl;
2104 }
2106 double condition __attribute__((unused)) = (double)(invertMatrix(matrix, inverse));
2108 return retval;
2109}
2110
2111////////////////////////////////////////////////////////////////////////////////
2112/// create only the weight formulas. static function for external usage.
2113
2115 const std::vector<RooArgList *> &vertices, RooArgList &couplings,
2116 const RooLagrangianMorphFunc::FlagMap &flagValues,
2117 const RooArgList &flags,
2118 const std::vector<std::vector<std::string>> &nonInterfering)
2119{
2120 FormulaList formulas = ::createFormulas("", inputs, flagValues, {vertices}, couplings, flags, nonInterfering);
2122 extractOperators(couplings, operators);
2124 if (size(matrix) < 1) {
2125 std::cerr << "input matrix is empty, please provide suitable input samples!" << std::endl;
2126 }
2128 double condition __attribute__((unused)) = (double)(invertMatrix(matrix, inverse));
2130 ::buildSampleWeights(retval, (const char *)nullptr /* name */, inputs, formulas, inverse);
2131 return retval;
2132}
2133
2134////////////////////////////////////////////////////////////////////////////////
2135/// create only the weight formulas. static function for external usage.
2136
2138 const std::vector<RooArgList *> &vertices, RooArgList &couplings)
2139{
2140 RooArgList flags;
2141 FlagMap flagValues;
2142 return RooLagrangianMorphFunc::createWeights(inputs, vertices, couplings, flagValues, flags, {});
2143}
2144
2145////////////////////////////////////////////////////////////////////////////////
2146/// return the RooProduct that is the element of the RooRealSumPdfi
2147/// corresponding to the given sample name
2148
2150{
2151 auto mf = this->getFunc();
2152 if (!mf) {
2153 coutE(Eval) << "unable to retrieve morphing function" << std::endl;
2154 return nullptr;
2155 }
2156 std::unique_ptr<RooArgSet> args{mf->getComponents()};
2158 prodname.Append("_");
2159 prodname.Append(this->GetName());
2160
2161 for (auto itr : *args) {
2162 RooProduct *prod = dynamic_cast<RooProduct *>(itr);
2163 if (!prod)
2164 continue;
2165 TString sname(prod->GetName());
2166 if (sname.CompareTo(prodname) == 0) {
2167 return prod;
2168 }
2169 }
2170 return nullptr;
2171}
2172////////////////////////////////////////////////////////////////////////////////
2173/// return the vector of sample names, used to build the morph func
2174
2175std::vector<std::string> RooLagrangianMorphFunc::getSamples() const
2176{
2177 return _config.folderNames;
2178}
2179
2180////////////////////////////////////////////////////////////////////////////////
2181/// retrieve the weight (prefactor) of a sample with the given name
2182
2184{
2185 auto cache = this->getCache();
2186 auto wname = std::string("w_") + name + "_" + this->GetName();
2187 return dynamic_cast<RooAbsReal *>(cache->_weights.find(wname.c_str()));
2188}
2189
2190////////////////////////////////////////////////////////////////////////////////
2191/// print the current sample weights
2192
2194{
2195 this->printSampleWeights();
2196}
2197
2198////////////////////////////////////////////////////////////////////////////////
2199/// print the current sample weights
2200
2202{
2203 auto *cache = this->getCache();
2204 for (const auto &sample : _sampleMap) {
2205 auto weightName = std::string("w_") + sample.first + "_" + this->GetName();
2206 auto weight = static_cast<RooAbsReal *>(cache->_weights.find(weightName.c_str()));
2207 if (!weight)
2208 continue;
2209 }
2210}
2211
2212////////////////////////////////////////////////////////////////////////////////
2213/// randomize the parameters a bit
2214/// useful to test and debug fitting
2215
2217{
2218 RooRealVar *obj;
2219 TRandom3 r;
2220
2221 for (auto itr : _operators) {
2222 obj = dynamic_cast<RooRealVar *>(itr);
2223 double val = obj->getVal();
2224 if (obj->isConstant())
2225 continue;
2226 double variation = r.Gaus(1, z);
2227 obj->setVal(val * variation);
2228 }
2229}
2230
2231////////////////////////////////////////////////////////////////////////////////
2232/// Retrieve the new physics objects and update the weights in the morphing
2233/// function.
2234
2236{
2237 auto cache = this->getCache();
2238
2239 std::string filename = _config.fileName;
2240 TDirectory *file = openFile(filename);
2241 if (!file) {
2242 coutE(InputArguments) << "unable to open file '" << filename << "'!" << std::endl;
2243 return false;
2244 }
2245
2246 this->readParameters(file);
2247
2249 this->collectInputs(file);
2250
2251 cache->buildMatrix(_config.paramCards, _config.flagValues, _flags);
2252 this->updateSampleWeights();
2253
2254 closeFile(file);
2255 return true;
2256}
2257
2258////////////////////////////////////////////////////////////////////////////////
2259/// setup the morphing function with a predefined inverse matrix
2260/// call this function *before* any other after creating the object
2261
2263{
2264 auto cache = static_cast<RooLagrangianMorphFunc::CacheElem *>(
2265 _cacheMgr.getObj(nullptr, static_cast<RooArgSet const *>(nullptr)));
2267 if (cache) {
2268 std::string filename = _config.fileName;
2269 cache->_inverse = m;
2270 TDirectory *file = openFile(filename);
2271 if (!file) {
2272 coutE(InputArguments) << "unable to open file '" << filename << "'!" << std::endl;
2273 return false;
2274 }
2275
2276 this->readParameters(file);
2278 this->collectInputs(file);
2279
2280 // then, update the weights in the morphing function
2281 this->updateSampleWeights();
2282
2283 closeFile(file);
2284 } else {
2286 if (!cache)
2287 coutE(Caching) << "unable to create cache!" << std::endl;
2288 _cacheMgr.setObj(nullptr, nullptr, cache, nullptr);
2289 }
2290 return true;
2291}
2292
2293////////////////////////////////////////////////////////////////////////////////
2294// setup the morphing function with a predefined inverse matrix
2295// call this function *before* any other after creating the object
2296
2298{
2299 auto cache = static_cast<RooLagrangianMorphFunc::CacheElem *>(
2300 _cacheMgr.getObj(nullptr, static_cast<RooArgSet const *>(nullptr)));
2301 if (cache) {
2302 return false;
2303 }
2305 if (!cache)
2306 coutE(Caching) << "unable to create cache!" << std::endl;
2307 _cacheMgr.setObj(nullptr, nullptr, cache, nullptr);
2308 return true;
2309}
2310
2311////////////////////////////////////////////////////////////////////////////////
2312/// write the inverse matrix to a file
2313
2315{
2316 auto cache = this->getCache();
2317 if (!cache)
2318 return false;
2319 writeMatrixToFileT(cache->_inverse, filename);
2320 return true;
2321}
2322
2323////////////////////////////////////////////////////////////////////////////////
2324/// retrieve the cache object
2325
2327{
2328 auto cache = static_cast<RooLagrangianMorphFunc::CacheElem *>(
2329 _cacheMgr.getObj(nullptr, static_cast<RooArgSet const *>(nullptr)));
2330 if (!cache) {
2331 cxcoutP(Caching) << "creating cache from getCache function for " << this << std::endl;
2332 cxcoutP(Caching) << "current storage has size " << _sampleMap.size() << std::endl;
2334 if (cache) {
2335 _cacheMgr.setObj(nullptr, nullptr, cache, nullptr);
2336 } else {
2337 coutE(Caching) << "unable to create cache!" << std::endl;
2338 }
2339 }
2340 return cache;
2341}
2342
2343////////////////////////////////////////////////////////////////////////////////
2344/// return true if a cache object is present, false otherwise
2345
2347{
2348 return (bool)(_cacheMgr.getObj(nullptr, static_cast<RooArgSet *>(nullptr)));
2349}
2350
2351////////////////////////////////////////////////////////////////////////////////
2352/// set one parameter to a specific value
2353
2355{
2356 RooRealVar *param = this->getParameter(name);
2357 if (!param) {
2358 return;
2359 }
2360 if (value > param->getMax())
2361 param->setMax(value);
2362 if (value < param->getMin())
2363 param->setMin(value);
2364 param->setVal(value);
2365}
2366
2367////////////////////////////////////////////////////////////////////////////////
2368/// set one flag to a specific value
2369
2371{
2372 RooRealVar *param = this->getFlag(name);
2373 if (!param) {
2374 return;
2375 }
2376 param->setVal(value);
2377}
2378
2379////////////////////////////////////////////////////////////////////////////////
2380/// set one parameter to a specific value and range
2381
2382void RooLagrangianMorphFunc::setParameter(const char *name, double value, double min, double max)
2383{
2384 RooRealVar *param = this->getParameter(name);
2385 if (!param) {
2386 return;
2387 }
2388 param->setMin(min);
2389 param->setMax(max);
2390 param->setVal(value);
2391}
2392
2393////////////////////////////////////////////////////////////////////////////////
2394/// set one parameter to a specific value and range
2395void RooLagrangianMorphFunc::setParameter(const char *name, double value, double min, double max, double error)
2396{
2397 RooRealVar *param = this->getParameter(name);
2398 if (!param) {
2399 return;
2400 }
2401 param->setMin(min);
2402 param->setMax(max);
2403 param->setVal(value);
2404 param->setError(error);
2405}
2406
2407////////////////////////////////////////////////////////////////////////////////
2408/// return true if the parameter with the given name is set constant, false
2409/// otherwise
2410
2412{
2413 RooRealVar *param = this->getParameter(name);
2414 if (param) {
2415 return param->isConstant();
2416 }
2417 return true;
2418}
2419
2420////////////////////////////////////////////////////////////////////////////////
2421/// retrieve the RooRealVar object incorporating the parameter with the given
2422/// name
2424{
2425
2426 return dynamic_cast<RooRealVar *>(_operators.find(name));
2427}
2428
2429////////////////////////////////////////////////////////////////////////////////
2430/// retrieve the RooRealVar object incorporating the flag with the given name
2431
2433{
2434 return dynamic_cast<RooRealVar *>(_flags.find(name));
2435}
2436
2437////////////////////////////////////////////////////////////////////////////////
2438/// check if a parameter of the given name is contained in the list of known
2439/// parameters
2440
2442{
2443 return this->getParameter(name);
2444}
2445
2446////////////////////////////////////////////////////////////////////////////////
2447/// call setConstant with the boolean argument provided on the parameter with
2448/// the given name
2449
2451{
2452 RooRealVar *param = this->getParameter(name);
2453 if (param) {
2454 return param->setConstant(constant);
2455 }
2456}
2457
2458////////////////////////////////////////////////////////////////////////////////
2459/// set one parameter to a specific value
2460
2462{
2463 RooRealVar *param = this->getParameter(name);
2464 if (param) {
2465 return param->getVal();
2466 }
2467 return 0.0;
2468}
2469
2470////////////////////////////////////////////////////////////////////////////////
2471/// set the morphing parameters to those supplied in the given param hist
2472
2477
2478////////////////////////////////////////////////////////////////////////////////
2479/// set the morphing parameters to those supplied in the sample with the given
2480/// name
2481
2483{
2484 std::string filename = _config.fileName;
2485 TDirectory *file = openFile(filename);
2486 auto paramhist = loadFromFileResidentFolder<TH1>(file, foldername, "param_card");
2487 setParams(paramhist.get(), _operators, false);
2488 closeFile(file);
2489}
2490
2491/////////////////////////////////////////////////////////////////////////////////
2492/// retrieve the morphing parameters associated to the sample with the given
2493/// name
2494
2500
2501////////////////////////////////////////////////////////////////////////////////
2502/// set the morphing parameters to those supplied in the list with the given
2503/// name
2504
2506{
2507 for (auto itr : *list) {
2508 RooRealVar *param = dynamic_cast<RooRealVar *>(itr);
2509 if (!param)
2510 continue;
2511 this->setParameter(param->GetName(), param->getVal());
2512 }
2513}
2514
2515////////////////////////////////////////////////////////////////////////////////
2516/// retrieve the histogram observable
2517
2519{
2520 if (_observables.empty()) {
2521 coutE(InputArguments) << "observable not available!" << std::endl;
2522 return nullptr;
2523 }
2524 return static_cast<RooRealVar *>(_observables.at(0));
2525}
2526
2527////////////////////////////////////////////////////////////////////////////////
2528/// retrieve the histogram observable
2529
2531{
2532 if (_binWidths.empty()) {
2533 coutE(InputArguments) << "bin width not available!" << std::endl;
2534 return nullptr;
2535 }
2536 return static_cast<RooRealVar *>(_binWidths.at(0));
2537}
2538
2539////////////////////////////////////////////////////////////////////////////////
2540/// retrieve a histogram output of the current morphing settings
2541
2543{
2544 return this->createTH1(name, false);
2545}
2546
2547////////////////////////////////////////////////////////////////////////////////
2548/// retrieve a histogram output of the current morphing settings
2549
2551{
2552 auto mf = std::make_unique<RooRealSumFunc>(*(this->getFunc()));
2553 RooRealVar *observable = this->getObservable();
2554
2555 const int nbins = observable->getBins();
2556
2557 auto hist = std::make_unique<TH1F>(name.c_str(), name.c_str(), nbins, observable->getBinning().array());
2558
2559 std::unique_ptr<RooArgSet> args{mf->getComponents()};
2560 for (int i = 0; i < nbins; ++i) {
2561 observable->setBin(i);
2562 double val = 0;
2563 double unc2 = 0;
2564 double unc = 0;
2565 for (auto itr : *args) {
2566 RooProduct *prod = dynamic_cast<RooProduct *>(itr);
2567 if (!prod)
2568 continue;
2569 RooAbsArg *phys = prod->components().find(Form("phys_%s", prod->GetName()));
2570 RooHistFunc *hf = dynamic_cast<RooHistFunc *>(phys);
2571 if (!hf) {
2572 continue;
2573 }
2574 const RooDataHist &dhist = hf->dataHist();
2575 dhist.get(i);
2576 RooAbsReal *formula = dynamic_cast<RooAbsReal *>(prod->components().find(Form("w_%s", prod->GetName())));
2577 double weight = formula->getVal();
2578 unc2 += dhist.weightSquared() * weight * weight;
2579 unc += sqrt(dhist.weightSquared()) * weight;
2580 val += dhist.weight() * weight;
2581 }
2582 hist->SetBinContent(i + 1, val);
2583 hist->SetBinError(i + 1, correlateErrors ? unc : sqrt(unc2));
2584 }
2585 return hist.release();
2586}
2587
2588////////////////////////////////////////////////////////////////////////////////
2589/// count the number of formulas that correspond to the current parameter set
2590
2592{
2593 int nFormulas = 0;
2594 auto mf = std::make_unique<RooRealSumFunc>(*(this->getFunc()));
2595 if (!mf)
2596 coutE(InputArguments) << "unable to retrieve morphing function" << std::endl;
2597 std::unique_ptr<RooArgSet> args{mf->getComponents()};
2598 for (auto itr : *args) {
2599 RooProduct *prod = dynamic_cast<RooProduct *>(itr);
2600 if (prod->getVal() != 0) {
2601 nFormulas++;
2602 }
2603 }
2604 return nFormulas;
2605}
2606
2607////////////////////////////////////////////////////////////////////////////////
2608/// check if there is any morphing power provided for the given parameter
2609/// morphing power is provided as soon as any two samples provide different,
2610/// non-zero values for this parameter
2611
2613{
2614 std::string pname(paramname);
2615 double val = 0;
2616 bool isUsed = false;
2617 for (const auto &sample : _config.paramCards) {
2618 double thisval = sample.second.at(pname);
2619 if (thisval != val) {
2620 if (val != 0)
2621 isUsed = true;
2622 val = thisval;
2623 }
2624 }
2625 return isUsed;
2626}
2627
2628////////////////////////////////////////////////////////////////////////////////
2629/// check if there is any morphing power provided for the given coupling
2630/// morphing power is provided as soon as any two samples provide
2631/// different, non-zero values for this coupling
2632
2634{
2635 std::string cname(couplname);
2636 const RooArgList *args = this->getCouplingSet();
2637 RooAbsReal *coupling = dynamic_cast<RooAbsReal *>(args->find(couplname));
2638 if (!coupling)
2639 return false;
2641 double val = 0;
2642 bool isUsed = false;
2643 for (const auto &sample : _config.paramCards) {
2644 this->setParameters(sample.second);
2645 double thisval = coupling->getVal();
2646 if (thisval != val) {
2647 if (val != 0)
2648 isUsed = true;
2649 val = thisval;
2650 }
2651 }
2652 this->setParameters(params);
2653 return isUsed;
2654}
2655
2656////////////////////////////////////////////////////////////////////////////////
2657/// return the number of parameters in this morphing function
2658
2660{
2661 return this->getParameterSet()->size();
2662}
2663
2664////////////////////////////////////////////////////////////////////////////////
2665/// return the number of samples in this morphing function
2666
2668{
2669 // return the number of samples in this morphing function
2670 auto cache = getCache();
2671 return cache->_formulas.size();
2672}
2673
2674////////////////////////////////////////////////////////////////////////////////
2675/// print the contributing samples and their respective weights
2676
2678{
2679 auto mf = std::make_unique<RooRealSumFunc>(*(this->getFunc()));
2680 if (!mf) {
2681 std::cerr << "Error: unable to retrieve morphing function" << std::endl;
2682 return;
2683 }
2684 std::unique_ptr<RooArgSet> args{mf->getComponents()};
2685 for (auto *formula : dynamic_range_cast<RooAbsReal*>(*args)) {
2686 if (formula) {
2687 TString name(formula->GetName());
2688 name.Remove(0, 2);
2689 name.Prepend("phys_");
2690 if (!args->find(name.Data())) {
2691 continue;
2692 }
2693 double val = formula->getVal();
2694 if (val != 0) {
2695 std::cout << formula->GetName() << ": " << val << " = " << formula->GetTitle() << std::endl;
2696 }
2697 }
2698 }
2699}
2700
2701////////////////////////////////////////////////////////////////////////////////
2702/// get the set of parameters
2703
2705{
2706 return &(_operators);
2707}
2708
2709////////////////////////////////////////////////////////////////////////////////
2710/// get the set of couplings
2711
2713{
2714 auto cache = getCache();
2715 return &(cache->_couplings);
2716}
2717
2718////////////////////////////////////////////////////////////////////////////////
2719/// retrieve a set of couplings (-?-)
2720
2722{
2724 for (auto obj : *(this->getCouplingSet())) {
2725 RooAbsReal *var = dynamic_cast<RooAbsReal *>(obj);
2726 if (!var)
2727 continue;
2728 const std::string name(var->GetName());
2729 double val = var->getVal();
2730 couplings[name] = val;
2731 }
2732 return couplings;
2733}
2734
2735////////////////////////////////////////////////////////////////////////////////
2736/// retrieve the parameter set
2737
2742
2743////////////////////////////////////////////////////////////////////////////////
2744/// retrieve a set of couplings (-?-)
2745
2747{
2748 setParams(params, _operators, false);
2749}
2750
2751////////////////////////////////////////////////////////////////////////////////
2752/// (currently similar to cloning the Pdf
2753
2754std::unique_ptr<RooWrapperPdf> RooLagrangianMorphFunc::createPdf() const
2755{
2756 auto cache = getCache();
2757 auto func = std::make_unique<RooRealSumFunc>(*(cache->_sumFunc));
2758
2759 // create a wrapper on the roorealsumfunc
2760 return std::make_unique<RooWrapperPdf>(Form("pdf_%s", func->GetName()), Form("pdf of %s", func->GetTitle()), *func);
2761}
2762
2763////////////////////////////////////////////////////////////////////////////////
2764/// get the func
2765
2767{
2768 auto cache = getCache();
2769 return cache->_sumFunc.get();
2770}
2771
2772////////////////////////////////////////////////////////////////////////////////
2773/// return extended mored capabilities
2774
2776{
2777 return this->createPdf()->extendMode();
2778}
2779
2780////////////////////////////////////////////////////////////////////////////////
2781/// return expected number of events for extended likelihood calculation,
2782/// this is the sum of all coefficients
2783
2785{
2786 return this->createPdf()->expectedEvents(nset);
2787}
2788
2789////////////////////////////////////////////////////////////////////////////////
2790/// return the number of expected events for the current parameter set
2791
2793{
2794 RooArgSet set;
2795 set.add(*this->getObservable());
2796 return this->createPdf()->expectedEvents(set);
2797}
2798
2799////////////////////////////////////////////////////////////////////////////////
2800/// return expected number of events for extended likelihood calculation,
2801/// this is the sum of all coefficients
2802
2804{
2805 return createPdf()->expectedEvents(&nset);
2806}
2807
2808////////////////////////////////////////////////////////////////////////////////
2809/// return the expected uncertainty for the current parameter set
2810
2812{
2813 RooRealVar *observable = this->getObservable();
2814 auto cache = this->getCache();
2815 double unc2 = 0;
2816 for (const auto &sample : _sampleMap) {
2817 RooAbsArg *phys = _physics.at(sample.second);
2818 auto weightName = std::string("w_") + sample.first + "_" + this->GetName();
2819 auto weight = static_cast<RooAbsReal *>(cache->_weights.find(weightName.c_str()));
2820 if (!weight) {
2821 coutE(InputArguments) << "unable to find object " + weightName << std::endl;
2822 return 0.0;
2823 }
2824 double newunc2 = 0;
2825 RooHistFunc *hf = dynamic_cast<RooHistFunc *>(phys);
2826 RooRealVar *rv = dynamic_cast<RooRealVar *>(phys);
2827 if (hf) {
2828 const RooDataHist &hist = hf->dataHist();
2829 for (Int_t j = 0; j < observable->getBins(); ++j) {
2830 hist.get(j);
2831 newunc2 += hist.weightSquared();
2832 }
2833 } else if (rv) {
2834 newunc2 = pow(rv->getError(), 2);
2835 }
2836 double w = weight->getVal();
2837 unc2 += newunc2 * w * w;
2838 // std::cout << phys->GetName() << " : " << weight->GetName() << "
2839 // thisweight: " << w << " thisxsec2: " << newunc2 << " weight " << weight
2840 // << std::endl;
2841 }
2842 return sqrt(unc2);
2843}
2844
2845////////////////////////////////////////////////////////////////////////////////
2846/// print the parameters and their current values
2847
2849{
2850 // print the parameters and their current values
2851 for (auto obj : _operators) {
2852 RooRealVar *param = static_cast<RooRealVar *>(obj);
2853 if (!param)
2854 continue;
2855 param->Print();
2856 }
2857}
2858
2859////////////////////////////////////////////////////////////////////////////////
2860/// print the flags and their current values
2861
2863{
2864 for (auto flag : _flags) {
2865 RooRealVar *param = static_cast<RooRealVar *>(flag);
2866 if (!param)
2867 continue;
2868 param->Print();
2869 }
2870}
2871
2872////////////////////////////////////////////////////////////////////////////////
2873/// print a set of couplings
2874
2876{
2878 for (auto c : couplings) {
2879 std::cout << c.first << ": " << c.second << std::endl;
2880 }
2881}
2882
2883////////////////////////////////////////////////////////////////////////////////
2884/// retrieve the list of bin boundaries
2885
2886std::list<double> *RooLagrangianMorphFunc::binBoundaries(RooAbsRealLValue &obs, double xlo, double xhi) const
2887{
2888 return this->getFunc()->binBoundaries(obs, xlo, xhi);
2889}
2890
2891////////////////////////////////////////////////////////////////////////////////
2892/// retrieve the sample Hint
2893
2894std::list<double> *RooLagrangianMorphFunc::plotSamplingHint(RooAbsRealLValue &obs, double xlo, double xhi) const
2895{
2896 return this->getFunc()->plotSamplingHint(obs, xlo, xhi);
2897}
2898
2899////////////////////////////////////////////////////////////////////////////////
2900/// call getVal on the internal function
2901
2903{
2904 // call getVal on the internal function
2905 const RooRealSumFunc *pdf = this->getFunc();
2907 for (auto &obs : _observables) {
2908 nSet.add(*obs);
2909 }
2910 if (pdf) {
2911 return _scale * pdf->getVal(&nSet);
2912 } else {
2913 std::cerr << "unable to acquire in-built function!" << std::endl;
2914 }
2915 return 0.;
2916}
2917
2918////////////////////////////////////////////////////////////////////////////////
2919/// check if this PDF is a binned distribution in the given observable
2920
2922{
2923 return this->getFunc()->isBinnedDistribution(obs);
2924}
2925
2926////////////////////////////////////////////////////////////////////////////////
2927/// check if observable exists in the RooArgSet (-?-)
2928
2930{
2931 return this->getFunc()->checkObservables(nset);
2932}
2933
2934////////////////////////////////////////////////////////////////////////////////
2935/// Force analytical integration for the given observable
2936
2938{
2939 return this->getFunc()->forceAnalyticalInt(arg);
2940}
2941
2942////////////////////////////////////////////////////////////////////////////////
2943/// Retrieve the mat
2944
2950
2951////////////////////////////////////////////////////////////////////////////////
2952/// Retrieve the matrix of coefficients
2953
2955{
2956 return this->getFunc()->analyticalIntegralWN(code, normSet, rangeName);
2957}
2958
2959////////////////////////////////////////////////////////////////////////////////
2960/// Retrieve the matrix of coefficients
2961
2962void RooLagrangianMorphFunc::printMetaArgs(std::ostream &os) const
2963{
2964 return this->getFunc()->printMetaArgs(os);
2965}
2966
2967////////////////////////////////////////////////////////////////////////////////
2968/// Retrieve the matrix of coefficients
2969
2974
2975////////////////////////////////////////////////////////////////////////////////
2976/// Retrieve the matrix of coefficients
2977
2982
2983////////////////////////////////////////////////////////////////////////////////
2984/// Retrieve the matrix of coefficients
2985
2987{
2988 auto cache = getCache();
2989 if (!cache)
2990 coutE(Caching) << "unable to retrieve cache!" << std::endl;
2991 return makeRootMatrix(cache->_matrix);
2992}
2993
2994////////////////////////////////////////////////////////////////////////////////
2995/// Retrieve the matrix of coefficients after inversion
2996
2998{
2999 auto cache = getCache();
3000 if (!cache)
3001 coutE(Caching) << "unable to retrieve cache!" << std::endl;
3002 return makeRootMatrix(cache->_inverse);
3003}
3004
3005////////////////////////////////////////////////////////////////////////////////
3006/// Retrieve the condition of the coefficient matrix. If the condition number
3007/// is very large, then the matrix is ill-conditioned and is almost singular.
3008/// The computation of the inverse is prone to large numerical errors
3009
3011{
3012 auto cache = getCache();
3013 if (!cache)
3014 coutE(Caching) << "unable to retrieve cache!" << std::endl;
3015 return cache->_condition;
3016}
3017
3018////////////////////////////////////////////////////////////////////////////////
3019/// Return the RooRatio form of products and denominators of morphing functions
3020
3021std::unique_ptr<RooRatio>
3023{
3024 RooArgList num;
3026 for (auto it : nr) {
3027 num.add(*it);
3028 }
3029 for (auto it : dr) {
3030 denom.add(*it);
3031 }
3032 // same for denom
3033 return make_unique<RooRatio>(name, title, num, denom);
3034}
3035
3036// Register the factory interface
3037
3038namespace {
3039
3040// Helper function for factory interface
3041std::vector<std::string> asStringV(std::string const &arg)
3042{
3043 std::vector<std::string> out;
3044
3045 for (std::string &tok : ROOT::Split(arg, ",{}", true)) {
3046 if (tok[0] == '\'') {
3047 out.emplace_back(tok.substr(1, tok.size() - 2));
3048 } else {
3049 throw std::runtime_error("Strings in factory expressions need to be in single quotes!");
3050 }
3051 }
3052
3054}
3055
3056class LMIFace : public RooFactoryWSTool::IFace {
3057public:
3058 std::string
3059 create(RooFactoryWSTool &, const char *typeName, const char *instName, std::vector<std::string> args) override;
3060};
3061
3062std::string LMIFace::create(RooFactoryWSTool &ft, const char * /*typeName*/, const char *instanceName,
3063 std::vector<std::string> args)
3064{
3065 // Perform syntax check. Warn about any meta parameters other than the ones needed
3066 const std::array<std::string, 4> funcArgs{{"fileName", "observableName", "couplings", "folders"}};
3067 std::map<string, string> mappedInputs;
3068
3069 for (unsigned int i = 1; i < args.size(); i++) {
3070 if (args[i].find("$fileName(") != 0 && args[i].find("$observableName(") != 0 &&
3071 args[i].find("$couplings(") != 0 && args[i].find("$folders(") != 0 && args[i].find("$NewPhysics(") != 0) {
3072 throw std::string(Form("%s::create() ERROR: unknown token %s encountered", instanceName, args[i].c_str()));
3073 }
3074 }
3075
3076 for (unsigned int i = 0; i < args.size(); i++) {
3077 if (args[i].find("$NewPhysics(") == 0) {
3078 vector<string> subargs = ft.splitFunctionArgs(args[i].c_str());
3079 for (const auto &subarg : subargs) {
3080 std::vector<std::string> parts = ROOT::Split(subarg, "=");
3081 if (parts.size() == 2) {
3082 ft.ws().arg(parts[0])->setAttribute("NewPhysics", atoi(parts[1].c_str()));
3083 } else {
3084 throw std::string(Form("%s::create() ERROR: unknown token %s encountered, check input provided for %s",
3085 instanceName, subarg.c_str(), args[i].c_str()));
3086 }
3087 }
3088 } else {
3089 std::vector<string> subargs = ft.splitFunctionArgs(args[i].c_str());
3090 if (subargs.size() == 1) {
3091 string expr = ft.processExpression(subargs[0].c_str());
3092 for (auto const &param : funcArgs) {
3093 if (args[i].find(param) != string::npos)
3094 mappedInputs[param] = subargs[0];
3095 }
3096 } else {
3097 throw std::string(
3098 Form("Incorrect number of arguments in %s, have %d, expect 1", args[i].c_str(), (Int_t)subargs.size()));
3099 }
3100 }
3101 }
3102
3104 config.fileName = asStringV(mappedInputs["fileName"])[0];
3105 config.observableName = asStringV(mappedInputs["observableName"])[0];
3106 config.folderNames = asStringV(mappedInputs["folders"]);
3107 config.couplings.add(ft.asLIST(mappedInputs["couplings"].c_str()));
3108
3110
3111 return instanceName;
3112}
3113
3114static Int_t init();
3115
3116int dummy = init();
3117
3118Int_t init()
3119{
3120 RooFactoryWSTool::IFace *iface = new LMIFace;
3121 RooFactoryWSTool::registerSpecial("lagrangianmorph", iface);
3122 (void)dummy;
3123 return 0;
3124}
3125
3126} // namespace
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define a(i)
Definition RSha256.hxx:99
#define e(i)
Definition RSha256.hxx:103
RooCollectionProxy< RooArgList > RooListProxy
Definition RooAbsArg.h:53
size_t size< TMatrixD >(const TMatrixD &mat)
void writeMatrixToStreamT(const MatrixT &matrix, std::ostream &stream)
write a matrix to a stream
TMatrixD Matrix
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
static constexpr double morphUnityDeviation
Matrix makeSuperMatrix(const TMatrixD &in)
convert a TMatrixD into a Matrix
static constexpr double morphLargestWeight
void writeMatrixToFileT(const MatrixT &matrix, const char *fname)
write a matrix to a text file
double invertMatrix(const Matrix &matrix, Matrix &inverse)
#define NaN
TMatrixD makeRootMatrix(const Matrix &in)
convert a matrix into a TMatrixD
Matrix diagMatrix(size_t n)
create a new diagonal matrix of size n
void printMatrix(const TMatrixD &mat)
write a matrix
#define oocxcoutW(o, a)
#define coutW(a)
#define oocxcoutP(o, a)
#define coutE(a)
#define cxcoutP(a)
#define TRACE_DESTROY
Definition RooTrace.h:24
#define TRACE_CREATE
Definition RooTrace.h:23
int Int_t
Definition RtypesCore.h:45
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define gDirectory
Definition TDirectory.h:384
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void input
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char cname
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
char name[80]
Definition TGX11.cxx:110
TMatrixT< Double_t > TMatrixD
Definition TMatrixDfwd.h:23
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2489
std::string & operator+=(std::string &left, const TString &right)
Definition TString.h:486
TTime operator*(const TTime &t1, const TTime &t2)
Definition TTime.h:85
const_iterator begin() const
const_iterator end() const
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:77
void Print(Option_t *options=nullptr) const override
Print the object to the defaultPrintStream().
Definition RooAbsArg.h:263
bool isConstant() const
Check if the "Constant" attribute is set.
Definition RooAbsArg.h:304
bool addOwnedComponents(const RooAbsCollection &comps)
Take ownership of the contents of 'comps'.
Abstract base class for objects to be stored in RooAbsCache cache manager objects.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Storage_t::size_type size() const
virtual bool addOwned(RooAbsArg &var, bool silent=false)
Add an argument and transfer the ownership to the collection.
RooAbsArg * find(const char *name) const
Find object with given name in list.
Abstract base class for objects that represent a real value that may appear on the left hand side of ...
Int_t numBins(const char *rangeName=nullptr) const override
virtual Int_t getBins(const char *name=nullptr) const
Get number of bins of currently defined range.
void setConstant(bool value=true)
virtual double getMax(const char *name=nullptr) const
Get maximum of currently defined range.
void setBin(Int_t ibin, const char *rangeName=nullptr) override
Set value to center of bin 'ibin' of binning 'rangeName' (or of default binning if no range is specif...
virtual double getMin(const char *name=nullptr) const
Get minimum of currently defined range.
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:59
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:103
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
RooAbsArg * at(Int_t idx) const
Return object at given index, or nullptr if index is out of range.
Definition RooArgList.h:110
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
Implements a RooAbsBinning in terms of an array of boundary values, posing no constraints on the choi...
Definition RooBinning.h:27
Int_t setObj(const RooArgSet *nset, T *obj, const TNamed *isetRangeName=nullptr)
Setter function without integration set.
T * getObj(const RooArgSet *nset, Int_t *sterileIndex=nullptr, const TNamed *isetRangeName=nullptr)
Getter function without integration set.
bool addOwned(RooAbsArg &var, bool silent=false) override
Overloaded RooCollection_t::addOwned() method insert object into owning set and registers object as s...
bool add(const RooAbsArg &var, bool valueServer, bool shapeServer, bool silent)
Overloaded RooCollection_t::add() method insert object into set and registers object as server to own...
Container class to hold N-dimensional binned data.
Definition RooDataHist.h:40
double weightSquared(std::size_t i) const
Return squared weight sum of i-th bin.
const RooArgSet * get() const override
Get bin centre of current bin.
Definition RooDataHist.h:82
Implementation detail of the RooWorkspace.
static void registerSpecial(const char *typeName, RooFactoryWSTool::IFace *iface)
Register foreign special objects in factory.
A real-valued function sampled from a multidimensional histogram.
Definition RooHistFunc.h:31
static TClass * Class()
static RooLagrangianMorphFunc::CacheElem * createCache(const RooLagrangianMorphFunc *func)
create all the temporary objects required by the class
void buildMatrix(const RooLagrangianMorphFunc::ParamMap &inputParameters, const RooLagrangianMorphFunc::FlagMap &inputFlags, const List &flags)
build and invert the morphing matrix
static RooLagrangianMorphFunc::CacheElem * createCache(const RooLagrangianMorphFunc *func, const Matrix &inverse)
create all the temporary objects required by the class function variant with precomputed inverse matr...
std::unique_ptr< RooRealSumFunc > _sumFunc
RooArgList containedArgs(Action) override
retrieve the list of contained args
void operModeHook(RooAbsArg::OperMode) override
Interface for changes of operation mode.
void createComponents(const RooLagrangianMorphFunc::ParamMap &inputParameters, const RooLagrangianMorphFunc::FlagMap &inputFlags, const char *funcname, const std::vector< std::vector< RooListProxy * > > &diagramProxyList, const std::vector< std::vector< std::string > > &nonInterfering, const RooArgList &flags)
create the basic objects required for the morphing
void buildMorphingFunction(const char *name, const RooLagrangianMorphFunc::ParamMap &inputParameters, const std::map< std::string, int > &storage, const RooArgList &physics, bool allowNegativeYields, RooRealVar *observable, RooRealVar *binWidth)
build the final morphing function
Class RooLagrangianMorphing is a implementation of the method of Effective Lagrangian Morphing,...
bool isParameterConstant(const char *paramname) const
return true if the parameter with the given name is set constant, false otherwise
bool isBinnedDistribution(const RooArgSet &obs) const override
check if this PDF is a binned distribution in the given observable
int nPolynomials() const
return the number of samples in this morphing function
void setParameter(const char *name, double value)
set one parameter to a specific value
RooArgSet createWeights(const ParamMap &inputs, const std::vector< RooArgList * > &vertices, RooArgList &couplings, const FlagMap &inputFlags, const RooArgList &flags, const std::vector< std::vector< std::string > > &nonInterfering)
create only the weight formulas. static function for external usage.
ParamSet getMorphParameters() const
retrieve the parameter set
double evaluate() const override
call getVal on the internal function
void disableInterference(const std::vector< const char * > &nonInterfering)
disable interference between terms
RooProduct * getSumElement(const char *name) const
return the RooProduct that is the element of the RooRealSumPdfi corresponding to the given sample nam...
RooRealVar * getBinWidth() const
retrieve the histogram observable
void writeMatrixToFile(const TMatrixD &matrix, const char *fname)
write a matrix to a file
RooRealVar * getParameter(const char *name) const
retrieve the RooRealVar object incorporating the parameter with the given name
bool useCoefficients(const TMatrixD &inverse)
setup the morphing function with a predefined inverse matrix call this function before any other afte...
const RooArgSet * getParameterSet() const
get the set of parameters
TMatrixD readMatrixFromStream(std::istream &stream)
read a matrix from a stream
std::vector< std::vector< std::string > > _nonInterfering
std::vector< std::string > getSamples() const
return the vector of sample names, used to build the morph func
int countSamples(std::vector< RooArgList * > &vertices)
calculate the number of samples needed to morph a certain physics process
void setCacheAndTrackHints(RooArgSet &) override
Retrieve the matrix of coefficients.
ParamSet getCouplings() const
retrieve a set of couplings (-?-)
void printSampleWeights() const
print the current sample weights
std::map< const std::string, double > ParamSet
void writeMatrixToStream(const TMatrixD &matrix, std::ostream &stream)
write a matrix to a stream
std::map< const std::string, ParamSet > ParamMap
bool updateCoefficients()
Retrieve the new physics objects and update the weights in the morphing function.
double _scale
The cache manager.
RooRealVar * getObservable() const
retrieve the histogram observable
int countContributingFormulas() const
count the number of formulas that correspond to the current parameter set
std::list< double > * plotSamplingHint(RooAbsRealLValue &, double, double) const override
retrieve the sample Hint
RooRealVar * getFlag(const char *name) const
retrieve the RooRealVar object incorporating the flag with the given name
void randomizeParameters(double z)
randomize the parameters a bit useful to test and debug fitting
bool isCouplingUsed(const char *couplname)
check if there is any morphing power provided for the given coupling morphing power is provided as so...
void readParameters(TDirectory *f)
read the parameters from the input file
double getScale()
get energy scale of the EFT expansion
double getCondition() const
Retrieve the condition of the coefficient matrix.
TMatrixD getMatrix() const
Retrieve the matrix of coefficients.
void printWeights() const
print the current sample weights
void printCouplings() const
print a set of couplings
TMatrixD readMatrixFromFile(const char *fname)
read a matrix from a text file
~RooLagrangianMorphFunc() override
default destructor
void printParameters() const
print the parameters and their current values
void printPhysics() const
print the current physics values
static std::unique_ptr< RooRatio > makeRatio(const char *name, const char *title, RooArgList &nr, RooArgList &dr)
Return the RooRatio form of products and denominators of morphing functions.
void setFlag(const char *name, double value)
set one flag to a specific value
TH1 * createTH1(const std::string &name)
retrieve a histogram output of the current morphing settings
double expectedUncertainty() const
return the expected uncertainty for the current parameter set
int nParameters() const
return the number of parameters in this morphing function
bool hasParameter(const char *paramname) const
check if a parameter of the given name is contained in the list of known parameters
bool checkObservables(const RooArgSet *nset) const override
check if observable exists in the RooArgSet (-?-)
bool hasCache() const
return true if a cache object is present, false otherwise
void printFlags() const
print the flags and their current values
void setScale(double val)
set energy scale of the EFT expansion
TMatrixD getInvertedMatrix() const
Retrieve the matrix of coefficients after inversion.
double analyticalIntegralWN(Int_t code, const RooArgSet *normSet, const char *rangeName=nullptr) const override
Retrieve the matrix of coefficients.
RooAbsArg::CacheMode canNodeBeCached() const override
Retrieve the matrix of coefficients.
void updateSampleWeights()
update sample weight (-?-)
void setParameters(const char *foldername)
set the morphing parameters to those supplied in the sample with the given name
bool isParameterUsed(const char *paramname) const
check if there is any morphing power provided for the given parameter morphing power is provided as s...
RooAbsPdf::ExtendMode extendMode() const
return extended mored capabilities
std::map< const std::string, FlagSet > FlagMap
bool forceAnalyticalInt(const RooAbsArg &arg) const override
Force analytical integration for the given observable.
void setParameterConstant(const char *paramname, bool constant) const
call setConstant with the boolean argument provided on the parameter with the given name
void disableInterferences(const std::vector< std::vector< const char * > > &nonInterfering)
disable interference between terms
void printSamples() const
print all the known samples to the console
double getParameterValue(const char *name) const
set one parameter to a specific value
void setup(bool ownParams=true)
setup this instance with the given set of operators and vertices if own=true, the class will own the ...
void printMetaArgs(std::ostream &os) const override
Retrieve the matrix of coefficients.
std::unique_ptr< RooWrapperPdf > createPdf() const
(currently similar to cloning the Pdf
RooAbsReal * getSampleWeight(const char *name)
retrieve the weight (prefactor) of a sample with the given name
std::map< std::string, std::string > createWeightStrings(const ParamMap &inputs, const std::vector< std::vector< std::string > > &vertices)
create only the weight formulas. static function for external usage.
Int_t getAnalyticalIntegralWN(RooArgSet &allVars, RooArgSet &numVars, const RooArgSet *normSet, const char *rangeName=nullptr) const override
Retrieve the mat.
std::vector< std::vector< RooListProxy * > > _diagrams
double expectedEvents() const
return the number of expected events for the current parameter set
std::map< std::string, int > _sampleMap
RooLagrangianMorphFunc::CacheElem * getCache() const
retrieve the cache object
RooRealVar * setupObservable(const char *obsname, TClass *mode, TObject *inputExample)
setup observable, recycle existing observable if defined
const RooArgList * getCouplingSet() const
get the set of couplings
RooRealSumFunc * getFunc() const
get the func
std::list< double > * binBoundaries(RooAbsRealLValue &, double, double) const override
retrieve the list of bin boundaries
void printEvaluation() const
print the contributing samples and their respective weights
bool writeCoefficients(const char *filename)
write the inverse matrix to a file
void collectInputs(TDirectory *f)
retrieve the physics inputs
void init()
initialise inputs required for the morphing function
RooLinearCombination is a class that helps perform linear combination of floating point numbers and p...
A histogram function that assigns scale parameters to every bin.
static TClass * Class()
Represents the product of a given set of RooAbsReal objects.
Definition RooProduct.h:29
RooArgList components()
Definition RooProduct.h:48
std::list< double > * binBoundaries(RooAbsRealLValue &, double, double) const override
Retrieve bin boundaries if this distribution is binned in obs.
void printMetaArgs(std::ostream &os) const override
Customized printing of arguments of a RooRealSumFunc to more intuitively reflect the contents of the ...
Int_t getAnalyticalIntegralWN(RooArgSet &allVars, RooArgSet &numVars, const RooArgSet *normSet, const char *rangeName=nullptr) const override
Variant of getAnalyticalIntegral that is also passed the normalization set that should be applied to ...
CacheMode canNodeBeCached() const override
double analyticalIntegralWN(Int_t code, const RooArgSet *normSet, const char *rangeName=nullptr) const override
Implements the actual analytical integral(s) advertised by getAnalyticalIntegral.
bool isBinnedDistribution(const RooArgSet &obs) const override
Tests if the distribution is binned. Unless overridden by derived classes, this always returns false.
bool checkObservables(const RooArgSet *nset) const override
Overloadable function in which derived classes can implement consistency checks of the variables.
void setCacheAndTrackHints(RooArgSet &) override
std::list< double > * plotSamplingHint(RooAbsRealLValue &, double, double) const override
Interface for returning an optional hint for initial sampling points when constructing a curve projec...
bool forceAnalyticalInt(const RooAbsArg &arg) const override
Variable that can be changed from the outside.
Definition RooRealVar.h:37
void setVal(double value) override
Set value of variable to 'value'.
void setError(double value)
Definition RooRealVar.h:60
void setMin(const char *name, double value)
Set minimum of name range to given value.
const RooAbsBinning & getBinning(const char *name=nullptr, bool verbose=true, bool createOnTheFly=false) const override
Return binning definition with name.
void setBinning(const RooAbsBinning &binning, const char *name=nullptr)
Add given binning under name 'name' with this variable.
void setBins(Int_t nBins, const char *name=nullptr)
Create a uniform binning under name 'name' for this variable.
void setMax(const char *name, double value)
Set maximum of name range to given value.
Class to manage histogram axis.
Definition TAxis.h:32
Double_t GetXmax() const
Definition TAxis.h:142
Double_t GetXmin() const
Definition TAxis.h:141
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:3069
LU Decomposition class.
Definition TDecompLU.h:24
Describe directory structure in memory.
Definition TDirectory.h:45
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
Definition TFile.h:131
virtual Bool_t IsOpen() const
Returns kTRUE in case file is open and kFALSE if file is not open.
Definition TFile.cxx:1474
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition TFile.cxx:4130
void Close(Option_t *option="") override
Close a file.
Definition TFile.cxx:955
<div class="legacybox"><h2>Legacy Code</h2> TFolder is a legacy interface: there will be no bug fixes...
Definition TFolder.h:30
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:59
static TClass * Class()
TAxis * GetXaxis()
Definition TH1.h:340
virtual Int_t GetNbinsX() const
Definition TH1.h:313
virtual void SetBinError(Int_t bin, Double_t error)
Set the bin Error Note that this resets the bin eror option to be of Normal Type and for the non-empt...
Definition TH1.cxx:9208
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition TH1.cxx:7943
virtual void SetBinContent(Int_t bin, Double_t content)
Set bin content see convention for numbering bins in TH1::GetBin In case the bin number is greater th...
Definition TH1.cxx:9224
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition TH1.cxx:9154
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5059
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width for 1D histogram.
Definition TH1.cxx:9165
virtual void Scale(Double_t c1=1, Option_t *option="")
Multiply this histogram by a constant c1.
Definition TH1.cxx:6602
Int_t GetNrows() const
TMatrixTBase< Element > & ResizeTo(Int_t nrows, Int_t ncols, Int_t=-1) override
Set size of the matrix to nrows x ncols New dynamic elements are created, the overlapping part of the...
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
Mother of all ROOT objects.
Definition TObject.h:41
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:226
Class used by TMap to store (key,value) pairs.
Definition TMap.h:102
TObject * Value() const
Definition TMap.h:121
TObject * Key() const
Definition TMap.h:120
Random number generator class based on M.
Definition TRandom3.h:27
Basic string class.
Definition TString.h:139
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2378
TLine * line
RooCmdArg Silence(bool flag=true)
const Int_t n
Definition legend1.C:16
#define T2
Definition md5.inl:147
#define T1
Definition md5.inl:146
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
std::vector< std::string > Split(std::string_view str, std::string_view delims, bool skipEmpty=false)
Splits a string at each character in delims.
std::vector< std::string > folderNames
std::vector< std::vector< const char * > > nonInterfering
TMarker m
Definition textangle.C:8