MaCh3 2.2.1
Reference Guide
Loading...
Searching...
No Matches
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 55 of file fitters.cpp.

55 {
56
57 auto m_fitters = m.def_submodule("fitters");
58 m_fitters.doc() =
59 "This is a Python binding of MaCh3s C++ fitters library.";
60
61
62 py::class_<FitterBase, PyFitterBase /* <--- trampoline*/>(m_fitters, "FitterBase")
63 .def(py::init<manager* const>())
64
65 .def(
66 "run",
68 "The implementation of the fitter, you should override this with your own desired fitting algorithm"
69 )
70
71 .def(
72 "get_name",
74 " The name of the algorithm, you should override this with something like:: \n"
75 "\n"
76 " return 'mySuperCoolAlgoName' \n"
77 )
78
79 .def(
80 "run_LLH_scan",
82 "Perform a 1D likelihood scan"
83 )
84
85 .def(
86 "get_step_scale_from_LLH_scan",
88 "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"
89 )
90
91 .def(
92 "run_2d_LLH_scan",
94 " Perform a 2D likelihood scan. \n"
95 " :param warning: This operation may take a significant amount of time, especially for complex models."
96 )
97
98 .def(
99 "run_sigma_var",
101 " Perform a 2D and 1D sigma var for all samples. \n"
102 " :param warning: Code uses TH2Poly"
103 )
104
105 .def(
106 "drag_race",
108 " Calculates the required time for each sample or covariance object in a drag race simulation. Inspired by Dan's feature \n"
109 " :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",
110 py::arg("NLaps") = 100
111 )
112
113 // stuff for registering other objects with the fitter
114
115 .def(
116 "add_sample_handler",
118 " 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"
119 " :param sample: A sample handler object derived from SampleHandlerBase. ",
120 py::arg("sample")
121 )
122
123 .def(
124 "add_syst_object",
126 " This function adds a Covariance object to the analysis framework. The Covariance object will be utilized in fitting procedures or likelihood scans. \n"
127 " :param cov: A Covariance object derived from ParameterHandlerBase. ",
128 py::arg("cov")
129 )
130
131 ; // End of FitterBase class binding
132
133 py::class_<mcmc, FitterBase>(m_fitters, "MCMC")
134 .def(py::init<manager* const>())
135
136 .def(
137 "set_chain_length",
139 "Set how long chain should be.",
140 py::arg("length")
141 )
142 ; // end of MCMC class binding
143
144 py::class_<LikelihoodFit, PyLikelihoodFit /* <--- trampoline*/, FitterBase>(m_fitters, "LikelihoodFit")
145 .def(py::init<manager* const>())
146
147 .def(
148 "caluclate_chi2",
149 [](LikelihoodFit &self, const std::vector<double> &parameterVals)
150 {
151 return self.CalcChi2(parameterVals.data());
152 },
153 "Get the Chi2 calculation over all included samples and syst objects for the specified parameter_values \n\
154 :param parameter_valuse: The location to evaluate the chi2 at.",
155 py::arg("parameter_values")
156 )
157
158 .def(
159 "get_n_params",
161 "Get The total number of parameters across all known covariance objects associated with this LikelihoodFit object."
162 )
163 ; // end of LikelihoodFit class binding
164
165 py::class_<MinuitFit, LikelihoodFit>(m_fitters, "MinuitFit")
166 .def(py::init<manager* const>())
167
168 ; // end of MinuitFit class binding
169
170 py::class_<PSO, LikelihoodFit>(m_fitters, "PSO")
171 .def(py::init<manager* const>())
172
173 .def(
174 "init",
175 &PSO::init,
176 "Initialise the fitter"
177 )
178
179 ; // end of PSO class binding
180
181}
Base class for implementing fitting algorithms.
Definition: FitterBase.h:23
void RunLLHScan()
Perform a 1D likelihood scan.
Definition: FitterBase.cpp:507
void AddSystObj(ParameterHandlerBase *cov)
This function adds a Covariance object to the analysis framework. The Covariance object will be utili...
Definition: FitterBase.cpp:267
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:246
virtual std::string GetName() const
Get name of class.
Definition: FitterBase.h:66
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:817
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:409
void Run2DLLHScan()
Perform a 2D likelihood scan.
Definition: FitterBase.cpp:866
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
virtual double CalcChi2(const double *x)
Chi2 calculation over all included samples and syst objects.
void init()
Definition: PSO.cpp:50
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:13
EW: As LikelihoodFit is an abstract base class we have to do some gymnastics to get it to get it into...
Definition: fitters.cpp:39
void setChainLength(unsigned int L)
Set how long chain should be.
Definition: mcmc.h:19

