diff --git a/.ci/version.txt b/.ci/version.txt index 994b00745a..0a20639219 100644 --- a/.ci/version.txt +++ b/.ci/version.txt @@ -1,5 +1,5 @@ 1.15.0 dev -1 +2 -c063813402a30d41ab51d39f29ee9df32ca25a1bec8274a41a9f6474b9bc696d \ No newline at end of file +284f91159ae886214f74b856d19f5cfed089bb90fc85c038d90a40da588bf13a \ No newline at end of file diff --git a/api/dotnet/src/Indigo.Net.csproj b/api/dotnet/src/Indigo.Net.csproj index 9804916830..4f2136bf26 100644 --- a/api/dotnet/src/Indigo.Net.csproj +++ b/api/dotnet/src/Indigo.Net.csproj @@ -2,7 +2,7 @@ netstandard2.0 - 1.15.0-dev.1 + 1.15.0-dev.2 EPAM Systems Life Science Department EPAM Systems Universal cheminformatics toolkit diff --git a/api/http/requirements.txt b/api/http/requirements.txt index 44e58b7de2..9bc53a51ab 100644 --- a/api/http/requirements.txt +++ b/api/http/requirements.txt @@ -1,7 +1,7 @@ anyio==3.7.0 asgiref==3.7.1 click==8.1.3 -epam.indigo==1.15.0.dev1 +epam.indigo==1.15.0.dev2 fastapi==0.95.2 h11==0.14.0 idna==3.4 diff --git a/api/http/setup.py b/api/http/setup.py index 38afea3d24..70b809942e 100644 --- a/api/http/setup.py +++ b/api/http/setup.py @@ -19,7 +19,7 @@ setup_kwargs = { "name": "indigo-service", - "version": "1.15.0.dev1", + "version": "1.15.0.dev2", "description": "", "long_description": None, "author": "Ruslan Khyurri", diff --git a/api/indigo-version.cmake b/api/indigo-version.cmake index 0f79b465be..d555900697 100644 --- a/api/indigo-version.cmake +++ b/api/indigo-version.cmake @@ -1,4 +1,4 @@ -set(INDIGO_DEFAULT_VERSION "1.15.0-dev.1") +set(INDIGO_DEFAULT_VERSION "1.15.0-dev.2") set(INDIGO_MAX_REVISION 1000) find_package(Git) if(GIT_EXECUTABLE) diff --git a/api/java/pom.xml b/api/java/pom.xml index b7e2e67c6a..2d24f91e5b 100644 --- a/api/java/pom.xml +++ b/api/java/pom.xml @@ -17,7 +17,7 @@ UTF-8 1.8 ${maven.compiler.source} - 1.15.0-dev.1 + 1.15.0-dev.2 diff --git a/api/python/indigo/__init__.py b/api/python/indigo/__init__.py index 1eb5723514..affa1eb677 100644 --- a/api/python/indigo/__init__.py +++ b/api/python/indigo/__init__.py @@ -3,4 +3,4 @@ from .indigo.indigo_exception import IndigoException # noqa from .indigo.indigo_object import IndigoObject # noqa -__version__ = "1.15.0.dev1" +__version__ = "1.15.0.dev2" diff --git a/api/python/setup.py b/api/python/setup.py index adbb7f0776..a0b124cd82 100644 --- a/api/python/setup.py +++ b/api/python/setup.py @@ -98,7 +98,7 @@ setup( name="epam.indigo", - version="1.15.0.dev1", + version="1.15.0.dev2", description="Indigo universal cheminformatics toolkit", author="EPAM Systems Life Science Department", author_email="lifescience.opensource@epam.com", diff --git a/api/r/DESCRIPTION b/api/r/DESCRIPTION index 508f53e59d..6d33a8a6bc 100644 --- a/api/r/DESCRIPTION +++ b/api/r/DESCRIPTION @@ -1,5 +1,5 @@ Package: rindigo -Version: 1.15.0-dev.1 +Version: 1.15.0-dev.2 Date: 2020-12-10 Title: R Package for Indigo Toolkit Authors@R: c(person(given = "Mikhail", family = "Kviatkovskii", role = c("cre"), diff --git a/api/tests/integration/ref/formats/ket_to_mol.py.out b/api/tests/integration/ref/formats/ket_to_mol.py.out index d35f29db50..c52c3e95c2 100644 --- a/api/tests/integration/ref/formats/ket_to_mol.py.out +++ b/api/tests/integration/ref/formats/ket_to_mol.py.out @@ -1,4 +1,10 @@ *** KET to MOL *** +chem.ket:SUCCEED +cysteine.ket:SUCCEED +dala.ket:SUCCEED +dcysteine.ket:SUCCEED +dthymine.ket:SUCCEED suplabel.ket:SUCCEED +thymine.ket:SUCCEED empty_apid.ket:SUCCEED ket-reaction-arrow.ket:SUCCEED diff --git a/api/tests/integration/ref/formats/mol_to_ket.py.out b/api/tests/integration/ref/formats/mol_to_ket.py.out index 69f4d6eb4a..766ba99f34 100644 --- a/api/tests/integration/ref/formats/mol_to_ket.py.out +++ b/api/tests/integration/ref/formats/mol_to_ket.py.out @@ -3,5 +3,10 @@ 1046-imp_hydrogen.ket:SUCCEED SgroupDifferent.ket:SUCCEED atropisomer.ket:SUCCEED +chem.ket:SUCCEED +cysteine.ket:SUCCEED +dcysteine.ket:SUCCEED +dthymine.ket:SUCCEED non_atrop.ket:SUCCEED suplabel.ket:SUCCEED +thymine.ket:SUCCEED diff --git a/api/tests/integration/ref/formats/smarts.py.out b/api/tests/integration/ref/formats/smarts.py.out index 7db26c6793..437f7ecbc4 100644 --- a/api/tests/integration/ref/formats/smarts.py.out +++ b/api/tests/integration/ref/formats/smarts.py.out @@ -27,3 +27,11 @@ CC[C+5]CCCCC [O;H] is ok. smarts_in==smarts_out [!O;H] is ok. smarts_in==smarts_out ([#6]1-[#6]-[#6]-1.[#6]) is ok. smarts_in==smarts_out +[#9]/[#6]=[#6]/[#6]=[#6]/[#6] is ok. smarts_in==smarts_out +[#9]\[#6]=[#6]\[#6]=[#6]\[#6] is ok. smarts_in==smarts_out +[#9]/[#6]=[#6]/[#6]=[#6]/[#6] is ok. smarts_in==smarts_out +[#9]/[#6]=[#6]/[#6]=[#6]/[#6] is ok. json_in==json_out +[#9]/[#6]=[#6]/[#6]=[#6]/[#6] is ok. expected string found in json +[#9]\[#6]=[#6]/[#6]=[#6]\[#6] is ok. smarts_in==smarts_out +[#9]\[#6]=[#6]/[#6]=[#6]\[#6] is ok. json_in==json_out +[#9]\[#6]=[#6]/[#6]=[#6]\[#6] is ok. expected string found in json diff --git a/api/tests/integration/tests/formats/ket_to_mol.py b/api/tests/integration/tests/formats/ket_to_mol.py index ea2bc685de..bf2258c78d 100644 --- a/api/tests/integration/tests/formats/ket_to_mol.py +++ b/api/tests/integration/tests/formats/ket_to_mol.py @@ -24,11 +24,22 @@ def find_diff(a, b): ref_path = joinPathPy("ref/", __file__) root_rea = joinPathPy("reactions/", __file__) -files = ["suplabel"] +files = [ + "suplabel", + "cysteine", + "dcysteine", + "thymine", + "dthymine", + "dala", + "chem", +] files.sort() for filename in files: mol = indigo.loadMoleculeFromFile(os.path.join(root, filename + ".ket")) + # with open(os.path.join(ref_path, filename) + ".mol", "w") as file: + # file.write(mol.molfile()) + with open(os.path.join(ref_path, filename) + ".mol", "r") as file: ket_ref = file.read() ket = mol.molfile() diff --git a/api/tests/integration/tests/formats/mol_to_ket.py b/api/tests/integration/tests/formats/mol_to_ket.py index 93a1f70a14..7e7f4a16d8 100644 --- a/api/tests/integration/tests/formats/mol_to_ket.py +++ b/api/tests/integration/tests/formats/mol_to_ket.py @@ -30,6 +30,11 @@ def find_diff(a, b): "suplabel", "atropisomer", "non_atrop", + "cysteine", + "dcysteine", + "thymine", + "dthymine", + "chem", ] files.sort() diff --git a/api/tests/integration/tests/formats/molecules/chem.ket b/api/tests/integration/tests/formats/molecules/chem.ket new file mode 100644 index 0000000000..8b9923cc5b --- /dev/null +++ b/api/tests/integration/tests/formats/molecules/chem.ket @@ -0,0 +1,183 @@ +{ + "root": { + "nodes": [], + "templates": [ + { + "$ref": "monomerTemplate-cch_3" + } + ] + }, + "monomerTemplate-cch_3": { + "type": "monomerTemplate", + "id": "cch_3", + "class": "Chem", + "classHELM": "CHEM", + "alias": "cch", + "attachmentPoints": [ + { + "type": "right", + "label": "R2", + "attachmentAtom": 8, + "leavingGroup": { + "atoms": [ + 1 + ] + } + }, + { + "type": "side", + "label": "R3", + "attachmentAtom": 6, + "leavingGroup": { + "atoms": [ + 2 + ] + } + }, + { + "type": "side", + "label": "R5", + "attachmentAtom": 3, + "leavingGroup": { + "atoms": [ + 0 + ] + } + } + ], + "atoms": [ + { + "label": "H", + "location": [ + 9.201199531555176, + -7.158699989318848, + 0.0 + ] + }, + { + "label": "H", + "location": [ + 8.374699592590332, + -7.985400199890137, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 10.02810001373291, + -7.985400199890137, + 0.0 + ] + }, + { + "label": "S", + "location": [ + 9.718199729919434, + -6.737199783325195, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 9.194899559020996, + -7.6427001953125, + 0.0 + ], + "stereoLabel": "abs" + }, + { + "label": "O", + "location": [ + 9.698399543762207, + -8.580300331115723, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 9.698399543762207, + -7.97629976272583, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 9.194899559020996, + -7.03879976272583, + 0.0 + ] + }, + { + "label": "N", + "location": [ + 8.704099655151368, + -7.994699954986572, + 0.0 + ] + } + ], + "bonds": [ + { + "type": 1, + "atoms": [ + 3, + 0 + ] + }, + { + "type": 1, + "atoms": [ + 6, + 2 + ] + }, + { + "type": 1, + "atoms": [ + 8, + 1 + ] + }, + { + "type": 2, + "atoms": [ + 6, + 5 + ] + }, + { + "type": 1, + "atoms": [ + 4, + 7 + ], + "stereo": 1 + }, + { + "type": 1, + "atoms": [ + 7, + 3 + ] + }, + { + "type": 1, + "atoms": [ + 4, + 6 + ] + }, + { + "type": 1, + "atoms": [ + 8, + 4 + ] + } + ] + } +} \ No newline at end of file diff --git a/api/tests/integration/tests/formats/molecules/chem.mol b/api/tests/integration/tests/formats/molecules/chem.mol new file mode 100644 index 0000000000..710fb22cf7 --- /dev/null +++ b/api/tests/integration/tests/formats/molecules/chem.mol @@ -0,0 +1,47 @@ + + -INDIGO-09062309442D + + 0 0 0 0 0 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 0 0 0 0 0 +M V30 END CTAB +M V30 BEGIN TEMPLATE +M V30 TEMPLATE 3 CHEM/cch/cch +M V30 BEGIN CTAB +M V30 COUNTS 9 8 4 0 1 +M V30 BEGIN ATOM +M V30 1 H 9.2012 -7.1587 0 0 +M V30 2 H 8.3747 -7.9854 0 0 +M V30 3 O 10.0281 -7.9854 0 0 +M V30 4 S 9.7182 -6.7372 0 0 +M V30 5 C 9.1949 -7.6427 0 0 CFG=2 +M V30 6 O 9.6984 -8.5803 0 0 +M V30 7 C 9.6984 -7.9763 0 0 +M V30 8 C 9.1949 -7.0388 0 0 +M V30 9 N 8.7041 -7.9947 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 4 1 +M V30 2 1 7 3 +M V30 3 1 9 2 +M V30 4 2 7 6 +M V30 5 1 5 8 CFG=1 +M V30 6 1 8 4 +M V30 7 1 5 7 +M V30 8 1 9 5 +M V30 END BOND +M V30 BEGIN SGROUP +M V30 1 SUP 1 ATOMS=(1 2) XBONDS=(1 3) LABEL=H CSTATE=(4 3 0.8265 0 0) - +M V30 CLASS=LGRP +M V30 2 SUP 2 ATOMS=(1 3) XBONDS=(1 2) LABEL=OH CSTATE=(4 2 -0.825 0 0) - +M V30 CLASS=LGRP +M V30 3 SUP 3 ATOMS=(1 1) XBONDS=(1 1) LABEL=H CSTATE=(4 1 0 -0.8267 0) - +M V30 CLASS=LGRP +M V30 4 SUP 4 ATOMS=(6 4 5 6 7 8 9) XBONDS=(3 1 2 3) LABEL=cch CSTATE=(4 3 - +M V30 -0.8265 0 0) CSTATE=(4 2 0.825 0 0) CSTATE=(4 1 0 0.8267 0) CLASS=AA - +M V30 SAP=(3 9 2 Br) SAP=(3 7 3 Cx) SAP=(3 4 1 Ex) +M V30 END SGROUP +M V30 END CTAB +M V30 END TEMPLATE +M END + diff --git a/api/tests/integration/tests/formats/molecules/cysteine.ket b/api/tests/integration/tests/formats/molecules/cysteine.ket new file mode 100644 index 0000000000..e8a46d44c1 --- /dev/null +++ b/api/tests/integration/tests/formats/molecules/cysteine.ket @@ -0,0 +1,177 @@ +{ + "root": { + "nodes": [], + "templates": [ + { + "$ref": "monomerTemplate-cys_3" + } + ] + }, + "monomerTemplate-cys_3": { + "type": "monomerTemplate", + "id": "cys_3", + "class": "AminoAcid", + "classHELM": "PEPTIDE", + "alias": "C", + "attachmentPoints": [ + { + "attachmentAtom": 8, + "leavingGroup": { + "atoms": [ + 1 + ] + } + }, + { + "attachmentAtom": 6, + "leavingGroup": { + "atoms": [ + 2 + ] + } + }, + { + "attachmentAtom": 3, + "leavingGroup": { + "atoms": [ + 0 + ] + } + } + ], + "atoms": [ + { + "label": "H", + "location": [ + 9.201199531555176, + -7.158699989318848, + 0.0 + ] + }, + { + "label": "H", + "location": [ + 8.374699592590332, + -7.985400199890137, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 10.02810001373291, + -7.985400199890137, + 0.0 + ] + }, + { + "label": "S", + "location": [ + 9.718199729919434, + -6.737199783325195, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 9.194899559020996, + -7.6427001953125, + 0.0 + ], + "stereoLabel": "abs" + }, + { + "label": "O", + "location": [ + 9.698399543762207, + -8.580300331115723, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 9.698399543762207, + -7.97629976272583, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 9.194899559020996, + -7.03879976272583, + 0.0 + ] + }, + { + "label": "N", + "location": [ + 8.704099655151368, + -7.994699954986572, + 0.0 + ] + } + ], + "bonds": [ + { + "type": 1, + "atoms": [ + 3, + 0 + ] + }, + { + "type": 1, + "atoms": [ + 6, + 2 + ] + }, + { + "type": 1, + "atoms": [ + 8, + 1 + ] + }, + { + "type": 2, + "atoms": [ + 6, + 5 + ] + }, + { + "type": 1, + "atoms": [ + 4, + 7 + ], + "stereo": 1 + }, + { + "type": 1, + "atoms": [ + 7, + 3 + ] + }, + { + "type": 1, + "atoms": [ + 4, + 6 + ] + }, + { + "type": 1, + "atoms": [ + 8, + 4 + ] + } + ] + } +} \ No newline at end of file diff --git a/api/tests/integration/tests/formats/molecules/cysteine.mol b/api/tests/integration/tests/formats/molecules/cysteine.mol new file mode 100644 index 0000000000..3974d8aa7b --- /dev/null +++ b/api/tests/integration/tests/formats/molecules/cysteine.mol @@ -0,0 +1,47 @@ + + -INDIGO-09062309442D + + 0 0 0 0 0 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 0 0 0 0 0 +M V30 END CTAB +M V30 BEGIN TEMPLATE +M V30 TEMPLATE 3 AA/cys/C +M V30 BEGIN CTAB +M V30 COUNTS 9 8 4 0 1 +M V30 BEGIN ATOM +M V30 1 H 9.2012 -7.1587 0 0 +M V30 2 H 8.3747 -7.9854 0 0 +M V30 3 O 10.0281 -7.9854 0 0 +M V30 4 S 9.7182 -6.7372 0 0 +M V30 5 C 9.1949 -7.6427 0 0 CFG=2 +M V30 6 O 9.6984 -8.5803 0 0 +M V30 7 C 9.6984 -7.9763 0 0 +M V30 8 C 9.1949 -7.0388 0 0 +M V30 9 N 8.7041 -7.9947 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 4 1 +M V30 2 1 7 3 +M V30 3 1 9 2 +M V30 4 2 7 6 +M V30 5 1 5 8 CFG=1 +M V30 6 1 8 4 +M V30 7 1 5 7 +M V30 8 1 9 5 +M V30 END BOND +M V30 BEGIN SGROUP +M V30 1 SUP 1 ATOMS=(1 2) XBONDS=(1 3) LABEL=H CSTATE=(4 3 0.8265 0 0) - +M V30 CLASS=LGRP +M V30 2 SUP 2 ATOMS=(1 3) XBONDS=(1 2) LABEL=OH CSTATE=(4 2 -0.825 0 0) - +M V30 CLASS=LGRP +M V30 3 SUP 3 ATOMS=(1 1) XBONDS=(1 1) LABEL=H CSTATE=(4 1 0 -0.8267 0) - +M V30 CLASS=LGRP +M V30 4 SUP 4 ATOMS=(6 4 5 6 7 8 9) XBONDS=(3 1 2 3) LABEL=Cys CSTATE=(4 3 - +M V30 -0.8265 0 0) CSTATE=(4 2 0.825 0 0) CSTATE=(4 1 0 0.8267 0) CLASS=AA - +M V30 SAP=(3 9 2 Al) SAP=(3 7 3 Br) SAP=(3 4 1 Cx) +M V30 END SGROUP +M V30 END CTAB +M V30 END TEMPLATE +M END + diff --git a/api/tests/integration/tests/formats/molecules/dala.ket b/api/tests/integration/tests/formats/molecules/dala.ket new file mode 100644 index 0000000000..11c52a388b --- /dev/null +++ b/api/tests/integration/tests/formats/molecules/dala.ket @@ -0,0 +1,141 @@ +{ + "root": { + "nodes": [], + "templates": [ + { + "$ref": "monomerTemplate-ala_23" + } + ] + }, + "monomerTemplate-ala_23": { + "type": "monomerTemplate", + "id": "ala_23", + "class": "D-AminoAcid", + "classHELM": "PEPTIDE", + "alias": "da", + "naturalAnalog": "Ala", + "naturalAnalogShort": "A", + "attachmentPoints": [ + { + "attachmentAtom": 2, + "leavingGroup": { + "atoms": [ + 1 + ] + } + }, + { + "attachmentAtom": 4, + "leavingGroup": { + "atoms": [ + 0 + ] + } + } + ], + "atoms": [ + { + "label": "O", + "location": [ + 6.6265997886657719, + -2.066200017929077, + 0.0 + ] + }, + { + "label": "H", + "location": [ + 5.0015997886657719, + -2.087599992752075, + 0.0 + ] + }, + { + "label": "N", + "location": [ + 5.135799884796143, + -2.078399896621704, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 5.78439998626709, + -1.5982999801635743, + 0.0 + ], + "stereoLabel": "abs" + }, + { + "label": "C", + "location": [ + 6.475299835205078, + -2.0652999877929689, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 6.475299835205078, + -2.897700071334839, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 5.78439998626709, + -0.7662000060081482, + 0.0 + ] + } + ], + "bonds": [ + { + "type": 1, + "atoms": [ + 2, + 3 + ] + }, + { + "type": 1, + "atoms": [ + 3, + 4 + ] + }, + { + "type": 2, + "atoms": [ + 4, + 5 + ] + }, + { + "type": 1, + "atoms": [ + 3, + 6 + ], + "stereo": 6 + }, + { + "type": 1, + "atoms": [ + 2, + 1 + ] + }, + { + "type": 1, + "atoms": [ + 4, + 0 + ] + } + ] + } +} \ No newline at end of file diff --git a/api/tests/integration/tests/formats/molecules/dala.mol b/api/tests/integration/tests/formats/molecules/dala.mol new file mode 100644 index 0000000000..db30974756 --- /dev/null +++ b/api/tests/integration/tests/formats/molecules/dala.mol @@ -0,0 +1,43 @@ + + ACCLDraw09281611442D + + 0 0 0 0 0 999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 0 0 0 0 0 +M V30 END CTAB +M V30 BEGIN TEMPLATE +M V30 TEMPLATE 23 dAA/ala/a/ NATREPLACE=AA/A +M V30 BEGIN CTAB +M V30 COUNTS 7 6 3 0 1 +M V30 BEGIN ATOM +M V30 1 O 6.6266 -2.0662 0 0 +M V30 2 H 5.0016 -2.0876 0 0 +M V30 3 N 5.1358 -2.0784 0 0 CFG=3 +M V30 4 C 5.7844 -1.5983 0 0 CFG=1 +M V30 5 C 6.4753 -2.0653 0 0 +M V30 6 O 6.4753 -2.8977 0 0 +M V30 7 C 5.7844 -0.7662 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 3 4 +M V30 2 1 4 5 +M V30 3 2 5 6 +M V30 4 1 4 7 CFG=3 +M V30 5 1 3 2 +M V30 6 1 5 1 +M V30 END BOND +M V30 BEGIN SGROUP +M V30 1 SUP 1 ATOMS=(1 1) XBONDS=(1 6) BRKXYZ=(9 7.02 -2.26 0 7.02 -1.85 0 - +M V30 0 0 0) CSTATE=(4 6 -0.82 -0.01 0) LABEL=OH CLASS=LGRP +M V30 2 SUP 2 ATOMS=(1 2) XBONDS=(1 5) BRKXYZ=(9 4.58 -1.87 0 4.6 -2.28 0 - +M V30 0 0 0) CSTATE=(4 5 0.8 0.02 0) LABEL=H CLASS=LGRP +M V30 3 SUP 3 ATOMS=(5 3 4 5 6 7) XBONDS=(2 5 6) BRKXYZ=(9 3.95 -3.33 0 3.95 - +M V30 -0.38 0 0 0 0) CSTATE=(4 5 -0.8 -0.02 0) CSTATE=(4 6 0.82 0.01 - +M V30 0) LABEL=a CLASS=AA SAP=(3 3 2 Al) SAP=(3 5 1 Br) NATREPLACE=AA/A +M V30 END SGROUP +M V30 BEGIN COLLECTION +M V30 MDLV30/STEABS ATOMS=(1 4) +M V30 END COLLECTION +M V30 END CTAB +M V30 END TEMPLATE +M END diff --git a/api/tests/integration/tests/formats/molecules/dcysteine.ket b/api/tests/integration/tests/formats/molecules/dcysteine.ket new file mode 100644 index 0000000000..34379115a6 --- /dev/null +++ b/api/tests/integration/tests/formats/molecules/dcysteine.ket @@ -0,0 +1,179 @@ +{ + "root": { + "nodes": [], + "templates": [ + { + "$ref": "monomerTemplate-cys_27" + } + ] + }, + "monomerTemplate-cys_27": { + "type": "monomerTemplate", + "id": "cys_27", + "class": "D-AminoAcid", + "classHELM": "PEPTIDE", + "alias": "dc", + "naturalAnalog": "Cys", + "naturalAnalogShort": "C", + "attachmentPoints": [ + { + "attachmentAtom": 8, + "leavingGroup": { + "atoms": [ + 1 + ] + } + }, + { + "attachmentAtom": 6, + "leavingGroup": { + "atoms": [ + 2 + ] + } + }, + { + "attachmentAtom": 3, + "leavingGroup": { + "atoms": [ + 0 + ] + } + } + ], + "atoms": [ + { + "label": "H", + "location": [ + 9.201199531555176, + -7.158699989318848, + 0.0 + ] + }, + { + "label": "H", + "location": [ + 8.374699592590332, + -7.985400199890137, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 10.02810001373291, + -7.985400199890137, + 0.0 + ] + }, + { + "label": "S", + "location": [ + 9.718199729919434, + -6.737199783325195, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 9.194899559020996, + -7.6427001953125, + 0.0 + ], + "stereoLabel": "abs" + }, + { + "label": "O", + "location": [ + 9.698399543762207, + -8.580300331115723, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 9.698399543762207, + -7.97629976272583, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 9.194899559020996, + -7.03879976272583, + 0.0 + ] + }, + { + "label": "N", + "location": [ + 8.704099655151368, + -7.994699954986572, + 0.0 + ] + } + ], + "bonds": [ + { + "type": 1, + "atoms": [ + 3, + 0 + ] + }, + { + "type": 1, + "atoms": [ + 6, + 2 + ] + }, + { + "type": 1, + "atoms": [ + 8, + 1 + ] + }, + { + "type": 2, + "atoms": [ + 6, + 5 + ] + }, + { + "type": 1, + "atoms": [ + 4, + 7 + ], + "stereo": 6 + }, + { + "type": 1, + "atoms": [ + 7, + 3 + ] + }, + { + "type": 1, + "atoms": [ + 4, + 6 + ] + }, + { + "type": 1, + "atoms": [ + 8, + 4 + ] + } + ] + } +} \ No newline at end of file diff --git a/api/tests/integration/tests/formats/molecules/dcysteine.mol b/api/tests/integration/tests/formats/molecules/dcysteine.mol new file mode 100644 index 0000000000..f53c698623 --- /dev/null +++ b/api/tests/integration/tests/formats/molecules/dcysteine.mol @@ -0,0 +1,50 @@ + + -INDIGO-09062309442D + + 0 0 0 0 0 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 0 0 0 0 0 +M V30 END CTAB +M V30 BEGIN TEMPLATE +M V30 TEMPLATE 27 dAA/cys/c/ NATREPLACE=AA/C +M V30 BEGIN CTAB +M V30 COUNTS 9 8 4 0 0 +M V30 BEGIN ATOM +M V30 1 H 9.2012 -7.1587 0 0 +M V30 2 H 8.3747 -7.9854 0 0 +M V30 3 O 10.0281 -7.9854 0 0 +M V30 4 S 9.7182 -6.7372 0 0 +M V30 5 C 9.1949 -7.6427 0 0 CFG=1 +M V30 6 O 9.6984 -8.5803 0 0 +M V30 7 C 9.6984 -7.9763 0 0 +M V30 8 C 9.1949 -7.0388 0 0 +M V30 9 N 8.7041 -7.9947 0 0 CFG=3 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 4 1 +M V30 2 1 7 3 +M V30 3 1 9 2 +M V30 4 2 7 6 +M V30 5 1 5 8 CFG=3 +M V30 6 1 8 4 +M V30 7 1 5 7 +M V30 8 1 9 5 +M V30 END BOND +M V30 BEGIN SGROUP +M V30 1 SUP 1 ATOMS=(1 2) XBONDS=(1 3) CSTATE=(4 3 0.83 -0 0) LABEL=H - +M V30 CLASS=LGRP +M V30 2 SUP 2 ATOMS=(1 3) XBONDS=(1 2) CSTATE=(4 2 -0.83 -0 0) LABEL=OH - +M V30 CLASS=LGRP +M V30 3 SUP 3 ATOMS=(1 1) XBONDS=(1 1) CSTATE=(4 1 0 -0.83 0) LABEL=H - +M V30 CLASS=LGRP +M V30 4 SUP 4 ATOMS=(6 9 5 6 7 8 4) XBONDS=(3 3 2 1) CSTATE=(4 3 -0.83 0 0) - +M V30 CSTATE=(4 2 0.83 0 0) CSTATE=(4 1 -0 0.83 0) LABEL=c SAP=(3 - +M V30 9 2 Al) SAP=(3 7 3 Br) SAP=(3 4 1 Cx) NATREPLACE=AA/C +M V30 END SGROUP +M V30 BEGIN COLLECTION +M V30 MDLV30/STEABS ATOMS=(1 5) +M V30 END COLLECTION +M V30 END CTAB +M V30 END TEMPLATE +M END + diff --git a/api/tests/integration/tests/formats/molecules/dthymine.ket b/api/tests/integration/tests/formats/molecules/dthymine.ket new file mode 100644 index 0000000000..d7cd558006 --- /dev/null +++ b/api/tests/integration/tests/formats/molecules/dthymine.ket @@ -0,0 +1,382 @@ +{ + "root": { + "nodes": [], + "templates": [ + { + "$ref": "monomerTemplate-Thy_45" + } + ] + }, + "monomerTemplate-Thy_45": { + "type": "monomerTemplate", + "id": "Thy_45", + "class": "DNA", + "classHELM": "RNA", + "alias": "T", + "attachmentPoints": [ + { + "attachmentAtom": 9, + "leavingGroup": { + "atoms": [ + 20 + ] + } + }, + { + "attachmentAtom": 0, + "leavingGroup": { + "atoms": [ + 21 + ] + } + } + ], + "atoms": [ + { + "label": "O", + "location": [ + 13.210200309753418, + -15.37720012664795, + 0.0 + ] + }, + { + "label": "N", + "location": [ + 14.565500259399414, + -12.637800216674805, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 13.616000175476075, + -13.013799667358399, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 14.294500350952149, + -13.512299537658692, + 0.0 + ], + "stereoLabel": "abs" + }, + { + "label": "C", + "location": [ + 14.042400360107422, + -14.283599853515625, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 13.210200309753418, + -14.283599853515625, + 0.0 + ], + "stereoLabel": "abs" + }, + { + "label": "C", + "location": [ + 12.947199821472168, + -13.501299858093262, + 0.0 + ], + "stereoLabel": "abs" + }, + { + "label": "C", + "location": [ + 12.16569995880127, + -13.255499839782715, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 11.916500091552735, + -12.463500022888184, + 0.0 + ] + }, + { + "label": "P", + "location": [ + 10.941300392150879, + -12.113499641418457, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 10.941300392150879, + -11.28849983215332, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 10.941300392150879, + -12.93850040435791, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 15.402700424194336, + -12.37279987335205, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 13.824299812316895, + -11.970499992370606, + 0.0 + ] + }, + { + "label": "N", + "location": [ + 15.675100326538086, + -11.494000434875489, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 16.06060028076172, + -13.013500213623047, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 14.096699714660645, + -11.09179973602295, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 14.973299980163575, + -10.844300270080567, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 15.244199752807618, + -9.970199584960938, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 13.437600135803223, + -10.448399543762207, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 10.800800323486329, + -13.745400428771973, + 0.0 + ] + }, + { + "label": "H", + "location": [ + 13.378700256347657, + -13.745400428771973, + 0.0 + ] + } + ], + "bonds": [ + { + "type": 1, + "atoms": [ + 0, + 21 + ] + }, + { + "type": 1, + "atoms": [ + 6, + 5 + ] + }, + { + "type": 1, + "atoms": [ + 9, + 10 + ] + }, + { + "type": 1, + "atoms": [ + 2, + 3 + ] + }, + { + "type": 2, + "atoms": [ + 9, + 11 + ] + }, + { + "type": 1, + "atoms": [ + 5, + 4 + ] + }, + { + "type": 1, + "atoms": [ + 3, + 4 + ] + }, + { + "type": 1, + "atoms": [ + 6, + 7 + ], + "stereo": 1 + }, + { + "type": 1, + "atoms": [ + 3, + 1 + ], + "stereo": 1 + }, + { + "type": 1, + "atoms": [ + 5, + 0 + ], + "stereo": 6 + }, + { + "type": 1, + "atoms": [ + 7, + 8 + ] + }, + { + "type": 1, + "atoms": [ + 1, + 12 + ] + }, + { + "type": 1, + "atoms": [ + 1, + 13 + ] + }, + { + "type": 1, + "atoms": [ + 12, + 14 + ] + }, + { + "type": 2, + "atoms": [ + 12, + 15 + ] + }, + { + "type": 2, + "atoms": [ + 13, + 16 + ] + }, + { + "type": 1, + "atoms": [ + 14, + 17 + ] + }, + { + "type": 2, + "atoms": [ + 17, + 18 + ] + }, + { + "type": 1, + "atoms": [ + 16, + 17 + ] + }, + { + "type": 1, + "atoms": [ + 6, + 2 + ] + }, + { + "type": 1, + "atoms": [ + 16, + 19 + ] + }, + { + "type": 1, + "atoms": [ + 9, + 20 + ] + }, + { + "type": 1, + "atoms": [ + 8, + 9 + ] + } + ] + } +} \ No newline at end of file diff --git a/api/tests/integration/tests/formats/molecules/dthymine.mol b/api/tests/integration/tests/formats/molecules/dthymine.mol new file mode 100644 index 0000000000..97fb8ea1d2 --- /dev/null +++ b/api/tests/integration/tests/formats/molecules/dthymine.mol @@ -0,0 +1,76 @@ + + -INDIGO-09062309442D + + 0 0 0 0 0 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 0 0 0 0 0 +M V30 END CTAB +M V30 BEGIN TEMPLATE +M V30 TEMPLATE 45 DNA/T +M V30 BEGIN CTAB +M V30 COUNTS 22 23 3 0 0 +M V30 BEGIN ATOM +M V30 1 O 13.2102 -15.3772 0 0 +M V30 2 N 14.5655 -12.6378 0 0 CFG=3 +M V30 3 O 13.616 -13.0138 0 0 +M V30 4 C 14.2945 -13.5123 0 0 CFG=2 +M V30 5 C 14.0424 -14.2836 0 0 +M V30 6 C 13.2102 -14.2836 0 0 CFG=1 +M V30 7 C 12.9472 -13.5013 0 0 CFG=1 +M V30 8 C 12.1657 -13.2555 0 0 +M V30 9 O 11.9165 -12.4635 0 0 +M V30 10 P 10.9413 -12.1135 0 0 CFG=3 +M V30 11 O 10.9413 -11.2885 0 0 +M V30 12 O 10.9413 -12.9385 0 0 +M V30 13 C 15.4027 -12.3728 0 0 +M V30 14 C 13.8243 -11.9705 0 0 +M V30 15 N 15.6751 -11.494 0 0 CFG=3 +M V30 16 O 16.0606 -13.0135 0 0 +M V30 17 C 14.0967 -11.0918 0 0 +M V30 18 C 14.9733 -10.8443 0 0 +M V30 19 O 15.2442 -9.9702 0 0 +M V30 20 C 13.4376 -10.4484 0 0 +M V30 21 O 10.8008 -13.7454 0 0 +M V30 22 H 13.3787 -13.7454 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 22 +M V30 2 1 7 6 +M V30 3 1 10 11 +M V30 4 1 3 4 +M V30 5 2 10 12 +M V30 6 1 6 5 +M V30 7 1 4 5 +M V30 8 1 7 8 CFG=1 +M V30 9 1 4 2 CFG=1 +M V30 10 1 6 1 CFG=3 +M V30 11 1 8 9 +M V30 12 1 2 13 +M V30 13 1 2 14 +M V30 14 1 13 15 +M V30 15 2 13 16 +M V30 16 2 14 17 +M V30 17 1 15 18 +M V30 18 2 18 19 +M V30 19 1 17 18 +M V30 20 1 7 3 +M V30 21 1 17 20 +M V30 22 1 10 21 +M V30 23 1 9 10 +M V30 END BOND +M V30 BEGIN SGROUP +M V30 1 SUP 1 ATOMS=(20 2 1 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20) - +M V30 XBONDS=(2 22 1) CSTATE=(4 22 -1.27 -0 0) CSTATE=(4 1 1.3 -0 - +M V30 0) LABEL=T CLASS=DNA SAP=(3 10 21 Al) SAP=(3 1 22 Br) +M V30 2 SUP 2 ATOMS=(1 21) XBONDS=(1 22) CSTATE=(4 22 1.27 0 0) LABEL="5'" - +M V30 CLASS=LGRP +M V30 3 SUP 3 ATOMS=(1 22) XBONDS=(1 1) CSTATE=(4 1 -1.3 0 0) LABEL="3'" - +M V30 CLASS=LGRP +M V30 END SGROUP +M V30 BEGIN COLLECTION +M V30 MDLV30/STEABS ATOMS=(3 4 6 7) +M V30 END COLLECTION +M V30 END CTAB +M V30 END TEMPLATE +M END + diff --git a/api/tests/integration/tests/formats/molecules/thymine.ket b/api/tests/integration/tests/formats/molecules/thymine.ket new file mode 100644 index 0000000000..c87483e86f --- /dev/null +++ b/api/tests/integration/tests/formats/molecules/thymine.ket @@ -0,0 +1,399 @@ +{ + "root": { + "nodes": [], + "templates": [ + { + "$ref": "monomerTemplate-Thy_131" + } + ] + }, + "monomerTemplate-Thy_131": { + "type": "monomerTemplate", + "id": "Thy_131", + "class": "RNA", + "classHELM": "RNA", + "alias": "T", + "attachmentPoints": [ + { + "attachmentAtom": 10, + "leavingGroup": { + "atoms": [ + 21 + ] + } + }, + { + "attachmentAtom": 0, + "leavingGroup": { + "atoms": [ + 22 + ] + } + } + ], + "atoms": [ + { + "label": "O", + "location": [ + 12.760199546813965, + -15.714699745178223, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 14.082500457763672, + -15.261699676513672, + 0.0 + ] + }, + { + "label": "N", + "location": [ + 14.108799934387207, + -12.9483003616333, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 13.166000366210938, + -13.326299667358399, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 13.844499588012696, + -13.824799537658692, + 0.0 + ], + "stereoLabel": "abs" + }, + { + "label": "C", + "location": [ + 13.592399597167969, + -14.596099853515625, + 0.0 + ], + "stereoLabel": "abs" + }, + { + "label": "C", + "location": [ + 12.760199546813965, + -14.596099853515625, + 0.0 + ], + "stereoLabel": "abs" + }, + { + "label": "C", + "location": [ + 12.497200012207032, + -13.813799858093262, + 0.0 + ], + "stereoLabel": "abs" + }, + { + "label": "C", + "location": [ + 11.715700149536133, + -13.567999839782715, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 11.466500282287598, + -12.776000022888184, + 0.0 + ] + }, + { + "label": "P", + "location": [ + 10.491299629211426, + -12.37600040435791, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 10.116299629211426, + -11.550999641418457, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 10.491299629211426, + -13.201000213623047, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 14.943900108337403, + -12.676899909973145, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 13.362500190734864, + -12.286600112915039, + 0.0 + ] + }, + { + "label": "N", + "location": [ + 15.209600448608399, + -11.795900344848633, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 15.60669994354248, + -13.3125, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 13.628100395202637, + -11.405900001525879, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 14.502799987792969, + -11.151599884033204, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 14.767000198364258, + -10.275500297546387, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 12.964200019836426, + -10.767499923706055, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 10.525699615478516, + -14.04539966583252, + 0.0 + ] + }, + { + "label": "H", + "location": [ + 12.559800148010254, + -14.04539966583252, + 0.0 + ] + } + ], + "bonds": [ + { + "type": 1, + "atoms": [ + 0, + 22 + ] + }, + { + "type": 1, + "atoms": [ + 7, + 6 + ] + }, + { + "type": 1, + "atoms": [ + 10, + 11 + ] + }, + { + "type": 1, + "atoms": [ + 3, + 4 + ] + }, + { + "type": 2, + "atoms": [ + 10, + 12 + ] + }, + { + "type": 1, + "atoms": [ + 6, + 5 + ] + }, + { + "type": 1, + "atoms": [ + 4, + 5 + ] + }, + { + "type": 1, + "atoms": [ + 7, + 8 + ], + "stereo": 1 + }, + { + "type": 1, + "atoms": [ + 4, + 2 + ], + "stereo": 1 + }, + { + "type": 1, + "atoms": [ + 5, + 1 + ], + "stereo": 6 + }, + { + "type": 1, + "atoms": [ + 6, + 0 + ], + "stereo": 6 + }, + { + "type": 1, + "atoms": [ + 8, + 9 + ] + }, + { + "type": 1, + "atoms": [ + 2, + 13 + ] + }, + { + "type": 1, + "atoms": [ + 2, + 14 + ] + }, + { + "type": 1, + "atoms": [ + 13, + 15 + ] + }, + { + "type": 2, + "atoms": [ + 13, + 16 + ] + }, + { + "type": 2, + "atoms": [ + 14, + 17 + ] + }, + { + "type": 1, + "atoms": [ + 15, + 18 + ] + }, + { + "type": 2, + "atoms": [ + 18, + 19 + ] + }, + { + "type": 1, + "atoms": [ + 17, + 18 + ] + }, + { + "type": 1, + "atoms": [ + 7, + 3 + ] + }, + { + "type": 1, + "atoms": [ + 17, + 20 + ] + }, + { + "type": 1, + "atoms": [ + 10, + 21 + ] + }, + { + "type": 1, + "atoms": [ + 9, + 10 + ] + } + ] + } +} \ No newline at end of file diff --git a/api/tests/integration/tests/formats/molecules/thymine.mol b/api/tests/integration/tests/formats/molecules/thymine.mol new file mode 100644 index 0000000000..cb553f23a7 --- /dev/null +++ b/api/tests/integration/tests/formats/molecules/thymine.mol @@ -0,0 +1,78 @@ + + -INDIGO-09062309442D + + 0 0 0 0 0 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 0 0 0 0 0 +M V30 END CTAB +M V30 BEGIN TEMPLATE +M V30 TEMPLATE 131 RNA/T +M V30 BEGIN CTAB +M V30 COUNTS 23 24 3 0 0 +M V30 BEGIN ATOM +M V30 1 O 12.7602 -15.7147 0 0 +M V30 2 O 14.0825 -15.2617 0 0 +M V30 3 N 14.1088 -12.9483 0 0 CFG=3 +M V30 4 O 13.166 -13.3263 0 0 +M V30 5 C 13.8445 -13.8248 0 0 CFG=2 +M V30 6 C 13.5924 -14.5961 0 0 CFG=1 +M V30 7 C 12.7602 -14.5961 0 0 CFG=1 +M V30 8 C 12.4972 -13.8138 0 0 CFG=1 +M V30 9 C 11.7157 -13.568 0 0 +M V30 10 O 11.4665 -12.776 0 0 +M V30 11 P 10.4913 -12.376 0 0 CFG=3 +M V30 12 O 10.1163 -11.551 0 0 +M V30 13 O 10.4913 -13.201 0 0 +M V30 14 C 14.9439 -12.6769 0 0 +M V30 15 C 13.3625 -12.2866 0 0 +M V30 16 N 15.2096 -11.7959 0 0 CFG=3 +M V30 17 O 15.6067 -13.3125 0 0 +M V30 18 C 13.6281 -11.4059 0 0 +M V30 19 C 14.5028 -11.1516 0 0 +M V30 20 O 14.767 -10.2755 0 0 +M V30 21 C 12.9642 -10.7675 0 0 +M V30 22 O 10.5257 -14.0454 0 0 +M V30 23 H 12.5598 -14.0454 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 23 +M V30 2 1 8 7 +M V30 3 1 11 12 +M V30 4 1 4 5 +M V30 5 2 11 13 +M V30 6 1 7 6 +M V30 7 1 5 6 +M V30 8 1 8 9 CFG=1 +M V30 9 1 5 3 CFG=1 +M V30 10 1 6 2 CFG=3 +M V30 11 1 7 1 CFG=3 +M V30 12 1 9 10 +M V30 13 1 3 14 +M V30 14 1 3 15 +M V30 15 1 14 16 +M V30 16 2 14 17 +M V30 17 2 15 18 +M V30 18 1 16 19 +M V30 19 2 19 20 +M V30 20 1 18 19 +M V30 21 1 8 4 +M V30 22 1 18 21 +M V30 23 1 11 22 +M V30 24 1 10 11 +M V30 END BOND +M V30 BEGIN SGROUP +M V30 1 SUP 1 ATOMS=(21 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21- +M V30 ) XBONDS=(2 23 1) CSTATE=(4 23 -1.1 -0 0) CSTATE=(4 1 0.93 -0 0) - +M V30 LABEL=T CLASS=RNA SAP=(3 11 22 Al) SAP=(3 1 23 Br) +M V30 2 SUP 2 ATOMS=(1 22) XBONDS=(1 23) CSTATE=(4 23 1.1 0 0) LABEL="5'" - +M V30 CLASS=LGRP +M V30 3 SUP 3 ATOMS=(1 23) XBONDS=(1 1) CSTATE=(4 1 -0.93 0 0) LABEL="3'" - +M V30 CLASS=LGRP +M V30 END SGROUP +M V30 BEGIN COLLECTION +M V30 MDLV30/STEABS ATOMS=(4 5 6 7 8) +M V30 END COLLECTION +M V30 END CTAB +M V30 END TEMPLATE +M END + diff --git a/api/tests/integration/tests/formats/ref/chem.ket b/api/tests/integration/tests/formats/ref/chem.ket new file mode 100644 index 0000000000..8b9923cc5b --- /dev/null +++ b/api/tests/integration/tests/formats/ref/chem.ket @@ -0,0 +1,183 @@ +{ + "root": { + "nodes": [], + "templates": [ + { + "$ref": "monomerTemplate-cch_3" + } + ] + }, + "monomerTemplate-cch_3": { + "type": "monomerTemplate", + "id": "cch_3", + "class": "Chem", + "classHELM": "CHEM", + "alias": "cch", + "attachmentPoints": [ + { + "type": "right", + "label": "R2", + "attachmentAtom": 8, + "leavingGroup": { + "atoms": [ + 1 + ] + } + }, + { + "type": "side", + "label": "R3", + "attachmentAtom": 6, + "leavingGroup": { + "atoms": [ + 2 + ] + } + }, + { + "type": "side", + "label": "R5", + "attachmentAtom": 3, + "leavingGroup": { + "atoms": [ + 0 + ] + } + } + ], + "atoms": [ + { + "label": "H", + "location": [ + 9.201199531555176, + -7.158699989318848, + 0.0 + ] + }, + { + "label": "H", + "location": [ + 8.374699592590332, + -7.985400199890137, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 10.02810001373291, + -7.985400199890137, + 0.0 + ] + }, + { + "label": "S", + "location": [ + 9.718199729919434, + -6.737199783325195, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 9.194899559020996, + -7.6427001953125, + 0.0 + ], + "stereoLabel": "abs" + }, + { + "label": "O", + "location": [ + 9.698399543762207, + -8.580300331115723, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 9.698399543762207, + -7.97629976272583, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 9.194899559020996, + -7.03879976272583, + 0.0 + ] + }, + { + "label": "N", + "location": [ + 8.704099655151368, + -7.994699954986572, + 0.0 + ] + } + ], + "bonds": [ + { + "type": 1, + "atoms": [ + 3, + 0 + ] + }, + { + "type": 1, + "atoms": [ + 6, + 2 + ] + }, + { + "type": 1, + "atoms": [ + 8, + 1 + ] + }, + { + "type": 2, + "atoms": [ + 6, + 5 + ] + }, + { + "type": 1, + "atoms": [ + 4, + 7 + ], + "stereo": 1 + }, + { + "type": 1, + "atoms": [ + 7, + 3 + ] + }, + { + "type": 1, + "atoms": [ + 4, + 6 + ] + }, + { + "type": 1, + "atoms": [ + 8, + 4 + ] + } + ] + } +} \ No newline at end of file diff --git a/api/tests/integration/tests/formats/ref/chem.mol b/api/tests/integration/tests/formats/ref/chem.mol new file mode 100644 index 0000000000..efd77a765a --- /dev/null +++ b/api/tests/integration/tests/formats/ref/chem.mol @@ -0,0 +1,58 @@ + + -INDIGO-01000000002D + + 0 0 0 0 0 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 0 0 0 0 0 +M V30 BEGIN ATOM +M V30 END ATOM +M V30 BEGIN BOND +M V30 END BOND +M V30 END CTAB +M V30 BEGIN TEMPLATE +M V30 TEMPLATE 1 CHEM/cch/cch +M V30 BEGIN CTAB +M V30 COUNTS 9 8 4 0 0 +M V30 BEGIN ATOM +M V30 1 H 9.2012 -7.1587 0.0 0 +M V30 2 H 8.3747 -7.9854 0.0 0 +M V30 3 O 10.0281 -7.9854 0.0 0 +M V30 4 S 9.7182 -6.7372 0.0 0 +M V30 5 C 9.1949 -7.6427 0.0 0 CFG=2 +M V30 6 O 9.6984 -8.5803 0.0 0 +M V30 7 C 9.6984 -7.9763 0.0 0 +M V30 8 C 9.1949 -7.0388 0.0 0 +M V30 9 N 8.7041 -7.9947 0.0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 4 1 +M V30 2 1 7 3 +M V30 3 1 9 2 +M V30 4 2 7 6 +M V30 5 1 5 8 CFG=1 +M V30 6 1 8 4 +M V30 7 1 5 7 +M V30 8 1 9 5 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEABS ATOMS=(1 5) +M V30 END COLLECTION +M V30 BEGIN SGROUP +M V30 1 SUP 1 ATOMS=(1 2) XBONDS=(1 3) BRKXYZ=(9 0.164700 -0.004650 0.000000- +M V30 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000) LABEL=H CLASS=- +M V30 LGRP +M V30 2 SUP 2 ATOMS=(1 3) XBONDS=(1 2) BRKXYZ=(9 -0.164850 0.004550 0.000000- +M V30 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000) LABEL=OH CLASS- +M V30 =LGRP +M V30 3 SUP 3 ATOMS=(1 1) XBONDS=(1 1) BRKXYZ=(9 0.258500 0.210750 0.000000 - +M V30 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000) LABEL=H CLASS=L- +M V30 GRP +M V30 4 SUP 4 ATOMS=(6 4 5 6 7 8 9) XBONDS=(3 1 2 3) BRKXYZ=(9 -0.258500 -0.- +M V30 210750 0.000000 0.164850 -0.004550 0.000000 0.000000 0.000000 0.000000- +M V30 ) BRKXYZ=(9 -0.164700 0.004650 0.000000 0.000000 0.000000 0.000000 0.0- +M V30 00000 0.000000 0.000000) LABEL=cch CLASS=CHEM SAP=(3 9 2 R2) SAP=(3 7 - +M V30 3 Dx) SAP=(3 4 1 Fx) +M V30 END SGROUP +M V30 END CTAB +M V30 END TEMPLATE +M END diff --git a/api/tests/integration/tests/formats/ref/cysteine.ket b/api/tests/integration/tests/formats/ref/cysteine.ket new file mode 100644 index 0000000000..e8a46d44c1 --- /dev/null +++ b/api/tests/integration/tests/formats/ref/cysteine.ket @@ -0,0 +1,177 @@ +{ + "root": { + "nodes": [], + "templates": [ + { + "$ref": "monomerTemplate-cys_3" + } + ] + }, + "monomerTemplate-cys_3": { + "type": "monomerTemplate", + "id": "cys_3", + "class": "AminoAcid", + "classHELM": "PEPTIDE", + "alias": "C", + "attachmentPoints": [ + { + "attachmentAtom": 8, + "leavingGroup": { + "atoms": [ + 1 + ] + } + }, + { + "attachmentAtom": 6, + "leavingGroup": { + "atoms": [ + 2 + ] + } + }, + { + "attachmentAtom": 3, + "leavingGroup": { + "atoms": [ + 0 + ] + } + } + ], + "atoms": [ + { + "label": "H", + "location": [ + 9.201199531555176, + -7.158699989318848, + 0.0 + ] + }, + { + "label": "H", + "location": [ + 8.374699592590332, + -7.985400199890137, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 10.02810001373291, + -7.985400199890137, + 0.0 + ] + }, + { + "label": "S", + "location": [ + 9.718199729919434, + -6.737199783325195, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 9.194899559020996, + -7.6427001953125, + 0.0 + ], + "stereoLabel": "abs" + }, + { + "label": "O", + "location": [ + 9.698399543762207, + -8.580300331115723, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 9.698399543762207, + -7.97629976272583, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 9.194899559020996, + -7.03879976272583, + 0.0 + ] + }, + { + "label": "N", + "location": [ + 8.704099655151368, + -7.994699954986572, + 0.0 + ] + } + ], + "bonds": [ + { + "type": 1, + "atoms": [ + 3, + 0 + ] + }, + { + "type": 1, + "atoms": [ + 6, + 2 + ] + }, + { + "type": 1, + "atoms": [ + 8, + 1 + ] + }, + { + "type": 2, + "atoms": [ + 6, + 5 + ] + }, + { + "type": 1, + "atoms": [ + 4, + 7 + ], + "stereo": 1 + }, + { + "type": 1, + "atoms": [ + 7, + 3 + ] + }, + { + "type": 1, + "atoms": [ + 4, + 6 + ] + }, + { + "type": 1, + "atoms": [ + 8, + 4 + ] + } + ] + } +} \ No newline at end of file diff --git a/api/tests/integration/tests/formats/ref/cysteine.mol b/api/tests/integration/tests/formats/ref/cysteine.mol new file mode 100644 index 0000000000..f38151667b --- /dev/null +++ b/api/tests/integration/tests/formats/ref/cysteine.mol @@ -0,0 +1,58 @@ + + -INDIGO-01000000002D + + 0 0 0 0 0 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 0 0 0 0 0 +M V30 BEGIN ATOM +M V30 END ATOM +M V30 BEGIN BOND +M V30 END BOND +M V30 END CTAB +M V30 BEGIN TEMPLATE +M V30 TEMPLATE 1 AA/cys/C +M V30 BEGIN CTAB +M V30 COUNTS 9 8 4 0 0 +M V30 BEGIN ATOM +M V30 1 H 9.2012 -7.1587 0.0 0 +M V30 2 H 8.3747 -7.9854 0.0 0 +M V30 3 O 10.0281 -7.9854 0.0 0 +M V30 4 S 9.7182 -6.7372 0.0 0 +M V30 5 C 9.1949 -7.6427 0.0 0 CFG=2 +M V30 6 O 9.6984 -8.5803 0.0 0 +M V30 7 C 9.6984 -7.9763 0.0 0 +M V30 8 C 9.1949 -7.0388 0.0 0 +M V30 9 N 8.7041 -7.9947 0.0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 4 1 +M V30 2 1 7 3 +M V30 3 1 9 2 +M V30 4 2 7 6 +M V30 5 1 5 8 CFG=1 +M V30 6 1 8 4 +M V30 7 1 5 7 +M V30 8 1 9 5 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEABS ATOMS=(1 5) +M V30 END COLLECTION +M V30 BEGIN SGROUP +M V30 1 SUP 1 ATOMS=(1 2) XBONDS=(1 3) BRKXYZ=(9 0.164700 -0.004650 0.000000- +M V30 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000) LABEL=H CLASS=- +M V30 LGRP +M V30 2 SUP 2 ATOMS=(1 3) XBONDS=(1 2) BRKXYZ=(9 -0.164850 0.004550 0.000000- +M V30 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000) LABEL=OH CLASS- +M V30 =LGRP +M V30 3 SUP 3 ATOMS=(1 1) XBONDS=(1 1) BRKXYZ=(9 0.258500 0.210750 0.000000 - +M V30 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000) LABEL=H CLASS=L- +M V30 GRP +M V30 4 SUP 4 ATOMS=(6 4 5 6 7 8 9) XBONDS=(3 1 2 3) BRKXYZ=(9 -0.258500 -0.- +M V30 210750 0.000000 0.164850 -0.004550 0.000000 0.000000 0.000000 0.000000- +M V30 ) BRKXYZ=(9 -0.164700 0.004650 0.000000 0.000000 0.000000 0.000000 0.0- +M V30 00000 0.000000 0.000000) LABEL=C CLASS=AA SAP=(3 9 2 Al) SAP=(3 7 3 Br- +M V30 ) SAP=(3 4 1 Cx) +M V30 END SGROUP +M V30 END CTAB +M V30 END TEMPLATE +M END diff --git a/api/tests/integration/tests/formats/ref/dala.mol b/api/tests/integration/tests/formats/ref/dala.mol new file mode 100644 index 0000000000..0310b71fa4 --- /dev/null +++ b/api/tests/integration/tests/formats/ref/dala.mol @@ -0,0 +1,49 @@ + + -INDIGO-01000000002D + + 0 0 0 0 0 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 0 0 0 0 0 +M V30 BEGIN ATOM +M V30 END ATOM +M V30 BEGIN BOND +M V30 END BOND +M V30 END CTAB +M V30 BEGIN TEMPLATE +M V30 TEMPLATE 1 dAA/ala/a NATREPLACE=AA/A +M V30 BEGIN CTAB +M V30 COUNTS 7 6 3 0 0 +M V30 BEGIN ATOM +M V30 1 O 6.6266 -2.0662 0.0 0 +M V30 2 H 5.0016 -2.0876 0.0 0 +M V30 3 N 5.1358 -2.0784 0.0 0 +M V30 4 C 5.7844 -1.5983 0.0 0 CFG=1 +M V30 5 C 6.4753 -2.0653 0.0 0 +M V30 6 O 6.4753 -2.8977 0.0 0 +M V30 7 C 5.7844 -0.7662 0.0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 3 4 +M V30 2 1 4 5 +M V30 3 2 5 6 +M V30 4 1 4 7 CFG=3 +M V30 5 1 3 2 +M V30 6 1 5 1 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEABS ATOMS=(1 4) +M V30 END COLLECTION +M V30 BEGIN SGROUP +M V30 1 SUP 1 ATOMS=(1 2) XBONDS=(1 5) BRKXYZ=(9 0.067100 0.004600 0.000000 - +M V30 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000) LABEL=H CLASS=L- +M V30 GRP +M V30 2 SUP 2 ATOMS=(1 1) XBONDS=(1 6) BRKXYZ=(9 -0.075650 0.000450 0.000000- +M V30 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000) LABEL=OH CLASS- +M V30 =LGRP +M V30 3 SUP 3 ATOMS=(5 3 4 5 6 7) XBONDS=(2 5 6) BRKXYZ=(9 -0.067100 -0.0046- +M V30 00 0.000000 0.075650 -0.000450 0.000000 0.000000 0.000000 0.000000) LA- +M V30 BEL=a CLASS=AA SAP=(3 3 2 Al) SAP=(3 5 1 Br) NATREPLACE=AA/A +M V30 END SGROUP +M V30 END CTAB +M V30 END TEMPLATE +M END diff --git a/api/tests/integration/tests/formats/ref/dcysteine.ket b/api/tests/integration/tests/formats/ref/dcysteine.ket new file mode 100644 index 0000000000..34379115a6 --- /dev/null +++ b/api/tests/integration/tests/formats/ref/dcysteine.ket @@ -0,0 +1,179 @@ +{ + "root": { + "nodes": [], + "templates": [ + { + "$ref": "monomerTemplate-cys_27" + } + ] + }, + "monomerTemplate-cys_27": { + "type": "monomerTemplate", + "id": "cys_27", + "class": "D-AminoAcid", + "classHELM": "PEPTIDE", + "alias": "dc", + "naturalAnalog": "Cys", + "naturalAnalogShort": "C", + "attachmentPoints": [ + { + "attachmentAtom": 8, + "leavingGroup": { + "atoms": [ + 1 + ] + } + }, + { + "attachmentAtom": 6, + "leavingGroup": { + "atoms": [ + 2 + ] + } + }, + { + "attachmentAtom": 3, + "leavingGroup": { + "atoms": [ + 0 + ] + } + } + ], + "atoms": [ + { + "label": "H", + "location": [ + 9.201199531555176, + -7.158699989318848, + 0.0 + ] + }, + { + "label": "H", + "location": [ + 8.374699592590332, + -7.985400199890137, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 10.02810001373291, + -7.985400199890137, + 0.0 + ] + }, + { + "label": "S", + "location": [ + 9.718199729919434, + -6.737199783325195, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 9.194899559020996, + -7.6427001953125, + 0.0 + ], + "stereoLabel": "abs" + }, + { + "label": "O", + "location": [ + 9.698399543762207, + -8.580300331115723, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 9.698399543762207, + -7.97629976272583, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 9.194899559020996, + -7.03879976272583, + 0.0 + ] + }, + { + "label": "N", + "location": [ + 8.704099655151368, + -7.994699954986572, + 0.0 + ] + } + ], + "bonds": [ + { + "type": 1, + "atoms": [ + 3, + 0 + ] + }, + { + "type": 1, + "atoms": [ + 6, + 2 + ] + }, + { + "type": 1, + "atoms": [ + 8, + 1 + ] + }, + { + "type": 2, + "atoms": [ + 6, + 5 + ] + }, + { + "type": 1, + "atoms": [ + 4, + 7 + ], + "stereo": 6 + }, + { + "type": 1, + "atoms": [ + 7, + 3 + ] + }, + { + "type": 1, + "atoms": [ + 4, + 6 + ] + }, + { + "type": 1, + "atoms": [ + 8, + 4 + ] + } + ] + } +} \ No newline at end of file diff --git a/api/tests/integration/tests/formats/ref/dcysteine.mol b/api/tests/integration/tests/formats/ref/dcysteine.mol new file mode 100644 index 0000000000..d4f5eaecb3 --- /dev/null +++ b/api/tests/integration/tests/formats/ref/dcysteine.mol @@ -0,0 +1,58 @@ + + -INDIGO-01000000002D + + 0 0 0 0 0 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 0 0 0 0 0 +M V30 BEGIN ATOM +M V30 END ATOM +M V30 BEGIN BOND +M V30 END BOND +M V30 END CTAB +M V30 BEGIN TEMPLATE +M V30 TEMPLATE 1 dAA/cys/c NATREPLACE=AA/C +M V30 BEGIN CTAB +M V30 COUNTS 9 8 4 0 0 +M V30 BEGIN ATOM +M V30 1 H 9.2012 -7.1587 0.0 0 +M V30 2 H 8.3747 -7.9854 0.0 0 +M V30 3 O 10.0281 -7.9854 0.0 0 +M V30 4 S 9.7182 -6.7372 0.0 0 +M V30 5 C 9.1949 -7.6427 0.0 0 CFG=1 +M V30 6 O 9.6984 -8.5803 0.0 0 +M V30 7 C 9.6984 -7.9763 0.0 0 +M V30 8 C 9.1949 -7.0388 0.0 0 +M V30 9 N 8.7041 -7.9947 0.0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 4 1 +M V30 2 1 7 3 +M V30 3 1 9 2 +M V30 4 2 7 6 +M V30 5 1 5 8 CFG=3 +M V30 6 1 8 4 +M V30 7 1 5 7 +M V30 8 1 9 5 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEABS ATOMS=(1 5) +M V30 END COLLECTION +M V30 BEGIN SGROUP +M V30 1 SUP 1 ATOMS=(1 2) XBONDS=(1 3) BRKXYZ=(9 0.164700 -0.004650 0.000000- +M V30 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000) LABEL=H CLASS=- +M V30 LGRP +M V30 2 SUP 2 ATOMS=(1 3) XBONDS=(1 2) BRKXYZ=(9 -0.164850 0.004550 0.000000- +M V30 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000) LABEL=OH CLASS- +M V30 =LGRP +M V30 3 SUP 3 ATOMS=(1 1) XBONDS=(1 1) BRKXYZ=(9 0.258500 0.210750 0.000000 - +M V30 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000) LABEL=H CLASS=L- +M V30 GRP +M V30 4 SUP 4 ATOMS=(6 4 5 6 7 8 9) XBONDS=(3 1 2 3) BRKXYZ=(9 -0.258500 -0.- +M V30 210750 0.000000 0.164850 -0.004550 0.000000 0.000000 0.000000 0.000000- +M V30 ) BRKXYZ=(9 -0.164700 0.004650 0.000000 0.000000 0.000000 0.000000 0.0- +M V30 00000 0.000000 0.000000) LABEL=c CLASS=AA SAP=(3 9 2 Al) SAP=(3 7 3 Br- +M V30 ) SAP=(3 4 1 Cx) NATREPLACE=AA/C +M V30 END SGROUP +M V30 END CTAB +M V30 END TEMPLATE +M END diff --git a/api/tests/integration/tests/formats/ref/dthymine.ket b/api/tests/integration/tests/formats/ref/dthymine.ket new file mode 100644 index 0000000000..d7cd558006 --- /dev/null +++ b/api/tests/integration/tests/formats/ref/dthymine.ket @@ -0,0 +1,382 @@ +{ + "root": { + "nodes": [], + "templates": [ + { + "$ref": "monomerTemplate-Thy_45" + } + ] + }, + "monomerTemplate-Thy_45": { + "type": "monomerTemplate", + "id": "Thy_45", + "class": "DNA", + "classHELM": "RNA", + "alias": "T", + "attachmentPoints": [ + { + "attachmentAtom": 9, + "leavingGroup": { + "atoms": [ + 20 + ] + } + }, + { + "attachmentAtom": 0, + "leavingGroup": { + "atoms": [ + 21 + ] + } + } + ], + "atoms": [ + { + "label": "O", + "location": [ + 13.210200309753418, + -15.37720012664795, + 0.0 + ] + }, + { + "label": "N", + "location": [ + 14.565500259399414, + -12.637800216674805, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 13.616000175476075, + -13.013799667358399, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 14.294500350952149, + -13.512299537658692, + 0.0 + ], + "stereoLabel": "abs" + }, + { + "label": "C", + "location": [ + 14.042400360107422, + -14.283599853515625, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 13.210200309753418, + -14.283599853515625, + 0.0 + ], + "stereoLabel": "abs" + }, + { + "label": "C", + "location": [ + 12.947199821472168, + -13.501299858093262, + 0.0 + ], + "stereoLabel": "abs" + }, + { + "label": "C", + "location": [ + 12.16569995880127, + -13.255499839782715, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 11.916500091552735, + -12.463500022888184, + 0.0 + ] + }, + { + "label": "P", + "location": [ + 10.941300392150879, + -12.113499641418457, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 10.941300392150879, + -11.28849983215332, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 10.941300392150879, + -12.93850040435791, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 15.402700424194336, + -12.37279987335205, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 13.824299812316895, + -11.970499992370606, + 0.0 + ] + }, + { + "label": "N", + "location": [ + 15.675100326538086, + -11.494000434875489, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 16.06060028076172, + -13.013500213623047, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 14.096699714660645, + -11.09179973602295, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 14.973299980163575, + -10.844300270080567, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 15.244199752807618, + -9.970199584960938, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 13.437600135803223, + -10.448399543762207, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 10.800800323486329, + -13.745400428771973, + 0.0 + ] + }, + { + "label": "H", + "location": [ + 13.378700256347657, + -13.745400428771973, + 0.0 + ] + } + ], + "bonds": [ + { + "type": 1, + "atoms": [ + 0, + 21 + ] + }, + { + "type": 1, + "atoms": [ + 6, + 5 + ] + }, + { + "type": 1, + "atoms": [ + 9, + 10 + ] + }, + { + "type": 1, + "atoms": [ + 2, + 3 + ] + }, + { + "type": 2, + "atoms": [ + 9, + 11 + ] + }, + { + "type": 1, + "atoms": [ + 5, + 4 + ] + }, + { + "type": 1, + "atoms": [ + 3, + 4 + ] + }, + { + "type": 1, + "atoms": [ + 6, + 7 + ], + "stereo": 1 + }, + { + "type": 1, + "atoms": [ + 3, + 1 + ], + "stereo": 1 + }, + { + "type": 1, + "atoms": [ + 5, + 0 + ], + "stereo": 6 + }, + { + "type": 1, + "atoms": [ + 7, + 8 + ] + }, + { + "type": 1, + "atoms": [ + 1, + 12 + ] + }, + { + "type": 1, + "atoms": [ + 1, + 13 + ] + }, + { + "type": 1, + "atoms": [ + 12, + 14 + ] + }, + { + "type": 2, + "atoms": [ + 12, + 15 + ] + }, + { + "type": 2, + "atoms": [ + 13, + 16 + ] + }, + { + "type": 1, + "atoms": [ + 14, + 17 + ] + }, + { + "type": 2, + "atoms": [ + 17, + 18 + ] + }, + { + "type": 1, + "atoms": [ + 16, + 17 + ] + }, + { + "type": 1, + "atoms": [ + 6, + 2 + ] + }, + { + "type": 1, + "atoms": [ + 16, + 19 + ] + }, + { + "type": 1, + "atoms": [ + 9, + 20 + ] + }, + { + "type": 1, + "atoms": [ + 8, + 9 + ] + } + ] + } +} \ No newline at end of file diff --git a/api/tests/integration/tests/formats/ref/dthymine.mol b/api/tests/integration/tests/formats/ref/dthymine.mol new file mode 100644 index 0000000000..3475b77bfe --- /dev/null +++ b/api/tests/integration/tests/formats/ref/dthymine.mol @@ -0,0 +1,82 @@ + + -INDIGO-01000000002D + + 0 0 0 0 0 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 0 0 0 0 0 +M V30 BEGIN ATOM +M V30 END ATOM +M V30 BEGIN BOND +M V30 END BOND +M V30 END CTAB +M V30 BEGIN TEMPLATE +M V30 TEMPLATE 1 DNA/Thy/T +M V30 BEGIN CTAB +M V30 COUNTS 22 23 3 0 0 +M V30 BEGIN ATOM +M V30 1 O 13.2102 -15.3772 0.0 0 +M V30 2 N 14.5655 -12.6378 0.0 0 +M V30 3 O 13.616 -13.0138 0.0 0 +M V30 4 C 14.2945 -13.5123 0.0 0 CFG=2 +M V30 5 C 14.0424 -14.2836 0.0 0 +M V30 6 C 13.2102 -14.2836 0.0 0 CFG=1 +M V30 7 C 12.9472 -13.5013 0.0 0 CFG=1 +M V30 8 C 12.1657 -13.2555 0.0 0 +M V30 9 O 11.9165 -12.4635 0.0 0 +M V30 10 P 10.9413 -12.1135 0.0 0 +M V30 11 O 10.9413 -11.2885 0.0 0 +M V30 12 O 10.9413 -12.9385 0.0 0 +M V30 13 C 15.4027 -12.3728 0.0 0 +M V30 14 C 13.8243 -11.9705 0.0 0 +M V30 15 N 15.6751 -11.494 0.0 0 +M V30 16 O 16.0606 -13.0135 0.0 0 +M V30 17 C 14.0967 -11.0918 0.0 0 +M V30 18 C 14.9733 -10.8443 0.0 0 +M V30 19 O 15.2442 -9.9702 0.0 0 +M V30 20 C 13.4376 -10.4484 0.0 0 +M V30 21 O 10.8008 -13.7454 0.0 0 +M V30 22 H 13.3787 -13.7454 0.0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 22 +M V30 2 1 7 6 +M V30 3 1 10 11 +M V30 4 1 3 4 +M V30 5 2 10 12 +M V30 6 1 6 5 +M V30 7 1 4 5 +M V30 8 1 7 8 CFG=1 +M V30 9 1 4 2 CFG=1 +M V30 10 1 6 1 CFG=3 +M V30 11 1 8 9 +M V30 12 1 2 13 +M V30 13 1 2 14 +M V30 14 1 13 15 +M V30 15 2 13 16 +M V30 16 2 14 17 +M V30 17 1 15 18 +M V30 18 2 18 19 +M V30 19 1 17 18 +M V30 20 1 7 3 +M V30 21 1 17 20 +M V30 22 1 10 21 +M V30 23 1 9 10 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEABS ATOMS=(3 4 6 7) +M V30 END COLLECTION +M V30 BEGIN SGROUP +M V30 1 SUP 1 ATOMS=(1 21) XBONDS=(1 22) BRKXYZ=(9 0.070250 0.815950 0.00000- +M V30 0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000) LABEL=OH CLAS- +M V30 S=LGRP +M V30 2 SUP 2 ATOMS=(1 22) XBONDS=(1 1) BRKXYZ=(9 -0.084250 -0.815900 0.0000- +M V30 00 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000) LABEL=H CLAS- +M V30 S=LGRP +M V30 3 SUP 3 ATOMS=(20 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20) - +M V30 XBONDS=(2 1 22) BRKXYZ=(9 0.084250 0.815900 0.000000 -0.070250 -0.8159- +M V30 50 0.000000 0.000000 0.000000 0.000000) LABEL=T CLASS=DNA SAP=(3 10 21- +M V30 Al) SAP=(3 1 22 Br) +M V30 END SGROUP +M V30 END CTAB +M V30 END TEMPLATE +M END diff --git a/api/tests/integration/tests/formats/ref/thymine.ket b/api/tests/integration/tests/formats/ref/thymine.ket new file mode 100644 index 0000000000..c87483e86f --- /dev/null +++ b/api/tests/integration/tests/formats/ref/thymine.ket @@ -0,0 +1,399 @@ +{ + "root": { + "nodes": [], + "templates": [ + { + "$ref": "monomerTemplate-Thy_131" + } + ] + }, + "monomerTemplate-Thy_131": { + "type": "monomerTemplate", + "id": "Thy_131", + "class": "RNA", + "classHELM": "RNA", + "alias": "T", + "attachmentPoints": [ + { + "attachmentAtom": 10, + "leavingGroup": { + "atoms": [ + 21 + ] + } + }, + { + "attachmentAtom": 0, + "leavingGroup": { + "atoms": [ + 22 + ] + } + } + ], + "atoms": [ + { + "label": "O", + "location": [ + 12.760199546813965, + -15.714699745178223, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 14.082500457763672, + -15.261699676513672, + 0.0 + ] + }, + { + "label": "N", + "location": [ + 14.108799934387207, + -12.9483003616333, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 13.166000366210938, + -13.326299667358399, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 13.844499588012696, + -13.824799537658692, + 0.0 + ], + "stereoLabel": "abs" + }, + { + "label": "C", + "location": [ + 13.592399597167969, + -14.596099853515625, + 0.0 + ], + "stereoLabel": "abs" + }, + { + "label": "C", + "location": [ + 12.760199546813965, + -14.596099853515625, + 0.0 + ], + "stereoLabel": "abs" + }, + { + "label": "C", + "location": [ + 12.497200012207032, + -13.813799858093262, + 0.0 + ], + "stereoLabel": "abs" + }, + { + "label": "C", + "location": [ + 11.715700149536133, + -13.567999839782715, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 11.466500282287598, + -12.776000022888184, + 0.0 + ] + }, + { + "label": "P", + "location": [ + 10.491299629211426, + -12.37600040435791, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 10.116299629211426, + -11.550999641418457, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 10.491299629211426, + -13.201000213623047, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 14.943900108337403, + -12.676899909973145, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 13.362500190734864, + -12.286600112915039, + 0.0 + ] + }, + { + "label": "N", + "location": [ + 15.209600448608399, + -11.795900344848633, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 15.60669994354248, + -13.3125, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 13.628100395202637, + -11.405900001525879, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 14.502799987792969, + -11.151599884033204, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 14.767000198364258, + -10.275500297546387, + 0.0 + ] + }, + { + "label": "C", + "location": [ + 12.964200019836426, + -10.767499923706055, + 0.0 + ] + }, + { + "label": "O", + "location": [ + 10.525699615478516, + -14.04539966583252, + 0.0 + ] + }, + { + "label": "H", + "location": [ + 12.559800148010254, + -14.04539966583252, + 0.0 + ] + } + ], + "bonds": [ + { + "type": 1, + "atoms": [ + 0, + 22 + ] + }, + { + "type": 1, + "atoms": [ + 7, + 6 + ] + }, + { + "type": 1, + "atoms": [ + 10, + 11 + ] + }, + { + "type": 1, + "atoms": [ + 3, + 4 + ] + }, + { + "type": 2, + "atoms": [ + 10, + 12 + ] + }, + { + "type": 1, + "atoms": [ + 6, + 5 + ] + }, + { + "type": 1, + "atoms": [ + 4, + 5 + ] + }, + { + "type": 1, + "atoms": [ + 7, + 8 + ], + "stereo": 1 + }, + { + "type": 1, + "atoms": [ + 4, + 2 + ], + "stereo": 1 + }, + { + "type": 1, + "atoms": [ + 5, + 1 + ], + "stereo": 6 + }, + { + "type": 1, + "atoms": [ + 6, + 0 + ], + "stereo": 6 + }, + { + "type": 1, + "atoms": [ + 8, + 9 + ] + }, + { + "type": 1, + "atoms": [ + 2, + 13 + ] + }, + { + "type": 1, + "atoms": [ + 2, + 14 + ] + }, + { + "type": 1, + "atoms": [ + 13, + 15 + ] + }, + { + "type": 2, + "atoms": [ + 13, + 16 + ] + }, + { + "type": 2, + "atoms": [ + 14, + 17 + ] + }, + { + "type": 1, + "atoms": [ + 15, + 18 + ] + }, + { + "type": 2, + "atoms": [ + 18, + 19 + ] + }, + { + "type": 1, + "atoms": [ + 17, + 18 + ] + }, + { + "type": 1, + "atoms": [ + 7, + 3 + ] + }, + { + "type": 1, + "atoms": [ + 17, + 20 + ] + }, + { + "type": 1, + "atoms": [ + 10, + 21 + ] + }, + { + "type": 1, + "atoms": [ + 9, + 10 + ] + } + ] + } +} \ No newline at end of file diff --git a/api/tests/integration/tests/formats/ref/thymine.mol b/api/tests/integration/tests/formats/ref/thymine.mol new file mode 100644 index 0000000000..cedce8dedd --- /dev/null +++ b/api/tests/integration/tests/formats/ref/thymine.mol @@ -0,0 +1,84 @@ + + -INDIGO-01000000002D + + 0 0 0 0 0 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 0 0 0 0 0 +M V30 BEGIN ATOM +M V30 END ATOM +M V30 BEGIN BOND +M V30 END BOND +M V30 END CTAB +M V30 BEGIN TEMPLATE +M V30 TEMPLATE 1 RNA/Thy/T +M V30 BEGIN CTAB +M V30 COUNTS 23 24 3 0 0 +M V30 BEGIN ATOM +M V30 1 O 12.7602 -15.7147 0.0 0 +M V30 2 O 14.0825 -15.2617 0.0 0 +M V30 3 N 14.1088 -12.9483 0.0 0 +M V30 4 O 13.166 -13.3263 0.0 0 +M V30 5 C 13.8445 -13.8248 0.0 0 CFG=2 +M V30 6 C 13.5924 -14.5961 0.0 0 CFG=1 +M V30 7 C 12.7602 -14.5961 0.0 0 CFG=1 +M V30 8 C 12.4972 -13.8138 0.0 0 CFG=1 +M V30 9 C 11.7157 -13.568 0.0 0 +M V30 10 O 11.4665 -12.776 0.0 0 +M V30 11 P 10.4913 -12.376 0.0 0 +M V30 12 O 10.1163 -11.551 0.0 0 +M V30 13 O 10.4913 -13.201 0.0 0 +M V30 14 C 14.9439 -12.6769 0.0 0 +M V30 15 C 13.3625 -12.2866 0.0 0 +M V30 16 N 15.2096 -11.7959 0.0 0 +M V30 17 O 15.6067 -13.3125 0.0 0 +M V30 18 C 13.6281 -11.4059 0.0 0 +M V30 19 C 14.5028 -11.1516 0.0 0 +M V30 20 O 14.767 -10.2755 0.0 0 +M V30 21 C 12.9642 -10.7675 0.0 0 +M V30 22 O 10.5257 -14.0454 0.0 0 +M V30 23 H 12.5598 -14.0454 0.0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 23 +M V30 2 1 8 7 +M V30 3 1 11 12 +M V30 4 1 4 5 +M V30 5 2 11 13 +M V30 6 1 7 6 +M V30 7 1 5 6 +M V30 8 1 8 9 CFG=1 +M V30 9 1 5 3 CFG=1 +M V30 10 1 6 2 CFG=3 +M V30 11 1 7 1 CFG=3 +M V30 12 1 9 10 +M V30 13 1 3 14 +M V30 14 1 3 15 +M V30 15 1 14 16 +M V30 16 2 14 17 +M V30 17 2 15 18 +M V30 18 1 16 19 +M V30 19 2 19 20 +M V30 20 1 18 19 +M V30 21 1 8 4 +M V30 22 1 18 21 +M V30 23 1 11 22 +M V30 24 1 10 11 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEABS ATOMS=(4 5 6 7 8) +M V30 END COLLECTION +M V30 BEGIN SGROUP +M V30 1 SUP 1 ATOMS=(1 22) XBONDS=(1 23) BRKXYZ=(9 -0.017200 0.834700 0.0000- +M V30 00 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000) LABEL=OH CLA- +M V30 SS=LGRP +M V30 2 SUP 2 ATOMS=(1 23) XBONDS=(1 1) BRKXYZ=(9 0.100200 -0.834650 0.00000- +M V30 0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000) LABEL=H CLASS- +M V30 =LGRP +M V30 3 SUP 3 ATOMS=(21 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 2- +M V30 1) XBONDS=(2 1 23) BRKXYZ=(9 -0.100200 0.834650 0.000000 0.017200 -0.8- +M V30 34700 0.000000 0.000000 0.000000 0.000000) LABEL=T CLASS=RNA SAP=(3 11- +M V30 22 Al) SAP=(3 1 23 Br) +M V30 END SGROUP +M V30 END CTAB +M V30 END TEMPLATE +M END diff --git a/api/tests/integration/tests/formats/smarts.py b/api/tests/integration/tests/formats/smarts.py index c676e57d3b..14854c10c1 100755 --- a/api/tests/integration/tests/formats/smarts.py +++ b/api/tests/integration/tests/formats/smarts.py @@ -28,6 +28,32 @@ def test_smarts_load_save(smarts_in): print("smarts_out=%s" % smarts_out) +def test_smarts_load_save_through_ket(smarts_in, expected_str): + m1 = indigo.loadSmarts(smarts_in) + json1 = m1.json() + m2 = indigo.loadQueryMolecule(json1) + smarts_out = m2.smarts() + m3 = indigo.loadSmarts(smarts_out) + json2 = m3.json() + if smarts_in == smarts_out: + print("%s is ok. smarts_in==smarts_out" % smarts_in) + else: + print("smarts_in!=smarts_out") + print(" smarts_in=%s" % smarts_in) + print("smarts_out=%s" % smarts_out) + if json1 == json2: + print("%s is ok. json_in==json_out" % smarts_in) + else: + print("json_in!=json_out") + print(" json_in=%s" % json1) + print("json_out=%s" % json2) + if expected_str in json1: + print("%s is ok. expected string found in json" % smarts_in) + else: + print("%s: expected string not found in json" % smarts_in) + print(json1) + + molstr = """ Ketcher 11241617102D 1 1.00000 0.00000 0 @@ -116,3 +142,13 @@ def test_smarts_load_save(smarts_in): test_smarts_load_save("[O;H]") test_smarts_load_save("[!O;H]") test_smarts_load_save("([#6]1-[#6]-[#6]-1.[#6])") +test_smarts_load_save("[#9]/[#6]=[#6]/[#6]=[#6]/[#6]") +test_smarts_load_save("[#9]\[#6]=[#6]\[#6]=[#6]\[#6]") +expected_str = '"bonds":[{"type":1,"atoms":[0,1],"stereo":1},{"type":2,"atoms":[1,2]},{"type":1,"atoms":[2,3],"stereo":1},{"type":2,"atoms":[3,4]},{"type":1,"atoms":[4,5],"stereo":1}]}}' +test_smarts_load_save_through_ket( + "[#9]/[#6]=[#6]/[#6]=[#6]/[#6]", expected_str +) +expected_str = '"bonds":[{"type":1,"atoms":[0,1],"stereo":6},{"type":2,"atoms":[1,2]},{"type":1,"atoms":[2,3],"stereo":1},{"type":2,"atoms":[3,4]},{"type":1,"atoms":[4,5],"stereo":6}]}}' +test_smarts_load_save_through_ket( + "[#9]\[#6]=[#6]/[#6]=[#6]\[#6]", expected_str +) diff --git a/api/wasm/indigo-ketcher/package.json b/api/wasm/indigo-ketcher/package.json index be8e476753..4271b5eac8 100644 --- a/api/wasm/indigo-ketcher/package.json +++ b/api/wasm/indigo-ketcher/package.json @@ -1,6 +1,6 @@ { "name": "indigo-ketcher", - "version": "1.15.0-dev.1", + "version": "1.15.0-dev.2", "description": "WASM implementation of Indigo organic chemistry toolkit web service for Ketcher", "main": "indigo-ketcher.js", "files": [ diff --git a/bingo/bingo-elastic/java/pom.xml b/bingo/bingo-elastic/java/pom.xml index 4717fe9280..a55077a102 100644 --- a/bingo/bingo-elastic/java/pom.xml +++ b/bingo/bingo-elastic/java/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.epam.indigo bingo-elastic - 1.15.0-dev.1 + 1.15.0-dev.2 jar Bingo Elastic diff --git a/bingo/bingo-elastic/python/bingo_elastic/__init__.py b/bingo/bingo-elastic/python/bingo_elastic/__init__.py index c6198af781..5ebf9a5f9b 100644 --- a/bingo/bingo-elastic/python/bingo_elastic/__init__.py +++ b/bingo/bingo-elastic/python/bingo_elastic/__init__.py @@ -1 +1 @@ -__version__ = "1.15.0.dev1" +__version__ = "1.15.0.dev2" diff --git a/bingo/bingo-elastic/python/setup.py b/bingo/bingo-elastic/python/setup.py index 6042efd0f7..81286bf3fd 100644 --- a/bingo/bingo-elastic/python/setup.py +++ b/bingo/bingo-elastic/python/setup.py @@ -21,7 +21,7 @@ setup( name="bingo_elastic", - version="1.15.0.dev1", + version="1.15.0.dev2", description="Cartridge that provides fast, scalable, and efficient storage and searching solution for chemical information using Elasticsearch", author="Ruslan Khyurri", author_email="ruslan_khyurri@epam.com", @@ -35,7 +35,7 @@ download_url="https://pypi.org/project/bingo_elastic", python_requires=">=3.7", packages=["bingo_elastic", "bingo_elastic.model"], - install_requires=["epam.indigo==1.15.0.dev1", "elasticsearch==7.16.2"], + install_requires=["epam.indigo==1.15.0.dev2", "elasticsearch==7.16.2"], extras_require={ "async": ["elasticsearch[async]==7.16.2"], "dev": [ diff --git a/core/indigo-core/molecule/base_molecule.h b/core/indigo-core/molecule/base_molecule.h index 902cd2a48f..0362900546 100644 --- a/core/indigo-core/molecule/base_molecule.h +++ b/core/indigo-core/molecule/base_molecule.h @@ -73,8 +73,6 @@ namespace indigo _BOND_ANY = 8, _BOND_COORDINATION = 9, _BOND_HYDROGEN = 10, - BOND_SMARTS_UP = 11, - BOND_SMARTS_DOWN = 12, }; enum @@ -84,6 +82,15 @@ namespace indigo BOND_EITHER = 3 }; + enum + { + BIOVIA_STEREO_NO = 0, + BIOVIA_STEREO_UP = 1, + BIOVIA_STEREO_DOUBLE_CISTRANS = 3, + BIOVIA_STEREO_ETHER = 4, + BIOVIA_STEREO_DOWN = 6, + }; + enum layout_orientation_value { UNCPECIFIED, diff --git a/core/indigo-core/molecule/ket_commons.h b/core/indigo-core/molecule/ket_commons.h index 3cfb2935de..b2b070914d 100644 --- a/core/indigo-core/molecule/ket_commons.h +++ b/core/indigo-core/molecule/ket_commons.h @@ -163,7 +163,7 @@ namespace indigo struct KETTextLine { std::string text; - std::map styles; + std::map styles; }; static const std::uint32_t CID = "KET text object"_hash; @@ -178,7 +178,7 @@ namespace indigo if (data.HasMember("blocks")) { Value& blocks = data["blocks"]; - for (int i = 0; i < blocks.Size(); ++i) + for (rapidjson::SizeType i = 0; i < blocks.Size(); ++i) { KETTextLine text_line; if (blocks[i].HasMember("text")) @@ -189,7 +189,7 @@ namespace indigo if (blocks[i].HasMember("inlineStyleRanges")) { Value& style_ranges = blocks[i]["inlineStyleRanges"]; - for (int j = 0; j < style_ranges.Size(); ++j) + for (rapidjson::SizeType j = 0; j < style_ranges.Size(); ++j) { int style_begin = style_ranges[j]["offset"].GetInt(); int style_end = style_begin + style_ranges[j]["length"].GetInt(); diff --git a/core/indigo-core/molecule/molecule_cdxml_loader.h b/core/indigo-core/molecule/molecule_cdxml_loader.h index 1cf0e7a73d..e37445cfa6 100644 --- a/core/indigo-core/molecule/molecule_cdxml_loader.h +++ b/core/indigo-core/molecule/molecule_cdxml_loader.h @@ -54,14 +54,6 @@ namespace indigo class Molecule; class QueryMolecule; - inline bool validate_base64(const std::string& str) - { - if (str.size() & 3) // check for padding - return false; - std::regex base64reg_exp("^[a-zA-Z0-9\\+/]*={0,3}$"); - return std::regex_match(str, base64reg_exp); - } - class AutoInt { public: @@ -113,8 +105,8 @@ namespace indigo struct CdxmlKetTextStyle { - int offset; - int size; + std::size_t offset; + std::size_t size; std::list styles; }; @@ -153,8 +145,8 @@ namespace indigo bool is_not_list; bool has_fragment; std::vector element_list; - std::unordered_map bond_id_to_connection_idx; - std::unordered_map node_id_to_connection_idx; + std::unordered_map bond_id_to_connection_idx; + std::unordered_map node_id_to_connection_idx; std::vector<_ExtConnection> connections; std::vector ext_connections; std::vector inner_nodes; @@ -186,19 +178,6 @@ namespace indigo bool is_superatom; }; - inline std::vector split(const std::string& str, char delim) - { - std::vector strings; - size_t start; - size_t end = 0; - while ((start = str.find_first_not_of(delim, end)) != std::string::npos) - { - end = str.find(delim, start); - strings.push_back(str.substr(start, end - start)); - } - return strings; - } - class CDXProperty { public: @@ -948,9 +927,9 @@ namespace indigo Molecule* _pmol; QueryMolecule* _pqmol; - std::unordered_map _id_to_atom_idx; - std::unordered_map _id_to_node_index; - std::unordered_map _id_to_bond_index; + std::unordered_map _id_to_atom_idx; + std::unordered_map _id_to_node_index; + std::unordered_map _id_to_bond_index; std::vector _fragment_nodes; std::vector _pluses; std::vector, int>> _arrows; diff --git a/core/indigo-core/molecule/molecule_json_loader.h b/core/indigo-core/molecule/molecule_json_loader.h index 0f1d143598..15878faf34 100644 --- a/core/indigo-core/molecule/molecule_json_loader.h +++ b/core/indigo-core/molecule/molecule_json_loader.h @@ -42,6 +42,7 @@ namespace indigo class Molecule; class QueryMolecule; class SGroup; + class Superatom; class MetaObjectsInterface; /* @@ -90,7 +91,7 @@ namespace indigo }; int addAtomToMoleculeQuery(const char* label, int element, int charge, int valence, int radical, int isotope); - int addBondToMoleculeQuery(int beg, int end, int order, int topology = 0); + int addBondToMoleculeQuery(int beg, int end, int order, int topology = 0, int direction = 0); void validateMoleculeBond(int order); void parseAtoms(const rapidjson::Value& atoms, BaseMolecule& mol, std::vector& stereo_centers); void parseBonds(const rapidjson::Value& bonds, BaseMolecule& mol); @@ -100,13 +101,16 @@ namespace indigo void parseProperties(const rapidjson::Value& props, BaseMolecule& mol); void setStereoFlagPosition(const rapidjson::Value& pos, int fragment_index, BaseMolecule& mol); void handleSGroup(SGroup& sgroup, const std::unordered_set& atoms, BaseMolecule& bmol); + void parseMonomerTemplate(const rapidjson::Value& monomer_template, BaseMolecule& mol); private: + void fillXBondsAndBrackets(Superatom& sa, BaseMolecule& mol); rapidjson::Value& _mol_nodes; RGroupDescriptionList _rgroups; rapidjson::Value _meta_objects; rapidjson::Value _mol_array; + rapidjson::Value _templates; Molecule* _pmol; QueryMolecule* _pqmol; std::vector _stereo_centers; diff --git a/core/indigo-core/molecule/molecule_json_saver.h b/core/indigo-core/molecule/molecule_json_saver.h index 3011ebdea7..46c8e0cf7b 100644 --- a/core/indigo-core/molecule/molecule_json_saver.h +++ b/core/indigo-core/molecule/molecule_json_saver.h @@ -179,6 +179,13 @@ namespace indigo void saveMolecule(BaseMolecule& bmol); void saveMolecule(BaseMolecule& bmol, JsonWriter& writer); static void saveMetaData(JsonWriter& writer, MetaDataStorage& meta); + static std::string monomerId(const TGroup& tg); + static std::string monomerAlias(const TGroup& tg); + + static std::string monomerKETClass(const TGroup& tg); + static std::string monomerHELMClass(const TGroup& tg); + static std::string naturalAnalog(const TGroup& tg); + bool add_stereo_desc; bool pretty_json; @@ -187,8 +194,8 @@ namespace indigo void saveBonds(BaseMolecule& mol, JsonWriter& writer); void saveRGroup(PtrPool& fragments, int rgnum, JsonWriter& writer); void saveFragment(BaseMolecule& fragment, JsonWriter& writer); - void saveTGroup(TGroup& tg, JsonWriter& writer); - + void saveMonomerTemplate(TGroup& tg, JsonWriter& writer); + void saveMonomerAttachmentPoints(TGroup& tg, JsonWriter& writer); void saveSGroups(BaseMolecule& mol, JsonWriter& writer); void saveSGroup(SGroup& sgroup, JsonWriter& writer); void saveAttachmentPoint(BaseMolecule& mol, int atom_idx, JsonWriter& writer); diff --git a/core/indigo-core/molecule/monomer_commons.h b/core/indigo-core/molecule/monomer_commons.h new file mode 100644 index 0000000000..5fc8e8cf96 --- /dev/null +++ b/core/indigo-core/molecule/monomer_commons.h @@ -0,0 +1,59 @@ +#ifndef __monomer_commons__ +#define __monomer_commons__ + +#include +#include + +#include "molecule/parse_utils.h" + +namespace indigo +{ + const int kStdMonomerDef = 3; + + const std::string kMonomerClassAA = "AA"; + const std::string kMonomerClassdAA = "dAA"; + const std::string kMonomerClassDNA = "DNA"; + const std::string kMonomerClassRNA = "RNA"; + const std::string kMonomerClassSUGAR = "SUGAR"; + const std::string kMonomerClassBASE = "BASE"; + const std::string kMonomerClassPHOSPHATE = "PHOSPHATE"; + const std::string kMonomerClassAminoAcid = "AminoAcid"; + const std::string kMonomerClassDAminoAcid = "D-AminoAcid"; + + const std::string kPrefix_d("d"); + const std::string kPrefix_r("r"); + + const std::unordered_set kNucleicClasses = {kMonomerClassDNA, kMonomerClassRNA, kMonomerClassSUGAR, kMonomerClassBASE, kMonomerClassPHOSPHATE}; + const std::unordered_set kAminoClasses = {kMonomerClassAA, kMonomerClassdAA, kMonomerClassAminoAcid, kMonomerClassDAminoAcid}; + + inline bool isNucleicClass(const std::string& monomer_class) + { + return kNucleicClasses.find(monomer_class) != kNucleicClasses.end(); + } + + inline bool isAminoAcidClass(const std::string& monomer_class) + { + return kAminoClasses.find(monomer_class) != kAminoClasses.end(); + } + + std::string classToPrefix(const std::string& monomer_class); + + std::string monomerNameByAlias(const std::string& monomer_class, const std::string& alias); + + std::string monomerAliasByName(const std::string& monomer_class, const std::string& name); + + std::string normalizeMonomerName(const std::string& monomer_class, const std::string& name); + + std::string normalizeMonomerAlias(const std::string& monomer_class, const std::string& alias); + + bool isAttachmentPointsInOrder(int order, const std::string& label); + + struct MonomerAttachmentPoint + { + int attachment_atom; + int leaving_group; + std::string id; + }; + +} +#endif \ No newline at end of file diff --git a/core/indigo-core/molecule/parse_utils.h b/core/indigo-core/molecule/parse_utils.h index e4f424ac29..5530aeff76 100644 --- a/core/indigo-core/molecule/parse_utils.h +++ b/core/indigo-core/molecule/parse_utils.h @@ -19,6 +19,7 @@ #ifndef __parse_utils__ #define __parse_utils__ +#include #include #ifdef _WIN32 @@ -30,6 +31,27 @@ namespace indigo { std::string latin1_to_utf8(const std::string& src); bool is_valid_utf8(const std::string& data); + + bool validate_base64(const std::string& str); + + std::vector split(const std::string& str, char delim); + + inline bool is_lower_case(const std::string& str) + { + for (auto c : str) + if (!std::islower(c)) + return false; + return true; + } + + inline bool is_upper_case(const std::string& str) + { + for (auto c : str) + if (!std::isupper(c)) + return false; + return true; + } + } // namespace indigo #ifdef _WIN32 diff --git a/core/indigo-core/molecule/query_molecule.h b/core/indigo-core/molecule/query_molecule.h index 698f4fac1e..a16c94c74e 100644 --- a/core/indigo-core/molecule/query_molecule.h +++ b/core/indigo-core/molecule/query_molecule.h @@ -180,7 +180,7 @@ namespace indigo Atom* clone() const; void copy(const Atom& other); - Atom* child(int idx) const; + Atom* child(int idx); bool valueWithinRange(int value); @@ -228,9 +228,11 @@ namespace indigo public: Bond(); Bond(int type_, int value_); + Bond(int type_, int value_, int direction_); ~Bond() override; int value; + int direction; Bond* clone(); @@ -309,6 +311,11 @@ namespace indigo bool possibleNitrogenV5(int idx); + static std::string getSmartsBondStr(QueryMolecule::Bond* bond); + static void writeSmartsBond(Output& output, QueryMolecule::Bond* bond, bool has_or_parent); + static std::string getSmartsAtomStr(QueryMolecule::Atom* atom); + static void writeSmartsAtom(Output& output, Atom* atom, int aam, int chirality, int depth, bool has_or_parent, bool has_not_parent); + enum QUERY_ATOM { QUERY_ATOM_A, @@ -323,13 +330,6 @@ namespace indigo QUERY_ATOM_NOTLIST, QUERY_ATOM_SINGLE }; - enum QUERY_BOND - { - QUERY_BOND_DOUBLE_OR_AROMATIC = 0, - QUERY_BOND_SINGLE_OR_AROMATIC, - QUERY_BOND_SINGLE_OR_DOUBLE, - QUERY_BOND_ANY - }; static bool isKnownAttr(QueryMolecule::Atom& qa); static bool isNotAtom(QueryMolecule::Atom& qa, int elem); @@ -344,8 +344,10 @@ namespace indigo static bool isOrBond(Bond& qb, int type1, int type2); static bool isSingleOrDouble(Bond& qb); static int getQueryBondType(Bond& qb); + static int getQueryBondType(Bond& qb, int& direction, bool& negative); static int getAtomType(const char* label); static void getQueryAtomLabel(int qa, Array& result); + static QueryMolecule::Bond* createQueryMoleculeBond(int order, int topology, int direction); bool bondStereoCare(int idx) override; void setBondStereoCare(int idx, bool stereo_care); diff --git a/core/indigo-core/molecule/smiles_saver.h b/core/indigo-core/molecule/smiles_saver.h index 8d55b41833..ac47effff1 100644 --- a/core/indigo-core/molecule/smiles_saver.h +++ b/core/indigo-core/molecule/smiles_saver.h @@ -80,9 +80,6 @@ namespace indigo const Array& getSavedCisTransParities(); - static std::string writeSmartsAtomStr(QueryMolecule::Atom* atom); - static std::string writeSmartsBondStr(QueryMolecule::Bond* bond); - protected: void _saveMolecule(); diff --git a/core/indigo-core/molecule/src/cmf_loader.cpp b/core/indigo-core/molecule/src/cmf_loader.cpp index a39509c369..1bb12d5678 100644 --- a/core/indigo-core/molecule/src/cmf_loader.cpp +++ b/core/indigo-core/molecule/src/cmf_loader.cpp @@ -288,7 +288,7 @@ void CmfLoader::_readBond(int& code, _BondDesc& bond) bond.cis_trans = 0; bond.flags = 0; bond.swap = false; - bond.direction = 0; + bond.direction = BOND_ZERO; bond.highlighted = false; if (code == CMF_BOND_SINGLE_CHAIN) diff --git a/core/indigo-core/molecule/src/cml_saver.cpp b/core/indigo-core/molecule/src/cml_saver.cpp index f034b01d4e..c534924da1 100644 --- a/core/indigo-core/molecule/src/cml_saver.cpp +++ b/core/indigo-core/molecule/src/cml_saver.cpp @@ -473,13 +473,13 @@ void CmlSaver::_addMoleculeElement(XMLElement* elem, BaseMolecule& mol, bool que int qb = QueryMolecule::getQueryBondType(qmol->getBond(i)); - if (qb == QueryMolecule::QUERY_BOND_SINGLE_OR_DOUBLE) + if (qb == _BOND_SINGLE_OR_DOUBLE) bond->SetAttribute("queryType", "SD"); - else if (qb == QueryMolecule::QUERY_BOND_SINGLE_OR_AROMATIC) + else if (qb == _BOND_SINGLE_OR_AROMATIC) bond->SetAttribute("queryType", "SA"); - else if (qb == QueryMolecule::QUERY_BOND_DOUBLE_OR_AROMATIC) + else if (qb == _BOND_DOUBLE_OR_AROMATIC) bond->SetAttribute("queryType", "DA"); - else if (qb == QueryMolecule::QUERY_BOND_ANY) + else if (qb == _BOND_ANY) bond->SetAttribute("queryType", "Any"); int indigo_topology = -1; diff --git a/core/indigo-core/molecule/src/inchi_wrapper.cpp b/core/indigo-core/molecule/src/inchi_wrapper.cpp index e20d692c13..c011ab4088 100644 --- a/core/indigo-core/molecule/src/inchi_wrapper.cpp +++ b/core/indigo-core/molecule/src/inchi_wrapper.cpp @@ -261,15 +261,15 @@ void InchiWrapper::parseInchiOutput(const InchiOutput& inchi_output, Molecule& m throw Molecule::Error("Indigo-InChI: ALTERN-typed bonds are not supported"); int bond_idx = mol.addBond(atom_indices[i], atom_indices[nei], bond_order); - if (bond_stereo == 1) + if (bond_stereo == BIOVIA_STEREO_UP) mol.setBondDirection(bond_idx, BOND_UP); - else if (bond_stereo == 6) + else if (bond_stereo == BIOVIA_STEREO_DOWN) mol.setBondDirection(bond_idx, BOND_DOWN); - else if (bond_stereo == 4) + else if (bond_stereo == BIOVIA_STEREO_ETHER) mol.setBondDirection(bond_idx, BOND_EITHER); - else if (bond_stereo == 3) + else if (bond_stereo == BIOVIA_STEREO_DOUBLE_CISTRANS) mol.cis_trans.ignore(bond_idx); - else if (bond_stereo != 0) + else if (bond_stereo != BIOVIA_STEREO_NO) throw Error("unknown number for bond stereo: %d", bond_stereo); } } diff --git a/core/indigo-core/molecule/src/molecule_auto_loader.cpp b/core/indigo-core/molecule/src/molecule_auto_loader.cpp index 925e391074..36fc8c3612 100644 --- a/core/indigo-core/molecule/src/molecule_auto_loader.cpp +++ b/core/indigo-core/molecule/src/molecule_auto_loader.cpp @@ -33,6 +33,7 @@ #include "molecule/molecule_json_loader.h" #include "molecule/molecule_name_parser.h" #include "molecule/molfile_loader.h" +#include "molecule/parse_utils.h" #include "molecule/query_molecule.h" #include "molecule/sdf_loader.h" #include "molecule/smiles_loader.h" diff --git a/core/indigo-core/molecule/src/molecule_cdxml_saver.cpp b/core/indigo-core/molecule/src/molecule_cdxml_saver.cpp index 1ab476b375..82ceb6b08a 100644 --- a/core/indigo-core/molecule/src/molecule_cdxml_saver.cpp +++ b/core/indigo-core/molecule/src/molecule_cdxml_saver.cpp @@ -22,6 +22,7 @@ #include "molecule/elements.h" #include "molecule/molecule.h" #include "molecule/molecule_cdxml_loader.h" +#include "molecule/parse_utils.h" #include "molecule/query_molecule.h" #include diff --git a/core/indigo-core/molecule/src/molecule_json_loader.cpp b/core/indigo-core/molecule/src/molecule_json_loader.cpp index 5683a99202..ed626ed934 100644 --- a/core/indigo-core/molecule/src/molecule_json_loader.cpp +++ b/core/indigo-core/molecule/src/molecule_json_loader.cpp @@ -11,6 +11,7 @@ #include "molecule/ket_commons.h" #include "molecule/molecule.h" #include "molecule/molecule_sgroups.h" +#include "molecule/monomer_commons.h" #include "molecule/query_molecule.h" #include "molecule/smiles_loader.h" @@ -21,13 +22,14 @@ using namespace std; IMPL_ERROR(MoleculeJsonLoader, "molecule json loader"); MoleculeJsonLoader::MoleculeJsonLoader(Document& ket) - : _mol_array(kArrayType), _mol_nodes(_mol_array), _meta_objects(kArrayType), _pmol(0), _pqmol(0), ignore_noncritical_query_features(false), - components_count(0) + : _mol_array(kArrayType), _mol_nodes(_mol_array), _meta_objects(kArrayType), _templates(kArrayType), _pmol(0), _pqmol(0), + ignore_noncritical_query_features(false), components_count(0) { Value& root = ket["root"]; Value& nodes = root["nodes"]; + // rewind to first molecule node - for (int i = 0; i < nodes.Size(); ++i) + for (rapidjson::SizeType i = 0; i < nodes.Size(); ++i) { if (nodes[i].HasMember("$ref")) { @@ -54,40 +56,31 @@ MoleculeJsonLoader::MoleculeJsonLoader(Document& ket) else throw Error("Unsupported node for molecule"); } + + if (root.HasMember("templates")) + { + Value& templates = root["templates"]; + for (int i = 0; i < templates.Size(); ++i) + { + std::string template_name = templates[i]["$ref"].GetString(); + if (ket.HasMember(template_name.c_str())) + { + Value& template_node = ket[template_name.c_str()]; + _templates.PushBack(template_node, ket.GetAllocator()); + } + } + } } MoleculeJsonLoader::MoleculeJsonLoader(Value& mol_nodes) - : _mol_nodes(mol_nodes), _meta_objects(kArrayType), _pmol(0), _pqmol(0), ignore_noncritical_query_features(false), ignore_no_chiral_flag(false), - skip_3d_chirality(false), treat_x_as_pseudoatom(false), treat_stereo_as(0), components_count(0) + : _mol_nodes(mol_nodes), _meta_objects(kArrayType), _templates(kArrayType), _pmol(0), _pqmol(0), ignore_noncritical_query_features(false), + ignore_no_chiral_flag(false), skip_3d_chirality(false), treat_x_as_pseudoatom(false), treat_stereo_as(0), components_count(0) { } -int MoleculeJsonLoader::addBondToMoleculeQuery(int beg, int end, int order, int topology) +int MoleculeJsonLoader::addBondToMoleculeQuery(int beg, int end, int order, int topology, int direction) { - std::unique_ptr bond; - if (order == BOND_SINGLE || order == BOND_DOUBLE || order == BOND_TRIPLE || order == BOND_AROMATIC || order == _BOND_COORDINATION || - order == _BOND_HYDROGEN) - bond = std::make_unique(QueryMolecule::BOND_ORDER, order); - else if (order == _BOND_SINGLE_OR_DOUBLE) - bond.reset(QueryMolecule::Bond::und(QueryMolecule::Bond::nicht(new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, BOND_AROMATIC)), - QueryMolecule::Bond::oder(new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, BOND_SINGLE), - new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, BOND_DOUBLE)))); - else if (order == _BOND_SINGLE_OR_AROMATIC) - bond.reset(QueryMolecule::Bond::oder(new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, BOND_SINGLE), - new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, BOND_AROMATIC))); - else if (order == _BOND_DOUBLE_OR_AROMATIC) - bond.reset(QueryMolecule::Bond::oder(new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, BOND_DOUBLE), - new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, BOND_AROMATIC))); - else if (order == _BOND_ANY) - bond = std::make_unique(); - else - throw Error("unknown bond type: %d", order); - if (topology != 0) - { - bond.reset( - QueryMolecule::Bond::und(bond.release(), new QueryMolecule::Bond(QueryMolecule::BOND_TOPOLOGY, topology == 1 ? TOPOLOGY_RING : TOPOLOGY_CHAIN))); - } - return _pqmol->addBond(beg, end, bond.release()); + return _pqmol->addBond(beg, end, QueryMolecule::createQueryMoleculeBond(order, topology, direction)); } int MoleculeJsonLoader::addAtomToMoleculeQuery(const char* label, int element, int charge, int valence, int radical, int isotope) @@ -282,7 +275,7 @@ void MoleculeJsonLoader::parseAtoms(const rapidjson::Value& atoms, BaseMolecule& const Value& elements = a["elements"]; int pseudo_count = 0; elem = ELEM_ATOMLIST; - for (int j = 0; j < elements.Size(); ++j) + for (rapidjson::SizeType j = 0; j < elements.Size(); ++j) { auto elem_label = elements[j].GetString(); int list_elem = Element::fromString2(elem_label); @@ -659,25 +652,31 @@ void MoleculeJsonLoader::parseBonds(const rapidjson::Value& bonds, BaseMolecule& int a1 = refs[0].GetInt(); int a2 = refs[1].GetInt(); int bond_idx = 0; - bond_idx = _pmol ? _pmol->addBond_Silent(a1, a2, order) : addBondToMoleculeQuery(a1, a2, order, topology); + int direction = BOND_ZERO; + if (_pqmol && stereo && order == BOND_SINGLE) + { + if (stereo == BIOVIA_STEREO_UP) + direction = BOND_UP; + else if (stereo == BIOVIA_STEREO_DOWN) + direction = BOND_DOWN; + } + bond_idx = _pmol ? _pmol->addBond_Silent(a1, a2, order) : addBondToMoleculeQuery(a1, a2, order, topology, direction); if (stereo) { switch (stereo) { - case 1: + case BIOVIA_STEREO_UP: mol.setBondDirection(bond_idx, BOND_UP); break; - case 3: + case BIOVIA_STEREO_DOUBLE_CISTRANS: mol.cis_trans.ignore(bond_idx); break; - case 4: + case BIOVIA_STEREO_ETHER: mol.setBondDirection(bond_idx, BOND_EITHER); break; - case 6: + case BIOVIA_STEREO_DOWN: mol.setBondDirection(bond_idx, BOND_DOWN); break; - break; - default: break; } @@ -713,7 +712,7 @@ void MoleculeJsonLoader::parseBonds(const rapidjson::Value& bonds, BaseMolecule& void indigo::MoleculeJsonLoader::parseHighlight(const rapidjson::Value& highlight, BaseMolecule& mol) { - for (int i = 0; i < highlight.Size(); ++i) + for (rapidjson::SizeType i = 0; i < highlight.Size(); ++i) { const rapidjson::Value& val = highlight[i]; if (val.HasMember("entityType") && val.HasMember("items")) @@ -722,12 +721,12 @@ void indigo::MoleculeJsonLoader::parseHighlight(const rapidjson::Value& highligh std::string et = val["entityType"].GetString(); if (et == "atoms") { - for (int j = 0; i < items.Size(); ++i) + for (rapidjson::SizeType j = 0; i < items.Size(); ++i) mol.highlightAtom(items[i].GetInt()); } else if (et == "bonds") { - for (int j = 0; i < items.Size(); ++i) + for (rapidjson::SizeType j = 0; i < items.Size(); ++i) mol.highlightBond(items[i].GetInt()); } } @@ -736,7 +735,7 @@ void indigo::MoleculeJsonLoader::parseHighlight(const rapidjson::Value& highligh void indigo::MoleculeJsonLoader::parseSelection(const rapidjson::Value& selection, BaseMolecule& mol) { - for (int i = 0; i < selection.Size(); ++i) + for (rapidjson::SizeType i = 0; i < selection.Size(); ++i) { const rapidjson::Value& val = selection[i]; if (val.HasMember("entityType") && val.HasMember("items")) @@ -745,12 +744,12 @@ void indigo::MoleculeJsonLoader::parseSelection(const rapidjson::Value& selectio std::string et = val["entityType"].GetString(); if (et == "atoms") { - for (int j = 0; i < items.Size(); ++i) + for (rapidjson::SizeType j = 0; i < items.Size(); ++i) mol.selectAtom(items[i].GetInt()); } else if (et == "bonds") { - for (int j = 0; i < items.Size(); ++i) + for (rapidjson::SizeType j = 0; i < items.Size(); ++i) mol.selectBond(items[i].GetInt()); } } @@ -871,7 +870,7 @@ void MoleculeJsonLoader::parseSGroups(const rapidjson::Value& sgroups, BaseMolec { _pqmol->components.expandFill(_pqmol->components.size() + atoms.Size(), 0); components_count++; - for (int j = 0; j < atoms.Size(); ++j) + for (rapidjson::SizeType j = 0; j < atoms.Size(); ++j) { int atom_idx = atoms[j].GetInt(); _pqmol->components[atom_idx] = components_count; @@ -886,7 +885,7 @@ void MoleculeJsonLoader::parseSGroups(const rapidjson::Value& sgroups, BaseMolec SGroup& sgroup = mol.sgroups.getSGroup(grp_idx); // add atoms std::unordered_set sgroup_atoms; - for (int j = 0; j < atoms.Size(); ++j) + for (rapidjson::SizeType j = 0; j < atoms.Size(); ++j) { int atom_idx = atoms[j].GetInt(); sgroup.atoms.push(atom_idx); @@ -1032,7 +1031,7 @@ void MoleculeJsonLoader::parseSGroups(const rapidjson::Value& sgroups, BaseMolec if (s.HasMember("bonds")) { const Value& bonds = s["bonds"]; - for (int j = 0; j < bonds.Size(); ++j) + for (rapidjson::SizeType j = 0; j < bonds.Size(); ++j) { sgroup.bonds.push(bonds[j].GetInt()); } @@ -1051,14 +1050,213 @@ void MoleculeJsonLoader::parseProperties(const rapidjson::Value& props, BaseMole } } +void MoleculeJsonLoader::fillXBondsAndBrackets(Superatom& sa, BaseMolecule& mol) +{ + std::unordered_set atoms; + std::vector brackets; + for (auto val : sa.atoms) + atoms.insert(val); + + // fill crossing bonds + + for (auto src_atom : sa.atoms) + { + const auto& vx = mol.getVertex(src_atom); + const auto& src_pos = mol.getAtomXyz(src_atom); + for (int i = vx.neiBegin(); i != vx.neiEnd(); i = vx.neiNext(i)) + { + auto target_atom = vx.neiVertex(i); + if (atoms.find(target_atom) == atoms.end()) + { + const auto& target_pos = mol.getAtomXyz(target_atom); + sa.bonds.push(vx.neiEdge(i)); + brackets.emplace_back((target_pos.x - src_pos.x) / 2, (target_pos.y - src_pos.y) / 2); + } + } + } + + // fill brackets + + for (int i = 0; i < brackets.size(); i += 2) + { + Vec2f* brk_pos = sa.brackets.push(); + brk_pos[0].copy(brackets[i]); + if (i + 1 == brackets.size()) + brk_pos[1].set(0, 0); + else + brk_pos[1].copy(brackets[i + 1]); + } +} + +void MoleculeJsonLoader::parseMonomerTemplate(const rapidjson::Value& monomer_template, BaseMolecule& mol) +{ + auto tg_idx = mol.tgroups.addTGroup(); + TGroup& tg = mol.tgroups.getTGroup(tg_idx); + tg.tgroup_id = tg_idx + 1; + Value one_tgroup(kArrayType); + Document data; + rapidjson::Value monomer_template_cp; + monomer_template_cp.CopyFrom(monomer_template, data.GetAllocator()); + one_tgroup.PushBack(monomer_template_cp, data.GetAllocator()); + MoleculeJsonLoader loader(one_tgroup); + loader.stereochemistry_options = stereochemistry_options; + tg.fragment.reset(mol.neu()); + loader.loadMolecule(*tg.fragment); + auto& monomer_mol = *tg.fragment; + std::string mclass, alias, natreplace; + std::unordered_set leaving_atoms; + if (monomer_template.HasMember("id")) + { + std::string id = monomer_template["id"].GetString(); + auto id_vecs = split(id, '_'); + tg.tgroup_name.appendString(id_vecs.front().c_str(), true); + if (monomer_template.HasMember("class")) + { + mclass = monomer_template["class"].GetString(); + if (mclass == kMonomerClassAminoAcid) + mclass = kMonomerClassAA; + else if (mclass == kMonomerClassDAminoAcid) + mclass = kMonomerClassdAA; + else + std::transform(mclass.begin(), mclass.end(), mclass.begin(), ::toupper); + + if (monomer_template.HasMember("naturalAnalog")) + { + std::string analog_alias = monomerAliasByName(mclass, monomer_template["naturalAnalog"].GetString()); + std::string natrep_class = mclass == kMonomerClassdAA ? kMonomerClassAA : mclass; + natreplace = natrep_class + "/" + analog_alias; + tg.tgroup_natreplace.appendString(natreplace.c_str(), true); + } + + tg.tgroup_class.appendString(mclass.c_str(), true); + if (monomer_template.HasMember("alias")) + { + alias = monomer_template["alias"].GetString(); + if (mclass == kMonomerClassdAA && alias.find(kPrefix_d) == 0) + { + alias.erase(0, 1); + mclass = kMonomerClassAA; + } + tg.tgroup_alias.appendString(alias.c_str(), true); + } + } + + if (monomer_template.HasMember("attachmentPoints")) + { + auto& att_points = monomer_template["attachmentPoints"]; + std::vector attachment_descs; + for (SizeType i = 0; i < att_points.Size(); i++) + { + auto& ap = att_points[i]; + std::string att_label(1, 'A' + i); + MonomerAttachmentPoint att_desc = {-1, -1, att_label + (i > 0 ? (i > 1 ? 'x' : 'r') : 'l')}; + if (ap.HasMember("leavingGroup")) + { + int grp_idx = monomer_mol.sgroups.addSGroup(SGroup::SG_TYPE_SUP); + auto& sa = (Superatom&)monomer_mol.sgroups.getSGroup(grp_idx); + auto& atoms = ap["leavingGroup"]["atoms"]; + std::string group_name; + for (SizeType j = 0; j < atoms.Size(); j++) + { + auto la = atoms[j].GetInt(); + sa.atoms.push(la); + leaving_atoms.insert(la); + auto total_h = monomer_mol.getAtomTotalH(la); + Array label; + monomer_mol.getAtomSymbol(la, label); + if (label.size()) + { + group_name += label.ptr(); + if (total_h) + { + group_name += 'H'; + if (total_h > 1) + group_name += std::to_string(total_h); + } + } + } + sa.sa_class.appendString("LGRP", true); + sa.subscript.appendString(group_name.c_str(), true); + + att_desc.leaving_group = grp_idx; + fillXBondsAndBrackets(sa, monomer_mol); + } + + if (ap.HasMember("attachmentAtom")) + att_desc.attachment_atom = ap["attachmentAtom"].GetInt(); + + if (ap.HasMember("label")) + { + std::string label = ap["label"].GetString(); + if (label.size() > 1) + { + if (label == "R1") + att_desc.id = "Al"; + else if (label == "R2") + att_desc.id = "Br"; + else + { + if (label[0] == 'R') + { + auto rnum = label.substr(1); + if (std::all_of(rnum.begin(), rnum.end(), ::isdigit)) + { + label = 'A' + std::stol(rnum); + label += 'x'; + } + } + } + } + att_desc.id = label; + } + attachment_descs.push_back(att_desc); + } + + int grp_idx = monomer_mol.sgroups.addSGroup(SGroup::SG_TYPE_SUP); + auto& sa = (Superatom&)monomer_mol.sgroups.getSGroup(grp_idx); + + if (mclass.size()) + sa.sa_class.appendString(mclass.c_str(), true); + + if (alias.size()) + sa.subscript.appendString(alias.c_str(), true); + + if (natreplace.size()) + sa.sa_natreplace.appendString(natreplace.c_str(), true); + + for (const auto& att_desc : attachment_descs) + { + int atp_index = sa.attachment_points.add(); + auto& atp = sa.attachment_points[atp_index]; + atp.aidx = att_desc.attachment_atom; + if (atp.lvidx >= 0) + { + auto& lgrp = (Superatom&)monomer_mol.sgroups.getSGroup(att_desc.leaving_group); + if (lgrp.atoms.size()) + atp.lvidx = lgrp.atoms[0]; + } + atp.apid.appendString(att_desc.id.c_str(), true); + } + + for (int i = monomer_mol.vertexBegin(); i != monomer_mol.vertexEnd(); i = monomer_mol.edgeNext(i)) + { + if (leaving_atoms.find(i) == leaving_atoms.end()) + sa.atoms.push(i); + } + + fillXBondsAndBrackets(sa, monomer_mol); + } + } +} + void MoleculeJsonLoader::loadMolecule(BaseMolecule& mol, bool load_arrows) { - for (int node_idx = 0; node_idx < _mol_nodes.Size(); ++node_idx) + for (rapidjson::SizeType node_idx = 0; node_idx < _mol_nodes.Size(); ++node_idx) { std::vector stereo_centers; std::unique_ptr pmol(mol.neu()); - _pmol = NULL; - _pqmol = NULL; + _pmol = nullptr; + _pqmol = nullptr; if (pmol->isQueryMolecule()) { _pqmol = &pmol->asQueryMolecule(); @@ -1070,6 +1268,7 @@ void MoleculeJsonLoader::loadMolecule(BaseMolecule& mol, bool load_arrows) mol.original_format = BaseMolecule::KET; auto& mol_node = _mol_nodes[node_idx]; + if (mol_node.HasMember("atoms")) { // parse atoms @@ -1154,6 +1353,14 @@ void MoleculeJsonLoader::loadMolecule(BaseMolecule& mol, bool load_arrows) } } + for (SizeType i = 0; i < _templates.Size(); i++) + { + auto& mt = _templates[i]; + int tp = mt.GetType(); + if (mt.HasMember("type") && mt["type"].GetString() == std::string("monomerTemplate")) + parseMonomerTemplate(mt, mol); + } + std::vector ignore_cistrans(mol.edgeCount()); std::vector sensible_bond_directions(mol.edgeCount()); for (int i = 0; i < mol.edgeCount(); i++) @@ -1205,7 +1412,7 @@ void MoleculeJsonLoader::loadMolecule(BaseMolecule& mol, bool load_arrows) { if (stereochemistry_options.ignore_errors) mol.addStereocentersIgnoreBad(sc._atom_idx, sc._type, sc._group, false); // add non-valid stereocenters - else + else if (!_pqmol) throw Error("stereo type specified for atom #%d, but the bond " "directions does not say that it is a stereocenter", sc._atom_idx); @@ -1218,7 +1425,7 @@ void MoleculeJsonLoader::loadMolecule(BaseMolecule& mol, bool load_arrows) { if (mol.getBondDirection(i) > 0 && !sensible_bond_directions[i]) { - if (!stereochemistry_options.ignore_errors) + if (!stereochemistry_options.ignore_errors && !_pqmol) throw Error("direction of bond #%d makes no sense", i); } } @@ -1255,7 +1462,7 @@ void MoleculeJsonLoader::loadMetaObjects(rapidjson::Value& meta_objects, MetaDat if (meta_objects.IsArray()) { - for (int obj_idx = 0; obj_idx < meta_objects.Size(); ++obj_idx) + for (rapidjson::SizeType obj_idx = 0; obj_idx < meta_objects.Size(); ++obj_idx) { std::string node_type = meta_objects[obj_idx]["type"].GetString(); auto& mobj = meta_objects[obj_idx]; diff --git a/core/indigo-core/molecule/src/molecule_json_saver.cpp b/core/indigo-core/molecule/src/molecule_json_saver.cpp index 1ae440b129..7a7fe8490e 100644 --- a/core/indigo-core/molecule/src/molecule_json_saver.cpp +++ b/core/indigo-core/molecule/src/molecule_json_saver.cpp @@ -25,8 +25,13 @@ #include "molecule/molecule_cip_calculator.h" #include "molecule/molecule_json_saver.h" #include "molecule/molecule_savers.h" +#include "molecule/molecule_substructure_matcher.h" +#include "molecule/monomer_commons.h" +#include "molecule/parse_utils.h" #include "molecule/query_molecule.h" +#include "molecule/smiles_loader.h" #include "molecule/smiles_saver.h" +#include using namespace indigo; using namespace rapidjson; @@ -303,7 +308,7 @@ void MoleculeJsonSaver::saveSGroup(SGroup& sgroup, JsonWriter& writer) { writer.StartObject(); auto& atp = sa.attachment_points[i]; - std::string atp_id_str(atp.apid.ptr(), atp.apid.size()); + std::string atp_id_str(atp.apid.ptr()); writer.Key("attachmentAtom"); writer.Int(atp.aidx); if (atp.lvidx != -1) @@ -412,41 +417,51 @@ void MoleculeJsonSaver::saveBonds(BaseMolecule& mol, JsonWriter& writer) { for (auto i : mol.edges()) { + int direction = BOND_ZERO; + bool negative = false; writer.StartObject(); writer.Key("type"); - int bond_order = mol.getBondOrder(i); - if (bond_order < 0 && _pqmol) + if (_pmol) { - QueryMolecule::Bond& qbond = _pqmol->getBond(i); - int qb = QueryMolecule::getQueryBondType(qbond); - if (qb == QueryMolecule::QUERY_BOND_SINGLE_OR_DOUBLE) - bond_order = 5; - else if (qb == QueryMolecule::QUERY_BOND_SINGLE_OR_AROMATIC) - bond_order = 6; - else if (qb == QueryMolecule::QUERY_BOND_DOUBLE_OR_AROMATIC) - bond_order = 7; - else if (qb == QueryMolecule::QUERY_BOND_ANY) - bond_order = 8; - if (bond_order < 0) + int bond_order = mol.getBondOrder(i); + + if (bond_order == BOND_ZERO && _pmol) { - // throw Error("Invalid query bond"); + bond_order = _BOND_COORDINATION; + const Edge& edge = mol.getEdge(i); + if ((_pmol->getAtomNumber(edge.beg) == ELEM_H) || (_pmol->getAtomNumber(edge.end) == ELEM_H)) + bond_order = _BOND_HYDROGEN; + } - std::string customQuery = SmilesSaver::writeSmartsBondStr(&qbond); + writer.Uint(bond_order); + } + else if (_pqmol) + { + QueryMolecule::Bond& qbond = _pqmol->getBond(i); + int bond_order = QueryMolecule::getQueryBondType(qbond, direction, negative); + if (bond_order < 0 || negative) + { + writer.Uint(BOND_SINGLE); + std::string customQuery = QueryMolecule::getSmartsBondStr(&qbond); writer.Key("customQuery"); writer.String(customQuery.c_str()); } + else + { + writer.Uint(bond_order); + // convert direction to Biovia constants, to override stereo later + switch (direction) + { + case BOND_UP: + direction = BIOVIA_STEREO_UP; + break; + case BOND_DOWN: + direction = BIOVIA_STEREO_DOWN; + break; + } + } } - if (bond_order == BOND_ZERO && _pmol) - { - bond_order = 9; - const Edge& edge = mol.getEdge(i); - if ((_pmol->getAtomNumber(edge.beg) == ELEM_H) || (_pmol->getAtomNumber(edge.end) == ELEM_H)) - bond_order = 10; - } - - writer.Uint(bond_order); - int topology = -1; if (_pqmol) { @@ -482,24 +497,24 @@ void MoleculeJsonSaver::saveBonds(BaseMolecule& mol, JsonWriter& writer) switch (stereo) { case BOND_UP: - stereo = 1; + stereo = BIOVIA_STEREO_UP; break; case BOND_EITHER: - stereo = 4; + stereo = BIOVIA_STEREO_ETHER; break; case BOND_DOWN: - stereo = 6; + stereo = BIOVIA_STEREO_DOWN; break; default: { - stereo = 0; + stereo = BIOVIA_STEREO_NO; } break; } - if (stereo) + if (stereo || direction) { writer.Key("stereo"); - writer.Uint(stereo); + writer.Uint(direction ? direction : stereo); // If have stored direction - override calculated } auto cip = mol.getBondCIP(i); @@ -800,7 +815,7 @@ void MoleculeJsonSaver::saveAtoms(BaseMolecule& mol, JsonWriter& writer) if (needCustomQuery) { QueryMolecule::Atom& atom = _pqmol->getAtom(i); - std::string customQuery = SmilesSaver::writeSmartsAtomStr(&atom); + std::string customQuery = QueryMolecule::getSmartsAtomStr(&atom); writer.Key("customQuery"); writer.String(customQuery.c_str()); } @@ -1016,43 +1031,206 @@ void MoleculeJsonSaver::saveAtoms(BaseMolecule& mol, JsonWriter& writer) } } -void MoleculeJsonSaver::saveTGroup(TGroup& tg, JsonWriter& writer) +std::string MoleculeJsonSaver::monomerId(const TGroup& tg) { - QS_DEF(Array, buf); - ArrayOutput out(buf); - buf.clear(); - out.printf("tg%d", tg.tgroup_id); - buf.push(0); - writer.Key(buf.ptr()); + std::string name; + std::string monomer_class; + if (tg.tgroup_name.ptr()) + name = tg.tgroup_name.ptr(); + if (tg.tgroup_class.ptr()) + monomer_class = tg.tgroup_class.ptr(); + if (name.size()) + name = monomerNameByAlias(monomer_class, name) + "_" + std::to_string(tg.tgroup_id); + else + name = std::string("#") + std::to_string(tg.tgroup_id); + return name; +} + +std::string MoleculeJsonSaver::monomerHELMClass(const TGroup& tg) +{ + auto mclass = std::string(tg.tgroup_class.ptr()); + if (kAminoClasses.find(mclass) != kAminoClasses.end()) + return "PEPTIDE"; + if (kNucleicClasses.find(mclass) != kNucleicClasses.end()) + return "RNA"; + return "CHEM"; +} + +std::string MoleculeJsonSaver::monomerKETClass(const TGroup& tg) +{ + auto mclass = std::string(tg.tgroup_class.ptr()); + if (mclass == "AA") + return "AminoAcid"; + + if (mclass == "dAA") + return "D-AminoAcid"; + + if (mclass == "RNA" || mclass == "DNA" || mclass.find("MOD") == 0 || mclass.find("XLINK") == 0) + return mclass; + + for (auto it = mclass.begin(); it < mclass.end(); ++it) + *it = it > mclass.begin() ? std::tolower(*it) : std::toupper(*it); + + return mclass; +} + +std::string MoleculeJsonSaver::naturalAnalog(const TGroup& tg) +{ + std::string res; + if (tg.tgroup_natreplace.ptr()) + { + auto nat_replace = split(std::string(tg.tgroup_natreplace.ptr()), '/'); + if (nat_replace.size() > 1) + res = normalizeMonomerName(nat_replace.front(), nat_replace[1]); + } + return res; +} + +std::string MoleculeJsonSaver::monomerAlias(const TGroup& tg) +{ + std::string monomer_class; + std::string alias; + std::string name; + + if (tg.tgroup_class.ptr()) + monomer_class = tg.tgroup_class.ptr(); + + if (tg.tgroup_alias.ptr()) + alias = tg.tgroup_alias.ptr(); + + if (tg.tgroup_name.ptr()) + name = tg.tgroup_name.ptr(); + + if (alias.size()) + alias = normalizeMonomerAlias(monomer_class, alias); + else + { + if (name.size() == 1) + alias = std::toupper(name[0]); + else + alias = monomerId(tg); + } + return alias; +} + +void MoleculeJsonSaver::saveMonomerTemplate(TGroup& tg, JsonWriter& writer) +{ + std::string template_name("monomerTemplate-"); + std::string tg_name(monomerId(tg)); + std::string template_class(monomerKETClass(tg)); + std::string helm_class(monomerHELMClass(tg)); + template_name += tg_name; + writer.Key(template_name.c_str()); writer.StartObject(); writer.Key("type"); - writer.String("tgroup"); - writer.Key("name"); - writer.String(tg.tgroup_name.ptr()); + writer.String("monomerTemplate"); + writer.Key("id"); + writer.String(tg_name.c_str()); if (tg.tgroup_class.size()) { writer.Key("class"); - writer.String(tg.tgroup_class.ptr()); - } - if (tg.tgroup_alias.size()) - { - writer.Key("alias"); - writer.String(tg.tgroup_alias.ptr()); + writer.String(template_class.c_str()); + writer.Key("classHELM"); + writer.String(helm_class.c_str()); } - if (tg.tgroup_natreplace.size()) + + writer.Key("alias"); + writer.String(monomerAlias(tg).c_str()); + + auto analog = naturalAnalog(tg); + if (analog.size()) { - writer.Key("natreplace"); - writer.String(tg.tgroup_natreplace.ptr()); + writer.Key("naturalAnalog"); + writer.String(analog.c_str()); + auto nat_alias = monomerAliasByName(template_class, analog); + if (nat_alias.size() < analog.size()) + { + writer.Key("naturalAnalogShort"); + writer.String(nat_alias.c_str()); + } } + if (tg.tgroup_comment.size()) { writer.Key("comment"); writer.String(tg.tgroup_comment.ptr()); } + + saveMonomerAttachmentPoints(tg, writer); saveFragment(*tg.fragment, writer); writer.EndObject(); } +void MoleculeJsonSaver::saveMonomerAttachmentPoints(TGroup& tg, JsonWriter& writer) +{ + auto& sgroups = tg.fragment->sgroups; + sgroups.getSGroupCount(); + for (int j = sgroups.begin(); j != sgroups.end(); j = sgroups.next(j)) + { + SGroup& sg = sgroups.getSGroup(j); + if (sg.sgroup_type == SGroup::SG_TYPE_SUP) + { + auto& sa = (Superatom&)sg; + std::map sorted_attachment_points; + if (sa.attachment_points.size()) + { + for (int i = sa.attachment_points.begin(); i != sa.attachment_points.end(); i = sa.attachment_points.next(i)) + { + auto& atp = sa.attachment_points[i]; + std::string atp_id_str(atp.apid.ptr()); + if (atp_id_str.size()) + sorted_attachment_points.insert(std::make_pair(atp_id_str, i)); + } + + if (sorted_attachment_points.size()) + { + writer.Key("attachmentPoints"); + writer.StartArray(); + int order = 0; + for (const auto& kvp : sorted_attachment_points) + { + writer.StartObject(); + auto& atp = sa.attachment_points[kvp.second]; + std::string atp_id_str(atp.apid.ptr()); + if (!isAttachmentPointsInOrder(order++, atp_id_str)) + { + writer.Key("type"); + if (atp_id_str == "Al" || atp_id_str == "R1") + writer.String("left"); + else if (atp_id_str == "Br" || atp_id_str == "R2") + writer.String("right"); + else + writer.String("side"); + writer.Key("label"); + if (::isupper(atp_id_str[0]) && atp_id_str.size() == 2) + { + if (atp_id_str == "Al") + atp_id_str = "R1"; + else if (atp_id_str == "Br") + atp_id_str = "R2"; + else if (atp_id_str[1] == 'x') + atp_id_str = std::string("R") + std::to_string(atp_id_str[0] - 'A' + 1); + } + writer.String(atp_id_str.c_str()); + } + writer.Key("attachmentAtom"); + writer.Int(atp.aidx); + writer.Key("leavingGroup"); + writer.StartObject(); + writer.Key("atoms"); + writer.StartArray(); + writer.Int(atp.lvidx); + writer.EndArray(); + writer.EndObject(); + writer.EndObject(); + } + writer.EndArray(); + } + } + sgroups.remove(j); + } + } +} void MoleculeJsonSaver::saveRGroup(PtrPool& fragments, int rgnum, JsonWriter& writer) { QS_DEF(Array, buf); @@ -1166,37 +1344,33 @@ void MoleculeJsonSaver::saveMolecule(BaseMolecule& bmol, JsonWriter& writer) writer.EndObject(); } - for (int i = mol->tgroups.begin(); i != mol->tgroups.end(); i = mol->tgroups.next(i)) + writer.EndArray(); // nodes + + if (mol->tgroups.getTGroupCount()) { - TGroup& tg = mol->tgroups.getTGroup(i); - buf.clear(); - out.printf("tg%d", i); - buf.push(0); - writer.StartObject(); - writer.Key("$ref"); - writer.String(buf.ptr()); - writer.EndObject(); + writer.Key("templates"); + writer.StartArray(); + + for (int i = mol->tgroups.begin(); i != mol->tgroups.end(); i = mol->tgroups.next(i)) + { + TGroup& tg = mol->tgroups.getTGroup(i); + auto template_name = std::string("monomerTemplate-") + monomerId(tg); + writer.StartObject(); + writer.Key("$ref"); + writer.String(template_name.c_str()); + writer.EndObject(); + } + writer.EndArray(); // templates } - writer.EndArray(); // nodes writer.EndObject(); // root for (int idx = 0; idx < mol->countComponents(s_neighbors); idx++) { - _pmol = nullptr; - _pqmol = nullptr; Filter filt(mol->getDecomposition().ptr(), Filter::EQ, idx); std::unique_ptr component(mol->neu()); component->makeSubmolecule(*mol, filt, NULL, NULL); - if (component->isQueryMolecule()) - _pqmol = &component->asQueryMolecule(); - else - _pmol = &component->asMolecule(); - - if (_pmol) - _pmol->setIgnoreBadValenceFlag(true); - if (component->vertexCount()) { std::string mol_node = std::string("mol") + std::to_string(idx); @@ -1233,7 +1407,7 @@ void MoleculeJsonSaver::saveMolecule(BaseMolecule& bmol, JsonWriter& writer) for (int i = mol->tgroups.begin(); i != mol->tgroups.end(); i = mol->tgroups.next(i)) { TGroup& tg = mol->tgroups.getTGroup(i); - saveTGroup(tg, writer); + saveMonomerTemplate(tg, writer); } writer.EndObject(); @@ -1241,6 +1415,16 @@ void MoleculeJsonSaver::saveMolecule(BaseMolecule& bmol, JsonWriter& writer) void MoleculeJsonSaver::saveFragment(BaseMolecule& fragment, JsonWriter& writer) { + _pmol = nullptr; + _pqmol = nullptr; + if (fragment.isQueryMolecule()) + _pqmol = &fragment.asQueryMolecule(); + else + _pmol = &fragment.asMolecule(); + + if (_pmol) + _pmol->setIgnoreBadValenceFlag(true); + writer.Key("atoms"); writer.StartArray(); saveAtoms(fragment, writer); diff --git a/core/indigo-core/molecule/src/molfile_loader.cpp b/core/indigo-core/molecule/src/molfile_loader.cpp index 6384e76abf..334eb0e4ed 100644 --- a/core/indigo-core/molecule/src/molfile_loader.cpp +++ b/core/indigo-core/molecule/src/molfile_loader.cpp @@ -586,44 +586,23 @@ void MolfileLoader::_readCtab2000() } else { - std::unique_ptr bond; - - if (order == BOND_SINGLE || order == BOND_DOUBLE || order == BOND_TRIPLE || order == BOND_AROMATIC || order == _BOND_HYDROGEN || - order == _BOND_COORDINATION) - bond = std::make_unique(QueryMolecule::BOND_ORDER, order); - else if (order == _BOND_SINGLE_OR_DOUBLE) - bond.reset(QueryMolecule::Bond::und(QueryMolecule::Bond::nicht(new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, BOND_AROMATIC)), - QueryMolecule::Bond::oder(new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, BOND_SINGLE), - new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, BOND_DOUBLE)))); - else if (order == _BOND_SINGLE_OR_AROMATIC) - bond.reset(QueryMolecule::Bond::oder(new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, BOND_SINGLE), - new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, BOND_AROMATIC))); - else if (order == _BOND_DOUBLE_OR_AROMATIC) - bond.reset(QueryMolecule::Bond::oder(new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, BOND_DOUBLE), - new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, BOND_AROMATIC))); - else if (order == _BOND_ANY) - bond = std::make_unique(); - else - throw Error("unknown bond type: %d", order); - - if (topology != 0) - { - bond.reset(QueryMolecule::Bond::und(bond.release(), - new QueryMolecule::Bond(QueryMolecule::BOND_TOPOLOGY, topology == 1 ? TOPOLOGY_RING : TOPOLOGY_CHAIN))); - } - - _qmol->addBond(beg - 1, end - 1, bond.release()); + int direction = BOND_ZERO; + if (stereo == BIOVIA_STEREO_UP) + direction = BOND_UP; + else if (stereo == BIOVIA_STEREO_DOWN) + direction = BOND_DOWN; + _qmol->addBond(beg - 1, end - 1, QueryMolecule::createQueryMoleculeBond(order, topology, direction)); } - if (stereo == 1) + if (stereo == BIOVIA_STEREO_UP) _bmol->setBondDirection(bond_idx, BOND_UP); - else if (stereo == 6) + else if (stereo == BIOVIA_STEREO_DOWN) _bmol->setBondDirection(bond_idx, BOND_DOWN); - else if (stereo == 4) + else if (stereo == BIOVIA_STEREO_ETHER) _bmol->setBondDirection(bond_idx, BOND_EITHER); - else if (stereo == 3) + else if (stereo == BIOVIA_STEREO_DOUBLE_CISTRANS) _ignore_cistrans[bond_idx] = 1; - else if (stereo != 0) + else if (stereo != BIOVIA_STEREO_NO) throw Error("unknown number for bond stereo: %d", stereo); _bmol->reaction_bond_reacting_center[bond_idx] = rcenter; @@ -2076,7 +2055,7 @@ void MolfileLoader::_postLoad() { if (_bmol->getBondDirection(i) && !_sensible_bond_directions[i]) { - if (!stereochemistry_options.ignore_errors) + if (!stereochemistry_options.ignore_errors && !_qmol) // Don't check for query molecule throw Error("direction of bond #%d makes no sense", i); } } @@ -2830,29 +2809,7 @@ void MolfileLoader::_readCtab3000() } else { - std::unique_ptr bond; - - if (order == BOND_SINGLE || order == BOND_DOUBLE || order == BOND_TRIPLE || order == BOND_AROMATIC || order == _BOND_COORDINATION || - order == _BOND_HYDROGEN) - bond = std::make_unique(QueryMolecule::BOND_ORDER, order); - else if (order == _BOND_SINGLE_OR_DOUBLE) - { - bond.reset(QueryMolecule::Bond::und(QueryMolecule::Bond::nicht(new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, BOND_AROMATIC)), - QueryMolecule::Bond::oder(new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, BOND_SINGLE), - new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, BOND_DOUBLE)))); - } - else if (order == _BOND_SINGLE_OR_AROMATIC) - bond.reset(QueryMolecule::Bond::oder(new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, BOND_SINGLE), - new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, BOND_AROMATIC))); - else if (order == _BOND_DOUBLE_OR_AROMATIC) - bond.reset(QueryMolecule::Bond::oder(new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, BOND_DOUBLE), - new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, BOND_AROMATIC))); - else if (order == _BOND_ANY) - bond = std::make_unique(); - else - throw Error("unknown bond type: %d", order); - - _qmol->addBond(beg, end, bond.release()); + _qmol->addBond(beg, end, QueryMolecule::createQueryMoleculeBond(order, 0, 0)); } while (true) diff --git a/core/indigo-core/molecule/src/molfile_saver.cpp b/core/indigo-core/molecule/src/molfile_saver.cpp index 36e632edf5..4aac1d51fe 100644 --- a/core/indigo-core/molecule/src/molfile_saver.cpp +++ b/core/indigo-core/molecule/src/molfile_saver.cpp @@ -149,7 +149,8 @@ void MolfileSaver::_saveMolecule(BaseMolecule& mol, bool query) { // auto-detect the format: save to v3000 molfile only // if v2000 is not enough - _v2000 = !(mol.hasHighlighting() || mol.stereocenters.haveEnhancedStereocenter() || (mol.vertexCount() > 999 || mol.edgeCount() > 999)); + _v2000 = !(mol.hasHighlighting() || mol.stereocenters.haveEnhancedStereocenter() || + (mol.vertexCount() > 999 || mol.edgeCount() > 999 || mol.tgroups.getTGroupCount())); } bool rg2000 = (_v2000 && mol.rgroups.getRGroupCount() > 0); @@ -629,14 +630,8 @@ void MolfileSaver::_writeCtab(Output& output, BaseMolecule& mol, bool query) { int qb = QueryMolecule::getQueryBondType(qmol->getBond(i)); - if (qb == QueryMolecule::QUERY_BOND_SINGLE_OR_DOUBLE) - bond_order = 5; - else if (qb == QueryMolecule::QUERY_BOND_SINGLE_OR_AROMATIC) - bond_order = 6; - else if (qb == QueryMolecule::QUERY_BOND_DOUBLE_OR_AROMATIC) - bond_order = 7; - else if (qb == QueryMolecule::QUERY_BOND_ANY) - bond_order = 8; + if (qb == _BOND_SINGLE_OR_DOUBLE || qb == _BOND_SINGLE_OR_AROMATIC || qb == _BOND_DOUBLE_OR_AROMATIC || qb == _BOND_ANY) + bond_order = qb; } if (bond_order < 0) @@ -644,9 +639,9 @@ void MolfileSaver::_writeCtab(Output& output, BaseMolecule& mol, bool query) if (bond_order == BOND_ZERO) { - bond_order = 9; + bond_order = _BOND_COORDINATION; if ((mol.getAtomNumber(edge.beg) == ELEM_H) || (mol.getAtomNumber(edge.end) == ELEM_H)) - bond_order = 10; + bond_order = _BOND_HYDROGEN; } out.printf("%d %d %d %d", iw, bond_order, _atom_mapping[edge.beg], _atom_mapping[edge.end]); @@ -1343,14 +1338,8 @@ void MolfileSaver::_writeCtab2000(Output& output, BaseMolecule& mol, bool query) { int qb = QueryMolecule::getQueryBondType(qmol->getBond(i)); - if (qb == QueryMolecule::QUERY_BOND_SINGLE_OR_DOUBLE) - bond_order = 5; - else if (qb == QueryMolecule::QUERY_BOND_SINGLE_OR_AROMATIC) - bond_order = 6; - else if (qb == QueryMolecule::QUERY_BOND_DOUBLE_OR_AROMATIC) - bond_order = 7; - else if (qb == QueryMolecule::QUERY_BOND_ANY) - bond_order = 8; + if (qb == _BOND_SINGLE_OR_DOUBLE || qb == _BOND_SINGLE_OR_AROMATIC || qb == _BOND_DOUBLE_OR_AROMATIC || qb == _BOND_ANY) + bond_order = qb; } if (bond_order < 0) diff --git a/core/indigo-core/molecule/src/monomer_commons.cpp b/core/indigo-core/molecule/src/monomer_commons.cpp new file mode 100644 index 0000000000..a0e7994638 --- /dev/null +++ b/core/indigo-core/molecule/src/monomer_commons.cpp @@ -0,0 +1,133 @@ +/**************************************************************************** + * Copyright (C) from 2009 to Present EPAM Systems. + * + * This file is part of Indigo toolkit. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ + +#include + +#include "molecule/monomer_commons.h" + +namespace indigo +{ + const std::unordered_map kAminoAcidToAlias = { + {"Ala", "A"}, {"Arg", "R"}, {"Asn", "N"}, {"Asp", "D"}, {"Cys", "C"}, {"Gln", "Q"}, {"Glu", "E"}, {"Gly", "G"}, {"His", "H"}, {"Ile", "I"}, + {"Leu", "L"}, {"Lys", "K"}, {"Met", "M"}, {"Phe", "F"}, {"Pro", "P"}, {"Ser", "S"}, {"Thr", "T"}, {"Trp", "W"}, {"Tyr", "Y"}, {"Val", "V"}}; + + const std::unordered_map kAliasToAminoAcid = { + {"A", "Ala"}, {"R", "Arg"}, {"N", "Asn"}, {"D", "Asp"}, {"C", "Cys"}, {"Q", "Gln"}, {"E", "Glu"}, {"G", "Gly"}, {"H", "His"}, {"I", "Ile"}, + {"L", "Leu"}, {"K", "Lys"}, {"M", "Met"}, {"F", "Phe"}, {"P", "Pro"}, {"S", "Ser"}, {"T", "Thr"}, {"W", "Trp"}, {"Y", "Tyr"}, {"V", "Val"}}; + + const std::unordered_map kNucleicToAlias = {{"Ade", "A"}, {"Cyt", "C"}, {"Gua", "G"}, {"Ura", "U"}, {"Thy", "T"}, + {"Rib", "r"}, {"dRib", "d"}, {"mRib", "m"}, {"Pi", "p"}}; + + const std::unordered_map kAliasToNucleic = {{"A", "Ade"}, {"C", "Cyt"}, {"G", "Gua"}, {"U", "Ura"}, {"T", "Thy"}, + {"r", "Rib"}, {"d", "dRib"}, {"m", "mRib"}, {"p", "Pi"}}; + + std::string classToPrefix(const std::string& monomer_class) + { + if (monomer_class == kMonomerClassdAA || monomer_class == kMonomerClassDNA) + return kPrefix_d; + return ""; + } + + std::string monomerNameByAlias(const std::string& monomer_class, const std::string& alias) + { + if (isAminoAcidClass(monomer_class)) + { + auto it = kAliasToAminoAcid.find(alias); + if (it != kAliasToAminoAcid.end()) + return it->second; + } + else if (isNucleicClass(monomer_class)) + { + auto it = kAliasToNucleic.find(alias); + if (it != kAliasToNucleic.end()) + return it->second; + } + return alias; + } + + std::string monomerAliasByName(const std::string& monomer_class, const std::string& name) + { + if (isAminoAcidClass(monomer_class)) + { + auto it = kAminoAcidToAlias.find(name); + if (it != kAminoAcidToAlias.end()) + return it->second; + } + else if (isNucleicClass(monomer_class)) + { + auto it = kNucleicToAlias.find(name); + if (it != kNucleicToAlias.end()) + return it->second; + } + return name; + } + + std::string normalizeMonomerName(const std::string& monomer_class, const std::string& name) + { + auto res = name; + if (name.size() == 1) + res = monomerNameByAlias(monomer_class, name); + else if (name.size() <= kStdMonomerDef) + { + if (is_lower_case(name) || is_upper_case(name)) + for (auto it = res.begin(); it < res.end(); ++it) + *it = it > res.begin() ? std::tolower(*it) : std::toupper(*it); + } + auto prefix = classToPrefix(monomer_class); + if (prefix.size()) + res = prefix + res; + return res; + } + + std::string normalizeMonomerAlias(const std::string& monomer_class, const std::string& alias) + { + auto res = alias; + if (monomer_class == kMonomerClassdAA) + res = kPrefix_d + res; + return res; + } + + bool isAttachmentPointsInOrder(int order, const std::string& label) + { + switch (order) + { + case 0: + if (label == "Al" || label == "R1") + return true; + break; + case 1: + if (label == "Br" || label == "R2") + return true; + break; + default: + if (label.size() > 1 || isupper(label[0])) + { + if (label[0] == 'R') + { + auto rnum = label.substr(1); + if (std::all_of(rnum.begin(), rnum.end(), ::isdigit) && (std::stol(rnum) == order + 1)) + return true; + } + if (label[1] == 'x' && (label[0] - 'A' == order)) + return true; + } + break; + } + return false; + } +} diff --git a/core/indigo-core/molecule/src/parse_utils.cpp b/core/indigo-core/molecule/src/parse_utils.cpp index 1f01ae0241..2af0a8a24a 100644 --- a/core/indigo-core/molecule/src/parse_utils.cpp +++ b/core/indigo-core/molecule/src/parse_utils.cpp @@ -81,4 +81,25 @@ namespace indigo } return cnt == 0; } + + bool validate_base64(const std::string& str) + { + if (str.size() & 3) // check for padding + return false; + std::regex base64reg_exp("^[a-zA-Z0-9\\+/]*={0,3}$"); + return std::regex_match(str, base64reg_exp); + } + + std::vector split(const std::string& str, char delim) + { + std::vector strings; + size_t start; + size_t end = 0; + while ((start = str.find_first_not_of(delim, end)) != std::string::npos) + { + end = str.find(delim, start); + strings.push_back(str.substr(start, end - start)); + } + return strings; + } } diff --git a/core/indigo-core/molecule/src/query_molecule.cpp b/core/indigo-core/molecule/src/query_molecule.cpp index b2361840e5..d78a8cbaef 100644 --- a/core/indigo-core/molecule/src/query_molecule.cpp +++ b/core/indigo-core/molecule/src/query_molecule.cpp @@ -328,6 +328,312 @@ void QueryMolecule::_getAtomDescription(Atom* atom, Output& out, int depth) } } +std::string QueryMolecule::getSmartsBondStr(Bond* bond) +{ + Array out; + ArrayOutput output(out); + writeSmartsBond(output, bond, false); + std::string result{out.ptr(), static_cast(out.size())}; + return result; +} + +void QueryMolecule::writeSmartsBond(Output& output, Bond* bond, bool has_or_parent) +{ + int i; + + switch (bond->type) + { + case OP_NONE: + output.writeChar('~'); + break; + case OP_NOT: { + output.writeChar('!'); + writeSmartsBond(output, bond->child(0), has_or_parent); + break; + } + case OP_OR: { + for (i = 0; i < bond->children.size(); i++) + { + if (i > 0) + output.printf(","); + writeSmartsBond(output, bond->child(i), true); + } + break; + } + case OP_AND: { + for (i = 0; i < bond->children.size(); i++) + { + if (i > 0) + output.writeChar(has_or_parent ? '&' : ';'); + writeSmartsBond(output, bond->child(i), has_or_parent); + } + break; + } + case BOND_ORDER: { + int bond_order = bond->value; + if (bond_order == BOND_SINGLE) + { + if (bond->direction == BOND_UP) + output.writeChar('/'); + else if (bond->direction == BOND_DOWN) + output.writeChar('\\'); + else + output.writeChar('-'); + } + if (bond_order == BOND_DOUBLE) + output.writeChar('='); + else if (bond_order == BOND_TRIPLE) + output.writeChar('#'); + else if (bond_order == BOND_AROMATIC) + output.writeChar(':'); + break; + } + case BOND_TOPOLOGY: { + if (bond->value == TOPOLOGY_RING) + output.writeChar('@'); + break; + } + default: + throw Error("Unexpected bond type: %d", bond->type); + } +} + +std::string QueryMolecule::getSmartsAtomStr(QueryMolecule::Atom* atom) +{ + Array out; + ArrayOutput output(out); + writeSmartsAtom(output, atom, -1, -1, 1, false, false); + std::string result{out.ptr(), static_cast(out.size())}; + return result; +} + +static void _write_num(indigo::Output& output, unsigned char ch, int num) +{ + output.writeChar(ch); + if (num != 1) + output.printf("%d", num); +} + +static void _write_num_if_set(indigo::Output& output, unsigned char ch, int min, int max) +{ + if (min == 1 && max == 100) + output.writeChar(ch); + else + { + output.printf("%c%d", ch, min); + } +} + +static void writeAnd(Output& _output, QueryMolecule::Node* node, bool has_or_parent) +{ + if (has_or_parent) + _output.writeChar('&'); + else if (node->hasOP_OR()) + _output.writeChar(';'); +} + +void QueryMolecule::writeSmartsAtom(Output& output, Atom* atom, int aam, int chirality, int depth, bool has_or_parent, bool has_not_parent) +{ + int i; + + if (depth == 0) + output.printf("["); + + switch (atom->type) + { + case OP_NOT: { + if (atom->artificial) // Skip atoms added by loader (!#1) + { + break; + } + else if (isNotAtom(*atom, ELEM_H)) + { + output.printf("*"); + break; + } + output.writeChar('!'); + writeSmartsAtom(output, atom->child(0), aam, chirality, depth + 1, has_or_parent, true); + break; + } + case OP_AND: { + bool has_number = false; + bool has_aromatic = false; + bool aromatic = false; + char atom_name[10]; + int cur_pos = output.tell(); + for (i = 0; i < atom->children.size(); i++) + { + if (atom->children[i]->type == ATOM_NUMBER) + { + has_number = true; + strncpy(atom_name, Element::toString(atom->child(i)->value_max), sizeof(atom_name)); + } + if (atom->children[i]->type == ATOM_AROMATICITY) + { + has_aromatic = true; + aromatic = atom->child(i)->value_min == ATOM_AROMATIC; + } + } + if (has_aromatic && has_number) + { // Convert a & #6 -> c, A & #6 -> C + if (aromatic) + atom_name[0] = tolower(atom_name[0]); + output.printf("%s", atom_name); + } + for (i = 0; i < atom->children.size(); i++) + { + if (has_aromatic && has_number && (atom->children[i]->type == ATOM_AROMATICITY || atom->children[i]->type == ATOM_NUMBER)) + { + continue; + } + if (atom->children[i]->type == ATOM_RADICAL || atom->children[i]->type == ATOM_VALENCE) + { + continue; + } + if (atom->children[i]->type == OP_NOT && atom->children[i]->artificial) + { + continue; + } + + if (output.tell() > cur_pos) + { + output.writeChar(has_or_parent ? '&' : ';'); + cur_pos = output.tell(); + } + writeSmartsAtom(output, atom->child(i), aam, chirality, depth + 1, has_or_parent, has_not_parent); + } + break; + } + case OP_OR: { + for (i = 0; i < atom->children.size(); i++) + { + if (atom->children[i]->type == QueryMolecule::ATOM_RADICAL || atom->children[i]->type == QueryMolecule::ATOM_VALENCE) + { + continue; + } + + if (i > 0) + output.printf(has_not_parent ? "!" : ","); + writeSmartsAtom(output, atom->child(i), aam, chirality, depth + 1, true, has_not_parent); + } + break; + } + case ATOM_ISOTOPE: + output.printf("%d", atom->value_max); + break; + case ATOM_NUMBER: { + output.printf("#%d", atom->value_max); + if (chirality == 1) + output.printf("@"); + else if (chirality == 2) + output.printf("@@"); + + if (aam > 0) + output.printf(":%d", aam); + + break; + } + case ATOM_CHARGE: { + int charge = atom->value_max; + + if (charge > 1) + output.printf("+%d", charge); + else if (charge < -1) + output.printf("-%d", -charge); + else if (charge == 1) + output.printf("+"); + else if (charge == -1) + output.printf("-"); + else + output.printf("+0"); + break; + } + case ATOM_FRAGMENT: { + if (atom->fragment->fragment_smarts.ptr() == 0) + throw Error("fragment_smarts has unexpectedly gone"); + output.printf("$(%s)", atom->fragment->fragment_smarts.ptr()); + break; + } + case ATOM_AROMATICITY: { + if (atom->value_min == ATOM_AROMATIC) + output.printf("a"); + else + output.printf("A"); + break; + } + case OP_NONE: + output.writeChar('*'); + break; + case ATOM_TOTAL_H: { + _write_num(output, 'H', atom->value_min); + break; + } + + case ATOM_SSSR_RINGS: { + _write_num_if_set(output, 'R', atom->value_min, atom->value_max); + break; + } + + case ATOM_RING_BONDS_AS_DRAWN: { + output.printf("x:%d", atom->value_min); + break; + } + + case ATOM_RING_BONDS: { + _write_num_if_set(output, 'x', atom->value_min, atom->value_max); + break; + } + + case ATOM_IMPLICIT_H: { + _write_num_if_set(output, 'h', atom->value_min, atom->value_max); + break; + } + + case ATOM_UNSATURATION: { + output.printf("$([*,#1]=,#,:[*,#1])"); + break; + } + + case ATOM_SMALLEST_RING_SIZE: { + _write_num_if_set(output, 'r', atom->value_min, atom->value_max); + break; + } + + case ATOM_SUBSTITUENTS: { + output.printf("D%d", atom->value_min); + break; + } + + case ATOM_SUBSTITUENTS_AS_DRAWN: { + output.printf("D%d", atom->value_min); + break; + } + + case ATOM_PSEUDO: { + output.printf("*", atom->alias.ptr()); + break; + } + + case ATOM_CONNECTIVITY: { + output.printf("X%d", atom->value_min); + break; + } + + case ATOM_TOTAL_BOND_ORDER: { + _write_num(output, 'v', atom->value_min); + break; + } + + default: { + throw Error("Unknown atom attribute %d", atom->type); + break; + } + } + + if (depth == 0) + output.writeChar(']'); +} + void QueryMolecule::getBondDescription(int idx, Array& description) { ArrayOutput out(description); @@ -562,13 +868,16 @@ QueryMolecule::Atom::~Atom() { } -QueryMolecule::Bond::Bond() : Node(OP_NONE) +QueryMolecule::Bond::Bond() : Node(OP_NONE), value(0), direction(0) +{ +} + +QueryMolecule::Bond::Bond(int type_, int value_) : Node(type_), value(value_), direction(0) { } -QueryMolecule::Bond::Bond(int type_, int value_) : Node(type_) +QueryMolecule::Bond::Bond(int type_, int value_, int direction_) : Node(type_), value(value_), direction(direction_) { - value = value_; } QueryMolecule::Bond::~Bond() @@ -1409,14 +1718,14 @@ bool QueryMolecule::Atom::valueWithinRange(int value) return result; } -QueryMolecule::Atom* QueryMolecule::Atom::child(int idx) const +QueryMolecule::Atom* QueryMolecule::Atom::child(int idx) { - return (Atom*)children[idx]; + return static_cast(children[idx]); } QueryMolecule::Bond* QueryMolecule::Bond::child(int idx) { - return (Bond*)children[idx]; + return static_cast(children[idx]); } QueryMolecule::Node* QueryMolecule::Atom::_neu() @@ -1529,6 +1838,7 @@ QueryMolecule::Bond* QueryMolecule::Bond::clone() res->type = type; res->value = value; + res->direction = direction; for (i = 0; i < children.size(); i++) res->children.add(((Bond*)children[i])->clone()); @@ -1983,7 +2293,7 @@ bool QueryMolecule::_isAtomListOr(const Atom* pqa, std::set& list) std::set collected; for (auto i = 0; i < pqa->children.size(); i++) { - auto pqc = pqa->child(i); + Atom* pqc = const_cast(pqa)->child(i); if (pqc->type == ATOM_NUMBER && pqc->value_max == pqc->value_max) { collected.insert(pqc->value_min); @@ -2016,7 +2326,7 @@ bool QueryMolecule::_isAtomOrListAndProps(const Atom* pqa, std::set& list, bool is_neg = false; if (pqa->type == OP_NOT) { - auto pqc = pqa->child(0); + Atom* pqc = const_cast(pqa)->child(0); is_neg = true; } if (pqc->type == ATOM_NUMBER && pqc->value_min == pqc->value_max) @@ -2041,7 +2351,7 @@ bool QueryMolecule::_isAtomOrListAndProps(const Atom* pqa, std::set& list, // OP_AND for (auto i = 0; i < pqa->children.size(); i++) { - Atom* pqc = pqa->child(i); + Atom* pqc = const_cast(pqa)->child(i); bool is_neg = false; if (_isAtomOrListAndProps(pqc, collected, is_neg, collected_properties)) { @@ -2258,28 +2568,109 @@ bool QueryMolecule::isSingleOrDouble(QueryMolecule::Bond& qb) int QueryMolecule::getQueryBondType(QueryMolecule::Bond& qb) { - if (!qb.hasConstraint(QueryMolecule::BOND_ORDER)) - return QUERY_BOND_ANY; + if (!qb.hasConstraint(BOND_ORDER)) + return _BOND_ANY; - QueryMolecule::Bond* qb2 = &qb; - std::unique_ptr qb_modified; + Bond* qb2 = &qb; + std::unique_ptr qb_modified; int topology; - if (qb.sureValue(QueryMolecule::BOND_TOPOLOGY, topology)) + if (qb.sureValue(BOND_TOPOLOGY, topology)) { qb_modified.reset(qb.clone()); - qb_modified->removeConstraints(QueryMolecule::BOND_TOPOLOGY); + qb_modified->removeConstraints(BOND_TOPOLOGY); qb2 = qb_modified.get(); } if (isSingleOrDouble(*qb2) || isOrBond(*qb2, BOND_SINGLE, BOND_DOUBLE)) - return QUERY_BOND_SINGLE_OR_DOUBLE; + return _BOND_SINGLE_OR_DOUBLE; if (isOrBond(*qb2, BOND_SINGLE, BOND_AROMATIC)) - return QUERY_BOND_SINGLE_OR_AROMATIC; + return _BOND_SINGLE_OR_AROMATIC; if (isOrBond(*qb2, BOND_DOUBLE, BOND_AROMATIC)) - return QUERY_BOND_DOUBLE_OR_AROMATIC; + return _BOND_DOUBLE_OR_AROMATIC; return -1; } +int QueryMolecule::getQueryBondType(Bond& qb, int& direction, bool& negative) +{ + int topology; + Bond* qbond = &qb; + if (qbond->type == OP_NOT) + { + qbond = qbond->child(0); + negative = true; + } + if (qbond->type == OP_AND) + { + int idx = qbond->children.size() - 1; + // Skip topology if any + if (qbond->children[idx]->type == BOND_TOPOLOGY) + --idx; + if (idx > 0) // Looks like _BOND_SINGLE_OR_DOUBLE + { + Bond* tbond = qbond->child(0); + if (tbond->type != OP_NOT) + return -1; + tbond = tbond->child(0); + if (tbond->type != BOND_ORDER || tbond->value != BOND_AROMATIC) + return -1; + tbond = qbond->child(1); + if (tbond->type != OP_OR || tbond->children.size() != 2) + return -1; + if (tbond->child(0)->type != BOND_ORDER || tbond->child(0)->value != BOND_SINGLE) + return -1; + if (tbond->child(1)->type != BOND_ORDER || tbond->child(1)->value != BOND_DOUBLE) + return -1; + return _BOND_SINGLE_OR_DOUBLE; + } + qbond = qbond->child(0); + } + + if (qbond->type == OP_NONE) + return _BOND_ANY; + + if (qbond->type == BOND_ORDER) + { + direction = qbond->direction; + return qbond->value; + } + + if (qbond->type != OP_OR || qbond->children.size() != 2) + return -1; + Bond* qb0 = qbond->child(0); + Bond* qb1 = qbond->child(1); + if (qb0->type != BOND_ORDER || qb1->type != BOND_ORDER) + return -1; + if (qb0->value == BOND_SINGLE && qb1->value == BOND_AROMATIC) + return _BOND_SINGLE_OR_AROMATIC; + if (qb0->value == BOND_DOUBLE && qb1->value == BOND_AROMATIC) + return _BOND_DOUBLE_OR_AROMATIC; + return -1; +} + +QueryMolecule::Bond* QueryMolecule::createQueryMoleculeBond(int order, int topology, int direction) +{ + std::unique_ptr bond; + if (order == BOND_SINGLE || order == BOND_DOUBLE || order == BOND_TRIPLE || order == BOND_AROMATIC || order == _BOND_COORDINATION || + order == _BOND_HYDROGEN) + bond = std::make_unique(BOND_ORDER, order, direction); + else if (order == _BOND_SINGLE_OR_DOUBLE) + bond.reset( + Bond::und(Bond::nicht(new Bond(BOND_ORDER, BOND_AROMATIC)), Bond::oder(new Bond(BOND_ORDER, BOND_SINGLE), new Bond(BOND_ORDER, BOND_DOUBLE)))); + else if (order == _BOND_SINGLE_OR_AROMATIC) + bond.reset(Bond::oder(new Bond(BOND_ORDER, BOND_SINGLE), new Bond(BOND_ORDER, BOND_AROMATIC))); + else if (order == _BOND_DOUBLE_OR_AROMATIC) + bond.reset(Bond::oder(new Bond(BOND_ORDER, BOND_DOUBLE), new Bond(BOND_ORDER, BOND_AROMATIC))); + else if (order == _BOND_ANY) + bond = std::make_unique(); + else + throw Error("unknown bond type: %d", order); + if (topology != 0) + { + bond.reset(Bond::und(bond.release(), new Bond(BOND_TOPOLOGY, topology == 1 ? TOPOLOGY_RING : TOPOLOGY_CHAIN))); + } + return bond.release(); +} + void QueryMolecule::invalidateAtom(int index, int mask) { BaseMolecule::invalidateAtom(index, mask); diff --git a/core/indigo-core/molecule/src/smiles_loader.cpp b/core/indigo-core/molecule/src/smiles_loader.cpp index c3790d0b3f..0f294df621 100644 --- a/core/indigo-core/molecule/src/smiles_loader.cpp +++ b/core/indigo-core/molecule/src/smiles_loader.cpp @@ -2549,6 +2549,7 @@ void SmilesLoader::_readBondSub(Array& bond_str, _BondDesc& bond, std::uni int next = scanner.lookNext(); int order = -1; int topology = -1; + int direction = BOND_ZERO; if (next == '!') { @@ -2582,9 +2583,8 @@ void SmilesLoader::_readBondSub(Array& bond_str, _BondDesc& bond, std::uni { scanner.skip(1); if (smarts_mode) - order = BOND_SMARTS_UP; - else - order = BOND_SINGLE; + direction = BOND_UP; + order = BOND_SINGLE; if (bond.dir == 2) throw Error("Specificiation of both cis- and trans- bond restriction is not supported yet."); bond.dir = 1; @@ -2593,9 +2593,8 @@ void SmilesLoader::_readBondSub(Array& bond_str, _BondDesc& bond, std::uni { scanner.skip(1); if (smarts_mode) - order = BOND_SMARTS_DOWN; - else - order = BOND_SINGLE; + direction = BOND_DOWN; + order = BOND_SINGLE; if (bond.dir == 1) throw Error("Specificiation of both cis- and trans- bond restriction is not supported yet."); bond.dir = 2; @@ -2625,9 +2624,9 @@ void SmilesLoader::_readBondSub(Array& bond_str, _BondDesc& bond, std::uni if (qbond.get() != 0) { if (subqbond.get() == 0) - subqbond = std::make_unique(QueryMolecule::BOND_ORDER, order); + subqbond = std::make_unique(QueryMolecule::BOND_ORDER, order, direction); else - subqbond.reset(QueryMolecule::Bond::und(subqbond.release(), new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, order))); + subqbond.reset(QueryMolecule::Bond::und(subqbond.release(), new QueryMolecule::Bond(QueryMolecule::BOND_ORDER, order, direction))); } } else if (order == _ANY_BOND) diff --git a/core/indigo-core/molecule/src/smiles_saver.cpp b/core/indigo-core/molecule/src/smiles_saver.cpp index 93164bb1b0..9313f8e245 100644 --- a/core/indigo-core/molecule/src/smiles_saver.cpp +++ b/core/indigo-core/molecule/src/smiles_saver.cpp @@ -48,7 +48,7 @@ SmilesSaver::SmilesSaver(Output& output) canonize_chiralities = false; write_extra_info = true; chemaxon = true; - _mol = 0; + _mol = nullptr; smarts_mode = false; inside_rsmiles = false; ignore_invalid_hcount = true; @@ -66,7 +66,7 @@ SmilesSaver::~SmilesSaver() void SmilesSaver::saveMolecule(Molecule& mol) { _bmol = &mol; - _qmol = 0; + _qmol = nullptr; _mol = &mol; _saveMolecule(); } @@ -75,7 +75,7 @@ void SmilesSaver::saveQueryMolecule(QueryMolecule& mol) { _bmol = &mol; _qmol = &mol; - _mol = 0; + _mol = nullptr; _saveMolecule(); } @@ -533,15 +533,17 @@ void SmilesSaver::_saveMolecule() int dir = 0; int bond_order = _bmol->getBondOrder(e_idx); - if (bond_order == BOND_SINGLE) - dir = _calcBondDirection(e_idx, v_prev_idx); + // SMARTS and KET loaders store directions in + if (!smarts_mode || _qmol == nullptr) // || (original_format != ket && original_format != smarts)) + if (bond_order == BOND_SINGLE) + dir = _calcBondDirection(e_idx, v_prev_idx); if ((dir == 1 && v_idx == edge.end) || (dir == 2 && v_idx == edge.beg)) _output.writeChar('/'); else if ((dir == 2 && v_idx == edge.end) || (dir == 1 && v_idx == edge.beg)) _output.writeChar('\\'); else if (smarts_mode && _qmol != 0) - _writeSmartsBond(_output, &_qmol->getBond(e_idx), false); + QueryMolecule::writeSmartsBond(_output, &_qmol->getBond(e_idx), false); else if (bond_order == BOND_DOUBLE) _output.writeChar('='); else if (bond_order == BOND_TRIPLE) @@ -599,7 +601,7 @@ void SmilesSaver::_saveMolecule() else if (_qmol != 0) { int aam = _bmol->reaction_atom_mapping[v_idx]; - _writeSmartsAtom(_output, &_qmol->getAtom(v_idx), aam, _atoms[v_idx].chirality, 0, false, false); + QueryMolecule::writeSmartsAtom(_output, &_qmol->getAtom(v_idx), aam, _atoms[v_idx].chirality, 0, false, false); } else throw Error("SMARTS format available for query only!"); @@ -931,318 +933,6 @@ void SmilesSaver::_writeCharge(int charge) const _output.printf("-"); } -static void _write_num(indigo::Output& output, unsigned char ch, int num) -{ - output.writeChar(ch); - if (num != 1) - output.printf("%d", num); -} - -static void _write_num_if_set(indigo::Output& output, unsigned char ch, int min, int max) -{ - if (min == 1 && max == 100) - output.writeChar(ch); - else - { - output.printf("%c%d", ch, min); - } -} - -static void writeAnd(Output& _output, QueryMolecule::Node* node, bool has_or_parent) -{ - if (has_or_parent) - _output.writeChar('&'); - else if (node->hasOP_OR()) - _output.writeChar(';'); -} - -std::string SmilesSaver::writeSmartsAtomStr(QueryMolecule::Atom* atom) -{ - Array out; - ArrayOutput output(out); - _writeSmartsAtom(output, atom, -1, -1, 1, false, false); - std::string result{out.ptr(), static_cast(out.size())}; - return result; -} - -void SmilesSaver::_writeSmartsAtom(Output& output, QueryMolecule::Atom* atom, int aam, int chirality, int depth, bool has_or_parent, bool has_not_parent) -{ - int i; - - if (depth == 0) - output.printf("["); - - switch (atom->type) - { - case QueryMolecule::OP_NOT: { - if (atom->artificial) // Skip atoms added by loader (!#1) - { - break; - } - else if (QueryMolecule::isNotAtom(*atom, ELEM_H)) - { - output.printf("*"); - break; - } - output.writeChar('!'); - _writeSmartsAtom(output, static_cast(atom->children[0]), aam, chirality, depth + 1, has_or_parent, true); - break; - } - case QueryMolecule::OP_AND: { - bool has_number = false; - bool has_aromatic = false; - bool aromatic = false; - char atom_name[10]; - int cur_pos = output.tell(); - for (i = 0; i < atom->children.size(); i++) - { - if (atom->children[i]->type == QueryMolecule::ATOM_NUMBER) - { - has_number = true; - strncpy(atom_name, Element::toString(static_cast(atom->children[0])->value_max), sizeof(atom_name)); - } - if (atom->children[i]->type == QueryMolecule::ATOM_AROMATICITY) - { - has_aromatic = true; - aromatic = static_cast(atom->children[i])->value_min == ATOM_AROMATIC; - } - } - if (has_aromatic && has_number) - { // Convert a & #6 -> c, A & #6 -> C - if (aromatic) - atom_name[0] = tolower(atom_name[0]); - output.printf("%s", atom_name); - } - for (i = 0; i < atom->children.size(); i++) - { - if (has_aromatic && has_number && - (atom->children[i]->type == QueryMolecule::ATOM_AROMATICITY || atom->children[i]->type == QueryMolecule::ATOM_NUMBER)) - { - continue; - } - if (atom->children[i]->type == QueryMolecule::ATOM_RADICAL || atom->children[i]->type == QueryMolecule::ATOM_VALENCE) - { - continue; - } - if (atom->children[i]->type == QueryMolecule::OP_NOT && atom->children[i]->artificial) - { - continue; - } - - if (output.tell() > cur_pos) - { - output.writeChar(has_or_parent ? '&' : ';'); - cur_pos = output.tell(); - } - _writeSmartsAtom(output, static_cast(atom->children[i]), aam, chirality, depth + 1, has_or_parent, has_not_parent); - } - break; - } - case QueryMolecule::OP_OR: { - for (i = 0; i < atom->children.size(); i++) - { - if (atom->children[i]->type == QueryMolecule::ATOM_RADICAL || atom->children[i]->type == QueryMolecule::ATOM_VALENCE) - { - continue; - } - - if (i > 0) - output.printf(has_not_parent ? "!" : ","); - _writeSmartsAtom(output, static_cast(atom->children[i]), aam, chirality, depth + 1, true, has_not_parent); - } - break; - } - case QueryMolecule::ATOM_ISOTOPE: - output.printf("%d", atom->value_max); - break; - case QueryMolecule::ATOM_NUMBER: { - output.printf("#%d", atom->value_max); - if (chirality == 1) - output.printf("@"); - else if (chirality == 2) - output.printf("@@"); - - if (aam > 0) - output.printf(":%d", aam); - - break; - } - case QueryMolecule::ATOM_CHARGE: { - int charge = atom->value_max; - - if (charge > 1) - output.printf("+%d", charge); - else if (charge < -1) - output.printf("-%d", -charge); - else if (charge == 1) - output.printf("+"); - else if (charge == -1) - output.printf("-"); - else - output.printf("+0"); - break; - } - case QueryMolecule::ATOM_FRAGMENT: { - if (atom->fragment->fragment_smarts.ptr() == 0) - throw Error("fragment_smarts has unexpectedly gone"); - output.printf("$(%s)", atom->fragment->fragment_smarts.ptr()); - break; - } - case QueryMolecule::ATOM_AROMATICITY: { - if (atom->value_min == ATOM_AROMATIC) - output.printf("a"); - else - output.printf("A"); - break; - } - case QueryMolecule::OP_NONE: - output.writeChar('*'); - break; - case QueryMolecule::ATOM_TOTAL_H: { - _write_num(output, 'H', atom->value_min); - break; - } - - case QueryMolecule::ATOM_SSSR_RINGS: { - _write_num_if_set(output, 'R', atom->value_min, atom->value_max); - break; - } - - case QueryMolecule::ATOM_RING_BONDS_AS_DRAWN: { - output.printf("x:%d", atom->value_min); - break; - } - - case QueryMolecule::ATOM_RING_BONDS: { - _write_num_if_set(output, 'x', atom->value_min, atom->value_max); - break; - } - - case QueryMolecule::ATOM_IMPLICIT_H: { - _write_num_if_set(output, 'h', atom->value_min, atom->value_max); - break; - } - - case QueryMolecule::ATOM_UNSATURATION: { - output.printf("$([*,#1]=,#,:[*,#1])"); - break; - } - - case QueryMolecule::ATOM_SMALLEST_RING_SIZE: { - _write_num_if_set(output, 'r', atom->value_min, atom->value_max); - break; - } - - case QueryMolecule::ATOM_SUBSTITUENTS: { - output.printf("D%d", atom->value_min); - break; - } - - case QueryMolecule::ATOM_SUBSTITUENTS_AS_DRAWN: { - output.printf("D%d", atom->value_min); - break; - } - - case QueryMolecule::ATOM_PSEUDO: { - output.printf("*", atom->alias.ptr()); - break; - } - - case QueryMolecule::ATOM_CONNECTIVITY: { - output.printf("X%d", atom->value_min); - break; - } - - case QueryMolecule::ATOM_TOTAL_BOND_ORDER: { - _write_num(output, 'v', atom->value_min); - break; - } - - default: { - throw Error("Unknown atom attribute %d", atom->type); - break; - } - } - - if (depth == 0) - output.writeChar(']'); -} - -std::string SmilesSaver::writeSmartsBondStr(QueryMolecule::Bond* bond) -{ - Array out; - ArrayOutput output(out); - _writeSmartsBond(output, bond, false); - std::string result{out.ptr(), static_cast(out.size())}; - return result; -} - -void SmilesSaver::_writeSmartsBond(Output& output, QueryMolecule::Bond* bond, bool has_or_parent) -{ - int i; - - int qb = QueryMolecule::getQueryBondType(*bond); - - if (qb == QueryMolecule::QUERY_BOND_SINGLE_OR_DOUBLE) - { - output.writeString("-,="); - return; - } - - switch (bond->type) - { - case QueryMolecule::OP_NONE: - output.writeChar('~'); - break; - case QueryMolecule::OP_NOT: { - output.writeChar('!'); - _writeSmartsBond(output, (QueryMolecule::Bond*)bond->children[0], has_or_parent); - break; - } - case QueryMolecule::OP_OR: { - for (i = 0; i < bond->children.size(); i++) - { - if (i > 0) - output.printf(","); - _writeSmartsBond(output, (QueryMolecule::Bond*)bond->children[i], true); - } - break; - } - case QueryMolecule::OP_AND: { - for (i = 0; i < bond->children.size(); i++) - { - if (i > 0) - output.writeChar(has_or_parent ? '&' : ';'); - _writeSmartsBond(output, (QueryMolecule::Bond*)bond->children[i], has_or_parent); - } - break; - } - case QueryMolecule::BOND_ORDER: { - int bond_order = bond->value; - - if (bond_order == BOND_SINGLE) - output.writeChar('-'); - if (bond_order == BOND_DOUBLE) - output.writeChar('='); - else if (bond_order == BOND_TRIPLE) - output.writeChar('#'); - else if (bond_order == BOND_AROMATIC) - output.writeChar(':'); - else if (bond_order == BOND_SMARTS_UP) - output.writeChar('/'); - else if (bond_order == BOND_SMARTS_DOWN) - output.writeChar('\\'); - break; - } - case QueryMolecule::BOND_TOPOLOGY: { - if (bond->value == TOPOLOGY_RING) - output.writeChar('@'); - break; - } - default:; - } -} - void SmilesSaver::_banSlashes() { QS_DEF(Array, slashes); diff --git a/core/indigo-core/reaction/src/reaction_auto_loader.cpp b/core/indigo-core/reaction/src/reaction_auto_loader.cpp index ddd0609205..c6e3a3fb77 100644 --- a/core/indigo-core/reaction/src/reaction_auto_loader.cpp +++ b/core/indigo-core/reaction/src/reaction_auto_loader.cpp @@ -19,6 +19,7 @@ #include "reaction/reaction_auto_loader.h" #include "gzip/gzip_scanner.h" #include "molecule/molecule_auto_loader.h" +#include "molecule/parse_utils.h" #include "reaction/icr_loader.h" #include "reaction/icr_saver.h" #include "reaction/query_reaction.h" diff --git a/core/indigo-core/reaction/src/reaction_cdxml_loader.cpp b/core/indigo-core/reaction/src/reaction_cdxml_loader.cpp index 6646e63024..38e8e133cb 100644 --- a/core/indigo-core/reaction/src/reaction_cdxml_loader.cpp +++ b/core/indigo-core/reaction/src/reaction_cdxml_loader.cpp @@ -22,6 +22,7 @@ #include "base_cpp/tlscont.h" #include "molecule/ket_commons.h" #include "molecule/molecule_cdxml_loader.h" +#include "molecule/parse_utils.h" #include "reaction/reaction.h" #include "reaction/reaction_cdxml_loader.h" diff --git a/core/render2d/src/render_internal.cpp b/core/render2d/src/render_internal.cpp index 456f6d2350..c1b3c599a8 100644 --- a/core/render2d/src/render_internal.cpp +++ b/core/render2d/src/render_internal.cpp @@ -142,8 +142,8 @@ static bool ElementHygrodenOnLeft[] = { static bool _isBondWide(const BondDescr& bd) { - return bd.type == BOND_DOUBLE || bd.type == BOND_TRIPLE || bd.queryType == QueryMolecule::QUERY_BOND_DOUBLE_OR_AROMATIC || - bd.queryType == QueryMolecule::QUERY_BOND_SINGLE_OR_AROMATIC || bd.queryType == QueryMolecule::QUERY_BOND_SINGLE_OR_DOUBLE; + return bd.type == BOND_DOUBLE || bd.type == BOND_TRIPLE || bd.queryType == _BOND_DOUBLE_OR_AROMATIC || bd.queryType == _BOND_SINGLE_OR_AROMATIC || + _BOND_SINGLE_OR_DOUBLE; } RenderOptions::RenderOptions() @@ -3660,16 +3660,16 @@ void MoleculeRenderInternal::_drawBond(int b) default: switch (bd.queryType) { - case QueryMolecule::QUERY_BOND_ANY: + case _BOND_ANY: _bondAny(bd, be1, be2); break; - case QueryMolecule::QUERY_BOND_SINGLE_OR_DOUBLE: + case _BOND_SINGLE_OR_DOUBLE: _bondSingleOrDouble(bd, be1, be2); break; - case QueryMolecule::QUERY_BOND_DOUBLE_OR_AROMATIC: + case _BOND_DOUBLE_OR_AROMATIC: _bondDoubleOrAromatic(bd, be1, be2); break; - case QueryMolecule::QUERY_BOND_SINGLE_OR_AROMATIC: + case _BOND_SINGLE_OR_AROMATIC: _bondSingleOrAromatic(bd, be1, be2); break; default: diff --git a/utils/indigo-ml/setup.py b/utils/indigo-ml/setup.py index 3f61d808f3..4debee000b 100644 --- a/utils/indigo-ml/setup.py +++ b/utils/indigo-ml/setup.py @@ -95,7 +95,7 @@ setup( name="epam.indigo", - version="1.15.0.dev1", + version="1.15.0.dev2", description="Indigo universal cheminformatics toolkit", author="EPAM Systems Life Science Department", author_email="lifescience.opensource@epam.com", diff --git a/utils/indigo-service/frontend/ui/yarn.lock b/utils/indigo-service/frontend/ui/yarn.lock index e8271ee27d..f7d27945ef 100644 --- a/utils/indigo-service/frontend/ui/yarn.lock +++ b/utils/indigo-service/frontend/ui/yarn.lock @@ -31,6 +31,14 @@ dependencies: "@babel/highlight" "^7.18.6" +"@babel/code-frame@^7.22.13": + version "7.22.13" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e" + integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== + dependencies: + "@babel/highlight" "^7.22.13" + chalk "^2.4.2" + "@babel/compat-data@^7.17.7", "@babel/compat-data@^7.22.0", "@babel/compat-data@^7.22.3": version "7.22.3" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.3.tgz#cd502a6a0b6e37d7ad72ce7e71a7160a3ae36f7e" @@ -66,7 +74,7 @@ eslint-visitor-keys "^2.1.0" semver "^6.3.0" -"@babel/generator@^7.22.0", "@babel/generator@^7.22.3", "@babel/generator@^7.7.2": +"@babel/generator@^7.22.0", "@babel/generator@^7.7.2": version "7.22.3" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.3.tgz#0ff675d2edb93d7596c5f6728b52615cfc0df01e" integrity sha512-C17MW4wlk//ES/CJDL51kPNwl+qiBQyN7b9SKyVp11BLGFeSPoVaHrv+MNt8jwQFhQWowW88z1eeBx3pFz9v8A== @@ -76,6 +84,16 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" +"@babel/generator@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420" + integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g== + dependencies: + "@babel/types" "^7.23.0" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + "@babel/helper-annotate-as-pure@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" @@ -142,6 +160,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.1.tgz#ac3a56dbada59ed969d712cf527bd8271fe3eba8" integrity sha512-Z2tgopurB/kTbidvzeBrc2To3PUP/9i5MUe+fU6QJCQDyPwSH2oRapkLw3KGECDYSjhQZCNxEvNvZlLw8JjGwA== +"@babel/helper-environment-visitor@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== + "@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0", "@babel/helper-function-name@^7.21.0": version "7.21.0" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz#d552829b10ea9f120969304023cd0645fa00b1b4" @@ -150,6 +173,14 @@ "@babel/template" "^7.20.7" "@babel/types" "^7.21.0" +"@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== + dependencies: + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" + "@babel/helper-hoist-variables@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" @@ -157,6 +188,13 @@ dependencies: "@babel/types" "^7.18.6" +"@babel/helper-hoist-variables@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" + integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-member-expression-to-functions@^7.22.0": version "7.22.3" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.3.tgz#4b77a12c1b4b8e9e28736ed47d8b91f00976911f" @@ -240,16 +278,33 @@ dependencies: "@babel/types" "^7.18.6" +"@babel/helper-split-export-declaration@^7.22.6": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" + integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-string-parser@^7.21.5": version "7.21.5" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz#2b3eea65443c6bdc31c22d037c65f6d323b6b2bd" integrity sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w== +"@babel/helper-string-parser@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" + integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== + "@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": version "7.19.1" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + "@babel/helper-validator-option@^7.21.0": version "7.21.0" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz#8224c7e13ace4bafdc4004da2cf064ef42673180" @@ -283,11 +338,25 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.21.9", "@babel/parser@^7.22.0", "@babel/parser@^7.22.4": +"@babel/highlight@^7.22.13": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54" + integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.21.9", "@babel/parser@^7.22.0": version "7.22.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.4.tgz#a770e98fd785c231af9d93f6459d36770993fb32" integrity sha512-VLLsx06XkEYqBtE5YGPwfSGwfrjnyPP5oiGty3S8pQLFDFLaS8VwWSIxkTXpcvr5zeYLE6+MBNl2npl/YnfofA== +"@babel/parser@^7.22.15", "@babel/parser@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719" + integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw== + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2" @@ -1143,19 +1212,28 @@ "@babel/parser" "^7.21.9" "@babel/types" "^7.21.5" -"@babel/traverse@^7.20.5", "@babel/traverse@^7.22.1", "@babel/traverse@^7.7.2": - version "7.22.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.4.tgz#c3cf96c5c290bd13b55e29d025274057727664c0" - integrity sha512-Tn1pDsjIcI+JcLKq1AVlZEr4226gpuAQTsLMorsYg9tuS/kG7nuwwJ4AB8jfQuEgb/COBwR/DqJxmoiYFu5/rQ== +"@babel/template@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" + integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== dependencies: - "@babel/code-frame" "^7.21.4" - "@babel/generator" "^7.22.3" - "@babel/helper-environment-visitor" "^7.22.1" - "@babel/helper-function-name" "^7.21.0" - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.22.4" - "@babel/types" "^7.22.4" + "@babel/code-frame" "^7.22.13" + "@babel/parser" "^7.22.15" + "@babel/types" "^7.22.15" + +"@babel/traverse@^7.20.5", "@babel/traverse@^7.22.1", "@babel/traverse@^7.7.2": + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8" + integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.23.0" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.23.0" + "@babel/types" "^7.23.0" debug "^4.1.0" globals "^11.1.0" @@ -1168,6 +1246,15 @@ "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" +"@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb" + integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg== + dependencies: + "@babel/helper-string-parser" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -3660,7 +3747,7 @@ chalk@2.4.1: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.1: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==