• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

rlalik / HelloFitty / 18023474237

25 Sep 2025 11:33PM UTC coverage: 82.012% (-1.4%) from 83.411%
18023474237

push

github

rlalik
fix: updating param limits now enables limits

Also, added two functions to remove/restore limits flag

0 of 11 new or added lines in 1 file covered. (0.0%)

1 existing line in 1 file now uncovered.

538 of 656 relevant lines covered (82.01%)

19.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

67.69
/source/entry.cpp
1
/*
2
    HelloFitty - a versatile histogram fitting tool for ROOT-based projects
3
    Copyright (C) 2015-2023  Rafał Lalik <rafallalik@gmail.com>
4

5
    This program is free software: you can redistribute it and/or modify
6
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation, either version 3 of the License, or
8
    (at your option) any later version.
9

10
    This program is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    GNU General Public License for more details.
14

15
    You should have received a copy of the GNU General Public License
16
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18

19
#include <fmt/core.h>
20

21
#include "hellofitty.hpp"
22

23
#include "details.hpp"
24

25
template<>
26
struct fmt::formatter<hf::entry>
27
{
28
    // Presentation format: 'f' - fixed, 'e' - exponential, 'g' - either.
29
    char presentation = 'g';
30

31
    // Parses format specifications of the form ['f' | 'e' | 'g'].
32
    CONSTEXPR auto parse(format_parse_context& ctx) -> format_parse_context::iterator
×
33
    {
34
        // Parse the presentation format and store it in the formatter:
35
        auto it = ctx.begin(), end = ctx.end();
×
36
        if (it != end && *it != '}') { FMT_THROW(format_error("invalid format")); }
×
37

38
        // Return an iterator past the end of the parsed range:
39
        return it;
×
40
    }
41

42
    auto format(const hf::entry& /*fitentry*/, format_context& ctx) const -> format_context::iterator
×
43
    {
44
        return ctx.out();
×
45
    }
46
};
47

