Skip to content

Commit

Permalink
#1285 Add new query properties support to KET format
Browse files Browse the repository at this point in the history
Fix UT
  • Loading branch information
AliaksandrDziarkach committed Sep 26, 2023
1 parent 9b941cb commit 9307464
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 120 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ def find_diff(a, b):
print("*** KET with query properties ***")

ref_path = joinPathPy("ref/", __file__)

filename = os.path.join(ref_path, "ket_with_query_properties.ket")
name = "ket_with_query_properties.ket"
filename = os.path.join(ref_path, name)

mol = indigo.loadQueryMoleculeFromFile(filename)
with open(filename, "r") as file:
ket_ref = file.read()
ket = mol.json()
diff = find_diff(ket_ref, ket)
if not diff:
print(filename + ".ket:SUCCEED")
print(name + ":SUCCEED")
else:
print(filename + ".ket:FAILED")
print(name + ":FAILED")
print(diff)
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,9 @@
],
"queryProperties": {
"aromaticity": "aliphatic",
"degree": 2,
"ringMembership": 3,
"ringSize": 4,
"connectivity": 5,
"ringConnectivity": 6,
"atomicMass": 12
"ringMembership": 3,
"ringSize": 4
}
}
],
Expand Down
1 change: 1 addition & 0 deletions core/indigo-core/molecule/query_molecule.h
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ namespace indigo
static bool isNotAtom(QueryMolecule::Atom& qa, int elem);
static QueryMolecule::Atom* stripKnownAttrs(QueryMolecule::Atom& qa);
static bool collectAtomList(Atom& qa, Array<int>& list, bool& notList);
static int parseQueryAtom(QueryMolecule::Atom& qa, Array<int>& list);
static int parseQueryAtom(QueryMolecule& qm, int aid, Array<int>& list);
static bool queryAtomIsRegular(QueryMolecule& qm, int aid);
static bool queryAtomIsSpecial(QueryMolecule& qm, int aid);
Expand Down
22 changes: 2 additions & 20 deletions core/indigo-core/molecule/src/molecule_json_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -540,12 +540,6 @@ void MoleculeJsonLoader::parseAtoms(const rapidjson::Value& atoms, BaseMolecule&
_pqmol->resetAtom(atom_idx, QueryMolecule::Atom::und(_pqmol->releaseAtom(atom_idx),
new QueryMolecule::Atom(QueryMolecule::ATOM_AROMATICITY, aromatic)));
}
if (qProps.HasMember("degree"))
{
int degree = qProps["degree"].GetInt();
_pqmol->resetAtom(atom_idx, QueryMolecule::Atom::und(_pqmol->releaseAtom(atom_idx),
new QueryMolecule::Atom(QueryMolecule::ATOM_SUBSTITUENTS, degree)));
}
if (qProps.HasMember("ringMembership"))
{
int rmem = qProps["ringMembership"].GetInt();
Expand All @@ -564,26 +558,14 @@ void MoleculeJsonLoader::parseAtoms(const rapidjson::Value& atoms, BaseMolecule&
_pqmol->resetAtom(
atom_idx, QueryMolecule::Atom::und(_pqmol->releaseAtom(atom_idx), new QueryMolecule::Atom(QueryMolecule::ATOM_CONNECTIVITY, conn)));
}
if (qProps.HasMember("ringConnectivity"))
{
int rconn = qProps["ringConnectivity"].GetInt();
_pqmol->resetAtom(
atom_idx, QueryMolecule::Atom::und(_pqmol->releaseAtom(atom_idx), new QueryMolecule::Atom(QueryMolecule::ATOM_RING_BONDS, rconn)));
}
if (qProps.HasMember("atomicMass"))
{
int mass = qProps["atomicMass"].GetInt();
_pqmol->resetAtom(atom_idx,
QueryMolecule::Atom::und(_pqmol->releaseAtom(atom_idx), new QueryMolecule::Atom(QueryMolecule::ATOM_ISOTOPE, mass)));
}
if (qProps.HasMember("chirality"))
{
std::string arom = qProps["chirality"].GetString();
int chirality;
if (arom == "clockwise")
chirality = ATOM_AROMATIC;
chirality = 1;
else if (arom == "anticlockwise")
chirality = ATOM_ALIPHATIC;
chirality = 2;
else
throw Error("Wrong value for chirality.");
// 2do - add hirality to atom
Expand Down
124 changes: 35 additions & 89 deletions core/indigo-core/molecule/src/molecule_json_saver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -612,91 +612,6 @@ void MoleculeJsonSaver::saveSelection(BaseMolecule& mol, JsonWriter& writer)
}
}

