Skip to content

Commit

Permalink
sdf mol writer chg impl
Browse files Browse the repository at this point in the history
  • Loading branch information
ishitani committed Sep 15, 2024
1 parent d3fafb4 commit 99732a7
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 15 deletions.
2 changes: 1 addition & 1 deletion src/modules/importers/SDFMolReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ void SDFMolReader::readCharge(const LString &str)
continue;
}
auto aid = iter->second;
m_pMol->getAtom(aid)->setAtomPropReal("charge", ichg);
m_pMol->getAtom(aid)->setAtomPropReal("formal_charge", ichg);

MB_DPRINTLN("SDFMolReader> atom %d set charge %d", aid, ichg);
}
Expand Down
41 changes: 41 additions & 0 deletions src/modules/importers/SDFMolWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <modules/molstr/MolResidue.hpp>
#include <modules/molstr/ResidIterator.hpp>
#include <qlib/PrintStream.hpp>
#include <algorithm>

namespace importers {

Expand Down Expand Up @@ -138,6 +139,7 @@ void SDFMolWriter::writeResidue(const molstr::MolResiduePtr &presid,
// 15.0880 10.7980 23.5470 N 0 3 0 4 0 4
int index = 1;
std::map<int, int> idmap;
std::map<int, int> chgmap;
// for (auto iter = presid->atomBegin(); iter != presid->atomEnd(); ++iter, ++index) {
for (int aid: atomset) {
// auto aid = iter->second;
Expand All @@ -148,6 +150,17 @@ void SDFMolWriter::writeResidue(const molstr::MolResiduePtr &presid,
// prs.formatln("%d", index);
prs.formatln("%10.4f%10.4f%10.4f%3s 0 0 0 0 0 0 0 0 0 0 0 0",
pos.x(), pos.y(), pos.z(), elem.c_str());
if (patom->hasAtomProp("formal_charge")) {
auto typenm = patom->getPropTypeName("formal_charge");
if (typenm.equals("real")) {
double charge = patom->getAtomPropReal("formal_charge");
MB_DPRINTLN("atom %d charge %f (%d)", aid, charge, int(charge));
chgmap.insert(std::pair<int, int>(aid, int(charge)));
}
else {
LOG_DPRINTLN("Warning: invalid atom charge type %s ignored", typenm.c_str());
}
}
++index;
}

Expand Down Expand Up @@ -178,10 +191,38 @@ void SDFMolWriter::writeResidue(const molstr::MolResiduePtr &presid,
prs.formatln("%3d%3d%3d 0", id1, id2, itype);
}

writeChgLines(chgmap, prs);

prs.println("M END");
prs.println("$$$$");

}

void SDFMolWriter::writeChgLines(const std::map<int, int> &chgmap,
qlib::PrintStream &prs)
{
int nchg = chgmap.size();
if (nchg==0) {
return;
}

int nchg_lines = int(nchg / 8) + 1;
auto iter = chgmap.begin();
for (int i=0; i<nchg_lines; ++i) {
int nn8 = std::min(nchg, 8);
prs.format("M CHG% 3d", nn8);
for (int j=0; j<8; ++j) {
if (iter == chgmap.end()) {
break;
}
const int aid = (iter->first) + 1;
const int chg = iter->second;
prs.format("% 4d% 4d", aid, chg);
++iter;
--nchg;
}
prs.formatln("");
}
}

} // namespace importers
2 changes: 2 additions & 0 deletions src/modules/importers/SDFMolWriter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ class IMPORTERS_API SDFMolWriter : public qsys::ObjWriter
using ResBondMap = std::map<LString, std::deque<int>>;
ResBondMap m_resBondMap;
void writeResidue(const molstr::MolResiduePtr &presid, qlib::PrintStream &prs);

void writeChgLines(const std::map<int, int> &chgmap,qlib::PrintStream &prs);
};

} // namespace importers
3 changes: 3 additions & 0 deletions src/modules/molstr/MolAtom.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,9 @@ namespace molstr {
*/
public:

bool hasAtomProp(const LString &propnm) const {
return hasDynProp(propnm);
}
bool getAtomProp(const LString &propnm, qlib::LVariant &presult) const {
return getDynProp(propnm, presult);
}
Expand Down
7 changes: 7 additions & 0 deletions src/qlib/LPropContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ LDynPropContainer::~LDynPropContainer()
{
}

bool LDynPropContainer::hasDynProp(const LString &propnm) const
{
DynPropTab::const_iterator i = m_props.find(propnm);
if (m_props.end()==i)
return false; // not found!!
return true;
}

bool LDynPropContainer::getDynProp(const LString &propnm, qlib::LVariant &presult) const
{
Expand Down
1 change: 1 addition & 0 deletions src/qlib/LPropContainer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ namespace qlib {

public:

bool hasDynProp(const LString &propnm) const;
bool getDynProp(const LString &propnm, qlib::LVariant &presult) const;
bool setDynProp(const LString &propnm, const qlib::LVariant &pvalue);
bool removeDynProp(const LString &propnm);
Expand Down
51 changes: 37 additions & 14 deletions tests/importers_tests/test_sdf_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,45 +23,68 @@ def test_sdf_reader(test_data_path):
assert nbonds == 40


def test_sdf_reader_chg(test_data_path):
@pytest.fixture
def mol_from_sdf(test_data_path):
svc = cuemol.getService("StreamManager")
reader = svc.createHandler("sdf", 0)
print(f"{reader=}")

test_sdf_file = test_data_path / "test_chg1.sdf"
test_sdf_file = test_data_path / "test1.sdf"
reader.setPath(str(test_sdf_file))
obj = reader.createDefaultObj()
reader.attach(obj)
reader.read()
reader.detach()
return obj


@pytest.fixture
def mol_from_sdf(test_data_path):
def test_sdf_writer(mol_from_sdf, tmp_path):
svc = cuemol.getService("StreamManager")
writer = svc.createHandler("sdf", 1)
print(f"{writer=}")

out_file = tmp_path / "test.sdf"
writer.setPath(str(out_file))
writer.attach(mol_from_sdf)
writer.write()
writer.detach()

with out_file.open() as f:
result = f.readlines()
# result = f.read()

assert len(result) == 83
assert result[3].rstrip() == " 37 40 0 0 0 0 0 0 0 0999 V2000"
assert result[81].rstrip() == "M END"
assert result[82].rstrip() == "$$$$"


def test_sdf_chg(test_data_path, tmp_path):
svc = cuemol.getService("StreamManager")
reader = svc.createHandler("sdf", 0)
test_sdf_file = test_data_path / "test1.sdf"
print(f"{reader=}")

test_sdf_file = test_data_path / "test_chg1.sdf"
reader.setPath(str(test_sdf_file))
obj = reader.createDefaultObj()
reader.attach(obj)
reader.read()
reader.detach()
return obj

###

def test_sdf_writer(mol_from_sdf, tmp_path):
svc = cuemol.getService("StreamManager")
writer = svc.createHandler("sdf", 1)
print(f"{writer=}")

out_file = tmp_path / "test.sdf"
writer.setPath(str(out_file))
writer.attach(mol_from_sdf)
writer.attach(obj)
writer.write()
writer.detach()

with out_file.open() as f:
result = f.readlines()
# result = f.read()
for i in result:
print(i.rstrip())

assert len(result) == 128
assert result[3].rstrip() == " 59 62 0 0 0 0 0 0 0 0999 V2000"
assert result[125].rstrip() == "M CHG 1 17 1"
assert result[126].rstrip() == "M END"
assert result[127].rstrip() == "$$$$"

0 comments on commit 99732a7

Please sign in to comment.