MaCh3  2.2.3
Reference Guide
Functions
pyMaCh3.cpp File Reference
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
Include dependency graph for pyMaCh3.cpp:

Go to the source code of this file.

Functions

void initPlotting (py::module &)
 
void initFitters (py::module &)
 
void initSamples (py::module &)
 
void initManager (py::module &)
 
void initParameters (py::module &)
 
void initSplines (py::module &)
 
 PYBIND11_MODULE (_pyMaCh3, m)
 

Detailed Description

Author
Ewan Miller

Definition in file pyMaCh3.cpp.

Function Documentation

◆ initFitters()

void initFitters ( py::module &  m)

Definition at line 47 of file fitters.cpp.

47  {
48 
49  auto m_fitters = m.def_submodule("fitters");
50  m_fitters.doc() =
51  "This is a Python binding of MaCh3s C++ fitters library.";
52 
53 
54  py::class_<FitterBase, PyFitterBase /* <--- trampoline*/>(m_fitters, "FitterBase")
55  .def(py::init<manager* const>())
56 
57  .def(
58  "run",
60  "The implementation of the fitter, you should override this with your own desired fitting algorithm"
61  )
62 
63  .def(
64  "get_name",
66  " The name of the algorithm, you should override this with something like:: \n"
67  "\n"
68  " return 'mySuperCoolAlgoName' \n"
69  )
70 
71  .def(
72  "run_LLH_scan",
74  "Perform a 1D likelihood scan"
75  )
76 
77  .def(
78  "get_step_scale_from_LLH_scan",
80  "LLH scan is good first estimate of step scale, this will get the rough estimates for the step scales based on running an LLH scan"
81  )
82 
83  .def(
84  "run_2d_LLH_scan",
86  " Perform a 2D likelihood scan. \n"
87  " :param warning: This operation may take a significant amount of time, especially for complex models."
88  )
89 
90  .def(
91  "run_sigma_var",
93  " Perform a 2D and 1D sigma var for all samples. \n"
94  " :param warning: Code uses TH2Poly"
95  )
96 
97  .def(
98  "drag_race",
100  " Calculates the required time for each sample or covariance object in a drag race simulation. Inspired by Dan's feature \n"
101  " :param NLaps: number of laps, every part of Fitter will be tested with given number of laps and you will get total and average time",
102  py::arg("NLaps") = 100
103  )
104 
105  // stuff for registering other objects with the fitter
106 
107  .def(
108  "add_sample_handler",
110  " This function adds a sample handler object to the analysis framework. The sample handler object will be utilized in fitting procedures or likelihood scans. \n"
111  " :param sample: A sample handler object derived from SampleHandlerBase. ",
112  py::arg("sample")
113  )
114 
115  .def(
116  "add_syst_object",
118  " This function adds a Covariance object to the analysis framework. The Covariance object will be utilized in fitting procedures or likelihood scans. \n"
119  " :param cov: A Covariance object derived from ParameterHandlerBase. ",
120  py::arg("cov")
121  )
122 
123  ; // End of FitterBase class binding
124 
125  py::class_<MR2T2, FitterBase>(m_fitters, "mcmc")
126  .def(py::init<manager *const>())
127 
128  .def(
129  "set_chain_length",
131  "Set how long chain should be.",
132  py::arg("length")); // end of MCMC class binding
133 
134  py::class_<DelayedMR2T2, FitterBase>(m_fitters, "DelayedMCMC")
135  .def(py::init<manager *const>())
136 
137  .def(
138  "set_chain_length",
140  "Set how long chain should be.",
141  py::arg("length")); // end of MCMC class binding
142 
143  py::class_<LikelihoodFit, PyLikelihoodFit /* <--- trampoline*/, FitterBase>(m_fitters, "LikelihoodFit")
144  .def(py::init<manager* const>())
145 
146  .def(
147  "caluclate_chi2",
148  [](LikelihoodFit &self, const std::vector<double> &parameterVals)
149  {
150  return self.CalcChi2(parameterVals.data());
151  },
152  "Get the Chi2 calculation over all included samples and syst objects for the specified parameter_values \n\
153  :param parameter_valuse: The location to evaluate the chi2 at.",
154  py::arg("parameter_values")
155  )
156 
157  .def(
158  "get_n_params",
160  "Get The total number of parameters across all known covariance objects associated with this LikelihoodFit object."
161  )
162  ; // end of LikelihoodFit class binding
163 
164  py::class_<MinuitFit, LikelihoodFit>(m_fitters, "MinuitFit")
165  .def(py::init<manager* const>())
166 
167  ; // end of MinuitFit class binding
168 
169  py::class_<PSO, LikelihoodFit>(m_fitters, "PSO")
170  .def(py::init<manager* const>())
171 
172  .def(
173  "init",
174  &PSO::init,
175  "Initialise the fitter"
176  )
177 
178  ; // end of PSO class binding
179 
180 }
Base class for implementing fitting algorithms.
Definition: FitterBase.h:23
void RunLLHScan()
Perform a 1D likelihood scan.
Definition: FitterBase.cpp:516
void AddSystObj(ParameterHandlerBase *cov)
This function adds a Covariance object to the analysis framework. The Covariance object will be utili...
Definition: FitterBase.cpp:276
std::string GetName() const
Get name of class.
Definition: FitterBase.h:70
void AddSampleHandler(SampleHandlerBase *sample)
This function adds a sample PDF object to the analysis framework. The sample PDF object will be utili...
Definition: FitterBase.cpp:255
virtual void RunMCMC()=0
The specific fitting algorithm implemented in this function depends on the derived class....
void GetStepScaleBasedOnLLHScan()
LLH scan is good first estimate of step scale.
Definition: FitterBase.cpp:826
void RunSigmaVar()
Perform a 2D and 1D sigma var for all samples.
void DragRace(const int NLaps=100)
Calculates the required time for each sample or covariance object in a drag race simulation....
Definition: FitterBase.cpp:418
void Run2DLLHScan()
Perform a 2D likelihood scan.
Definition: FitterBase.cpp:875
Implementation of base Likelihood Fit class, it is mostly responsible for likelihood calculation whil...
Definition: LikelihoodFit.h:6
int GetNPars()
Get total number of params, this sums over all covariance objects.
Definition: LikelihoodFit.h:16
void setChainLength(unsigned int L)
Set how long chain should be.
Definition: MCMCBase.h:27
void init()
Definition: PSO.cpp:51
EW: As FitterBase is an abstract base class we have to do some gymnastics to get it to get it into py...
Definition: fitters.cpp:14
EW: As LikelihoodFit is an abstract base class we have to do some gymnastics to get it to get it into...
Definition: fitters.cpp:31

