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