MaCh3  2.5.1
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);
24  add_prior_llh = GetFromManager(fitMan->raw()["NuDock"]["AddPriorLLH"], false);
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(const nlohmann::json &request) {
120  (void)request;
121  // reweight sample and add to data
122  for (size_t ipdf=0; ipdf<samples.size(); ipdf++) {
123  samples[ipdf]->Reweight();
124  auto* base_casted_sample = dynamic_cast<SampleHandlerBase*>(samples[ipdf]);
125  if(!base_casted_sample) {
126  MACH3LOG_ERROR("Sample object does not derive from SampleHandlerBase. Consider overloading {} for this sample type.", __func__);
127  throw MaCh3Exception(__FILE__,__LINE__);
128  }
129  for (int iSample = 0; iSample < samples[ipdf]->GetNSamples(); ++iSample) {
130  base_casted_sample->AddData(iSample, base_casted_sample->GetMCArray(iSample));
131  }
132  }
133 
134  // set prefit parameter values to the current parameter values
135  for (size_t s = 0; s < systematics.size(); ++s) {
136  int npars = systematics[s]->GetNumParams();
137  for (int p = 0; p < npars; ++p) {
138  std::string param_name = systematics[s]->GetParFancyName(p);
139  double param_value = systematics[s]->GetParCurr(p);
140  systematics[s]->SetPar(p, param_value);
141  if (verbose) MACH3LOG_INFO("Setting prefit param {} to current value {}", param_name, param_value);
142  }
143  }
144 
145  nlohmann::json response;
146  response["status"] = "success";
147  return response;
148 }
149 // ***************************************************************************
150 void TH1toResponse(const TH1* mc_hist, const std::string& sample_title, nlohmann::json &response) {
151 // ***************************************************************************
152  auto hist1d = dynamic_cast<const TH1D*>(mc_hist);
153  if (!hist1d) {
154  MACH3LOG_ERROR("{}: input histogram is not TH1D", __func__);
155  throw MaCh3Exception(__FILE__,__LINE__);
156  }
157  const TAxis *ax = mc_hist->GetXaxis();
158  std::string xtitle = ax->GetTitle();
159  int nxbins = ax->GetNbins();
160  std::vector<double> xbins(nxbins+1);
161  std::vector<double> binvals(nxbins);
162 
163  xbins[0] = ax->GetBinLowEdge(1);
164  for (int ix = 1; ix <= nxbins; ++ix) {
165  xbins[ix] = ax->GetBinUpEdge(ix);
166  binvals[ix-1] = mc_hist->GetBinContent(ix);
167  }
168  response["axis_titles"][sample_title] = {xtitle};
169  response["bin_edges"][sample_title] = {xbins};
170  response["bin_values"][sample_title] = binvals;
171 }
172 
173 // ***************************************************************************
174 void TH2toResponse(const TH2* mc_hist, const std::string& sample_title, nlohmann::json &response) {
175 // ***************************************************************************
176  auto hist2d = dynamic_cast<const TH2D*>(mc_hist);
177  if (!hist2d) {
178  MACH3LOG_ERROR("{}: input histogram is not TH2D", __func__);
179  throw MaCh3Exception(__FILE__,__LINE__);
180  }
181  const TAxis *x_axis = mc_hist->GetXaxis();
182  std::string xtitle = x_axis->GetTitle();
183  int nxbins = x_axis->GetNbins();
184  std::vector<double> xbins(nxbins+1);
185 
186  const TAxis *y_axis = mc_hist->GetYaxis();
187  std::string ytitle = y_axis->GetTitle();
188  int nybins = y_axis->GetNbins();
189  std::vector<double> ybins(nybins+1);
190 
191  std::vector<std::vector<double>> binvals(nxbins, std::vector<double>(nybins));
192 
193  xbins[0] = x_axis->GetBinLowEdge(1);
194  ybins[0] = y_axis->GetBinLowEdge(1);
195  for (int ix = 1; ix <= nxbins; ++ix) {
196  for (int iy = 1; iy <= nybins; ++iy) {
197  xbins[ix] = x_axis->GetBinUpEdge(ix);
198  ybins[iy] = y_axis->GetBinUpEdge(iy);
199  binvals[ix-1][iy-1] = mc_hist->GetBinContent(ix, iy);
200  }
201  }
202  response["axis_titles"][sample_title] = {xtitle, ytitle};
203  response["bin_edges"][sample_title] = {xbins, ybins};
204  response["bin_values"][sample_title] = binvals;
205 }
206 
207 // ***************************************************************************
209 // ***************************************************************************
210 nlohmann::json NuDockServerBase::getMCSpectrum(const nlohmann::json &request) {
211  (void)request;
212  nlohmann::json response;
213 
214  std::vector<std::string> sample_titles = {};
215 
216  for (size_t ipdf=0; ipdf<samples.size(); ipdf++) {
217  auto* base_casted_sample = dynamic_cast<SampleHandlerBase*>(samples[ipdf]);
218  if(!base_casted_sample) {
219  MACH3LOG_ERROR("Sample object does not derive from SampleHandlerBase. Consider overloading {} for this sample type.", __func__);
220  throw MaCh3Exception(__FILE__,__LINE__);
221  }
222  for (int iSample = 0; iSample < samples[ipdf]->GetNSamples(); ++iSample) {
223  std::string sample_title = samples[ipdf]->GetSampleTitle(iSample);
224  sample_titles.push_back(sample_title);
225 
226  int dimension = samples[ipdf]->GetNDim(iSample);
227  response["dimensions"][sample_title] = dimension;
228 
229  if (dimension == 1) {
230  TH1toResponse(samples[ipdf]->GetMCHist(iSample), sample_title, response);
231  } else if (dimension == 2) {
232  TH2toResponse(static_cast<const TH2*>(samples[ipdf]->GetMCHist(iSample)), sample_title, response);
233  } else {
234  MACH3LOG_ERROR("Not implemented for dim =", dimension);
235  throw MaCh3Exception(__FILE__,__LINE__);
236  }
237  }
238  }
239  response["sample_names"] = sample_titles;
240  return response;
241 }
242 
243 // ***************************************************************************
245 // ***************************************************************************
246 nlohmann::json NuDockServerBase::getDataSpectrum(const nlohmann::json &request) {
247  (void)request;
248  nlohmann::json response;
249 
250  std::vector<std::string> sample_titles = {};
251 
252  for (size_t ipdf=0; ipdf<samples.size(); ipdf++) {
253  auto* base_casted_sample = dynamic_cast<SampleHandlerBase*>(samples[ipdf]);
254  if(!base_casted_sample) {
255  MACH3LOG_ERROR("Sample object does not derive from SampleHandlerBase. Consider overloading {} for this sample type.", __func__);
256  throw MaCh3Exception(__FILE__,__LINE__);
257  }
258  for (int iSample = 0; iSample < samples[ipdf]->GetNSamples(); ++iSample) {
259  std::string sample_title = samples[ipdf]->GetSampleTitle(iSample);
260  sample_titles.push_back(sample_title);
261 
262  int dimension = samples[ipdf]->GetNDim(iSample);
263  response["dimensions"][sample_title] = dimension;
264 
265  if (dimension == 1) {
266  TH1toResponse(samples[ipdf]->GetDataHist(iSample), sample_title, response);
267  } else if (dimension == 2) {
268  TH2toResponse(static_cast<const TH2*>(samples[ipdf]->GetDataHist(iSample)), sample_title, response);
269  } else {
270  MACH3LOG_ERROR("Not implemented for dim =", dimension);
271  throw MaCh3Exception(__FILE__,__LINE__);
272  }
273  }
274  }
275  response["sample_names"] = sample_titles;
276  return response;
277 }
278 
279 // ***************************************************************************
281 // ***************************************************************************
282 nlohmann::json NuDockServerBase::getParametersNames(const nlohmann::json &request) {
283  (void)request;
284  std::vector<std::string> syst_par_names;
285 
286  for (size_t s = 0; s < systematics.size(); ++s) {
287  int npars = systematics[s]->GetNumParams();
288  for (int p = 0; p < npars; ++p) {
289  std::string param_name = systematics[s]->GetParFancyName(p);
290  if (NuDockOscNameMap_r.find(param_name) != NuDockOscNameMap_r.end()) continue;
291  if (!systematics[s]->IsParameterFixed(p)) {
292  syst_par_names.push_back(param_name);
293  }
294  }
295  }
296  nlohmann::json response;
297  response["sys_pars"] = syst_par_names;
298  return response;
299 }
300 
301 // ***************************************************************************
303 // ***************************************************************************
304 nlohmann::json NuDockServerBase::getParameters(const nlohmann::json &request) {
305  std::map<std::string, double> osc_params;
306  std::map<std::string, double> syst_params;
307 
308  for (size_t s = 0; s < systematics.size(); ++s) {
309  int npars = systematics[s]->GetNumParams();
310  for (int p = 0; p < npars; ++p) {
311  std::string param_name = systematics[s]->GetParFancyName(p);
312  double param_value = systematics[s]->GetParProp(p);
313  if (NuDockOscNameMap_r.find(param_name) != NuDockOscNameMap_r.end()){
314  param_name = NuDockOscNameMap_r.at(param_name);
315  osc_params[param_name] = param_value;
316  } else {
317  if (!systematics[s]->IsParameterFixed(p)) {
318  syst_params[param_name] = param_value;
319  }
320  }
321  }
322  }
323  (void)request;
324  // Convert maps to json
325  nlohmann::json response;
326  response["sys_pars"] = syst_params;
327  response["osc_pars"] = osc_params;
328  return response;
329 }
330 
331 // ***************************************************************************
333 // ***************************************************************************
334 nlohmann::json NuDockServerBase::get2NLL(const nlohmann::json &request) {
335  (void)request;
336  nlohmann::json response;
337  response["log_likelihood"] = 2*getLogLikelihood();
338  return response;
339 }
#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=1)
Get content of config file if node is not found take default value specified.
Definition: YamlHelper.h:329
Base class for implementing fitting algorithms.
Definition: FitterBase.h:26
std::vector< double > sample_llh
store the llh breakdowns
Definition: FitterBase.h:126
std::vector< SampleHandlerInterface * > samples
Sample holder.
Definition: FitterBase.h:131
Manager * fitMan
The manager for configuration handling.
Definition: FitterBase.h:110
std::vector< double > syst_llh
systematic llh breakdowns
Definition: FitterBase.h:128
std::vector< ParameterHandlerBase * > systematics
Systematic holder.
Definition: FitterBase.h:136
Custom exception class used throughout MaCh3.
The manager class is responsible for managing configurations and settings.
Definition: Manager.h:16
YAML::Node const & raw() const
Return config.
Definition: Manager.h:47
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