◆ initManager()

void initManager ( py::module &  m)

Definition at line 11 of file manager.cpp.

11  {
12 
13  auto m_manager = m.def_submodule("manager");
14  m_manager.doc() =
15  "This is a Python binding of MaCh3s C++ based manager library.";
16 
17  // Bind some of the cpp-yaml library
18  // shamelessly stolen from stackoverflow: https://stackoverflow.com/questions/62347521/using-pybind11-to-wrap-yaml-cpp-iterator
19  py::enum_<YAML::NodeType::value>(m_manager, "NodeType")
20  .value("Undefined", YAML::NodeType::Undefined)
21  .value("Null", YAML::NodeType::Null)
22  .value("Scalar", YAML::NodeType::Scalar)
23  .value("Sequence", YAML::NodeType::Sequence)
24  .value("Map", YAML::NodeType::Map);
25 
26  py::class_<YAML::Node>(m_manager, "YamlNode")
27  .def(py::init<const std::string &>())
28 
29  .def("data",
30  [](const YAML::Node node){
31  if ( node.Type() != YAML::NodeType::Scalar )
32  {
33  throw MaCh3Exception(__FILE__, __LINE__, "Attempting to access the data of non-scalar yaml node. This is undefined.");
34  }
35  return node.Scalar();
36  },
37  "Access the data stored in the node. This is only valid if the node is a 'scalar' type, i.e. it is a leaf of the yaml tree structure.")
38 
39  .def("__getitem__",
40  [](const YAML::Node node, const std::string& key){
41  return node[key];
42  })
43 
44  .def("__getitem__",
45  [](const YAML::Node node, const int& key){
46  if ( node.Type() != YAML::NodeType::Sequence)
47  {
48  throw MaCh3Exception(__FILE__, __LINE__, "Trying to access a non sequence yaml node with integer index");
49  }
50  return node[key];
51  })
52 
53  .def("__iter__",
54  [](const YAML::Node &node) {
55  return py::make_iterator(node.begin(), node.end());},
56  py::keep_alive<0, 1>())
57 
58  .def("__str__",
59  [](const YAML::Node& node) {
60  YAML::Emitter out;
61  out << node;
62  return std::string(out.c_str());
63  })
64 
65  .def("type", &YAML::Node::Type)
66 
67  .def("__len__", &YAML::Node::size)
68  ;
69 
70  py::class_<YAML::detail::iterator_value, YAML::Node>(m_manager, "_YamlDetailIteratorValue")
71  .def(py::init<>())
72  .def("first", [](YAML::detail::iterator_value& val) { return val.first;})
73  .def("second", [](YAML::detail::iterator_value& val) { return val.second;})
74  ;
75 
76  m.def("load_file", &YAML::LoadFile, "");
77 
78  py::class_<manager>(m_manager, "Manager")
79  .def(
80  py::init<std::string const &>(),
81  "create a Manager object with a specified *config_file*",
82  py::arg("config_file")
83  )
84 
85  .def(
86  "print",
88  "Print currently used config."
89  )
90 
91  .def(
92  "raw",
93  &manager::raw,
94  "Get the raw yaml config."
95  )
96 
97  .def(
98  "get_test_stat",
100  "Get the test statistic that was specified in the config file."
101  )
102  ;
103 
104 }
int size
void Print()
Print currently used config.
Definition: Manager.cpp:90
int GetMCStatLLH()
Get likelihood type defined in the config.
Definition: Manager.cpp:98
YAML::Node const & raw()
Return config.
Definition: Manager.h:41

◆ initParameters()

void initParameters ( py::module &  m)

Definition at line 38 of file parameters.cpp.

