/
OpenCubicSpline.h
110 lines (103 loc) · 3.77 KB
/
OpenCubicSpline.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/**
* \file IMP/score_functor/OpenCubicSpline.h
* \brief A Score on the distance between a pair of particles.
*
* Copyright 2007-2022 IMP Inventors. All rights reserved.
*/
#ifndef IMPSCORE_FUNCTOR_OPEN_CUBIC_SPLINE_H
#define IMPSCORE_FUNCTOR_OPEN_CUBIC_SPLINE_H
#include <IMP/score_functor/score_functor_config.h>
#include "Score.h"
#include "internal/RawOpenCubicSpline.h"
IMPSCOREFUNCTOR_BEGIN_NAMESPACE
//! Open cubic spline function.
/** This function interpolates a set of evenly spaced values using a spline.
The second derivative at the termini is set to zero. See
core::ClosedCubicSpline for a periodic version.
\see core::ClosedCubicSpline
*/
class OpenCubicSpline : public Score {
double spacing_;
double inverse_spacing_;
internal::RawOpenCubicSpline spline_;
double minrange_;
double maxrange_;
bool extend_;
public:
//! Constructor.
/** \param[in] values Score value at each spline point
\param[in] minrange Feature value at first spline point
\param[in] spacing Distance (in feature space) between points
\param[in] extend If extend is true, the nearest value is used
as the value for any feature outside of the range.
*/
OpenCubicSpline(const Floats &values, Float minrange, Float spacing,
bool extend = false)
: spacing_(spacing),
inverse_spacing_(1.0 / spacing_),
spline_(values, spacing_, inverse_spacing_),
minrange_(minrange),
maxrange_(minrange_ + spacing_ * (values.size() - 1)),
extend_(extend) {
IMP_USAGE_CHECK(spacing > 0,
"The spacing between values must be positive.");
IMP_USAGE_CHECK(values.size() >= 1, "You must provide at least one value.");
}
// depend on get_is_trivially_zero
template <unsigned int D>
double get_score(Model *,
const Array<D, ParticleIndex> &,
double distance) const {
// check for feature in range
if (distance < minrange_ || distance > maxrange_) {
if (extend_) {
if (distance < minrange_)
return spline_.get_first();
else
return spline_.get_last();
} else {
IMP_THROW("Value " << distance << " out of range [" << minrange_ << ", "
<< maxrange_ << "] for open cubic spline", ValueException);
}
}
return spline_.evaluate(distance - minrange_, spacing_, inverse_spacing_);
}
template <unsigned int D>
DerivativePair get_score_and_derivative(
Model *, const Array<D, ParticleIndex> &,
double distance) const {
// check for distance in range
if (distance < minrange_ || distance > maxrange_) {
if (extend_) {
if (distance < minrange_)
return std::make_pair(spline_.get_first(), 0.0);
else
return std::make_pair(spline_.get_last(), 0.0);
} else {
IMP_THROW("Value " << distance << " out of range [" << minrange_ << ", "
<< maxrange_ << "] for open cubic spline", ValueException);
}
}
return spline_.evaluate_with_derivative(distance - minrange_, spacing_,
inverse_spacing_);
}
template <unsigned int D>
double get_maximum_range(
Model *, const Array<D, ParticleIndex> &) const {
if (!extend_ || spline_.get_last() == 0)
return maxrange_;
else
return std::numeric_limits<double>::max();
}
template <unsigned int D>
bool get_is_trivially_zero(Model *,
const Array<D, ParticleIndex> &,
double squared_distance) const {
if (!extend_ || spline_.get_last() == 0) {
return squared_distance > algebra::get_squared(maxrange_);
} else
return false;
}
};
IMPSCOREFUNCTOR_END_NAMESPACE
#endif /* IMPSCORE_FUNCTOR_OPEN_CUBIC_SPLINE_H */