00001 #ifndef CCTBX_GEOMETRY_RESTRAINTS_CHIRALITY_H
00002 #define CCTBX_GEOMETRY_RESTRAINTS_CHIRALITY_H
00003
00004 #include <cctbx/geometry_restraints/utils.h>
00005
00006 namespace cctbx { namespace geometry_restraints {
00007
00009 struct chirality_proxy
00010 {
00012 typedef af::tiny<unsigned, 4> i_seqs_type;
00013
00015 chirality_proxy() {}
00016
00018 chirality_proxy(
00019 i_seqs_type const& i_seqs_,
00020 double volume_ideal_,
00021 bool both_signs_,
00022 double weight_)
00023 :
00024 i_seqs(i_seqs_),
00025 volume_ideal(volume_ideal_),
00026 both_signs(both_signs_),
00027 weight(weight_)
00028 {}
00029
00031 chirality_proxy(
00032 i_seqs_type const& i_seqs_,
00033 chirality_proxy const& other)
00034 :
00035 i_seqs(i_seqs_),
00036 volume_ideal(other.volume_ideal),
00037 both_signs(other.both_signs),
00038 weight(other.weight)
00039 {}
00040
00042 chirality_proxy
00043 sort_i_seqs() const
00044 {
00045 chirality_proxy result(*this);
00046 for(unsigned i=1;i<3;i++) {
00047 for(unsigned j=i+1;j<4;j++) {
00048 if (result.i_seqs[i] > result.i_seqs[j]) {
00049 std::swap(result.i_seqs[i], result.i_seqs[j]);
00050 if (!both_signs) result.volume_ideal *= -1;
00051 }
00052 }
00053 }
00054 return result;
00055 }
00056
00058 i_seqs_type i_seqs;
00060 double volume_ideal;
00062 bool both_signs;
00064 double weight;
00065 };
00066
00068 class chirality
00069 {
00070 public:
00072 chirality() {}
00073
00075 chirality(
00076 af::tiny<scitbx::vec3<double>, 4> const& sites_,
00077 double volume_ideal_,
00078 bool both_signs_,
00079 double weight_)
00080 :
00081 sites(sites_),
00082 volume_ideal(volume_ideal_),
00083 both_signs(both_signs_),
00084 weight(weight_)
00085 {
00086 init_volume_model();
00087 }
00088
00092 chirality(
00093 af::const_ref<scitbx::vec3<double> > const& sites_cart,
00094 chirality_proxy const& proxy)
00095 :
00096 volume_ideal(proxy.volume_ideal),
00097 both_signs(proxy.both_signs),
00098 weight(proxy.weight)
00099 {
00100 for(int i=0;i<4;i++) {
00101 std::size_t i_seq = proxy.i_seqs[i];
00102 CCTBX_ASSERT(i_seq < sites_cart.size());
00103 sites[i] = sites_cart[i_seq];
00104 }
00105 init_volume_model();
00106 }
00107
00109
00111 double
00112 residual() const { return weight * scitbx::fn::pow2(delta); }
00113
00115
00119 af::tiny<scitbx::vec3<double>, 4>
00120 gradients() const
00121 {
00122 af::tiny<scitbx::vec3<double>, 4> result;
00123 double f = delta_sign * 2 * weight * delta;
00124 result[1] = f * d_02_cross_d_03;
00125 result[2] = f * d_03.cross(d_01);
00126 result[3] = f * d_01.cross(d_02);
00127 result[0] = -result[1]-result[2]-result[3];
00128 return result;
00129 }
00130
00132
00134 void
00135 add_gradients(
00136 af::ref<scitbx::vec3<double> > const& gradient_array,
00137 chirality_proxy::i_seqs_type const& i_seqs) const
00138 {
00139 af::tiny<scitbx::vec3<double>, 4> grads = gradients();
00140 for(int i=0;i<4;i++) {
00141 gradient_array[i_seqs[i]] += grads[i];
00142 }
00143 }
00144
00146 af::tiny<scitbx::vec3<double>, 4> sites;
00148 double volume_ideal;
00150 bool both_signs;
00152 double weight;
00153 protected:
00154 scitbx::vec3<double> d_01;
00155 scitbx::vec3<double> d_02;
00156 scitbx::vec3<double> d_03;
00157 scitbx::vec3<double> d_02_cross_d_03;
00158 public:
00160 double volume_model;
00162 double delta_sign;
00164 double delta;
00165
00166 protected:
00167 void
00168 init_volume_model()
00169 {
00170 d_01 = sites[1] - sites[0];
00171 d_02 = sites[2] - sites[0];
00172 d_03 = sites[3] - sites[0];
00173 d_02_cross_d_03 = d_02.cross(d_03);
00174 volume_model = d_01 * d_02_cross_d_03;
00175 delta_sign = -1;
00176 if (both_signs && volume_model < 0) delta_sign = 1;
00177 delta = volume_ideal + delta_sign * volume_model;
00178 }
00179 };
00180
00182 inline
00183 af::shared<double>
00184 chirality_deltas(
00185 af::const_ref<scitbx::vec3<double> > const& sites_cart,
00186 af::const_ref<chirality_proxy> const& proxies)
00187 {
00188 return detail::generic_deltas<chirality_proxy, chirality>::get(
00189 sites_cart, proxies);
00190 }
00191
00195 inline
00196 af::shared<double>
00197 chirality_residuals(
00198 af::const_ref<scitbx::vec3<double> > const& sites_cart,
00199 af::const_ref<chirality_proxy> const& proxies)
00200 {
00201 return detail::generic_residuals<chirality_proxy, chirality>::get(
00202 sites_cart, proxies);
00203 }
00204
00214 inline
00215 double
00216 chirality_residual_sum(
00217 af::const_ref<scitbx::vec3<double> > const& sites_cart,
00218 af::const_ref<chirality_proxy> const& proxies,
00219 af::ref<scitbx::vec3<double> > const& gradient_array)
00220 {
00221 return detail::generic_residual_sum<chirality_proxy, chirality>::get(
00222 sites_cart, proxies, gradient_array);
00223 }
00224
00225 }}
00226
00227 #endif // CCTBX_GEOMETRY_RESTRAINTS_CHIRALITY_H