◆ 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",
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}
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.
const std::vector< double > & GetParPropVec()
Get a reference to the proposed parameter values Can be useful if you want to track these without hav...
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
std::string GetParName(const int i) const
Get name of parameter.
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 GetParFancyName(const int i) const
Get fancy name of the Parameter.
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}
double getPostFitError(int fileNum, const std::string &paramName, std::string errorType="") const
Get the post fit error for a particular parameter from a particular input file.
bool getEnabledLLH(int fileNum, 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:418
const std::vector< std::string > & getKnown1dPosteriorParameters(int fileId) const
Definition: inputManager.h:514
const std::vector< std::string > & getKnownLLHSamples(int fileId) const
Definition: inputManager.h:505
const std::vector< std::string > & getKnownMCMCParameters(int fileId) const
Definition: inputManager.h:511
const std::vector< std::string > & getKnownPostFitParameters(int fileId) const
Definition: inputManager.h:508
std::vector< std::vector< double > > getSampleSpecificLLHScan(int fileNum, std::string paramName, std::string sample) const
Get the log likelihood scan for a particular parameter, for a specific sample, from a particular inpu...
Definition: inputManager.h:382
void getMCMCentry(int fileNum, int entry) const
Get the MCMC chain entry in an InputFile.
Definition: inputManager.h:298
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:480
std::vector< std::vector< double > > getLLHScan(int fileNum, std::string paramName, std::string LLHType) const
Get the log likelihood scan data for a particular parameter from a particular input file.
Definition: inputManager.h:285
int getnMCMCentries(int fileNum) const
Get the number of entries in the MCMC chain in a particular file.
Definition: inputManager.h:345
const std::vector< std::string > & getKnownSamples() const
Definition: inputManager.h:470
std::vector< std::vector< double > > get1dPosterior(int fileNum, std::string paramName) const
Get the 1d posterior particular parameter from a particular input file.
Definition: inputManager.h:333
const std::vector< std::string > & getKnownLLHParameters(int fileId) const
Definition: inputManager.h:502
const std::vector< std::string > & getKnownParameters() const
Definition: inputManager.h:469
double getPostFitValue(int fileNum, const std::string &paramName, std::string errorType="") const
Get the post fit value for a particular parameter from a particular input file.
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:318
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:491
bool getEnabledLLHBySample(int fileNum, std::string paramName, 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:429
size_t getNInputFiles() const
Definition: inputManager.h:471
void print(const std::string &printLevel="summary") const
Print out what this Inputmanager instance knows about.
const std::string getOutputName()
Get the straight up output file name with no bells or whistles, just the file extension.
void initialise()
initalise this PlottingManager.
void parseInputsVec(std::vector< std::string > argv)
Parse vector of command line arguments.
void setExec(std::string execName)
Internally set the name of the executable that manager is being used in.
const std::vector< std::string > getFileNames()
void usage()
Print a usage message for the current executable.
const std::string getFileName(int i)
const std::vector< std::string > getFileLabels()
const std::string getDrawOptions()
const std::string getFileLabel(int i)
const StyleManager & style()
Get the StyleManager contained within this PlottingManager, for doing style related things.
const InputManager & input()
Get the InputManager contained within this PlottingManager, for doing input related things.
std::string prettifyParamName(const std::string &origName) const
Convert hideous and vulgar internal parameter name into a beautiful presentable name.
Definition: styleManager.h:44

◆ 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.
virtual double GetLikelihood()=0
double GetTestStatLLH(double data, double mc) const
Calculate test statistic for a single bin using Poisson.

◆ 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 setSplinePointers(std::vector< const double * > spline_ParsPointers)
KS: Set pointers to spline params.
const float * retPointer(const int event)
KS: Get pointer to total weight to make fit faster wrooom!
void SynchroniseMemTransfer()
KS: After calculations are done on GPU we copy memory to CPU. This operation is asynchronous meaning ...
Base class for calculating weight from spline.
Definition: SplineBase.h:25
short int GetNParams() const
Get number of spline parameters.
Definition: SplineBase.h:39
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 See root/hist/hist/src/TSpline3FindX(double) or samp...
double float_t
Definition: Core.h:28

◆ 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);
22 initSplines(m);
23}
void initFitters(py::module &)
Definition: fitters.cpp:55
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