38  {
39 
40  auto m_parameters = m.def_submodule("parameters");
41  m_parameters.doc() =
42  "This is a Python binding of MaCh3s C++ parameters library.";
43 
44 
45  // Bind the systematic type enum that lets us set different types of systematics
46  py::enum_<SystType>(m_parameters, "SystematicType")
47  .value("Normalisation", SystType::kNorm)
48  .value("Spline", SystType::kSpline)
49  .value("Functional", SystType::kFunc)
50  .value("N_Systematic_Types", SystType::kSystTypes);
51 
52 
53  py::class_<ParameterHandlerBase, PyParameterHandlerBase /* <--- trampoline*/>(m_parameters, "ParameterHandlerBase")
54  .def(
55  py::init<const std::vector<std::string>&, const char *, double, int, int>(),
56  "Construct a parameters object from a set of yaml files that define the systematic parameters \n\
57  :param yaml_files: The name of the yaml file to initialise from. \n\
58  :param name: the name of this ParameterHandler object. \n\
59  :param threshold: threshold PCA threshold from 0 to 1. Default is -1 and means no PCA. \n\
60  :param first_PCA_par: FirstPCAdpar First PCA parameter that will be decomposed. \n\
61  :param last_PCA_par: LastPCAdpar First PCA parameter that will be decomposed.",
62  py::arg("yaml_files"),
63  py::arg("name"),
64  py::arg("threshold") = -1.0,
65  py::arg("firs_PCA_par") = -999,
66  py::arg("last_PCA_par") = -999
67  )
68 
69  .def(
70  "calculate_likelihood",
72  "Calculate penalty term based on inverted covariance matrix."
73  )
74 
75  .def(
76  "throw_par_prop",
78  "Throw the proposed parameter by magnitude *mag* X sigma. \n\
79  :param mag: This value multiplied by the prior value of each parameter will be the width of the distribution that the parameter values are drawn from. ",
80  py::arg("mag") = 1.0
81  )
82 
83  .def(
84  "get_internal_par_name",
85  [](ParameterHandlerBase &self, int index)
86  {
87  // do this to disambiguate between the std::string and const char* version of this fn
88  std::string ret;
89  ret = self.GetParName(index);
90  return ret;
91  },
92  "Get the internally used name of this parameter. \n\
93  :param index: The global index of the parameter",
94  py::arg("index")
95  )
96 
97  .def(
98  "get_fancy_par_name",
99  [](ParameterHandlerBase &self, int index)
100  {
101  // do this to disambiguate between the std::string and const char* version of this fn
102  std::string ret;
103  ret = self.GetParFancyName(index);
104  return ret;
105  },
106  "Get the name of this parameter. \n\
107  :param index: The global index of the parameter",
108  py::arg("index")
109  )
110 
111  .def(
112  "get_n_pars",
114  "Get the number of parameters that this ParameterHandler object knows about."
115  )
116 
117  .def(
118  "propose_step",
120  "Propose a step based on the covariances. Also feel free to overwrite if you want something more funky."
121  )
122 
123  .def(
124  "get_proposal_array",
125  [](ParameterHandlerBase &self)
126  {
127  return py::memoryview::from_buffer<double>(
128  self.GetParPropVec().data(), // the data pointer
129  {self.GetNParameters()}, // shape
130  {sizeof(double)} // shape
131  );
132  },
133  "Bind a python array to the parameter proposal values for this ParameterHandler object. \n\
134  This allows you to set e.g. a numpy array to 'track' the parameter proposal values. You could either use this to directly set the proposals, or to just read the values proposed by e.g. throw_par_prop() \n\
135  :warning: This should be set *AFTER* all of the parameters have been read in from the config file as it resizes the array to fit the number of parameters. \n\
136  :param array: This is the array that will be set. Size and contents don't matter as it will be changed to fit the parameters. "
137  )
138 
139 
140  ; // End of ParameterHandlerBase binding
141 
142 
143  py::class_<ParameterHandlerGeneric, ParameterHandlerBase /* <--- trampoline*/>(m_parameters, "ParameterHandlerGeneric")
144  .def(
145  py::init<const std::vector<std::string>&, const char *, double, int, int>(),
146  "Construct a systematic ParameterHandler object from a set of yaml files that define the systematic parameters \n\
147  :param yaml_files: The name of the yaml file to initialise from. \n\
148  :param name: the name of this ParameterHandler object. \n\
149  :param threshold: threshold PCA threshold from 0 to 1. Default is -1 and means no PCA. \n\
150  :param first_PCA_par: FirstPCAdpar First PCA parameter that will be decomposed. \n\
151  :param last_PCA_par: LastPCAdpar First PCA parameter that will be decomposed.",
152  py::arg("yaml_files"),
153  py::arg("name") = "xsec_cov",
154  py::arg("threshold") = -1.0,
155  py::arg("firs_PCA_par") = -999,
156  py::arg("last_PCA_par") = -999
157  )
158 
159  .def(
160  "get_par_type",
162  "Get what type of systematic this parameters is (see :py:class:`pyMaCh3.m_parameters.SystematicType` for possible types). \n\
163  :param index: The global index of the parameter",
164  py::arg("index")
165  )
166 
167  .def(
168  "get_par_spline_type",
170  "Get what type of spline this parameter is set to use (assuming that it is a spline type parameter). \n\
171  :param index: The index of the spline parameter",
172  py::arg("index")
173  )
174 
175  .def(
176  "get_par_spline_name",
178  "Get the name of the spline associated with a spline parameter. This is generally what it is called in input spline files and can in principle be different to the parameters name. \n\
179  :param index: The index of the spline parameter",
180  py::arg("index")
181  )
182 
183  ; // End of ParameterHandlerGeneric binding
184 }
@ kNorm
For normalisation parameters.
@ kSpline
For splined parameters (1D)
@ kSystTypes
This only enumerates.
@ kFunc
For functional parameters.
Base class responsible for handling of systematic error parameters. Capable of using PCA or using ada...
virtual void ProposeStep()
Generate a new proposed state.
void ThrowParProp(const double mag=1.)
Throw the proposed parameter by mag sigma. Should really just have the user specify this throw by hav...
double CalcLikelihood() const _noexcept_
Calc penalty term based on inverted covariance matrix.
Class responsible for handling of systematic error parameters with different types defined in the con...
SplineInterpolation GetParSplineInterpolation(const int i) const
Get interpolation type for a given parameter.
EW: As ParameterHandlerBase is an abstract base class we have to do some gymnastics to get it to get ...
Definition: parameters.cpp:12
SystType GetParamType(const int i) const
Returns enum describing our param type.
int GetNParameters() const
Get number of params which will be different depending if using Eigen decomposition or not.
std::string GetParSplineName(const int i) const
Get the name of the spline associated with the spline at index i.

