Commit 065ba540 by maarten

faster distmap

git-svn-id: svn+ssh://gitlab/srv/svn-repos/pdb-redo/trunk@257 a1961a4f-ab94-4bcc-80e8-33b5a54de466
parent e19fc4f7
...@@ -21,7 +21,7 @@ class BondMap ...@@ -21,7 +21,7 @@ class BondMap
private: private:
uint32 dim; size_t dim;
std::vector<bool> bond; std::vector<bool> bond;
std::unordered_map<std::string,size_t> index; std::unordered_map<std::string,size_t> index;
}; };
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include <unordered_map> #include <unordered_map>
//#include <boost/hash/hash.hpp>
#include <clipper/clipper.h> #include <clipper/clipper.h>
#include "cif++/Structure.h" #include "cif++/Structure.h"
...@@ -28,8 +30,19 @@ class DistanceMap ...@@ -28,8 +30,19 @@ class DistanceMap
private: private:
size_t dim; size_t dim;
std::vector<float> dist;
std::unordered_map<std::string,size_t> index; std::unordered_map<std::string,size_t> index;
struct key_hash
{
size_t operator()(std::tuple<size_t,size_t> const& k) const noexcept
{
size_t i[2];
std::tie(i[0], i[1]) = k;
return boost::hash_range(i, i + 1);
}
};
std::unordered_map<std::tuple<size_t,size_t>,float,key_hash> dist;
}; };
} }
...@@ -63,6 +63,15 @@ struct Point ...@@ -63,6 +63,15 @@ struct Point
return *this; return *this;
} }
Point& operator+=(float d)
{
mX += d;
mY += d;
mZ += d;
return *this;
}
Point& operator-=(const Point& rhs) Point& operator-=(const Point& rhs)
{ {
mX -= rhs.mX; mX -= rhs.mX;
...@@ -72,6 +81,15 @@ struct Point ...@@ -72,6 +81,15 @@ struct Point
return *this; return *this;
} }
Point& operator-=(float d)
{
mX -= d;
mY -= d;
mZ -= d;
return *this;
}
Point& operator*=(float rhs) Point& operator*=(float rhs)
{ {
mX *= rhs; mX *= rhs;
......
...@@ -36,7 +36,7 @@ BondMap::BondMap(const Structure& p) ...@@ -36,7 +36,7 @@ BondMap::BondMap(const Structure& p)
if (ixb < ixa) if (ixb < ixa)
swap(ixa, ixb); swap(ixa, ixb);
uint32 ix = ixb + ixa * dim - ixa * (ixa + 1) / 2; size_t ix = ixb + ixa * dim - ixa * (ixa + 1) / 2;
assert(ix < bond.size()); assert(ix < bond.size());
bond[ix] = true; bond[ix] = true;
...@@ -80,11 +80,11 @@ BondMap::BondMap(const Structure& p) ...@@ -80,11 +80,11 @@ BondMap::BondMap(const Structure& p)
} }
auto c = db["atom_site"].find(cif::Key("label_asym_id") == asymId and cif::Key("label_seq_id") == lastSeqID and cif::Key("label_atom_id") == "C"); auto c = db["atom_site"].find(cif::Key("label_asym_id") == asymId and cif::Key("label_seq_id") == lastSeqID and cif::Key("label_atom_id") == "C");
if (c.size() != 1) if (c.size() != 1 and VERBOSE > 1)
cerr << "Unexpected number (" << c.size() << ") of atoms with atom ID C in asym_id " << asymId << " with seq id " << lastSeqID << endl; cerr << "Unexpected number (" << c.size() << ") of atoms with atom ID C in asym_id " << asymId << " with seq id " << lastSeqID << endl;
auto n = db["atom_site"].find(cif::Key("label_asym_id") == asymId and cif::Key("label_seq_id") == seqId and cif::Key("label_atom_id") == "N"); auto n = db["atom_site"].find(cif::Key("label_asym_id") == asymId and cif::Key("label_seq_id") == seqId and cif::Key("label_atom_id") == "N");
if (n.size() != 1) if (n.size() != 1 and VERBOSE > 1)
cerr << "Unexpected number (" << n.size() << ") of atoms with atom ID N in asym_id " << asymId << " with seq id " << seqId << endl; cerr << "Unexpected number (" << n.size() << ") of atoms with atom ID N in asym_id " << asymId << " with seq id " << seqId << endl;
if (not (c.empty() or n.empty())) if (not (c.empty() or n.empty()))
...@@ -107,7 +107,7 @@ BondMap::BondMap(const Structure& p) ...@@ -107,7 +107,7 @@ BondMap::BondMap(const Structure& p)
db["atom_site"].find(cif::Key("label_asym_id") == asym1 and cif::Key("label_atom_id") == atomId1) : db["atom_site"].find(cif::Key("label_asym_id") == asym1 and cif::Key("label_atom_id") == atomId1) :
db["atom_site"].find(cif::Key("label_asym_id") == asym1 and cif::Key("label_seq_id") == seqId1 and cif::Key("label_atom_id") == atomId1); db["atom_site"].find(cif::Key("label_asym_id") == asym1 and cif::Key("label_seq_id") == seqId1 and cif::Key("label_atom_id") == atomId1);
if (a.size() != 1) if (a.size() != 1 and VERBOSE > 1)
cerr << "Unexpected number (" << a.size() << ") of atoms for link with asym_id " << asym1 << " seq_id " << seqId1 << " atom_id " << atomId1 << endl; cerr << "Unexpected number (" << a.size() << ") of atoms for link with asym_id " << asym1 << " seq_id " << seqId1 << " atom_id " << atomId1 << endl;
auto b = auto b =
...@@ -115,7 +115,7 @@ BondMap::BondMap(const Structure& p) ...@@ -115,7 +115,7 @@ BondMap::BondMap(const Structure& p)
db["atom_site"].find(cif::Key("label_asym_id") == asym2 and cif::Key("label_atom_id") == atomId2) : db["atom_site"].find(cif::Key("label_asym_id") == asym2 and cif::Key("label_atom_id") == atomId2) :
db["atom_site"].find(cif::Key("label_asym_id") == asym2 and cif::Key("label_seq_id") == seqId2 and cif::Key("label_atom_id") == atomId2); db["atom_site"].find(cif::Key("label_asym_id") == asym2 and cif::Key("label_seq_id") == seqId2 and cif::Key("label_atom_id") == atomId2);
if (b.size() != 1) if (b.size() != 1 and VERBOSE > 1)
cerr << "Unexpected number (" << b.size() << ") of atoms for link with asym_id " << asym2 << " seq_id " << seqId2 << " atom_id " << atomId2 << endl; cerr << "Unexpected number (" << b.size() << ") of atoms for link with asym_id " << asym2 << " seq_id " << seqId2 << " atom_id " << atomId2 << endl;
if (not (a.empty() or b.empty())) if (not (a.empty() or b.empty()))
...@@ -186,7 +186,7 @@ BondMap::BondMap(const Structure& p) ...@@ -186,7 +186,7 @@ BondMap::BondMap(const Structure& p)
if (ixb < ixa) if (ixb < ixa)
swap(ixa, ixb); swap(ixa, ixb);
uint32 ix = ixb + ixa * dim - ixa * (ixa + 1) / 2; size_t ix = ixb + ixa * dim - ixa * (ixa + 1) / 2;
assert(ix < bond.size()); assert(ix < bond.size());
bond[ix] = true; bond[ix] = true;
...@@ -201,13 +201,13 @@ BondMap::BondMap(const Structure& p) ...@@ -201,13 +201,13 @@ BondMap::BondMap(const Structure& p)
bool BondMap::operator()(const Atom& a, const Atom& b) const bool BondMap::operator()(const Atom& a, const Atom& b) const
{ {
uint32 ixa = index.at(a.id()); size_t ixa = index.at(a.id());
uint32 ixb = index.at(b.id()); size_t ixb = index.at(b.id());
if (ixb < ixa) if (ixb < ixa)
swap(ixa, ixb); swap(ixa, ixb);
uint32 ix = ixb + ixa * dim - ixa * (ixa + 1) / 2; size_t ix = ixb + ixa * dim - ixa * (ixa + 1) / 2;
assert(ix < bond.size()); assert(ix < bond.size());
return bond[ix]; return bond[ix];
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include "cif++/Config.h" #include "cif++/Config.h"
#include <atomic> #include <atomic>
#include <mutex>
#include <boost/thread.hpp> #include <boost/thread.hpp>
...@@ -44,13 +45,18 @@ vector<clipper::RTop_orth> AlternativeSites(const clipper::Spacegroup& spacegrou ...@@ -44,13 +45,18 @@ vector<clipper::RTop_orth> AlternativeSites(const clipper::Spacegroup& spacegrou
DistanceMap::DistanceMap(const Structure& p, const clipper::Spacegroup& spacegroup, const clipper::Cell& cell) DistanceMap::DistanceMap(const Structure& p, const clipper::Spacegroup& spacegroup, const clipper::Cell& cell)
: dim(0) : dim(0)
{ {
const float kMaxDistance = 5, kMaxDistanceSQ = kMaxDistance * kMaxDistance;
auto atoms = p.atoms(); auto atoms = p.atoms();
dim = atoms.size(); dim = atoms.size();
dist = vector<float>(dim * (dim - 1), 0.f);
vector<clipper::Coord_orth> locations(dim); vector<clipper::Coord_orth> locations(dim);
vector<bool> isWater(dim, false); vector<bool> isWater(dim, false);
// bounding box
Point pMin(numeric_limits<float>::max(), numeric_limits<float>::max(), numeric_limits<float>::max()),
pMax(numeric_limits<float>::min(), numeric_limits<float>::min(), numeric_limits<float>::min());
for (auto& atom: atoms) for (auto& atom: atoms)
{ {
size_t ix = index.size(); size_t ix = index.size();
...@@ -58,8 +64,27 @@ DistanceMap::DistanceMap(const Structure& p, const clipper::Spacegroup& spacegro ...@@ -58,8 +64,27 @@ DistanceMap::DistanceMap(const Structure& p, const clipper::Spacegroup& spacegro
locations[ix] = atom.location(); locations[ix] = atom.location();
isWater[ix] = atom.isWater(); isWater[ix] = atom.isWater();
auto p = atom.location();
if (pMin.mX > p.mX)
pMin.mX = p.mX;
if (pMin.mY > p.mY)
pMin.mY = p.mY;
if (pMin.mZ > p.mZ)
pMin.mZ = p.mZ;
if (pMax.mX < p.mX)
pMax.mX = p.mX;
if (pMax.mY < p.mY)
pMax.mY = p.mY;
if (pMax.mZ < p.mZ)
pMax.mZ = p.mZ;
}; };
pMin -= kMaxDistance; // extend bounding box
pMax += kMaxDistance;
vector<clipper::RTop_orth> rtOrth = AlternativeSites(spacegroup, cell); vector<clipper::RTop_orth> rtOrth = AlternativeSites(spacegroup, cell);
cif::Progress progress(locations.size() - 1, "Creating distance map"); cif::Progress progress(locations.size() - 1, "Creating distance map");
...@@ -67,6 +92,7 @@ DistanceMap::DistanceMap(const Structure& p, const clipper::Spacegroup& spacegro ...@@ -67,6 +92,7 @@ DistanceMap::DistanceMap(const Structure& p, const clipper::Spacegroup& spacegro
boost::thread_group t; boost::thread_group t;
size_t N = boost::thread::hardware_concurrency(); size_t N = boost::thread::hardware_concurrency();
atomic<size_t> next(0); atomic<size_t> next(0);
mutex m;
for (size_t i = 0; i < N; ++i) for (size_t i = 0; i < N; ++i)
t.create_thread([&]() t.create_thread([&]()
...@@ -90,15 +116,25 @@ DistanceMap::DistanceMap(const Structure& p, const clipper::Spacegroup& spacegro ...@@ -90,15 +116,25 @@ DistanceMap::DistanceMap(const Structure& p, const clipper::Spacegroup& spacegro
{ {
auto p = locations[j].transform(rt); auto p = locations[j].transform(rt);
if (p[0] < pMin.mX or p[1] < pMin.mY or p[2] < pMin.mZ or
p[0] > pMax.mX or p[1] > pMax.mY or p[2] > pMax.mZ)
{
continue;
}
double r2 = (locations[i] - p).lengthsq(); double r2 = (locations[i] - p).lengthsq();
if (minR2 > r2) if (minR2 > r2)
minR2 = r2; minR2 = r2;
} }
size_t ix = j + i * dim - i * (i + 1) / 2; if (minR2 < kMaxDistanceSQ)
{
float d = sqrt(minR2);
auto k = make_tuple(i, j);
assert(ix < dist.size()); lock_guard<mutex> lock(m);
dist[ix] = sqrt(minR2); dist[k] = d;
}
} }
progress.consumed(1); progress.consumed(1);
...@@ -113,8 +149,6 @@ DistanceMap::DistanceMap(const vector<Atom>& atoms) ...@@ -113,8 +149,6 @@ DistanceMap::DistanceMap(const vector<Atom>& atoms)
{ {
dim = atoms.size(); dim = atoms.size();
dist = vector<float>(dim * (dim - 1), 0.f);
for (auto& atom: atoms) for (auto& atom: atoms)
{ {
size_t ix = index.size(); size_t ix = index.size();
...@@ -125,9 +159,7 @@ DistanceMap::DistanceMap(const vector<Atom>& atoms) ...@@ -125,9 +159,7 @@ DistanceMap::DistanceMap(const vector<Atom>& atoms)
{ {
for (size_t j = i + 1; j < dim; ++j) for (size_t j = i + 1; j < dim; ++j)
{ {
size_t ix = j + i * dim - i * (i + 1) / 2; dist[make_tuple(i, j)] = Distance(atoms[i].location(), atoms[j].location());
assert(ix < dist.size());
dist[ix] = Distance(atoms[i].location(), atoms[j].location());
} }
} }
} }
...@@ -157,10 +189,16 @@ float DistanceMap::operator()(const Atom& a, const Atom& b) const ...@@ -157,10 +189,16 @@ float DistanceMap::operator()(const Atom& a, const Atom& b) const
if (ixb < ixa) if (ixb < ixa)
swap(ixa, ixb); swap(ixa, ixb);
size_t ix = ixb + ixa * dim - ixa * (ixa + 1) / 2; tuple<size_t,size_t> k{ ixa, ixb };
auto ii = dist.find(k);
assert(ix < dist.size()); float result = 100;
return dist[ix];
if (ii != dist.end())
result = ii->second;
return result;
} }
vector<Atom> DistanceMap::near(const Atom& a, float maxDistance) const vector<Atom> DistanceMap::near(const Atom& a, float maxDistance) const
...@@ -185,15 +223,12 @@ vector<Atom> DistanceMap::near(const Atom& a, float maxDistance) const ...@@ -185,15 +223,12 @@ vector<Atom> DistanceMap::near(const Atom& a, float maxDistance) const
if (ixb == ixa) if (ixb == ixa)
continue; continue;
size_t ix; auto ii =
ixa < ixb ?
if (ixa < ixb) dist.find(make_tuple(ixa, ixb)) :
ix = ixb + ixa * dim - ixa * (ixa + 1) / 2; dist.find(make_tuple(ixb, ixa));
else
ix = ixa + ixb * dim - ixb * (ixb + 1) / 2;
assert(ix < dist.size()); if (ii != dist.end() and ii->second <= maxDistance)
if (dist[ix] != 0 and dist[ix] <= maxDistance)
result.emplace_back(f, i.first); result.emplace_back(f, i.first);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment