MaCh3  2.8.0
Reference Guide
NuDockServerBase.cpp
Go to the documentation of this file.
1 #include "NuDockServerBase.h"
3 
4 // ***************************************************************************
6 // ***************************************************************************
8 }
9 
10 // ***************************************************************************
12 // ***************************************************************************
14 }
15 
16 // ***************************************************************************
18 // ***************************************************************************
20  // Resize the likelihood storage vectors
21  syst_llh.resize(systematics.size(), M3::_BAD_DOUBLE_);
22  sample_llh.resize(samples.size(), M3::_BAD_DOUBLE_);
23  verbose = GetFromManager(fitMan->raw()["NuDock"]["Verbose"], false, __FILE__, __LINE__);
24  add_prior_llh = GetFromManager(fitMan->raw()["NuDock"]["AddPriorLLH"], false, __FILE__, __LINE__);
25 }
26 
27 // ***************************************************************************
29 // ***************************************************************************
31  // HH: Based on MR2T2::ProposeStep()
32  // Initial likelihood
33  double llh = 0.0;
34 
35  if (add_prior_llh) {
36  // Loop over the systematics and propose the initial step
37  for (size_t s = 0; s < systematics.size(); ++s) {
38  // Get the likelihood from the systematics
39  syst_llh[s] = systematics[s]->GetLikelihood();
40  if (verbose) MACH3LOG_INFO("Syst {} llh: {}", systematics[s]->GetName(), syst_llh[s]);
41  llh += syst_llh[s];
42 
43  if (verbose) MACH3LOG_INFO("LLH after {} {}", systematics[s]->GetName(), llh);
44  }
45  }
46 
47  // DB for atmospheric event by event sample migration, need to fully reweight all samples to allow event passing prior to likelihood evaluation
48  for (size_t i = 0; i < samples.size(); ++i) {
49  // Get the sample likelihoods and add them
50  sample_llh[i] = samples[i]->GetLikelihood();
51  if (verbose) {
52  MACH3LOG_INFO("Total LLH in sample handler {}: {}", i, sample_llh[i]);
53  for (int iSample = 0; iSample < samples[i]->GetNSamples(); ++iSample) {
54  double sample_llh_ind = samples[i]->GetSampleLikelihood(iSample);
55  MACH3LOG_INFO(" Sample {} llh: {}", samples[i]->GetSampleTitle(iSample), sample_llh_ind);
56  }
57  }
58  llh += sample_llh[i];
59  if (verbose) MACH3LOG_INFO("LLH after sample {} {}", i, llh); }
60 
61  return llh;
62 }
63 
64 // ***************************************************************************
66 // ***************************************************************************
67 nlohmann::json NuDockServerBase::setParameters(const nlohmann::json &request) {
68  if (verbose) {
69  MACH3LOG_INFO("Setting parameters from NuDock request: {}", request.dump());
70  }
71  std::map<std::string, double> syst_params = request["sys_pars"].get<std::map<std::string, double>>();
72  std::map<std::string, double> osc_params = request["osc_pars"].get<std::map<std::string, double>>();
73  // Loop over systematic objects
74  for (size_t s = 0; s < systematics.size(); ++s) {
75  int npars = systematics[s]->GetNumParams();
76  // Loop over each parameter in the systematics object
77  for (int p = 0; p < npars; ++p) {
78  std::string param_name = systematics[s]->GetParFancyName(p);
79  // Check if this is an oscillation parameter
80  if (NuDockOscNameMap_r.find(param_name) != NuDockOscNameMap_r.end()) {
81  std::string param_name_nudock = NuDockOscNameMap_r.at(param_name);
82  // Check if it exists in the request
83  if (osc_params.find(param_name_nudock) != osc_params.end()) {
84  double param_value = osc_params[param_name_nudock];
85  FormatOscParsForMaCh3(param_name_nudock, param_value);
86  systematics[s]->SetParCurrProp(p, param_value);
87  if (verbose) MACH3LOG_INFO("Setting osc param {} to value {}", param_name, param_value);
88  } else {
89  MACH3LOG_WARN("Oscillation parameter {} not found in request", param_name);
90  }
91  } else {
92  if (!systematics[s]->IsParameterFixed(p)) {
93  // Non-oscillation parameter
94  // Check if it exists in the request
95  if (syst_params.find(param_name) != syst_params.end()) {
96  double param_value = syst_params[param_name];
97  systematics[s]->SetParCurrProp(p, param_value);
98  if (verbose) MACH3LOG_INFO("Setting syst param {} to value {}", param_name, param_value);
99  } else {
100  MACH3LOG_WARN("Systematic parameter {} not found in request", param_name);
101  }
102  }
103  }
104  }
105  }
106  // HH: Reweights here is probably a better idea than getLikelihood, thanks to Jude
107  for (size_t i = 0; i < samples.size(); ++i) {
108  samples[i]->Reweight();
109  }
110 
111  nlohmann::json response;
112  response["status"] = "success";
113  return response;
114 }
115 
116 // ***************************************************************************
118 // ***************************************************************************
119 nlohmann::json NuDockServerBase::setAsimovPoint([[maybe_unused]] const nlohmann::json &request) {
120  // reweight sample and add to data
121  for (size_t ipdf=0; ipdf<samples.size(); ipdf++) {
122  samples[ipdf]->Reweight();
123  auto* base_casted_sample = dynamic_cast<SampleHandlerBase*>(samples[ipdf]);
124  if(!base_casted_sample) {
125  MACH3LOG_ERROR("Sample object does not derive from SampleHandlerBase. Consider overloading {} for this sample type.", __func__);
126  throw MaCh3Exception(__FILE__,__LINE__);
127  }
128  for (int iSample = 0; iSample < samples[ipdf]->GetNSamples(); ++iSample) {
129  base_casted_sample->AddData(iSample, base_casted_sample->GetMCArray(iSample));
130  }
131  }
132 
133  // set prefit parameter values to the current parameter values
134  for (size_t s = 0; s < systematics.size(); ++s) {
135  int npars = systematics[s]->GetNumParams();
136  for (int p = 0; p < npars; ++p) {
137  std::string param_name = systematics[s]->GetParFancyName(p);
138  double param_value = systematics[s]->GetParCurr(p);
139  systematics[s]->SetPar(p, param_value);
140  if (verbose) MACH3LOG_INFO("Setting prefit param {} to current value {}", param_name, param_value);
141  }
142  }
143 
144  nlohmann::json response;
145  response["status"] = "success";
146  return response;
147 }
148 // ***************************************************************************
149 void TH1toResponse(const TH1* mc_hist, const std::string& sample_title, nlohmann::json &response) {
150 // ***************************************************************************
151  auto hist1d = dynamic_cast<const TH1D*>(mc_hist);
152  if (!hist1d) {
153  MACH3LOG_ERROR("{}: input histogram is not TH1D", __func__);
154  throw MaCh3Exception(__FILE__,__LINE__);
155  }
156  const TAxis *ax = mc_hist->GetXaxis();
157  std::string xtitle = ax->GetTitle();
158  int nxbins = ax->GetNbins();
159  std::vector<double> xbins(nxbins+1);
160  std::vector<double> binvals(nxbins);
161 
162  xbins[0] = ax->GetBinLowEdge(1);
163  for (int ix = 1; ix <= nxbins; ++ix) {
164  xbins[ix] = ax->GetBinUpEdge(ix);
165  binvals[ix-1] = mc_hist->GetBinContent(ix);
166  }
167  response["axis_titles"][sample_title] = {xtitle};
168  response["bin_edges"][sample_title] = {xbins};
169  response["bin_values"][sample_title] = binvals;
170 }
171 
172 // ***************************************************************************
173 void TH2toResponse(const TH2* mc_hist, const std::string& sample_title, nlohmann::json &response) {
174 // ***************************************************************************
175  auto hist2d = dynamic_cast<const TH2D*>(mc_hist);
176  if (!hist2d) {
177  MACH3LOG_ERROR("{}: input histogram is not TH2D", __func__);
178  throw MaCh3Exception(__FILE__,__LINE__);
179  }
180  const TAxis *x_axis = mc_hist->GetXaxis();
181  std::string xtitle = x_axis->GetTitle();
182  int nxbins = x_axis->GetNbins();
183  std::vector<double> xbins(nxbins+1);
184 
185  const TAxis *y_axis = mc_hist->GetYaxis();
186  std::string ytitle = y_axis->GetTitle();
187  int nybins = y_axis->GetNbins();
188  std::vector<double> ybins(nybins+1);
189 
190  std::vector<std::vector<double>> binvals(nxbins, std::vector<double>(nybins));
191 
192  xbins[0] = x_axis->GetBinLowEdge(1);
193  ybins[0] = y_axis->GetBinLowEdge(1);
194  for (int ix = 1; ix <= nxbins; ++ix) {
195  for (int iy = 1; iy <= nybins; ++iy) {
196  xbins[ix] = x_axis->GetBinUpEdge(ix);
197  ybins[iy] = y_axis->GetBinUpEdge(iy);
198  binvals[ix-1][iy-1] = mc_hist->GetBinContent(ix, iy);
199  }
200  }
201  response["axis_titles"][sample_title] = {xtitle, ytitle};
202  response["bin_edges"][sample_title] = {xbins, ybins};
203  response["bin_values"][sample_title] = binvals;
204 }
205 
206 // ***************************************************************************
208 // ***************************************************************************
209 nlohmann::json NuDockServerBase::getMCSpectrum([[maybe_unused]] const nlohmann::json &request) {
210  nlohmann::json response;
211 
212  std::vector<std::string> sample_titles = {};
213 
214  for (size_t ipdf=0; ipdf<samples.size(); ipdf++) {
215  auto* base_casted_sample = dynamic_cast<SampleHandlerBase*>(samples[ipdf]);
216  if(!base_casted_sample) {
217  MACH3LOG_ERROR("Sample object does not derive from SampleHandlerBase. Consider overloading {} for this sample type.", __func__);
218  throw MaCh3Exception(__FILE__,__LINE__);
219  }
220  for (int iSample = 0; iSample < samples[ipdf]->GetNSamples(); ++iSample) {
221  std::string sample_title = samples[ipdf]->GetSampleTitle(iSample);
222  sample_titles.push_back(sample_title);
223 
224  int dimension = samples[ipdf]->GetNDim(iSample);
225  response["dimensions"][sample_title] = dimension;
226 
227  if (dimension == 1) {
228  TH1toResponse(samples[ipdf]->GetMCHist(iSample), sample_title, response);
229  } else if (dimension == 2) {
230  TH2toResponse(static_cast<const TH2*>(samples[ipdf]->GetMCHist(iSample)), sample_title, response);
231  } else {
232  MACH3LOG_ERROR("Not implemented for dim =", dimension);
233  throw MaCh3Exception(__FILE__,__LINE__);
234  }
235  }
236  }
237  response["sample_names"] = sample_titles;
238  return response;
239 }
240 
241 // ***************************************************************************
243 // ***************************************************************************
244 nlohmann::json NuDockServerBase::getDataSpectrum([[maybe_unused]] const nlohmann::json &request) {
245  nlohmann::json response;
246 
247  std::vector<std::string> sample_titles = {};
248 
249  for (size_t ipdf=0; ipdf<samples.size(); ipdf++) {
250  auto* base_casted_sample = dynamic_cast<SampleHandlerBase*>(samples[ipdf]);
251  if(!base_casted_sample) {
252  MACH3LOG_ERROR("Sample object does not derive from SampleHandlerBase. Consider overloading {} for this sample type.", __func__);
253  throw MaCh3Exception(__FILE__,__LINE__);
254  }
255  for (int iSample = 0; iSample < samples[ipdf]->GetNSamples(); ++iSample) {
256  std::string sample_title = samples[ipdf]->GetSampleTitle(iSample);
257  sample_titles.push_back(sample_title);
258 
259  int dimension = samples[ipdf]->GetNDim(iSample);
260  response["dimensions"][sample_title] = dimension;
261 
262  if (dimension == 1) {
263  TH1toResponse(samples[ipdf]->GetDataHist(iSample), sample_title, response);
264  } else if (dimension == 2) {
265  TH2toResponse(static_cast<const TH2*>(samples[ipdf]->GetDataHist(iSample)), sample_title, response);
266  } else {
267  MACH3LOG_ERROR("Not implemented for dim =", dimension);
268  throw MaCh3Exception(__FILE__,__LINE__);
269  }
270  }
271  }
272  response["sample_names"] = sample_titles;
273  return response;
274 }
275 
276 // ***************************************************************************
278 // ***************************************************************************
279 nlohmann::json NuDockServerBase::getParametersNames([[maybe_unused]] const nlohmann::json &request) {
280  std::vector<std::string> syst_par_names;
281 
282  for (size_t s = 0; s < systematics.size(); ++s) {
283  int npars = systematics[s]->GetNumParams();
284  for (int p = 0; p < npars; ++p) {
285  std::string param_name = systematics[s]->GetParFancyName(p);
286  if (NuDockOscNameMap_r.find(param_name) != NuDockOscNameMap_r.end()) continue;
287  if (!systematics[s]->IsParameterFixed(p)) {
288  syst_par_names.push_back(param_name);
289  }
290  }
291  }
292  nlohmann::json response;
293  response["sys_pars"] = syst_par_names;
294  return response;
295 }
296 
297 // ***************************************************************************
299 // ***************************************************************************
300 nlohmann::json NuDockServerBase::getParameters([[maybe_unused]] const nlohmann::json &request) {
301  std::map<std::string, double> osc_params;
302  std::map<std::string, double> syst_params;
303 
304  for (size_t s = 0; s < systematics.size(); ++s) {
305  int npars = systematics[s]->GetNumParams();
306  for (int p = 0; p < npars; ++p) {
307  std::string param_name = systematics[s]->GetParFancyName(p);
308  double param_value = systematics[s]->GetParProp(p);
309  if (NuDockOscNameMap_r.find(param_name) != NuDockOscNameMap_r.end()){
310  param_name = NuDockOscNameMap_r.at(param_name);
311  osc_params[param_name] = param_value;
312  } else {
313  if (!systematics[s]->IsParameterFixed(p)) {
314  syst_params[param_name] = param_value;
315  }
316  }
317  }
318  }
319  // Convert maps to json
320  nlohmann::json response;
321  response["sys_pars"] = syst_params;
322  response["osc_pars"] = osc_params;
323  return response;
324 }
325 
326 // ***************************************************************************
328 // ***************************************************************************
329 nlohmann::json NuDockServerBase::get2NLL([[maybe_unused]] const nlohmann::json &request) {
330  nlohmann::json response;
331  response["log_likelihood"] = 2*getLogLikelihood();
332  return response;
333 }
#define MACH3LOG_ERROR
Definition: MaCh3Logger.h:37
#define MACH3LOG_INFO
Definition: MaCh3Logger.h:35
#define MACH3LOG_WARN
Definition: MaCh3Logger.h:36
const std::unordered_map< std::string, std::string > NuDockOscNameMap_r
Mapping from MaCh3 oscillation parameter names to NuDock names.
void FormatOscParsForMaCh3(const std::string &param_name, double &param_value)
Convert an oscillation parameter value from NuDock convention to MaCh3 convention.
void TH2toResponse(const TH2 *mc_hist, const std::string &sample_title, nlohmann::json &response)
void TH1toResponse(const TH1 *mc_hist, const std::string &sample_title, nlohmann::json &response)
Base class for the MaCh3 NuDock server, exposing fit internals via a JSON-based request/response prot...
Type GetFromManager(const YAML::Node &node, const Type defval, const std::string &File, const int Line)
Get content of config file if node is not found take default value specified.
Definition: YamlHelper.h:328
Base class for implementing fitting algorithms.
Definition: FitterBase.h:29
std::vector< double > sample_llh
store the llh breakdowns
Definition: FitterBase.h:136
std::vector< SampleHandlerInterface * > samples
Sample holder.
Definition: FitterBase.h:141
Manager * fitMan
The manager for configuration handling.
Definition: FitterBase.h:120
std::vector< double > syst_llh
systematic llh breakdowns
Definition: FitterBase.h:138
std::vector< ParameterHandlerBase * > systematics
Systematic holder.
Definition: FitterBase.h:146
Custom exception class used throughout MaCh3.
The manager class is responsible for managing configurations and settings.
Definition: Manager.h:17
YAML::Node const & raw() const
Return config.
Definition: Manager.h:48
virtual nlohmann::json getDataSpectrum(const nlohmann::json &request)
Handle a "get_data_spectrum" request.
virtual nlohmann::json setAsimovPoint(const nlohmann::json &request)
Handle a "set_asimov" request.
void setup()
Perform one-time server setup.
virtual nlohmann::json get2NLL(const nlohmann::json &request)
Handle a "log_likelihood" request.
virtual ~NuDockServerBase()
Destructor.
virtual double getLogLikelihood()
Compute the total log-likelihood across all systematics and samples.
NuDockServerBase(Manager *const fitMan)
Construct the NuDock server.
std::string GetName() const
Return a human-readable identifier for this fitter.
virtual nlohmann::json getParameters(const nlohmann::json &request)
Handle a "get_parameters" request.
virtual nlohmann::json getMCSpectrum(const nlohmann::json &request)
Handle a "get_mc_spectrum" request.
virtual nlohmann::json getParametersNames(const nlohmann::json &request)
Handle a "get_parameter_names" request.
virtual nlohmann::json setParameters(const nlohmann::json &request)
Handle a "set_parameters" request.
bool verbose
Flag controlling verbose logging of server operations.
bool add_prior_llh
If true, systematic prior likelihoods are added to the total LLH.
Class responsible for handling implementation of samples used in analysis, reweighting and returning ...
constexpr static const double _BAD_DOUBLE_
Default value used for double initialisation.
Definition: Core.h:53