8 #ifndef IMPSAXS_PROFILE_FITTER_H
9 #define IMPSAXS_PROFILE_FITTER_H
18 IMPSAXS_BEGIN_NAMESPACE
29 template<
class ScoringFunctionT = ChiScore>
37 exp_profile_(exp_profile) {
39 scoring_function_ =
new ScoringFunctionT();
43 ScoringFunctionT* sf): base::Object(
"ProfileFitter%1%"),
44 exp_profile_(exp_profile) {
46 scoring_function_ = sf;
50 Float compute_score(
const Profile* model_profile,
51 bool use_offset =
false,
52 const std::string fit_file_name =
"")
const;
55 Float compute_score(
const Profile* model_profile,
72 FitParameters fit_profile(Profile* partial_profile,
73 float min_c1=0.95,
float max_c1=1.05,
74 float min_c2=-2.0,
float max_c2=4.0,
75 bool use_offset =
false,
76 const std::string fit_file_name =
"")
const;
85 Float offset = 0.0)
const {
86 return scoring_function_->compute_scale_factor(exp_profile_, model_profile,
97 return scoring_function_->compute_offset(exp_profile_, model_profile);
102 void resample(
const Profile* model_profile,
Profile* resampled_profile)
const;
105 void write_SAXS_fit_file(
const std::string& file_name,
107 const Float chi_square,
111 FitParameters search_fit_parameters(
Profile* partial_profile,
112 float min_c1,
float max_c1,
113 float min_c2,
float max_c2,
114 bool use_offset,
float old_chi)
const;
123 ScoringFunctionT* scoring_function_;
126 template<
class ScoringFunctionT>
128 Profile* resampled_profile)
const
130 model_profile->
resample(exp_profile_, resampled_profile);
133 template<
class ScoringFunctionT>
136 float min_c1,
float max_c1,
137 float min_c2,
float max_c2,
138 bool use_offset,
float old_chi)
const
142 if(old_chi < (std::numeric_limits<float>::max()-1)) {
147 float delta_c1 = (max_c1-min_c1)/c1_cells;
148 float delta_c2 = (max_c2-min_c2)/c2_cells;
150 bool last_c1 =
false;
151 bool last_c2 =
false;
152 if(delta_c1 < 0.0001) { c1_cells=1; delta_c1 = max_c1-min_c1; last_c1=
true; }
153 if(delta_c2 < 0.001) { c2_cells=1; delta_c2 = max_c2-min_c2; last_c2=
true; }
154 float best_c1(1.0), best_c2(0.0), best_chi(old_chi);
155 bool best_set =
false;
158 for(
int i=0; i<=c1_cells; i++, c1+= delta_c1) {
160 for(
int j=0; j<=c2_cells; j++, c2+= delta_c2) {
162 float curr_chi = compute_score(partial_profile, use_offset);
163 if(!best_set || curr_chi < best_chi) {
172 if(std::fabs(best_chi-old_chi) > 0.0001 &&
173 (!(last_c1 && last_c2))) {
174 min_c1 = std::max(best_c1-delta_c1, min_c1);
175 max_c1 = std::min(best_c1+delta_c1, max_c1);
176 min_c2 = std::max(best_c2-delta_c2, min_c2);
177 max_c2 = std::min(best_c2+delta_c2, max_c2);
178 return search_fit_parameters(partial_profile,
179 min_c1, max_c1, min_c2, max_c2,
180 use_offset, best_chi);
182 return FitParameters(best_chi, best_c1, best_c2);
185 template<
class ScoringFunctionT>
188 float min_c1,
float max_c1,
189 float min_c2,
float max_c2,
191 const std::string fit_file_name)
const {
194 float default_c1 = 1.0, default_c2 = 0.0;
196 float default_chi = compute_score(partial_profile, use_offset);
198 FitParameters fp = search_fit_parameters(partial_profile,
199 min_c1, max_c1, min_c2, max_c2,
201 std::numeric_limits<float>::max());
202 float best_c1 = fp.get_c1();
203 float best_c2 = fp.get_c2();
204 fp.set_default_chi(default_chi);
208 compute_score(partial_profile, use_offset, fit_file_name);
215 template<
class ScoringFunctionT>
221 exp_profile_->get_max_q(),
222 exp_profile_->get_delta_q()));
223 model_profile->
resample(exp_profile_, resampled_profile);
225 Float score = scoring_function_->compute_score(exp_profile_,
231 template<
class ScoringFunctionT>
235 const std::string fit_file_name)
const
238 exp_profile_->get_max_q(),
239 exp_profile_->get_delta_q()));
240 model_profile->
resample(exp_profile_, resampled_profile);
242 Float score = scoring_function_->compute_score(exp_profile_,
246 if(fit_file_name.length() > 0) {
249 offset=scoring_function_->compute_offset(exp_profile_,
251 Float c= scoring_function_->compute_scale_factor(exp_profile_,
254 write_SAXS_fit_file(fit_file_name, resampled_profile, score, c, offset);
259 template<
class ScoringFunctionT>
261 const std::string& file_name,
265 const Float offset)
const {
266 std::ofstream out_file(file_name.c_str());
268 IMP_THROW(
"Can't open file " << file_name,
272 unsigned int profile_size = std::min(model_profile->
size(),
273 exp_profile_->size());
275 out_file.precision(15);
276 out_file <<
"# SAXS profile: number of points = " << profile_size
277 <<
", q_min = " << exp_profile_->get_min_q()
278 <<
", q_max = " << exp_profile_->get_max_q();
279 out_file <<
", delta_q = " << exp_profile_->get_delta_q() << std::endl;
281 out_file.setf(std::ios::showpoint);
282 out_file <<
"# offset = " << offset <<
", scaling c = " << c
283 <<
", Chi = " << score << std::endl;
284 out_file <<
"# q exp_intensity model_intensity"
287 out_file.setf(std::ios::fixed, std::ios::floatfield);
289 for (
unsigned int i = 0; i < profile_size; i++) {
290 out_file.setf(std::ios::left);
292 out_file.precision(5);
293 out_file << exp_profile_->get_q(i) <<
" ";
295 out_file.setf(std::ios::left);
297 out_file.precision(8);
298 out_file << exp_profile_->get_intensity(i) <<
" ";
300 out_file.setf(std::ios::left);
302 out_file.precision(8);
303 out_file << model_profile->get_intensity(i)*c - offset << std::endl;
308 IMPSAXS_END_NAMESPACE
unsigned int size() const
return number of entries in SAXS profile
ProfileFitter(const Profile *exp_profile)
Constructor.
Basic chi score implementation.
void resample(const Profile *exp_profile, Profile *resampled_profile, bool partial_profiles=false) const
return a profile that is sampled on the q values of the exp_profile
A smart pointer to a ref-counted Object that is a class memeber.
#define IMP_REF_COUNTED_DESTRUCTOR(Name)
Ref counted objects should have private destructors.
#define IMP_NEW(Typename, varname, args)
Declare a ref counted pointer to a new object.
Float compute_scale_factor(const Profile *model_profile, Float offset=0.0) const
computes the scaling factor needed for fitting the modeled profile
void sum_partial_profiles(Float c1, Float c2)
computes full profile for given fitting parameters
Copyright 2007-2013 IMP Inventors. All rights reserved.
Common base class for heavy weight IMP objects.
Float 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.
double Float
Basic floating-point value (could be float, double...)
A shared base class to help in debugging and things.
A class for profile storing and computation.