00001 #ifndef CCTBX_GEOMETRY_RESTRAINTS_BOND_SIMILARITY_H
00002 #define CCTBX_GEOMETRY_RESTRAINTS_BOND_SIMILARITY_H
00003
00004 #include <cctbx/sgtbx/rt_mx.h>
00005 #include <cctbx/geometry_restraints/utils.h>
00006 #include <scitbx/optional_copy.h>
00007
00008 namespace cctbx { namespace geometry_restraints {
00009
00012 struct bond_similarity_proxy
00013 {
00015 typedef af::shared<af::tiny<std::size_t, 2> > i_seqs_type;
00016
00018 bond_similarity_proxy() {}
00019
00021 bond_similarity_proxy(
00022 i_seqs_type const& i_seqs_,
00023 af::shared<double> const& weights_)
00024 :
00025 weights(weights_),
00026 i_seqs(i_seqs_)
00027 {}
00028
00030 bond_similarity_proxy(
00031 i_seqs_type const& i_seqs_,
00032 af::shared<sgtbx::rt_mx> const& sym_ops_,
00033 af::shared<double> const& weights_)
00034 :
00035 weights(weights_),
00036 i_seqs(i_seqs_),
00037 sym_ops(sym_ops_)
00038 {}
00039
00041 af::shared<double> weights;
00043 i_seqs_type i_seqs;
00044
00047
00050 scitbx::optional_copy<af::shared<sgtbx::rt_mx> > sym_ops;
00051 };
00052
00054 class bond_similarity
00055 {
00056 public:
00058 typedef scitbx::vec3<double> vec3;
00059
00061 bond_similarity() {}
00062
00064 bond_similarity(
00065 af::shared<af::tiny<vec3, 2> > const& sites_array_,
00066 af::shared<double> const& weights_)
00067 :
00068 sites_array(sites_array_),
00069 weights(weights_)
00070 {
00071 init_deltas();
00072 }
00073
00077 bond_similarity(
00078 af::const_ref<vec3> const& sites_cart,
00079 bond_similarity_proxy const& proxy)
00080 :
00081 weights(proxy.weights)
00082 {
00083 sites_array.reserve(proxy.i_seqs.size());
00084 for(int i=0;i<proxy.i_seqs.size();i++) {
00085 af::tiny<vec3, 2> sites;
00086 for(int j=0;j<2;j++) {
00087 std::size_t i_seq = proxy.i_seqs[i][j];
00088 CCTBX_ASSERT(i_seq < sites_cart.size());
00089 sites[j] = sites_cart[i_seq];
00090 }
00091 sites_array.push_back(sites);
00092 }
00093 init_deltas();
00094 }
00095
00100 bond_similarity(
00101 uctbx::unit_cell const& unit_cell,
00102 af::const_ref<vec3> const& sites_cart,
00103 bond_similarity_proxy const& proxy)
00104 :
00105 weights(proxy.weights)
00106 {
00107 sites_array.reserve(proxy.i_seqs.size());
00108 for(int i=0;i<proxy.i_seqs.size();i++) {
00109 af::tiny<vec3, 2> sites;
00110 for(int j=0;j<2;j++) {
00111 std::size_t i_seq = proxy.i_seqs[i][j];
00112 CCTBX_ASSERT(i_seq < sites_cart.size());
00113 sites[j] = sites_cart[i_seq];
00114 }
00115 if ( proxy.sym_ops.get() ) {
00116 sgtbx::rt_mx rt_mx = proxy.sym_ops[i];
00117 if ( !rt_mx.is_unit_mx() ) {
00118 sites[1] = unit_cell.orthogonalize(
00119 rt_mx * unit_cell.fractionalize(sites[1]));
00120 }
00121 }
00122 sites_array.push_back(sites);
00123 }
00124 init_deltas();
00125 }
00126
00128 af::shared<double> const&
00129 deltas() const { return deltas_; }
00130
00132 double
00133 rms_deltas() const {
00134 return std::sqrt(af::mean_sq(deltas_.const_ref()));
00135 }
00136
00138 double
00139 residual() const
00140 {
00141 double result = 0;
00142 af::const_ref<double> weights_ref = weights.const_ref();
00143 af::const_ref<double> deltas_ref = deltas_.const_ref();
00144 for(std::size_t i_site=0;i_site<deltas_ref.size();i_site++) {
00145 result += weights_ref[i_site]
00146 * scitbx::fn::pow2(deltas_ref[i_site])
00147 / sum_weights_;
00148 }
00149 return result;
00150 }
00151
00153 af::shared<af::tiny<vec3, 2> >
00154 gradients() const
00155 {
00156 af::shared<af::tiny<vec3, 2> > result;
00157 af::tiny<vec3, 2> pair_grads;
00158 af::const_ref<double> weights_ref = weights.const_ref();
00159 af::const_ref<double> deltas_ref = deltas_.const_ref();
00160 af::const_ref<double> distances_ref
00161 = bond_distances_.const_ref();
00162 result.reserve(deltas_ref.size());
00163 for(std::size_t i_pair=0;i_pair<deltas_ref.size();i_pair++) {
00164 vec3 grad_0 = (2 * weights_ref[i_pair] * deltas_ref[i_pair])
00165 / (distances_ref[i_pair] * sum_weights_)
00166 * (sites_array[i_pair][0] - sites_array[i_pair][1]);
00167 pair_grads[0] = grad_0;
00168 pair_grads[1] = -grad_0;
00169 result.push_back(pair_grads);
00170 }
00171 return result;
00172 }
00173
00175
00177 void
00178 add_gradients(
00179 af::ref<scitbx::vec3<double> > const& gradient_array,
00180 bond_similarity_proxy::i_seqs_type const& i_seqs) const
00181 {
00182 af::const_ref<af::tiny<std::size_t, 2> > i_seqs_ref = i_seqs.const_ref();
00183 af::shared<af::tiny<vec3, 2> > grads = gradients();
00184 af::const_ref<af::tiny<vec3, 2> > grads_ref = grads.const_ref();
00185 for(std::size_t i=0;i<grads_ref.size();i++) {
00186 gradient_array[i_seqs_ref[i][0]] += grads_ref[i][0];
00187 gradient_array[i_seqs_ref[i][1]] += grads_ref[i][1];
00188 }
00189 }
00190
00192
00197 void
00198 add_gradients(
00199 uctbx::unit_cell const& unit_cell,
00200 af::ref<scitbx::vec3<double> > const& gradient_array,
00201 bond_similarity_proxy const& proxy) const
00202 {
00203 af::const_ref<af::tiny<std::size_t, 2> > i_seqs_ref
00204 = proxy.i_seqs.const_ref();
00205 scitbx::optional_copy<af::shared<sgtbx::rt_mx> > const& sym_ops = proxy.sym_ops;
00206 af::shared<af::tiny<vec3, 2> > grads = gradients();
00207 af::const_ref<af::tiny<vec3, 2> > grads_ref = grads.const_ref();
00208 for(std::size_t i=0;i<grads_ref.size();i++) {
00209 gradient_array[i_seqs_ref[i][0]] += grads_ref[i][0];
00210 sgtbx::rt_mx const& rt_mx = sym_ops[i];
00211 if ( sym_ops.get() && !sym_ops[i].is_unit_mx() ) {
00212 scitbx::mat3<double> r_inv_cart_ = r_inv_cart(unit_cell, sym_ops[i]);
00213 gradient_array[i_seqs_ref[i][1]] += grads_ref[i][1] * r_inv_cart_;
00214 }
00215 else gradient_array[i_seqs_ref[i][1]] += grads_ref[i][1];
00216 }
00217 }
00218
00220 double
00221 mean_distance() const { return mean_distance_; }
00223 af::shared<af::tiny<vec3, 2> > sites_array;
00225 af::shared<double> weights;
00226
00227 protected:
00228 double mean_distance_;
00229 double sum_weights_;
00230 af::shared<double> deltas_;
00231 af::shared<double> bond_distances_;
00232
00233 void
00234 init_deltas()
00235 {
00236 af::const_ref<af::tiny<vec3, 2> > sites_ref
00237 = sites_array.const_ref();
00238 af::const_ref<double> weights_ref = weights.const_ref();
00239 bond_distances_.reserve(sites_ref.size());
00240 mean_distance_ = 0;
00241 sum_weights_ = 0;
00242 for (std::size_t i_pair=0;i_pair<sites_array.size();i_pair++) {
00243 double w = weights_ref[i_pair];
00244 af::tiny<vec3, 2> sites = sites_array[i_pair];
00245 bond_distances_.push_back((sites[0] - sites[1]).length());
00246 mean_distance_ += w * bond_distances_[i_pair];
00247 sum_weights_ += w;
00248 }
00249 CCTBX_ASSERT(sum_weights_ > 0);
00250 mean_distance_ /= sum_weights_;
00251 deltas_.reserve(sites_ref.size());
00252 for (std::size_t i_pair=0;i_pair<sites_array.size();i_pair++) {
00253 deltas_.push_back(bond_distances_[i_pair] - mean_distance_);
00254 }
00255 }
00256 };
00257
00261 inline
00262 af::shared<double>
00263 bond_similarity_deltas_rms(
00264 af::const_ref<scitbx::vec3<double> > const& sites_cart,
00265 af::const_ref<bond_similarity_proxy> const& proxies)
00266 {
00267 af::shared<double> result((af::reserve(proxies.size())));
00268 for(std::size_t i=0;i<proxies.size();i++) {
00269 result.push_back(bond_similarity(sites_cart, proxies[i]).rms_deltas());
00270 }
00271 return result;
00272 }
00273
00277 inline
00278 af::shared<double>
00279 bond_similarity_residuals(
00280 af::const_ref<scitbx::vec3<double> > const& sites_cart,
00281 af::const_ref<bond_similarity_proxy> const& proxies)
00282 {
00283 return detail::generic_residuals<bond_similarity_proxy,
00284 bond_similarity>::get(sites_cart, proxies);
00285 }
00286
00296 inline
00297 double
00298 bond_similarity_residual_sum(
00299 af::const_ref<scitbx::vec3<double> > const& sites_cart,
00300 af::const_ref<bond_similarity_proxy> const& proxies,
00301 af::ref<scitbx::vec3<double> > const& gradient_array)
00302 {
00303 return detail::generic_residual_sum<bond_similarity_proxy,
00304 bond_similarity>::get(sites_cart, proxies, gradient_array);
00305 }
00306
00310 inline
00311 af::shared<double>
00312 bond_similarity_deltas_rms(
00313 uctbx::unit_cell const& unit_cell,
00314 af::const_ref<scitbx::vec3<double> > const& sites_cart,
00315 af::const_ref<bond_similarity_proxy> const& proxies)
00316 {
00317 af::shared<double> result((af::reserve(proxies.size())));
00318 for(std::size_t i=0;i<proxies.size();i++) {
00319 result.push_back(bond_similarity(
00320 unit_cell, sites_cart, proxies[i]).rms_deltas());
00321 }
00322 return result;
00323 }
00324
00328 inline
00329 af::shared<double>
00330 bond_similarity_residuals(
00331 uctbx::unit_cell const& unit_cell,
00332 af::const_ref<scitbx::vec3<double> > const& sites_cart,
00333 af::const_ref<bond_similarity_proxy> const& proxies)
00334 {
00335 return detail::generic_residuals<bond_similarity_proxy,
00336 bond_similarity>::get(
00337 unit_cell, sites_cart, proxies);
00338 }
00339
00349 inline
00350 double
00351 bond_similarity_residual_sum(
00352 uctbx::unit_cell const& unit_cell,
00353 af::const_ref<scitbx::vec3<double> > const& sites_cart,
00354 af::const_ref<bond_similarity_proxy> const& proxies,
00355 af::ref<scitbx::vec3<double> > const& gradient_array)
00356 {
00357 return detail::generic_residual_sum<bond_similarity_proxy,
00358 bond_similarity>::get(
00359 unit_cell, sites_cart, proxies, gradient_array);
00360 }
00361
00362 }}
00363
00364 #endif // CCTBX_GEOMETRY_RESTRAINTS_BOND_SIMILARITY_H