bool MoleculeJsonSaver::_needCustomQuery(QueryMolecule::Atom* atom) const
{
switch (atom->type)
{
case QueryMolecule::ATOM_NUMBER:
case QueryMolecule::ATOM_UNSATURATION: // Processed in other place
case QueryMolecule::ATOM_AROMATICITY:
case QueryMolecule::ATOM_SUBSTITUENTS:
case QueryMolecule::ATOM_SSSR_RINGS:
case QueryMolecule::ATOM_SMALLEST_RING_SIZE:
case QueryMolecule::ATOM_CONNECTIVITY:
case QueryMolecule::ATOM_RING_BONDS:
case QueryMolecule::ATOM_ISOTOPE:
// 2do add hirality
// case QueryMolecule::ATOM_CHIRALITY:
return false;
case QueryMolecule::OP_AND:
for (int i = 0; i < atom->children.size(); i++)
{
if (_needCustomQuery(static_cast<QueryMolecule::Atom*>(atom->children[i])))
return true;
}
return false;
case QueryMolecule::OP_OR:
case QueryMolecule::OP_NOT:
default:
return true;
}
}

void MoleculeJsonSaver::_writeQueryProperties(QueryMolecule::Atom* atom, JsonWriter& writer)
{
switch (atom->type)
{
case QueryMolecule::ATOM_NUMBER:
case QueryMolecule::ATOM_UNSATURATION:
// Processed in other place
break;
case QueryMolecule::ATOM_AROMATICITY:
writer.Key("aromaticity");
if (atom->value_min == ATOM_AROMATIC)
writer.String(ATOM_AROMATIC_STR);
else if (atom->value_min == ATOM_ALIPHATIC)
writer.String(ATOM_ALIPHATIC_STR);
else
throw "Wrong aromaticity value";
break;
case QueryMolecule::ATOM_SUBSTITUENTS:
writer.Key("degree");
writer.Int(atom->value_min);
break;
case QueryMolecule::ATOM_SSSR_RINGS:
writer.Key("ringMembership");
writer.Int(atom->value_min);
break;
case QueryMolecule::ATOM_SMALLEST_RING_SIZE:
writer.Key("ringSize");
writer.Int(atom->value_min);
break;
case QueryMolecule::ATOM_CONNECTIVITY:
writer.Key("connectivity");
writer.Int(atom->value_min);
break;
case QueryMolecule::ATOM_RING_BONDS:
writer.Key("ringConnectivity");
writer.Int(atom->value_min);
break;
case QueryMolecule::ATOM_ISOTOPE:
writer.Key("atomicMass");
writer.Int(atom->value_min);
break;
// 2do add hirality
// case QueryMolecule::ATOM_CHIRALITY:
// break;
case QueryMolecule::OP_AND:
for (int i = 0; i < atom->children.size(); i++)
{
_writeQueryProperties(static_cast<QueryMolecule::Atom*>(atom->children[i]), writer);
}
break;
default:
throw "Invalid queryProperties option.";
}
}

