1 /// @brief HH - a helper function for RegisterFunctionalParameter
2 template <typename EventType, typename SFType>
3 void SampleHandlerBase::RegisterIndividualFunctionalParameter(
4 std::vector<EventType> &ExptEvents,
5 std::vector<std::string> const &par_names, SFType shift_func) {
9 std::function<void(std::vector<double> const &, EventType &)>,
10 decltype(std::function(shift_func))>,
11 "Function call signature for single parameter Functional shift must be "
12 "void(std::vector<double> const &, EventType &).");
14 // check against all parameters defined on all Samples handled by this
16 std::vector<std::vector<FunctionalParameter>> all_sample_pars;
17 std::map<int, std::vector<int>> par_applicable_samplenames;
18 for (int iSample = 0; iSample < nSamples; ++iSample) {
19 all_sample_pars.push_back(ParHandler->GetFunctionalParametersFromSampleName(
20 GetSampleName(iSample)));
21 for (auto const &fp : all_sample_pars.back()) {
22 par_applicable_samplenames[fp.index].push_back(iSample);
26 std::stringstream ss_pars, ss_miss;
27 std::vector<FunctionalParameter const *> matched_pars;
28 for (auto const &par_name : par_names) {
29 ss_pars << par_name << " ";
32 for (int iSample = 0; iSample < nSamples; ++iSample) {
33 for (auto const &fp : all_sample_pars[iSample]) {
34 if (fp.name == par_name) {
35 matched_pars.push_back(&fp);
49 // allows experiments to effectively disable functional parameters by not
50 // supplying the YAML defining the parameters
51 if (!matched_pars.size()) {
52 MACH3LOG_INFO("Functional shift consuming parameters: [ {}], found no "
53 "matching parameters for "
55 ss_pars.str(), SampleHandlerName);
57 } else if (matched_pars.size() !=
58 par_names.size()) { // not well defined how to procede with
59 // partially defined parameter sets, so don't
61 "Functional shift consuming parameters: [ {}], only partially "
62 "applys to sample handler: {}, missed parameters: [ {}]",
63 ss_pars.str(), SampleHandlerName, ss_miss.str());
64 throw MaCh3Exception(__FILE__, __LINE__);
67 if (!functional.event_shifts.size()) {
68 functional.event_shifts.resize(ExptEvents.size());
69 } else if (functional.event_shifts.size() != ExptEvents.size()) {
70 MACH3LOG_ERROR("When registering functional shift consuming parameters: "
71 "[ {}], SampleHandler: {} has an allocated event map of "
72 "size: {}, but passed a vector of experiment events size: "
73 "{}. SampleHandler must have a unique set of event "
74 "indices so this indicates something has gone wrong.",
75 ss_pars.str(), SampleHandlerName,
76 functional.event_shifts.size(), ExptEvents.size());
77 throw MaCh3Exception(__FILE__, __LINE__);
80 if (ExptEvents.size() != MCEvents.size()) {
81 MACH3LOG_ERROR("When registering functional shift consuming parameters: "
82 "[ {}], SampleHandler: {} knows about {} MCEvents, but "
83 "passed a vector of experiment events size: "
84 "{}. SampleHandler must have a unique set of event "
85 "indices so this indicates something has gone wrong.",
86 ss_pars.str(), SampleHandlerName, MCEvents.size(),
88 throw MaCh3Exception(__FILE__, __LINE__);
91 // If we've made it here, then this functional shift is correctly
92 // configured for this SampleHandler
94 int iShift = int(functional.shifts.size());
95 M3::detail::Functional::Shift shift;
97 std::vector<int> par_indices;
98 for (auto const &fp : matched_pars) {
99 par_indices.push_back(fp->index);
102 shift.par_vals.resize(par_indices.size());
103 shift.update_vals = [par_indices,this](std::vector<double> &par_vals) {
104 for (size_t i = 0; i < par_indices.size(); ++i) {
105 auto const &fpi = par_indices[i];
106 par_vals[i] = ParHandler->GetParPropVec()[fpi];
110 shift.apply = [shift_func, &ExptEvents](std::vector<double> const &par_vals,
112 shift_func(par_vals, ExptEvents[iEvent]);
115 functional.shifts.push_back(std::move(shift));
117 // For each event, make a vector of pointers to the functional parameters
118 int NEvents = GetNEvents();
119 int neventsaffected = 0;
120 for (int iEvent = 0; iEvent < NEvents; ++iEvent) {
122 for (auto const &fp : matched_pars) {
123 const int Mode = static_cast<int>(
124 std::round(ReturnKinematicParameter("Mode", iEvent)));
125 if (!MatchCondition(fp->modes, Mode)) {
126 MACH3LOG_TRACE("Event {}, missed Mode check ({}) for dial {}", iEvent,
130 if (!MatchCondition(par_applicable_samplenames[fp->index],
131 MCEvents[iEvent].NominalSample)) {
132 MACH3LOG_TRACE("Event {}, missed Sample check ({}) for dial {}", iEvent,
133 MCEvents[iEvent].NominalSample, fp->name);
136 if (!PassesSelection((*fp), iEvent)) {
137 MACH3LOG_TRACE("Event {}, missed Kinematic var check for dial {}",
143 // check sample name vs event.NominalSample
147 if (nmatch != static_cast<int>(matched_pars.size())) {
149 "When determining wether functional shift consuming parameters: "
150 "[ {}], in SampleHandler: {} should apply to event: {}, only {}/{} "
151 "parameters matched. Partially applied shifts are ill-defined.",
152 ss_pars.str(), SampleHandlerName, iEvent, nmatch,
153 matched_pars.size());
154 throw MaCh3Exception(__FILE__, __LINE__);
156 functional.event_shifts[iEvent].push_back(iShift);
160 "Registered functional shift consuming parameters: "
161 "[ {}] for SampleHandler: {}, with {} par vals affecting {} events.",
162 ss_pars.str(), SampleHandlerName, shift.par_vals.size(), neventsaffected);
165 template <typename EventType, typename SFType>
166 void SampleHandlerBase::RegisterIndividualFunctionalParameter(
167 std::vector<EventType> &ExptEvents, std::string const &par_name,
171 std::is_same_v<std::function<void(double const &, EventType &)>,
172 decltype(std::function(shift_func))>,
173 "Function call signature for single parameter Functional shift must be "
174 "void(double const &, EventType&).");
176 RegisterIndividualFunctionalParameter(
178 std::vector<std::string>{
181 [=](std::vector<double> const &par_vals, EventType &ev) {
182 shift_func(par_vals[0], ev);
186 // ***************************************************************************
187 template <typename ParT>
188 bool SampleHandlerBase::PassesSelection(const ParT &Par, std::size_t iEvent) {
189 // ***************************************************************************
190 bool IsSelected = true;
191 if (Par.hasKinBounds) {
192 const auto &kinVars = Par.KinematicVarStr;
193 const auto &selection = Par.Selection;
195 for (std::size_t iKinPar = 0; iKinPar < kinVars.size(); ++iKinPar) {
196 const double kinVal =
197 ReturnKinematicParameter(kinVars[iKinPar], static_cast<int>(iEvent));
199 bool passedAnyBound = false;
200 const auto &boundsList = selection[iKinPar];
202 for (const auto &bounds : boundsList) {
203 if (kinVal > bounds[0] && kinVal <= bounds[1]) {
204 passedAnyBound = true;
209 if (!passedAnyBound) {
210 MACH3LOG_TRACE("Event {}, missed kinematic check ({}) for dial {}",
211 iEvent, kinVars[iKinPar], Par.name);