00001 #ifndef CCTBX_HENDRICKSON_LATTMAN_H
00002 #define CCTBX_HENDRICKSON_LATTMAN_H
00003
00004 #include <scitbx/array_family/tiny_plain.h>
00005 #include <cctbx/import_scitbx_af.h>
00006 #include <scitbx/math/bessel.h>
00007 #include <scitbx/math/atanh.h>
00008 #include <scitbx/constants.h>
00009 #include <boost/shared_array.hpp>
00010 #include <complex>
00011
00012 namespace cctbx {
00013
00015
00019 template<typename FloatType = double>
00020 class hendrickson_lattman : public af::tiny_plain<FloatType, 4>
00021 {
00022 public:
00023 typedef af::tiny_plain<FloatType, 4> base_type;
00024
00026 hendrickson_lattman() {}
00027
00029 hendrickson_lattman(base_type const& coeff)
00030 : base_type(coeff)
00031 {}
00032
00034 explicit
00035 hendrickson_lattman(const FloatType* coeff)
00036 {
00037 std::copy(coeff, coeff + 4, this->begin());
00038 }
00039
00041 hendrickson_lattman(
00042 FloatType const& a,
00043 FloatType const& b,
00044 FloatType const& c,
00045 FloatType const& d)
00046 {
00047 (*this)[0] = a;
00048 (*this)[1] = b;
00049 (*this)[2] = c;
00050 (*this)[3] = d;
00051 }
00052
00061 hendrickson_lattman(
00062 bool centric_flag,
00063 std::complex<FloatType> const& phase_integral,
00064 FloatType const& max_figure_of_merit)
00065 {
00066 FloatType fom = std::min(std::abs(phase_integral),max_figure_of_merit);
00067 FloatType weight;
00068 if (centric_flag) {
00069 weight = scitbx::math::atanh(fom);
00070 }
00071 else {
00072 weight = scitbx::math::bessel::inverse_i1_over_i0(fom);
00073 }
00074 FloatType angle = std::arg(phase_integral);
00075 this->elems[0] = weight * std::cos(angle);
00076 this->elems[1] = weight * std::sin(angle);
00077 this->elems[2] = 0;
00078 this->elems[3] = 0;
00079 }
00080
00082 base_type const&
00083 coeff() const { return *this; }
00084
00086 base_type&
00087 coeff() { return *this; }
00088
00090 FloatType const& a() const { return (*this)[0]; }
00091
00093 FloatType const& b() const { return (*this)[1]; }
00094
00096 FloatType const& c() const { return (*this)[2]; }
00097
00099 FloatType const& d() const { return (*this)[3]; }
00100
00108 hendrickson_lattman
00109 conj() const
00110 {
00111 return hendrickson_lattman(a(), -b(), c(), -d());
00112 }
00113
00115
00119 hendrickson_lattman
00120 shift_phase(FloatType const& delta_phi) const
00121 {
00122 FloatType c1 = std::cos(delta_phi);
00123 FloatType s1 = std::sin(delta_phi);
00124 FloatType c2 = std::cos(2. * delta_phi);
00125 FloatType s2 = std::sin(2. * delta_phi);
00126 return hendrickson_lattman(
00127 a()*c1 - b()*s1,
00128 a()*s1 + b()*c1,
00129 c()*c2 - d()*s2,
00130 c()*s2 + d()*c2);
00131 }
00132
00134 hendrickson_lattman
00135 operator+(hendrickson_lattman const& rhs) const
00136 {
00137 hendrickson_lattman result;
00138 for(unsigned i=0;i<4;i++) {
00139 result[i] = this->elems[i] + rhs[i];
00140 }
00141 return result;
00142 }
00143
00145 hendrickson_lattman&
00146 operator+=(hendrickson_lattman const& rhs)
00147 {
00148 for(unsigned i=0;i<4;i++) {
00149 this->elems[i] += rhs[i];
00150 }
00151 return *this;
00152 }
00153
00155 hendrickson_lattman
00156 operator/(FloatType const& rhs) const
00157 {
00158 hendrickson_lattman result;
00159 for(unsigned i=0;i<4;i++) {
00160 result[i] = this->elems[i] / rhs;
00161 }
00162 return result;
00163 }
00164
00166 bool
00167 operator==(hendrickson_lattman const& rhs) const
00168 {
00169 for(unsigned i=0;i<4;i++) {
00170 if (this->elems[i] != rhs[i]) return false;
00171 }
00172 return true;
00173 }
00174
00175 struct phase_integration_cos_sin_table
00176 {
00177 unsigned n_steps;
00178 FloatType angular_step;
00179 boost::shared_array<af::tiny_plain<FloatType, 4> > data;
00180
00181 phase_integration_cos_sin_table() {}
00182
00183 phase_integration_cos_sin_table(
00184 unsigned n_steps_)
00185 :
00186 n_steps(n_steps_),
00187 angular_step(scitbx::constants::two_pi / n_steps),
00188 data(new af::tiny_plain<FloatType, 4>[n_steps])
00189 {
00190 af::tiny_plain<FloatType, 4>* d = data.get();
00191 for(unsigned i_step=0;i_step<n_steps_;i_step++) {
00192 FloatType angle = i_step * angular_step;
00193 *d++ = af::tiny_plain<FloatType, 4>(
00194 std::cos(angle),
00195 std::sin(angle),
00196 std::cos(angle+angle),
00197 std::sin(angle+angle));
00198 }
00199 }
00200 };
00201 };
00202
00203 }
00204
00205 #endif // CCTBX_HENDRICKSON_LATTMAN_H