IMP logo
IMP Reference Guide  develop.b3a5ae88fa,2024/05/01
The Integrative Modeling Platform
SAXSMultiStateModelScore.h
Go to the documentation of this file.
1 /**
2  * \file IMP/multi_state/SAXSMultiStateModelScore.h
3  * \brief
4  *
5  * \authors Dina Schneidman
6  * Copyright 2007-2022 IMP Inventors. All rights reserved.
7  *
8  */
9 
10 #ifndef IMPMULTI_STATE_SAXS_MULTI_STATE_MODEL_SCORE_H
11 #define IMPMULTI_STATE_SAXS_MULTI_STATE_MODEL_SCORE_H
12 
13 #include "MultiStateModelScore.h"
14 #include "MultiStateModel.h"
15 
16 #include <IMP/saxs/Profile.h>
18 #include <IMP/Object.h>
19 
20 #include <vector>
21 
22 IMPMULTISTATE_BEGIN_NAMESPACE
23 
24 /** Score multi-state models against SAXS profiles */
25 template <typename ScoringFunctionT>
27 public:
28 
29  /* if c1_c2_approximate=true, get_score will return approximate score
30  based on average c1/c2
31  min_weight_threshold, multi-state models with one or more weights below
32  min_weight_threshold will get a negative score
33  */
35  const saxs::Profile* exp_profile,
36  bool c1_c2_approximate,
37  double min_c1 = 0.99, double max_c1 = 1.05,
38  double min_c2 = -0.5, double max_c2 = 2.0,
39  bool use_offset = false);
40 
41  double get_score(const MultiStateModel& m) const override;
42 
43  double get_score(const MultiStateModel& m,
44  Vector<double>& weights) const override;
45 
46  saxs::WeightedFitParameters get_fit_parameters(
47  MultiStateModel& m) const override;
48 
49  saxs::WeightedFitParameters get_fit_parameters() const override;
50 
51  void write_fit_file(MultiStateModel& m,
53  const std::string fit_file_name) const override;
54 
55  std::string get_state_name(unsigned int id) const override {
56  return profiles_[id]->get_name();
57  }
58 
59  std::string get_dataset_name() const override {
60  return exp_profile_->get_name();
61  }
62 
63  double get_average_c1() const { return average_c1_; }
64  double get_average_c2() const { return average_c2_; }
65 
66  void set_average_c1_c2(const Vector<saxs::WeightedFitParameters>& fps);
67 
68 private:
69  void resample(const saxs::Profile* exp_profile,
70  const saxs::Profiles& profiles,
71  saxs::Profiles& resampled_profiles);
72 
73  void set_average_c1_c2(saxs::WeightedProfileFitter<ScoringFunctionT>* score,
74  const saxs::Profiles& profiles);
75 
76 private:
77  // input profiles
78  const saxs::Profiles profiles_;
80 
81  // resampled on experimental profile q's
82  saxs::Profiles resampled_profiles_;
83 
84  // scoring with exp_profile_
86 
87  double min_c1_, max_c1_, min_c2_, max_c2_;
88  double average_c1_, average_c2_;
89 
90  // approximate c1/c2 at get_score(), do accurate fitting at get_fit_parameters()
91  bool c1_c2_approximate_;
92 
93  // do not perform any c1/c2 fitting
94  bool c1_c2_no_fitting_;
95 
96  bool use_offset_;
97 };
98 
99 template <typename ScoringFunctionT>
101  const saxs::Profiles& profiles,
102  const saxs::Profile* exp_profile,
103  bool c1_c2_approximate,
104  double min_c1, double max_c1,
105  double min_c2, double max_c2,
106  bool use_offset) :
107  profiles_(profiles), exp_profile_(exp_profile),
108  min_c1_(min_c1), max_c1_(max_c1), min_c2_(min_c2), max_c2_(max_c2),
109  c1_c2_approximate_(c1_c2_approximate), c1_c2_no_fitting_(false),
110  use_offset_(use_offset) {
111 
112  if(profiles_.size() < 1) {
113  IMP_THROW("SAXSMultiStateModelScore - please provide at least one profile"
114  << std::endl, IOException);
115  }
116 
117  // resample all models profiles
118  resample(exp_profile_, profiles_, resampled_profiles_);
119 
120  // init scoring object
121  score_ = new saxs::WeightedProfileFitter<ScoringFunctionT>(exp_profile_);
122 
123  // compute average c1/c2
124  set_average_c1_c2(score_, resampled_profiles_);
125 }
126 
127 template <typename ScoringFunctionT>
128 void SAXSMultiStateModelScore<ScoringFunctionT>::resample(
129  const saxs::Profile* exp_profile,
130  const saxs::Profiles& profiles,
131  saxs::Profiles& resampled_profiles) {
132 
133  resampled_profiles.reserve(profiles.size());
134  for(unsigned int i=0; i<profiles.size(); i++) {
135  saxs::Profile *resampled_profile =
136  new saxs::Profile(exp_profile->get_min_q(), exp_profile->get_max_q(),
137  exp_profile->get_delta_q());
138  profiles[i]->resample(exp_profile, resampled_profile);
139  resampled_profiles.push_back(resampled_profile);
140  if(!profiles[i]->is_partial_profile()) c1_c2_no_fitting_ = true;
141  }
142 }
143 
144 template <typename ScoringFunctionT>
145 void SAXSMultiStateModelScore<ScoringFunctionT>::set_average_c1_c2(
146  saxs::WeightedProfileFitter<ScoringFunctionT>* score,
147  const saxs::Profiles& profiles) {
148  if(c1_c2_no_fitting_) return;
149  average_c1_ = 0.0;
150  average_c2_ = 0.0;
151  saxs::ProfilesTemp profiles_temp(1);
152  for(unsigned int i=0; i<profiles.size(); i++) {
153  profiles_temp[0] = profiles[i];
154  saxs::WeightedFitParameters fp =
155  score->fit_profile(profiles_temp, min_c1_, max_c1_, min_c2_, max_c2_, use_offset_);
156  average_c1_ += fp.get_c1();
157  average_c2_ += fp.get_c2();
158  }
159  average_c1_ /= profiles.size();
160  average_c2_ /= profiles.size();
161 }
162 
163 template <typename ScoringFunctionT>
164 void SAXSMultiStateModelScore<ScoringFunctionT>::set_average_c1_c2(
165  const Vector<saxs::WeightedFitParameters>& fps) {
166  if(c1_c2_no_fitting_) return;
167  double c1 = 0.0;
168  double c2 = 0.0;
169  for(unsigned int i=0; i<fps.size(); i++) {
170  c1 += fps[i].get_c1();
171  c2 += fps[i].get_c2();
172  }
173  c1 /= fps.size();
174  c2 /= fps.size();
175 
176  average_c1_ = c1;
177  average_c2_ = c2;
178 }
179 
180 
181 template <typename ScoringFunctionT>
182 double SAXSMultiStateModelScore<ScoringFunctionT>::get_score(const MultiStateModel& m,
183  Vector<double>& weights) const {
184  const Vector<unsigned int>& states = m.get_states();
185  saxs::ProfilesTemp profiles(states.size());
186  for(unsigned int i=0; i<states.size(); i++) {
187  profiles[i] = resampled_profiles_[states[i]];
188  if(c1_c2_approximate_ && !c1_c2_no_fitting_)
189  profiles[i]->sum_partial_profiles(average_c1_, average_c2_);
190  }
191 
192  double chi_square;
193  if(c1_c2_approximate_ || c1_c2_no_fitting_) { // just score calculation
194  chi_square = score_->compute_score(profiles, weights, use_offset_);
195  } else { // optimize c1/c2 fit and score
196  saxs::WeightedFitParameters fp =
197  score_->fit_profile(profiles, min_c1_, max_c1_, min_c2_, max_c2_, use_offset_);
198  chi_square = fp.get_chi_square();
199  }
200  return chi_square;
201 }
202 
203 template <typename ScoringFunctionT>
204 double SAXSMultiStateModelScore<ScoringFunctionT>::get_score(const MultiStateModel& m) const {
205  Vector<double> weights;
206  return get_score(m, weights);
207 }
208 
209 
210 template <typename ScoringFunctionT>
211 saxs::WeightedFitParameters
212  SAXSMultiStateModelScore<ScoringFunctionT>::get_fit_parameters(MultiStateModel& m) const {
213 
214  if(c1_c2_no_fitting_) {
215  Vector<double> weights;
216  double s = get_score(m, weights);
217  saxs::WeightedFitParameters wfp(s, 1.0, 0.0, weights);
218  return wfp;
219  }
220 
221  const Vector<unsigned int>& states = m.get_states();
222  saxs::ProfilesTemp profiles(states.size());
223  for(unsigned int i=0; i<states.size(); i++)
224  profiles[i] = resampled_profiles_[states[i]];
225 
226  saxs::WeightedFitParameters fp =
227  score_->fit_profile(profiles, min_c1_, max_c1_, min_c2_, max_c2_, use_offset_);
228  m.set_score(fp.get_chi_square());
229  return fp;
230 }
231 
232 template <typename ScoringFunctionT>
233 saxs::WeightedFitParameters
234  SAXSMultiStateModelScore<ScoringFunctionT>::get_fit_parameters() const {
235 
236  if(c1_c2_no_fitting_) {
237  Vector<double> weights;
238  double s = score_->compute_score(resampled_profiles_, weights, use_offset_);
239  saxs::WeightedFitParameters wfp(s, 1.0, 0.0, weights);
240  return wfp;
241  }
242 
243  saxs::WeightedFitParameters fp = score_->fit_profile(resampled_profiles_,
244  min_c1_, max_c1_,
245  min_c2_, max_c2_, use_offset_);
246  return fp;
247 }
248 
249 template <typename ScoringFunctionT>
250 void SAXSMultiStateModelScore<ScoringFunctionT>::write_fit_file(MultiStateModel& m,
251  const saxs::WeightedFitParameters& fp,
252  const std::string fit_file_name) const {
253 
254  const Vector<unsigned int>& states = m.get_states();
255  saxs::ProfilesTemp profiles(states.size());
256  for(unsigned int i=0; i<states.size(); i++)
257  profiles[i] = resampled_profiles_[states[i]];
258  score_->write_fit_file(profiles, fp, fit_file_name, use_offset_);
259 }
260 
261 IMPMULTISTATE_END_NAMESPACE
262 
263 #endif /* IMPMULTI_STATE_SAXS_MULTI_STATE_MODEL_SCORE_H */
IMP::Vector< IMP::Pointer< Profile > > Profiles
Definition: Profile.h:336
base class for MultiStateModel scoring classes
Fitting of multiple profiles to the experimental one. The weights of the profiles are computed analyt...
Base class for MultiStateModel scoring classes.
A more IMP-like version of the std::vector.
Definition: Vector.h:50
An input/output exception.
Definition: exception.h:173
Fitting of multiple profiles to the experimental one.
Keep track of multiple states.
IMP::Vector< IMP::WeakPointer< Profile > > ProfilesTemp
Definition: Profile.h:336
#define IMP_THROW(message, exception_name)
Throw an exception with a message.
Definition: check_macros.h:50
Parameters of a weighted fit, from WeightedProfileFitter.
A shared base class to help in debugging and things.
Keep track of multiple states.
A class for profile storing and computation.