8 #ifndef IMPSAXS_PROFILE_FITTER_H
9 #define IMPSAXS_PROFILE_FITTER_H
18 IMPSAXS_BEGIN_NAMESPACE
28 template <
typename ScoringFunctionT = ChiScore>
36 :
Object(
"ProfileFitter%1%"), exp_profile_(exp_profile) {
38 scoring_function_ =
new ScoringFunctionT();
42 :
Object(
"ProfileFitter%1%"), exp_profile_(exp_profile) {
44 scoring_function_ = sf;
48 double compute_score(
const Profile* model_profile,
bool use_offset =
false,
49 const std::string fit_file_name =
"")
const;
65 FitParameters fit_profile(Profile* partial_profile,
double min_c1 = 0.95,
66 double max_c1 = 1.05,
double min_c2 = -2.0,
67 double max_c2 = 4.0,
bool use_offset =
false,
68 const std::string fit_file_name =
"")
const;
77 double offset = 0.0)
const {
78 return scoring_function_->compute_scale_factor(exp_profile_, model_profile,
89 return scoring_function_->compute_offset(exp_profile_, model_profile);
94 void resample(
const Profile* model_profile,
Profile* resampled_profile)
const;
97 void write_SAXS_fit_file(
const std::string& file_name,
98 const Profile* model_profile,
const double chi_square,
99 const double c = 1,
const double offset = 0)
const;
106 double max_c1,
double min_c2,
double max_c2,
107 bool use_offset,
double old_chi)
const;
118 template <
typename ScoringFunctionT>
121 model_profile->
resample(exp_profile_, resampled_profile);
124 template <
typename ScoringFunctionT>
126 Profile* partial_profile,
double min_c1,
double max_c1,
double min_c2,
127 double max_c2,
bool use_offset,
double old_chi)
const {
130 if (old_chi < (std::numeric_limits<double>::max() - 1)) {
135 double delta_c1 = (max_c1 - min_c1) / c1_cells;
136 double delta_c2 = (max_c2 - min_c2) / c2_cells;
138 bool last_c1 =
false;
139 bool last_c2 =
false;
140 if (delta_c1 < 0.0001) {
142 delta_c1 = max_c1 - min_c1;
145 if (delta_c2 < 0.001) {
147 delta_c2 = max_c2 - min_c2;
150 double best_c1(1.0), best_c2(0.0), best_chi(old_chi);
151 bool best_set =
false;
154 for (
int i = 0; i <= c1_cells; i++, c1 += delta_c1) {
156 for (
int j = 0; j <= c2_cells; j++, c2 += delta_c2) {
158 double curr_chi = compute_score(partial_profile, use_offset);
159 if (!best_set || curr_chi < best_chi) {
168 if (std::fabs(best_chi - old_chi) > 0.0001 &&
169 (!(last_c1 && last_c2))) {
170 min_c1 = std::max(best_c1 - delta_c1, min_c1);
171 max_c1 = std::min(best_c1 + delta_c1, max_c1);
172 min_c2 = std::max(best_c2 - delta_c2, min_c2);
173 max_c2 = std::min(best_c2 + delta_c2, max_c2);
174 return search_fit_parameters(partial_profile, min_c1, max_c1, min_c2,
175 max_c2, use_offset, best_chi);
177 return FitParameters(best_chi, best_c1, best_c2);
180 template <
typename ScoringFunctionT>
182 Profile* partial_profile,
double min_c1,
double max_c1,
double min_c2,
183 double max_c2,
bool use_offset,
const std::string fit_file_name)
const {
186 double default_c1 = 1.0, default_c2 = 0.0;
188 double default_chi = compute_score(partial_profile, use_offset);
191 search_fit_parameters(partial_profile, min_c1, max_c1, min_c2, max_c2,
192 use_offset, std::numeric_limits<double>::max());
193 double best_c1 = fp.get_c1();
194 double best_c2 = fp.get_c2();
195 fp.set_default_chi_square(default_chi);
199 compute_score(partial_profile, use_offset, fit_file_name);
204 template <
typename ScoringFunctionT>
206 const Profile* model_profile,
bool use_offset,
207 const std::string fit_file_name)
const {
209 (exp_profile_->get_min_q(), exp_profile_->get_max_q(),
210 exp_profile_->get_delta_q()));
211 model_profile->
resample(exp_profile_, resampled_profile);
213 double score = scoring_function_->compute_score(exp_profile_,
216 if (fit_file_name.length() > 0) {
220 scoring_function_->compute_offset(exp_profile_, resampled_profile);
221 double c = scoring_function_->compute_scale_factor(exp_profile_,
224 write_SAXS_fit_file(fit_file_name, resampled_profile, score, c, offset);
229 template <
typename ScoringFunctionT>
231 const std::string& file_name,
const Profile* model_profile,
232 const double score,
const double c,
const double offset)
const {
233 std::ofstream out_file(file_name.c_str());
238 unsigned int profile_size =
239 std::min(model_profile->
size(), exp_profile_->size());
241 out_file.precision(15);
242 out_file <<
"# SAXS profile: number of points = " << profile_size
243 <<
", q_min = " << exp_profile_->get_min_q()
244 <<
", q_max = " << exp_profile_->get_max_q();
245 out_file <<
", delta_q = " << exp_profile_->get_delta_q() << std::endl;
247 out_file.setf(std::ios::showpoint);
248 out_file <<
"# offset = " << offset <<
", scaling c = " << c
249 <<
", Chi^2 = " << score << std::endl;
250 out_file <<
"# q exp_intensity model_intensity error" << std::endl;
252 out_file.setf(std::ios::fixed, std::ios::floatfield);
254 for (
unsigned int i = 0; i < profile_size; i++) {
255 out_file.setf(std::ios::left);
257 out_file.precision(8);
258 out_file << exp_profile_->get_q(i) <<
" ";
260 out_file.setf(std::ios::left);
262 out_file.precision(8);
263 out_file << exp_profile_->get_intensity(i) <<
" ";
265 out_file.setf(std::ios::left);
267 out_file.precision(8);
268 out_file << model_profile->get_intensity(i) * c - offset <<
" ";
270 out_file.setf(std::ios::left);
272 out_file.precision(8);
273 out_file << exp_profile_->get_error(i) << std::endl;
279 std::string file_name2 = file_name.substr(0, file_name.length()-4);
280 file_name2 +=
".fit";
281 std::ofstream out_file2(file_name2.c_str());
283 IMP_THROW(
"Can't open file " << file_name2, IOException);
287 out_file2.precision(15);
288 out_file2 <<
"# SAXS profile: number of points = " << profile_size
289 <<
", q_min = " << exp_profile_->get_min_q()
290 <<
", q_max = " << exp_profile_->get_max_q();
291 out_file2 <<
", delta_q = " << exp_profile_->get_delta_q() << std::endl;
293 out_file2.setf(std::ios::showpoint);
294 out_file2 <<
"# offset = " << offset <<
", scaling c = " << c
295 <<
", Chi^2 = " << score << std::endl;
296 out_file2 <<
"# q exp_intensity error model_intensity" << std::endl;
298 out_file2.setf(std::ios::fixed, std::ios::floatfield);
300 for (
unsigned int i = 0; i < profile_size; i++) {
301 out_file2.setf(std::ios::left);
303 out_file2.precision(8);
304 out_file2 << exp_profile_->get_q(i) <<
" ";
306 out_file2.setf(std::ios::left);
308 out_file2.precision(8);
309 out_file2 << exp_profile_->get_intensity(i) <<
" ";
311 out_file2.setf(std::ios::left);
313 out_file2.precision(8);
314 out_file2 << exp_profile_->get_error(i) <<
" ";
316 out_file2.setf(std::ios::left);
318 out_file2.precision(8);
319 out_file2 << model_profile->get_intensity(i) * c - offset << std::endl;
326 IMPSAXS_END_NAMESPACE
unsigned int size() const
return number of entries in SAXS profile
ProfileFitter(const Profile *exp_profile)
Constructor.
Basic chi score implementation.
Parameters of a fit, from ProfileFitter.
#define IMP_REF_COUNTED_DESTRUCTOR(Name)
Set up destructor for a ref counted object.
#define IMP_NEW(Typename, varname, args)
Declare a ref counted pointer to a new object.
An input/output exception.
Common base class for heavy weight IMP objects.
A smart pointer to a ref-counted Object that is a class member.
Copyright 2007-2022 IMP Inventors. All rights reserved.
double compute_offset(const Profile *model_profile) const
computes offset for fitting for fitting the modeled profile
#define IMP_THROW(message, exception_name)
Throw an exception with a message.
A shared base class to help in debugging and things.
void resample(const Profile *exp_profile, Profile *resampled_profile) const
return a profile that is sampled on the q values of the exp_profile
Fit two profiles with user-defined scoring function as a template parameter.
void sum_partial_profiles(double c1, double c2, bool check_cashed=true)
computes full profile for given fitting parameters
double compute_scale_factor(const Profile *model_profile, double offset=0.0) const
computes the scaling factor needed for fitting the modeled profile
const Profile * get_profile() const
A class for profile storing and computation.