00001 #ifndef CCTBX_CRYSTAL_ASU_CLUSTERS_H
00002 #define CCTBX_CRYSTAL_ASU_CLUSTERS_H
00003
00004 #include <cctbx/crystal/pair_tables.h>
00005 #include <scitbx/array_family/sort.h>
00006
00007 namespace cctbx { namespace crystal {
00008
00012 class asu_clusters
00013 {
00014 public:
00016 asu_clusters() {}
00017
00019
00022 template <typename FloatType, typename IntShiftType>
00023 asu_clusters(
00024 crystal::pair_asu_table<FloatType, IntShiftType> const& pair_asu_table,
00025 bool strictly_in_asu=true)
00026 {
00027 af::const_ref<pair_asu_dict> table=pair_asu_table.table().const_ref();
00028 unsigned n_sites = table.size();
00029 std::vector<unsigned> i_clusters(n_sites, n_sites);
00030 std::vector<std::vector<unsigned> > index_groups_;
00031 unsigned n_cleared_index_groups = 0;
00032 for(unsigned i_seq=0;i_seq<n_sites;i_seq++) {
00033 unsigned i_cluster = i_clusters[i_seq];
00034 if (i_cluster == n_sites) {
00035 i_cluster = i_clusters[i_seq] = index_groups_.size();
00036 index_groups_.push_back(std::vector<unsigned>(1, i_seq));
00037 }
00038 std::vector<unsigned>* index_group_i = &index_groups_[i_cluster];
00039 for(pair_asu_dict::const_iterator
00040 asu_dict_i = table[i_seq].begin();
00041 asu_dict_i != table[i_seq].end();
00042 asu_dict_i++) {
00043 unsigned j_seq = asu_dict_i->first;
00044 unsigned j_cluster = i_clusters[j_seq];
00045 if (j_cluster == i_cluster) continue;
00046 for(pair_asu_j_sym_groups::const_iterator
00047 j_sym_groups_i = asu_dict_i->second.begin();
00048 j_sym_groups_i != asu_dict_i->second.end();
00049 j_sym_groups_i++) {
00050 unsigned j_syms_0 = *(j_sym_groups_i->begin());
00051 if (!strictly_in_asu || j_syms_0 == 0) {
00052 if (j_cluster == n_sites) {
00053 i_clusters[j_seq] = i_cluster;
00054 index_group_i->push_back(j_seq);
00055 }
00056 else {
00057 for(unsigned i=0;i<index_group_i->size();i++) {
00058 i_clusters[(*index_group_i)[i]] = j_cluster;
00059 }
00060 std::vector<unsigned>*
00061 index_groups_j = &index_groups_[j_cluster];
00062 index_groups_j->reserve(
00063 index_groups_j->size() + index_group_i->size());
00064 for(unsigned i=0;i<index_group_i->size();i++) {
00065 index_groups_j->push_back((*index_group_i)[i]);
00066 }
00067 index_group_i = index_groups_j;
00068
00069 index_groups_[i_cluster] = std::vector<unsigned>();
00070 n_cleared_index_groups++;
00071 i_cluster = j_cluster;
00072 }
00073 break;
00074 }
00075 }
00076 }
00077 }
00078 index_groups.resize(index_groups_.size() - n_cleared_index_groups);
00079 af::ref<std::vector<unsigned> > index_groups_ref = index_groups.ref();
00080 std::size_t j_cluster=0;
00081 for(std::size_t
00082 i_cluster=0;
00083 i_cluster<index_groups_.size();
00084 i_cluster++) {
00085 if (index_groups_[i_cluster].size() > 0) {
00086
00087 index_groups_ref[j_cluster++].swap(index_groups_[i_cluster]);
00088 }
00089 }
00090 CCTBX_ASSERT(j_cluster == index_groups_ref.size());
00091 }
00092
00094 asu_clusters&
00095 sort_index_groups_by_size()
00096 {
00097 af::ref<std::vector<unsigned> > index_groups_ref = index_groups.ref();
00098 std::vector<unsigned> sizes;
00099 sizes.reserve(index_groups_ref.size());
00100 for(std::size_t i=0;i<index_groups_ref.size();i++) {
00101 sizes.push_back(index_groups_ref[i].size());
00102 }
00103 af::shared<std::size_t> perm_owner = af::sort_permutation(
00104 af::make_ref(sizes), true);
00105 af::const_ref<std::size_t> perm = perm_owner.const_ref();
00106 af::shared<std::vector<unsigned> >
00107 sorted_index_groups_owner(index_groups.size());
00108 af::ref<std::vector<unsigned> >
00109 sorted_index_groups = sorted_index_groups_owner.ref();
00110 for(std::size_t i_cluster=0;i_cluster<perm.size();i_cluster++) {
00111
00112 sorted_index_groups[i_cluster].swap(index_groups[perm[i_cluster]]);
00113 }
00114 index_groups = sorted_index_groups_owner;
00115 return *this;
00116 }
00117
00119 asu_clusters&
00120 sort_indices_in_each_group()
00121 {
00122 af::ref<std::vector<unsigned> > index_groups_ref = index_groups.ref();
00123 for(std::size_t
00124 i_cluster=0;
00125 i_cluster<index_groups_ref.size();
00126 i_cluster++){
00127 std::sort(
00128 index_groups_ref[i_cluster].begin(),
00129 index_groups_ref[i_cluster].end());
00130 }
00131 return *this;
00132 }
00133
00137 af::shared<std::vector<unsigned> > index_groups;
00138 };
00139
00140 }}
00141
00142 #endif // CCTBX_CRYSTAL_ASU_CLUSTERS_H