Logo ROOT  
Reference Guide
 
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 namespace std;
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 cerr << "unable to read file '" << fname << "'!" << std::endl;
148 }
149 writeMatrixToStreamT(matrix, of);
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
243inline RooFit::SuperFloat invertMatrix(const Matrix &matrix, Matrix &inverse)
244{
245 boost::numeric::ublas::permutation_matrix<size_t> pm(size(matrix));
246 RooFit::SuperFloat mnorm = norm_inf(matrix);
247 Matrix lu(matrix);
248 try {
249 int res = lu_factorize(lu, pm);
250 if (res != 0) {
251 std::stringstream ss;
252 ::writeMatrixToStreamT(matrix, ss);
253 cxcoutP(Eval) << ss.str << std::endl;
254 }
255 // back-substitute to get the inverse
256 lu_substitute(lu, pm, inverse);
257 } catch (boost::numeric::ublas::internal_logic &error) {
258 // coutE(Eval) << "boost::numberic::ublas error: matrix is not invertible!"
259 // << std::endl;
260 }
261 RooFit::SuperFloat inorm = norm_inf(inverse);
262 RooFit::SuperFloat condition = mnorm * inorm;
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{
310 TDecompLU lu(matrix);
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 return condition;
324}
325#endif
326
327/////////////////////////////////////////////////////////////////////////////////
328// LOCAL FUNCTIONS AND DEFINITIONS
329// //////////////////////////////////////////////
330/////////////////////////////////////////////////////////////////////////////////
331/// anonymous namespace to prohibit use of these functions outside the class
332/// itself
333namespace {
334///////////////////////////////////////////////////////////////////////////////
335// HELPERS ////////////////////////////////////////////////////////////////////
336///////////////////////////////////////////////////////////////////////////////
337
338typedef std::vector<std::vector<bool>> FeynmanDiagram;
339typedef std::vector<std::vector<int>> MorphFuncPattern;
340typedef std::map<int, std::unique_ptr<RooAbsReal>> FormulaList;
341
342///////////////////////////////////////////////////////////////////////////////
343/// (-?-)
344
345inline TString makeValidName(const char *input)
346{
347 TString retval(input);
348 retval.ReplaceAll("/", "_");
349 retval.ReplaceAll("^", "");
350 retval.ReplaceAll("*", "X");
351 retval.ReplaceAll("[", "");
352 retval.ReplaceAll("]", "");
353 return retval;
354}
355
356//////////////////////////////////////////////////////////////////////////////
357/// concatenate the names of objects in a collection to a single string
358
359template <class List>
360std::string concatNames(const List &c, const char *sep)
361{
362 std::stringstream ss;
363 bool first = true;
364 for (auto itr : c) {
365 if (!first)
366 ss << sep;
367 ss << itr->GetName();
368 first = false;
369 }
370 return ss.str();
371}
372
373///////////////////////////////////////////////////////////////////////////////
374/// this is a workaround for the missing implicit conversion from
375/// SuperFloat<>double
376
377template <class A, class B>
378inline void assignElement(A &a, const B &b)
379{
380 a = static_cast<A>(b);
381}
382///////////////////////////////////////////////////////////////////////////////
383// read a matrix from a stream
384
385template <class MatrixT>
386inline MatrixT readMatrixFromStreamT(std::istream &stream)
387{
388 std::vector<std::vector<RooFit::SuperFloat>> matrix;
389 std::vector<RooFit::SuperFloat> line;
390 while (!stream.eof()) {
391 if (stream.peek() == '\n') {
392 stream.get();
393 stream.peek();
394 continue;
395 }
397 stream >> val;
398 line.push_back(val);
399 while (stream.peek() == ' ' || stream.peek() == '\t') {
400 stream.get();
401 }
402 if (stream.peek() == '\n') {
403 matrix.push_back(line);
404 line.clear();
405 }
406 }
407 MatrixT retval(matrix.size(), matrix.size());
408 for (size_t i = 0; i < matrix.size(); ++i) {
409 if (matrix[i].size() != matrix.size()) {
410 std::cerr << "matrix read from stream doesn't seem to be square!" << std::endl;
411 }
412 for (size_t j = 0; j < matrix[i].size(); ++j) {
413 assignElement(retval(i, j), matrix[i][j]);
414 }
415 }
416 return retval;
417}
418
419///////////////////////////////////////////////////////////////////////////////
420/// read a matrix from a text file
421
422template <class MatrixT>
423inline MatrixT readMatrixFromFileT(const char *fname)
424{
425 std::ifstream in(fname);
426 if (!in.good()) {
427 std::cerr << "unable to read file '" << fname << "'!" << std::endl;
428 }
429 MatrixT mat = readMatrixFromStreamT<MatrixT>(in);
430 in.close();
431 return mat;
432}
433
434///////////////////////////////////////////////////////////////////////////////
435/// convert a TH1* param hist into the corresponding ParamSet object
436
437template <class T>
438void readValues(std::map<const std::string, T> &myMap, TH1 *h_pc)
439{
440 if (h_pc) {
441 // loop over all bins of the param_card histogram
442 for (int ibx = 1; ibx <= h_pc->GetNbinsX(); ++ibx) {
443 // read the value of one parameter
444 const std::string s_coup(h_pc->GetXaxis()->GetBinLabel(ibx));
445 double coup_val = h_pc->GetBinContent(ibx);
446 // add it to the map
447 if (!s_coup.empty()) {
448 myMap[s_coup] = T(coup_val);
449 }
450 }
451 }
452}
453
454///////////////////////////////////////////////////////////////////////////////
455/// Set up folder ownership over its children, and treat likewise any subfolders.
456/// @param theFolder: folder to update. Assumed to be a valid pointer
457void setOwnerRecursive(TFolder *theFolder)
458{
459 theFolder->SetOwner();
460 // And also need to set up ownership for nested folders
461 auto subdirs = theFolder->GetListOfFolders();
462 for (auto *subdir : *subdirs) {
463 auto thisfolder = dynamic_cast<TFolder *>(subdir);
464 if (thisfolder) {
465 // no explicit deletion here, will be handled by parent
466 setOwnerRecursive(thisfolder);
467 }
468 }
469}
470
471///////////////////////////////////////////////////////////////////////////////
472/// Load a TFolder from a file while ensuring it owns its content.
473/// This avoids memory leaks. Note that when fetching objects
474/// from this folder, you need to clone them to prevent deletion.
475/// Also recursively updates nested subfolders accordingly
476/// @param inFile: Input file to read - assumed to be a valid pointer
477/// @param folderName: Name of the folder to read from the file
478/// @return a unique_ptr to the folder. Nullptr if not found.
479std::unique_ptr<TFolder> readOwningFolderFromFile(TDirectory *inFile, const std::string &folderName)
480{
481 std::unique_ptr<TFolder> theFolder(inFile->Get<TFolder>(folderName.c_str()));
482 if (!theFolder) {
483 std::cerr << "Error: unable to access data from folder '" << folderName << "' from file '" << inFile->GetName()
484 << "'!" << std::endl;
485 return nullptr;
486 }
487 setOwnerRecursive(theFolder.get());
488 return theFolder;
489}
490
491///////////////////////////////////////////////////////////////////////////////
492/// Helper to load a single object from a file-resident TFolder, while
493/// avoiding memory leaks.
494/// @tparam AObjType Type of object to load.
495/// @param inFile input file to load from. Expected to be a valid pointer
496/// @param folderName Name of the TFolder to load from the file
497/// @param objName Name of the object to load
498/// @param notFoundError If set, print a detailed error if we didn't find something
499/// @return Returns a pointer to a clone of the loaded object. Ownership assigned to the caller.
500template <class AObjType>
501std::unique_ptr<AObjType> loadFromFileResidentFolder(TDirectory *inFile, const std::string &folderName,
502 const std::string &objName, bool notFoundError = true)
503{
504 auto folder = readOwningFolderFromFile(inFile, folderName);
505 if (!folder) {
506 return nullptr;
507 }
508 AObjType *loadedObject = dynamic_cast<AObjType *>(folder->FindObject(objName.c_str()));
509 if (!loadedObject) {
510 if (notFoundError) {
511 std::stringstream errstr;
512 errstr << "Error: unable to retrieve object '" << objName << "' from folder '" << folderName
513 << "'. contents are:";
514 TIter next(folder->GetListOfFolders()->begin());
515 TFolder *f;
516 while ((f = (TFolder *)next())) {
517 errstr << " " << f->GetName();
518 }
519 std::cerr << errstr.str() << std::endl;
520 }
521 return nullptr;
522 }
523 // replace the loaded object by a clone, as the loaded folder will delete the original
524 // can use a static_cast - confirmed validity by initial cast above.
525 return std::unique_ptr<AObjType>{static_cast<AObjType *>(loadedObject->Clone())};
526}
527
528///////////////////////////////////////////////////////////////////////////////
529/// retrieve a ParamSet from a certain subfolder 'name' of the file
530
531template <class T>
532void readValues(std::map<const std::string, T> &myMap, TDirectory *file, const std::string &name,
533 const std::string &key = "param_card", bool notFoundError = true)
534{
535 auto h_pc = loadFromFileResidentFolder<TH1F>(file, name, key, notFoundError);
536 readValues(myMap, h_pc.get());
537}
538
539///////////////////////////////////////////////////////////////////////////////
540/// retrieve the param_hists file and return a map of the parameter values
541/// by providing a list of names, only the param_hists of those subfolders are
542/// read leaving the list empty is interpreted as meaning 'read everything'
543
544template <class T>
545void readValues(std::map<const std::string, std::map<const std::string, T>> &inputParameters, TDirectory *f,
546 const std::vector<std::string> &names, const std::string &key = "param_card", bool notFoundError = true)
547{
548 inputParameters.clear();
549 // if the list of names is empty, we assume that this means 'all'
550 // loop over all folders in the file
551 for (size_t i = 0; i < names.size(); i++) {
552 const std::string name(names[i]);
553 // actually read an individual param_hist
554 readValues(inputParameters[name], f, name, key, notFoundError);
555 }
556
557 // now the map is filled with all parameter values found for all samples
558}
559
560///////////////////////////////////////////////////////////////////////////////
561/// open the file and return a file pointer
562
563inline TDirectory *openFile(const std::string &filename)
564{
565 if (filename.empty()) {
566 return gDirectory;
567 } else {
568 TFile *file = TFile::Open(filename.c_str(), "READ");
569 if (!file || !file->IsOpen()) {
570 if (file)
571 delete file;
572 std::cerr << "could not open file '" << filename << "'!" << std::endl;
573 }
574 return file;
575 }
576}
577
578///////////////////////////////////////////////////////////////////////////////
579/// open the file and return a file pointer
580
581inline void closeFile(TDirectory *d)
582{
583 TFile *f = dynamic_cast<TFile *>(d);
584 if (f) {
585 f->Close();
586 delete f;
587 d = nullptr;
588 }
589}
590
591///////////////////////////////////////////////////////////////////////////////
592/// extract the operators from a single coupling
593template <class T2>
594inline void extractServers(const RooAbsArg &coupling, T2 &operators)
595{
596 int nservers = 0;
597 for (const auto server : coupling.servers()) {
598 extractServers(*server, operators);
599 nservers++;
600 }
601 if (nservers == 0) {
602 operators.add(coupling);
603 }
604}
605
606///////////////////////////////////////////////////////////////////////////////
607/// extract the operators from a list of couplings
608
609template <class T1, class T2, typename std::enable_if<!is_specialization<T1, std::vector>::value, T1>::type * = nullptr>
610inline void extractOperators(const T1 &couplings, T2 &operators)
611{
612 // coutD(InputArguments) << "extracting operators from
613 // "<<couplings.getSize()<<" couplings" << std::endl;
614 for (auto itr : couplings) {
615 extractServers(*itr, operators);
616 }
617}
618
619///////////////////////////////////////////////////////////////////////////////
620/// extract the operators from a list of vertices
621
622template <class T1, class T2, typename std::enable_if<is_specialization<T1, std::vector>::value, T1>::type * = nullptr>
623inline void extractOperators(const T1 &vec, T2 &operators)
624{
625 for (const auto &v : vec) {
626 extractOperators(v, operators);
627 }
628}
629
630///////////////////////////////////////////////////////////////////////////////
631/// extract the couplings from a given set and copy them to a new one
632
633template <class T1, class T2>
634inline void extractCouplings(const T1 &inCouplings, T2 &outCouplings)
635{
636 for (auto itr : inCouplings) {
637 if (!outCouplings.find(itr->GetName())) {
638 // coutD(InputArguments) << "adding parameter "<< obj->GetName() <<
639 // std::endl;
640 outCouplings.add(*itr);
641 }
642 }
643}
644
645////////////////////////////////////////////////////////////////////////////////
646/// set parameter values first set all values to defaultVal (if value not
647/// present in param_card then it should be 0)
648
649inline bool setParam(RooRealVar *p, double val, bool force)
650{
651 bool ok = true;
652 if (val > p->getMax()) {
653 if (force) {
654 p->setMax(val);
655 } else {
656 std::cerr << ": parameter " << p->GetName() << " out of bounds: " << val << " > " << p->getMax() << std::endl;
657 ok = false;
658 }
659 } else if (val < p->getMin()) {
660 if (force) {
661 p->setMin(val);
662 } else {
663 std::cerr << ": parameter " << p->GetName() << " out of bounds: " << val << " < " << p->getMin() << std::endl;
664 ok = false;
665 }
666 }
667 if (ok)
668 p->setVal(val);
669 return ok;
670}
671
672////////////////////////////////////////////////////////////////////////////////
673/// set parameter values first set all values to defaultVal (if value not
674/// present in param_card then it should be 0)
675
676template <class T1, class T2>
677inline bool setParams(const T2 &args, T1 val)
678{
679 for (auto itr : args) {
680 RooRealVar *param = dynamic_cast<RooRealVar *>(itr);
681 if (!param)
682 continue;
683 setParam(param, val, true);
684 }
685 return true;
686}
687
688////////////////////////////////////////////////////////////////////////////////
689/// set parameter values first set all values to defaultVal (if value not
690/// present in param_card then it should be 0)
691
692template <class T1, class T2>
693inline bool
694setParams(const std::map<const std::string, T1> &point, const T2 &args, bool force = false, T1 defaultVal = 0)
695{
696 bool ok = true;
697 for (auto itr : args) {
698 RooRealVar *param = dynamic_cast<RooRealVar *>(itr);
699 if (!param || param->isConstant())
700 continue;
701 ok = setParam(param, defaultVal, force) && ok;
702 }
703 // set all parameters to the values in the param_card histogram
704 for (auto paramit : point) {
705 // loop over all the parameters
706 const std::string param(paramit.first);
707 // retrieve them from the map
708 RooRealVar *p = dynamic_cast<RooRealVar *>(args.find(param.c_str()));
709 if (!p)
710 continue;
711 // set them to their nominal value
712 ok = setParam(p, paramit.second, force) && ok;
713 }
714 return ok;
715}
716
717////////////////////////////////////////////////////////////////////////////////
718/// set parameter values first set all values to defaultVal (if value not
719/// present in param_card then it should be 0)
720
721template <class T>
722inline bool setParams(TH1 *hist, const T &args, bool force = false)
723{
724 bool ok = true;
725
726 for (auto itr : args) {
727 RooRealVar *param = dynamic_cast<RooRealVar *>(itr);
728 if (!param)
729 continue;
730 ok = setParam(param, 0., force) && ok;
731 }
732
733 // set all parameters to the values in the param_card histogram
734 TAxis *ax = hist->GetXaxis();
735 for (int i = 1; i <= ax->GetNbins(); ++i) {
736 // loop over all the parameters
737 RooRealVar *p = dynamic_cast<RooRealVar *>(args.find(ax->GetBinLabel(i)));
738 if (!p)
739 continue;
740 // set them to their nominal value
741 ok = setParam(p, hist->GetBinContent(i), force) && ok;
742 }
743 return ok;
744}
745
746////////////////////////////////////////////////////////////////////////////////
747/// create a set of parameters
748
749template <class T>
750inline RooLagrangianMorphFunc::ParamSet getParams(const T &parameters)
751{
753 for (auto itr : parameters) {
754 RooRealVar *param = dynamic_cast<RooRealVar *>(itr);
755 if (!param)
756 continue;
757 retval[param->GetName()] = param->getVal();
758 }
759 return retval;
760}
761
762////////////////////////////////////////////////////////////////////////////////
763/// collect the histograms from the input file and convert them to RooFit
764/// objects
765
766void collectHistograms(const char *name, TDirectory *file, std::map<std::string, int> &list_hf, RooArgList &physics,
767 RooRealVar &var, const std::string &varname,
768 const RooLagrangianMorphFunc::ParamMap &inputParameters, bool normalize)
769{
770 bool binningOK = false;
771 for (auto sampleit : inputParameters) {
772 const std::string sample(sampleit.first);
773 auto hist = loadFromFileResidentFolder<TH1>(file, sample, varname, true);
774 if (!hist)
775 return;
776
777 if (normalize) {
778 hist.get()->Scale(1. / hist.get()->Integral());
779 }
780
781 auto it = list_hf.find(sample);
782 if (it != list_hf.end()) {
783 RooHistFunc *hf = (RooHistFunc *)(physics.at(it->second));
784 hf->setValueDirty();
785 // commenting out To-be-resolved
786 // RooDataHist* dh = &(hf->dataHist());
787 // RooLagrangianMorphFunc::setDataHistogram(hist,&var,dh);
788 // RooArgSet vars;
789 // vars.add(var);
790 // dh->importTH1(vars,*hist,1.,false);
791 } else {
792 if (!binningOK) {
793 int n = hist->GetNbinsX();
794 std::vector<double> bins;
795 for (int i = 1; i < n + 1; ++i) {
796 bins.push_back(hist->GetBinLowEdge(i));
797 }
798 bins.push_back(hist->GetBinLowEdge(n) + hist->GetBinWidth(n));
799 var.setBinning(RooBinning(n, &(bins[0])));
800 }
801
802 // generate the mean value
803 TString histname = makeValidName(Form("dh_%s_%s", sample.c_str(), name));
804 TString funcname = makeValidName(Form("phys_%s_%s", sample.c_str(), name));
805 RooArgSet vars;
806 vars.add(var);
807
808 auto dh = std::make_unique<RooDataHist>(histname, histname, vars, hist.get());
809 // add it to the list
810 auto hf = std::make_unique<RooHistFunc>(funcname, funcname, var, std::move(dh));
811 int idx = physics.getSize();
812 list_hf[sample] = idx;
813 physics.addOwned(std::move(hf));
814 }
815 // std::cout << "found histogram " << hist->GetName() << " with integral "
816 // << hist->Integral() << std::endl;
817 }
818}
819
820////////////////////////////////////////////////////////////////////////////////
821/// collect the RooAbsReal objects from the input directory
822
823void collectRooAbsReal(const char * /*name*/, TDirectory *file, std::map<std::string, int> &list_hf,
824 RooArgList &physics, const std::string &varname,
825 const RooLagrangianMorphFunc::ParamMap &inputParameters)
826{
827 for (auto sampleit : inputParameters) {
828 const std::string sample(sampleit.first);
829 auto obj = loadFromFileResidentFolder<RooAbsReal>(file, sample, varname, true);
830 if (!obj)
831 return;
832 auto it = list_hf.find(sample);
833 if (it == list_hf.end()) {
834 int idx = physics.getSize();
835 list_hf[sample] = idx;
836 physics.addOwned(std::move(obj));
837 }
838 }
839}
840
841////////////////////////////////////////////////////////////////////////////////
842/// collect the TParameter objects from the input file and convert them to
843/// RooFit objects
844
845template <class T>
846void collectCrosssections(const char *name, TDirectory *file, std::map<std::string, int> &list_xs, RooArgList &physics,
847 const std::string &varname, const RooLagrangianMorphFunc::ParamMap &inputParameters)
848{
849 for (auto sampleit : inputParameters) {
850 const std::string sample(sampleit.first);
851 auto obj = loadFromFileResidentFolder<TObject>(file, sample, varname, false);
852 TParameter<T> *xsection = nullptr;
853 TParameter<T> *error = nullptr;
854 TParameter<T> *p = dynamic_cast<TParameter<T> *>(obj.get());
855 if (p) {
856 xsection = p;
857 }
858 TPair *pair = dynamic_cast<TPair *>(obj.get());
859 if (pair) {
860 xsection = dynamic_cast<TParameter<T> *>(pair->Key());
861 error = dynamic_cast<TParameter<T> *>(pair->Value());
862 }
863 if (!xsection) {
864 std::stringstream errstr;
865 errstr << "Error: unable to retrieve cross section '" << varname << "' from folder '" << sample;
866 return;
867 }
868
869 auto it = list_xs.find(sample.c_str());
870 RooRealVar *xs;
871 if (it != list_xs.end()) {
872 xs = (RooRealVar *)(physics.at(it->second));
873 xs->setVal(xsection->GetVal());
874 } else {
875 std::string objname = Form("phys_%s_%s", name, sample.c_str());
876 auto xsOwner = std::make_unique<RooRealVar>(objname.c_str(), objname.c_str(), xsection->GetVal());
877 xs = xsOwner.get();
878 xs->setConstant(true);
879 int idx = physics.getSize();
880 list_xs[sample] = idx;
881 physics.addOwned(std::move(xsOwner));
882 assert(physics.at(idx) == xs);
883 }
884 if (error) {
885 xs->setError(error->GetVal());
886 }
887 }
888}
889
890////////////////////////////////////////////////////////////////////////////////
891/// collect the TPair<TParameter,TParameter> objects from the input file and
892/// convert them to RooFit objects
893
894void collectCrosssectionsTPair(const char *name, TDirectory *file, std::map<std::string, int> &list_xs,
895 RooArgList &physics, const std::string &varname, const std::string &basefolder,
896 const RooLagrangianMorphFunc::ParamMap &inputParameters)
897{
898 auto pair = loadFromFileResidentFolder<TPair>(file, basefolder, varname, false);
899 if (!pair)
900 return;
901 if (dynamic_cast<TParameter<double> *>(pair->Key())) {
902 collectCrosssections<double>(name, file, list_xs, physics, varname, inputParameters);
903 } else if (dynamic_cast<TParameter<float> *>(pair->Key())) {
904 collectCrosssections<float>(name, file, list_xs, physics, varname, inputParameters);
905 } else {
906 std::cerr << "cannot morph objects of class 'TPair' if parameter is not "
907 "double or float!"
908 << std::endl;
909 }
910}
911
912///////////////////////////////////////////////////////////////////////////////
913// FORMULA CALCULATION ////////////////////////////////////////////////////////
914///////////////////////////////////////////////////////////////////////////////
915///////////////////////////////////////////////////////////////////////////////
916
917////////////////////////////////////////////////////////////////////////////////
918/// recursive function to determine polynomials
919
920void collectPolynomialsHelper(const FeynmanDiagram &diagram, MorphFuncPattern &morphfunc, std::vector<int> &term,
921 int vertexid, bool first)
922{
923 if (vertexid > 0) {
924 for (size_t i = 0; i < diagram[vertexid - 1].size(); ++i) {
925 if (!diagram[vertexid - 1][i])
926 continue;
927 std::vector<int> newterm(term);
928 newterm[i]++;
929 if (first) {
930 ::collectPolynomialsHelper(diagram, morphfunc, newterm, vertexid, false);
931 } else {
932 ::collectPolynomialsHelper(diagram, morphfunc, newterm, vertexid - 1, true);
933 }
934 }
935 } else {
936 bool found = false;
937 for (size_t i = 0; i < morphfunc.size(); ++i) {
938 bool thisfound = true;
939 for (size_t j = 0; j < morphfunc[i].size(); ++j) {
940 if (morphfunc[i][j] != term[j]) {
941 thisfound = false;
942 break;
943 }
944 }
945 if (thisfound) {
946 found = true;
947 break;
948 }
949 }
950 if (!found) {
951 morphfunc.push_back(term);
952 }
953 }
954}
955
956////////////////////////////////////////////////////////////////////////////////
957/// calculate the morphing function pattern based on a vertex map
958
959void collectPolynomials(MorphFuncPattern &morphfunc, const FeynmanDiagram &diagram)
960{
961 int nvtx(diagram.size());
962 std::vector<int> term(diagram[0].size(), 0);
963
964 ::collectPolynomialsHelper(diagram, morphfunc, term, nvtx, true);
965}
966
967////////////////////////////////////////////////////////////////////////////////
968/// build a vertex map based on vertices and couplings appearing
969
970template <class List>
971inline void fillFeynmanDiagram(FeynmanDiagram &diagram, const std::vector<List *> &vertices, RooArgList &couplings)
972{
973 const int ncouplings = couplings.getSize();
974 // std::cout << "Number of couplings " << ncouplings << std::endl;
975 for (auto const &vertex : vertices) {
976 std::vector<bool> vertexCouplings(ncouplings, false);
977 int idx = -1;
978 RooAbsReal *coupling;
979 for (auto citr : couplings) {
980 coupling = dynamic_cast<RooAbsReal *>(citr);
981 idx++;
982 if (!coupling) {
983 std::cerr << "encountered invalid list of couplings in vertex!" << std::endl;
984 return;
985 }
986 if (vertex->find(coupling->GetName())) {
987 vertexCouplings[idx] = true;
988 }
989 }
990 diagram.push_back(vertexCouplings);
991 }
992}
993
994////////////////////////////////////////////////////////////////////////////////
995/// fill the matrix of coefficients
996
997template <class MatrixT, class T1, class T2>
998inline MatrixT buildMatrixT(const RooLagrangianMorphFunc::ParamMap &inputParameters, const FormulaList &formulas,
999 const T1 &args, const RooLagrangianMorphFunc::FlagMap &flagValues, const T2 &flags)
1000{
1001 const size_t dim = inputParameters.size();
1002 MatrixT matrix(dim, dim);
1003 int row = 0;
1004 for (auto sampleit : inputParameters) {
1005 const std::string sample(sampleit.first);
1006 // set all vars to value stored in input file
1007 if (!setParams<double>(sampleit.second, args, true, 0)) {
1008 std::cout << "unable to set parameters for sample " << sample << "!" << std::endl;
1009 }
1010 auto flagit = flagValues.find(sample);
1011 if (flagit != flagValues.end() && !setParams<int>(flagit->second, flags, true, 1)) {
1012 std::cout << "unable to set parameters for sample " << sample << "!" << std::endl;
1013 }
1014 // loop over all the formulas
1015 int col = 0;
1016 for (auto const &formula : formulas) {
1017 if (!formula.second) {
1018 std::cerr << "Error: invalid formula encountered!" << std::endl;
1019 }
1020 matrix(row, col) = formula.second->getVal();
1021 col++;
1022 }
1023 row++;
1024 }
1025 return matrix;
1026}
1027
1028////////////////////////////////////////////////////////////////////////////////
1029/// check if the matrix is square
1030
1031inline void checkMatrix(const RooLagrangianMorphFunc::ParamMap &inputParameters, const FormulaList &formulas)
1032{
1033 if (inputParameters.size() != formulas.size()) {
1034 std::stringstream ss;
1035 ss << "matrix is not square, consistency check failed: " << inputParameters.size() << " samples, "
1036 << formulas.size() << " expressions:" << std::endl;
1037 ss << "formulas: " << std::endl;
1038 for (auto const &formula : formulas) {
1039 ss << formula.second->GetTitle() << std::endl;
1040 }
1041 ss << "samples: " << std::endl;
1042 for (auto sample : inputParameters) {
1043 ss << sample.first << std::endl;
1044 }
1045 std::cerr << ss.str() << std::endl;
1046 }
1047}
1048
1049////////////////////////////////////////////////////////////////////////////////
1050/// check if the entries in the inverted matrix are sensible
1051
1052inline void inverseSanity(const Matrix &matrix, const Matrix &inverse, double &unityDeviation, double &largestWeight)
1053{
1054 Matrix unity(inverse * matrix);
1055
1056 unityDeviation = 0.;
1057 largestWeight = 0.;
1058 const size_t dim = size(unity);
1059 for (size_t i = 0; i < dim; ++i) {
1060 for (size_t j = 0; j < dim; ++j) {
1061 if (inverse(i, j) > largestWeight) {
1062 largestWeight = (double)inverse(i, j);
1063 }
1064 if (std::abs(unity(i, j) - static_cast<int>(i == j)) > unityDeviation) {
1065 unityDeviation = std::abs((double)unity(i, j)) - static_cast<int>(i == j);
1066 }
1067 }
1068 }
1069}
1070
1071////////////////////////////////////////////////////////////////////////////////
1072/// check for name conflicts between the input samples and an argument set
1073template <class List>
1074inline void checkNameConflict(const RooLagrangianMorphFunc::ParamMap &inputParameters, List &args)
1075{
1076 for (auto sampleit : inputParameters) {
1077 const std::string sample(sampleit.first);
1078 RooAbsArg *arg = args.find(sample.c_str());
1079 if (arg) {
1080 std::cerr << "detected name conflict: cannot use sample '" << sample
1081 << "' - a parameter with the same name of type '" << arg->ClassName() << "' is present in set '"
1082 << args.GetName() << "'!" << std::endl;
1083 }
1084 }
1085}
1086
1087////////////////////////////////////////////////////////////////////////////////
1088/// build the formulas corresponding to the given set of input files and
1089/// the physics process
1090
1091FormulaList buildFormulas(const char *mfname, const RooLagrangianMorphFunc::ParamMap &inputParameters,
1092 const RooLagrangianMorphFunc::FlagMap &inputFlags, const MorphFuncPattern &morphfunc,
1093 const RooArgList &couplings, const RooArgList &flags,
1094 const std::vector<std::vector<std::string>> &nonInterfering)
1095{
1096 // example vbf hww:
1097 // Operators kSM, kHww, kAww, kHdwR,kHzz, kAzz
1098 // std::vector<bool> vertexProd = {true, true, true, true, true, true };
1099 // std::vector<bool> vertexDecay = {true, true, true, true, false,false};
1100 // diagram.push_back(vertexProd);
1101 // diagram.push_back(vertexDecay);
1102
1103 const int ncouplings = couplings.getSize();
1104 std::vector<bool> couplingsZero(ncouplings, true);
1105 std::map<TString, bool> flagsZero;
1106
1107 RooArgList operators;
1108 extractOperators(couplings, operators);
1109 size_t nOps = operators.getSize();
1110
1111 for (auto sampleit : inputParameters) {
1112 const std::string sample(sampleit.first);
1113 if (!setParams(sampleit.second, operators, true)) {
1114 std::cerr << "unable to set parameters for sample '" << sample << "'!" << std::endl;
1115 }
1116
1117 if ((int)nOps != (operators.getSize())) {
1118 std::cerr << "internal error, number of operators inconsistent!" << std::endl;
1119 }
1120
1121 RooAbsReal *obj0;
1122 int idx = 0;
1123
1124 for (auto itr1 : couplings) {
1125 obj0 = dynamic_cast<RooAbsReal *>(itr1);
1126 if (obj0->getVal() != 0) {
1127 couplingsZero[idx] = false;
1128 }
1129 idx++;
1130 }
1131 }
1132
1133 for (auto itr2 : flags) {
1134 auto obj1 = dynamic_cast<RooAbsReal *>(itr2);
1135 int nZero = 0;
1136 int nNonZero = 0;
1137 for (auto sampleit : inputFlags) {
1138 const auto &flag = sampleit.second.find(obj1->GetName());
1139 if (flag != sampleit.second.end()) {
1140 if (flag->second == 0.)
1141 nZero++;
1142 else
1143 nNonZero++;
1144 }
1145 }
1146 if (nZero > 0 && nNonZero == 0)
1147 flagsZero[obj1->GetName()] = true;
1148 else
1149 flagsZero[obj1->GetName()] = false;
1150 }
1151
1152 FormulaList formulas;
1153 for (size_t i = 0; i < morphfunc.size(); ++i) {
1154 RooArgList ss;
1155 bool isZero = false;
1156 std::string reason;
1157 // check if this is a blacklisted interference term
1158 for (const auto &group : nonInterfering) {
1159 int nInterferingOperators = 0;
1160 for (size_t j = 0; j < morphfunc[i].size(); ++j) {
1161 if (morphfunc[i][j] % 2 == 0)
1162 continue; // even exponents are not interference terms
1163 // if the coupling is part of a "pairwise non-interfering group"
1164 if (std::find(group.begin(), group.end(), couplings.at(j)->GetName()) != group.end()) {
1165 nInterferingOperators++;
1166 }
1167 }
1168 if (nInterferingOperators > 1) {
1169 isZero = true;
1170 reason = "blacklisted interference term!";
1171 }
1172 }
1173 int nNP = 0;
1174 if (!isZero) {
1175 // prepare the term
1176 for (size_t j = 0; j < morphfunc[i].size(); ++j) {
1177 const int exponent = morphfunc[i][j];
1178 if (exponent == 0)
1179 continue;
1180 RooAbsReal *coupling = dynamic_cast<RooAbsReal *>(couplings.at(j));
1181 for (int k = 0; k < exponent; ++k) {
1182 ss.add(*coupling);
1183 if (coupling->getAttribute("NewPhysics")) {
1184 nNP++;
1185 }
1186 }
1187 std::string cname(coupling->GetName());
1188 if (coupling->getAttribute("LO") && exponent > 1) {
1189 isZero = true;
1190 reason = "coupling " + cname + " was listed as leading-order-only";
1191 }
1192 // mark the term as zero if any of the couplings are zero
1193 if (!isZero && couplingsZero[j]) {
1194 isZero = true;
1195 reason = "coupling " + cname + " is zero!";
1196 }
1197 }
1198 }
1199 // check and apply flags
1200 bool removedByFlag = false;
1201
1202 for (auto itr : flags) {
1203 auto obj = dynamic_cast<RooAbsReal *>(itr);
1204 if (!obj)
1205 continue;
1206 TString sval(obj->getStringAttribute("NewPhysics"));
1207 int val = atoi(sval);
1208 if (val == nNP) {
1209 if (flagsZero.find(obj->GetName()) != flagsZero.end() && flagsZero.at(obj->GetName())) {
1210 removedByFlag = true;
1211 reason = Form("flag %s is zero", obj->GetName());
1212 }
1213 ss.add(*obj);
1214 }
1215 }
1216
1217 // create and add the formula
1218 if (!isZero && !removedByFlag) {
1219 // build the name
1220 const auto name = std::string(mfname) + "_pol" + std::to_string(i);
1221 formulas[i] = std::make_unique<RooProduct>(name.c_str(), ::concatNames(ss, " * ").c_str(), ss);
1222 }
1223 }
1224 return formulas;
1225}
1226
1227////////////////////////////////////////////////////////////////////////////////
1228/// create the weight formulas required for the morphing
1229
1230FormulaList createFormulas(const char *name, const RooLagrangianMorphFunc::ParamMap &inputs,
1231 const RooLagrangianMorphFunc::FlagMap &inputFlags,
1232 const std::vector<std::vector<RooArgList *>> &diagrams, RooArgList &couplings,
1233 const RooArgList &flags, const std::vector<std::vector<std::string>> &nonInterfering)
1234{
1235 MorphFuncPattern morphfuncpattern;
1236
1237 for (const auto &vertices : diagrams) {
1238 FeynmanDiagram d;
1239 ::fillFeynmanDiagram(d, vertices, couplings);
1240 ::collectPolynomials(morphfuncpattern, d);
1241 }
1242 FormulaList retval = buildFormulas(name, inputs, inputFlags, morphfuncpattern, couplings, flags, nonInterfering);
1243 if (retval.empty()) {
1244 std::stringstream errorMsgStream;
1245 errorMsgStream
1246 << "no formulas are non-zero, check if any if your couplings is floating and missing from your param_cards!"
1247 << std::endl;
1248 const auto errorMsg = errorMsgStream.str();
1249 throw std::runtime_error(errorMsg);
1250 }
1251 checkMatrix(inputs, retval);
1252 return retval;
1253}
1254
1255////////////////////////////////////////////////////////////////////////////////
1256/// build the sample weights required for the input templates
1257//
1258template <class T1>
1259inline void buildSampleWeights(T1 &weights, const char *fname, const RooLagrangianMorphFunc::ParamMap &inputParameters,
1260 FormulaList &formulas, const Matrix &inverse)
1261{
1262 int sampleidx = 0;
1263
1264 for (auto sampleit : inputParameters) {
1265 const std::string sample(sampleit.first);
1266 std::stringstream title;
1267 TString name_full(makeValidName(sample.c_str()));
1268 if (fname) {
1269 name_full.Append("_");
1270 name_full.Append(fname);
1271 name_full.Prepend("w_");
1272 }
1273
1274 int formulaidx = 0;
1275 // build the formula with the correct normalization
1276 auto sampleformula = std::make_unique<RooLinearCombination>(name_full.Data());
1277 for (auto const &formulait : formulas) {
1278 const RooFit::SuperFloat val(inverse(formulaidx, sampleidx));
1279 sampleformula->add(val, formulait.second.get());
1280 formulaidx++;
1281 }
1282 weights.addOwned(std::move(sampleformula));
1283 sampleidx++;
1284 }
1285}
1286
1287inline std::map<std::string, std::string>
1288buildSampleWeightStrings(const RooLagrangianMorphFunc::ParamMap &inputParameters, const FormulaList &formulas,
1289 const Matrix &inverse)
1290{
1291 int sampleidx = 0;
1292 std::map<std::string, std::string> weights;
1293 for (auto sampleit : inputParameters) {
1294 const std::string sample(sampleit.first);
1295 std::stringstream str;
1296 int formulaidx = 0;
1297 // build the formula with the correct normalization
1298 for (auto const &formulait : formulas) {
1299 double val(inverse(formulaidx, sampleidx));
1300 if (val != 0.) {
1301 if (formulaidx > 0 && val > 0)
1302 str << " + ";
1303 str << val << "*(" << formulait.second->GetTitle() << ")";
1304 }
1305 formulaidx++;
1306 }
1307 weights[sample] = str.str();
1308 sampleidx++;
1309 }
1310 return weights;
1311}
1312} // namespace
1313
1314///////////////////////////////////////////////////////////////////////////////
1315// CacheElem magic ////////////////////////////////////////////////////////////
1316///////////////////////////////////////////////////////////////////////////////
1317
1319public:
1320 std::unique_ptr<RooRealSumFunc> _sumFunc = nullptr;
1322
1323 FormulaList _formulas;
1325
1329
1332
1333 //////////////////////////////////////////////////////////////////////////////
1334 /// retrieve the list of contained args
1335
1337 {
1338 RooArgList args(*_sumFunc);
1339 args.add(_weights);
1340 args.add(_couplings);
1341 for (auto const &it : _formulas) {
1342 args.add(*(it.second));
1343 }
1344 return args;
1345 }
1346
1347 //////////////////////////////////////////////////////////////////////////////
1348 // default destructor
1349
1350 ~CacheElem() override {}
1351
1352 //////////////////////////////////////////////////////////////////////////////
1353 /// create the basic objects required for the morphing
1354
1355 inline void createComponents(const RooLagrangianMorphFunc::ParamMap &inputParameters,
1356 const RooLagrangianMorphFunc::FlagMap &inputFlags, const char *funcname,
1357 const std::vector<std::vector<RooListProxy *>> &diagramProxyList,
1358 const std::vector<std::vector<std::string>> &nonInterfering, const RooArgList &flags)
1359 {
1360 RooArgList operators;
1361 std::vector<std::vector<RooArgList *>> diagrams;
1362 for (const auto &diagram : diagramProxyList) {
1363 diagrams.emplace_back();
1364 for (RooArgList *vertex : diagram) {
1365 extractCouplings(*vertex, _couplings);
1366 diagrams.back().emplace_back(vertex);
1367 }
1368 }
1369 extractOperators(_couplings, operators);
1370 _formulas = ::createFormulas(funcname, inputParameters, inputFlags, diagrams, _couplings, flags, nonInterfering);
1371 }
1372
1373 //////////////////////////////////////////////////////////////////////////////
1374 /// build and invert the morphing matrix
1375 template <class List>
1376 inline void buildMatrix(const RooLagrangianMorphFunc::ParamMap &inputParameters,
1377 const RooLagrangianMorphFunc::FlagMap &inputFlags, const List &flags)
1378 {
1379 RooArgList operators;
1380 extractOperators(_couplings, operators);
1381 Matrix matrix(buildMatrixT<Matrix>(inputParameters, _formulas, operators, inputFlags, flags));
1382 if (size(matrix) < 1) {
1383 std::cerr << "input matrix is empty, please provide suitable input samples!" << std::endl;
1384 }
1385 Matrix inverse(diagMatrix(size(matrix)));
1386
1387 double condition = (double)(invertMatrix(matrix, inverse));
1388 double unityDeviation, largestWeight;
1389 inverseSanity(matrix, inverse, unityDeviation, 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 *)0, 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 *)0, 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 *)0, 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 *)0, 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 *)0, Eval) << obj->GetName() << "=" << obj->getVal();
1421 first = false;
1422 }
1423 oocxcoutW((TObject *)0, 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;
1432 _condition = condition;
1433 }
1434
1435 ////////////////////////////////////////////////////////////////////////////////
1436 /// build the final morphing function
1437
1438 inline void buildMorphingFunction(const char *name, const RooLagrangianMorphFunc::ParamMap &inputParameters,
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
1451 RooArgList operators;
1452 extractOperators(_couplings, operators);
1453
1454 // retrieve the weights
1455 ::buildSampleWeights(_weights, name, inputParameters, _formulas, _inverse);
1456
1457 // build the products of element and weight for each sample
1458 size_t i = 0;
1459 RooArgList sumElements;
1460 RooArgList scaleElements;
1461 for (auto sampleit : inputParameters) {
1462 // for now, we assume all the lists are nicely ordered
1463 TString prodname(makeValidName(sampleit.first.c_str()));
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>(Form("%s_morphfunc", name), name, sumElements, scaleElements);
1500
1501 if (!observable)
1502 std::cerr << "unable to access observable" << std::endl;
1503 _sumFunc.get()->addServer(*observable);
1504 if (!binWidth)
1505 std::cerr << "unable to access bin width" << std::endl;
1506 _sumFunc.get()->addServer(*binWidth);
1507 if (operators.getSize() < 1)
1508 std::cerr << "no operators listed" << std::endl;
1509 _sumFunc.get()->addServerList(operators);
1510 if (_weights.getSize() < 1)
1511 std::cerr << "unable to access weight objects" << std::endl;
1512 _sumFunc.get()->addOwnedComponents(std::move(sumElements));
1513 _sumFunc.get()->addServerList(sumElements);
1514 _sumFunc.get()->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();
1526 RooLagrangianMorphFunc::ParamSet values = getParams(func->_operators);
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 *)0, ObjectHandling) << "observable: " << func->getObservable()->GetName() << std::endl;
1542 oocxcoutP((TObject *)0, 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 {
1558 RooLagrangianMorphFunc::ParamSet values = getParams(func->_operators);
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
1587void RooLagrangianMorphFunc::writeMatrixToFile(const TMatrixD &matrix, const char *fname)
1588{
1589 writeMatrixToFileT(matrix, fname);
1590}
1591
1592////////////////////////////////////////////////////////////////////////////////
1593/// write a matrix to a stream
1594
1595void RooLagrangianMorphFunc::writeMatrixToStream(const TMatrixD &matrix, std::ostream &stream)
1596{
1597 writeMatrixToStreamT(matrix, stream);
1598}
1599
1600////////////////////////////////////////////////////////////////////////////////
1601/// read a matrix from a text file
1602
1604{
1605 return readMatrixFromFileT<TMatrixD>(fname);
1606}
1607
1608////////////////////////////////////////////////////////////////////////////////
1609/// read a matrix from a stream
1610
1612{
1613 return readMatrixFromStreamT<TMatrixD>(stream);
1614}
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) != 0) {
1625 obs = (RooRealVar *)_observables.at(0);
1626 obsExists = true;
1627 }
1628
1629 if (mode && mode->InheritsFrom(RooHistFunc::Class())) {
1630 obs = (RooRealVar *)(dynamic_cast<RooHistFunc *>(inputExample)->getHistObsList().first());
1631 obsExists = true;
1632 _observables.add(*obs);
1633 } else if (mode && mode->InheritsFrom(RooParamHistFunc::Class())) {
1634 obs = (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 = (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 = Form("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
1726{
1727 readValues<double>(_config.paramCards, f, _config.folderNames, "param_card", true);
1728 readValues<int>(_config.flagValues, f, _config.folderNames, "flags", false);
1729}
1730
1731////////////////////////////////////////////////////////////////////////////////
1732/// retrieve the physics inputs
1733
1735{
1736 std::string obsName;
1737 if (_config.observable) {
1739 if (_config.observableName.empty()) {
1740 obsName = _observables.at(0)->GetName();
1741 } else {
1742 obsName = _config.observableName;
1743 }
1744 } else {
1745 obsName = _config.observableName;
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) {
1767 collectRooAbsReal(this->GetName(), file, _sampleMap, _physics, obsName, _config.paramCards);
1768 } else if (classname.find("TParameter<double>") != std::string::npos) {
1769 collectCrosssections<double>(this->GetName(), file, _sampleMap, _physics, obsName, _config.paramCards);
1770 } else if (classname.find("TParameter<float>") != std::string::npos) {
1771 collectCrosssections<float>(this->GetName(), file, _sampleMap, _physics, obsName, _config.paramCards);
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
1783void RooLagrangianMorphFunc::printParameters(const char *samplename) const
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.size() > 0) {
1841 RooArgList operators;
1842 std::vector<RooListProxy *> vertices;
1843 extractOperators(_config.couplings, operators);
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 {
1849 _operators.add(operators);
1850 vertices[0]->add(_config.couplings);
1851 }
1852 _diagrams.push_back(vertices);
1853 }
1854
1855 else if (_config.prodCouplings.size() > 0 && _config.decCouplings.size() > 0) {
1856 std::vector<RooListProxy *> vertices;
1857 RooArgList operators;
1858 cxcoutP(InputArguments) << "prod/dec couplings provided" << std::endl;
1859 extractOperators(_config.prodCouplings, operators);
1860 extractOperators(_config.decCouplings, operators);
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;
1870 _operators.add(operators);
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 << "noInteference";
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.c_str());
1913 if (!file) {
1914 coutE(InputArguments) << "unable to open file '" << filename << "'!" << std::endl;
1915 return;
1916 }
1917 this->readParameters(file);
1918 checkNameConflict(_config.paramCards, _operators);
1919 this->collectInputs(file);
1920 closeFile(file);
1921 RooRealVar *nNP0 = new RooRealVar("nNP0", "nNP0", 1., 0, 1.);
1922 nNP0->setStringAttribute("NewPhysics", "0");
1923 nNP0->setConstant(true);
1924 _flags.add(*nNP0);
1925 RooRealVar *nNP1 = new RooRealVar("nNP1", "nNP1", 1., 0, 1.);
1926 nNP1->setStringAttribute("NewPhysics", "1");
1927 nNP1->setConstant(true);
1928 _flags.add(*nNP1);
1929 RooRealVar *nNP2 = new RooRealVar("nNP2", "nNP2", 1., 0, 1.);
1930 nNP2->setStringAttribute("NewPhysics", "2");
1931 nNP2->setConstant(true);
1932 _flags.add(*nNP2);
1933 RooRealVar *nNP3 = new RooRealVar("nNP3", "nNP3", 1., 0, 1.);
1934 nNP3->setStringAttribute("NewPhysics", "3");
1935 nNP3->setConstant(true);
1936 _flags.add(*nNP3);
1937 RooRealVar *nNP4 = new RooRealVar("nNP4", "nNP4", 1., 0, 1.);
1938 nNP4->setStringAttribute("NewPhysics", "4");
1939 nNP4->setConstant(true);
1940 _flags.add(*nNP4);
1941 // we can't use `addOwned` before, because the RooListProxy doesn't overload
1942 // `addOwned` correctly (it might in the future, then this can be changed).
1944}
1945
1946////////////////////////////////////////////////////////////////////////////////
1947/// copy constructor
1948
1950 : RooAbsReal(other, name), _cacheMgr(other._cacheMgr, this), _scale(other._scale), _sampleMap(other._sampleMap),
1951 _physics(other._physics.GetName(), this, other._physics),
1952 _operators(other._operators.GetName(), this, other._operators),
1953 _observables(other._observables.GetName(), this, other._observables),
1954 _binWidths(other._binWidths.GetName(), this, other._binWidths), _flags{other._flags.GetName(), this, other._flags},
1955 _config(other._config)
1956{
1957 for (size_t j = 0; j < other._diagrams.size(); ++j) {
1958 std::vector<RooListProxy *> diagram;
1959 for (size_t i = 0; i < other._diagrams[j].size(); ++i) {
1960 RooListProxy *list = new RooListProxy(other._diagrams[j][i]->GetName(), this, *(other._diagrams[j][i]));
1961 diagram.push_back(list);
1962 }
1963 _diagrams.push_back(diagram);
1964 }
1966}
1967
1968////////////////////////////////////////////////////////////////////////////////
1969/// set energy scale of the EFT expansion
1970
1972{
1973 _scale = val;
1974}
1975
1976////////////////////////////////////////////////////////////////////////////////
1977/// get energy scale of the EFT expansion
1978
1980{
1981 return _scale;
1982}
1983
1984////////////////////////////////////////////////////////////////////////////////
1985// default constructor
1986
1988 : _cacheMgr(this, 10, true, true), _operators("operators", "set of operators", this, true, false),
1989 _observables("observable", "morphing observable", this, true, false),
1990 _binWidths("binWidths", "set of bin width objects", this, true, false)
1991{
1993}
1994
1995////////////////////////////////////////////////////////////////////////////////
1996/// default destructor
1997
1999{
2000 for (auto const &diagram : _diagrams) {
2001 for (RooListProxy *vertex : diagram) {
2002 delete vertex;
2003 }
2004 }
2006}
2007
2008////////////////////////////////////////////////////////////////////////////////
2009/// calculate the number of samples needed to morph a bivertex, 2-2 physics
2010/// process
2011
2012int RooLagrangianMorphFunc::countSamples(int nprod, int ndec, int nboth)
2013{
2014 FeynmanDiagram diagram;
2015 std::vector<bool> prod;
2016 std::vector<bool> dec;
2017 for (int i = 0; i < nboth; ++i) {
2018 prod.push_back(true);
2019 dec.push_back(true);
2020 }
2021 for (int i = 0; i < nprod; ++i) {
2022 prod.push_back(true);
2023 dec.push_back(false);
2024 }
2025 for (int i = 0; i < ndec; ++i) {
2026 prod.push_back(false);
2027 dec.push_back(true);
2028 }
2029 diagram.push_back(prod);
2030 diagram.push_back(dec);
2031 MorphFuncPattern morphfuncpattern;
2032 ::collectPolynomials(morphfuncpattern, diagram);
2033 return morphfuncpattern.size();
2034}
2035
2036////////////////////////////////////////////////////////////////////////////////
2037/// calculate the number of samples needed to morph a certain physics process
2038
2039int RooLagrangianMorphFunc::countSamples(std::vector<RooArgList *> &vertices)
2040{
2041 RooArgList operators, couplings;
2042 for (auto vertex : vertices) {
2043 extractOperators(*vertex, operators);
2044 extractCouplings(*vertex, couplings);
2045 }
2046 FeynmanDiagram diagram;
2047 ::fillFeynmanDiagram(diagram, vertices, couplings);
2048 MorphFuncPattern morphfuncpattern;
2049 ::collectPolynomials(morphfuncpattern, diagram);
2050 return morphfuncpattern.size();
2051}
2052
2053////////////////////////////////////////////////////////////////////////////////
2054/// create only the weight formulas. static function for external usage.
2055
2056std::map<std::string, std::string>
2058 const std::vector<std::vector<std::string>> &vertices_str)
2059{
2060 std::stack<RooArgList> ownedVertices;
2061 std::vector<RooArgList *> vertices;
2062 RooArgList couplings;
2063 for (const auto &vtx : vertices_str) {
2064 ownedVertices.emplace();
2065 auto &vertex = ownedVertices.top();
2066 for (const auto &c : vtx) {
2067 auto coupling = static_cast<RooRealVar *>(couplings.find(c.c_str()));
2068 if (!coupling) {
2069 auto couplingOwner = std::make_unique<RooRealVar>(c.c_str(), c.c_str(), 1., 0., 10.);
2070 coupling = couplingOwner.get();
2071 couplings.addOwned(std::move(couplingOwner));
2072 }
2073 vertex.add(*coupling);
2074 }
2075 vertices.push_back(&vertex);
2076 }
2077 auto retval = RooLagrangianMorphFunc::createWeightStrings(inputs, vertices, couplings);
2078 return retval;
2079}
2080
2081////////////////////////////////////////////////////////////////////////////////
2082/// create only the weight formulas. static function for external usage.
2083
2084std::map<std::string, std::string>
2086 const std::vector<RooArgList *> &vertices, RooArgList &couplings)
2087{
2088 return createWeightStrings(inputs, vertices, couplings, {}, {}, {});
2089}
2090
2091////////////////////////////////////////////////////////////////////////////////
2092/// create only the weight formulas. static function for external usage.
2093
2094std::map<std::string, std::string>
2096 const std::vector<RooArgList *> &vertices, RooArgList &couplings,
2097 const RooLagrangianMorphFunc::FlagMap &flagValues, const RooArgList &flags,
2098 const std::vector<std::vector<std::string>> &nonInterfering)
2099{
2100 FormulaList formulas = ::createFormulas("", inputs, flagValues, {vertices}, couplings, flags, nonInterfering);
2101 RooArgSet operators;
2102 extractOperators(couplings, operators);
2103 Matrix matrix(::buildMatrixT<Matrix>(inputs, formulas, operators, flagValues, flags));
2104 if (size(matrix) < 1) {
2105 std::cerr << "input matrix is empty, please provide suitable input samples!" << std::endl;
2106 }
2107 Matrix inverse(::diagMatrix(size(matrix)));
2108 double condition __attribute__((unused)) = (double)(invertMatrix(matrix, inverse));
2109 auto retval = buildSampleWeightStrings(inputs, formulas, inverse);
2110 return retval;
2111}
2112
2113////////////////////////////////////////////////////////////////////////////////
2114/// create only the weight formulas. static function for external usage.
2115
2117 const std::vector<RooArgList *> &vertices, RooArgList &couplings,
2118 const RooLagrangianMorphFunc::FlagMap &flagValues,
2119 const RooArgList &flags,
2120 const std::vector<std::vector<std::string>> &nonInterfering)
2121{
2122 FormulaList formulas = ::createFormulas("", inputs, flagValues, {vertices}, couplings, flags, nonInterfering);
2123 RooArgSet operators;
2124 extractOperators(couplings, operators);
2125 Matrix matrix(::buildMatrixT<Matrix>(inputs, formulas, operators, flagValues, flags));
2126 if (size(matrix) < 1) {
2127 std::cerr << "input matrix is empty, please provide suitable input samples!" << std::endl;
2128 }
2129 Matrix inverse(::diagMatrix(size(matrix)));
2130 double condition __attribute__((unused)) = (double)(invertMatrix(matrix, inverse));
2131 RooArgSet retval;
2132 ::buildSampleWeights(retval, (const char *)nullptr /* name */, inputs, formulas, inverse);
2133 return retval;
2134}
2135
2136////////////////////////////////////////////////////////////////////////////////
2137/// create only the weight formulas. static function for external usage.
2138
2140 const std::vector<RooArgList *> &vertices, RooArgList &couplings)
2141{
2142 RooArgList flags;
2143 FlagMap flagValues;
2144 return RooLagrangianMorphFunc::createWeights(inputs, vertices, couplings, flagValues, flags, {});
2145}
2146
2147////////////////////////////////////////////////////////////////////////////////
2148/// return the RooProduct that is the element of the RooRealSumPdfi
2149/// corresponding to the given sample name
2150
2152{
2153 auto mf = this->getFunc();
2154 if (!mf) {
2155 coutE(Eval) << "unable to retrieve morphing function" << std::endl;
2156 return nullptr;
2157 }
2158 std::unique_ptr<RooArgSet> args{mf->getComponents()};
2159 TString prodname(name);
2160 prodname.Append("_");
2161 prodname.Append(this->GetName());
2162
2163 for (auto itr : *args) {
2164 RooProduct *prod = dynamic_cast<RooProduct *>(itr);
2165 if (!prod)
2166 continue;
2167 TString sname(prod->GetName());
2168 if (sname.CompareTo(prodname) == 0) {
2169 return prod;
2170 }
2171 }
2172 return nullptr;
2173}
2174////////////////////////////////////////////////////////////////////////////////
2175/// return the vector of sample names, used to build the morph func
2176
2177std::vector<std::string> RooLagrangianMorphFunc::getSamples() const
2178{
2179 return _config.folderNames;
2180}
2181
2182////////////////////////////////////////////////////////////////////////////////
2183/// retrieve the weight (prefactor) of a sample with the given name
2184
2186{
2187 auto cache = this->getCache();
2188 auto wname = std::string("w_") + name + "_" + this->GetName();
2189 return dynamic_cast<RooAbsReal *>(cache->_weights.find(wname.c_str()));
2190}
2191
2192////////////////////////////////////////////////////////////////////////////////
2193/// print the current sample weights
2194
2196{
2197 this->printSampleWeights();
2198}
2199
2200////////////////////////////////////////////////////////////////////////////////
2201/// print the current sample weights
2202
2204{
2205 auto *cache = this->getCache();
2206 for (const auto &sample : _sampleMap) {
2207 auto weightName = std::string("w_") + sample.first + "_" + this->GetName();
2208 auto weight = static_cast<RooAbsReal *>(cache->_weights.find(weightName.c_str()));
2209 if (!weight)
2210 continue;
2211 }
2212}
2213
2214////////////////////////////////////////////////////////////////////////////////
2215/// randomize the parameters a bit
2216/// useful to test and debug fitting
2217
2219{
2220 RooRealVar *obj;
2221 TRandom3 r;
2222
2223 for (auto itr : _operators) {
2224 obj = dynamic_cast<RooRealVar *>(itr);
2225 double val = obj->getVal();
2226 if (obj->isConstant())
2227 continue;
2228 double variation = r.Gaus(1, z);
2229 obj->setVal(val * variation);
2230 }
2231}
2232
2233////////////////////////////////////////////////////////////////////////////////
2234/// retrive the new physics objects and update the weights in the morphing
2235/// function
2236
2238{
2239 auto cache = this->getCache();
2240
2241 std::string filename = _config.fileName;
2242 TDirectory *file = openFile(filename.c_str());
2243 if (!file) {
2244 coutE(InputArguments) << "unable to open file '" << filename << "'!" << std::endl;
2245 return false;
2246 }
2247
2248 this->readParameters(file);
2249
2250 checkNameConflict(_config.paramCards, _operators);
2251 this->collectInputs(file);
2252
2253 cache->buildMatrix(_config.paramCards, _config.flagValues, _flags);
2254 this->updateSampleWeights();
2255
2256 closeFile(file);
2257 return true;
2258}
2259
2260////////////////////////////////////////////////////////////////////////////////
2261/// setup the morphing function with a predefined inverse matrix
2262/// call this function *before* any other after creating the object
2263
2265{
2266 auto cache = static_cast<RooLagrangianMorphFunc::CacheElem *>(_cacheMgr.getObj(0, (RooArgSet *)0));
2267 Matrix m = makeSuperMatrix(inverse);
2268 if (cache) {
2269 std::string filename = _config.fileName;
2270 cache->_inverse = m;
2271 TDirectory *file = openFile(filename.c_str());
2272 if (!file) {
2273 coutE(InputArguments) << "unable to open file '" << filename << "'!" << std::endl;
2274 return false;
2275 }
2276
2277 this->readParameters(file);
2278 checkNameConflict(_config.paramCards, _operators);
2279 this->collectInputs(file);
2280
2281 // then, update the weights in the morphing function
2282 this->updateSampleWeights();
2283
2284 closeFile(file);
2285 } else {
2287 if (!cache)
2288 coutE(Caching) << "unable to create cache!" << std::endl;
2289 _cacheMgr.setObj(0, 0, cache, 0);
2290 }
2291 return true;
2292}
2293
2294////////////////////////////////////////////////////////////////////////////////
2295// setup the morphing function with a predefined inverse matrix
2296// call this function *before* any other after creating the object
2297
2299{
2300 auto cache = static_cast<RooLagrangianMorphFunc::CacheElem *>(_cacheMgr.getObj(0, (RooArgSet *)0));
2301 if (cache) {
2302 return false;
2303 }
2304 cache = RooLagrangianMorphFunc::CacheElem::createCache(this, readMatrixFromFileT<Matrix>(filename));
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 *>(_cacheMgr.getObj(0, (RooArgSet *)0));
2329 if (!cache) {
2330 cxcoutP(Caching) << "creating cache from getCache function for " << this << std::endl;
2331 cxcoutP(Caching) << "current storage has size " << _sampleMap.size() << std::endl;
2333 if (cache)
2334 _cacheMgr.setObj(nullptr, nullptr, cache, nullptr);
2335 else
2336 coutE(Caching) << "unable to create cache!" << std::endl;
2337 }
2338 return cache;
2339}
2340
2341////////////////////////////////////////////////////////////////////////////////
2342/// return true if a cache object is present, false otherwise
2343
2345{
2346 return (bool)(_cacheMgr.getObj(nullptr, static_cast<RooArgSet *>(nullptr)));
2347}
2348
2349////////////////////////////////////////////////////////////////////////////////
2350/// set one parameter to a specific value
2351
2353{
2354 RooRealVar *param = this->getParameter(name);
2355 if (!param) {
2356 return;
2357 }
2358 if (value > param->getMax())
2359 param->setMax(value);
2360 if (value < param->getMin())
2361 param->setMin(value);
2362 param->setVal(value);
2363}
2364
2365////////////////////////////////////////////////////////////////////////////////
2366/// set one flag to a specific value
2367
2369{
2370 RooRealVar *param = this->getFlag(name);
2371 if (!param) {
2372 return;
2373 }
2374 param->setVal(value);
2375}
2376
2377////////////////////////////////////////////////////////////////////////////////
2378/// set one parameter to a specific value and range
2379
2380void RooLagrangianMorphFunc::setParameter(const char *name, double value, double min, double max)
2381{
2382 RooRealVar *param = this->getParameter(name);
2383 if (!param) {
2384 return;
2385 }
2386 param->setMin(min);
2387 param->setMax(max);
2388 param->setVal(value);
2389}
2390
2391////////////////////////////////////////////////////////////////////////////////
2392/// set one parameter to a specific value and range
2393void RooLagrangianMorphFunc::setParameter(const char *name, double value, double min, double max, double error)
2394{
2395 RooRealVar *param = this->getParameter(name);
2396 if (!param) {
2397 return;
2398 }
2399 param->setMin(min);
2400 param->setMax(max);
2401 param->setVal(value);
2402 param->setError(error);
2403}
2404
2405////////////////////////////////////////////////////////////////////////////////
2406/// return true if the parameter with the given name is set constant, false
2407/// otherwise
2408
2410{
2411 RooRealVar *param = this->getParameter(name);
2412 if (param) {
2413 return param->isConstant();
2414 }
2415 return true;
2416}
2417
2418////////////////////////////////////////////////////////////////////////////////
2419/// retrieve the RooRealVar object incorporating the parameter with the given
2420/// name
2422{
2423
2424 return dynamic_cast<RooRealVar *>(_operators.find(name));
2425}
2426
2427////////////////////////////////////////////////////////////////////////////////
2428/// retrieve the RooRealVar object incorporating the flag with the given name
2429
2431{
2432 return dynamic_cast<RooRealVar *>(_flags.find(name));
2433}
2434
2435////////////////////////////////////////////////////////////////////////////////
2436/// check if a parameter of the given name is contained in the list of known
2437/// parameters
2438
2440{
2441 return this->getParameter(name);
2442}
2443
2444////////////////////////////////////////////////////////////////////////////////
2445/// call setConstant with the boolean argument provided on the parameter with
2446/// the given name
2447
2448void RooLagrangianMorphFunc::setParameterConstant(const char *name, bool constant) const
2449{
2450 RooRealVar *param = this->getParameter(name);
2451 if (param) {
2452 return param->setConstant(constant);
2453 }
2454}
2455
2456////////////////////////////////////////////////////////////////////////////////
2457/// set one parameter to a specific value
2458
2460{
2461 RooRealVar *param = this->getParameter(name);
2462 if (param) {
2463 return param->getVal();
2464 }
2465 return 0.0;
2466}
2467
2468////////////////////////////////////////////////////////////////////////////////
2469/// set the morphing parameters to those supplied in the given param hist
2470
2472{
2473 setParams(paramhist, _operators, false);
2474}
2475
2476////////////////////////////////////////////////////////////////////////////////
2477/// set the morphing parameters to those supplied in the sample with the given
2478/// name
2479
2480void RooLagrangianMorphFunc::setParameters(const char *foldername)
2481{
2482 std::string filename = _config.fileName;
2483 TDirectory *file = openFile(filename.c_str());
2484 auto paramhist = loadFromFileResidentFolder<TH1>(file, foldername, "param_card");
2485 setParams(paramhist.get(), _operators, false);
2486 closeFile(file);
2487}
2488
2489/////////////////////////////////////////////////////////////////////////////////
2490/// retrieve the morphing parameters associated to the sample with the given
2491/// name
2492
2494{
2495 const std::string name(foldername);
2496 return _config.paramCards.at(name);
2497}
2498
2499////////////////////////////////////////////////////////////////////////////////
2500/// set the morphing parameters to those supplied in the list with the given
2501/// name
2502
2504{
2505 for (auto itr : *list) {
2506 RooRealVar *param = dynamic_cast<RooRealVar *>(itr);
2507 if (!param)
2508 continue;
2509 this->setParameter(param->GetName(), param->getVal());
2510 }
2511}
2512
2513////////////////////////////////////////////////////////////////////////////////
2514/// retrieve the histogram observable
2515
2517{
2518 if (_observables.getSize() < 1) {
2519 coutE(InputArguments) << "observable not available!" << std::endl;
2520 return nullptr;
2521 }
2522 return static_cast<RooRealVar *>(_observables.at(0));
2523}
2524
2525////////////////////////////////////////////////////////////////////////////////
2526/// retrieve the histogram observable
2527
2529{
2530 if (_binWidths.getSize() < 1) {
2531 coutE(InputArguments) << "bin width not available!" << std::endl;
2532 return nullptr;
2533 }
2534 return static_cast<RooRealVar *>(_binWidths.at(0));
2535}
2536
2537////////////////////////////////////////////////////////////////////////////////
2538/// retrieve a histogram output of the current morphing settings
2539
2541{
2542 return this->createTH1(name, false);
2543}
2544
2545////////////////////////////////////////////////////////////////////////////////
2546/// retrieve a histogram output of the current morphing settings
2547
2548TH1 *RooLagrangianMorphFunc::createTH1(const std::string &name, bool correlateErrors)
2549{
2550 auto mf = std::make_unique<RooRealSumFunc>(*(this->getFunc()));
2551 RooRealVar *observable = this->getObservable();
2552
2553 const int nbins = observable->getBins();
2554
2555 auto hist = std::make_unique<TH1F>(name.c_str(), name.c_str(), nbins, observable->getBinning().array());
2556
2557 std::unique_ptr<RooArgSet> args{mf->getComponents()};
2558 for (int i = 0; i < nbins; ++i) {
2559 observable->setBin(i);
2560 double val = 0;
2561 double unc2 = 0;
2562 double unc = 0;
2563 for (auto itr : *args) {
2564 RooProduct *prod = dynamic_cast<RooProduct *>(itr);
2565 if (!prod)
2566 continue;
2567 RooAbsArg *phys = prod->components().find(Form("phys_%s", prod->GetName()));
2568 RooHistFunc *hf = dynamic_cast<RooHistFunc *>(phys);
2569 if (!hf) {
2570 continue;
2571 }
2572 const RooDataHist &dhist = hf->dataHist();
2573 dhist.get(i);
2574 RooAbsReal *formula = dynamic_cast<RooAbsReal *>(prod->components().find(Form("w_%s", prod->GetName())));
2575 double weight = formula->getVal();
2576 unc2 += dhist.weightSquared() * weight * weight;
2577 unc += sqrt(dhist.weightSquared()) * weight;
2578 val += dhist.weight() * weight;
2579 }
2580 hist->SetBinContent(i + 1, val);
2581 hist->SetBinError(i + 1, correlateErrors ? unc : sqrt(unc2));
2582 }
2583 return hist.release();
2584}
2585
2586////////////////////////////////////////////////////////////////////////////////
2587/// count the number of formulas that correspond to the current parameter set
2588
2590{
2591 int nFormulas = 0;
2592 auto mf = std::make_unique<RooRealSumFunc>(*(this->getFunc()));
2593 if (!mf)
2594 coutE(InputArguments) << "unable to retrieve morphing function" << std::endl;
2595 std::unique_ptr<RooArgSet> args{mf->getComponents()};
2596 for (auto itr : *args) {
2597 RooProduct *prod = dynamic_cast<RooProduct *>(itr);
2598 if (prod->getVal() != 0) {
2599 nFormulas++;
2600 }
2601 }
2602 return nFormulas;
2603}
2604
2605////////////////////////////////////////////////////////////////////////////////
2606/// check if there is any morphing power provided for the given parameter
2607/// morphing power is provided as soon as any two samples provide different,
2608/// non-zero values for this parameter
2609
2610bool RooLagrangianMorphFunc::isParameterUsed(const char *paramname) const
2611{
2612 std::string pname(paramname);
2613 double val = 0;
2614 bool isUsed = false;
2615 for (const auto &sample : _config.paramCards) {
2616 double thisval = sample.second.at(pname);
2617 if (thisval != val) {
2618 if (val != 0)
2619 isUsed = true;
2620 val = thisval;
2621 }
2622 }
2623 return isUsed;
2624}
2625
2626////////////////////////////////////////////////////////////////////////////////
2627/// check if there is any morphing power provided for the given coupling
2628/// morphing power is provided as soon as any two samples provide
2629/// different, non-zero values for this coupling
2630
2632{
2633 std::string cname(couplname);
2634 const RooArgList *args = this->getCouplingSet();
2635 RooAbsReal *coupling = dynamic_cast<RooAbsReal *>(args->find(couplname));
2636 if (!coupling)
2637 return false;
2639 double val = 0;
2640 bool isUsed = false;
2641 for (const auto &sample : _config.paramCards) {
2642 this->setParameters(sample.second);
2643 double thisval = coupling->getVal();
2644 if (thisval != val) {
2645 if (val != 0)
2646 isUsed = true;
2647 val = thisval;
2648 }
2649 }
2650 this->setParameters(params);
2651 return isUsed;
2652}
2653
2654////////////////////////////////////////////////////////////////////////////////
2655/// return the number of parameters in this morphing function
2656
2658{
2659 return this->getParameterSet()->getSize();
2660}
2661
2662////////////////////////////////////////////////////////////////////////////////
2663/// return the number of samples in this morphing function
2664
2666{
2667 // return the number of samples in this morphing function
2668 auto cache = getCache();
2669 return cache->_formulas.size();
2670}
2671
2672////////////////////////////////////////////////////////////////////////////////
2673/// print the contributing samples and their respective weights
2674
2676{
2677 auto mf = std::make_unique<RooRealSumFunc>(*(this->getFunc()));
2678 if (!mf) {
2679 std::cerr << "Error: unable to retrieve morphing function" << std::endl;
2680 return;
2681 }
2682 std::unique_ptr<RooArgSet> args{mf->getComponents()};
2683 for (auto *formula : dynamic_range_cast<RooAbsReal*>(*args)) {
2684 if (formula) {
2685 TString name(formula->GetName());
2686 name.Remove(0, 2);
2687 name.Prepend("phys_");
2688 if (!args->find(name.Data())) {
2689 continue;
2690 }
2691 double val = formula->getVal();
2692 if (val != 0) {
2693 std::cout << formula->GetName() << ": " << val << " = " << formula->GetTitle() << std::endl;
2694 }
2695 }
2696 }
2697}
2698
2699////////////////////////////////////////////////////////////////////////////////
2700/// get the set of parameters
2701
2703{
2704 return &(_operators);
2705}
2706
2707////////////////////////////////////////////////////////////////////////////////
2708/// get the set of couplings
2709
2711{
2712 auto cache = getCache();
2713 return &(cache->_couplings);
2714}
2715
2716////////////////////////////////////////////////////////////////////////////////
2717/// retrieve a set of couplings (-?-)
2718
2720{
2722 for (auto obj : *(this->getCouplingSet())) {
2723 RooAbsReal *var = dynamic_cast<RooAbsReal *>(obj);
2724 if (!var)
2725 continue;
2726 const std::string name(var->GetName());
2727 double val = var->getVal();
2728 couplings[name] = val;
2729 }
2730 return couplings;
2731}
2732
2733////////////////////////////////////////////////////////////////////////////////
2734/// retrieve the parameter set
2735
2737{
2738 return getParams(_operators);
2739}
2740
2741////////////////////////////////////////////////////////////////////////////////
2742/// retrieve a set of couplings (-?-)
2743
2745{
2746 setParams(params, _operators, false);
2747}
2748
2749////////////////////////////////////////////////////////////////////////////////
2750/// (currently similar to cloning the Pdf
2751
2752std::unique_ptr<RooWrapperPdf> RooLagrangianMorphFunc::createPdf() const
2753{
2754 auto cache = getCache();
2755 auto func = std::make_unique<RooRealSumFunc>(*(cache->_sumFunc));
2756
2757 // create a wrapper on the roorealsumfunc
2758 return std::make_unique<RooWrapperPdf>(Form("pdf_%s", func->GetName()), Form("pdf of %s", func->GetTitle()), *func);
2759}
2760
2761////////////////////////////////////////////////////////////////////////////////
2762/// get the func
2763
2765{
2766 auto cache = getCache();
2767 return cache->_sumFunc.get();
2768}
2769
2770////////////////////////////////////////////////////////////////////////////////
2771/// return extended mored capabilities
2772
2774{
2775 return this->createPdf()->extendMode();
2776}
2777
2778////////////////////////////////////////////////////////////////////////////////
2779/// return expected number of events for extended likelihood calculation,
2780/// this is the sum of all coefficients
2781
2783{
2784 return this->createPdf()->expectedEvents(nset);
2785}
2786
2787////////////////////////////////////////////////////////////////////////////////
2788/// return the number of expected events for the current parameter set
2789
2791{
2792 RooArgSet set;
2793 set.add(*this->getObservable());
2794 return this->createPdf()->expectedEvents(set);
2795}
2796
2797////////////////////////////////////////////////////////////////////////////////
2798/// return expected number of events for extended likelihood calculation,
2799/// this is the sum of all coefficients
2800
2802{
2803 return createPdf()->expectedEvents(&nset);
2804}
2805
2806////////////////////////////////////////////////////////////////////////////////
2807/// return the expected uncertainty for the current parameter set
2808
2810{
2811 RooRealVar *observable = this->getObservable();
2812 auto cache = this->getCache();
2813 double unc2 = 0;
2814 for (const auto &sample : _sampleMap) {
2815 RooAbsArg *phys = _physics.at(sample.second);
2816 auto weightName = std::string("w_") + sample.first + "_" + this->GetName();
2817 auto weight = static_cast<RooAbsReal *>(cache->_weights.find(weightName.c_str()));
2818 if (!weight) {
2819 coutE(InputArguments) << "unable to find object " + weightName << std::endl;
2820 return 0.0;
2821 }
2822 double newunc2 = 0;
2823 RooHistFunc *hf = dynamic_cast<RooHistFunc *>(phys);
2824 RooRealVar *rv = dynamic_cast<RooRealVar *>(phys);
2825 if (hf) {
2826 const RooDataHist &hist = hf->dataHist();
2827 for (Int_t j = 0; j < observable->getBins(); ++j) {
2828 hist.get(j);
2829 newunc2 += hist.weightSquared();
2830 }
2831 } else if (rv) {
2832 newunc2 = pow(rv->getError(), 2);
2833 }
2834 double w = weight->getVal();
2835 unc2 += newunc2 * w * w;
2836 // std::cout << phys->GetName() << " : " << weight->GetName() << "
2837 // thisweight: " << w << " thisxsec2: " << newunc2 << " weight " << weight
2838 // << std::endl;
2839 }
2840 return sqrt(unc2);
2841}
2842
2843////////////////////////////////////////////////////////////////////////////////
2844/// print the parameters and their current values
2845
2847{
2848 // print the parameters and their current values
2849 for (auto obj : _operators) {
2850 RooRealVar *param = static_cast<RooRealVar *>(obj);
2851 if (!param)
2852 continue;
2853 param->Print();
2854 }
2855}
2856
2857////////////////////////////////////////////////////////////////////////////////
2858/// print the flags and their current values
2859
2861{
2862 for (auto flag : _flags) {
2863 RooRealVar *param = static_cast<RooRealVar *>(flag);
2864 if (!param)
2865 continue;
2866 param->Print();
2867 }
2868}
2869
2870////////////////////////////////////////////////////////////////////////////////
2871/// print a set of couplings
2872
2874{
2876 for (auto c : couplings) {
2877 std::cout << c.first << ": " << c.second << std::endl;
2878 }
2879}
2880
2881////////////////////////////////////////////////////////////////////////////////
2882/// retrieve the list of bin boundaries
2883
2884std::list<double> *RooLagrangianMorphFunc::binBoundaries(RooAbsRealLValue &obs, double xlo, double xhi) const
2885{
2886 return this->getFunc()->binBoundaries(obs, xlo, xhi);
2887}
2888
2889////////////////////////////////////////////////////////////////////////////////
2890/// retrieve the sample Hint
2891
2892std::list<double> *RooLagrangianMorphFunc::plotSamplingHint(RooAbsRealLValue &obs, double xlo, double xhi) const
2893{
2894 return this->getFunc()->plotSamplingHint(obs, xlo, xhi);
2895}
2896
2897////////////////////////////////////////////////////////////////////////////////
2898/// call getVal on the internal function
2899
2901{
2902 // call getVal on the internal function
2903 const RooRealSumFunc *pdf = this->getFunc();
2904 RooArgSet nSet;
2905 for (auto &obs : _observables) {
2906 nSet.add(*obs);
2907 }
2908 if (pdf)
2909 return _scale * pdf->getVal(&nSet);
2910 else
2911 std::cerr << "unable to acquire in-built function!" << std::endl;
2912 return 0.;
2913}
2914
2915////////////////////////////////////////////////////////////////////////////////
2916/// check if this PDF is a binned distribution in the given observable
2917
2919{
2920 return this->getFunc()->isBinnedDistribution(obs);
2921}
2922
2923////////////////////////////////////////////////////////////////////////////////
2924/// check if observable exists in the RooArgSet (-?-)
2925
2927{
2928 return this->getFunc()->checkObservables(nset);
2929}
2930
2931////////////////////////////////////////////////////////////////////////////////
2932/// Force analytical integration for the given observable
2933
2935{
2936 return this->getFunc()->forceAnalyticalInt(arg);
2937}
2938
2939////////////////////////////////////////////////////////////////////////////////
2940/// Retrieve the mat
2941
2943 const char *rangeName) const
2944{
2945 return this->getFunc()->getAnalyticalIntegralWN(allVars, numVars, normSet, rangeName);
2946}
2947
2948////////////////////////////////////////////////////////////////////////////////
2949/// Retrieve the matrix of coefficients
2950
2951double RooLagrangianMorphFunc::analyticalIntegralWN(Int_t code, const RooArgSet *normSet, const char *rangeName) const
2952{
2953 return this->getFunc()->analyticalIntegralWN(code, normSet, rangeName);
2954}
2955
2956////////////////////////////////////////////////////////////////////////////////
2957/// Retrieve the matrix of coefficients
2958
2959void RooLagrangianMorphFunc::printMetaArgs(std::ostream &os) const
2960{
2961 return this->getFunc()->printMetaArgs(os);
2962}
2963
2964////////////////////////////////////////////////////////////////////////////////
2965/// Retrieve the matrix of coefficients
2966
2968{
2969 return this->getFunc()->canNodeBeCached();
2970}
2971
2972////////////////////////////////////////////////////////////////////////////////
2973/// Retrieve the matrix of coefficients
2974
2976{
2977 this->getFunc()->setCacheAndTrackHints(arg);
2978}
2979
2980////////////////////////////////////////////////////////////////////////////////
2981/// Retrieve the matrix of coefficients
2982
2984{
2985 auto cache = getCache();
2986 if (!cache)
2987 coutE(Caching) << "unable to retrieve cache!" << std::endl;
2988 return makeRootMatrix(cache->_matrix);
2989}
2990
2991////////////////////////////////////////////////////////////////////////////////
2992/// Retrieve the matrix of coefficients after inversion
2993
2995{
2996 auto cache = getCache();
2997 if (!cache)
2998 coutE(Caching) << "unable to retrieve cache!" << std::endl;
2999 return makeRootMatrix(cache->_inverse);
3000}
3001
3002////////////////////////////////////////////////////////////////////////////////
3003/// Retrieve the condition of the coefficient matrix. If the condition number
3004/// is very large, then the matrix is ill-conditioned and is almost singular.
3005/// The computation of the inverse is prone to large numerical errors
3006
3008{
3009 auto cache = getCache();
3010 if (!cache)
3011 coutE(Caching) << "unable to retrieve cache!" << std::endl;
3012 return cache->_condition;
3013}
3014
3015////////////////////////////////////////////////////////////////////////////////
3016/// Return the RooRatio form of products and denominators of morphing functions
3017
3018std::unique_ptr<RooRatio>
3019RooLagrangianMorphFunc::makeRatio(const char *name, const char *title, RooArgList &nr, RooArgList &dr)
3020{
3021 RooArgList num, denom;
3022 for (auto it : nr) {
3023 num.add(*it);
3024 }
3025 for (auto it : dr) {
3026 denom.add(*it);
3027 }
3028 // same for denom
3029 return make_unique<RooRatio>(name, title, num, denom);
3030}
3031
3032// Register the factory interface
3033
3034namespace {
3035
3036// Helper function for factory interface
3037std::vector<std::string> asStringV(std::string const &arg)
3038{
3039 std::vector<std::string> out;
3040
3041 for (std::string &tok : ROOT::Split(arg, ",{}", true)) {
3042 if (tok[0] == '\'') {
3043 out.emplace_back(tok.substr(1, tok.size() - 2));
3044 } else {
3045 throw std::runtime_error("Strings in factory expressions need to be in single quotes!");
3046 }
3047 }
3048
3049 return out;
3050}
3051
3052class LMIFace : public RooFactoryWSTool::IFace {
3053public:
3054 std::string
3055 create(RooFactoryWSTool &, const char *typeName, const char *instName, std::vector<std::string> args) override;
3056};
3057
3058std::string LMIFace::create(RooFactoryWSTool &ft, const char * /*typeName*/, const char *instanceName,
3059 std::vector<std::string> args)
3060{
3061 // Perform syntax check. Warn about any meta parameters other than the ones needed
3062 const std::array<std::string, 4> funcArgs{{"fileName", "observableName", "couplings", "folders"}};
3063 std::map<string, string> mappedInputs;
3064
3065 for (unsigned int i = 1; i < args.size(); i++) {
3066 if (args[i].find("$fileName(") != 0 && args[i].find("$observableName(") != 0 &&
3067 args[i].find("$couplings(") != 0 && args[i].find("$folders(") != 0 && args[i].find("$NewPhysics(") != 0) {
3068 throw std::string(Form("%s::create() ERROR: unknown token %s encountered", instanceName, args[i].c_str()));
3069 }
3070 }
3071
3072 for (unsigned int i = 0; i < args.size(); i++) {
3073 if (args[i].find("$NewPhysics(") == 0) {
3074 vector<string> subargs = ft.splitFunctionArgs(args[i].c_str());
3075 for (const auto &subarg : subargs) {
3076 std::vector<std::string> parts = ROOT::Split(subarg, "=");
3077 if (parts.size() == 2) {
3078 ft.ws().arg(parts[0].c_str())->setAttribute("NewPhysics", atoi(parts[1].c_str()));
3079 } else
3080 throw std::string(Form("%s::create() ERROR: unknown token %s encountered, check input provided for %s",
3081 instanceName, subarg.c_str(), args[i].c_str()));
3082 }
3083 } else {
3084 std::vector<string> subargs = ft.splitFunctionArgs(args[i].c_str());
3085 if (subargs.size() == 1) {
3086 string expr = ft.processExpression(subargs[0].c_str());
3087 for (auto const &param : funcArgs) {
3088 if (args[i].find(param) != string::npos)
3089 mappedInputs[param] = subargs[0];
3090 }
3091 } else
3092 throw std::string(
3093 Form("Incorrect number of arguments in %s, have %d, expect 1", args[i].c_str(), (Int_t)subargs.size()));
3094 }
3095 }
3096
3098 config.fileName = asStringV(mappedInputs["fileName"])[0];
3099 config.observableName = asStringV(mappedInputs["observableName"])[0];
3100 config.folderNames = asStringV(mappedInputs["folders"]);
3101 config.couplings.add(ft.asLIST(mappedInputs["couplings"].c_str()));
3102
3103 ft.ws().import(RooLagrangianMorphFunc{instanceName, instanceName, config}, RooFit::Silence());
3104
3105 return instanceName;
3106}
3107
3108static Int_t init();
3109
3110int dummy = init();
3111
3112static Int_t init()
3113{
3114 RooFactoryWSTool::IFace *iface = new LMIFace;
3115 RooFactoryWSTool::registerSpecial("lagrangianmorph", iface);
3116 (void)dummy;
3117 return 0;
3118}
3119
3120} // 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:52
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
#define ClassImp(name)
Definition Rtypes.h:377
#define gDirectory
Definition TDirectory.h:386
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:2467
std::string & operator+=(std::string &left, const TString &right)
Definition TString.h:490
TTime operator*(const TTime &t1, const TTime &t2)
Definition TTime.h:85
RooAbsArg is the common abstract base class for objects that represent a value and a "shape" in RooFi...
Definition RooAbsArg.h:74
void Print(Option_t *options=nullptr) const override
Print the object to the defaultPrintStream().
Definition RooAbsArg.h:318
void setStringAttribute(const Text_t *key, const Text_t *value)
Associate string 'value' to this object under key 'key'.
bool isConstant() const
Check if the "Constant" attribute is set.
Definition RooAbsArg.h:359
bool addOwnedComponents(const RooAbsCollection &comps)
Take ownership of the contents of 'comps'.
void setValueDirty()
Mark the element dirty. This forces a re-evaluation when a value is requested.
Definition RooAbsArg.h:487
bool getAttribute(const Text_t *name) const
Check if a named attribute is set. By default, all attributes are unset.
void setAttribute(const Text_t *name, bool value=true)
Set (default) or clear a named boolean attribute of this object.
virtual double * array() const =0
RooAbsCacheElement is the abstract base class for objects to be stored in RooAbsCache cache manager o...
Int_t getSize() const
Return the number of elements in the collection.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Storage_t::size_type size() const
RooAbsArg * first() 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.
RooAbsRealLValue is the common abstract base class for objects that represent a real value that may a...
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.
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition RooAbsReal.h:62
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:91
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:55
Class RooBinning is an implements RooAbsBinning in terms of an array of boundary values,...
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...
The RooDataHist is a container class to hold N-dimensional binned data.
Definition RooDataHist.h:39
double weight(std::size_t i) const
Return weight of i-th bin.
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:76
virtual std::string create(RooFactoryWSTool &ft, const char *typeName, const char *instanceName, std::vector< std::string > args)=0
RooFactoryWSTool is a class similar to TTree::MakeClass() that generates skeleton code for RooAbsPdf ...
RooWorkspace & ws()
static void registerSpecial(const char *typeName, RooFactoryWSTool::IFace *iface)
Register foreign special objects in factory.
std::string processExpression(const char *expr)
Process a single high-level expression or list of expressions.
RooArgList asLIST(const char *)
CINT constructor interface, return constructor string argument #idx as RooArgList of objects found in...
std::vector< std::string > splitFunctionArgs(const char *funcExpr)
Allocate and fill work buffer.
RooHistFunc implements a real-valued function sampled from a multidimensional histogram.
Definition RooHistFunc.h:31
RooArgSet const & getHistObsList() const
Definition RooHistFunc.h:94
RooDataHist & dataHist()
Return RooDataHist that is represented.
Definition RooHistFunc.h:45
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()
retrive 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...
void setCoefficient(size_t idx, RooFit::SuperFloat c)
RooFit::SuperFloat getCoefficient(size_t idx)
A histogram function that assigns scale parameters to every bin.
static TClass * Class()
const RooArgList & paramList() const
A RooProduct 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
RooRealVar represents a variable that can be changed from the outside.
Definition RooRealVar.h:40
void setVal(double value) override
Set value of variable to 'value'.
void setError(double value)
Definition RooRealVar.h:64
void setMin(const char *name, double value)
Set minimum of name range to given value.
double getError() const
Definition RooRealVar.h:62
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.
bool import(const RooAbsArg &arg, const RooCmdArg &arg1=RooCmdArg(), const RooCmdArg &arg2=RooCmdArg(), const RooCmdArg &arg3=RooCmdArg(), const RooCmdArg &arg4=RooCmdArg(), const RooCmdArg &arg5=RooCmdArg(), const RooCmdArg &arg6=RooCmdArg(), const RooCmdArg &arg7=RooCmdArg(), const RooCmdArg &arg8=RooCmdArg(), const RooCmdArg &arg9=RooCmdArg())
Import a RooAbsArg object, e.g.
RooAbsArg * arg(RooStringView name) const
Return RooAbsArg with given name. A null pointer is returned if none is found.
Class to manage histogram axis.
Definition TAxis.h:30
Double_t GetXmax() const
Definition TAxis.h:135
const char * GetBinLabel(Int_t bin) const
Return label for bin.
Definition TAxis.cxx:440
Double_t GetXmin() const
Definition TAxis.h:134
Int_t GetNbins() const
Definition TAxis.h:121
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:81
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:2968
Double_t GetCondition() const
Definition TDecompBase.h:70
LU Decomposition class.
Definition TDecompLU.h:24
Bool_t Invert(TMatrixD &inv)
For a matrix A(m,m), its inverse A_inv is defined as A * A_inv = A_inv * A = unit (m x m) Ainv is ret...
Describe directory structure in memory.
Definition TDirectory.h:45
virtual TObject * Get(const char *namecycle)
Return pointer to object identified by namecycle.
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition TFile.h:51
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:4053
void Close(Option_t *option="") override
Close a file.
Definition TFile.cxx:914
<div class="legacybox"><h2>Legacy Code</h2> TFolder is a legacy interface: there will be no bug fixes...
Definition TFolder.h:30
TCollection * GetListOfFolders() const
Definition TFolder.h:55
virtual void SetOwner(Bool_t owner=kTRUE)
Set ownership.
Definition TFolder.cxx:483
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:58
static TClass * Class()
TAxis * GetXaxis()
Definition TH1.h:322
virtual Int_t GetNbinsX() const
Definition TH1.h:295
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:9072
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition TH1.cxx:7851
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:9088
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition TH1.cxx:9018
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5025
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width for 1D histogram.
Definition TH1.cxx:9029
virtual void Scale(Double_t c1=1, Option_t *option="")
Multiply this histogram by a constant c1.
Definition TH1.cxx:6586
Int_t GetNrows() const
virtual TMatrixTBase< Element > & UnitMatrix()
Make a unit matrix (matrix need not be a square one).
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:47
Mother of all ROOT objects.
Definition TObject.h:41
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:439
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:207
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
Named parameter, streamable and storable.
Definition TParameter.h:35
const AParamType & GetVal() const
Definition TParameter.h:67
Random number generator class based on M.
Definition TRandom3.h:27
Basic string class.
Definition TString.h:139
int CompareTo(const char *cs, ECaseCompare cmp=kExact) const
Compare a string to char *cs2.
Definition TString.cxx:450
const char * Data() const
Definition TString.h:380
TString & Append(const char *cs)
Definition TString.h:576
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
void(off) SmallVectorTemplateBase< T
double T(double x)
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
std::vector< std::string > Split(std::string_view str, std::string_view delims, bool skipEmpty=false)
Splits a string at each character in delims.
void init()
Inspect hardware capabilities, and load the optimal library for RooFit computations.
Definition file.py:1
Definition first.py:1
std::vector< std::string > folderNames
std::vector< std::vector< const char * > > nonInterfering
TMarker m
Definition textangle.C:8
double * vertex
Definition triangle.c:513
#define Split(a, ahi, alo)
Definition triangle.c:4776