mirror of
https://github.com/PDB-REDO/libcifpp.git
synced 2026-06-04 13:54:25 +08:00
backup
git-svn-id: svn+ssh://gitlab/srv/svn-repos/pdb-redo/trunk@172 a1961a4f-ab94-4bcc-80e8-33b5a54de466
This commit is contained in:
27
include/cif++/BondMap.h
Normal file
27
include/cif++/BondMap.h
Normal file
@@ -0,0 +1,27 @@
|
||||
// copyright
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "cif++/Structure.h"
|
||||
|
||||
namespace libcif
|
||||
{
|
||||
|
||||
class BondMap
|
||||
{
|
||||
public:
|
||||
BondMap(const Structure& p);
|
||||
|
||||
BondMap(const BondMap&) = delete;
|
||||
BondMap& operator=(const BondMap&) = delete;
|
||||
|
||||
bool operator()(const Atom& a, const Atom& b) const;
|
||||
|
||||
private:
|
||||
|
||||
uint32 dim;
|
||||
std::vector<bool> bond;
|
||||
std::unordered_map<std::string,size_t> index;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <regex>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
#include <list>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/any.hpp>
|
||||
@@ -211,12 +212,11 @@ class Datablock
|
||||
Category* get(const string& name);
|
||||
|
||||
void getTagOrder(vector<string>& tags) const;
|
||||
void write(std::ostream& os, const vector<string>& order);
|
||||
void write(std::ostream& os);
|
||||
|
||||
private:
|
||||
|
||||
void write(std::ostream& os);
|
||||
void write(std::ostream& os, const vector<string>& order);
|
||||
|
||||
std::list<Category> mCategories;
|
||||
string mName;
|
||||
Validator* mValidator;
|
||||
@@ -451,7 +451,7 @@ class Row
|
||||
{
|
||||
public:
|
||||
friend class Category;
|
||||
friend class catIndex;
|
||||
friend class CatIndex;
|
||||
friend class RowComparator;
|
||||
friend struct detail::ItemReference;
|
||||
|
||||
@@ -995,7 +995,7 @@ class Category
|
||||
vector<ItemColumn> mColumns;
|
||||
ItemRow* mHead;
|
||||
ItemRow* mTail;
|
||||
class catIndex* mIndex;
|
||||
class CatIndex* mIndex;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -53,4 +53,30 @@ std::tuple<std::string,std::string> splitTagName(const std::string& tag);
|
||||
|
||||
std::vector<std::string> wordWrap(const std::string& text, unsigned int width);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Code helping with terminal i/o
|
||||
|
||||
uint32 get_terminal_width();
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// A progress bar
|
||||
|
||||
class Progress
|
||||
{
|
||||
public:
|
||||
Progress(int64 inMax, const std::string& inAction);
|
||||
virtual ~Progress();
|
||||
|
||||
void consumed(int64 inConsumed); // consumed is relative
|
||||
void progress(int64 inProgress); // progress is absolute
|
||||
|
||||
void message(const std::string& inMessage);
|
||||
|
||||
private:
|
||||
Progress(const Progress&);
|
||||
Progress& operator=(const Progress&);
|
||||
|
||||
struct ProgressImpl* mImpl;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
32
include/cif++/DistanceMap.h
Normal file
32
include/cif++/DistanceMap.h
Normal file
@@ -0,0 +1,32 @@
|
||||
// copyright
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include <clipper/clipper.h>
|
||||
|
||||
#include "cif++/Structure.h"
|
||||
|
||||
namespace libcif
|
||||
{
|
||||
|
||||
class DistanceMap
|
||||
{
|
||||
public:
|
||||
DistanceMap(const Structure& p, const clipper::Spacegroup& spacegroup, const clipper::Cell& cell);
|
||||
|
||||
DistanceMap(const DistanceMap&) = delete;
|
||||
DistanceMap& operator=(const DistanceMap&) = delete;
|
||||
|
||||
float operator()(const Atom& a, const Atom& b) const;
|
||||
std::vector<Atom> near(const Atom& a, float maxDistance = 3.5f) const;
|
||||
|
||||
private:
|
||||
|
||||
uint32 dim;
|
||||
std::vector<float> dist;
|
||||
std::unordered_map<std::string,size_t> index;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "pdb2cif.h"
|
||||
#include "cif++/PDB2Cif.h"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -11,30 +11,30 @@ class Remark3Parser
|
||||
public:
|
||||
virtual ~Remark3Parser() {}
|
||||
|
||||
static bool parse(const std::string& expMethod, PDBRecord* r, cif::datablock& db);
|
||||
static bool parse(const std::string& expMethod, PDBRecord* r, cif::Datablock& db);
|
||||
|
||||
virtual std::string program();
|
||||
virtual std::string version();
|
||||
|
||||
protected:
|
||||
|
||||
Remark3Parser(const std::string& name, const std::string& expMethod, PDBRecord* r, cif::datablock& db,
|
||||
Remark3Parser(const std::string& name, const std::string& expMethod, PDBRecord* r, cif::Datablock& db,
|
||||
const TemplateLine templatelines[], uint32 templateLineCount, std::regex programVersion);
|
||||
|
||||
virtual float Parse();
|
||||
std::string NextLine();
|
||||
virtual float parse();
|
||||
std::string nextLine();
|
||||
|
||||
bool Match(const char* expr, int nextState);
|
||||
void StoreCapture(const char* category, std::initializer_list<const char*> items, bool createNew = false);
|
||||
void StoreRefineLsRestr(const char* type, std::initializer_list<const char*> values);
|
||||
void UpdateRefineLsRestr(const char* type, std::initializer_list<const char*> values);
|
||||
bool match(const char* expr, int nextState);
|
||||
void storeCapture(const char* category, std::initializer_list<const char*> items, bool createNew = false);
|
||||
void storeRefineLsRestr(const char* type, std::initializer_list<const char*> values);
|
||||
void updateRefineLsRestr(const char* type, std::initializer_list<const char*> values);
|
||||
|
||||
virtual void Fixup() {}
|
||||
virtual void fixup() {}
|
||||
|
||||
std::string mName;
|
||||
std::string mExpMethod;
|
||||
PDBRecord* mRec;
|
||||
cif::datablock mDb;
|
||||
cif::Datablock mDb;
|
||||
std::string mLine;
|
||||
std::smatch mM;
|
||||
uint32 mState;
|
||||
|
||||
@@ -12,15 +12,15 @@ class PeptideDB
|
||||
public:
|
||||
static PeptideDB& Instance();
|
||||
|
||||
void PushDictionary(boost::filesystem::path dict);
|
||||
void PopDictionary();
|
||||
void pushDictionary(boost::filesystem::path dict);
|
||||
void popDictionary();
|
||||
|
||||
bool IsKnownPeptide(const std::string& res_name) const;
|
||||
bool IsKnownBase(const std::string& res_name) const;
|
||||
bool isKnownPeptide(const std::string& res_name) const;
|
||||
bool isKnownBase(const std::string& res_name) const;
|
||||
|
||||
std::string GetNameForResidue(const std::string& res_name) const;
|
||||
std::string GetFormulaForResidue(const std::string& res_name) const;
|
||||
std::string Unalias(const std::string& res_name) const;
|
||||
std::string nameForResidue(const std::string& res_name) const;
|
||||
std::string formulaForResidue(const std::string& res_name) const;
|
||||
std::string unalias(const std::string& res_name) const;
|
||||
|
||||
private:
|
||||
PeptideDB();
|
||||
|
||||
@@ -231,9 +231,9 @@ class SphericalDots
|
||||
double lat = std::asin((2.0 * i) / P);
|
||||
double lon = std::fmod(i, kGoldenRatio) * 2 * kPI / kGoldenRatio;
|
||||
|
||||
p->x(sin(lon) * cos(lat));
|
||||
p->y(cos(lon) * cos(lat));
|
||||
p->z( sin(lat));
|
||||
p->setX(sin(lon) * cos(lat));
|
||||
p->setY(cos(lon) * cos(lat));
|
||||
p->setZ( sin(lat));
|
||||
|
||||
++p;
|
||||
}
|
||||
|
||||
@@ -37,9 +37,9 @@
|
||||
namespace cif
|
||||
{
|
||||
class Datablock;
|
||||
class File;
|
||||
};
|
||||
|
||||
|
||||
namespace libcif
|
||||
{
|
||||
|
||||
@@ -218,6 +218,7 @@ class File : public std::enable_shared_from_this<File>
|
||||
std::vector<const Entity*> entities();
|
||||
|
||||
cif::Datablock& data();
|
||||
cif::File& file();
|
||||
|
||||
private:
|
||||
|
||||
|
||||
207
src/BondMap.cpp
Normal file
207
src/BondMap.cpp
Normal file
@@ -0,0 +1,207 @@
|
||||
// copyright
|
||||
|
||||
#include "cif++/Config.h"
|
||||
|
||||
#include "cif++/Cif++.h"
|
||||
#include "cif++/BondMap.h"
|
||||
#include "cif++/Compound.h"
|
||||
#include "cif++/CifUtils.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace libcif
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
BondMap::BondMap(const Structure& p)
|
||||
: dim(0)
|
||||
{
|
||||
auto atoms = p.atoms();
|
||||
dim = atoms.size();
|
||||
|
||||
bond = vector<bool>(dim * (dim - 1), false);
|
||||
|
||||
for (auto& atom: atoms)
|
||||
{
|
||||
size_t ix = index.size();
|
||||
index[atom.id()] = ix;
|
||||
};
|
||||
|
||||
auto bindAtoms = [this](const string& a, const string& b)
|
||||
{
|
||||
size_t ixa = index[a];
|
||||
size_t ixb = index[b];
|
||||
|
||||
if (ixb < ixa)
|
||||
swap(ixa, ixb);
|
||||
|
||||
uint32 ix = ixb + ixa * dim - ixa * (ixa + 1) / 2;
|
||||
|
||||
assert(ix < bond.size());
|
||||
bond[ix] = true;
|
||||
|
||||
};
|
||||
|
||||
cif::Datablock& db = p.getFile().data();
|
||||
|
||||
// collect all compounds first
|
||||
set<string> compounds;
|
||||
for (auto c: db["chem_comp"])
|
||||
compounds.insert(c["id"].as<string>());
|
||||
|
||||
// make sure we also have all residues in the polyseq
|
||||
for (auto m: db["entity_poly_seq"])
|
||||
{
|
||||
string c = m["mon_id"].as<string>();
|
||||
if (compounds.count(c))
|
||||
continue;
|
||||
|
||||
cerr << "Warning: mon_id " << c << " is missing in the chem_comp category" << endl;
|
||||
compounds.insert(c);
|
||||
}
|
||||
|
||||
// first link all residues in a polyseq
|
||||
|
||||
string lastAsymID;
|
||||
int lastSeqID;
|
||||
for (auto r: db["pdbx_poly_seq_scheme"])
|
||||
{
|
||||
string asymId;
|
||||
int seqId;
|
||||
|
||||
cif::tie(asymId, seqId) = r.get("asym_id", "seq_id");
|
||||
|
||||
if (asymId != lastAsymID) // first in a new sequece
|
||||
{
|
||||
lastAsymID = asymId;
|
||||
lastSeqID = seqId;
|
||||
continue;
|
||||
}
|
||||
|
||||
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)
|
||||
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");
|
||||
if (n.size() != 1)
|
||||
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()))
|
||||
bindAtoms(c.front()["id"].as<string>(), n.front()["id"].as<string>());
|
||||
|
||||
lastSeqID = seqId;
|
||||
}
|
||||
|
||||
for (auto l: db["struct_conn"])
|
||||
{
|
||||
string asym1, asym2, atomId1, atomId2;
|
||||
int seqId1, seqId2;
|
||||
cif::tie(asym1, asym2, atomId1, atomId2, seqId1, seqId2) =
|
||||
l.get("ptnr1_label_asym_id", "ptnr2_label_asym_id",
|
||||
"ptnr1_label_atom_id", "ptnr2_label_atom_id",
|
||||
"ptnr1_label_seq_id", "ptnr2_label_seq_id");
|
||||
|
||||
auto a = 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)
|
||||
cerr << "Unexpected number (" << a.size() << ") of atoms for link with asym_id " << asym1 << " seq_id " << seqId1 << " atom_id " << atomId1 << endl;
|
||||
|
||||
auto b = 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)
|
||||
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()))
|
||||
bindAtoms(a.front()["id"].as<string>(), b.front()["id"].as<string>());
|
||||
}
|
||||
|
||||
// then link all atoms in the compounds
|
||||
|
||||
cif::Progress progress(compounds.size(), "Creating bond map");
|
||||
|
||||
for (auto c: compounds)
|
||||
{
|
||||
auto* compound = libcif::Compound::create(c);
|
||||
if (not compound)
|
||||
{
|
||||
cerr << "Missing compound information for " << c << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (compound->isWater())
|
||||
{
|
||||
if (VERBOSE)
|
||||
cerr << "skipping water in bond map calculation" << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// loop over poly_seq_scheme
|
||||
for (auto r: db["pdbx_poly_seq_scheme"].find(cif::Key("mon_id") == c))
|
||||
{
|
||||
string asymId;
|
||||
int seqId;
|
||||
cif::tie(asymId, seqId) = r.get("asym_id", "seq_id");
|
||||
|
||||
vector<Atom> rAtoms;
|
||||
for (auto a: db["atom_site"].find(cif::Key("label_asym_id") == asymId and cif::Key("label_seq_id") == seqId))
|
||||
rAtoms.push_back(p.getAtomById(a["id"].as<string>()));
|
||||
|
||||
for (size_t i = 0; i + 1 < rAtoms.size(); ++i)
|
||||
{
|
||||
for (size_t j = i + 1; j < rAtoms.size(); ++j)
|
||||
{
|
||||
if (compound->atomsBonded(rAtoms[i].labelAtomId(), rAtoms[j].labelAtomId()))
|
||||
bindAtoms(rAtoms[i].id(), rAtoms[j].id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// loop over pdbx_nonpoly_scheme
|
||||
for (auto r: db["pdbx_nonpoly_scheme"].find(cif::Key("mon_id") == c))
|
||||
{
|
||||
string asymId;
|
||||
cif::tie(asymId) = r.get("asym_id");
|
||||
|
||||
vector<Atom> rAtoms;
|
||||
for (auto a: db["atom_site"].find(cif::Key("label_asym_id") == asymId))
|
||||
rAtoms.push_back(p.getAtomById(a["id"].as<string>()));
|
||||
|
||||
for (size_t i = 0; i + 1 < rAtoms.size(); ++i)
|
||||
{
|
||||
for (size_t j = i + 1; j < rAtoms.size(); ++j)
|
||||
{
|
||||
if (compound->atomsBonded(rAtoms[i].labelAtomId(), rAtoms[j].labelAtomId()))
|
||||
{
|
||||
size_t ixa = index[rAtoms[i].id()];
|
||||
size_t ixb = index[rAtoms[j].id()];
|
||||
|
||||
if (ixb < ixa)
|
||||
swap(ixa, ixb);
|
||||
|
||||
uint32 ix = ixb + ixa * dim - ixa * (ixa + 1) / 2;
|
||||
|
||||
assert(ix < bond.size());
|
||||
bond[ix] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
progress.consumed(1);
|
||||
}
|
||||
}
|
||||
|
||||
bool BondMap::operator()(const Atom& a, const Atom& b) const
|
||||
{
|
||||
uint32 ixa = index.at(a.id());
|
||||
uint32 ixb = index.at(b.id());
|
||||
|
||||
if (ixb < ixa)
|
||||
swap(ixa, ixb);
|
||||
|
||||
uint32 ix = ixb + ixa * dim - ixa * (ixa + 1) / 2;
|
||||
|
||||
assert(ix < bond.size());
|
||||
return bond[ix];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -525,11 +525,11 @@ int RowComparator::operator()(const ItemRow* a, const ItemRow* b) const
|
||||
// class to keep an index on the keys of a Category. This is a red/black
|
||||
// tree implementation.
|
||||
|
||||
class catIndex
|
||||
class CatIndex
|
||||
{
|
||||
public:
|
||||
catIndex(Category* cat);
|
||||
~catIndex();
|
||||
CatIndex(Category* cat);
|
||||
~CatIndex();
|
||||
|
||||
ItemRow* find(ItemRow* k) const;
|
||||
|
||||
@@ -716,17 +716,17 @@ class catIndex
|
||||
entry* mRoot;
|
||||
};
|
||||
|
||||
catIndex::catIndex(Category* cat)
|
||||
CatIndex::CatIndex(Category* cat)
|
||||
: mCat(*cat), mComp(cat), mRoot(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
catIndex::~catIndex()
|
||||
CatIndex::~CatIndex()
|
||||
{
|
||||
delete mRoot;
|
||||
}
|
||||
|
||||
ItemRow* catIndex::find(ItemRow* k) const
|
||||
ItemRow* CatIndex::find(ItemRow* k) const
|
||||
{
|
||||
const entry* r = mRoot;
|
||||
while (r != nullptr)
|
||||
@@ -743,13 +743,13 @@ ItemRow* catIndex::find(ItemRow* k) const
|
||||
return r ? r->mRow : nullptr;
|
||||
}
|
||||
|
||||
void catIndex::insert(ItemRow* k)
|
||||
void CatIndex::insert(ItemRow* k)
|
||||
{
|
||||
mRoot = insert(mRoot, k);
|
||||
mRoot->mRed = false;
|
||||
}
|
||||
|
||||
catIndex::entry* catIndex::insert(entry* h, ItemRow* v)
|
||||
CatIndex::entry* CatIndex::insert(entry* h, ItemRow* v)
|
||||
{
|
||||
if (h == nullptr)
|
||||
return new entry(v);
|
||||
@@ -772,14 +772,14 @@ catIndex::entry* catIndex::insert(entry* h, ItemRow* v)
|
||||
return h;
|
||||
}
|
||||
|
||||
void catIndex::erase(ItemRow* k)
|
||||
void CatIndex::erase(ItemRow* k)
|
||||
{
|
||||
mRoot = erase(mRoot, k);
|
||||
if (mRoot != nullptr)
|
||||
mRoot->mRed = false;
|
||||
}
|
||||
|
||||
catIndex::entry* catIndex::erase(entry* h, ItemRow* k)
|
||||
CatIndex::entry* CatIndex::erase(entry* h, ItemRow* k)
|
||||
{
|
||||
if (mComp(k, h->mRow) < 0)
|
||||
{
|
||||
@@ -820,7 +820,7 @@ catIndex::entry* catIndex::erase(entry* h, ItemRow* k)
|
||||
return fixUp(h);
|
||||
}
|
||||
|
||||
void catIndex::reconstruct()
|
||||
void CatIndex::reconstruct()
|
||||
{
|
||||
delete mRoot;
|
||||
mRoot = nullptr;
|
||||
@@ -897,7 +897,7 @@ void catIndex::reconstruct()
|
||||
// mRoot = e.front();
|
||||
}
|
||||
|
||||
size_t catIndex::size() const
|
||||
size_t CatIndex::size() const
|
||||
{
|
||||
stack<entry*> s;
|
||||
s.push(mRoot);
|
||||
@@ -921,7 +921,7 @@ size_t catIndex::size() const
|
||||
return result;
|
||||
}
|
||||
|
||||
void catIndex::validate() const
|
||||
void CatIndex::validate() const
|
||||
{
|
||||
if (mRoot != nullptr)
|
||||
{
|
||||
@@ -935,7 +935,7 @@ void catIndex::validate() const
|
||||
}
|
||||
}
|
||||
|
||||
void catIndex::validate(entry* h, bool isParentRed, uint32 blackDepth, uint32& minBlack, uint32& maxBlack) const
|
||||
void CatIndex::validate(entry* h, bool isParentRed, uint32 blackDepth, uint32& minBlack, uint32& maxBlack) const
|
||||
{
|
||||
if (h->mRed)
|
||||
assert(not isParentRed);
|
||||
@@ -1018,7 +1018,7 @@ Category::Category(Datablock& db, const string& name, Validator* Validator)
|
||||
for (auto& k: mCatValidator->mMandatoryFields)
|
||||
addColumn(k);
|
||||
|
||||
mIndex = new catIndex(this);
|
||||
mIndex = new CatIndex(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1044,7 +1044,7 @@ void Category::setValidator(Validator* v)
|
||||
mCatValidator = mValidator->getValidatorForCategory(mName);
|
||||
if (mCatValidator != nullptr)
|
||||
{
|
||||
mIndex = new catIndex(this);
|
||||
mIndex = new CatIndex(this);
|
||||
mIndex->reconstruct();
|
||||
#if DEBUG
|
||||
assert(mIndex->size() == size());
|
||||
@@ -1192,7 +1192,7 @@ void Category::clear()
|
||||
if (mIndex != nullptr)
|
||||
{
|
||||
delete mIndex;
|
||||
mIndex = new catIndex(this);
|
||||
mIndex = new CatIndex(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -762,11 +762,11 @@ void DictParser::parseSaveFrame()
|
||||
string category = dict.firstItem("_category.id");
|
||||
|
||||
vector<string> keys;
|
||||
for (auto k: dict["categoryKey"])
|
||||
for (auto k: dict["category_key"])
|
||||
keys.push_back(get<1>(splitTagName(k["name"].as<string>())));
|
||||
|
||||
iset groups;
|
||||
for (auto g: dict["categoryGroup"])
|
||||
for (auto g: dict["category_group"])
|
||||
groups.insert(g["id"].as<string>());
|
||||
|
||||
mImpl->mCategoryValidators.push_back(ValidateCategory{category, keys, groups});
|
||||
|
||||
192
src/CifUtils.cpp
192
src/CifUtils.cpp
@@ -4,8 +4,21 @@
|
||||
|
||||
#include <tuple>
|
||||
#include <iostream>
|
||||
#include <cstdio>
|
||||
#include <atomic>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define TERM_WIDTH 80
|
||||
#else
|
||||
#include <termios.h>
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#if BOOST_VERSION >= 104800
|
||||
#include <boost/timer/timer.hpp>
|
||||
#endif
|
||||
|
||||
#include "cif++/CifUtils.h"
|
||||
|
||||
@@ -94,13 +107,13 @@ int icompare(const char* a, const char* b)
|
||||
return d;
|
||||
}
|
||||
|
||||
void to_lower(string& s)
|
||||
void toLower(string& s)
|
||||
{
|
||||
for (auto& c: s)
|
||||
c = tolower(c);
|
||||
}
|
||||
|
||||
string to_lower_copy(const string& s)
|
||||
string toLowerCopy(const string& s)
|
||||
{
|
||||
string result(s);
|
||||
for (auto& c: result)
|
||||
@@ -110,7 +123,7 @@ string to_lower_copy(const string& s)
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
tuple<string,string> split_tag_name(const string& tag)
|
||||
tuple<string,string> splitTagName(const string& tag)
|
||||
{
|
||||
if (tag.empty())
|
||||
throw runtime_error("empty tag");
|
||||
@@ -196,12 +209,12 @@ const LineBreakClass kASCII_LBTable[128] =
|
||||
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_OpenPunctuation, kLBC_BreakAfter, kLBC_ClosePunctuation, kLBC_Alphabetic, kLBC_CombiningMark
|
||||
};
|
||||
|
||||
string::const_iterator next_line_break(string::const_iterator text, string::const_iterator end)
|
||||
string::const_iterator nextLineBreak(string::const_iterator text, string::const_iterator end)
|
||||
{
|
||||
if (text == end)
|
||||
return text;
|
||||
|
||||
enum break_action
|
||||
enum breakAction
|
||||
{
|
||||
DBK = 0, // direct break (blank in table)
|
||||
IBK, // indirect break (% in table)
|
||||
@@ -210,7 +223,7 @@ string::const_iterator next_line_break(string::const_iterator text, string::cons
|
||||
CPB // combining prohibited break
|
||||
};
|
||||
|
||||
const break_action brkTable[27][27] = {
|
||||
const breakAction brkTable[27][27] = {
|
||||
// OP CL CP QU GL NS EX SY IS PR PO NU AL ID IN HY BA BB B2 ZW CM WJ H2 H3 JL JV JT
|
||||
/* OP */ { PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, CPB, PBK, PBK, PBK, PBK, PBK, PBK },
|
||||
/* CL */ { DBK, PBK, PBK, IBK, IBK, PBK, PBK, PBK, PBK, IBK, IBK, DBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK },
|
||||
@@ -278,7 +291,7 @@ string::const_iterator next_line_break(string::const_iterator text, string::cons
|
||||
if (ncls == kLBC_Space)
|
||||
continue;
|
||||
|
||||
break_action brk = brkTable[cls][ncls];
|
||||
breakAction brk = brkTable[cls][ncls];
|
||||
|
||||
if (brk == DBK or (brk == IBK and lcls == kLBC_Space))
|
||||
break;
|
||||
@@ -289,7 +302,7 @@ string::const_iterator next_line_break(string::const_iterator text, string::cons
|
||||
return text;
|
||||
}
|
||||
|
||||
vector<string> wrap_line(const string& text, unsigned int width)
|
||||
vector<string> wrapLine(const string& text, unsigned int width)
|
||||
{
|
||||
vector<string> result;
|
||||
vector<size_t> offsets = { 0 };
|
||||
@@ -297,7 +310,7 @@ vector<string> wrap_line(const string& text, unsigned int width)
|
||||
auto b = text.begin();
|
||||
while (b != text.end())
|
||||
{
|
||||
auto e = next_line_break(b, text.end());
|
||||
auto e = nextLineBreak(b, text.end());
|
||||
|
||||
offsets.push_back(e - text.begin());
|
||||
|
||||
@@ -350,7 +363,7 @@ vector<string> wrap_line(const string& text, unsigned int width)
|
||||
return result;
|
||||
}
|
||||
|
||||
vector<string> word_wrap(const string& text, unsigned int width)
|
||||
vector<string> wordWrap(const string& text, unsigned int width)
|
||||
{
|
||||
vector<string> paragraphs;
|
||||
ba::split(paragraphs, text, ba::is_any_of("\n"));
|
||||
@@ -364,11 +377,168 @@ vector<string> word_wrap(const string& text, unsigned int width)
|
||||
continue;
|
||||
}
|
||||
|
||||
auto lines = wrap_line(p, width);
|
||||
auto lines = wrapLine(p, width);
|
||||
result.insert(result.end(), lines.begin(), lines.end());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifdef _MSC_VER
|
||||
uint32 get_terminal_width()
|
||||
{
|
||||
return TERM_WIDTH;
|
||||
}
|
||||
#else
|
||||
uint32 get_terminal_width()
|
||||
{
|
||||
struct winsize w;
|
||||
ioctl(0, TIOCGWINSZ, &w);
|
||||
return w.ws_col;
|
||||
}
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
struct ProgressImpl
|
||||
{
|
||||
ProgressImpl(int64 inMax, const string& inAction)
|
||||
: mMax(inMax), mConsumed(0), mAction(inAction), mMessage(inAction)
|
||||
, mThread(boost::bind(&ProgressImpl::Run, this)) {}
|
||||
|
||||
void Run();
|
||||
|
||||
void PrintProgress();
|
||||
void PrintDone();
|
||||
|
||||
int64 mMax;
|
||||
atomic<int64> mConsumed;
|
||||
string mAction, mMessage;
|
||||
boost::mutex mMutex;
|
||||
boost::thread mThread;
|
||||
boost::timer::cpu_timer
|
||||
mTimer;
|
||||
};
|
||||
|
||||
void ProgressImpl::Run()
|
||||
{
|
||||
try
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
boost::this_thread::sleep(boost::posix_time::seconds(1));
|
||||
|
||||
boost::mutex::scoped_lock lock(mMutex);
|
||||
|
||||
if (mConsumed == mMax)
|
||||
break;
|
||||
|
||||
PrintProgress();
|
||||
}
|
||||
}
|
||||
catch (...) {}
|
||||
|
||||
PrintDone();
|
||||
}
|
||||
|
||||
void ProgressImpl::PrintProgress()
|
||||
{
|
||||
uint32 width = get_terminal_width();
|
||||
|
||||
string msg;
|
||||
msg.reserve(width + 1);
|
||||
if (mMessage.length() <= 20)
|
||||
{
|
||||
msg = mMessage;
|
||||
if (msg.length() < 20)
|
||||
msg.append(20 - msg.length(), ' ');
|
||||
}
|
||||
else
|
||||
msg = mMessage.substr(0, 17) + "...";
|
||||
|
||||
msg += " [";
|
||||
|
||||
float progress = static_cast<float>(mConsumed) / mMax;
|
||||
int tw = width - 28;
|
||||
int twd = static_cast<int>(tw * progress + 0.5f);
|
||||
msg.append(twd, '=');
|
||||
msg.append(tw - twd, ' ');
|
||||
msg.append("] ");
|
||||
|
||||
int perc = static_cast<int>(100 * progress);
|
||||
if (perc < 100)
|
||||
msg += ' ';
|
||||
if (perc < 10)
|
||||
msg += ' ';
|
||||
msg += to_string(perc);
|
||||
msg += '%';
|
||||
|
||||
cout << '\r' << msg;
|
||||
cout.flush();
|
||||
}
|
||||
|
||||
void ProgressImpl::PrintDone()
|
||||
{
|
||||
string msg = mAction + " done in " + mTimer.format(0, "%ts cpu / %ws wall");
|
||||
|
||||
uint32 width = get_terminal_width();
|
||||
|
||||
if (msg.length() < width)
|
||||
msg += string(width - msg.length(), ' ');
|
||||
|
||||
cout << '\r' << msg << endl;
|
||||
}
|
||||
|
||||
Progress::Progress(int64 inMax, const string& inAction)
|
||||
: mImpl(nullptr)
|
||||
{
|
||||
if (isatty(STDOUT_FILENO))
|
||||
mImpl = new ProgressImpl(inMax, inAction);
|
||||
}
|
||||
|
||||
Progress::~Progress()
|
||||
{
|
||||
if (mImpl != nullptr and mImpl->mThread.joinable())
|
||||
{
|
||||
mImpl->mThread.interrupt();
|
||||
mImpl->mThread.join();
|
||||
}
|
||||
|
||||
delete mImpl;
|
||||
}
|
||||
|
||||
void Progress::consumed(int64 inConsumed)
|
||||
{
|
||||
if (mImpl != nullptr and
|
||||
(mImpl->mConsumed += inConsumed) >= mImpl->mMax and
|
||||
mImpl->mThread.joinable())
|
||||
{
|
||||
mImpl->mThread.interrupt();
|
||||
mImpl->mThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
void Progress::progress(int64 inProgress)
|
||||
{
|
||||
if (mImpl != nullptr and
|
||||
(mImpl->mConsumed = inProgress) >= mImpl->mMax and
|
||||
mImpl->mThread.joinable())
|
||||
{
|
||||
mImpl->mThread.interrupt();
|
||||
mImpl->mThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
void Progress::message(const std::string& inMessage)
|
||||
{
|
||||
if (mImpl != nullptr)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(mImpl->mMutex);
|
||||
mImpl->mMessage = inMessage;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
154
src/DistanceMap.cpp
Normal file
154
src/DistanceMap.cpp
Normal file
@@ -0,0 +1,154 @@
|
||||
// copyright
|
||||
|
||||
#include "cif++/Config.h"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
#include "cif++/DistanceMap.h"
|
||||
#include "cif++/CifUtils.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace libcif
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
vector<clipper::RTop_orth> AlternativeSites(const clipper::Spacegroup& spacegroup,
|
||||
const clipper::Cell& cell)
|
||||
{
|
||||
vector<clipper::RTop_orth> result;
|
||||
|
||||
for (int i = 0; i < spacegroup.num_symops(); ++i)
|
||||
{
|
||||
const auto& symop = spacegroup.symop(i);
|
||||
|
||||
for (int u: { -1, 0, 1})
|
||||
for (int v: { -1, 0, 1})
|
||||
for (int w: { -1, 0, 1})
|
||||
{
|
||||
result.push_back(
|
||||
clipper::RTop_frac(
|
||||
symop.rot(), symop.trn() + clipper::Vec3<>(u, v, w)
|
||||
).rtop_orth(cell));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
DistanceMap::DistanceMap(const Structure& p, const clipper::Spacegroup& spacegroup, const clipper::Cell& cell)
|
||||
: dim(0)
|
||||
{
|
||||
auto atoms = p.atoms();
|
||||
dim = atoms.size();
|
||||
|
||||
dist = vector<float>(dim * (dim - 1), 0.f);
|
||||
vector<clipper::Coord_orth> locations(dim);
|
||||
vector<bool> isWater(dim, false);
|
||||
|
||||
for (auto& atom: atoms)
|
||||
{
|
||||
size_t ix = index.size();
|
||||
index[atom.id()] = ix;
|
||||
|
||||
locations[ix] = atom.location();
|
||||
isWater[ix] = atom.isWater();
|
||||
};
|
||||
|
||||
vector<clipper::RTop_orth> rtOrth = AlternativeSites(spacegroup, cell);
|
||||
|
||||
cif::Progress progress(locations.size() - 1, "Creating distance map");
|
||||
|
||||
boost::thread_group t;
|
||||
size_t N = boost::thread::hardware_concurrency();
|
||||
atomic<size_t> next(0);
|
||||
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
t.create_thread([&]()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
size_t i = next++;
|
||||
|
||||
if (i >= locations.size())
|
||||
break;
|
||||
|
||||
for (size_t j = i + 1; j < locations.size(); ++j)
|
||||
{
|
||||
// if (not (isWater[i] or isWater[j]))
|
||||
// continue;
|
||||
|
||||
// find nearest location based on spacegroup/cell
|
||||
double minR2 = numeric_limits<double>::max();
|
||||
|
||||
for (const auto& rt: rtOrth)
|
||||
{
|
||||
auto p = locations[j].transform(rt);
|
||||
|
||||
double r2 = (locations[i] - p).lengthsq();
|
||||
if (minR2 > r2)
|
||||
minR2 = r2;
|
||||
}
|
||||
|
||||
uint32 ix = j + i * dim - i * (i + 1) / 2;
|
||||
|
||||
assert(ix < dist.size());
|
||||
dist[ix] = sqrt(minR2);
|
||||
}
|
||||
|
||||
progress.consumed(1);
|
||||
}
|
||||
});
|
||||
|
||||
t.join_all();
|
||||
}
|
||||
|
||||
float DistanceMap::operator()(const Atom& a, const Atom& b) const
|
||||
{
|
||||
uint32 ixa = index.at(a.id());
|
||||
uint32 ixb = index.at(b.id());
|
||||
|
||||
if (ixb < ixa)
|
||||
swap(ixa, ixb);
|
||||
|
||||
uint32 ix = ixb + ixa * dim - ixa * (ixa + 1) / 2;
|
||||
|
||||
assert(ix < dist.size());
|
||||
return dist[ix];
|
||||
}
|
||||
|
||||
vector<Atom> DistanceMap::near(const Atom& a, float maxDistance) const
|
||||
{
|
||||
vector<Atom> result;
|
||||
const File& f = a.getFile();
|
||||
|
||||
uint32 ixa = index.at(a.id());
|
||||
|
||||
for (auto& i: index)
|
||||
{
|
||||
uint32 ixb = i.second;
|
||||
|
||||
if (ixb == ixa)
|
||||
continue;
|
||||
|
||||
uint32 ix;
|
||||
|
||||
if (ixa < ixb)
|
||||
ix = ixb + ixa * dim - ixa * (ixa + 1) / 2;
|
||||
else
|
||||
ix = ixa + ixb * dim - ixb * (ixb + 1) / 2;
|
||||
|
||||
assert(ix < dist.size());
|
||||
if (dist[ix] != 0 and dist[ix] <= maxDistance)
|
||||
result.emplace_back(f, i.first);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
2804
src/PDB2Cif.cpp
2804
src/PDB2Cif.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
#include "libpr.h"
|
||||
#include "cif++/Config.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
@@ -8,19 +8,18 @@
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/numeric/ublas/matrix.hpp>
|
||||
|
||||
#include "peptidedb.h"
|
||||
#include "pdb2cif.h"
|
||||
#include "libcif/atom_type.h"
|
||||
#include "libcif/compound.h"
|
||||
#include "libcif/pdb2cif-remark3.h"
|
||||
#include "cif++/AtomType.h"
|
||||
#include "cif++/Compound.h"
|
||||
#include "cif++/PDB2CifRemark3.h"
|
||||
#include "cif++/PeptideDB.h"
|
||||
|
||||
using namespace std;
|
||||
namespace ba = boost::algorithm;
|
||||
|
||||
using cif::datablock;
|
||||
using cif::category;
|
||||
using cif::row;
|
||||
using cif::key;
|
||||
using cif::Datablock;
|
||||
using cif::Category;
|
||||
using cif::Row;
|
||||
using cif::Key;
|
||||
using cif::iequals;
|
||||
|
||||
static const char* kRedOn = "\033[37;1;41m";
|
||||
@@ -31,11 +30,11 @@ static const char* kRedOff = "\033[0m";
|
||||
struct TemplateLine
|
||||
{
|
||||
const char* rx;
|
||||
int next_state_offset;
|
||||
int nextStateOffset;
|
||||
const char* category;
|
||||
initializer_list<const char*> items;
|
||||
const char* ls_restr_type = nullptr;
|
||||
bool create_new;
|
||||
const char* lsRestrType = nullptr;
|
||||
bool createNew;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -139,7 +138,7 @@ const TemplateLine kBusterTNT_Template[] = {
|
||||
class BUSTER_TNT_Remark3Parser : public Remark3Parser
|
||||
{
|
||||
public:
|
||||
BUSTER_TNT_Remark3Parser(const string& name, const string& expMethod, PDBRecord* r, cif::datablock& db)
|
||||
BUSTER_TNT_Remark3Parser(const string& name, const string& expMethod, PDBRecord* r, cif::Datablock& db)
|
||||
: Remark3Parser(name, expMethod, r, db,
|
||||
kBusterTNT_Template, sizeof(kBusterTNT_Template) / sizeof(TemplateLine),
|
||||
regex(R"((BUSTER(?:-TNT)?)(?: (\d+(?:\..+)?))?)")) {}
|
||||
@@ -232,7 +231,7 @@ const TemplateLine kCNS_Template[] = {
|
||||
class CNS_Remark3Parser : public Remark3Parser
|
||||
{
|
||||
public:
|
||||
CNS_Remark3Parser(const string& name, const string& expMethod, PDBRecord* r, cif::datablock& db)
|
||||
CNS_Remark3Parser(const string& name, const string& expMethod, PDBRecord* r, cif::Datablock& db)
|
||||
: Remark3Parser(name, expMethod, r, db, kCNS_Template,
|
||||
sizeof(kCNS_Template) / sizeof(TemplateLine), regex(R"((CN[SX])(?: (\d+(?:\.\d+)?))?)")) {}
|
||||
};
|
||||
@@ -310,16 +309,16 @@ const TemplateLine kPHENIX_Template[] = {
|
||||
class PHENIX_Remark3Parser : public Remark3Parser
|
||||
{
|
||||
public:
|
||||
PHENIX_Remark3Parser(const string& name, const string& expMethod, PDBRecord* r, cif::datablock& db)
|
||||
PHENIX_Remark3Parser(const string& name, const string& expMethod, PDBRecord* r, cif::Datablock& db)
|
||||
: Remark3Parser(name, expMethod, r, db, kPHENIX_Template, sizeof(kPHENIX_Template) / sizeof(TemplateLine),
|
||||
regex(R"((PHENIX)(?: \(PHENIX\.REFINE:) (\d+(?:\.[^)]+)?)\)?)")) {}
|
||||
|
||||
virtual void Fixup();
|
||||
virtual void fixup();
|
||||
};
|
||||
|
||||
void PHENIX_Remark3Parser::Fixup()
|
||||
void PHENIX_Remark3Parser::fixup()
|
||||
{
|
||||
for (auto r: m_db["refine_ls_shell"])
|
||||
for (auto r: mDb["refine_ls_shell"])
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -401,7 +400,7 @@ const TemplateLine kPROLSQ_Template[] = {
|
||||
class PROLSQ_Remark3Parser : public Remark3Parser
|
||||
{
|
||||
public:
|
||||
PROLSQ_Remark3Parser(const string& name, const string& expMethod, PDBRecord* r, cif::datablock& db)
|
||||
PROLSQ_Remark3Parser(const string& name, const string& expMethod, PDBRecord* r, cif::Datablock& db)
|
||||
: Remark3Parser(name, expMethod, r, db, kPROLSQ_Template, sizeof(kPROLSQ_Template) / sizeof(TemplateLine),
|
||||
regex(R"((PROLSQ|NUCLSQ)(?: (\d+(?:\.\d+)?))?)")) {}
|
||||
};
|
||||
@@ -472,12 +471,12 @@ const TemplateLine kREFMAC_Template[] = {
|
||||
class REFMAC_Remark3Parser : public Remark3Parser
|
||||
{
|
||||
public:
|
||||
REFMAC_Remark3Parser(const string& name, const string& expMethod, PDBRecord* r, cif::datablock& db)
|
||||
REFMAC_Remark3Parser(const string& name, const string& expMethod, PDBRecord* r, cif::Datablock& db)
|
||||
: Remark3Parser(name, expMethod, r, db, kREFMAC_Template, sizeof(kREFMAC_Template) / sizeof(TemplateLine),
|
||||
regex(".+")) {}
|
||||
|
||||
virtual string Program() { return "REFMAC"; }
|
||||
virtual string Version() { return ""; }
|
||||
virtual string program() { return "REFMAC"; }
|
||||
virtual string version() { return ""; }
|
||||
};
|
||||
|
||||
const TemplateLine kREFMAC5_Template[] = {
|
||||
@@ -624,7 +623,7 @@ const TemplateLine kREFMAC5_Template[] = {
|
||||
class REFMAC5_Remark3Parser : public Remark3Parser
|
||||
{
|
||||
public:
|
||||
REFMAC5_Remark3Parser(const string& name, const string& expMethod, PDBRecord* r, cif::datablock& db)
|
||||
REFMAC5_Remark3Parser(const string& name, const string& expMethod, PDBRecord* r, cif::Datablock& db)
|
||||
: Remark3Parser(name, expMethod, r, db, kREFMAC5_Template, sizeof(kREFMAC5_Template) / sizeof(TemplateLine),
|
||||
regex(R"((REFMAC)(?: (\d+(?:\..+)?))?)")) {}
|
||||
};
|
||||
@@ -682,7 +681,7 @@ const TemplateLine kSHELXL_Template[] = {
|
||||
class SHELXL_Remark3Parser : public Remark3Parser
|
||||
{
|
||||
public:
|
||||
SHELXL_Remark3Parser(const string& name, const string& expMethod, PDBRecord* r, cif::datablock& db)
|
||||
SHELXL_Remark3Parser(const string& name, const string& expMethod, PDBRecord* r, cif::Datablock& db)
|
||||
: Remark3Parser(name, expMethod, r, db, kSHELXL_Template, sizeof(kSHELXL_Template) / sizeof(TemplateLine),
|
||||
regex(R"((SHELXL)(?:-(\d+(?:\..+)?)))")) {}
|
||||
};
|
||||
@@ -737,7 +736,7 @@ const TemplateLine kTNT_Template[] = {
|
||||
class TNT_Remark3Parser : public Remark3Parser
|
||||
{
|
||||
public:
|
||||
TNT_Remark3Parser(const string& name, const string& expMethod, PDBRecord* r, cif::datablock& db)
|
||||
TNT_Remark3Parser(const string& name, const string& expMethod, PDBRecord* r, cif::Datablock& db)
|
||||
: Remark3Parser(name, expMethod, r, db, kTNT_Template, sizeof(kTNT_Template) / sizeof(TemplateLine),
|
||||
regex(R"((TNT)(?: V. (\d+.+)?)?)")) {}
|
||||
};
|
||||
@@ -815,45 +814,45 @@ const TemplateLine kXPLOR_Template[] = {
|
||||
class XPLOR_Remark3Parser : public Remark3Parser
|
||||
{
|
||||
public:
|
||||
XPLOR_Remark3Parser(const string& name, const string& expMethod, PDBRecord* r, cif::datablock& db)
|
||||
XPLOR_Remark3Parser(const string& name, const string& expMethod, PDBRecord* r, cif::Datablock& db)
|
||||
: Remark3Parser(name, expMethod, r, db, kXPLOR_Template, sizeof(kXPLOR_Template) / sizeof(TemplateLine),
|
||||
regex(R"((X-PLOR)(?: (\d+(?:\.\d+)?))?)")) {}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
Remark3Parser::Remark3Parser(const std::string& name, const std::string& expMethod, PDBRecord* r, cif::datablock& db,
|
||||
const TemplateLine templatelines[], uint32 templateLineCount, std::regex program_version)
|
||||
: m_name(name), m_expMethod(expMethod), m_rec(r), m_db(db.name())
|
||||
, m_template(templatelines), m_templateCount(templateLineCount), m_program_version(program_version)
|
||||
Remark3Parser::Remark3Parser(const std::string& name, const std::string& expMethod, PDBRecord* r, cif::Datablock& db,
|
||||
const TemplateLine templatelines[], uint32 templateLineCount, std::regex programversion)
|
||||
: mName(name), mExpMethod(expMethod), mRec(r), mDb(db.getName())
|
||||
, mTemplate(templatelines), mTemplateCount(templateLineCount), mProgramVersion(programversion)
|
||||
{
|
||||
}
|
||||
|
||||
string Remark3Parser::NextLine()
|
||||
string Remark3Parser::nextLine()
|
||||
{
|
||||
m_line.clear();
|
||||
mLine.clear();
|
||||
|
||||
while (m_rec != nullptr and m_rec->is("REMARK 3"))
|
||||
while (mRec != nullptr and mRec->is("REMARK 3"))
|
||||
{
|
||||
size_t valueIndent = 0;
|
||||
for (size_t i = 4; i < m_rec->m_vlen; ++i)
|
||||
for (size_t i = 4; i < mRec->mVlen; ++i)
|
||||
{
|
||||
if (m_rec->m_value[i] == ' ')
|
||||
if (mRec->mValue[i] == ' ')
|
||||
continue;
|
||||
|
||||
if (m_rec->m_value[i] == ':')
|
||||
if (mRec->mValue[i] == ':')
|
||||
{
|
||||
valueIndent = i;
|
||||
while (valueIndent < m_rec->m_vlen and m_rec->m_value[i] == ' ')
|
||||
while (valueIndent < mRec->mVlen and mRec->mValue[i] == ' ')
|
||||
++valueIndent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_line = m_rec->v_s(12);
|
||||
m_rec = m_rec->m_next;
|
||||
mLine = mRec->vS(12);
|
||||
mRec = mRec->mNext;
|
||||
|
||||
if (m_line.empty())
|
||||
if (mLine.empty())
|
||||
continue;
|
||||
|
||||
// concatenate value that is wrapped over multiple lines (tricky code...)
|
||||
@@ -862,25 +861,25 @@ string Remark3Parser::NextLine()
|
||||
{
|
||||
string indent(valueIndent - 4, ' ');
|
||||
|
||||
while (m_rec->is("REMARK 3") and m_rec->m_vlen > valueIndent)
|
||||
while (mRec->is("REMARK 3") and mRec->mVlen > valueIndent)
|
||||
{
|
||||
string v(m_rec->m_value + 4, m_rec->m_value + m_rec->m_vlen);
|
||||
string v(mRec->mValue + 4, mRec->mValue + mRec->mVlen);
|
||||
if (not ba::starts_with(v, indent))
|
||||
break;
|
||||
|
||||
m_line += ' ';
|
||||
m_line.append(m_rec->m_value + valueIndent, m_rec->m_value + m_rec->m_vlen);
|
||||
mLine += ' ';
|
||||
mLine.append(mRec->mValue + valueIndent, mRec->mValue + mRec->mVlen);
|
||||
|
||||
m_rec = m_rec->m_next;
|
||||
mRec = mRec->mNext;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// collapse multiple spaces
|
||||
bool space = false;
|
||||
auto i = m_line.begin(), j = i;
|
||||
auto i = mLine.begin(), j = i;
|
||||
|
||||
while (i != m_line.end())
|
||||
while (i != mLine.end())
|
||||
{
|
||||
bool nspace = isspace(*i);
|
||||
|
||||
@@ -893,129 +892,129 @@ string Remark3Parser::NextLine()
|
||||
space = nspace;
|
||||
++i;
|
||||
}
|
||||
m_line.erase(j, m_line.end());
|
||||
mLine.erase(j, mLine.end());
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (VERBOSE >= 2)
|
||||
cerr << "RM3: " << m_line << endl;
|
||||
cerr << "RM3: " << mLine << endl;
|
||||
|
||||
return m_line;
|
||||
return mLine;
|
||||
}
|
||||
|
||||
bool Remark3Parser::Match(const char* expr, int nextState)
|
||||
bool Remark3Parser::match(const char* expr, int nextState)
|
||||
{
|
||||
regex rx(expr);
|
||||
|
||||
bool result = regex_match(m_line, m_m, rx);
|
||||
bool result = regex_match(mLine, mM, rx);
|
||||
|
||||
if (result)
|
||||
m_state = nextState;
|
||||
mState = nextState;
|
||||
else if (VERBOSE >= 3)
|
||||
cerr << kRedOn << "No Match:" << kRedOff << " '" << expr << '\'' << endl;
|
||||
cerr << kRedOn << "No match:" << kRedOff << " '" << expr << '\'' << endl;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
float Remark3Parser::Parse()
|
||||
float Remark3Parser::parse()
|
||||
{
|
||||
int lineCount = 0, dropped = 0;
|
||||
string remarks;
|
||||
m_state = 0;
|
||||
mState = 0;
|
||||
|
||||
while (m_rec != nullptr)
|
||||
while (mRec != nullptr)
|
||||
{
|
||||
NextLine();
|
||||
nextLine();
|
||||
|
||||
if (m_line.empty())
|
||||
if (mLine.empty())
|
||||
break;
|
||||
|
||||
++lineCount;
|
||||
|
||||
// Skip over AUTHORS lines
|
||||
if (m_state == 0 and Match(R"(AUTHORS\s*:.+)", 0))
|
||||
if (mState == 0 and match(R"(AUTHORS\s*:.+)", 0))
|
||||
continue;
|
||||
|
||||
auto state = m_state;
|
||||
for (state = m_state; state < m_templateCount; ++state)
|
||||
auto state = mState;
|
||||
for (state = mState; state < mTemplateCount; ++state)
|
||||
{
|
||||
const TemplateLine& tmpl = m_template[state];
|
||||
const TemplateLine& tmpl = mTemplate[state];
|
||||
|
||||
if (Match(tmpl.rx, state + tmpl.next_state_offset))
|
||||
if (match(tmpl.rx, state + tmpl.nextStateOffset))
|
||||
{
|
||||
if (not (tmpl.category == nullptr or tmpl.items.size() == 0))
|
||||
{
|
||||
if (tmpl.ls_restr_type == nullptr)
|
||||
StoreCapture(tmpl.category, tmpl.items, tmpl.create_new);
|
||||
else if (tmpl.create_new)
|
||||
StoreRefineLsRestr(tmpl.ls_restr_type, tmpl.items);
|
||||
if (tmpl.lsRestrType == nullptr)
|
||||
storeCapture(tmpl.category, tmpl.items, tmpl.createNew);
|
||||
else if (tmpl.createNew)
|
||||
storeRefineLsRestr(tmpl.lsRestrType, tmpl.items);
|
||||
else
|
||||
UpdateRefineLsRestr(tmpl.ls_restr_type, tmpl.items);
|
||||
updateRefineLsRestr(tmpl.lsRestrType, tmpl.items);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (state < m_templateCount)
|
||||
if (state < mTemplateCount)
|
||||
continue;
|
||||
|
||||
if (state == m_templateCount and Match(R"(OTHER REFINEMENT REMARKS\s*:\s*(.*))", m_templateCount + 1))
|
||||
if (state == mTemplateCount and match(R"(OTHER REFINEMENT REMARKS\s*:\s*(.*))", mTemplateCount + 1))
|
||||
{
|
||||
remarks = m_m[1].str();
|
||||
remarks = mM[1].str();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (state == m_templateCount + 1)
|
||||
if (state == mTemplateCount + 1)
|
||||
{
|
||||
remarks = remarks + '\n' + m_line;
|
||||
remarks = remarks + '\n' + mLine;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (VERBOSE >= 2)
|
||||
cerr << kRedOn << "Dropping line:" << kRedOff << " '" << m_line << '\'' << endl;
|
||||
cerr << kRedOn << "Dropping line:" << kRedOff << " '" << mLine << '\'' << endl;
|
||||
|
||||
++dropped;
|
||||
}
|
||||
|
||||
if (not remarks.empty() and not iequals(remarks, "NULL"))
|
||||
m_db["refine"].front()["details"] = remarks;
|
||||
mDb["refine"].front()["details"] = remarks;
|
||||
|
||||
float score = float(lineCount - dropped) / lineCount;
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
string Remark3Parser::Program()
|
||||
string Remark3Parser::program()
|
||||
{
|
||||
string result = m_name;
|
||||
string result = mName;
|
||||
|
||||
smatch m;
|
||||
if (regex_match(m_name, m, m_program_version))
|
||||
if (regex_match(mName, m, mProgramVersion))
|
||||
result = m[1].str();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
string Remark3Parser::Version()
|
||||
string Remark3Parser::version()
|
||||
{
|
||||
string result;
|
||||
|
||||
smatch m;
|
||||
if (regex_match(m_name, m, m_program_version))
|
||||
if (regex_match(mName, m, mProgramVersion))
|
||||
result = m[2].str();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Remark3Parser::StoreCapture(const char* category, initializer_list<const char*> items, bool createNew)
|
||||
void Remark3Parser::storeCapture(const char* category, initializer_list<const char*> items, bool createNew)
|
||||
{
|
||||
int capture = 0;
|
||||
for (auto item: items)
|
||||
{
|
||||
++capture;
|
||||
|
||||
string value = m_m[capture].str();
|
||||
string value = mM[capture].str();
|
||||
ba::trim(value);
|
||||
|
||||
if (iequals(value, "NULL") or iequals(value, "NONE"))
|
||||
@@ -1024,60 +1023,60 @@ void Remark3Parser::StoreCapture(const char* category, initializer_list<const ch
|
||||
if (VERBOSE >= 3)
|
||||
cerr << "storing: '" << value << "' in _" << category << '.' << item << endl;
|
||||
|
||||
auto& cat = m_db[category];
|
||||
auto& cat = mDb[category];
|
||||
if (cat.empty() or createNew)
|
||||
{
|
||||
if (iequals(category, "refine"))
|
||||
cat.emplace({
|
||||
{ "pdbx_refine_id", m_expMethod },
|
||||
{ "entry_id", m_db.name() },
|
||||
{ "pdbx_refine_id", mExpMethod },
|
||||
{ "entry_id", mDb.getName() },
|
||||
#warning("???")
|
||||
{ "pdbx_diffrn_id", 1 }
|
||||
});
|
||||
else if (iequals(category, "refine_analyze") or iequals(category, "pdbx_refine"))
|
||||
cat.emplace({
|
||||
{ "pdbx_refine_id", m_expMethod },
|
||||
{ "entry_id", m_db.name() },
|
||||
{ "pdbx_refine_id", mExpMethod },
|
||||
{ "entry_id", mDb.getName() },
|
||||
// { "pdbx_diffrn_id", 1 }
|
||||
});
|
||||
else if (iequals(category, "refine_hist"))
|
||||
{
|
||||
string d_res_high, d_res_low;
|
||||
for (auto r: m_db["refine"])
|
||||
string dResHigh, dResLow;
|
||||
for (auto r: mDb["refine"])
|
||||
{
|
||||
cif::tie(d_res_high, d_res_low) = r.get("ls_d_res_high", "ls_d_res_low");
|
||||
cif::tie(dResHigh, dResLow) = r.get("ls_d_res_high", "ls_d_res_low");
|
||||
break;
|
||||
}
|
||||
|
||||
cat.emplace({
|
||||
{ "pdbx_refine_id", m_expMethod },
|
||||
{ "pdbx_refine_id", mExpMethod },
|
||||
{ "cycle_id", "LAST" },
|
||||
{ "d_res_high", d_res_high.empty() ? "." : d_res_high },
|
||||
{ "d_res_low", d_res_low.empty() ? "." : d_res_low }
|
||||
{ "d_res_high", dResHigh.empty() ? "." : dResHigh },
|
||||
{ "d_res_low", dResLow.empty() ? "." : dResLow }
|
||||
});
|
||||
}
|
||||
else if (iequals(category, "refine_ls_shell"))
|
||||
{
|
||||
cat.emplace({
|
||||
{ "pdbx_refine_id", m_expMethod },
|
||||
{ "pdbx_refine_id", mExpMethod },
|
||||
});
|
||||
}
|
||||
else if (iequals(category, "pdbx_refine_tls_group"))
|
||||
{
|
||||
string tls_group_id;
|
||||
if (not m_db["pdbx_refine_tls"].empty())
|
||||
tls_group_id = m_db["pdbx_refine_tls"].back()["id"].as<string>();
|
||||
string tlsGroupId;
|
||||
if (not mDb["pdbx_refine_tls"].empty())
|
||||
tlsGroupId = mDb["pdbx_refine_tls"].back()["id"].as<string>();
|
||||
|
||||
cat.emplace({
|
||||
{ "pdbx_refine_id", m_expMethod },
|
||||
{ "id", tls_group_id },
|
||||
{ "refine_tls_id", tls_group_id }
|
||||
{ "pdbx_refine_id", mExpMethod },
|
||||
{ "id", tlsGroupId },
|
||||
{ "refine_tls_id", tlsGroupId }
|
||||
});
|
||||
}
|
||||
else if (iequals(category, "pdbx_refine_tls"))
|
||||
{
|
||||
cat.emplace({
|
||||
{ "pdbx_refine_id", m_expMethod },
|
||||
{ "pdbx_refine_id", mExpMethod },
|
||||
{ "method", "refined" }
|
||||
});
|
||||
}
|
||||
@@ -1107,25 +1106,25 @@ void Remark3Parser::StoreCapture(const char* category, initializer_list<const ch
|
||||
}
|
||||
}
|
||||
|
||||
void Remark3Parser::StoreRefineLsRestr(const char* type, initializer_list<const char*> items)
|
||||
void Remark3Parser::storeRefineLsRestr(const char* type, initializer_list<const char*> items)
|
||||
{
|
||||
row r;
|
||||
Row r;
|
||||
int capture = 0;
|
||||
|
||||
for (auto item: items)
|
||||
{
|
||||
++capture;
|
||||
|
||||
string value = m_m[capture].str();
|
||||
string value = mM[capture].str();
|
||||
ba::trim(value);
|
||||
if (value.empty() or iequals(value, "NULL"))
|
||||
continue;
|
||||
|
||||
if (not r)
|
||||
{
|
||||
std::tie(r, std::ignore) = m_db["refine_ls_restr"].emplace({});
|
||||
std::tie(r, std::ignore) = mDb["refine_ls_restr"].emplace({});
|
||||
|
||||
r["pdbx_refine_id"] = m_expMethod;
|
||||
r["pdbx_refine_id"] = mExpMethod;
|
||||
r["type"] = type;
|
||||
}
|
||||
|
||||
@@ -1133,21 +1132,21 @@ void Remark3Parser::StoreRefineLsRestr(const char* type, initializer_list<const
|
||||
}
|
||||
}
|
||||
|
||||
void Remark3Parser::UpdateRefineLsRestr(const char* type, initializer_list<const char*> items)
|
||||
void Remark3Parser::updateRefineLsRestr(const char* type, initializer_list<const char*> items)
|
||||
{
|
||||
auto rows = m_db["refine_ls_restr"].find(cif::key("type") == type and cif::key("pdbx_refine_id") == m_expMethod);
|
||||
auto rows = mDb["refine_ls_restr"].find(cif::Key("type") == type and cif::Key("pdbx_refine_id") == mExpMethod);
|
||||
if (rows.empty())
|
||||
StoreRefineLsRestr(type, items);
|
||||
storeRefineLsRestr(type, items);
|
||||
else
|
||||
{
|
||||
for (row r: rows)
|
||||
for (Row r: rows)
|
||||
{
|
||||
int capture = 0;
|
||||
for (auto item: items)
|
||||
{
|
||||
++capture;
|
||||
|
||||
string value = m_m[capture].str();
|
||||
string value = mM[capture].str();
|
||||
ba::trim(value);
|
||||
if (iequals(value, "NULL"))
|
||||
value.clear();
|
||||
@@ -1162,17 +1161,17 @@ void Remark3Parser::UpdateRefineLsRestr(const char* type, initializer_list<const
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
bool Remark3Parser::Parse(const string& expMethod, PDBRecord* r, cif::datablock& db)
|
||||
bool Remark3Parser::parse(const string& expMethod, PDBRecord* r, cif::Datablock& db)
|
||||
{
|
||||
// simple version, only for the first few lines
|
||||
auto GetNextLine = [&]()
|
||||
auto getNextLine = [&]()
|
||||
{
|
||||
string result;
|
||||
|
||||
while (result.empty() and r != nullptr and r->is("REMARK 3"))
|
||||
{
|
||||
result = r->v_s(12);
|
||||
r = r->m_next;
|
||||
result = r->vS(12);
|
||||
r = r->mNext;
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -1180,12 +1179,12 @@ bool Remark3Parser::Parse(const string& expMethod, PDBRecord* r, cif::datablock&
|
||||
|
||||
// All remark 3 records should start with the same data.
|
||||
|
||||
string line = GetNextLine();
|
||||
string line = getNextLine();
|
||||
|
||||
if (line != "REFINEMENT.")
|
||||
throw runtime_error("Unexpected data in REMARK 3");
|
||||
|
||||
line = GetNextLine();
|
||||
line = getNextLine();
|
||||
|
||||
regex rxp(R"(^PROGRAM\s*:\s*(.+))");
|
||||
smatch m;
|
||||
@@ -1194,36 +1193,36 @@ bool Remark3Parser::Parse(const string& expMethod, PDBRecord* r, cif::datablock&
|
||||
throw runtime_error("Expected valid PROGRAM line in REMARK 3");
|
||||
line = m[1].str();
|
||||
|
||||
struct program_score
|
||||
struct programScore
|
||||
{
|
||||
program_score(const string& program, Remark3Parser* parser, float score)
|
||||
programScore(const string& program, Remark3Parser* parser, float score)
|
||||
: program(program), parser(parser), score(score) {}
|
||||
|
||||
string program;
|
||||
unique_ptr<Remark3Parser> parser;
|
||||
float score;
|
||||
|
||||
bool operator<(const program_score& rhs) const
|
||||
bool operator<(const programScore& rhs) const
|
||||
{
|
||||
return score > rhs.score;
|
||||
}
|
||||
};
|
||||
|
||||
vector<program_score> scores;
|
||||
vector<programScore> scores;
|
||||
|
||||
auto tryParser = [&](Remark3Parser* p)
|
||||
{
|
||||
unique_ptr<Remark3Parser> parser(p);
|
||||
float score = parser->Parse();
|
||||
float score = parser->parse();
|
||||
|
||||
if (VERBOSE >= 2)
|
||||
cerr << "Score for " << parser->Program() << ": " << score << endl;
|
||||
cerr << "Score for " << parser->program() << ": " << score << endl;
|
||||
|
||||
if (score > 0)
|
||||
{
|
||||
auto& software = db["software"];
|
||||
string program = parser->Program();
|
||||
string version = parser->Version();
|
||||
string program = parser->program();
|
||||
string version = parser->version();
|
||||
|
||||
software.emplace({
|
||||
{ "name", program },
|
||||
@@ -1278,11 +1277,11 @@ bool Remark3Parser::Parse(const string& expMethod, PDBRecord* r, cif::datablock&
|
||||
auto& best = scores.front();
|
||||
|
||||
if (VERBOSE >= 2)
|
||||
cerr << "Choosing " << best.parser->Program() << " version '" << best.parser->Version() << "' as refinement program. Score = " << best.score << endl;
|
||||
cerr << "Choosing " << best.parser->program() << " version '" << best.parser->version() << "' as refinement program. Score = " << best.score << endl;
|
||||
|
||||
best.parser->Fixup();
|
||||
best.parser->fixup();
|
||||
|
||||
for (auto& cat1: best.parser->m_db)
|
||||
for (auto& cat1: best.parser->mDb)
|
||||
{
|
||||
auto& cat2 = db[cat1.name()];
|
||||
|
||||
@@ -1292,8 +1291,8 @@ bool Remark3Parser::Parse(const string& expMethod, PDBRecord* r, cif::datablock&
|
||||
if (cat2.empty()) // duh... this will generate a validation error anyway...
|
||||
cat2.emplace({});
|
||||
|
||||
row r1 = cat1.front();
|
||||
row r2 = cat2.front();
|
||||
Row r1 = cat1.front();
|
||||
Row r2 = cat2.front();
|
||||
|
||||
for (auto& i: r1)
|
||||
r2[i.name()] = i.value();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "libpr.h"
|
||||
#include "cif++/Config.h"
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
@@ -8,9 +8,8 @@
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include "cif++.h"
|
||||
|
||||
#include "peptidedb.h"
|
||||
#include "cif++/Cif++.h"
|
||||
#include "cif++/PeptideDB.h"
|
||||
|
||||
using namespace std;
|
||||
namespace fs = boost::filesystem;
|
||||
@@ -62,46 +61,46 @@ struct PeptideDBImpl
|
||||
|
||||
~PeptideDBImpl()
|
||||
{
|
||||
delete m_next;
|
||||
delete mNext;
|
||||
}
|
||||
|
||||
/*unordered_*/set<string> m_known_peptides;
|
||||
set<string> m_known_bases;
|
||||
cif::file m_file;
|
||||
cif::category& m_chem_comp;
|
||||
PeptideDBImpl* m_next;
|
||||
/*unordered_*/set<string> mKnownPeptides;
|
||||
set<string> mKnownBases;
|
||||
cif::File mFile;
|
||||
cif::Category& mChemComp;
|
||||
PeptideDBImpl* mNext;
|
||||
|
||||
string name_for(const string& res_name) const
|
||||
string nameFor(const string& resName) const
|
||||
{
|
||||
string result;
|
||||
|
||||
for (auto& chem_comp: m_chem_comp)
|
||||
for (auto& chemComp: mChemComp)
|
||||
{
|
||||
if (ba::iequals(chem_comp["three_letter_code"].as<string>(), res_name) == false)
|
||||
if (ba::iequals(chemComp["three_letter_code"].as<string>(), resName) == false)
|
||||
continue;
|
||||
|
||||
result = chem_comp["name"].as<string>();
|
||||
result = chemComp["name"].as<string>();
|
||||
ba::trim(result);
|
||||
break;
|
||||
}
|
||||
|
||||
if (result.empty() and m_next)
|
||||
result = m_next->name_for(res_name);
|
||||
if (result.empty() and mNext)
|
||||
result = mNext->nameFor(resName);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
string formula_for(string res_name) const;
|
||||
string formulaFor(string resName) const;
|
||||
|
||||
string unalias(const string& res_name) const
|
||||
string unalias(const string& resName) const
|
||||
{
|
||||
string result = res_name;
|
||||
string result = resName;
|
||||
|
||||
auto& e = const_cast<cif::file&>(m_file)["comp_synonym_list"];
|
||||
auto& e = const_cast<cif::File&>(mFile)["comp_synonym_list"];
|
||||
|
||||
for (auto& synonym: e["chem_comp_synonyms"])
|
||||
{
|
||||
if (ba::iequals(synonym["comp_alternative_id"].as<string>(), res_name) == false)
|
||||
if (ba::iequals(synonym["comp_alternative_id"].as<string>(), resName) == false)
|
||||
continue;
|
||||
|
||||
result = synonym["comp_id"].as<string>();
|
||||
@@ -109,38 +108,38 @@ struct PeptideDBImpl
|
||||
break;
|
||||
}
|
||||
|
||||
if (result.empty() and m_next)
|
||||
result = m_next->unalias(res_name);
|
||||
if (result.empty() and mNext)
|
||||
result = mNext->unalias(resName);
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
PeptideDBImpl::PeptideDBImpl(istream& data, PeptideDBImpl* next)
|
||||
: m_file(data), m_chem_comp(m_file.first_datablock()["chem_comp"]), m_next(next)
|
||||
: mFile(data), mChemComp(mFile.firstDatablock()["chem_comp"]), mNext(next)
|
||||
{
|
||||
for (auto& chem_comp: m_chem_comp)
|
||||
for (auto& chemComp: mChemComp)
|
||||
{
|
||||
string group, three_letter_code;
|
||||
string group, threeLetterCode;
|
||||
|
||||
cif::tie(group, three_letter_code) = chem_comp.get("group", "three_letter_code");
|
||||
cif::tie(group, threeLetterCode) = chemComp.get("group", "three_letter_code");
|
||||
|
||||
if (group == "peptide" or group == "M-peptide" or group == "P-peptide")
|
||||
m_known_peptides.insert(three_letter_code);
|
||||
mKnownPeptides.insert(threeLetterCode);
|
||||
else if (group == "DNA" or group == "RNA")
|
||||
m_known_bases.insert(three_letter_code);
|
||||
mKnownBases.insert(threeLetterCode);
|
||||
}
|
||||
}
|
||||
|
||||
string PeptideDBImpl::formula_for(string res) const
|
||||
string PeptideDBImpl::formulaFor(string res) const
|
||||
{
|
||||
string result;
|
||||
|
||||
ba::to_upper(res);
|
||||
|
||||
for (auto& db: m_file)
|
||||
for (auto& db: mFile)
|
||||
{
|
||||
if (db.name() != "comp_" + res)
|
||||
if (db.getName() != "comp_" + res)
|
||||
continue;
|
||||
|
||||
auto& cat = db["chem_comp_atom"];
|
||||
@@ -162,15 +161,15 @@ string PeptideDBImpl::formula_for(string res) const
|
||||
|
||||
if (result.empty())
|
||||
{
|
||||
if (m_next != nullptr)
|
||||
result = m_next->formula_for(res);
|
||||
if (mNext != nullptr)
|
||||
result = mNext->formulaFor(res);
|
||||
else
|
||||
{
|
||||
const char* clibd_mon = getenv("CLIBD_MON");
|
||||
if (clibd_mon == nullptr)
|
||||
const char* clibdMon = getenv("CLIBD_MON");
|
||||
if (clibdMon == nullptr)
|
||||
throw runtime_error("Cannot locate peptide list, please souce the CCP4 environment");
|
||||
|
||||
fs::path resFile = fs::path(clibd_mon) / ba::to_lower_copy(res.substr(0, 1)) / (res + ".cif");
|
||||
fs::path resFile = fs::path(clibdMon) / ba::to_lower_copy(res.substr(0, 1)) / (res + ".cif");
|
||||
if (fs::exists(resFile))
|
||||
{
|
||||
fs::ifstream file(resFile);
|
||||
@@ -178,7 +177,7 @@ string PeptideDBImpl::formula_for(string res) const
|
||||
{
|
||||
try
|
||||
{
|
||||
cif::file cf(file);
|
||||
cif::File cf(file);
|
||||
|
||||
auto& cat = cf["comp_" + res]["chem_comp_atom"];
|
||||
|
||||
@@ -223,18 +222,18 @@ PeptideDB& PeptideDB::Instance()
|
||||
|
||||
PeptideDB::PeptideDB()
|
||||
{
|
||||
const char* clibd_mon = getenv("CLIBD_MON");
|
||||
if (clibd_mon == nullptr)
|
||||
const char* clibdMon = getenv("CLIBD_MON");
|
||||
if (clibdMon == nullptr)
|
||||
throw runtime_error("Cannot locate peptide list, please souce the CCP4 environment");
|
||||
|
||||
fs::path db = fs::path(clibd_mon) / "list" / "mon_lib_list.cif";
|
||||
fs::path db = fs::path(clibdMon) / "list" / "mon_lib_list.cif";
|
||||
|
||||
PushDictionary(db);
|
||||
pushDictionary(db);
|
||||
|
||||
sInstance = this;
|
||||
}
|
||||
|
||||
void PeptideDB::PushDictionary(boost::filesystem::path dict)
|
||||
void PeptideDB::pushDictionary(boost::filesystem::path dict)
|
||||
{
|
||||
if (not fs::exists(dict))
|
||||
throw runtime_error("file not found: " + dict.string());
|
||||
@@ -246,13 +245,13 @@ void PeptideDB::PushDictionary(boost::filesystem::path dict)
|
||||
mImpl = new PeptideDBImpl(file, mImpl);
|
||||
}
|
||||
|
||||
void PeptideDB::PopDictionary()
|
||||
void PeptideDB::popDictionary()
|
||||
{
|
||||
if (mImpl != nullptr)
|
||||
{
|
||||
auto i = mImpl;
|
||||
mImpl = i->m_next;
|
||||
i->m_next = nullptr;
|
||||
mImpl = i->mNext;
|
||||
i->mNext = nullptr;
|
||||
delete i;
|
||||
}
|
||||
}
|
||||
@@ -262,27 +261,27 @@ PeptideDB::~PeptideDB()
|
||||
delete mImpl;
|
||||
}
|
||||
|
||||
bool PeptideDB::IsKnownPeptide(const string& res_name) const
|
||||
bool PeptideDB::isKnownPeptide(const string& resName) const
|
||||
{
|
||||
return mImpl->m_known_peptides.count(res_name) > 0;
|
||||
return mImpl->mKnownPeptides.count(resName) > 0;
|
||||
}
|
||||
|
||||
bool PeptideDB::IsKnownBase(const string& res_name) const
|
||||
bool PeptideDB::isKnownBase(const string& resName) const
|
||||
{
|
||||
return mImpl->m_known_bases.count(res_name) > 0;
|
||||
return mImpl->mKnownBases.count(resName) > 0;
|
||||
}
|
||||
|
||||
string PeptideDB::GetNameForResidue(const string& res_name) const
|
||||
string PeptideDB::nameForResidue(const string& resName) const
|
||||
{
|
||||
return mImpl->name_for(res_name);
|
||||
return mImpl->nameFor(resName);
|
||||
}
|
||||
|
||||
string PeptideDB::GetFormulaForResidue(const string& res_name) const
|
||||
string PeptideDB::formulaForResidue(const string& resName) const
|
||||
{
|
||||
return mImpl->formula_for(res_name);
|
||||
return mImpl->formulaFor(resName);
|
||||
}
|
||||
|
||||
string PeptideDB::Unalias(const string& res_name) const
|
||||
string PeptideDB::unalias(const string& resName) const
|
||||
{
|
||||
return mImpl->unalias(res_name);
|
||||
return mImpl->unalias(resName);
|
||||
}
|
||||
|
||||
@@ -457,6 +457,16 @@ cif::Datablock& File::data()
|
||||
return *mImpl->mDb;
|
||||
}
|
||||
|
||||
cif::File& File::file()
|
||||
{
|
||||
assert(mImpl);
|
||||
|
||||
if (mImpl == nullptr)
|
||||
throw runtime_error("No data loaded");
|
||||
|
||||
return mImpl->mData;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Structure
|
||||
|
||||
|
||||
Reference in New Issue
Block a user