◆ initPlotting()

void initPlotting ( py::module &  m)

Definition at line 15 of file plotting.cpp.

15  {
16 
17  auto m_plotting = m.def_submodule("plotting");
18  m_plotting.doc() = "This is a Python binding of MaCh3s C++ based plotting library.";
19 
20  py::class_<MaCh3Plotting::PlottingManager>(m_plotting, "PlottingManager")
21  .def(
22  py::init<const std::string &>(),
23  "construct a PlottingManager using the specified config file",
24  py::arg("config_file_name")
25  )
26 
27  .def(
28  py::init(),
29  "default constructor, will initialise the PlottingManager with the default plotting config"
30  )
31 
32  .def(
33  "initialise",
35  "initalise this PlottingManager"
36  )
37 
38  .def(
39  "usage",
41  "Print a usage message for the current executable"
42  )
43 
44  .def(
45  "parse_inputs",
47  "Parse command line variables",
48  py::arg("arguments")
49  )
50 
51  .def(
52  "set_exec",
54  "Set the name of the current executable, which will be used when getting executable specific options from the plotting config file",
55  py::arg("exec_name")
56  )
57 
58  .def(
59  "get_file_name",
61  "Get the path to a particular file",
62  py::arg("input_file_id")
63  )
64 
65  .def(
66  "get_file_label",
68  "Get the specified label of a particular input file",
69  py::arg("input_file_id")
70  )
71 
72  .def(
73  "get_draw_options",
75  "Get any additional root drawing options specified by the user"
76  )
77 
78  .def(
79  "get_output_name",
80  py::overload_cast<const std::string &>(&MaCh3Plotting::PlottingManager::getOutputName),
81  "Get the output name specified by the user, can specify an additional *suffix* to append to the file name but before the file extension",
82  py::arg("suffix") = ""
83  )
84 
85  .def(
86  "get_file_names",
88  "Get the list of all file names"
89  )
90 
91  .def(
92  "get_file_labels",
94  "Get the list of all file labels"
95  )
96 
97  .def(
98  "get_n_files",
100  "Get the number of specified files"
101  )
102 
103  .def(
104  "get_split_by_sample",
106  "Get whether or not the user has set the 'split by sample' (-s) option"
107  )
108 
109  .def(
110  "get_plot_ratios",
112  "Get whether or not the user specified the 'plot ratios' (-r) option"
113  )
114 
115  .def(
116  "get_draw_grid",
118  "Get wheter or not the user has specified the 'draw grid' (-g) option"
119  )
120 
121  .def(
122  "style",
123  &MaCh3Plotting::PlottingManager::style, py::return_value_policy::reference,
124  "Get the StyleManager associated with this PlottingManager"
125  )
126 
127  .def(
128  "input",
129  &MaCh3Plotting::PlottingManager::input, py::return_value_policy::reference,
130  "Get the InputManager associated with this PlottingManager"
131  )
132 
133  // EM: I can't figure out how to add the getOption methods as theres not really a way to deduce the return type from yaml so leaving them out for now :/
134  // I think one solution would be to extend the PlottingManager class inside of python (add a pyPlottingManager (or something like that) that derives
135  // from this one and add the functions to that) and then fold that python code into the module somehow. But that is currently beyond my pybinding abilities
136  ;
137 
138  py::class_<MaCh3Plotting::InputManager>(m_plotting, "InputManager")
139  .def(
140  "print",
142  "Print a summary of everything this manager knows"
143  )
144 
145  .def(
146  "get_llh_scan",
148  "Get the LLH scan for a particular parameter from a particular file",
149  py::arg("input_file_id"),
150  py::arg("param_name"),
151  py::arg("LLH_type") = "total"
152  )
153 
154  .def(
155  "get_llh_scan_by_sample",
157  "Get the LLH scan for a particular parameter from a particular file for a particular sample",
158  py::arg("input_file_id"),
159  py::arg("param"),
160  py::arg("sample")
161  )
162 
163  .def(
164  "get_enabled_llh",
166  "Get whether a particular file has LLH scans for a particular parameter",
167  py::arg("input_file_id"),
168  py::arg("param"),
169  py::arg("LLH_type") = "total"
170  )
171 
172  .def(
173  "get_enabled_llh_by_sample",
175  "Get whether a particular file has LLH scans for a particular parameter for a particular sample",
176  py::arg("input_file_id"),
177  py::arg("param"),
178  py::arg("sample")
179  )
180 
181  .def(
182  "get_post_fit_error",
184  "Get the post fit error for a parameter from a particular file",
185  py::arg("input_file_id"),
186  py::arg("param"),
187  py::arg("error_type") = ""
188  )
189 
190  .def(
191  "get_post_fit_value",
193  "Get the post fit value for a parameter from a particular file",
194  py::arg("input_file_id"),
195  py::arg("param"),
196  py::arg("error_type") = ""
197  )
198 
199  .def(
200  "get_known_parameters",
202  "Get all the parameters that this manager knows about. Useful for iterating over"
203  )
204 
205  .def(
206  "get_known_samples",
208  "Get all the samples that this manager knows about. Useful for iterating over"
209  )
210 
211  .def(
212  "get_tagged_parameters",
214  "Get all the parameters whose tags match some specified list",
215  py::arg("tags"),
216  py::arg("check_type") = "all"
217  )
218 
219  .def(
220  "get_tagged_samples",
222  "Get all the samples whose tags match some specified list",
223  py::arg("tags"),
224  py::arg("check_type") = "all"
225  )
226 
227  .def(
228  "get_n_input_files",
230  "Get the number of input files registered with this manager"
231  )
232 
233  .def(
234  "get_known_llh_parameters",
236  "Get all the parameters that a file has LLH scans for",
237  py::arg("file_id")
238  )
239 
240  .def(
241  "get_known_llh_samples",
243  "Get all the samples that a file has individual LLH scans for",
244  py::arg("file_id")
245  )
246 
247  .def(
248  "get_known_post_fit_parameters",
250  "Get all the parameters that a file has post fit values and errors for",
251  py::arg("file_id")
252  )
253 
254  .def(
255  "get_known_MCMC_parameters",
257  "Get all the parameters that a file has MCMC chain entries for",
258  py::arg("file_id")
259  )
260 
261  .def(
262  "get_known_1d_posterior_parameters",
264  "Get all the parameters that a file has processed 1d posteriors for",
265  py::arg("file_id")
266  )
267 
268  .def(
269  "get_MCMC_entry",
271  "Load up a particular step in the MCMC chain for a particular input file",
272  py::arg("file_id"),
273  py::arg("step")
274  )
275 
276  .def(
277  "get_MCMC_value",
279  "Get the value of a particular parameter for the current entry (set by set_MCMC_entry) in the chain for a particular file",
280  py::arg("file_id"),
281  py::arg("param")
282  )
283 
284  .def(
285  "get_n_MCMC_entries",
287  "Get the number of entries in the MCMC chain in a particular file"
288  )
289 
290  .def(
291  "get_1d_posterior",
293  "Get the 1d posterior for a particular parameter from a particular file",
294  py::arg("file_id"),
295  py::arg("param")
296  )
297 
298  ;
299 
300  py::class_<MaCh3Plotting::StyleManager>(m_plotting, "StyleManager")
301  .def(
302  "prettify_parameter_name",
304  "Convert internally used parameter name to a nice pretty name that can be used in plots",
305  py::arg("param")
306  )
307 
308  .def(
309  "prettify_sample_name",
311  "Convert internally used sample name to a nice pretty name that can be used in plots",
312  py::arg("sample")
313  )
314  ;
315 
316 }
const std::vector< std::string > & getKnownParameters() const
Definition: inputManager.h:471
std::vector< std::string > getTaggedSamples(const std::vector< std::string > &tags, std::string checkType="all") const
Get all samples which have some set of tags.
Definition: inputManager.h:493
const std::vector< std::string > & getKnownLLHParameters(int fileId) const
Definition: inputManager.h:504
void getMCMCentry(const int fileNum, const int entry) const
Get the MCMC chain entry in an InputFile.
Definition: inputManager.h:300
double getPostFitError(const int fileNum, const std::string &paramName, std::string errorType="") const
Get the post fit error for a particular parameter from a particular input file.
double getPostFitValue(const int fileNum, const std::string &paramName, std::string errorType="") const
Get the post fit value for a particular parameter from a particular input file.
std::vector< std::string > getTaggedParameters(const std::vector< std::string > &tags, std::string checkType="all") const
Get all parameters which have some set of tags.
Definition: inputManager.h:482
std::vector< std::vector< double > > getLLHScan(const int fileNum, const std::string &paramName, const std::string &LLHType) const
Get the log likelihood scan data for a particular parameter from a particular input file.
Definition: inputManager.h:287
const std::vector< std::string > & getKnownPostFitParameters(int fileId) const
Definition: inputManager.h:510
const std::vector< std::string > & getKnownLLHSamples(int fileId) const
Definition: inputManager.h:507
std::vector< std::vector< double > > get1dPosterior(const int fileNum, const std::string &paramName) const
Get the 1d posterior particular parameter from a particular input file.
Definition: inputManager.h:335
bool getEnabledLLHBySample(const int fileNum, const std::string &paramName, const std::string &sample) const
Get whether or not a particular parameter has an LLH scan in a particular input file for a particular...
Definition: inputManager.h:431
std::vector< std::vector< double > > getSampleSpecificLLHScan(const int fileNum, const std::string &paramName, const std::string &sample) const
Get the log likelihood scan for a particular parameter, for a specific sample, from a particular inpu...
Definition: inputManager.h:384
const std::vector< std::string > & getKnownSamples() const
Definition: inputManager.h:472
bool getEnabledLLH(const int fileNum, const std::string &paramName, std::string LLHType="total") const
Get whether or not a particular parameter has an LLH scan in a particular input file.
Definition: inputManager.h:420
double getMCMCvalue(int fileNum, std::string paramName) const
Get the parameter value for the current step for a particular parameter from a particular input file.
Definition: inputManager.h:320
int getnMCMCentries(const int fileNum) const
Get the number of entries in the MCMC chain in a particular file.
Definition: inputManager.h:347
size_t getNInputFiles() const
Definition: inputManager.h:473
const std::vector< std::string > & getKnown1dPosteriorParameters(int fileId) const
Definition: inputManager.h:516
void print(const std::string &printLevel="summary") const
Print out what this Inputmanager instance knows about.
const std::vector< std::string > & getKnownMCMCParameters(int fileId) const
Definition: inputManager.h:513
const std::string getFileName(int i) const
void initialise()
initalise this PlottingManager.
void setExec(const std::string &execName)
Internally set the name of the executable that manager is being used in.
void parseInputsVec(std::vector< std::string > argv)
Parse vector of command line arguments.
const std::string getFileLabel(int i) const
const InputManager & input() const
Get the InputManager contained within this PlottingManager, for doing input related things.
const std::string getOutputName() const
Get the straight up output file name with no bells or whistles, just the file extension.
void usage()
Print a usage message for the current executable.
const StyleManager & style() const
Get the StyleManager contained within this PlottingManager, for doing style related things.
const std::vector< std::string > getFileNames() const
const std::string getDrawOptions() const
const std::vector< std::string > getFileLabels() const
std::string prettifyParamName(const std::string &origName) const
Convert hideous and vulgar internal parameter name into a beautiful presentable name.
Definition: styleManager.h:39

◆ initSamples()

void initSamples ( py::module &  m)

Definition at line 196 of file samples.cpp.

196  {
197 
198  auto m_samples = m.def_submodule("samples");
199  m_samples.doc() =
200  "This is a Python binding of MaCh3s C++ based samples library.";
201 
202  // Bind the systematic type enum that lets us set different types of systematics
203  py::enum_<TestStatistic>(m_samples, "TestStatistic")
204  .value("Poisson", TestStatistic::kPoisson)
205  .value("Barlow_Beeston", TestStatistic::kBarlowBeeston)
206  .value("Ice_Cube", TestStatistic::kIceCube)
207  .value("Pearson", TestStatistic::kPearson)
208  .value("Dembinski_Abdelmottele", TestStatistic::kDembinskiAbdelmotteleb)
209  .value("N_Test_Statistics", TestStatistic::kNTestStatistics);
210 
211  py::class_<SampleHandlerBase, PySampleHandlerBase /* <--- trampoline*/>(m_samples, "SampleHandlerBase")
212  .def(py::init())
213 
214  .def(
215  "reweight",
217  "reweight the MC events in this sample. You will need to override this."
218  )
219 
220  .def(
221  "get_likelihood",
223  "Get the sample likelihood at the current point in your model space. You will need to override this."
224  )
225 
226  .def(
227  "set_test_stat",
229  "Set the test statistic that should be used when calculating likelihoods. \n\
230  :param test_stat: The new test statistic to use",
231  py::arg("test_stat")
232  )
233 
234  .def(
235  "get_bin_LLH",
236  py::overload_cast<double, double, double>(&SampleHandlerBase::GetTestStatLLH, py::const_),
237  "Get the LLH for a bin by comparing the data and MC. The result depends on having previously set the test statistic using :py:meth:`pyMaCh3.samples.SampleHandlerBase.set_test_stat` \n\
238  :param data: The data content of the bin. \n\
239  :param mc: The mc content of the bin \n\
240  :param w2: The Sum(w_{i}^2) (sum of weights squared) in the bin, which is sigma^2_{MC stats}",
241  py::arg("data"),
242  py::arg("mc"),
243  py::arg("w2")
244  )
245  ; // End of SampleHandlerBase binding
246 
247  py::class_<SampleHandlerFD, PySampleHandlerFD /* <--- trampoline*/, SampleHandlerBase>(m_samples, "SampleHandlerFD")
248  .def(
249  py::init<std::string, ParameterHandlerGeneric*>(),
250  "This should never be called directly as SampleHandlerFD is an abstract base class. \n\
251  However when creating a derived class, in the __init__() method, you should call the parent constructor i.e. this one by doing:: \n\
252  \n\
253  \tsuper(<your derived SampleHandler class>, self).__init__(*args) \n\
254  \n ",
255  py::arg("mc_version"),
256  py::arg("xsec_cov")
257  )
258  ;
259 
260  /* Not sure if this will be needed in future versions of MaCh3 so leaving commented for now
261  py::class_<fdmc_base>(m_samples, "MCstruct")
262  .def(py::init())
263 
264  // Because a lot of the variables in fdmc_base use c style arrays,
265  // we need to provide some setter functions to be able to set them using more
266  // "pythony" objects, e.g. lists and numpy arrays
267  .def(
268  "set_event_variable_values",
269  [](fdmc_base &self, int dim, py::array_t<double, py::array::c_style> &array)
270  {
271  py::buffer_info bufInfo = array.request();
272 
273  if ( dim > 2 )
274  throw MaCh3Exception(__FILE__, __LINE__, "Currently only dimensions of 1 or 2 are supported sorry :(");
275 
276  if ( bufInfo.ndim != 1 )
277  throw MaCh3Exception(__FILE__, __LINE__, "Number of dimensions in parameter array must be one if setting only one of the event variable arrays!");
278 
279  if( dim ==1 )
280  self.x_var = array.data();
281 
282  else if ( dim == 2)
283  self.y_var = array.data();
284  }
285  )
286  ;
287  */
288 }
@ kNTestStatistics
Number of test statistics.
@ kPearson
Standard Pearson likelihood .
@ kBarlowBeeston
Barlow-Beeston () following Conway approximation ()
@ kIceCube
Based on .
@ kDembinskiAbdelmotteleb
Based on .
@ kPoisson
Standard Poisson likelihood .
EW: As SampleHandlerBase is an abstract base class we have to do some gymnastics to get it to get it ...
Definition: samples.cpp:10
As SampleHandlerFD is an abstract base class we have to do some gymnastics to get it to get it into p...
Definition: samples.cpp:56
Class responsible for handling implementation of samples used in analysis, reweighting and returning ...
virtual void Reweight()=0
Class responsible for handling implementation of samples used in analysis, reweighting and returning ...
void SetTestStatistic(TestStatistic testStat)
Set the test statistic to be used when calculating the binned likelihoods.
double GetTestStatLLH(const double data, const double mc, const double w2) const
Calculate test statistic for a single bin. Calculation depends on setting of fTestStatistic....
virtual double GetLikelihood()=0