void MoleculeJsonSaver::saveAtoms(BaseMolecule& mol, JsonWriter& writer)
{
QS_DEF(Array<char>, buf);
Expand Down Expand Up @@ -924,20 +839,51 @@ void MoleculeJsonSaver::saveAtoms(BaseMolecule& mol, JsonWriter& writer)
if (_pqmol)
{
QueryMolecule::Atom& atom = _pqmol->getAtom(i);
if (atom.type != QueryMolecule::ATOM_NUMBER && atom.type != QueryMolecule::OP_NONE && atom.type != QueryMolecule::ATOM_UNSATURATION)
int query_atom_type = -1;
QS_DEF(Array<int>, qatom_list);
query_atom_type = QueryMolecule::parseQueryAtom(atom, qatom_list);
QueryMolecule::Atom* s_atom = QueryMolecule::stripKnownAttrs(atom);
bool needCustomQuery = query_atom_type == -1 && s_atom->type != QueryMolecule::ATOM_NUMBER;
std::map<int, const char*> qprops{{QueryMolecule::ATOM_SSSR_RINGS, "ringMembership"},
{QueryMolecule::ATOM_SMALLEST_RING_SIZE, "ringSize"},
{QueryMolecule::ATOM_CONNECTIVITY, "connectivity"}};
bool hasQueryProperties = atom.hasConstraint(QueryMolecule::ATOM_AROMATICITY) ||
std::any_of(qprops.cbegin(), qprops.cend(), [&atom](auto p) { return atom.hasConstraint(p.first); });
if (needCustomQuery || hasQueryProperties)
{
writer.Key("queryProperties");
writer.StartObject();
if (_needCustomQuery(&atom))
if (needCustomQuery)
{
// 2do generate customquery
std::string customQuery;
std::string customQuery = "";
writer.Key("customQuery");
writer.String(customQuery.c_str());
}
else
{
_writeQueryProperties(&atom, writer);
int value = -1;

if (atom.sureValue(QueryMolecule::ATOM_AROMATICITY, value))
{
writer.Key("aromaticity");
if (value == ATOM_AROMATIC)
writer.String(ATOM_AROMATIC_STR);
else if (value == ATOM_ALIPHATIC)
writer.String(ATOM_ALIPHATIC_STR);
else
throw "Wrong aromaticity value";
}
for (auto p : qprops)
{
if (atom.sureValue(p.first, value))
{
writer.Key(p.second);
writer.Uint(value);
}
}
// 2do add hirality
//*/
}
writer.EndObject();
}
Expand Down
9 changes: 7 additions & 2 deletions core/indigo-core/molecule/src/query_molecule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1868,7 +1868,8 @@ bool QueryMolecule::isKnownAttr(QueryMolecule::Atom& qa)
return (qa.type == QueryMolecule::ATOM_CHARGE || qa.type == QueryMolecule::ATOM_ISOTOPE || qa.type == QueryMolecule::ATOM_RADICAL ||
qa.type == QueryMolecule::ATOM_VALENCE || qa.type == QueryMolecule::ATOM_TOTAL_H || qa.type == QueryMolecule::ATOM_SUBSTITUENTS ||
qa.type == QueryMolecule::ATOM_SUBSTITUENTS_AS_DRAWN || qa.type == QueryMolecule::ATOM_RING_BONDS ||
qa.type == QueryMolecule::ATOM_RING_BONDS_AS_DRAWN || qa.type == QueryMolecule::ATOM_UNSATURATION) &&
qa.type == QueryMolecule::ATOM_RING_BONDS_AS_DRAWN || qa.type == QueryMolecule::ATOM_UNSATURATION || qa.type == QueryMolecule::ATOM_AROMATICITY ||
qa.type == QueryMolecule::ATOM_SSSR_RINGS || qa.type == QueryMolecule::ATOM_SMALLEST_RING_SIZE || qa.type == QueryMolecule::ATOM_CONNECTIVITY) &&
qa.value_max == qa.value_min;
}

Expand Down Expand Up @@ -1951,7 +1952,11 @@ QueryMolecule::Atom* QueryMolecule::stripKnownAttrs(QueryMolecule::Atom& qa)

int QueryMolecule::parseQueryAtom(QueryMolecule& qm, int aid, Array<int>& list)
{
QueryMolecule::Atom& qa = qm.getAtom(aid);
return parseQueryAtom(qm.getAtom(aid), list);
}

int QueryMolecule::parseQueryAtom(QueryMolecule::Atom& qa, Array<int>& list)
{
QueryMolecule::Atom* qc = stripKnownAttrs(qa);
if (qa.type == QueryMolecule::OP_NONE)
return QUERY_ATOM_AH;
Expand Down

0 comments on commit 9307464

Please sign in to comment.