libpappsomspp
Library for mass spectrometry
Toggle main menu visibility
Loading...
Searching...
No Matches
cubicsplinemodel.cpp
Go to the documentation of this file.
1
// Copyright 2026 Filippo Rusconi
2
// Inspired by work by Lars Nilse in OpenMS
3
4
5
/////////////////////// stdlib includes
6
#include <limits>
7
#include <algorithm>
8
9
10
/////////////////////// Qt includes
11
#include <QList>
12
#include <QDebug>
13
14
15
/////////////////////// pappsomspp includes
16
17
18
/////////////////////// Local includes
19
#include "
pappsomspp/core/processing/detection/cubicsplinemodel.h
"
20
21
namespace
pappso
22
{
23
24
CubicSplineModel::CubicSplineModel
()
25
{
26
// qDebug() << "Allocating:" << this;
27
}
28
29
CubicSplineModel::CubicSplineModel
(
const
QList<double> &x_values,
30
const
QList<double> &y_values)
31
{
32
// qDebug() << "Allocating:" << this;
33
34
Q_ASSERT(x_values.size() == y_values.size());
35
Q_ASSERT(x_values.size() >= 2);
36
37
double
eps = std::numeric_limits<double>::epsilon();
38
39
// Ensure the x_values are sorted increasingly.
40
41
Q_ASSERT(std::adjacent_find(
42
x_values.cbegin(), x_values.cend(), [=](
double
a
,
double
b
) {
43
return !(b > a + eps);
44
}) == x_values.cend());
45
46
setup
(x_values, y_values);
47
48
// qDebug() << "Number of knots:" << m_knots.size();
49
}
50
51
// Use delegating constructor.
52
CubicSplineModel::CubicSplineModel
(
const
QMap<double, double> &x_y_values_map)
53
:
CubicSplineModel
(x_y_values_map.keys(), x_y_values_map.values())
54
{
55
}
56
57
CubicSplineModel::CubicSplineModel
(
const
CubicSplineModel
&other)
58
{
59
// qDebug() << "Allocating:" << this;
60
m_constCoeffs
= other.
m_constCoeffs
;
61
m_linearCoeffs
= other.
m_linearCoeffs
;
62
m_quadraticCoeffs
= other.
m_quadraticCoeffs
;
63
m_cubicCoeffs
= other.
m_cubicCoeffs
;
64
m_knots
= other.
m_knots
;
65
}
66
67
CubicSplineModel
*
68
CubicSplineModel::clone
(
const
CubicSplineModel
&other)
69
{
70
// qDebug() << "Cloning.";
71
CubicSplineModel
*copy_p =
new
CubicSplineModel
();
72
73
copy_p->
m_name
= other.
m_name
;
74
copy_p->
m_constCoeffs
= other.
m_constCoeffs
;
75
copy_p->
m_linearCoeffs
= other.
m_linearCoeffs
;
76
copy_p->
m_quadraticCoeffs
= other.
m_quadraticCoeffs
;
77
copy_p->
m_cubicCoeffs
= other.
m_cubicCoeffs
;
78
copy_p->
m_knots
= other.
m_knots
;
79
80
return
copy_p;
81
}
82
83
CubicSplineModel::~CubicSplineModel
()
84
{
85
// qDebug() << "Destructing the cubic spline model";
86
}
87
88
void
89
CubicSplineModel::setup
(
const
QList<double> &x_values,
90
const
QList<double> &y_values)
91
{
92
// qDebug() << "Setting up with x_values size:" << x_values.size();
93
94
Q_ASSERT(x_values.size() == y_values.size());
95
96
const
size_t
n = x_values.size() - 1;
97
98
std::vector<double> h;
99
h.reserve(n);
100
m_constCoeffs
.reserve(n);
101
m_knots
.reserve(n + 1);
102
// do the 0'th element manually, since the loop below only starts at 1
103
h.push_back(x_values[1] - x_values[0]);
104
m_knots
.push_back(x_values[0]);
105
m_constCoeffs
.push_back(y_values[0]);
106
107
std::vector<double> mu(n, 0.0);
108
std::vector<double>
z
(n, 0.0);
109
for
(
unsigned
i = 1; i < n; ++i)
110
{
111
h.push_back(x_values[i + 1] - x_values[i]);
112
const
double
l =
113
2 * (x_values[i + 1] - x_values[i - 1]) - h[i - 1] * mu[i - 1];
114
mu[i] = h[i] / l;
115
z
[i] = (3 *
116
(y_values[i + 1] * h[i - 1] -
117
y_values[i] * (x_values[i + 1] - x_values[i - 1]) +
118
y_values[i - 1] * h[i]) /
119
(h[i - 1] * h[i]) -
120
h[i - 1] *
z
[i - 1]) /
121
l;
122
// store x,y -- required for evaluation later on
123
m_knots
.push_back(x_values[i]);
124
m_constCoeffs
.push_back(y_values[i]);
125
}
126
// 'm_knots' needs to be full length (all other member vectors (except
127
// m_quadraticCoeffs) are one element shorter)
128
m_knots
.push_back(x_values[n]);
129
130
m_linearCoeffs
.resize(n);
131
m_cubicCoeffs
.resize(n);
132
m_quadraticCoeffs
.resize(n + 1);
133
m_quadraticCoeffs
.back() = 0;
134
for
(
int
j =
static_cast<
int
>
(n) - 1; j >= 0; --j)
135
{
136
m_quadraticCoeffs
[j] =
z
[j] - mu[j] *
m_quadraticCoeffs
[j + 1];
137
m_linearCoeffs
[j] =
138
(y_values[j + 1] - y_values[j]) / h[j] -
139
h[j] * (
m_quadraticCoeffs
[j + 1] + 2 *
m_quadraticCoeffs
[j]) / 3;
140
m_cubicCoeffs
[j] =
141
(
m_quadraticCoeffs
[j + 1] -
m_quadraticCoeffs
[j]) / (3 * h[j]);
142
}
143
// qDebug() << "m_knots size:" << m_knots.size();
144
}
145
146
CubicSplineModel
&
147
CubicSplineModel::operator=
(
const
CubicSplineModel
&other)
148
{
149
if
(&other ==
this
)
150
return
*
this
;
151
152
m_name
= other.
m_name
;
153
m_constCoeffs
= other.
m_constCoeffs
;
154
m_linearCoeffs
= other.
m_linearCoeffs
;
155
m_quadraticCoeffs
= other.
m_quadraticCoeffs
;
156
m_cubicCoeffs
= other.
m_cubicCoeffs
;
157
m_knots
= other.
m_knots
;
158
159
return
*
this
;
160
}
161
162
const
QList<double> &
163
CubicSplineModel::getKnots
()
const
164
{
165
return
m_knots
;
166
}
167
168
double
169
CubicSplineModel::evalSplineAt
(
double
x_value)
const
170
{
171
Q_ASSERT(x_value >=
m_knots
.front() || x_value <=
m_knots
.back());
172
173
// What is the index of the closest knot left of x_value (or the same).
174
unsigned
i =
static_cast<
unsigned
>
(
175
std::lower_bound(
m_knots
.begin(),
m_knots
.end(), x_value) -
176
m_knots
.begin());
177
178
if
(
m_knots
[i] > x_value ||
m_knots
.back() == x_value)
179
{
180
--i;
181
}
182
183
const
double
delta_x = x_value -
m_knots
[i];
184
185
double
eval_value =
186
((
m_cubicCoeffs
[i] * delta_x +
m_quadraticCoeffs
[i]) * delta_x +
187
m_linearCoeffs
[i]) *
188
delta_x +
189
m_constCoeffs
[i];
190
191
// qDebug() << "Now returning evaluation value:" << eval_value;
192
193
return
eval_value;
194
}
195
196
double
197
CubicSplineModel::derivative
(
const
double
x_value)
const
198
{
199
return
derivatives
(x_value, 1);
200
}
201
202
double
203
CubicSplineModel::derivatives
(
const
double
x_value,
unsigned
order)
const
204
{
205
// qDebug() << "Size of m_knots:" << m_knots.size();
206
207
Q_ASSERT(x_value >=
m_knots
.front() && x_value <=
m_knots
.back());
208
209
Q_ASSERT(order >= 1 && order <= 3);
210
211
// determine index of closest node left of (or exactly at) x_value
212
unsigned
i =
static_cast<
unsigned
>
(
213
std::lower_bound(
m_knots
.begin(),
m_knots
.end(), x_value) -
214
m_knots
.begin());
215
216
if
(
m_knots
[i] > x_value ||
217
m_knots
.back() ==
218
x_value)
// also, i must not point to last index in 'm_knots',
219
// since all other vectors are one element shorter
220
{
221
--i;
222
}
223
224
const
double
delta_x = x_value -
m_knots
[i];
225
if
(order == 1)
226
{
227
return
m_linearCoeffs
[i] + 2 *
m_quadraticCoeffs
[i] * delta_x +
228
3 *
m_cubicCoeffs
[i] * delta_x * delta_x;
229
}
230
else
if
(order == 2)
231
{
232
return
2 *
m_quadraticCoeffs
[i] + 6 *
m_cubicCoeffs
[i] * delta_x;
233
}
234
else
235
{
236
return
6 *
m_cubicCoeffs
[i];
237
}
238
}
239
240
void
241
spline_bisection
(
const
CubicSplineModel
&spline_model,
242
double
const
mz_at_left,
243
double
const
mz_at_right,
244
double
¢er_peak_mz,
245
double
¢er_peak_intensity,
246
double
const
threshold)
247
{
248
// qDebug() << "spline model has" << spline_model.getKnots().size();
249
250
// calculate maximum by evaluating the spline's 1st derivative
251
// (bisection method)
252
double
lefthand = mz_at_left;
253
double
righthand = mz_at_right;
254
255
bool
lefthand_sign =
true
;
256
double
eps = std::numeric_limits<double>::epsilon();
257
258
// bisection
259
do
260
{
261
double
mid = (lefthand + righthand) / 2.0;
262
double
midpoint_deriv_val = spline_model.
derivative
(mid);
263
264
// if deriv nearly zero then maximum already found
265
if
(!(std::fabs(midpoint_deriv_val) > eps))
266
{
267
break
;
268
}
269
270
bool
midpoint_sign = (midpoint_deriv_val < 0.0) ?
false
:
true
;
271
272
if
(lefthand_sign ^ midpoint_sign)
273
{
274
righthand = mid;
275
}
276
else
277
{
278
lefthand = mid;
279
}
280
}
281
while
(righthand - lefthand > threshold);
282
283
center_peak_mz = (lefthand + righthand) / 2;
284
285
center_peak_intensity = spline_model.
evalSplineAt
(center_peak_mz);
286
287
// qDebug() << "center_peak_intensity:" << center_peak_intensity;
288
}
289
290
}
// namespace pappso
pappso::CubicSplineModel
Definition
cubicsplinemodel.h:24
pappso::CubicSplineModel::m_quadraticCoeffs
QList< double > m_quadraticCoeffs
Definition
cubicsplinemodel.h:51
pappso::CubicSplineModel::setup
void setup(const QList< double > &x_values, const QList< double > &y_values)
Definition
cubicsplinemodel.cpp:89
pappso::CubicSplineModel::CubicSplineModel
CubicSplineModel()
Definition
cubicsplinemodel.cpp:24
pappso::CubicSplineModel::~CubicSplineModel
virtual ~CubicSplineModel()
Definition
cubicsplinemodel.cpp:83
pappso::CubicSplineModel::m_name
QString m_name
Definition
cubicsplinemodel.h:48
pappso::CubicSplineModel::operator=
CubicSplineModel & operator=(const CubicSplineModel &other)
Definition
cubicsplinemodel.cpp:147
pappso::CubicSplineModel::m_linearCoeffs
QList< double > m_linearCoeffs
Definition
cubicsplinemodel.h:50
pappso::CubicSplineModel::derivatives
double derivatives(const double x_value, unsigned order) const
Definition
cubicsplinemodel.cpp:203
pappso::CubicSplineModel::derivative
double derivative(const double x_value) const
Definition
cubicsplinemodel.cpp:197
pappso::CubicSplineModel::getKnots
const QList< double > & getKnots() const
Definition
cubicsplinemodel.cpp:163
pappso::CubicSplineModel::m_cubicCoeffs
QList< double > m_cubicCoeffs
Definition
cubicsplinemodel.h:52
pappso::CubicSplineModel::m_constCoeffs
QList< double > m_constCoeffs
Definition
cubicsplinemodel.h:49
pappso::CubicSplineModel::m_knots
QList< double > m_knots
Definition
cubicsplinemodel.h:53
pappso::CubicSplineModel::clone
CubicSplineModel * clone(const CubicSplineModel &other)
Definition
cubicsplinemodel.cpp:68
pappso::CubicSplineModel::evalSplineAt
double evalSplineAt(double x_value) const
Definition
cubicsplinemodel.cpp:169
cubicsplinemodel.h
pappso
tries to keep as much as possible monoisotopes, removing any possible C13 peaks and changes multichar...
Definition
aa.cpp:39
pappso::PeptideIonNter::a
@ a
Definition
peptide.h:77
pappso::PeptideIonNter::b
@ b
Definition
peptide.h:74
pappso::spline_bisection
void spline_bisection(const CubicSplineModel &spline_model, double const mz_at_left, double const mz_at_right, double ¢er_peak_mz, double ¢er_peak_intensity, double const threshold)
Definition
cubicsplinemodel.cpp:241
pappso::PeptideIonCter::z
@ z
Definition
peptide.h:90
pappsomspp
core
processing
detection
cubicsplinemodel.cpp
Generated on
for libpappsomspp by
1.17.0