From 7eea202e7b20b0318692cc5a4716e3ba9f90cead Mon Sep 17 00:00:00 2001 From: Roman Porozhnetov Date: Tue, 15 Nov 2022 16:08:33 +0100 Subject: [PATCH 1/3] multistep to rxn-smiles --- .../ketcher/multistep_to_rxn_smiles.py.out | 94 +++++++++++++++++++ .../tests/ketcher/multistep_to_rxn_smiles.py | 19 ++++ .../reaction/reaction_json_loader.h | 1 + .../reaction/src/base_reaction.cpp | 2 +- .../reaction/src/reaction_json_loader.cpp | 13 ++- .../reaction/src/rsmiles_saver.cpp | 11 +++ .../reaction/src/rxnfile_saver.cpp | 15 ++- 7 files changed, 148 insertions(+), 7 deletions(-) create mode 100644 api/tests/integration/ref/ketcher/multistep_to_rxn_smiles.py.out create mode 100644 api/tests/integration/tests/ketcher/multistep_to_rxn_smiles.py diff --git a/api/tests/integration/ref/ketcher/multistep_to_rxn_smiles.py.out b/api/tests/integration/ref/ketcher/multistep_to_rxn_smiles.py.out new file mode 100644 index 0000000000..1f3aa9880d --- /dev/null +++ b/api/tests/integration/ref/ketcher/multistep_to_rxn_smiles.py.out @@ -0,0 +1,94 @@ +C1CCC1.C1CC1>>C1CCCCCC1.C1CCCC1.C1C=CC=CC=1.P +$RXN + + -INDIGO- 0100000000 + + 2 4 +$MOL + + -INDIGO-01000000002D + + 4 4 0 0 0 0 0 0 0 0999 V2000 + 2.9822 -4.9975 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.9785 -4.0025 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.9703 -4.9846 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.9678 -4.0025 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 3 4 1 0 0 0 0 +M END +$MOL + + -INDIGO-01000000002D + + 3 3 0 0 0 0 0 0 0 0999 V2000 + 4.6994 -4.9825 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7006 -4.9825 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.2001 -4.1175 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 2 3 1 0 0 0 0 +M END +$MOL + + -INDIGO-01000000002D + + 6 6 0 0 0 0 0 0 0 0999 V2000 + 21.1098 -3.6751 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 22.8402 -3.6746 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 21.9766 -3.1750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 22.8402 -4.6755 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 21.1098 -4.6800 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 21.9788 -5.1750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3 1 2 0 0 0 0 + 4 2 2 0 0 0 0 + 1 5 1 0 0 0 0 + 2 3 1 0 0 0 0 + 5 6 2 0 0 0 0 + 6 4 1 0 0 0 0 +M END +$MOL + + -INDIGO-01000000002D + + 1 0 0 0 0 0 0 0 0 0999 V2000 + 25.1750 -4.3000 0.0000 P 0 0 0 0 0 0 0 0 0 0 0 0 +M END +$MOL + + -INDIGO-01000000002D + + 7 7 0 0 0 0 0 0 0 0999 V2000 + 9.9045 -4.0436 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 10.6884 -3.4260 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 11.6614 -3.6486 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 12.0955 -4.5444 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 9.9100 -5.0508 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 11.6621 -5.4514 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 10.6884 -5.6740 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 2 3 1 0 0 0 0 + 3 4 1 0 0 0 0 + 4 6 1 0 0 0 0 + 1 5 1 0 0 0 0 + 5 7 1 0 0 0 0 + 6 7 1 0 0 0 0 +M END +$MOL + + -INDIGO-01000000002D + + 5 5 0 0 0 0 0 0 0 0999 V2000 + 15.3250 -3.6806 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 16.1340 -4.2684 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 15.8250 -5.2194 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 14.8250 -5.2194 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 14.5160 -4.2684 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 2 3 1 0 0 0 0 + 3 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 5 1 1 0 0 0 0 +M END + diff --git a/api/tests/integration/tests/ketcher/multistep_to_rxn_smiles.py b/api/tests/integration/tests/ketcher/multistep_to_rxn_smiles.py new file mode 100644 index 0000000000..7176b7a8cc --- /dev/null +++ b/api/tests/integration/tests/ketcher/multistep_to_rxn_smiles.py @@ -0,0 +1,19 @@ +import os +import sys + +sys.path.append( + os.path.normpath( + os.path.join(os.path.abspath(__file__), "..", "..", "..", "common") + ) +) +from env_indigo import * +from rendering import * + +if __name__ == "__main__": + indigo = Indigo() + indigo.setOption("molfile-saving-skip-date", True) + rfile = open(joinPathPy("molecules/multistep.ket", __file__)) + reaction = rfile.read() + r = indigo.loadReaction(reaction) + print(r.smiles()) + print(r.rxnfile()) diff --git a/core/indigo-core/reaction/reaction_json_loader.h b/core/indigo-core/reaction/reaction_json_loader.h index 87df4f06d2..bd4cb4c226 100644 --- a/core/indigo-core/reaction/reaction_json_loader.h +++ b/core/indigo-core/reaction/reaction_json_loader.h @@ -68,6 +68,7 @@ namespace indigo bool ignore_no_chiral_flag; const Vec2f PLUS_BBOX_SHIFT = {0.9, 0.9}; + const Vec2f MIN_MOL_SIZE = {0.5, 0.5}; const Vec2f ARROW_BBOX_SHIFT = {0.0, 0.9}; private: diff --git a/core/indigo-core/reaction/src/base_reaction.cpp b/core/indigo-core/reaction/src/base_reaction.cpp index e133105549..aaa1b6b740 100644 --- a/core/indigo-core/reaction/src/base_reaction.cpp +++ b/core/indigo-core/reaction/src/base_reaction.cpp @@ -73,7 +73,7 @@ SideIter SideAuto::begin() idx = _owner.catalystBegin(); break; case BaseReaction::INTERMEDIATE: - idx = _owner.catalystBegin(); + idx = _owner.intermediateBegin(); break; case BaseReaction::UNDEFINED: idx = _owner.catalystBegin(); diff --git a/core/indigo-core/reaction/src/reaction_json_loader.cpp b/core/indigo-core/reaction/src/reaction_json_loader.cpp index e585d4058a..51a270163a 100644 --- a/core/indigo-core/reaction/src/reaction_json_loader.cpp +++ b/core/indigo-core/reaction/src/reaction_json_loader.cpp @@ -242,6 +242,15 @@ void ReactionJsonLoader::parseMultipleArrowReaction(BaseReaction& rxn) mol.makeSubmolecule(*_pmol, filter, 0, 0); Rect2f bbox; mol.getBoundingBox(bbox); + + if (bbox.width() < MIN_MOL_SIZE.x || bbox.height() < MIN_MOL_SIZE.y) + { + Vec2f center(bbox.center()); + const auto hw = std::max(bbox.width() / 2, MIN_MOL_SIZE.x / 2); + const auto hh = std::max(bbox.height() / 2, MIN_MOL_SIZE.y / 2); + bbox.copy(Rect2f(Vec2f(center.x - hw, center.y - hh), Vec2f(center.x + hw, center.y + hh))); + } + mol_tops.emplace_back(bbox.top(), i); mol_bottoms.emplace_back(bbox.bottom(), i); mol_lefts.emplace_back(bbox.left(), i); @@ -400,7 +409,7 @@ void ReactionJsonLoader::parseMultipleArrowReaction(BaseReaction& rxn) for (int index_cs = 0; index_cs < _component_summ_blocks.size(); ++index_cs) { auto& csb = _component_summ_blocks[index_cs]; - if (csb.bbox.rayIntersectsRect(arr_begin, arr_end)) + if (csb.bbox.rayIntersectsRect(arr_end, arr_begin)) { float dist = csb.bbox.pointDistance(arr_end); if (min_dist_prod < 0 || dist < min_dist_prod) @@ -409,7 +418,7 @@ void ReactionJsonLoader::parseMultipleArrowReaction(BaseReaction& rxn) idx_cs_min_prod = index_cs; } } - else if (csb.bbox.rayIntersectsRect(arr_end, arr_begin)) + else if (csb.bbox.rayIntersectsRect(arr_begin, arr_end)) { float dist = csb.bbox.pointDistance(arr_begin); if (min_dist_reac < 0 || dist < min_dist_reac) diff --git a/core/indigo-core/reaction/src/rsmiles_saver.cpp b/core/indigo-core/reaction/src/rsmiles_saver.cpp index 45169a3855..fe40a26fca 100644 --- a/core/indigo-core/reaction/src/rsmiles_saver.cpp +++ b/core/indigo-core/reaction/src/rsmiles_saver.cpp @@ -126,6 +126,17 @@ void RSmilesSaver::_saveReaction() _output.writeString(">"); dot = false; + + for (auto i : _brxn->intermediates) + { + if (dot) + _output.writeChar('.'); + else + dot = true; + + _writeMolecule(i); + } + for (auto i : _brxn->products) { if (dot) diff --git a/core/indigo-core/reaction/src/rxnfile_saver.cpp b/core/indigo-core/reaction/src/rxnfile_saver.cpp index 25851edac5..076200f823 100644 --- a/core/indigo-core/reaction/src/rxnfile_saver.cpp +++ b/core/indigo-core/reaction/src/rxnfile_saver.cpp @@ -115,6 +115,12 @@ void RxnfileSaver::_saveReaction() _writeMol(molfileSaver, i); } + for (int i = _brxn->intermediateBegin(); i < _brxn->intermediateEnd(); i = _brxn->intermediateNext(i)) + { + _writeMolHeader(); + _writeMol(molfileSaver, i); + } + _writeProductsFooter(); if (_brxn->catalystCount() > 0) @@ -159,16 +165,17 @@ void RxnfileSaver::_writeRxnHeader(BaseReaction& reaction) if (_v2000) { if (reaction.catalystCount() > 0) - _output.printf("%3d%3d%3d\n", reaction.reactantsCount(), reaction.productsCount(), reaction.catalystCount()); + _output.printf("%3d%3d%3d\n", reaction.reactantsCount(), reaction.productsCount() + reaction.intermediateCount(), reaction.catalystCount()); else - _output.printf("%3d%3d\n", reaction.reactantsCount(), reaction.productsCount()); + _output.printf("%3d%3d\n", reaction.reactantsCount(), reaction.productsCount() + reaction.intermediateCount()); } else { if (reaction.catalystCount() > 0) - _output.printf("M V30 COUNTS %d %d %d\n", reaction.reactantsCount(), reaction.productsCount(), reaction.catalystCount()); + _output.printf("M V30 COUNTS %d %d %d\n", reaction.reactantsCount(), reaction.productsCount() + reaction.intermediateCount(), + reaction.catalystCount()); else - _output.printf("M V30 COUNTS %d %d\n", reaction.reactantsCount(), reaction.productsCount()); + _output.printf("M V30 COUNTS %d %d\n", reaction.reactantsCount(), reaction.productsCount() + reaction.intermediateCount()); } } From 74cd75f283fd641b16caf7e3aa92503bbd5430d6 Mon Sep 17 00:00:00 2001 From: Roman Porozhnetov Date: Tue, 15 Nov 2022 16:25:04 +0100 Subject: [PATCH 2/3] reference to temp --- core/indigo-core/reaction/src/reaction_json_loader.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/indigo-core/reaction/src/reaction_json_loader.cpp b/core/indigo-core/reaction/src/reaction_json_loader.cpp index 51a270163a..c0bdde8032 100644 --- a/core/indigo-core/reaction/src/reaction_json_loader.cpp +++ b/core/indigo-core/reaction/src/reaction_json_loader.cpp @@ -248,7 +248,8 @@ void ReactionJsonLoader::parseMultipleArrowReaction(BaseReaction& rxn) Vec2f center(bbox.center()); const auto hw = std::max(bbox.width() / 2, MIN_MOL_SIZE.x / 2); const auto hh = std::max(bbox.height() / 2, MIN_MOL_SIZE.y / 2); - bbox.copy(Rect2f(Vec2f(center.x - hw, center.y - hh), Vec2f(center.x + hw, center.y + hh))); + Rect2f new_bbox(Vec2f(center.x - hw, center.y - hh), Vec2f(center.x + hw, center.y + hh)); + bbox.copy(new_bbox); } mol_tops.emplace_back(bbox.top(), i); From f1849855d0e57a7421f8e5e61b800cfaf30ca7c9 Mon Sep 17 00:00:00 2001 From: Roman Porozhnetov Date: Tue, 15 Nov 2022 16:57:15 +0100 Subject: [PATCH 3/3] missing multistep.ket --- .../tests/ketcher/molecules/multistep.ket | 510 ++++++++++++++++++ 1 file changed, 510 insertions(+) create mode 100644 api/tests/integration/tests/ketcher/molecules/multistep.ket diff --git a/api/tests/integration/tests/ketcher/molecules/multistep.ket b/api/tests/integration/tests/ketcher/molecules/multistep.ket new file mode 100644 index 0000000000..bb45a0d9be --- /dev/null +++ b/api/tests/integration/tests/ketcher/molecules/multistep.ket @@ -0,0 +1,510 @@ +{ + "root": { + "nodes": [ + { + "$ref": "mol0" + }, + { + "$ref": "mol1" + }, + { + "$ref": "mol2" + }, + { + "$ref": "mol3" + }, + { + "$ref": "mol4" + }, + { + "$ref": "mol5" + }, + { + "type": "arrow", + "data": { + "mode": "open-angle", + "pos": [ + { + "x": 6.4750000000000005, + "y": -4.6000000000000005, + "z": 0 + }, + { + "x": 9.225, + "y": -4.575, + "z": 0 + } + ] + } + }, + { + "type": "arrow", + "data": { + "mode": "open-angle", + "pos": [ + { + "x": 17.3, + "y": -4.375, + "z": 0 + }, + { + "x": 20.75, + "y": -4.4, + "z": 0 + } + ] + } + }, + { + "type": "plus", + "location": [ + 3.8000000000000003, + -4.4750000000000005, + 0 + ], + "prop": {} + }, + { + "type": "plus", + "location": [ + 13.15, + -4.675, + 0 + ], + "prop": {} + }, + { + "type": "plus", + "location": [ + 24, + -4.3, + 0 + ], + "prop": {} + } + ] + }, + "mol0": { + "type": "molecule", + "atoms": [ + { + "label": "C", + "location": [ + 2.9822074547389787, + -4.997548743464718, + 0 + ] + }, + { + "label": "C", + "location": [ + 2.97850411466491, + -4.002451256535281, + 0 + ] + }, + { + "label": "C", + "location": [ + 1.9702948020678241, + -4.984637098341615, + 0 + ] + }, + { + "label": "C", + "location": [ + 1.9677925452610214, + -4.002451256535281, + 0 + ] + } + ], + "bonds": [ + { + "type": 1, + "atoms": [ + 0, + 1 + ] + }, + { + "type": 1, + "atoms": [ + 0, + 2 + ] + }, + { + "type": 1, + "atoms": [ + 1, + 3 + ] + }, + { + "type": 1, + "atoms": [ + 2, + 3 + ] + } + ] + }, + "mol1": { + "type": "molecule", + "atoms": [ + { + "label": "C", + "location": [ + 4.69937421436393, + -4.982470415521405, + 0 + ] + }, + { + "label": "C", + "location": [ + 5.7006257856360705, + -4.982470415521405, + 0 + ] + }, + { + "label": "C", + "location": [ + 5.200050188048685, + -4.117529584478595, + 0 + ] + } + ], + "bonds": [ + { + "type": 1, + "atoms": [ + 0, + 1 + ] + }, + { + "type": 1, + "atoms": [ + 0, + 2 + ] + }, + { + "type": 1, + "atoms": [ + 1, + 2 + ] + } + ] + }, + "mol2": { + "type": "molecule", + "atoms": [ + { + "label": "C", + "location": [ + 9.904476379955526, + -4.043603270895515, + 0 + ] + }, + { + "label": "C", + "location": [ + 10.688409765774512, + -3.4260316269757665, + 0 + ] + }, + { + "label": "C", + "location": [ + 11.661440664360363, + -3.648581771768125, + 0 + ] + }, + { + "label": "C", + "location": [ + 12.095523620044471, + -4.544391175468779, + 0 + ] + }, + { + "label": "C", + "location": [ + 9.909985046905831, + -5.050787904573263, + 0 + ] + }, + { + "label": "C", + "location": [ + 11.662141767426768, + -5.451418228231875, + 0 + ] + }, + { + "label": "C", + "location": [ + 10.688409765774512, + -5.673968373024233, + 0 + ] + } + ], + "bonds": [ + { + "type": 1, + "atoms": [ + 0, + 1 + ] + }, + { + "type": 1, + "atoms": [ + 1, + 2 + ] + }, + { + "type": 1, + "atoms": [ + 2, + 3 + ] + }, + { + "type": 1, + "atoms": [ + 3, + 5 + ] + }, + { + "type": 1, + "atoms": [ + 0, + 4 + ] + }, + { + "type": 1, + "atoms": [ + 4, + 6 + ] + }, + { + "type": 1, + "atoms": [ + 5, + 6 + ] + } + ] + }, + "mol3": { + "type": "molecule", + "atoms": [ + { + "label": "C", + "location": [ + 15.325000000000001, + -3.6805595485514346, + 0 + ] + }, + { + "label": "C", + "location": [ + 16.13398996064967, + -4.268352254200232, + 0 + ] + }, + { + "label": "C", + "location": [ + 15.824993795209934, + -5.219440451448566, + 0 + ] + }, + { + "label": "C", + "location": [ + 14.825006204790068, + -5.219440451448566, + 0 + ] + }, + { + "label": "C", + "location": [ + 14.516010039350329, + -4.268352254200232, + 0 + ] + } + ], + "bonds": [ + { + "type": 1, + "atoms": [ + 0, + 1 + ] + }, + { + "type": 1, + "atoms": [ + 1, + 2 + ] + }, + { + "type": 1, + "atoms": [ + 2, + 3 + ] + }, + { + "type": 1, + "atoms": [ + 3, + 4 + ] + }, + { + "type": 1, + "atoms": [ + 4, + 0 + ] + } + ] + }, + "mol4": { + "type": "molecule", + "atoms": [ + { + "label": "C", + "location": [ + 21.109849152128568, + -3.675074417174607, + 0 + ] + }, + { + "label": "C", + "location": [ + 22.840150847871435, + -3.6745892291772027, + 0 + ] + }, + { + "label": "C", + "location": [ + 21.97663750949124, + -3.174966888850187, + 0 + ] + }, + { + "label": "C", + "location": [ + 22.840150847871435, + -4.6755320678221475, + 0 + ] + }, + { + "label": "C", + "location": [ + 21.109849152128568, + -4.680020056798137, + 0 + ] + }, + { + "label": "C", + "location": [ + 21.978820855479558, + -5.175033111149812, + 0 + ] + } + ], + "bonds": [ + { + "type": 2, + "atoms": [ + 2, + 0 + ] + }, + { + "type": 2, + "atoms": [ + 3, + 1 + ] + }, + { + "type": 1, + "atoms": [ + 0, + 4 + ] + }, + { + "type": 1, + "atoms": [ + 1, + 2 + ] + }, + { + "type": 2, + "atoms": [ + 4, + 5 + ] + }, + { + "type": 1, + "atoms": [ + 5, + 3 + ] + } + ] + }, + "mol5": { + "type": "molecule", + "atoms": [ + { + "label": "P", + "location": [ + 25.175, + -4.3, + 0 + ] + } + ] + } +} \ No newline at end of file