◆ initSplines()

void initSplines ( py::module &  m)

Definition at line 72 of file splines.cpp.

72  {
73 
74  auto m_splines = m.def_submodule("splines");
75  m_splines.doc() =
76  "This is a Python binding of MaCh3s C++ based spline library.";
77 
78  // Bind the interpolation type enum that lets us set different interpolation types for our splines
79  py::enum_<SplineInterpolation>(m_splines, "InterpolationType")
80  .value("Linear", SplineInterpolation::kLinear, "Linear interpolation between the knots")
81  .value("Linear_Func", SplineInterpolation::kLinearFunc, "Same as 'Linear'")
82  .value("Cubic_TSpline3", SplineInterpolation::kTSpline3, "Use same coefficients as `ROOT's TSpline3 <https://root.cern.ch/doc/master/classTSpline3.html>`_ implementation")
83  .value("Cubic_Monotonic", SplineInterpolation::kMonotonic, "Coefficients are calculated such that the segments between knots are forced to be monotonic. The implementation we use is based on `this method <https://www.jstor.org/stable/2156610>`_ by Fritsch and Carlson.")
84  .value("Cubic_Akima", SplineInterpolation::kAkima, "The second derivative is not required to be continuous at the knots. This means that these splines are useful if the second derivative is rapidly varying. The implementation we used is based on `this paper <http://www.leg.ufpr.br/lib/exe/fetch.php/wiki:internas:biblioteca:akima.pdf>`_ by Akima.")
85  .value("N_Interpolation_Types", SplineInterpolation::kSplineInterpolations, "This is only to be used when iterating and is not a valid interpolation type.");
86 
87 
88  py::class_<SplineBase, PySplineBase /* <--- trampoline*/>(m_splines, "SplineBase");
89 
90  py::class_<TResponseFunction_red>(m_splines, "_ResponseFunctionBase")
91  .doc() = "Base class of the response function, this binding only exists for consistency with the inheritance structure of the c++ code. Just pretend it doesn't exist and don't worry about it...";
92 
93  // Bind the TSpline3_red class. Decided to go with a clearer name of ResponseFunction for the python binding
94  // and make the interface a bit more python-y. Additionally remove passing root stuff so we don't need to deal
95  // with root python binding and can just pass it native python objects.
96  py::class_<TSpline3_red, TResponseFunction_red, std::unique_ptr<TSpline3_red, py::nodelete>>(m_splines, "ResponseFunction")
97  .def(
98  // define a more python friendly constructor that massages the inputs and passes them
99  // through to the c++ constructor
100  py::init
101  (
102  // Just take in some vectors, then build a TSpline3 and pass this to the constructor
103  [](std::vector<double> &xVals, std::vector<double> &yVals, SplineInterpolation interpType)
104  {
105  if ( xVals.size() != yVals.size() )
106  {
107  throw MaCh3Exception(__FILE__, __LINE__, "Different number of x values and y values!");
108  }
109 
110  int length = int(xVals.size());
111 
112  if (length == 1)
113  {
114  M3::float_t xKnot = M3::float_t(xVals[0]);
115  M3::float_t yKnot = M3::float_t(yVals[0]);
116 
117  std::vector<M3::float_t *> pars;
118  pars.resize(3);
119  pars[0] = new M3::float_t(0.0);
120  pars[1] = new M3::float_t(0.0);
121  pars[2] = new M3::float_t(0.0);
122  delete pars[0];
123  delete pars[1];
124  delete pars[2];
125 
126  return new TSpline3_red(&xKnot, &yKnot, 1, pars.data());
127  }
128 
129  TSpline3 *splineTmp = new TSpline3( "spline_tmp", xVals.data(), yVals.data(), length );
130  return new TSpline3_red(splineTmp, interpType);
131  }
132  )
133  )
134 
135  .def(
136  "find_segment",
138  "Find the segment that a particular *value* lies in. \n"
139  ":param value: The value to test",
140  py::arg("value")
141  )
142 
143  .def(
144  "evaluate",
146  "Evaluate the response function at a particular *value*. \n"
147  ":param value: The value to evaluate at.",
148  py::arg("value")
149  )
150  ; // End of binding for ResponseFunction
151 
152  py::class_<SMonolith, SplineBase>(m_splines, "EventSplineMonolith")
153  .def(
154  py::init(
155  [](std::vector<std::vector<TResponseFunction_red*>> &responseFns, const bool saveFlatTree)
156  {
157  std::vector<RespFuncType> respFnTypes;
158  for(uint i = 0; i < responseFns[0].size(); i++)
159  {
160  // ** WARNING **
161  // Right now I'm only pushing back TSpline3_reds as that's all that's supported right now
162  // In the future there might be more
163  // I think what would be best to do would be to store the interpolation type somehow in the ResponseFunction objects
164  // then just read them here and pass through to the constructor
165  respFnTypes.push_back(RespFuncType::kTSpline3_red);
166  }
167  return new SMonolith(responseFns, respFnTypes, saveFlatTree);
168  }
169  ),
170  "Create an EventSplineMonolith \n"
171  ":param master_splines: These are the 'knot' values to make splines from. This should be an P x E 2D list where P is the number of parameters and E is the number of events. \n"
172  ":param save_flat_tree: Whether we want to save monolith into speedy flat tree",
173  py::arg("master_splines"),
174  py::arg("save_flat_tree") = false
175  )
176 
177  .def(
178  py::init<std::string>(),
179  "Constructor where you pass path to preprocessed root FileName which is generated by creating an EventSplineMonolith with the `save_flat_tree` flag set to True. \n"
180  ":param file_name: The name of the file to read from.",
181  py::arg("file_name")
182  )
183 
184  .def(
185  "evaluate",
187  "Evaluate the splines at their current values."
188  )
189 
190  .def(
191  "sync_mem_transfer",
193  "This is important when running on GPU. After calculations are done on GPU we copy memory to CPU. This operation is asynchronous meaning while memory is being copied some operations are being carried. Memory must be copied before actual reweight. This function make sure all has been copied."
194  )
195 
196  .def(
197  "get_event_weight",
199  py::return_value_policy::reference,
200  "Get the weight of a particular event. \n"
201  ":param event: The index of the event whose weight you would like.",
202  py::arg("event")
203  )
204 
205  .def(
206  "set_param_value_array",
207  // Wrap up the setSplinePointers method so that we can take in a numpy array and get
208  // pointers to it's sweet sweet data and use those pointers in the splineMonolith
209  [](SMonolith &self, py::array_t<double, py::array::c_style> &array)
210  {
211  py::buffer_info bufInfo = array.request();
212 
213  if ( bufInfo.ndim != 1)
214  {
215  throw MaCh3Exception(__FILE__, __LINE__, "Number of dimensions in parameter array must be one!");
216  }
217 
218  if ( bufInfo.shape[0] != self.GetNParams() )
219  {
220  throw MaCh3Exception(__FILE__, __LINE__, "Number of entries in parameter array must equal the number of parameters!");
221  }
222 
223  std::vector<const double *> paramVec;
224  paramVec.resize(self.GetNParams());
225 
226  for( int idx = 0; idx < self.GetNParams(); idx++ )
227  {
228  // booooo pointer arithmetic
229  paramVec[idx] = array.data() + idx;
230  }
231 
232  self.setSplinePointers(paramVec);
233  },
234  "Set the array that the monolith should use to read parameter values from. \n"
235  "Usage of this might vary a bit from what you're used to in python. \n"
236  "Rather than just setting the values here, what you're really doing is setting pointers in the underlying c++ code. \n"
237  "What that means is that you pass an array to this function like:: \n"
238  "\n event_spline_monolith_instance.set_param_value_array(array) \n\n"
239  "Then when you set values in that array as normal, they will also be updated inside of the event_spline_monolith_instance.",
240  py::arg("array")
241 
242  )
243 
244  .doc() = "This 'monolith' deals with event by event weighting using splines."
245 
246  ; // End of binding for EventSplineMonolith
247 }
SplineInterpolation
Make an enum of the spline interpolation type.
@ kTSpline3
Default TSpline3 interpolation.
@ kMonotonic
EM: DOES NOT make the entire spline monotonic, only the segments.
@ kSplineInterpolations
This only enumerates.
@ kLinear
Linear interpolation between knots.
@ kLinearFunc
Liner interpolation using TF1 not spline.
@ kAkima
EM: Akima spline iis allowed to be discontinuous in 2nd derivative and coefficients in any segment.
@ kTSpline3_red
Uses TSpline3_red for interpolation.
Custom exception class for MaCh3 errors.
EW: As SplineBase is an abstract base class we have to do some gymnastics to get it to get it into py...
Definition: splines.cpp:19
Even-by-event class calculating response for spline parameters. It is possible to use GPU acceleratio...
void Evaluate() override
CW: This Eval should be used when using two separate x,{y,a,b,c,d} arrays to store the weights; proba...
void SynchroniseMemTransfer()
KS: After calculations are done on GPU we copy memory to CPU. This operation is asynchronous meaning ...
const float * retPointer(const int event)
KS: Get pointer to total weight to make fit faster wrooom!
Base class for calculating weight from spline.
Definition: SplineBase.h:25
CW: Reduced TSpline3 class.
double Eval(double var) override
CW: Evaluate the weight from a variation.
int FindX(double x)
Find the segment relevant to this variation in x.
double float_t
Definition: Core.h:30

◆ PYBIND11_MODULE()

PYBIND11_MODULE ( _pyMaCh3  ,
 
)

Definition at line 16 of file pyMaCh3.cpp.

16  {
17  initPlotting(m);
18  initFitters(m);
19  initSamples(m);
20  initManager(m);
21  initParameters(m);
22  initSplines(m);
23 }
void initFitters(py::module &)
Definition: fitters.cpp:47
void initParameters(py::module &)
Definition: parameters.cpp:38
void initSplines(py::module &)
Definition: splines.cpp:72
void initManager(py::module &)
Definition: manager.cpp:11
void initSamples(py::module &)
Definition: samples.cpp:196
void initPlotting(py::module &)
Definition: plotting.cpp:15