48
namespace hf
49
{
50

51
entry::entry()
×
52
    : m_d {make_unique<detail::entry_impl>()}
×
53
{
54
}
×
55

56
entry::entry(Double_t range_lower, Double_t range_upper)
32✔
57
    : m_d {make_unique<detail::entry_impl>()}
32✔
58
{
59
    if (range_lower == range_upper) { throw hf::range_error("fitting range cannot be empty"); }
32✔
60

61
    m_d->range_min = range_lower;
32✔
62
    m_d->range_max = range_upper;
32✔
63
}
32✔
64

65
entry::entry(const entry& other) { m_d = make_unique<detail::entry_impl>(*other.m_d); }
6✔
66

67
auto entry::operator=(const entry& other) -> entry&
×
68
{
69
    m_d = make_unique<detail::entry_impl>(*other.m_d);
×
70
    return *this;
×
71
}
72

73
entry::~entry() noexcept = default;
69✔
74

75
auto entry::is_valid() const -> bool { return m_d->range_max > m_d->range_min; }
×
76

77
auto entry::clear() -> void { drop(); }
1✔
78

79
auto entry::add_function(std::string formula) -> int
14✔
80
{
81
    auto current_function_idx = m_d->add_function_lazy(std::move(formula));
14✔
82
    m_d->compile();
14✔
83
    return current_function_idx;
14✔
84
}
85

86
auto entry::get_function(int function_index) const -> const char*
45✔
87
{
88
    return m_d->funcs.at(int2size_t(function_index)).body_string.c_str();
90✔
89
}
90

91
auto entry::set_param(int par_id, hf::param par) -> void
90✔
92
{
93
    const auto upar_id = int2size_t(par_id);
90✔
94
    m_d->pars.at(upar_id) = std::move(par);
90✔
95
}
86✔
96

97
auto entry::set_param(int par_id, Double_t value, hf::param::fit_mode mode) -> void
58✔
98
{
99
    set_param(par_id, hf::param(value, mode));
58✔
100
}
55✔
101

102
auto entry::set_param(int par_id, Double_t value, Double_t l, Double_t u, param::fit_mode mode) -> void
28✔
103
{
104
    set_param(par_id, hf::param(value, l, u, mode));
28✔
105
}
27✔
106

107
auto entry::update_param_value(int par_id, Double_t value) -> void
46✔
108
{
109
    const auto upar_id = int2size_t(par_id);
46✔
110
    auto& par = m_d->pars.at(upar_id);
46✔
111

112
    par.value = value;
46✔
113
}
46✔
114

115
auto entry::update_param_limits(int par_id, Double_t min, Double_t max) -> void
×
116
{
117
    const auto upar_id = int2size_t(par_id);
×
118
    auto& par = m_d->pars.at(upar_id);
×
119

120
    par.min = min;
×
121
    par.max = max;
×
NEW
122
    par.has_limits = true;
×
UNCOV
123
}
×
124

125
auto entry::update_param_mode(int par_id, hf::param::fit_mode mode) -> void
×
126
{
127
    const auto upar_id = int2size_t(par_id);
×
128
    auto& par = m_d->pars.at(upar_id);
×
129

130
    par.mode = mode;
×
131
}
×
132

NEW
133
auto entry::remove_param_limits(int par_id) -> void
×
134
{
NEW
135
    const auto upar_id = int2size_t(par_id);
×
NEW
136
    auto& par = m_d->pars.at(upar_id);
×
137

NEW
138
    par.has_limits = false;
×
NEW
139
}
×
140

NEW
141
auto entry::restore_param_limits(int par_id) -> void
×
142
{
NEW
143
    const auto upar_id = int2size_t(par_id);
×
NEW
144
    auto& par = m_d->pars.at(upar_id);
×
145

NEW
146
    par.has_limits = true;
×
NEW
147
}
×
148

149
auto entry::get_param(int par_id) const -> hf::param { return param(par_id); }
40✔
150

151
auto get_param_name_index(TF1* fun, const char* name) -> Int_t
4✔
152
{
153
    auto par_index = fun->GetParNumber(name);
4✔
154
    if (par_index == -1) { throw hf::index_error("No such parameter"); }
4✔
155
    return par_index;
3✔
156
}
157

158
auto entry::get_param(const char* name) const -> hf::param
×
159
{
160
    return get_param(get_param_name_index(&m_d->complete_function_object, name));
×
161
}
162

163
auto entry::param(int par_id) const -> const hf::param&
187✔
164
{
165
    const auto upar_id = int2size_t(par_id);
187✔
166
    try
187✔
167
    {
168
        return m_d->pars.at(upar_id);
187✔
169
    }
170
    catch (std::out_of_range& e)
1✔
171
    {
172
        throw hf::index_error(e.what());
1✔
173
    }
1✔
174
}
175

176
auto entry::param(int par_id) -> hf::param&
97✔
177
{
178
    return const_cast<hf::param&>(const_cast<const entry*>(this)->param(par_id));
97✔
179
}
180

181
auto entry::param(const char* name) const -> const hf::param&
4✔
182
{
183
    return param(get_param_name_index(&m_d->complete_function_object, name));
4✔
184
}
185

186
auto entry::param(const char* name) -> hf::param&
3✔
187
{
188
    return const_cast<hf::param&>(const_cast<const entry*>(this)->param(name));
3✔
189
}
190

191
auto entry::set_fit_range(Double_t range_lower, Double_t range_upper) -> void
1✔
192
{
193
    if (range_lower == range_upper) { throw hf::range_error("fitting range cannot be empty"); }
1✔
194

195
    m_d->range_min = range_lower;
1✔
196
    m_d->range_max = range_upper;
1✔
197

198
    m_d->complete_function_object.SetRange(range_lower, range_upper);
1✔
199
    for (auto& f : m_d->funcs)
2✔
200
    {
201
        f.function_obj.SetRange(range_lower, range_upper);
1✔
202
    }
203
}
1✔
204

205
auto entry::get_fit_range_min() const -> Double_t { return m_d->range_min; }
34✔
206

207
auto entry::get_fit_range_max() const -> Double_t { return m_d->range_max; }
34✔
208

209
auto entry::get_functions_count() const -> int { return size_t2int(m_d->funcs.size()); }
32✔
210

211
auto entry::get_function_object(int function_index) const -> const TF1&
69✔
212
{
213
    return m_d->funcs.at(int2size_t(function_index)).function_obj;
138✔
214
}
215

216
auto entry::get_function_object(int function_index) -> TF1&
69✔
217
{
218
    return const_cast<TF1&>(const_cast<const entry*>(this)->get_function_object(function_index));
69✔
219
}
220

221
auto entry::get_function_object() const -> const TF1&
65✔
222
{
223
    if (!m_d->complete_function_object.IsValid()) { m_d->compile(); }
65✔
224
    return m_d->complete_function_object;
65✔
225
}
226

227
auto entry::get_function_object() -> TF1&
9✔
228
{
229
    return const_cast<TF1&>(const_cast<const entry*>(this)->get_function_object());
9✔
230
}
231

232
auto entry::clone_function(int function_index, const char* new_name) -> std::unique_ptr<TF1>
×
233
{
234
    return std::unique_ptr<TF1>(dynamic_cast<TF1*>(get_function_object(function_index).Clone(new_name)));
×
235
}
236

237
auto entry::clone_function(const char* new_name) -> std::unique_ptr<TF1>
×
238
{
239
    return std::unique_ptr<TF1>(dynamic_cast<TF1*>(get_function_object().Clone(new_name)));
×
240
}
241

242
auto entry::get_function_params_count() const -> int { return get_function_object().GetNpar(); }
56✔
243

244
auto entry::get_flag_rebin() const -> int { return m_d->rebin; }
25✔
245

246
auto entry::get_flag_disabled() const -> bool { return m_d->fit_disabled; }
32✔
247

248
auto entry::set_flag_disabled(bool new_state) -> void { m_d->fit_disabled = new_state; }
×
249

250
auto entry::print(const std::string& name, bool detailed) const -> void
16✔
251
{
252
    fmt::print("## name: {:s}    rebin: {:d}   range: {:g} -- {:g}  param num: {:d}  {:s}\n", name, m_d->rebin,
16✔
253
               m_d->range_min, m_d->range_max, get_function_params_count(), get_flag_disabled() ? "DISABLED" : "");
32✔
254

255
    for (const auto& func : m_d->funcs)
45✔
256
    {
257
        func.print(detailed);
29✔
258
    }
259

260
    auto s = m_d->pars.size();
16✔
261
    for (decltype(s) i = 0; i < s; ++i)
85✔
262
    {
263
        fmt::print("   {}: ", i);
69✔
264
        m_d->pars[i].print();
69✔
265
    }
266

267
    // auto s = m_d->pars.size();
268
    // for (decltype(s) i = 0; i < s; ++i)
269
    // {
270
    //     fmt::print("   {}: ", i);
271
    //     m_d->pars[i].print();
272
    // }
273
    //
274
    // if (detailed)
275
    // {
276
    //     fmt::print("{}\n", "+++++++++ SIG function +++++++++");
277
    //     m_d->function_sig.Print("V");
278
    //     fmt::print("{}\n", "+++++++++ BKG function +++++++++");
279
    //     m_d->function_bkg.Print("V");
280
    //     fmt::print("{}\n", "+++++++++ SUM function +++++++++");
281
    //     m_d->function_sum.Print("V");
282
    //     fmt::print("{}\n", "++++++++++++++++++++++++++++++++");
283
    // } FIXME
284
}
16✔
285

286
auto entry::backup() -> void { m_d->backup(); }
13✔
287

288
auto entry::restore() -> void { m_d->restore(); }
4✔
289

290
auto entry::drop() -> void { m_d->parameters_backup.clear(); }
3✔
291

292
auto entry::set_function_style(int function_index) -> draw_opts&
4✔
293
{
294
    auto res = m_d->partial_functions_styles.insert({function_index, draw_opts()});
8✔
295
    return res.first->second;
4✔
296
}
297

298
auto entry::set_function_style() -> draw_opts& { return set_function_style(-1); }
2✔
299

300
} // namespace hf
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc