00001 #ifndef CCTBX_CRYSTAL_DIRECT_SPACE_ASU_H
00002 #define CCTBX_CRYSTAL_DIRECT_SPACE_ASU_H
00003
00004 #include <cctbx/sgtbx/sym_equiv_sites.h>
00005 #include <cctbx/sgtbx/site_symmetry_table.h>
00006 #include <scitbx/math/minimum_covering_sphere.h>
00007
00008 namespace cctbx { namespace crystal {
00009
00011 namespace direct_space_asu {
00012
00014 template <typename FloatType=double>
00015 class float_cut_plane
00016 {
00017 public:
00019 float_cut_plane() {}
00020
00022 float_cut_plane(
00023 fractional<FloatType> const& n_,
00024 FloatType const& c_)
00025 :
00026 n(n_),
00027 c(c_)
00028 {}
00029
00031 fractional<FloatType> n;
00032
00034 FloatType c;
00035
00037 FloatType
00038 evaluate(fractional<FloatType> const& point) const
00039 {
00040 return n * point + c;
00041 }
00042
00044 bool
00045 is_inside(
00046 fractional<FloatType> const& point,
00047 FloatType const& epsilon=0) const
00048 {
00049 if (evaluate(point) < -epsilon) return false;
00050 return true;
00051 }
00052
00054 fractional<FloatType>
00055 get_point_in_plane() const
00056 {
00057 fractional<FloatType> result(0,0,0);
00058 for(std::size_t i=0;i<3;i++) {
00059 if (n[i] != 0) {
00060 result[i] = -c / n[i];
00061 return result;
00062 }
00063 }
00064 throw error("float_cut_plane normal vector is the null vector.");
00065 }
00066
00068 float_cut_plane
00069 add_buffer(
00070 uctbx::unit_cell const& unit_cell,
00071 FloatType const& thickness) const
00072 {
00073 typedef fractional<FloatType> f_t;
00074 typedef cartesian<FloatType> c_t;
00075 f_t x_frac = get_point_in_plane();
00076 c_t x_cart = unit_cell.orthogonalize(x_frac);
00077 c_t n_cart = unit_cell.v_times_fractionalization_matrix_transpose(
00078 n).normalize();
00079 c_t y_cart = x_cart - n_cart * thickness;
00080 f_t y_frac = unit_cell.fractionalize(y_cart);
00081 return float_cut_plane(n, -n * y_frac);
00082 }
00083 };
00084
00086 template <typename FloatType=double>
00087 class float_asu
00088 {
00089 public:
00091 typedef af::small<float_cut_plane<FloatType>, 12> facets_t;
00092
00094 float_asu() {}
00095
00097 float_asu(
00098 uctbx::unit_cell const& unit_cell,
00099 facets_t const& facets,
00100 FloatType const& is_inside_epsilon=1.e-6)
00101 :
00102 unit_cell_(unit_cell),
00103 facets_(facets),
00104 is_inside_epsilon_(is_inside_epsilon),
00105 have_box_(false)
00106 {}
00107
00109 uctbx::unit_cell const&
00110 unit_cell() const { return unit_cell_; }
00111
00113 facets_t const&
00114 facets() const { return facets_; }
00115
00117 FloatType
00118 is_inside_epsilon() const { return is_inside_epsilon_; }
00119
00121
00123 bool
00124 is_inside(fractional<FloatType> const& point) const
00125 {
00126 for(std::size_t i=0;i<facets_.size();i++) {
00127 if (!facets_[i].is_inside(point, is_inside_epsilon_)) return false;
00128 }
00129 return true;
00130 }
00131
00133 af::shared<bool>
00134 is_inside_frac(
00135 af::const_ref<scitbx::vec3<FloatType> > const& sites_frac)
00136 {
00137 af::shared<bool>
00138 result(sites_frac.size(), af::init_functor_null<bool>());
00139 bool* res = result.begin();
00140 for(std::size_t i=0;i<sites_frac.size();i++) {
00141 *res++ = is_inside(sites_frac[i]);
00142 }
00143 return result;
00144 }
00145
00147 af::shared<bool>
00148 is_inside_cart(
00149 af::const_ref<scitbx::vec3<FloatType> > const& sites_cart)
00150 {
00151 af::shared<bool>
00152 result(sites_cart.size(), af::init_functor_null<bool>());
00153 uctbx::unit_cell const& uc = unit_cell();
00154 bool* res = result.begin();
00155 for(std::size_t i=0;i<sites_cart.size();i++) {
00156 *res++ = is_inside(uc.fractionalize(sites_cart[i]));
00157 }
00158 return result;
00159 }
00160
00164 float_asu
00165 add_buffer(FloatType const& thickness) const
00166 {
00167 facets_t buffer_facets;
00168 for(std::size_t i=0;i<facets_.size();i++) {
00169 buffer_facets.push_back(
00170 facets_[i].add_buffer(unit_cell_, thickness));
00171 }
00172 return float_asu(unit_cell_, buffer_facets, is_inside_epsilon_);
00173 }
00174
00176
00179 af::shared<scitbx::vec3<FloatType> >
00180 volume_vertices(
00181 bool cartesian=false,
00182 FloatType const& epsilon=1.e-6) const
00183 {
00184 CCTBX_ASSERT(epsilon > 0);
00185 af::shared<scitbx::vec3<FloatType> > result;
00186 if (facets_.size() < 3) return result;
00187 scitbx::mat3<FloatType> m;
00188 scitbx::vec3<FloatType> b;
00189 for(std::size_t i0=0 ;i0<facets_.size()-2;i0++) {
00190 m.set_row(0, facets_[i0].n);
00191 b[0] = -facets_[i0].c;
00192 for(std::size_t i1=i0+1;i1<facets_.size()-1;i1++) {
00193 m.set_row(1, facets_[i1].n);
00194 b[1] = -facets_[i1].c;
00195 for(std::size_t i2=i1+1;i2<facets_.size() ;i2++) {
00196 m.set_row(2, facets_[i2].n);
00197 b[2] = -facets_[i2].c;
00198 FloatType d = m.determinant();
00199 scitbx::mat3<FloatType> c = m.co_factor_matrix_transposed();
00200 if (scitbx::fn::absolute(d) > c.max_abs() * epsilon) {
00201 c /= d;
00202 fractional<FloatType> vertex = c * b;
00203 if (is_inside(vertex)) {
00204 if (cartesian) {
00205 result.push_back(unit_cell_.orthogonalize(vertex));
00206 }
00207 else {
00208 result.push_back(vertex);
00209 }
00210 }
00211 }
00212 }}}
00213 return result;
00214 }
00215
00219 scitbx::vec3<FloatType> const&
00220 box_min(bool cartesian=false) const
00221 {
00222 if (!have_box_) compute_box();
00223 if (cartesian) return box_min_cart_;
00224 return box_min_frac_;
00225 }
00226
00230 scitbx::vec3<FloatType> const&
00231 box_max(bool cartesian=false) const
00232 {
00233 if (!have_box_) compute_box();
00234 if (cartesian) return box_max_cart_;
00235 return box_max_frac_;
00236 }
00237
00240 scitbx::vec3<FloatType>
00241 box_span(bool cartesian=false) const
00242 {
00243 if (!have_box_) compute_box();
00244 if (cartesian) return box_max_cart_ - box_min_cart_;
00245 return box_max_frac_ - box_min_frac_;
00246 }
00247
00248 protected:
00249 uctbx::unit_cell unit_cell_;
00250 facets_t facets_;
00251 FloatType is_inside_epsilon_;
00252 mutable bool have_box_;
00253 mutable scitbx::vec3<FloatType> box_min_frac_;
00254 mutable scitbx::vec3<FloatType> box_max_frac_;
00255 mutable scitbx::vec3<FloatType> box_min_cart_;
00256 mutable scitbx::vec3<FloatType> box_max_cart_;
00257
00258 void
00259 compute_box() const
00260 {
00261 af::shared<scitbx::vec3<FloatType> > vertices_ = volume_vertices();
00262 af::const_ref<scitbx::vec3<FloatType> > vertices = vertices_.ref();
00263 CCTBX_ASSERT(vertices.size() >= 4);
00264 box_min_frac_ = box_max_frac_ = vertices[0];
00265 box_min_cart_ = box_max_cart_ = unit_cell_.orthogonalize(vertices[0]);
00266 for(std::size_t i=1;i<vertices.size();i++) {
00267 scitbx::vec3<FloatType> vertex = vertices[i];
00268 for(std::size_t j=0;j<3;j++) {
00269 scitbx::math::update_min(box_min_frac_[j], vertex[j]);
00270 scitbx::math::update_max(box_max_frac_[j], vertex[j]);
00271 }
00272 vertex = unit_cell_.orthogonalize(vertex);
00273 for(std::size_t j=0;j<3;j++) {
00274 scitbx::math::update_min(box_min_cart_[j], vertex[j]);
00275 scitbx::math::update_max(box_max_cart_[j], vertex[j]);
00276 }
00277 }
00278 have_box_ = true;
00279 }
00280 };
00281
00283 template <typename FloatType=double, typename IntShiftType=int>
00284 class asu_mapping
00285 {
00286 public:
00288 asu_mapping() {}
00289
00291
00293 asu_mapping(
00294 unsigned i_sym_op,
00295 scitbx::vec3<IntShiftType> const& unit_shifts,
00296 cartesian<FloatType> const& mapped_site)
00297 :
00298 i_sym_op_(i_sym_op),
00299 unit_shifts_(unit_shifts),
00300 mapped_site_(mapped_site)
00301 {}
00302
00304 unsigned
00305 i_sym_op() const { return i_sym_op_; }
00306
00308 scitbx::vec3<IntShiftType> const&
00309 unit_shifts() const { return unit_shifts_; }
00310
00312
00314 cartesian<FloatType> const&
00315 mapped_site() const { return mapped_site_; }
00316
00317 private:
00318 unsigned i_sym_op_;
00319 scitbx::vec3<IntShiftType> unit_shifts_;
00320 cartesian<FloatType> mapped_site_;
00321 };
00322
00324
00326 struct asu_mapping_index
00327 {
00328 asu_mapping_index() {}
00329
00330 asu_mapping_index(unsigned i_seq_, unsigned i_sym_)
00331 :
00332 i_seq(i_seq_),
00333 i_sym(i_sym_)
00334 {}
00335
00336 bool
00337 operator<(asu_mapping_index const& other) const
00338 {
00339 if (i_seq < other.i_seq) return true;
00340 if (i_seq > other.i_seq) return false;
00341 if (i_sym < other.i_sym) return true;
00342 return false;
00343 }
00344
00345 unsigned i_seq;
00346 unsigned i_sym;
00347 };
00348
00350 struct asu_mapping_index_pair
00351 {
00353 unsigned i_seq;
00355 unsigned j_seq;
00357 unsigned j_sym;
00358
00365 bool
00366 is_active(bool minimal=false) const
00367 {
00368 return i_seq <= j_seq || (!minimal && j_sym != 0);
00369 }
00370 };
00371
00373 template <typename FloatType=double>
00374 struct asu_mapping_index_pair_and_diff : asu_mapping_index_pair
00375 {
00377 cartesian<FloatType> diff_vec;
00379 FloatType dist_sq;
00380 };
00381
00383
00386 template <typename FloatType=double, typename IntShiftType=int>
00387 class asu_mappings
00388 {
00389 public:
00391 typedef std::vector<asu_mapping<FloatType, IntShiftType> >
00392 array_of_mappings_for_one_site;
00393
00395 typedef af::shared<array_of_mappings_for_one_site>
00396 array_of_array_of_mappings_for_one_site;
00397
00399 asu_mappings();
00400
00402 asu_mappings(
00403 sgtbx::space_group const& space_group,
00404 float_asu<FloatType> const& asu,
00405 FloatType const& buffer_thickness)
00406 :
00407 space_group_(space_group),
00408 asu_(asu),
00409 buffer_thickness_(buffer_thickness),
00410 space_group_ops_(space_group.all_ops()),
00411 space_group_ops_const_ref_(space_group_ops_.const_ref()),
00412 asu_buffer_(asu.add_buffer(buffer_thickness)),
00413 buffer_covering_sphere_(
00414 scitbx::math::minimum_covering_sphere_3d<FloatType>(
00415 asu.volume_vertices(true).const_ref())
00416 .expand(buffer_thickness)
00417 .expand_relative(2*asu.is_inside_epsilon())),
00418 mappings_const_ref_(mappings_.const_ref()),
00419 n_sites_in_asu_and_buffer_(0),
00420 mapped_sites_min_(0,0,0),
00421 mapped_sites_max_(0,0,0)
00422 {}
00423
00425 void
00426 reserve(std::size_t n_sites_final)
00427 {
00428 site_symmetry_table_.reserve(n_sites_final);
00429 mappings_.reserve(n_sites_final);
00430 mappings_const_ref_ = mappings_.const_ref();
00431 }
00432
00434
00436 void
00437 discard_last()
00438 {
00439 site_symmetry_table_.discard_last();
00440 mappings_.pop_back();
00441 mappings_const_ref_ = mappings_.const_ref();
00442 }
00443
00445 sgtbx::space_group const&
00446 space_group() const { return space_group_; }
00447
00449 float_asu<FloatType> const&
00450 asu() const { return asu_; }
00451
00453 uctbx::unit_cell const&
00454 unit_cell() const { return asu_.unit_cell(); }
00455
00457 FloatType
00458 buffer_thickness() const { return buffer_thickness_; }
00459
00463 float_asu<FloatType> const&
00464 asu_buffer() const { return asu_buffer_; }
00465
00467
00472 scitbx::math::sphere_3d<FloatType> const&
00473 buffer_covering_sphere() const { return buffer_covering_sphere_; }
00474
00476 asu_mappings&
00477 process(
00478 fractional<FloatType> const& original_site,
00479 FloatType const& min_distance_sym_equiv=0.5)
00480 {
00481 return process(
00482 original_site,
00483 sgtbx::site_symmetry(
00484 asu_.unit_cell(),
00485 space_group_,
00486 original_site,
00487 min_distance_sym_equiv,
00488 true));
00489 }
00490
00492 asu_mappings&
00493 process(
00494 fractional<FloatType> const& original_site,
00495 sgtbx::site_symmetry_ops const& site_symmetry_ops)
00496 {
00497 CCTBX_ASSERT(mappings_.begin()
00498 == mappings_const_ref_.begin());
00499 mappings_.push_back(array_of_mappings_for_one_site());
00500 mappings_const_ref_ = mappings_.const_ref();
00501 array_of_mappings_for_one_site& site_mappings = mappings_.back();
00502 site_symmetry_table_.process(site_symmetry_ops);
00503 sgtbx::sym_equiv_sites<FloatType> equiv_sites(
00504 asu_.unit_cell(),
00505 space_group_,
00506 original_site,
00507 site_symmetry_ops);
00508 af::const_ref<typename sgtbx::sym_equiv_sites<FloatType>::coor_t>
00509 coordinates = equiv_sites.coordinates().const_ref();
00510 af::const_ref<std::size_t>
00511 sym_op_indices = equiv_sites.sym_op_indices().const_ref();
00512 bool have_site_in_asu = false;
00513 for(std::size_t i_sym_eq=0;i_sym_eq<coordinates.size();i_sym_eq++) {
00514 scitbx::vec3<FloatType> const& site = coordinates[i_sym_eq];
00515 scitbx::vec3<IntShiftType> unit_shifts_min;
00516 scitbx::vec3<IntShiftType> unit_shifts_max;
00517 for(std::size_t i=0;i<3;i++) {
00518 unit_shifts_min[i] = scitbx::math::iceil(
00519 asu_buffer_.box_min()[i] - site[i] - 2*asu_.is_inside_epsilon());
00520 unit_shifts_max[i] = scitbx::math::ifloor(
00521 asu_buffer_.box_max()[i] - site[i] + 2*asu_.is_inside_epsilon());
00522 }
00523 scitbx::vec3<IntShiftType> u;
00524 fractional<FloatType> mapped_site;
00525 for(u[0]=unit_shifts_min[0];u[0]<=unit_shifts_max[0];u[0]++) {
00526 mapped_site[0] = site[0] + u[0];
00527 for(u[1]=unit_shifts_min[1];u[1]<=unit_shifts_max[1];u[1]++) {
00528 mapped_site[1] = site[1] + u[1];
00529 for(u[2]=unit_shifts_min[2];u[2]<=unit_shifts_max[2];u[2]++) {
00530 mapped_site[2] = site[2] + u[2];
00531 if ( asu_buffer_.is_inside(mapped_site)
00532 && buffer_covering_sphere_.is_inside(
00533 asu_.unit_cell().orthogonalize(mapped_site))) {
00534 asu_mapping<FloatType, IntShiftType> mapping(
00535 sym_op_indices[i_sym_eq],
00536 u,
00537 asu_.unit_cell().orthogonalize(mapped_site));
00538 if (!have_site_in_asu && asu_.is_inside(mapped_site)) {
00539 site_mappings.insert(site_mappings.begin(), mapping);
00540 have_site_in_asu = true;
00541 }
00542 else {
00543 site_mappings.push_back(mapping);
00544 }
00545 n_sites_in_asu_and_buffer_++;
00546 if ( site_mappings.size() == 1
00547 && mappings_const_ref_.size() == 1) {
00548 mapped_sites_min_ = mapping.mapped_site();
00549 mapped_sites_max_ = mapping.mapped_site();
00550 }
00551 else {
00552 for(std::size_t i=0;i<3;i++) {
00553 FloatType const& e = mapping.mapped_site()[i];
00554 scitbx::math::update_min(mapped_sites_min_[i], e);
00555 scitbx::math::update_max(mapped_sites_max_[i], e);
00556 }
00557 }
00558 }
00559 }}}
00560 }
00561 CCTBX_ASSERT(have_site_in_asu);
00562 return *this;
00563 }
00564
00566 asu_mappings&
00567 process_sites_frac(
00568 af::const_ref<scitbx::vec3<FloatType> > const& original_sites,
00569 FloatType const& min_distance_sym_equiv=0.5)
00570 {
00571 for(std::size_t i=0;i<original_sites.size();i++) {
00572 process(original_sites[i], min_distance_sym_equiv);
00573 }
00574 return *this;
00575 }
00576
00578 asu_mappings&
00579 process_sites_frac(
00580 af::const_ref<scitbx::vec3<FloatType> > const& original_sites,
00581 sgtbx::site_symmetry_table const& site_symmetry_table)
00582 {
00583 CCTBX_ASSERT(site_symmetry_table.indices_const_ref().size()
00584 == original_sites.size());
00585 for(std::size_t i=0;i<original_sites.size();i++) {
00586 process(original_sites[i], site_symmetry_table.get(i));
00587 }
00588 return *this;
00589 }
00590
00592 asu_mappings&
00593 process_sites_cart(
00594 af::const_ref<scitbx::vec3<FloatType> > const& original_sites,
00595 FloatType const& min_distance_sym_equiv=0.5)
00596 {
00597 uctbx::unit_cell const& uc = unit_cell();
00598 for(std::size_t i=0;i<original_sites.size();i++) {
00599 process(
00600 uc.fractionalize(original_sites[i]), min_distance_sym_equiv);
00601 }
00602 return *this;
00603 }
00604
00606 asu_mappings&
00607 process_sites_cart(
00608 af::const_ref<scitbx::vec3<FloatType> > const& original_sites,
00609 sgtbx::site_symmetry_table const& site_symmetry_table)
00610 {
00611 CCTBX_ASSERT(site_symmetry_table.indices_const_ref().size()
00612 == original_sites.size());
00613 uctbx::unit_cell const& uc = unit_cell();
00614 for(std::size_t i=0;i<original_sites.size();i++) {
00615 process(
00616 uc.fractionalize(original_sites[i]), site_symmetry_table.get(i));
00617 }
00618 return *this;
00619 }
00620
00624 std::size_t
00625 n_sites_in_asu_and_buffer() const { return n_sites_in_asu_and_buffer_; }
00626
00628 array_of_array_of_mappings_for_one_site const&
00629 mappings() const { return mappings_; }
00630
00632
00634 af::const_ref<array_of_mappings_for_one_site> const&
00635 mappings_const_ref() const { return mappings_const_ref_; }
00636
00638 cartesian<FloatType> const&
00639 mapped_sites_min() const { return mapped_sites_min_; }
00640
00642 cartesian<FloatType> const&
00643 mapped_sites_max() const { return mapped_sites_max_; }
00644
00646 cartesian<FloatType>
00647 mapped_sites_span() const
00648 {
00649 return mapped_sites_max_ - mapped_sites_min_;
00650 }
00651
00653 sgtbx::rt_mx const&
00654 special_op(std::size_t i_seq) const
00655 {
00656 return site_symmetry_table_.get(i_seq).special_op();
00657 }
00658
00660 sgtbx::site_symmetry_table const&
00661 site_symmetry_table() const { return site_symmetry_table_; }
00662
00664
00666 asu_mapping<FloatType, IntShiftType> const&
00667 get_asu_mapping(std::size_t i_seq, std::size_t i_sym) const
00668 {
00669 CCTBX_ASSERT(mappings_const_ref_.begin() == mappings_.begin());
00670 CCTBX_ASSERT(i_seq < mappings_const_ref_.size());
00671 CCTBX_ASSERT(i_sym < mappings_const_ref_[i_seq].size());
00672 return mappings_const_ref_[i_seq][i_sym];
00673 }
00674
00676 sgtbx::rt_mx
00677 get_rt_mx(asu_mapping<FloatType, IntShiftType> const& mapping) const
00678 {
00679 sgtbx::rt_mx const&
00680 rt = space_group_ops_const_ref_[mapping.i_sym_op()];
00681 int t_den = rt.t().den();
00682 return rt + sgtbx::tr_vec(mapping.unit_shifts()*t_den, t_den);
00683 }
00684
00686
00688 sgtbx::rt_mx
00689 get_rt_mx(std::size_t i_seq, std::size_t i_sym) const
00690 {
00691 return get_rt_mx(get_asu_mapping(i_seq, i_sym));
00692 }
00693
00695
00697 sgtbx::rt_mx
00698 get_rt_mx_i(asu_mapping_index_pair const& pair) const
00699 {
00700 return get_rt_mx(pair.i_seq, 0);
00701 }
00702
00704
00706 sgtbx::rt_mx
00707 get_rt_mx_j(asu_mapping_index_pair const& pair) const
00708 {
00709 return get_rt_mx(pair.j_seq, pair.j_sym);
00710 }
00711
00713
00715 cartesian<FloatType>
00716 diff_vec(asu_mapping_index_pair const& pair) const
00717 {
00718 return get_asu_mapping(pair.j_seq, pair.j_sym).mapped_site()
00719 - get_asu_mapping(pair.i_seq, 0).mapped_site();
00720 }
00721
00723 cartesian<FloatType>
00724 map_moved_site_to_asu(
00725 cartesian<FloatType> const& moved_original_site,
00726 std::size_t i_seq,
00727 std::size_t i_sym) const
00728 {
00729 if (r_cart_.size() == 0) {
00730 scitbx::mat3<FloatType> o(unit_cell().orthogonalization_matrix());
00731 scitbx::mat3<FloatType> f(unit_cell().fractionalization_matrix());
00732 r_cart_.reserve(space_group_.order_z());
00733 t_cart_.reserve(space_group_.order_z());
00734 for(std::size_t i_sym_op=0;
00735 i_sym_op<space_group_.order_z();
00736 i_sym_op++) {
00737 sgtbx::rt_mx const& s = space_group_ops_const_ref_[i_sym_op];
00738 typedef scitbx::type_holder<FloatType> t_h;
00739 r_cart_.push_back(o*s.r().as_floating_point(t_h())*f);
00740 t_cart_.push_back(o*s.t().as_floating_point(t_h()));
00741 }
00742 }
00743 asu_mapping<FloatType, IntShiftType> const&
00744 am = get_asu_mapping(i_seq, i_sym);
00745 return r_cart_[am.i_sym_op()] * moved_original_site
00746 + t_cart_[am.i_sym_op()]
00747 + scitbx::vec3<FloatType>(
00748 unit_cell().orthogonalization_matrix() * am.unit_shifts());
00749 }
00750
00760 scitbx::mat3<FloatType>
00761 r_inv_cart(std::size_t i_seq, std::size_t i_sym) const
00762 {
00763 if (r_inv_cart_.size() == 0) {
00764 scitbx::mat3<FloatType> o(unit_cell().orthogonalization_matrix());
00765 scitbx::mat3<FloatType> f(unit_cell().fractionalization_matrix());
00766 r_inv_cart_.reserve(space_group_.order_z());
00767 for(std::size_t i_sym_op=0;
00768 i_sym_op<space_group_.order_z();
00769 i_sym_op++) {
00770 sgtbx::rt_mx const& s = space_group_ops_const_ref_[i_sym_op];
00771 typedef scitbx::type_holder<FloatType> t_h;
00772 r_inv_cart_
00773 .push_back(o*s.r().inverse().as_floating_point(t_h())*f);
00774 }
00775 }
00776 return r_inv_cart_[get_asu_mapping(i_seq, i_sym).i_sym_op()];
00777 }
00778
00784 bool
00785 is_simple_interaction(asu_mapping_index_pair const& pair) const
00786 {
00787 CCTBX_ASSERT(
00788 pair.i_seq < mappings_const_ref_.size()
00789 && pair.j_seq < mappings_const_ref_.size()
00790 && pair.j_sym < mappings_const_ref_[pair.j_seq].size());
00791 if ( site_symmetry_table_.indices_const_ref()[pair.i_seq]
00792 || site_symmetry_table_.indices_const_ref()[pair.j_seq]) {
00793 return false;
00794 }
00795 asu_mapping<FloatType, IntShiftType> const&
00796 am_i = mappings_const_ref_[pair.i_seq][0];
00797 asu_mapping<FloatType, IntShiftType> const&
00798 am_j = mappings_const_ref_[pair.j_seq][pair.j_sym];
00799 sgtbx::rt_mx const& rt_i = space_group_ops_const_ref_[am_i.i_sym_op()];
00800 sgtbx::rt_mx const& rt_j = space_group_ops_const_ref_[am_j.i_sym_op()];
00801 CCTBX_ASSERT(rt_i.r().den() == rt_j.r().den()
00802 && rt_i.t().den() == rt_j.t().den());
00803 if (rt_i.r().num() != rt_j.r().num()) return false;
00804 scitbx::vec3<IntShiftType> const& u_i = am_i.unit_shifts();
00805 scitbx::vec3<IntShiftType> const& u_j = am_j.unit_shifts();
00806 int t_den = rt_i.t().den();
00807 for(unsigned i=0;i<3;i++) {
00808 if ( rt_i.t().num()[i] + u_i[i] * t_den
00809 != rt_j.t().num()[i] + u_j[i] * t_den) return false;
00810 }
00811 return true;
00812 }
00813
00815 asu_mapping_index_pair
00816 make_trial_pair(unsigned i_seq, unsigned j_seq, unsigned j_sym) const
00817 {
00818 CCTBX_ASSERT(mappings_const_ref_.begin() == mappings_.begin());
00819 CCTBX_ASSERT(i_seq < mappings_const_ref_.size());
00820 CCTBX_ASSERT(j_seq < mappings_const_ref_.size());
00821 CCTBX_ASSERT(j_sym < mappings_const_ref_[j_seq].size());
00822 asu_mapping_index_pair new_pair;
00823 new_pair.i_seq = i_seq;
00824 new_pair.j_seq = j_seq;
00825 new_pair.j_sym = j_sym;
00826 return new_pair;
00827 }
00828
00832 asu_mapping_index_pair
00833 make_pair(unsigned i_seq, unsigned j_seq, unsigned j_sym) const
00834 {
00835 asu_mapping_index_pair new_pair = make_trial_pair(i_seq, j_seq, j_sym);
00836 CCTBX_ASSERT(new_pair.is_active());
00837 return new_pair;
00838 }
00839
00841
00849 int
00850 find_i_sym(unsigned i_seq, sgtbx::rt_mx const& rt_mx) const
00851 {
00852 CCTBX_ASSERT(i_seq < mappings_const_ref_.size());
00853 std::size_t i_sst = site_symmetry_table_.indices_const_ref()[i_seq];
00854 if (i_sst == 0) {
00855 sgtbx::rt_mx rt_mx_sp = rt_mx.cancel();
00856 for(int i_sym=0; i_sym<mappings_const_ref_[i_seq].size(); i_sym++) {
00857 if (get_rt_mx(i_seq, i_sym).cancel() == rt_mx_sp) {
00858 return i_sym;
00859 }
00860 }
00861 }
00862 else {
00863 sgtbx::rt_mx const& special_op
00864 = site_symmetry_table_.table_const_ref()[i_sst].special_op();
00865 sgtbx::rt_mx rt_mx_sp = rt_mx.multiply(special_op);
00866 for(int i_sym=0; i_sym<mappings_const_ref_[i_seq].size(); i_sym++) {
00867 if (get_rt_mx(i_seq, i_sym).multiply(special_op) == rt_mx_sp) {
00868 return i_sym;
00869 }
00870 }
00871 }
00872 return -1;
00873 }
00874
00875 protected:
00876 sgtbx::space_group space_group_;
00877 float_asu<FloatType> asu_;
00878 FloatType buffer_thickness_;
00879 af::shared<sgtbx::rt_mx> space_group_ops_;
00880 af::const_ref<sgtbx::rt_mx> space_group_ops_const_ref_;
00881 float_asu<FloatType> asu_buffer_;
00882 scitbx::math::sphere_3d<FloatType> buffer_covering_sphere_;
00883 sgtbx::site_symmetry_table site_symmetry_table_;
00884 array_of_array_of_mappings_for_one_site mappings_;
00885 af::const_ref<array_of_mappings_for_one_site> mappings_const_ref_;
00886 std::size_t n_sites_in_asu_and_buffer_;
00887 cartesian<FloatType> mapped_sites_min_;
00888 cartesian<FloatType> mapped_sites_max_;
00889 mutable std::vector<scitbx::mat3<FloatType> > r_cart_;
00890 mutable std::vector<scitbx::vec3<FloatType> > t_cart_;
00891 mutable std::vector<scitbx::mat3<FloatType> > r_inv_cart_;
00892 };
00893
00894 }}}
00895
00896 #endif // CCTBX_CRYSTAL_DIRECT_SPACE_ASU_H