/** * \file DerivativeCalculator \brief A class for computing SAXS derivatives * * Copyright 2007-2013 IMP Inventors. All rights reserved. * */ #include #include #include #define IMP_SAXS_DELTA_LIMIT 1.0e-15 IMPSAXS_BEGIN_NAMESPACE DerivativeCalculator::DerivativeCalculator(const Profile& exp_profile) : exp_profile_(exp_profile) {} //tabulates (sin(qr)/qr - cos(qr))/r^2 over the range of qs of the profile //and up to max_distance for r. void DerivativeCalculator::compute_sinc_cos(Float pr_resolution, Float max_distance, const Profile& model_profile, std::vector& output_values) const { //can be input unsigned int nr=algebra::get_rounded(max_distance/pr_resolution) + 1; output_values.clear(); unsigned int profile_size = std::min(model_profile.size(), exp_profile_.size()); Floats r_size(nr, 0.0); output_values.insert(output_values.begin(), profile_size, r_size); for(unsigned int iq = 0; iq& profile_diff) const { // compute difference of intensities and squares of weight // profile_diff[q] = -2 * c * weight_tilda * (I_exp[q] - c*I_mod[q] + offset) unsigned int profile_size = std::min(model_profile.size(), exp_profile_.size()); profile_diff.clear(); profile_diff.resize(profile_size, 0.0); for (unsigned int iq=0; iq DerivativeCalculator::compute_gaussian_effect_size( const Profile& model_profile, const ProfileFitter* pf, bool use_offset) const { Float offset = 0.0; if(use_offset) offset = pf->compute_offset(model_profile); Float c = pf->compute_scale_factor(model_profile); std::vector effect_size; compute_profile_difference(model_profile, c, offset, effect_size); return effect_size; } /* * precompute sinc_cos function and derivative of distance distribution */ DeltaDistributionFunction DerivativeCalculator::precompute_derivative_helpers( const Profile& resampled_model_profile, const Particles& particles1, const Particles& particles2, std::vector& sinc_cos_values) const { // estimate upper limit on max_distance Float max_distance = compute_max_distance(particles1, particles2); DeltaDistributionFunction delta_dist = DeltaDistributionFunction(particles2, max_distance); // (sinc(qr) - cos(qr)) / (r*r) compute_sinc_cos(delta_dist.get_bin_size(), max_distance, resampled_model_profile, sinc_cos_values); return delta_dist; } /* compute dI(q)/dx_k for given q and k dI(q)/dx_k = - 2 E^2(q) \sum_l * (x_k-x_l)/d_{kl}^2 f_l f_k (sinc(q*d_{kl}) - * cos(q*d_{kl})) */ void DerivativeCalculator::compute_intensity_derivatives( const DeltaDistributionFunction& delta_dist, const std::vector& sinc_cos_values, unsigned int iq, algebra::Vector3D &dIdx) const { dIdx = algebra::Vector3D(0.0, 0.0, 0.0); for (unsigned int ir=0; ir& derivatives, const std::vector& effect_size) const { algebra::Vector3D dIdx, chisquare_derivative; std::vector sinc_cos_values; DeltaDistributionFunction delta_dist = precompute_derivative_helpers(model_profile, particles1, particles2, sinc_cos_values); unsigned int profile_size = std::min(model_profile.size(), exp_profile_.size()); derivatives.clear(); derivatives.resize(particles1.size()); for (unsigned int iatom=0; iatom& rigid_bodies, const std::vector& rigid_bodies_decorators, const Profile& model_profile, const std::vector& effect_size, DerivativeAccumulator *acc) const { std::vector > derivatives; const FloatKeys keys = IMP::core::XYZ::get_xyz_keys(); // 1. compute derivatives for each rigid body for(unsigned int i=0; iadd_to_derivative(keys[0],derivatives[k][0], *acc); rigid_bodies[i][k]->add_to_derivative(keys[1],derivatives[k][1], *acc); rigid_bodies[i][k]->add_to_derivative(keys[2],derivatives[k][2], *acc); } } if(particles.size() > 0) { // contribution from other particles compute_chisquare_derivative(model_profile, rigid_bodies[i], particles, derivatives, effect_size); for (unsigned int k = 0; k < rigid_bodies[i].size(); k++) { rigid_bodies[i][k]->add_to_derivative(keys[0],derivatives[k][0], *acc); rigid_bodies[i][k]->add_to_derivative(keys[1],derivatives[k][1], *acc); rigid_bodies[i][k]->add_to_derivative(keys[2],derivatives[k][2], *acc); } } } // 2. compute derivatives for other particles if(particles.size() > 0) { // particles own contribution compute_chisquare_derivative(model_profile, particles, derivatives, effect_size); for (unsigned int i = 0; i < particles.size(); i++) { particles[i]->add_to_derivative(keys[0], derivatives[i][0], *acc); particles[i]->add_to_derivative(keys[1], derivatives[i][1], *acc); particles[i]->add_to_derivative(keys[2], derivatives[i][2], *acc); } // rigid bodies contribution for(unsigned int i=0; iadd_to_derivative(keys[0], derivatives[i][0], *acc); particles[i]->add_to_derivative(keys[1], derivatives[i][1], *acc); particles[i]->add_to_derivative(keys[2], derivatives[i][2], *acc); } } } } IMPSAXS_END_NAMESPACE