diff --git a/.github/workflows/indigo-ci.yaml b/.github/workflows/indigo-ci.yaml index 4a7a05e49b..a3a13af246 100644 --- a/.github/workflows/indigo-ci.yaml +++ b/.github/workflows/indigo-ci.yaml @@ -676,7 +676,7 @@ jobs: python setup.py bdist_wheel cp dist/*.whl ${GITHUB_WORKSPACE}/dist/ - name: Run pylint - run: pylint bingo_elastic + run: pylint --max-args 10 bingo_elastic working-directory: bingo/bingo-elastic/python - name: Run tests run: pytest tests diff --git a/api/c/indigo/src/indigo_layout.cpp b/api/c/indigo/src/indigo_layout.cpp index eec28abc5f..d1d3ad72cd 100644 --- a/api/c/indigo/src/indigo_layout.cpp +++ b/api/c/indigo/src/indigo_layout.cpp @@ -58,19 +58,16 @@ CEXPORT int indigoLayout(int object) ml.max_iterations = self.layout_max_iterations; ml.bond_length = 1.6f; ml.layout_orientation = (layout_orientation_value)self.layout_orientation; - bool has_atropisomery = mol->hasAtropisomericCenter(); - if (has_atropisomery) + if (mol->hasAtropoStereoBonds()) ml.respect_existing_layout = true; TimeoutCancellationHandler cancellation(self.cancellation_timeout); ml.setCancellationHandler(&cancellation); - ml.make(); if (obj.type != IndigoObject::SUBMOLECULE) { - if (!has_atropisomery) - mol->clearBondDirections(); + mol->clearBondDirections(); try { mol->markBondsStereocenters(); diff --git a/api/tests/integration/ref/basic/buffer_string_load_iterate.py.out b/api/tests/integration/ref/basic/buffer_string_load_iterate.py.out index 3c241d861f..9ef808c527 100644 --- a/api/tests/integration/ref/basic/buffer_string_load_iterate.py.out +++ b/api/tests/integration/ref/basic/buffer_string_load_iterate.py.out @@ -35741,7 +35741,7 @@ C(O)(C)C=C>>C(=O)(C)CC [C:1]1([F:33])([O:4][C:10]2[C:15]([F:20])=[C:19]([C:21]([F:24])=[C:17]([F:22])[C:14]=2[F:18])[F:23])[C:3]([F:9])=[C:8]([C:11](=O)[C:6]([F:12])=[C:2]1[F:7])[F:13].[C:25]1([NH:28][NH2:31])=[CH:27][CH:30]=[CH:32][CH:29]=[CH:26]1>>[C:1]1(=[C:3]([F:9])[C:8](=[C:11]([N:31]=[N:28][C:25]2[CH:26]=[CH:29][CH:32]=[CH:30][CH:27]=2)[C:6]([F:12])=[C:2]1[F:7])[F:13])[O:4][C:10]1[C:15]([F:20])=[C:19]([C:21]([F:24])=[C:17]([F:22])[C:14]=1[F:18])[F:23].[C:11]1([N:31]=[N:28][C:25]2[CH:26]=[CH:29][CH:32]=[CH:30][CH:27]=2)[C:8]([F:13])=[C:3]([C:1]([F:33])=[C:2]([F:7])[C:6]=1[F:12])[F:9] [C@:1]1([H])([C:4]#[C:8][CH3:13])[CH2:3][O:7]C(C)(C)[N:2]1[C:6](=[O:12])OC(C)(C)C.C(C)(C)(C)OC(=O)OC(=O)[O:19][C:18]([CH3:22])([CH3:21])[CH3:20]>>[C@H:1]([C:3](=O)[OH:7])([C:4]#[C:8][CH3:13])[NH:2][C:6](=[O:12])[O:19][C:18]([CH3:22])([CH3:21])[CH3:20].[NH:2]([C:1](=O)[C:4]#[C:8][CH3:13])[C:6](=[O:12])[O:19][C:18]([CH3:22])([CH3:21])[CH3:20] [C:1]1([Si](C)(C)C)([O:21][CH2:3]1)[CH:2](OS(=O)(=O)C)[C:6]1([CH2:13][CH2:15][CH2:19][CH3:20])[O:22][CH2:11]1>>[C:6]1([CH2:13][CH2:15][CH2:19][CH3:20])=[CH:11][O:22][C:1]([CH2:3]F)=[CH:2]1.[C:6]1([CH2:13][CH2:15][CH2:19][CH3:20])=[CH:11][O:22][C:1]([CH2:3][OH:21])=[CH:2]1 -[C:1]1([O:48][CH2:4]1)([C@@:3]1([H])[CH2:9][CH2:17][C@@:14]2([H])[C@:24]3([H])[CH2:27][CH:29]=[C:30]4[CH2:33][C@H:35]([CH2:34][CH2:31][C@:28]4([CH3:32])[C@@:26]3([H])[CH2:25][CH2:15][C@:8]12[CH3:16])[O:36][Si](C)(C)C(C)(C)C)[CH:2](OS(=O)(=O)C)[C:6]1([Si](C)(C)C)[O:49][CH2:10]1>>[C@:8]12([CH3:16])[CH2:15][CH2:25][C@:26]3([H])[C@@:28]4([CH3:32])[CH2:31][CH2:34][C@H:35]([OH:36])[CH2:33][C:30]4=[CH:29][CH2:27][C@@:24]3([H])[C@:14]1([H])[CH2:17][CH2:9][C@:3]2([H])[C:1]1=[CH:4][O:48][C:6]([CH2:10]F)=[CH:2]1.[C@:8]12([CH3:16])[CH2:15][CH2:25][C@:26]3([H])[C@@:28]4([CH3:32])[CH2:31][CH2:34][C@H:35]([OH:36])[CH2:33][C:30]4=[CH:29][CH2:27][C@@:24]3([H])[C@:14]1([H])[CH2:17][CH2:9][C@:3]2([H])[C:1]1=[CH:4][O:48][C:6]([CH2:10][OH:49])=[CH:2]1 |w:0,34,40,a:3,7,9,15,18,20,24,47,51,53,57,63,65,69,78,82,84,88,94,96,100| +[C@:1]1([O:48][CH2:4]1)([C@@:3]1([H])[CH2:9][CH2:17][C@@:14]2([H])[C@:24]3([H])[CH2:27][CH:29]=[C:30]4[CH2:33][C@H:35]([CH2:34][CH2:31][C@:28]4([CH3:32])[C@@:26]3([H])[CH2:25][CH2:15][C@:8]12[CH3:16])[O:36][Si](C)(C)C(C)(C)C)[CH:2](OS(=O)(=O)C)[C:6]1([Si](C)(C)C)[O:49][CH2:10]1>>[C@:8]12([CH3:16])[CH2:15][CH2:25][C@:26]3([H])[C@@:28]4([CH3:32])[CH2:31][CH2:34][C@H:35]([OH:36])[CH2:33][C:30]4=[CH:29][CH2:27][C@@:24]3([H])[C@:14]1([H])[CH2:17][CH2:9][C@:3]2([H])[C:1]1=[CH:4][O:48][C:6]([CH2:10]F)=[CH:2]1.[C@:8]12([CH3:16])[CH2:15][CH2:25][C@:26]3([H])[C@@:28]4([CH3:32])[CH2:31][CH2:34][C@H:35]([OH:36])[CH2:33][C:30]4=[CH:29][CH2:27][C@@:24]3([H])[C@:14]1([H])[CH2:17][CH2:9][C@:3]2([H])[C:1]1=[CH:4][O:48][C:6]([CH2:10][OH:49])=[CH:2]1 |a:0,3,7,9,15,18,20,24,47,51,53,57,63,65,69,78,82,84,88,94,96,100,w:34,40| [C@H:1]1([CH2:4][C:9](=[O:13])[O:12][CH3:14])[C:3](=[O:8])[CH2:7][C@@:10]2([H])[CH:11]=[CH:6][C@:2]1([H])[O:29]2.S(=O)(=O)(C(F)(F)F)O[Si:22]([CH3:28])([CH3:27])[CH3:26]>>[CH:10]1([O:29][Si:22]([CH3:28])([CH3:27])[CH3:26])[CH2:11][CH2:6][CH:2]=[C:1]([CH2:4][C:9](=[O:13])[O:12][CH3:14])[C:3](=[O:8])[CH2:7]1.[C@@H:2]1([CH2:6][CH2:11][CH:10]=[CH:7][C:3](=[O:8])[C@@H:1]1[CH2:4][C:9](=[O:13])[O:12][CH3:14])[O:29][Si:22]([CH3:28])([CH3:27])[CH3:26].[C@@:3]12([CH:7]=[CH:10][CH2:11][CH2:6][C@H:2]([O:29][Si:22]([CH3:28])([CH3:27])[CH3:26])[C@@:1]1([H])[C@@H:4]2[C:9](=[O:13])[O:12][CH3:14])[O:8][Si:22]([CH3:28])([CH3:27])[CH3:26] |&1:0,9,13,46,53,64,69,75,77| [C:1]1([O:4][Si:8]([CH3:14])([CH3:13])[C:12]([CH3:21])([CH3:20])[CH3:19])=[CH:3][C:7](=[CH:9][CH:5]=[C:2]1[O:6][Si:10]([CH3:17])([CH3:16])[C:15]([CH3:24])([CH3:23])[CH3:22])[CH2:11][N:18]([C:26](=[O:29])[C:28]([F:33])([F:32])[F:31])[CH2:25][CH2:27][C:30]1[CH:35]=[CH:37][C:38]([OH:39])=[CH:36][CH:34]=1>>[C:30]12([CH:34]=[CH:36][C:38](=[O:39])[CH:37]=[CH:35]1)[CH2:27][CH2:25][N:18]([CH2:11][C:7]1[CH:3]=[C:1]([C:2]([O:6][Si:10]([CH3:16])([CH3:17])[C:15]([CH3:24])([CH3:22])[CH3:23])=[CH:5][C:9]2=1)[O:4][Si:8]([CH3:13])([CH3:14])[C:12]([CH3:21])([CH3:19])[CH3:20])[C:26](=[O:29])[C:28]([F:33])([F:31])[F:32].[C:9]12[CH:5]=[C:2]([C:1]([O:4][Si:8]([CH3:13])([CH3:14])[C:12]([CH3:21])([CH3:19])[CH3:20])=[CH:3][C:7]=1[CH2:11][N:18]([C:26](=[O:29])[C:28]([F:33])([F:31])[F:32])[CH2:25][CH2:27][C:30]1[CH:34]=[CH:36][C:38]([OH:39])=[CH:37][C:35]2=1)[O:6][Si:10]([CH3:16])([CH3:17])[C:15]([CH3:24])([CH3:22])[CH3:23] [C:12]1([N+:11]([O-:4])=[O:5])=[CH:7][C:9](=[C:8]([F:1])[CH:6]=[C:10]1[F:3])[F:2].[C:23]([CH3:15])([CH3:14])([CH3:13])[O:25][C:24](=[O:17])[N:26]1[CH2:21][CH2:19][CH:22]([OH:16])[CH2:18][CH2:20]1>>[C:8]1([CH:6]=[C:10]([C:12]([N+:11]([O-:4])=[O:5])=[CH:7][C:9]=1[F:2])[F:3])[O:16][CH:22]1[CH2:19][CH2:21][N:26]([C:24](=[O:17])[O:25][C:23]([CH3:15])([CH3:13])[CH3:14])[CH2:20][CH2:18]1.[C:10]1(=[CH:6][C:8](=[C:9]([F:2])[CH:7]=[C:12]1[N+:11]([O-:4])=[O:5])[F:1])[O:16][CH:22]1[CH2:19][CH2:21][N:26]([C:24](=[O:17])[O:25][C:23]([CH3:15])([CH3:13])[CH3:14])[CH2:20][CH2:18]1 @@ -36072,7 +36072,7 @@ C(O)(C)C=C>>C(=O)(C)CC [C:1]1([F:33])([O:4][C:10]2[C:15]([F:20])=[C:19]([C:21]([F:24])=[C:17]([F:22])[C:14]=2[F:18])[F:23])[C:3]([F:9])=[C:8]([C:11](=O)[C:6]([F:12])=[C:2]1[F:7])[F:13].[C:25]1([NH:28][NH2:31])=[CH:27][CH:30]=[CH:32][CH:29]=[CH:26]1>>[C:1]1(=[C:3]([F:9])[C:8](=[C:11]([N:31]=[N:28][C:25]2[CH:26]=[CH:29][CH:32]=[CH:30][CH:27]=2)[C:6]([F:12])=[C:2]1[F:7])[F:13])[O:4][C:10]1[C:15]([F:20])=[C:19]([C:21]([F:24])=[C:17]([F:22])[C:14]=1[F:18])[F:23].[C:11]1([N:31]=[N:28][C:25]2[CH:26]=[CH:29][CH:32]=[CH:30][CH:27]=2)[C:8]([F:13])=[C:3]([C:1]([F:33])=[C:2]([F:7])[C:6]=1[F:12])[F:9] [C@:1]1([H])([C:4]#[C:8][CH3:13])[CH2:3][O:7]C(C)(C)[N:2]1[C:6](=[O:12])OC(C)(C)C.C(C)(C)(C)OC(=O)OC(=O)[O:19][C:18]([CH3:22])([CH3:21])[CH3:20]>>[C@H:1]([C:3](=O)[OH:7])([C:4]#[C:8][CH3:13])[NH:2][C:6](=[O:12])[O:19][C:18]([CH3:22])([CH3:21])[CH3:20].[NH:2]([C:1](=O)[C:4]#[C:8][CH3:13])[C:6](=[O:12])[O:19][C:18]([CH3:22])([CH3:21])[CH3:20] [C:1]1([Si](C)(C)C)([O:21][CH2:3]1)[CH:2](OS(=O)(=O)C)[C:6]1([CH2:13][CH2:15][CH2:19][CH3:20])[O:22][CH2:11]1>>[C:6]1([CH2:13][CH2:15][CH2:19][CH3:20])=[CH:11][O:22][C:1]([CH2:3]F)=[CH:2]1.[C:6]1([CH2:13][CH2:15][CH2:19][CH3:20])=[CH:11][O:22][C:1]([CH2:3][OH:21])=[CH:2]1 -[C:1]1([O:48][CH2:4]1)([C@@:3]1([H])[CH2:9][CH2:17][C@@:14]2([H])[C@:24]3([H])[CH2:27][CH:29]=[C:30]4[CH2:33][C@H:35]([CH2:34][CH2:31][C@:28]4([CH3:32])[C@@:26]3([H])[CH2:25][CH2:15][C@:8]12[CH3:16])[O:36][Si](C)(C)C(C)(C)C)[CH:2](OS(=O)(=O)C)[C:6]1([Si](C)(C)C)[O:49][CH2:10]1>>[C@:8]12([CH3:16])[CH2:15][CH2:25][C@:26]3([H])[C@@:28]4([CH3:32])[CH2:31][CH2:34][C@H:35]([OH:36])[CH2:33][C:30]4=[CH:29][CH2:27][C@@:24]3([H])[C@:14]1([H])[CH2:17][CH2:9][C@:3]2([H])[C:1]1=[CH:4][O:48][C:6]([CH2:10]F)=[CH:2]1.[C@:8]12([CH3:16])[CH2:15][CH2:25][C@:26]3([H])[C@@:28]4([CH3:32])[CH2:31][CH2:34][C@H:35]([OH:36])[CH2:33][C:30]4=[CH:29][CH2:27][C@@:24]3([H])[C@:14]1([H])[CH2:17][CH2:9][C@:3]2([H])[C:1]1=[CH:4][O:48][C:6]([CH2:10][OH:49])=[CH:2]1 |w:0,34,40,a:3,7,9,15,18,20,24,47,51,53,57,63,65,69,78,82,84,88,94,96,100| +[C@:1]1([O:48][CH2:4]1)([C@@:3]1([H])[CH2:9][CH2:17][C@@:14]2([H])[C@:24]3([H])[CH2:27][CH:29]=[C:30]4[CH2:33][C@H:35]([CH2:34][CH2:31][C@:28]4([CH3:32])[C@@:26]3([H])[CH2:25][CH2:15][C@:8]12[CH3:16])[O:36][Si](C)(C)C(C)(C)C)[CH:2](OS(=O)(=O)C)[C:6]1([Si](C)(C)C)[O:49][CH2:10]1>>[C@:8]12([CH3:16])[CH2:15][CH2:25][C@:26]3([H])[C@@:28]4([CH3:32])[CH2:31][CH2:34][C@H:35]([OH:36])[CH2:33][C:30]4=[CH:29][CH2:27][C@@:24]3([H])[C@:14]1([H])[CH2:17][CH2:9][C@:3]2([H])[C:1]1=[CH:4][O:48][C:6]([CH2:10]F)=[CH:2]1.[C@:8]12([CH3:16])[CH2:15][CH2:25][C@:26]3([H])[C@@:28]4([CH3:32])[CH2:31][CH2:34][C@H:35]([OH:36])[CH2:33][C:30]4=[CH:29][CH2:27][C@@:24]3([H])[C@:14]1([H])[CH2:17][CH2:9][C@:3]2([H])[C:1]1=[CH:4][O:48][C:6]([CH2:10][OH:49])=[CH:2]1 |a:0,3,7,9,15,18,20,24,47,51,53,57,63,65,69,78,82,84,88,94,96,100,w:34,40| [C@H:1]1([CH2:4][C:9](=[O:13])[O:12][CH3:14])[C:3](=[O:8])[CH2:7][C@@:10]2([H])[CH:11]=[CH:6][C@:2]1([H])[O:29]2.S(=O)(=O)(C(F)(F)F)O[Si:22]([CH3:28])([CH3:27])[CH3:26]>>[CH:10]1([O:29][Si:22]([CH3:28])([CH3:27])[CH3:26])[CH2:11][CH2:6][CH:2]=[C:1]([CH2:4][C:9](=[O:13])[O:12][CH3:14])[C:3](=[O:8])[CH2:7]1.[C@@H:2]1([CH2:6][CH2:11][CH:10]=[CH:7][C:3](=[O:8])[C@@H:1]1[CH2:4][C:9](=[O:13])[O:12][CH3:14])[O:29][Si:22]([CH3:28])([CH3:27])[CH3:26].[C@@:3]12([CH:7]=[CH:10][CH2:11][CH2:6][C@H:2]([O:29][Si:22]([CH3:28])([CH3:27])[CH3:26])[C@@:1]1([H])[C@@H:4]2[C:9](=[O:13])[O:12][CH3:14])[O:8][Si:22]([CH3:28])([CH3:27])[CH3:26] |&1:0,9,13,46,53,64,69,75,77| [C:1]1([O:4][Si:8]([CH3:14])([CH3:13])[C:12]([CH3:21])([CH3:20])[CH3:19])=[CH:3][C:7](=[CH:9][CH:5]=[C:2]1[O:6][Si:10]([CH3:17])([CH3:16])[C:15]([CH3:24])([CH3:23])[CH3:22])[CH2:11][N:18]([C:26](=[O:29])[C:28]([F:33])([F:32])[F:31])[CH2:25][CH2:27][C:30]1[CH:35]=[CH:37][C:38]([OH:39])=[CH:36][CH:34]=1>>[C:30]12([CH:34]=[CH:36][C:38](=[O:39])[CH:37]=[CH:35]1)[CH2:27][CH2:25][N:18]([CH2:11][C:7]1[CH:3]=[C:1]([C:2]([O:6][Si:10]([CH3:16])([CH3:17])[C:15]([CH3:24])([CH3:22])[CH3:23])=[CH:5][C:9]2=1)[O:4][Si:8]([CH3:13])([CH3:14])[C:12]([CH3:21])([CH3:19])[CH3:20])[C:26](=[O:29])[C:28]([F:33])([F:31])[F:32].[C:9]12[CH:5]=[C:2]([C:1]([O:4][Si:8]([CH3:13])([CH3:14])[C:12]([CH3:21])([CH3:19])[CH3:20])=[CH:3][C:7]=1[CH2:11][N:18]([C:26](=[O:29])[C:28]([F:33])([F:31])[F:32])[CH2:25][CH2:27][C:30]1[CH:34]=[CH:36][C:38]([OH:39])=[CH:37][C:35]2=1)[O:6][Si:10]([CH3:16])([CH3:17])[C:15]([CH3:24])([CH3:22])[CH3:23] [C:12]1([N+:11]([O-:4])=[O:5])=[CH:7][C:9](=[C:8]([F:1])[CH:6]=[C:10]1[F:3])[F:2].[C:23]([CH3:15])([CH3:14])([CH3:13])[O:25][C:24](=[O:17])[N:26]1[CH2:21][CH2:19][CH:22]([OH:16])[CH2:18][CH2:20]1>>[C:8]1([CH:6]=[C:10]([C:12]([N+:11]([O-:4])=[O:5])=[CH:7][C:9]=1[F:2])[F:3])[O:16][CH:22]1[CH2:19][CH2:21][N:26]([C:24](=[O:17])[O:25][C:23]([CH3:15])([CH3:13])[CH3:14])[CH2:20][CH2:18]1.[C:10]1(=[CH:6][C:8](=[C:9]([F:2])[CH:7]=[C:12]1[N+:11]([O-:4])=[O:5])[F:1])[O:16][CH:22]1[CH2:19][CH2:21][N:26]([C:24](=[O:17])[O:25][C:23]([CH3:15])([CH3:13])[CH3:14])[CH2:20][CH2:18]1 diff --git a/api/tests/integration/ref/basic/molfile_stereo_desc.py.out b/api/tests/integration/ref/basic/molfile_stereo_desc.py.out index 7a1990e0b6..63cfe19281 100644 --- a/api/tests/integration/ref/basic/molfile_stereo_desc.py.out +++ b/api/tests/integration/ref/basic/molfile_stereo_desc.py.out @@ -2360,7 +2360,7 @@ M V30 COUNTS 15 16 1 0 0 M V30 BEGIN ATOM M V30 1 C 0.0884 2.7107 0.0 0 M V30 2 C -0.6261 2.2982 0.0 0 -M V30 3 C -0.6261 1.4732 0.0 0 CFG=3 +M V30 3 C -0.6261 1.4732 0.0 0 CFG=1 M V30 4 C 0.0884 1.0607 0.0 0 M V30 5 C 0.8029 1.4732 0.0 0 M V30 6 C 0.8029 2.2982 0.0 0 @@ -2393,7 +2393,7 @@ M V30 15 2 13 14 M V30 16 1 13 15 M V30 END BOND M V30 BEGIN COLLECTION -M V30 MDLV30/STERAC1 ATOMS=(1 7) +M V30 MDLV30/STERAC1 ATOMS=(2 3 7) M V30 END COLLECTION M V30 BEGIN SGROUP M V30 1 DAT 1 ATOMS=(1 7) FIELDNAME=INDIGO_CIP_DESC FIELDDISP=" 0.0000 - diff --git a/api/tests/integration/ref/bingo/molecules.py.out b/api/tests/integration/ref/bingo/molecules.py.out index 97783072cc..6c1a060fc8 100644 --- a/api/tests/integration/ref/bingo/molecules.py.out +++ b/api/tests/integration/ref/bingo/molecules.py.out @@ -39,7 +39,7 @@ Structure 275 excluded: molfile loader: direction of bond #7 makes no sense Structure 276 excluded: element: bad valence on H having 1 drawn bonds, charge 1, and 0 radical electrons Structure 283 excluded: element: bad valence on N having 4 drawn bonds, charge 0, and 0 radical electrons Structure 286 excluded: stereocenters: stereo types of the opposite bonds mismatch near atom 0 -Structure 294 excluded: molfile loader: direction of bond #22 makes no sense +Structure 294 excluded: molfile loader: direction of bond #185 makes no sense Structure 295 excluded: stereocenters: stereo types of the opposite bonds mismatch near atom 0 Structure 301 excluded: stereocenters: stereo types of the opposite bonds mismatch near atom 1 Structure 316 excluded: stereocenters: stereo types of non-opposite bonds match near atom 30 @@ -263,7 +263,7 @@ Structure 1785 excluded: stereocenters: one bond up, one bond down -- indefinite Structure 1792 excluded: stereocenters: 2 hydrogens near stereocenter 6 Structure 1797 excluded: element: bad valence on N having 5 drawn bonds, charge 1, and 0 radical electrons Structure 1799 excluded: molfile loader: direction of bond #45 makes no sense -Structure 1800 excluded: molfile loader: direction of bond #177 makes no sense +Structure 1800 excluded: molfile loader: direction of bond #185 makes no sense Structure 1823 excluded: molfile loader: direction of bond #0 makes no sense Structure 1830 excluded: molfile loader: direction of bond #1 makes no sense Structure 1831 excluded: molfile loader: direction of bond #9 makes no sense @@ -288,7 +288,7 @@ Structure 1926 excluded: molfile loader: direction of bond #7 makes no sense Structure 1931 excluded: element: bad valence on H having 4 drawn bonds, charge 0, and 0 radical electrons Structure 1939 excluded: element: bad valence on C having 5 drawn bonds, charge 0, and 0 radical electrons Structure 1945 excluded: molfile loader: direction of bond #5 makes no sense -Structure 1948 excluded: molfile loader: direction of bond #22 makes no sense +Structure 1948 excluded: molfile loader: direction of bond #185 makes no sense Structure 1952 excluded: molfile loader: direction of bond #3 makes no sense Structure 1953 excluded: stereocenters: stereo types of the opposite bonds mismatch near atom 0 Structure 1956 excluded: element: bad valence on C having 4 drawn bonds, charge -1, and 1 radical electrons @@ -1479,7 +1479,7 @@ Finished indexing 2026 structures. 304 wrong structures excluded 1366 c1(N2C[C@H](CNC(C)=O)OC2=O)cc(F)c([C@]2([C@@]3([H])[C@@]2(C[S@@](C3)=O)[H])[H])cc1 c1(N2C[C@H](CNC(C)=O)OC2=O)cc(F)c([C@]2([C@@]3([H])[C@@]2(C[S@@](C3)=O)[H])[H])cc1 1541 C(C(C([H])([H])[H])(C([H])([H])[H])N(C([C@@]1(C([H])([H])N(C(c2c([H])c([H])c([H])[n]c2[H])([H])[H])C([H])([H])C([H])([H])N1C([C@](C([C@](C(c1c([H])c([H])c([H])c([H])c1[H])([H])[H])(C(N([C@]1(c2c(c(c(c([H])c2C([H])([H])[C@]1(OC(C(C(C(=O)OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])=O)[H])[H])[H])[H])[H])[H])=O)[H])([H])[H])(O[H])[H])([H])[H])[H])=O)[H])([H])([H])[H] C(C(C([H])([H])[H])(C([H])([H])[H])N(C([C@@]1(C([H])([H])N(C(c2c([H])c([H])c([H])[n]c2[H])([H])[H])C([H])([H])C([H])([H])N1C([C@](C([C@](C(c1c([H])c([H])c([H])c([H])c1[H])([H])[H])(C(N([C@]1(c2c(c(c(c([H])c2C([H])([H])[C@]1(OC(C(C(C(=O)OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])=O)[H])[H])[H])[H])[H])[H])=O)[H])([H])[H])(O[H])[H])([H])[H])[H])=O)[H])([H])([H])[H] 1670 N1(CC(=O)OCC=CC1)CP(O)(O)=O N1(CC(=O)OCC=CC1)CP(O)(O)=O - 1766 C(O)[C@]12COC(c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12COC(c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,12,24,27,35,46,49,56,68,78,79,r| C(O)[C@]12COC(c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12COC(c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,12,24,27,35,46,49,56,68,78,79,r| + 1766 C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,5,12,13,24,27,35,46,49,56,57,68,71,78,79,r| C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,5,12,13,24,27,35,46,49,56,57,68,71,78,79,r| 1807 C(C(C(C(C(C(C(C(C(C(C(C(O[H])(C(C(=O)N(C1(C(OP(=O)(O[H])O[H])([H])OC(C(OC2(C(N(C(=O)C(C(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])(OC(=O)C(C(C(C(C(C(C(/C(=C(/C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])\[H])/[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])[H])([H])C(OC(=O)C(C(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])(OC(=O)C(C(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])([H])C(OP(O[H])(O[H])=O)([H])C(C(OC3(C([H])([H])C(OC4(OC(C(O[H])(C(O[H])([H])[H])[H])([H])C(O[H])([H])C(O[H])([H])C4([H])[H])C(O[H])=O)([H])C(O[H])([H])C(C(O[H])(C(O[H])([H])[H])[H])([H])O3)C(O[H])=O)([H])[H])([H])O2)[H])([H])[H])([H])C(O[H])([H])C1(OC(=O)C(C(O[H])(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])[H])[H])[H])([H])[H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])([H])[H] C(C(C(C(C(C(C(C(C(C(C(C(O[H])(C(C(=O)N(C1(C(OP(=O)(O[H])O[H])([H])OC(C(OC2(C(N(C(=O)C(C(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])(OC(=O)C(C(C(C(C(C(C(/C(=C(/C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])\[H])/[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])[H])([H])C(OC(=O)C(C(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])(OC(=O)C(C(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])([H])C(OP(O[H])(O[H])=O)([H])C(C(OC3(C([H])([H])C(OC4(OC(C(O[H])(C(O[H])([H])[H])[H])([H])C(O[H])([H])C(O[H])([H])C4([H])[H])C(O[H])=O)([H])C(O[H])([H])C(C(O[H])(C(O[H])([H])[H])[H])([H])O3)C(O[H])=O)([H])[H])([H])O2)[H])([H])[H])([H])C(O[H])([H])C1(OC(=O)C(C(O[H])(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])[H])[H])[H])([H])[H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])([H])[H] 1962 CN1CCCOCC1 CN1CCCOCC1 1971 [C@]1(OC(C(O[H])(C(O[H])([H])[H])[H])([H])[C@](O[H])([H])C(O[C@]2(OC(C(O[H])(C(O[H])([H])[H])[H])([H])[C@](O[H])([H])C(O[H])([H])C2([H])[H])C(=O)O[H])([H])C1([H])[H])(OC1([C@@](O[C@@]2(OC(C(O[H])(C(O[H])([H])[H])[H])([H])[C@](OP(OP(=O)(OC(C(N([H])[H])([H])[H])([H])[H])O[H])(=O)O[H])([H])C(O[C@]3(OC(C(C(O[C@@]4([C@@](O[H])([H])C(O[H])([H])[C@](C(O[H])(C(O[H])([H])[H])[H])(O[H])C([H])([H])O4)[H])([H])[H])(O[H])[H])([H])[C@](OP(=O)(O[H])O[H])([H])C(O[C@]4(C(O[H])([H])C(O[C@]5(C(O[C@]6(C(O[C@@]7([C@](N(C(=O)C([H])([H])[H])[H])([H])C(O[H])([H])[C@](O[H])([H])C(C(O[H])([H])[H])([H])O7)[H])([H])C(O[H])([H])[C@@](O[C@]7(C(O[H])([H])C(OC8([C@](O[H])([H])C(O[H])([H])C(O[C@]9(C(O[C@]%10(C(O[H])([H])C(O[H])([H])[C@](O[H])([H])C(C(O[H])([H])[H])([H])O%10)[H])([H])C(O[C@@]%10(OC(C([H])([H])[H])([H])[C@](O[H])([H])C([H])([H])C%10(O[H])[H])[H])([H])[C@@](O[H])([H])C(C(O[H])([H])[H])([H])O9)[H])([H])[C@@](C([H])([H])[H])([H])O8)[H])([H])[C@](O[H])([H])C(C(O[H])([H])[H])([H])O7)[H])([H])C(C(O[H])([H])[H])([H])O6)[H])([H])C(O[H])([H])[C@](O[H])([H])C(C(O[H])([H])[H])([H])O5)[H])([H])[C@@](O[H])([H])C(C(O[C@]5(C(O[H])([H])C(O[H])([H])[C@](O[H])([H])C(C(O[H])([H])[H])([H])O5)[H])([H])[H])([H])O4)[H])([H])[C@]3(O[H])[H])[H])([H])[C@]2(O[H])[H])[H])([H])C(C(O[H])(C(O[H])([H])[H])[H])([H])O[C@](C(=O)O[H])(OC(C2([C@@](OP(=O)(O[H])O[H])([H])C(OC(C(C(OC(=O)C(C(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])=O)([H])[C@@](N(C(C(C(OC(=O)C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])=O)[H])([H])[C@@](OC(C3(O[C@](C(P(=O)(O[H])O[H])([H])[H])([H])C(C(C(C(C(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[C@](OC(C(C(O[H])(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])=O)([H])[C@]3(O[H])[H])[H])([H])[H])([H])O2)[H])([H])[H])C1([H])[H])[H])C(=O)O[H] [C@]1(OC(C(O[H])(C(O[H])([H])[H])[H])([H])[C@](O[H])([H])C(O[C@]2(OC(C(O[H])(C(O[H])([H])[H])[H])([H])[C@](O[H])([H])C(O[H])([H])C2([H])[H])C(=O)O[H])([H])C1([H])[H])(OC1([C@@](O[C@@]2(OC(C(O[H])(C(O[H])([H])[H])[H])([H])[C@](OP(OP(=O)(OC(C(N([H])[H])([H])[H])([H])[H])O[H])(=O)O[H])([H])C(O[C@]3(OC(C(C(O[C@@]4([C@@](O[H])([H])C(O[H])([H])[C@](C(O[H])(C(O[H])([H])[H])[H])(O[H])C([H])([H])O4)[H])([H])[H])(O[H])[H])([H])[C@](OP(=O)(O[H])O[H])([H])C(O[C@]4(C(O[H])([H])C(O[C@]5(C(O[C@]6(C(O[C@@]7([C@](N(C(=O)C([H])([H])[H])[H])([H])C(O[H])([H])[C@](O[H])([H])C(C(O[H])([H])[H])([H])O7)[H])([H])C(O[H])([H])[C@@](O[C@]7(C(O[H])([H])C(OC8([C@](O[H])([H])C(O[H])([H])C(O[C@]9(C(O[C@]%10(C(O[H])([H])C(O[H])([H])[C@](O[H])([H])C(C(O[H])([H])[H])([H])O%10)[H])([H])C(O[C@@]%10(OC(C([H])([H])[H])([H])[C@](O[H])([H])C([H])([H])C%10(O[H])[H])[H])([H])[C@@](O[H])([H])C(C(O[H])([H])[H])([H])O9)[H])([H])[C@@](C([H])([H])[H])([H])O8)[H])([H])[C@](O[H])([H])C(C(O[H])([H])[H])([H])O7)[H])([H])C(C(O[H])([H])[H])([H])O6)[H])([H])C(O[H])([H])[C@](O[H])([H])C(C(O[H])([H])[H])([H])O5)[H])([H])[C@@](O[H])([H])C(C(O[C@]5(C(O[H])([H])C(O[H])([H])[C@](O[H])([H])C(C(O[H])([H])[H])([H])O5)[H])([H])[H])([H])O4)[H])([H])[C@]3(O[H])[H])[H])([H])[C@]2(O[H])[H])[H])([H])C(C(O[H])(C(O[H])([H])[H])[H])([H])O[C@](C(=O)O[H])(OC(C2([C@@](OP(=O)(O[H])O[H])([H])C(OC(C(C(OC(=O)C(C(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])=O)([H])[C@@](N(C(C(C(OC(=O)C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])=O)[H])([H])[C@@](OC(C3(O[C@](C(P(=O)(O[H])O[H])([H])[H])([H])C(C(C(C(C(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[C@](OC(C(C(O[H])(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])=O)([H])[C@]3(O[H])[H])[H])([H])[H])([H])O2)[H])([H])[H])C1([H])[H])[H])C(=O)O[H] @@ -2251,7 +2251,7 @@ Finished indexing 2026 structures. 304 wrong structures excluded 1691 C(C1C2C(C(C(C(N([H])[H])=O)([H])[H])([H])[H])(C(C([H])([H])[H])(C([H])([H])[H])C(N=2)=C([H])C2C(C(C(C(N([H])[H])=O)([H])[H])([H])[H])(C(C([H])([H])[H])(C(C(N([H])[H])=O)([H])[H])C(N=2)=C(C([H])([H])[H])C2C(C(C(C(N([H])[H])=O)([H])[H])([H])[H])(C(C([H])([H])[H])(C(C(N([H])[H])=O)([H])[H])C(C([H])([H])[H])(N=2)C2(C(C(C(N([H])[H])=O)([H])[H])(C(C([H])([H])[H])(C(C(C(N(C(C(C([H])([H])[H])(OP([O-])(=O)OC3(C(C(O[H])([H])[H])([H])OC([n]4c([H])[n]c5[n]c([n]c(N([H])[H])c45)S(C([H])([H])[H])(=O)=O)([H])C3(O[H])[H])[H])[H])([H])[H])[H])=O)([H])[H])([H])[H])C=1[N-]2)[H])[H])[H])[H])[H])([H])([H])[H].[C-]#N.[Co+3] |c:26,57,174| C(C1C2C(C(C(C(N([H])[H])=O)([H])[H])([H])[H])(C(C([H])([H])[H])(C([H])([H])[H])C(N=2)=C([H])C2C(C(C(C(N([H])[H])=O)([H])[H])([H])[H])(C(C([H])([H])[H])(C(C(N([H])[H])=O)([H])[H])C(N=2)=C(C([H])([H])[H])C2C(C(C(C(N([H])[H])=O)([H])[H])([H])[H])(C(C([H])([H])[H])(C(C(N([H])[H])=O)([H])[H])C(C([H])([H])[H])(N=2)C2(C(C(C(N([H])[H])=O)([H])[H])(C(C([H])([H])[H])(C(C(C(N(C(C(C([H])([H])[H])(OP([O-])(=O)OC3(C(C(O[H])([H])[H])([H])OC([n]4c([H])[n]c5[n]c([n]c(N([H])[H])c45)S(C([H])([H])[H])(=O)=O)([H])C3(O[H])[H])[H])[H])([H])[H])[H])=O)([H])[H])([H])[H])C=1[N-]2)[H])[H])[H])[H])[H])([H])([H])[H].[C-]#N.[Co+3] |c:26,57,174| 1722 C(C(O/C(=C(/C(=O)N([H])C([H])(C(S[H])([H])[H])C(=O)O[H])\[N+]#N)/O[H])([H])[H])([H])([H])[H] C(C(O/C(=C(/C(=O)N([H])C([H])(C(S[H])([H])[H])C(=O)O[H])\[N+]#N)/O[H])([H])[H])([H])([H])[H] 1748 C1(C)CCC(C)[N+]1(CC)CCCCCCCCCCCC.C(C)OS(=O)(=O)[O-] C1(C)CCC(C)[N+]1(CC)CCCCCCCCCCCC.C(C)OS(=O)(=O)[O-] - 1766 C(O)[C@]12COC(c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12COC(c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,12,24,27,35,46,49,56,68,78,79,r| C(O)[C@]12COC(c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12COC(c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,12,24,27,35,46,49,56,68,78,79,r| + 1766 C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,5,12,13,24,27,35,46,49,56,57,68,71,78,79,r| C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,5,12,13,24,27,35,46,49,56,57,68,71,78,79,r| 1807 C(C(C(C(C(C(C(C(C(C(C(C(O[H])(C(C(=O)N(C1(C(OP(=O)(O[H])O[H])([H])OC(C(OC2(C(N(C(=O)C(C(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])(OC(=O)C(C(C(C(C(C(C(/C(=C(/C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])\[H])/[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])[H])([H])C(OC(=O)C(C(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])(OC(=O)C(C(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])([H])C(OP(O[H])(O[H])=O)([H])C(C(OC3(C([H])([H])C(OC4(OC(C(O[H])(C(O[H])([H])[H])[H])([H])C(O[H])([H])C(O[H])([H])C4([H])[H])C(O[H])=O)([H])C(O[H])([H])C(C(O[H])(C(O[H])([H])[H])[H])([H])O3)C(O[H])=O)([H])[H])([H])O2)[H])([H])[H])([H])C(O[H])([H])C1(OC(=O)C(C(O[H])(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])[H])[H])[H])([H])[H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])([H])[H] C(C(C(C(C(C(C(C(C(C(C(C(O[H])(C(C(=O)N(C1(C(OP(=O)(O[H])O[H])([H])OC(C(OC2(C(N(C(=O)C(C(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])(OC(=O)C(C(C(C(C(C(C(/C(=C(/C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])\[H])/[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])[H])([H])C(OC(=O)C(C(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])(OC(=O)C(C(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])([H])C(OP(O[H])(O[H])=O)([H])C(C(OC3(C([H])([H])C(OC4(OC(C(O[H])(C(O[H])([H])[H])[H])([H])C(O[H])([H])C(O[H])([H])C4([H])[H])C(O[H])=O)([H])C(O[H])([H])C(C(O[H])(C(O[H])([H])[H])[H])([H])O3)C(O[H])=O)([H])[H])([H])O2)[H])([H])[H])([H])C(O[H])([H])C1(OC(=O)C(C(O[H])(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])[H])[H])[H])([H])[H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])([H])[H] 1829 CNC(C1CCS(=O)(=O)N1CC)=O CNC(C1CCS(=O)(=O)N1CC)=O 1841 CC1(C)C(=O)NC(C)(C)C(=O)N1[2H] CC1(C)C(=O)NC(C)(C)C(=O)N1[2H] @@ -2318,7 +2318,7 @@ Finished indexing 2026 structures. 304 wrong structures excluded 1541 C(C(C([H])([H])[H])(C([H])([H])[H])N(C([C@@]1(C([H])([H])N(C(c2c([H])c([H])c([H])[n]c2[H])([H])[H])C([H])([H])C([H])([H])N1C([C@](C([C@](C(c1c([H])c([H])c([H])c([H])c1[H])([H])[H])(C(N([C@]1(c2c(c(c(c([H])c2C([H])([H])[C@]1(OC(C(C(C(=O)OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])=O)[H])[H])[H])[H])[H])[H])=O)[H])([H])[H])(O[H])[H])([H])[H])[H])=O)[H])([H])([H])[H] C(C(C([H])([H])[H])(C([H])([H])[H])N(C([C@@]1(C([H])([H])N(C(c2c([H])c([H])c([H])[n]c2[H])([H])[H])C([H])([H])C([H])([H])N1C([C@](C([C@](C(c1c([H])c([H])c([H])c([H])c1[H])([H])[H])(C(N([C@]1(c2c(c(c(c([H])c2C([H])([H])[C@]1(OC(C(C(C(=O)OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])=O)[H])[H])[H])[H])[H])[H])=O)[H])([H])[H])(O[H])[H])([H])[H])[H])=O)[H])([H])([H])[H] 1578 C1C([S+](C)C)([H])[CH-]1.N#C[C-](C1([H])C([N+](CC)(CC)CC)([H])/C/1=C(\C#N)/C#N)C#N.c1c([P+](Cl)(Cl)Cl)c[cH-]c1.C1C(=P(Cl)(Cl)Cl)C=CC=1.[N+](C)(C)(C)CC(=O)[O-].c1ccccc1[P+](c1ccccc1)(c1ccccc1)[C-2][P+](c1ccccc1)(c1ccccc1)c1ccccc1.C(#C[B-](c1ccccc1)(c1ccccc1)c1ccccc1)[P+](C)(c1ccccc1)c1ccccc1.[n+]1(ccc(CC(O)[O-])cc1)C.c12cc([O-])ccc1ccc(-c1c[s][s+]c1)c2.c1cc([O-])ccc1O[O+].c1cc([O-])ccc1[O+]=O.C(/C)(=C/C[S+](c1cc(C(C)(C)C)c([O-])c(C(C)(C)C)c1)C)\C.c1c([N-]c2[n+](-c3ccccc3)c[n](-c3ccccc3)[n]2)cccc1.c1(ccc(C)cc1)S([N-][n+]1ccccc1)(=O)=O.C1CCC[N+]1=[N-] C1C([S+](C)C)([H])[CH-]1.N#C[C-](C1([H])C([N+](CC)(CC)CC)([H])/C/1=C(\C#N)/C#N)C#N.c1c([P+](Cl)(Cl)Cl)c[cH-]c1.C1C(=P(Cl)(Cl)Cl)C=CC=1.[N+](C)(C)(C)CC(=O)[O-].c1ccccc1[P+](c1ccccc1)(c1ccccc1)[C-2][P+](c1ccccc1)(c1ccccc1)c1ccccc1.C(#C[B-](c1ccccc1)(c1ccccc1)c1ccccc1)[P+](C)(c1ccccc1)c1ccccc1.[n+]1(ccc(CC(O)[O-])cc1)C.c12cc([O-])ccc1ccc(-c1c[s][s+]c1)c2.c1cc([O-])ccc1O[O+].c1cc([O-])ccc1[O+]=O.C(/C)(=C/C[S+](c1cc(C(C)(C)C)c([O-])c(C(C)(C)C)c1)C)\C.c1c([N-]c2[n+](-c3ccccc3)c[n](-c3ccccc3)[n]2)cccc1.c1(ccc(C)cc1)S([N-][n+]1ccccc1)(=O)=O.C1CCC[N+]1=[N-] 1670 N1(CC(=O)OCC=CC1)CP(O)(O)=O N1(CC(=O)OCC=CC1)CP(O)(O)=O - 1766 C(O)[C@]12COC(c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12COC(c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,12,24,27,35,46,49,56,68,78,79,r| C(O)[C@]12COC(c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12COC(c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,12,24,27,35,46,49,56,68,78,79,r| + 1766 C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,5,12,13,24,27,35,46,49,56,57,68,71,78,79,r| C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,5,12,13,24,27,35,46,49,56,57,68,71,78,79,r| 1845 Cl([O-])(=[O+][H])(=O)=O.O(C(C([N+]12C([H])([H])C([H])([H])O[Ni+2]341(OC([H])([H])C([H])([H])[N+]3(C(C(O[H])([H])[H])([H])[H])C([H])([H])C([H])([H])O4)OC(C2([H])[H])([H])[H])([H])[H])([H])[H])[H] Cl([O-])(=[O+][H])(=O)=O.O(C(C([N+]12C([H])([H])C([H])([H])O[Ni+2]341(OC([H])([H])C([H])([H])[N+]3(C(C(O[H])([H])[H])([H])[H])C([H])([H])C([H])([H])O4)OC(C2([H])[H])([H])[H])([H])[H])([H])[H])[H] 1861 C/C=C/N1[C-](C2CCCCC2)C(=O)[O+]=C1C C/C=C/N1[C-](C2CCCCC2)C(=O)[O+]=C1C 1962 CN1CCCOCC1 CN1CCCOCC1 @@ -2475,7 +2475,7 @@ Finished indexing 2026 structures. 304 wrong structures excluded 1707 O1[C@H]([C@@H](C)CO)[C@H](O)[C@H]([C@@H](C)CO)OC1 |&1:1,2,6,8,9,r| O1[C@H]([C@@H](C)CO)[C@H](O)[C@H]([C@@H](C)CO)OC1 |&1:1,2,6,8,9,r| 1708 C12OSC3C4(C5OSC6OSC(OS5)C(C(SO3)OS1)(C1SOC3SOC(SO1)C6(C1OSC4OSC(OS1)C23Br)C)Cl)I C12OSC3C4(C5OSC6OSC(OS5)C(C(SO3)OS1)(C1SOC3SOC(SO1)C6(C1OSC4OSC(OS1)C23Br)C)Cl)I 1759 O1[C@H](C(C)CO)[C@H](O)[C@H](C(C)CO)OC1 |&1:1,6,8,r| O1[C@H](C(C)CO)[C@H](O)[C@H](C(C)CO)OC1 |&1:1,6,8,r| - 1766 C(O)[C@]12COC(c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12COC(c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,12,24,27,35,46,49,56,68,78,79,r| C(O)[C@]12COC(c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12COC(c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,12,24,27,35,46,49,56,68,78,79,r| + 1766 C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,5,12,13,24,27,35,46,49,56,57,68,71,78,79,r| C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,5,12,13,24,27,35,46,49,56,57,68,71,78,79,r| 1933 C(C(=O)[O-])C(CO)(C(=O)[O-])C(=O)[O-].[Ce+3] C(C(=O)[O-])C(CO)(C(=O)[O-])C(=O)[O-].[Ce+3] 1971 [C@]1(OC(C(O[H])(C(O[H])([H])[H])[H])([H])[C@](O[H])([H])C(O[C@]2(OC(C(O[H])(C(O[H])([H])[H])[H])([H])[C@](O[H])([H])C(O[H])([H])C2([H])[H])C(=O)O[H])([H])C1([H])[H])(OC1([C@@](O[C@@]2(OC(C(O[H])(C(O[H])([H])[H])[H])([H])[C@](OP(OP(=O)(OC(C(N([H])[H])([H])[H])([H])[H])O[H])(=O)O[H])([H])C(O[C@]3(OC(C(C(O[C@@]4([C@@](O[H])([H])C(O[H])([H])[C@](C(O[H])(C(O[H])([H])[H])[H])(O[H])C([H])([H])O4)[H])([H])[H])(O[H])[H])([H])[C@](OP(=O)(O[H])O[H])([H])C(O[C@]4(C(O[H])([H])C(O[C@]5(C(O[C@]6(C(O[C@@]7([C@](N(C(=O)C([H])([H])[H])[H])([H])C(O[H])([H])[C@](O[H])([H])C(C(O[H])([H])[H])([H])O7)[H])([H])C(O[H])([H])[C@@](O[C@]7(C(O[H])([H])C(OC8([C@](O[H])([H])C(O[H])([H])C(O[C@]9(C(O[C@]%10(C(O[H])([H])C(O[H])([H])[C@](O[H])([H])C(C(O[H])([H])[H])([H])O%10)[H])([H])C(O[C@@]%10(OC(C([H])([H])[H])([H])[C@](O[H])([H])C([H])([H])C%10(O[H])[H])[H])([H])[C@@](O[H])([H])C(C(O[H])([H])[H])([H])O9)[H])([H])[C@@](C([H])([H])[H])([H])O8)[H])([H])[C@](O[H])([H])C(C(O[H])([H])[H])([H])O7)[H])([H])C(C(O[H])([H])[H])([H])O6)[H])([H])C(O[H])([H])[C@](O[H])([H])C(C(O[H])([H])[H])([H])O5)[H])([H])[C@@](O[H])([H])C(C(O[C@]5(C(O[H])([H])C(O[H])([H])[C@](O[H])([H])C(C(O[H])([H])[H])([H])O5)[H])([H])[H])([H])O4)[H])([H])[C@]3(O[H])[H])[H])([H])[C@]2(O[H])[H])[H])([H])C(C(O[H])(C(O[H])([H])[H])[H])([H])O[C@](C(=O)O[H])(OC(C2([C@@](OP(=O)(O[H])O[H])([H])C(OC(C(C(OC(=O)C(C(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])=O)([H])[C@@](N(C(C(C(OC(=O)C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])=O)[H])([H])[C@@](OC(C3(O[C@](C(P(=O)(O[H])O[H])([H])[H])([H])C(C(C(C(C(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[C@](OC(C(C(O[H])(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])=O)([H])[C@]3(O[H])[H])[H])([H])[H])([H])O2)[H])([H])[H])C1([H])[H])[H])C(=O)O[H] [C@]1(OC(C(O[H])(C(O[H])([H])[H])[H])([H])[C@](O[H])([H])C(O[C@]2(OC(C(O[H])(C(O[H])([H])[H])[H])([H])[C@](O[H])([H])C(O[H])([H])C2([H])[H])C(=O)O[H])([H])C1([H])[H])(OC1([C@@](O[C@@]2(OC(C(O[H])(C(O[H])([H])[H])[H])([H])[C@](OP(OP(=O)(OC(C(N([H])[H])([H])[H])([H])[H])O[H])(=O)O[H])([H])C(O[C@]3(OC(C(C(O[C@@]4([C@@](O[H])([H])C(O[H])([H])[C@](C(O[H])(C(O[H])([H])[H])[H])(O[H])C([H])([H])O4)[H])([H])[H])(O[H])[H])([H])[C@](OP(=O)(O[H])O[H])([H])C(O[C@]4(C(O[H])([H])C(O[C@]5(C(O[C@]6(C(O[C@@]7([C@](N(C(=O)C([H])([H])[H])[H])([H])C(O[H])([H])[C@](O[H])([H])C(C(O[H])([H])[H])([H])O7)[H])([H])C(O[H])([H])[C@@](O[C@]7(C(O[H])([H])C(OC8([C@](O[H])([H])C(O[H])([H])C(O[C@]9(C(O[C@]%10(C(O[H])([H])C(O[H])([H])[C@](O[H])([H])C(C(O[H])([H])[H])([H])O%10)[H])([H])C(O[C@@]%10(OC(C([H])([H])[H])([H])[C@](O[H])([H])C([H])([H])C%10(O[H])[H])[H])([H])[C@@](O[H])([H])C(C(O[H])([H])[H])([H])O9)[H])([H])[C@@](C([H])([H])[H])([H])O8)[H])([H])[C@](O[H])([H])C(C(O[H])([H])[H])([H])O7)[H])([H])C(C(O[H])([H])[H])([H])O6)[H])([H])C(O[H])([H])[C@](O[H])([H])C(C(O[H])([H])[H])([H])O5)[H])([H])[C@@](O[H])([H])C(C(O[C@]5(C(O[H])([H])C(O[H])([H])[C@](O[H])([H])C(C(O[H])([H])[H])([H])O5)[H])([H])[H])([H])O4)[H])([H])[C@]3(O[H])[H])[H])([H])[C@]2(O[H])[H])[H])([H])C(C(O[H])(C(O[H])([H])[H])[H])([H])O[C@](C(=O)O[H])(OC(C2([C@@](OP(=O)(O[H])O[H])([H])C(OC(C(C(OC(=O)C(C(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])=O)([H])[C@@](N(C(C(C(OC(=O)C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])=O)[H])([H])[C@@](OC(C3(O[C@](C(P(=O)(O[H])O[H])([H])[H])([H])C(C(C(C(C(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[C@](OC(C(C(O[H])(C(C(C(C(C(C(C(C(C(C(C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])[H])([H])[H])=O)([H])[C@]3(O[H])[H])[H])([H])[H])([H])O2)[H])([H])[H])C1([H])[H])[H])C(=O)O[H] ** searchSim(C(CO)(CO)C, 0.9, 1, tanimoto) ** @@ -2795,7 +2795,7 @@ Finished indexing 2026 structures. 304 wrong structures excluded 1558 [H]C1([H])[C@]2(C([H])([H])[C@@]([H])([C@@]([H])(C(=O)OC([H])([H])[H])[C@@](N2C([H])([H])[H])([H])C1([H])[H])OC(c1c([H])c([H])c([H])c([H])c1[H])=O)[H].[H]C1([H])[C@]2(C([H])([H])[C@@]([H])([C@@]([H])(C(=O)OC([H])([H])[H])[C@@](N2C([H])([H])[H])([H])C1([H])[H])OC(c1c([H])c([H])c([H])c([H])c1[H])=O)[H] [H]C1([H])[C@]2(C([H])([H])[C@@]([H])([C@@]([H])(C(=O)OC([H])([H])[H])[C@@](N2C([H])([H])[H])([H])C1([H])[H])OC(c1c([H])c([H])c([H])c([H])c1[H])=O)[H].[H]C1([H])[C@]2(C([H])([H])[C@@]([H])([C@@]([H])(C(=O)OC([H])([H])[H])[C@@](N2C([H])([H])[H])([H])C1([H])[H])OC(c1c([H])c([H])c([H])c([H])c1[H])=O)[H] 1578 C1C([S+](C)C)([H])[CH-]1.N#C[C-](C1([H])C([N+](CC)(CC)CC)([H])/C/1=C(\C#N)/C#N)C#N.c1c([P+](Cl)(Cl)Cl)c[cH-]c1.C1C(=P(Cl)(Cl)Cl)C=CC=1.[N+](C)(C)(C)CC(=O)[O-].c1ccccc1[P+](c1ccccc1)(c1ccccc1)[C-2][P+](c1ccccc1)(c1ccccc1)c1ccccc1.C(#C[B-](c1ccccc1)(c1ccccc1)c1ccccc1)[P+](C)(c1ccccc1)c1ccccc1.[n+]1(ccc(CC(O)[O-])cc1)C.c12cc([O-])ccc1ccc(-c1c[s][s+]c1)c2.c1cc([O-])ccc1O[O+].c1cc([O-])ccc1[O+]=O.C(/C)(=C/C[S+](c1cc(C(C)(C)C)c([O-])c(C(C)(C)C)c1)C)\C.c1c([N-]c2[n+](-c3ccccc3)c[n](-c3ccccc3)[n]2)cccc1.c1(ccc(C)cc1)S([N-][n+]1ccccc1)(=O)=O.C1CCC[N+]1=[N-] C1C([S+](C)C)([H])[CH-]1.N#C[C-](C1([H])C([N+](CC)(CC)CC)([H])/C/1=C(\C#N)/C#N)C#N.c1c([P+](Cl)(Cl)Cl)c[cH-]c1.C1C(=P(Cl)(Cl)Cl)C=CC=1.[N+](C)(C)(C)CC(=O)[O-].c1ccccc1[P+](c1ccccc1)(c1ccccc1)[C-2][P+](c1ccccc1)(c1ccccc1)c1ccccc1.C(#C[B-](c1ccccc1)(c1ccccc1)c1ccccc1)[P+](C)(c1ccccc1)c1ccccc1.[n+]1(ccc(CC(O)[O-])cc1)C.c12cc([O-])ccc1ccc(-c1c[s][s+]c1)c2.c1cc([O-])ccc1O[O+].c1cc([O-])ccc1[O+]=O.C(/C)(=C/C[S+](c1cc(C(C)(C)C)c([O-])c(C(C)(C)C)c1)C)\C.c1c([N-]c2[n+](-c3ccccc3)c[n](-c3ccccc3)[n]2)cccc1.c1(ccc(C)cc1)S([N-][n+]1ccccc1)(=O)=O.C1CCC[N+]1=[N-] 1748 C1(C)CCC(C)[N+]1(CC)CCCCCCCCCCCC.C(C)OS(=O)(=O)[O-] C1(C)CCC(C)[N+]1(CC)CCCCCCCCCCCC.C(C)OS(=O)(=O)[O-] - 1766 C(O)[C@]12COC(c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12COC(c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,12,24,27,35,46,49,56,68,78,79,r| C(O)[C@]12COC(c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12COC(c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,12,24,27,35,46,49,56,68,78,79,r| + 1766 C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,5,12,13,24,27,35,46,49,56,57,68,71,78,79,r| C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,5,12,13,24,27,35,46,49,56,57,68,71,78,79,r| 1861 C/C=C/N1[C-](C2CCCCC2)C(=O)[O+]=C1C C/C=C/N1[C-](C2CCCCC2)C(=O)[O+]=C1C 1941 N1(C(C)=C(C)N(C(C)C)[C]1)C(C)C |^3:9| N1(C(C)=C(C)N(C(C)C)[C]1)C(C)C |^3:9| 1981 O=C1N2[C@](CCC2)([H])C(=O)N([H])CC(=O)N([H])[C@](C(N([C@](C(N([C@]2([C@](C)([H])SC[C@@](C(=O)N([C@](C(N([C@](C(N([C@](C(N([C@@]3([C@@](C)([H])SC[C@]4(C(=O)N([C@](Cc5[n]c[n]([H])c5)(C(=O)N([C@@](C(N([C@](C(N([C@](C(N([C@@](Cc5c[n]([H])c[n]5)(C(N([C@](C(=O)N(C(C(N([C@@](CCCCN([H])[H])(C(=O)O[H])[H])[H])=O)=C)[H])(C(C)C)[H])[H])=O)[H])[H])=O)([C@@](CC)(C)[H])[H])[H])=O)(CO[H])[H])[H])=O)(CS[C@@](C)([H])[C@@](C(N4[H])=O)([H])N([H])C(=O)[C@@](C)([H])N([H])C3=O)[H])[H])[H])[H])[H])[H])[H])=O)(CCCCN([H])[H])[H])[H])=O)(CCSC)[H])[H])=O)(CC(N([H])[H])=O)[H])[H])([H])N([H])C(=O)CN([H])C(=O)[C@](CCSC)([H])N([H])C(=O)[C@](CC(C)C)([H])N([H])C(=O)[C@](C)([H])N([H])C(=O)CN([H])C2=O)[H])[H])=O)(CCCCN([H])[H])[H])[H])=O)([H])CS[C@@](C)([H])[C@@]1(N(C(=O)[C@@]1(N([H])C(=O)[C@](CC(C)C)([H])N([H])C(=O)C(=C)N([H])C(=O)[C@@]([C@@](CC)(C)[H])([H])N([H])C(=O)[C@](N(C(=O)/C(/N(C([C@]([C@](CC)(C)[H])(N([H])[H])[H])=O)[H])=C(/C)\[H])[H])([H])CSC1)[H])[H])[H] O=C1N2[C@](CCC2)([H])C(=O)N([H])CC(=O)N([H])[C@](C(N([C@](C(N([C@]2([C@](C)([H])SC[C@@](C(=O)N([C@](C(N([C@](C(N([C@](C(N([C@@]3([C@@](C)([H])SC[C@]4(C(=O)N([C@](Cc5[n]c[n]([H])c5)(C(=O)N([C@@](C(N([C@](C(N([C@](C(N([C@@](Cc5c[n]([H])c[n]5)(C(N([C@](C(=O)N(C(C(N([C@@](CCCCN([H])[H])(C(=O)O[H])[H])[H])=O)=C)[H])(C(C)C)[H])[H])=O)[H])[H])=O)([C@@](CC)(C)[H])[H])[H])=O)(CO[H])[H])[H])=O)(CS[C@@](C)([H])[C@@](C(N4[H])=O)([H])N([H])C(=O)[C@@](C)([H])N([H])C3=O)[H])[H])[H])[H])[H])[H])[H])=O)(CCCCN([H])[H])[H])[H])=O)(CCSC)[H])[H])=O)(CC(N([H])[H])=O)[H])[H])([H])N([H])C(=O)CN([H])C(=O)[C@](CCSC)([H])N([H])C(=O)[C@](CC(C)C)([H])N([H])C(=O)[C@](C)([H])N([H])C(=O)CN([H])C2=O)[H])[H])=O)(CCCCN([H])[H])[H])[H])=O)([H])CS[C@@](C)([H])[C@@]1(N(C(=O)[C@@]1(N([H])C(=O)[C@](CC(C)C)([H])N([H])C(=O)C(=C)N([H])C(=O)[C@@]([C@@](CC)(C)[H])([H])N([H])C(=O)[C@](N(C(=O)/C(/N(C([C@]([C@](CC)(C)[H])(N([H])[H])[H])=O)[H])=C(/C)\[H])[H])([H])CSC1)[H])[H])[H] @@ -5151,7 +5151,7 @@ Finished indexing 2026 structures. 304 wrong structures excluded 1541 C(C(C([H])([H])[H])(C([H])([H])[H])N(C([C@@]1(C([H])([H])N(C(c2c([H])c([H])c([H])[n]c2[H])([H])[H])C([H])([H])C([H])([H])N1C([C@](C([C@](C(c1c([H])c([H])c([H])c([H])c1[H])([H])[H])(C(N([C@]1(c2c(c(c(c([H])c2C([H])([H])[C@]1(OC(C(C(C(=O)OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])=O)[H])[H])[H])[H])[H])[H])=O)[H])([H])[H])(O[H])[H])([H])[H])[H])=O)[H])([H])([H])[H] C(C(C([H])([H])[H])(C([H])([H])[H])N(C([C@@]1(C([H])([H])N(C(c2c([H])c([H])c([H])[n]c2[H])([H])[H])C([H])([H])C([H])([H])N1C([C@](C([C@](C(c1c([H])c([H])c([H])c([H])c1[H])([H])[H])(C(N([C@]1(c2c(c(c(c([H])c2C([H])([H])[C@]1(OC(C(C(C(=O)OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC(C(OC([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])=O)[H])[H])[H])[H])[H])[H])=O)[H])([H])[H])(O[H])[H])([H])[H])[H])=O)[H])([H])([H])[H] 1578 C1C([S+](C)C)([H])[CH-]1.N#C[C-](C1([H])C([N+](CC)(CC)CC)([H])/C/1=C(\C#N)/C#N)C#N.c1c([P+](Cl)(Cl)Cl)c[cH-]c1.C1C(=P(Cl)(Cl)Cl)C=CC=1.[N+](C)(C)(C)CC(=O)[O-].c1ccccc1[P+](c1ccccc1)(c1ccccc1)[C-2][P+](c1ccccc1)(c1ccccc1)c1ccccc1.C(#C[B-](c1ccccc1)(c1ccccc1)c1ccccc1)[P+](C)(c1ccccc1)c1ccccc1.[n+]1(ccc(CC(O)[O-])cc1)C.c12cc([O-])ccc1ccc(-c1c[s][s+]c1)c2.c1cc([O-])ccc1O[O+].c1cc([O-])ccc1[O+]=O.C(/C)(=C/C[S+](c1cc(C(C)(C)C)c([O-])c(C(C)(C)C)c1)C)\C.c1c([N-]c2[n+](-c3ccccc3)c[n](-c3ccccc3)[n]2)cccc1.c1(ccc(C)cc1)S([N-][n+]1ccccc1)(=O)=O.C1CCC[N+]1=[N-] C1C([S+](C)C)([H])[CH-]1.N#C[C-](C1([H])C([N+](CC)(CC)CC)([H])/C/1=C(\C#N)/C#N)C#N.c1c([P+](Cl)(Cl)Cl)c[cH-]c1.C1C(=P(Cl)(Cl)Cl)C=CC=1.[N+](C)(C)(C)CC(=O)[O-].c1ccccc1[P+](c1ccccc1)(c1ccccc1)[C-2][P+](c1ccccc1)(c1ccccc1)c1ccccc1.C(#C[B-](c1ccccc1)(c1ccccc1)c1ccccc1)[P+](C)(c1ccccc1)c1ccccc1.[n+]1(ccc(CC(O)[O-])cc1)C.c12cc([O-])ccc1ccc(-c1c[s][s+]c1)c2.c1cc([O-])ccc1O[O+].c1cc([O-])ccc1[O+]=O.C(/C)(=C/C[S+](c1cc(C(C)(C)C)c([O-])c(C(C)(C)C)c1)C)\C.c1c([N-]c2[n+](-c3ccccc3)c[n](-c3ccccc3)[n]2)cccc1.c1(ccc(C)cc1)S([N-][n+]1ccccc1)(=O)=O.C1CCC[N+]1=[N-] 1748 C1(C)CCC(C)[N+]1(CC)CCCCCCCCCCCC.C(C)OS(=O)(=O)[O-] C1(C)CCC(C)[N+]1(CC)CCCCCCCCCCCC.C(C)OS(=O)(=O)[O-] - 1766 C(O)[C@]12COC(c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12COC(c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,12,24,27,35,46,49,56,68,78,79,r| C(O)[C@]12COC(c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12COC(c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,12,24,27,35,46,49,56,68,78,79,r| + 1766 C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,5,12,13,24,27,35,46,49,56,57,68,71,78,79,r| C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,5,12,13,24,27,35,46,49,56,57,68,71,78,79,r| 1981 O=C1N2[C@](CCC2)([H])C(=O)N([H])CC(=O)N([H])[C@](C(N([C@](C(N([C@]2([C@](C)([H])SC[C@@](C(=O)N([C@](C(N([C@](C(N([C@](C(N([C@@]3([C@@](C)([H])SC[C@]4(C(=O)N([C@](Cc5[n]c[n]([H])c5)(C(=O)N([C@@](C(N([C@](C(N([C@](C(N([C@@](Cc5c[n]([H])c[n]5)(C(N([C@](C(=O)N(C(C(N([C@@](CCCCN([H])[H])(C(=O)O[H])[H])[H])=O)=C)[H])(C(C)C)[H])[H])=O)[H])[H])=O)([C@@](CC)(C)[H])[H])[H])=O)(CO[H])[H])[H])=O)(CS[C@@](C)([H])[C@@](C(N4[H])=O)([H])N([H])C(=O)[C@@](C)([H])N([H])C3=O)[H])[H])[H])[H])[H])[H])[H])=O)(CCCCN([H])[H])[H])[H])=O)(CCSC)[H])[H])=O)(CC(N([H])[H])=O)[H])[H])([H])N([H])C(=O)CN([H])C(=O)[C@](CCSC)([H])N([H])C(=O)[C@](CC(C)C)([H])N([H])C(=O)[C@](C)([H])N([H])C(=O)CN([H])C2=O)[H])[H])=O)(CCCCN([H])[H])[H])[H])=O)([H])CS[C@@](C)([H])[C@@]1(N(C(=O)[C@@]1(N([H])C(=O)[C@](CC(C)C)([H])N([H])C(=O)C(=C)N([H])C(=O)[C@@]([C@@](CC)(C)[H])([H])N([H])C(=O)[C@](N(C(=O)/C(/N(C([C@]([C@](CC)(C)[H])(N([H])[H])[H])=O)[H])=C(/C)\[H])[H])([H])CSC1)[H])[H])[H] O=C1N2[C@](CCC2)([H])C(=O)N([H])CC(=O)N([H])[C@](C(N([C@](C(N([C@]2([C@](C)([H])SC[C@@](C(=O)N([C@](C(N([C@](C(N([C@](C(N([C@@]3([C@@](C)([H])SC[C@]4(C(=O)N([C@](Cc5[n]c[n]([H])c5)(C(=O)N([C@@](C(N([C@](C(N([C@](C(N([C@@](Cc5c[n]([H])c[n]5)(C(N([C@](C(=O)N(C(C(N([C@@](CCCCN([H])[H])(C(=O)O[H])[H])[H])=O)=C)[H])(C(C)C)[H])[H])=O)[H])[H])=O)([C@@](CC)(C)[H])[H])[H])=O)(CO[H])[H])[H])=O)(CS[C@@](C)([H])[C@@](C(N4[H])=O)([H])N([H])C(=O)[C@@](C)([H])N([H])C3=O)[H])[H])[H])[H])[H])[H])[H])=O)(CCCCN([H])[H])[H])[H])=O)(CCSC)[H])[H])=O)(CC(N([H])[H])=O)[H])[H])([H])N([H])C(=O)CN([H])C(=O)[C@](CCSC)([H])N([H])C(=O)[C@](CC(C)C)([H])N([H])C(=O)[C@](C)([H])N([H])C(=O)CN([H])C2=O)[H])[H])=O)(CCCCN([H])[H])[H])[H])=O)([H])CS[C@@](C)([H])[C@@]1(N(C(=O)[C@@]1(N([H])C(=O)[C@](CC(C)C)([H])N([H])C(=O)C(=C)N([H])C(=O)[C@@]([C@@](CC)(C)[H])([H])N([H])C(=O)[C@](N(C(=O)/C(/N(C([C@]([C@](CC)(C)[H])(N([H])[H])[H])=O)[H])=C(/C)\[H])[H])([H])CSC1)[H])[H])[H] ** searchSim(N(CC)(CC)C(C)C, 0.9, 1, tanimoto) ** 107 C[N+]([C-](C)C)(C)C C[N+]([C-](C)C)(C)C @@ -5629,7 +5629,7 @@ Finished indexing 2026 structures. 304 wrong structures excluded 1592 c1(c([H])c([H])c(C(C(N(/N=C(\c2c([O-])[n]c3c(c(c(c([H])c3[n]2)[H])[N+](O[H])=O)[H])/C(c2c([H])c([H])c(C(/C(=C3/C(=O)N=C4C(=C(C(=C([H])C4=N/3)[H])N(O[H])O[H])[H])/N=N/C(C(c3c([H])c([H])c([H])c([H])c3[H])([H])[H])=O)(O[H])[H])c([H])c2[H])(O[H])[H])[H])=O)([H])[H])c([H])c1[H])[H] c1(c([H])c([H])c(C(C(N(/N=C(\c2c([O-])[n]c3c(c(c(c([H])c3[n]2)[H])[N+](O[H])=O)[H])/C(c2c([H])c([H])c(C(/C(=C3/C(=O)N=C4C(=C(C(=C([H])C4=N/3)[H])N(O[H])O[H])[H])/N=N/C(C(c3c([H])c([H])c([H])c([H])c3[H])([H])[H])=O)(O[H])[H])c([H])c2[H])(O[H])[H])[H])=O)([H])[H])c([H])c1[H])[H] 1602 c1(cc(C(O[2H])=N)cc(/C(/C)=C(/C)\CC)c1)[C@@]([12CH3])(C)C.c1(cc(C(O[2H])=N)cc(/C(/C)=C(\C)/CC)c1)[C@]([12CH3])(C)C |&1:16,36,r| c1(cc(C(O[2H])=N)cc(/C(/C)=C(/C)\CC)c1)[C@@]([12CH3])(C)C.c1(cc(C(O[2H])=N)cc(/C(/C)=C(\C)/CC)c1)[C@]([12CH3])(C)C |&1:16,36,r| 1646 c1(cc(C(O[2H])=N)cc(/C(/C)=C(/C)\CC)c1)[C@@]([12CH3])(C)C |&1:16,r| c1(cc(C(O[2H])=N)cc(/C(/C)=C(/C)\CC)c1)[C@@]([12CH3])(C)C |&1:16,r| - 1766 C(O)[C@]12COC(c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12COC(c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,12,24,27,35,46,49,56,68,78,79,r| C(O)[C@]12COC(c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12COC(c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,12,24,27,35,46,49,56,68,78,79,r| + 1766 C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,5,12,13,24,27,35,46,49,56,57,68,71,78,79,r| C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,5,12,13,24,27,35,46,49,56,57,68,71,78,79,r| 1855 c1(-c2[n][nH]c3c2cccc3)[n]c2ccc(C(=O)OC)cc2[nH]1 c1(-c2[n][nH]c3c2cccc3)[n]c2ccc(C(=O)OC)cc2[nH]1 1862 c12[n](CCCCCc3c(-c4[n][n][n][n-]4)cc(C)[n]3C)c(OCC)[n]c1cccc2C(NC)=O.c12[n+](CCCCCc3c(-c4[n][n-][n][n]4)cc(C)[n]3C)c(OCC)[nH]c1cccc2/C(=N/C)/[O-].c12[n](CCCCCc3c(-c4[n][n][n][n-]4)cc(C)[n]3C)c(OCC)[n]c1cccc2/C(=N/C)/O.c12[n+](CCCCCc3c(-c4[n][nH][n][n]4)cc(C)[n]3C)c(OCC)[nH]c1cccc2/C(=N/C)/O.c12[n+](CCCCCc3c(-c4[n][n-][n][n]4)cc(C)[n]3C)c(OCC)[nH]c1cccc2C([N-]C)=O c12[n](CCCCCc3c(-c4[n][n][n][n-]4)cc(C)[n]3C)c(OCC)[n]c1cccc2C(NC)=O.c12[n+](CCCCCc3c(-c4[n][n-][n][n]4)cc(C)[n]3C)c(OCC)[nH]c1cccc2/C(=N/C)/[O-].c12[n](CCCCCc3c(-c4[n][n][n][n-]4)cc(C)[n]3C)c(OCC)[n]c1cccc2/C(=N/C)/O.c12[n+](CCCCCc3c(-c4[n][nH][n][n]4)cc(C)[n]3C)c(OCC)[nH]c1cccc2/C(=N/C)/O.c12[n+](CCCCCc3c(-c4[n][n-][n][n]4)cc(C)[n]3C)c(OCC)[nH]c1cccc2C([N-]C)=O 1874 c1c(C(=O)O[Na])c(O)ccc1 c1c(C(=O)O[Na])c(O)ccc1 @@ -11432,7 +11432,7 @@ Finished indexing 2026 structures. 304 wrong structures excluded 1429 C(c1c(/C(/c2c([H])c([H])c([H])c([H])c2S([O-])(=O)=O)=C2/C([H])=C(C(C([H])([H])[H])(C([H])([H])[H])[H])C(=O)C(C(N(C(C(O[H])=O)([H])[H])C(C([O-])=O)([H])[H])([H])[H])=C/2C([H])([H])[H])c([H])c(C(C([H])([H])[H])(C([H])([H])[H])[H])c(O[H])c1C(N(C(C([O-])=O)([H])[H])C(C([O-])=O)([H])[H])([H])[H])([H])([H])[H] C(c1c(/C(/c2c([H])c([H])c([H])c([H])c2S([O-])(=O)=O)=C2/C([H])=C(C(C([H])([H])[H])(C([H])([H])[H])[H])C(=O)C(C(N(C(C(O[H])=O)([H])[H])C(C([O-])=O)([H])[H])([H])[H])=C/2C([H])([H])[H])c([H])c(C(C([H])([H])[H])(C([H])([H])[H])[H])c(O[H])c1C(N(C(C([O-])=O)([H])[H])C(C([O-])=O)([H])[H])([H])[H])([H])([H])[H] 1475 c1ccccc1C[N+](C)(C)C.[Br-] c1ccccc1C[N+](C)(C)C.[Br-] 1594 C(C(C([H])([H])[H])(C([H])([H])[H])OC(N(C(C(C(C(C(N1C([H])([H])C([H])([H])C([H])([H])N(C(C(C(C(C(N(C(c2c([H])c([H])c([H])c([H])c2[H])([H])[H])C(=O)OC(C([H])([H])[H])(C([H])([H])[H])C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])C([H])([H])C([H])([H])N(C(C(C(C(C(N(C(c2c([H])c([H])c([H])c([H])c2[H])([H])[H])C(=O)OC(C([H])([H])[H])(C([H])([H])[H])C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])C([H])([H])C([H])([H])C([H])([H])[N+](C(C(C(C(C(N(C(c2c([H])c([H])c([H])c([H])c2[H])([H])[H])C(=O)OC(C([H])([H])[H])(C([H])([H])[H])C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])(C(C(C(C(C(N(C(c2c([H])c([H])c([H])c([H])c2[H])([H])[H])C(=O)OC(C([H])([H])[H])(C([H])([H])[H])C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])C([H])([H])C([H])([H])C1([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])C(c1c([H])c([H])c([H])c([H])c1[H])([H])[H])=O)([H])([H])[H] C(C(C([H])([H])[H])(C([H])([H])[H])OC(N(C(C(C(C(C(N1C([H])([H])C([H])([H])C([H])([H])N(C(C(C(C(C(N(C(c2c([H])c([H])c([H])c([H])c2[H])([H])[H])C(=O)OC(C([H])([H])[H])(C([H])([H])[H])C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])C([H])([H])C([H])([H])N(C(C(C(C(C(N(C(c2c([H])c([H])c([H])c([H])c2[H])([H])[H])C(=O)OC(C([H])([H])[H])(C([H])([H])[H])C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])C([H])([H])C([H])([H])C([H])([H])[N+](C(C(C(C(C(N(C(c2c([H])c([H])c([H])c([H])c2[H])([H])[H])C(=O)OC(C([H])([H])[H])(C([H])([H])[H])C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])(C(C(C(C(C(N(C(c2c([H])c([H])c([H])c([H])c2[H])([H])[H])C(=O)OC(C([H])([H])[H])(C([H])([H])[H])C([H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])C([H])([H])C([H])([H])C1([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])([H])[H])C(c1c([H])c([H])c([H])c([H])c1[H])([H])[H])=O)([H])([H])[H] - 1766 C(O)[C@]12COC(c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12COC(c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,12,24,27,35,46,49,56,68,78,79,r| C(O)[C@]12COC(c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1C(c1ccccc1)OC2.C(O)[C@]12COC(c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,12,24,27,35,46,49,56,68,78,79,r| + 1766 C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,5,12,13,24,27,35,46,49,56,57,68,71,78,79,r| C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)N1[C@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@@H](c1ccccc1)OC2.C(O)[C@]12CO[C@H](c3ccccc3)[N@@]1[C@H](c1ccccc1)OC2 |&1:2,5,12,13,24,27,35,46,49,56,57,68,71,78,79,r| ** searchSim(N(C)(CC1C=CC=CC=1)C, 0.9, 1, tanimoto) ** 1475 c1ccccc1C[N+](C)(C)C.[Br-] c1ccccc1C[N+](C)(C)C.[Br-] ** searchSim(N(C)(CC1C=CC=CC=1)C, 0.9, 1, tversky 0.3 0.7) ** diff --git a/api/tests/integration/ref/formats/mol_to_smiles.py.out b/api/tests/integration/ref/formats/mol_to_smiles.py.out index 900d00b2b0..1bdefd0c40 100644 --- a/api/tests/integration/ref/formats/mol_to_smiles.py.out +++ b/api/tests/integration/ref/formats/mol_to_smiles.py.out @@ -1,3 +1,3 @@ C1%82(C%83O%84%85)OC%86(C(O%87%88%89)C(O%90%91)C%921O%93%94%95)O%96%97%98.[*:1]%96.[*:2]%93.[*:3]%84.[*:4]%90.[*:5]%87.[*:6]%94%85.[*:7]%95%97.[*:8]%83.[*:9]%91%88.[*:10]%89%98.[*:11]%86.[*:12]%92.[*:13]%82 |$;;;;;;;;;;;;_R1;_R2;_R3;_R4;_R5;_R6;_R7;_R8;_R9;_R10;_R11;_R12;_R13$| [O-][N+](C1=NN=NN1CC1N=NNN=1)=O -C1C(O)=C(C2C=CC(C)=CC=2N)C(C)=CC=1 |o1:3,r,wU:3.12| +C1C(O)=C(C2C=CC(C)=CC=2N)C(C)=CC=1 |o1:3,r,wU:3.12,(25.51,-10.61,;25.51,-12.12,;24.22,-12.87,;26.82,-12.86,;26.82,-14.36,;25.51,-15.12,;25.52,-16.62,;26.82,-17.36,;26.82,-18.86,;28.12,-16.61,;28.12,-15.11,;29.18,-14.05,;28.11,-12.11,;29.41,-12.86,;28.11,-10.61,;26.82,-9.86,)| diff --git a/api/tests/integration/ref/formats/serialize_badmols.py.out b/api/tests/integration/ref/formats/serialize_badmols.py.out index ae892d9358..61136f7275 100644 --- a/api/tests/integration/ref/formats/serialize_badmols.py.out +++ b/api/tests/integration/ref/formats/serialize_badmols.py.out @@ -11,7 +11,7 @@ M V30 1 C 0.0884202 2.7107 0.0 0 M V30 2 C 0.8029 2.29818 0.0 0 M V30 3 C 0.8029 1.4732 0.0 0 M V30 4 C 0.0884202 1.06068 0.0 0 -M V30 5 C -0.626110 1.4732 0.0 0 CFG=3 +M V30 5 C -0.626110 1.4732 0.0 0 CFG=1 M V30 6 C -1.34049 1.06068 0.0 0 CFG=2 M V30 7 C -2.05502 1.4732 0.0 0 M V30 8 C -2.7695 1.06068 0.0 0 @@ -42,7 +42,7 @@ M V30 15 1 5 15 M V30 16 1 1 15 CFG=1 M V30 END BOND M V30 BEGIN COLLECTION -M V30 MDLV30/STERAC1 ATOMS=(1 6) +M V30 MDLV30/STERAC1 ATOMS=(2 5 6) M V30 END COLLECTION M V30 END CTAB M END @@ -59,7 +59,7 @@ M V30 1 C 0.0884202 2.7107 0.0 0 M V30 2 C 0.8029 2.29818 0.0 0 M V30 3 C 0.8029 1.4732 0.0 0 M V30 4 C 0.0884202 1.06068 0.0 0 -M V30 5 C -0.626110 1.4732 0.0 0 CFG=3 +M V30 5 C -0.626110 1.4732 0.0 0 CFG=1 M V30 6 C -1.34049 1.06068 0.0 0 CFG=2 M V30 7 C -2.05502 1.4732 0.0 0 M V30 8 C -2.7695 1.06068 0.0 0 @@ -90,7 +90,7 @@ M V30 15 1 5 15 M V30 16 1 1 15 CFG=1 M V30 END BOND M V30 BEGIN COLLECTION -M V30 MDLV30/STERAC1 ATOMS=(1 6) +M V30 MDLV30/STERAC1 ATOMS=(2 5 6) M V30 MDLV30/HILITE BONDS=(12 1 2 3 4 6 7 8 9 10 11 15 16) M V30 MDLV30/HILITE ATOMS=(12 1 2 3 4 5 6 7 8 9 10 11 15) M V30 END COLLECTION @@ -110,7 +110,7 @@ M V30 1 C 0.0884202 2.7107 0.0 0 M V30 2 C 0.8029 2.29821 0.0 0 M V30 3 C 0.8029 1.47324 0.0 0 M V30 4 C 0.0884202 1.06067 0.0 0 -M V30 5 C -0.626110 1.47324 0.0 0 CFG=3 +M V30 5 C -0.626110 1.47324 0.0 0 CFG=1 M V30 6 C -1.34049 1.06067 0.0 0 CFG=2 M V30 7 C -2.05502 1.47324 0.0 0 M V30 8 C -2.7695 1.06067 0.0 0 @@ -152,7 +152,7 @@ M V30 21 1 5 20 M V30 22 1 1 20 CFG=1 M V30 END BOND M V30 BEGIN COLLECTION -M V30 MDLV30/STERAC1 ATOMS=(1 6) +M V30 MDLV30/STERAC1 ATOMS=(2 5 6) M V30 END COLLECTION M V30 END CTAB M END @@ -169,7 +169,7 @@ M V30 1 C 0.0884202 2.7107 0.0 0 M V30 2 C 0.8029 2.29821 0.0 0 M V30 3 C 0.8029 1.47324 0.0 0 M V30 4 C 0.0884202 1.06067 0.0 0 -M V30 5 C -0.626110 1.47324 0.0 0 CFG=3 +M V30 5 C -0.626110 1.47324 0.0 0 CFG=1 M V30 6 C -1.34049 1.06067 0.0 0 CFG=2 M V30 7 C -2.05502 1.47324 0.0 0 M V30 8 C -2.7695 1.06067 0.0 0 @@ -211,7 +211,7 @@ M V30 21 1 5 20 M V30 22 1 1 20 CFG=1 M V30 END BOND M V30 BEGIN COLLECTION -M V30 MDLV30/STERAC1 ATOMS=(1 6) +M V30 MDLV30/STERAC1 ATOMS=(2 5 6) M V30 MDLV30/HILITE BONDS=(18 1 2 3 4 6 7 8 9 10 11 14 15 16 17 18 19 21 22) M V30 MDLV30/HILITE ATOMS=(18 1 2 3 4 5 6 7 8 9 10 11 13 14 15 16 17 18 20) M V30 END COLLECTION diff --git a/api/tests/integration/ref/formats/serialize_badrxns.py.out b/api/tests/integration/ref/formats/serialize_badrxns.py.out index 5f42e8c406..a276164680 100644 --- a/api/tests/integration/ref/formats/serialize_badrxns.py.out +++ b/api/tests/integration/ref/formats/serialize_badrxns.py.out @@ -41,7 +41,7 @@ M V30 COUNTS 15 16 0 0 0 M V30 BEGIN ATOM M V30 1 C 0.0884 2.7107 0.0 0 M V30 2 C -0.6261 2.2982 0.0 0 -M V30 3 C -0.6261 1.4732 0.0 0 CFG=3 +M V30 3 C -0.6261 1.4732 0.0 0 CFG=1 M V30 4 C 0.0884 1.0607 0.0 0 M V30 5 C 0.8029 1.4732 0.0 0 M V30 6 C 0.8029 2.2982 0.0 0 @@ -74,7 +74,7 @@ M V30 15 2 13 14 M V30 16 1 13 15 M V30 END BOND M V30 BEGIN COLLECTION -M V30 MDLV30/STERAC1 ATOMS=(1 7) +M V30 MDLV30/STERAC1 ATOMS=(2 3 7) M V30 END COLLECTION M V30 END CTAB M V30 END PRODUCT @@ -124,7 +124,7 @@ M V30 1 C 0.0884202 2.7107 0.0 0 M V30 2 C 0.8029 2.29818 0.0 0 M V30 3 C 0.8029 1.4732 0.0 0 M V30 4 C 0.0884202 1.06068 0.0 0 -M V30 5 C -0.626110 1.4732 0.0 0 CFG=3 +M V30 5 C -0.626110 1.4732 0.0 0 CFG=1 M V30 6 C -1.34049 1.06068 0.0 0 CFG=2 M V30 7 C -2.05502 1.4732 0.0 0 M V30 8 C -2.7695 1.06068 0.0 0 @@ -155,7 +155,7 @@ M V30 15 1 5 15 M V30 16 1 1 15 CFG=1 M V30 END BOND M V30 BEGIN COLLECTION -M V30 MDLV30/STERAC1 ATOMS=(1 6) +M V30 MDLV30/STERAC1 ATOMS=(2 5 6) M V30 END COLLECTION M V30 END CTAB M V30 END PRODUCT @@ -205,7 +205,7 @@ M V30 1 C 0.0884202 2.7107 0.0 0 M V30 2 C 0.8029 2.29818 0.0 0 M V30 3 C 0.8029 1.4732 0.0 0 M V30 4 C 0.0884202 1.06068 0.0 0 -M V30 5 C -0.626110 1.4732 0.0 0 CFG=3 +M V30 5 C -0.626110 1.4732 0.0 0 CFG=1 M V30 6 C -1.34049 1.06068 0.0 0 CFG=2 M V30 7 C -2.05502 1.4732 0.0 0 M V30 8 C -2.7695 1.06068 0.0 0 @@ -236,7 +236,7 @@ M V30 15 1 5 15 M V30 16 1 1 15 CFG=1 M V30 END BOND M V30 BEGIN COLLECTION -M V30 MDLV30/STERAC1 ATOMS=(1 6) +M V30 MDLV30/STERAC1 ATOMS=(2 5 6) M V30 MDLV30/HILITE BONDS=(6 1 2 3 4 15 16) M V30 MDLV30/HILITE ATOMS=(6 1 2 3 4 5 15) M V30 END COLLECTION @@ -287,7 +287,7 @@ M V30 COUNTS 20 22 0 0 0 M V30 BEGIN ATOM M V30 1 C 0.0884 2.7107 0.0 0 M V30 2 C -0.6261 2.2982 0.0 0 -M V30 3 C -0.6261 1.4732 0.0 0 CFG=3 +M V30 3 C -0.6261 1.4732 0.0 0 CFG=1 M V30 4 C 0.0884 1.0607 0.0 0 M V30 5 C 0.8029 1.4732 0.0 0 M V30 6 C 0.8029 2.2982 0.0 0 @@ -331,7 +331,7 @@ M V30 21 4 18 19 M V30 22 4 19 20 M V30 END BOND M V30 BEGIN COLLECTION -M V30 MDLV30/STERAC1 ATOMS=(1 7) +M V30 MDLV30/STERAC1 ATOMS=(2 3 7) M V30 END COLLECTION M V30 END CTAB M V30 END PRODUCT @@ -381,7 +381,7 @@ M V30 1 C 0.0884202 2.7107 0.0 0 M V30 2 C 0.8029 2.29821 0.0 0 M V30 3 C 0.8029 1.47324 0.0 0 M V30 4 C 0.0884202 1.06067 0.0 0 -M V30 5 C -0.626110 1.47324 0.0 0 CFG=3 +M V30 5 C -0.626110 1.47324 0.0 0 CFG=1 M V30 6 C -1.34049 1.06067 0.0 0 CFG=2 M V30 7 C -2.05502 1.47324 0.0 0 M V30 8 C -2.7695 1.06067 0.0 0 @@ -423,7 +423,7 @@ M V30 21 1 5 20 M V30 22 1 1 20 CFG=1 M V30 END BOND M V30 BEGIN COLLECTION -M V30 MDLV30/STERAC1 ATOMS=(1 6) +M V30 MDLV30/STERAC1 ATOMS=(2 5 6) M V30 END COLLECTION M V30 END CTAB M V30 END PRODUCT @@ -473,7 +473,7 @@ M V30 1 C 0.0884202 2.7107 0.0 0 M V30 2 C 0.8029 2.29821 0.0 0 M V30 3 C 0.8029 1.47324 0.0 0 M V30 4 C 0.0884202 1.06067 0.0 0 -M V30 5 C -0.626110 1.47324 0.0 0 CFG=3 +M V30 5 C -0.626110 1.47324 0.0 0 CFG=1 M V30 6 C -1.34049 1.06067 0.0 0 CFG=2 M V30 7 C -2.05502 1.47324 0.0 0 M V30 8 C -2.7695 1.06067 0.0 0 @@ -515,7 +515,7 @@ M V30 21 1 5 20 M V30 22 1 1 20 CFG=1 M V30 END BOND M V30 BEGIN COLLECTION -M V30 MDLV30/STERAC1 ATOMS=(1 6) +M V30 MDLV30/STERAC1 ATOMS=(2 5 6) M V30 MDLV30/HILITE BONDS=(6 1 2 3 4 21 22) M V30 MDLV30/HILITE ATOMS=(6 1 2 3 4 5 20) M V30 END COLLECTION diff --git a/api/tests/integration/ref/formats/smiles.py.out b/api/tests/integration/ref/formats/smiles.py.out index 8d8a2820b4..27d92a67c4 100644 --- a/api/tests/integration/ref/formats/smiles.py.out +++ b/api/tests/integration/ref/formats/smiles.py.out @@ -74,4 +74,10 @@ CCCCC |Sg:n:1,2,3::hh| *** Atropisomers *** atropisomer: C1=CC=C(C)C(C2=C(N)C=C(C)C=C2)=C1O |o1:5,r,wU:5.4| -C1=CC=C(C)C(C2=C(N)C=C(C)C=C2)=C1O |o1:5,r,wU:5.4| +C1=CC=C(C)C(C2=C(N)C=C(C)C=C2)=C1O |o1:5,r,wU:5.4,(2.40,-1.39,;3.20,-0.00,;2.40,1.39,;0.80,1.39,;0.00,2.77,;0.00,0.00,;-1.60,0.00,;-2.40,1.39,;-1.60,2.77,;-4.00,1.39,;-4.80,0.00,;-6.40,0.00,;-4.00,-1.39,;-2.40,-1.39,;0.80,-1.39,;-0.00,-2.77,)| +atropisomer: +C1C(O)=C(C2C=CC(C)=CC=2N)C(C)=CC=1 |wU:3.12,wD:3.3| +C1C(O)=C(C2C=CC(C)=CC=2N)C(C)=CC=1 |wU:3.12,wD:3.3,(-2.40,1.39,;-0.80,1.39,;-0.00,2.77,;0.00,0.00,;1.60,0.00,;2.40,1.39,;4.00,1.39,;4.80,0.00,;6.40,0.00,;4.00,-1.39,;2.40,-1.39,;1.60,-2.77,;-0.80,-1.39,;0.00,-2.77,;-2.40,-1.39,;-3.20,-0.00,)| +atropisomer: +C1C(O)=C(C2C=CC(C)=CC=2N)C(C)=CC=1 |w:3.3,3.12| +C1C(O)=C(C2C=CC(C)=CC=2N)C(C)=CC=1 |w:3.3,3.12,(-2.40,1.39,;-0.80,1.39,;-0.00,2.77,;0.00,0.00,;1.60,0.00,;2.40,1.39,;4.00,1.39,;4.80,0.00,;6.40,0.00,;4.00,-1.39,;2.40,-1.39,;1.60,-2.77,;-0.80,-1.39,;0.00,-2.77,;-2.40,-1.39,;-3.20,-0.00,)| diff --git a/api/tests/integration/ref/rsmiles/rsmiles2.py.out b/api/tests/integration/ref/rsmiles/rsmiles2.py.out index 7f6b65fa3d..a41a34b572 100644 --- a/api/tests/integration/ref/rsmiles/rsmiles2.py.out +++ b/api/tests/integration/ref/rsmiles/rsmiles2.py.out @@ -866,8 +866,8 @@ CO[CH:10](OC)[O:7][CH3:1].[CH3:2][O:8][C:12](=[O:4])[CH2:6][C:11](=[O:5])[O:9][C [C:1]1([Si](C)(C)C)([O:21][CH2:3]1)[CH:2](OS(=O)(=O)C)[C:6]1([CH2:13][CH2:15][CH2:19][CH3:20])[O:22][CH2:11]1>>[C:6]1([CH2:13][CH2:15][CH2:19][CH3:20])=[CH:11][O:22][C:1]([CH2:3]F)=[CH:2]1.[C:6]1([CH2:13][CH2:15][CH2:19][CH3:20])=[CH:11][O:22][C:1]([CH2:3][OH:21])=[CH:2]1 [CH3:1][CH2:6][CH2:2][CH2:3][C:10]1([CH2:5][O:8]1)[CH:9](OS(C)(=O)=O)[C:11]1([CH2:4][O:7]1)[Si](C)(C)C>>[CH3:1][CH2:6][CH2:2][CH2:3][C:10]1[CH:9]=[C:11]([CH2:4][OH:7])[O:8][CH:5]=1.[CH3:1][CH2:6][CH2:2][CH2:3][C:10]1[CH:9]=[C:11]([CH2:4]F)[O:8][CH:5]=1 |f:1.2| *** 289 *** -[C:1]1([O:48][CH2:4]1)([C@@:3]1([H])[CH2:9][CH2:17][C@@:14]2([H])[C@:24]3([H])[CH2:27][CH:29]=[C:30]4[CH2:33][C@H:35]([CH2:34][CH2:31][C@:28]4([CH3:32])[C@@:26]3([H])[CH2:25][CH2:15][C@:8]12[CH3:16])[O:36][Si](C)(C)C(C)(C)C)[CH:2](OS(=O)(=O)C)[C:6]1([Si](C)(C)C)[O:49][CH2:10]1>>[C@:8]12([CH3:16])[CH2:15][CH2:25][C@:26]3([H])[C@@:28]4([CH3:32])[CH2:31][CH2:34][C@H:35]([OH:36])[CH2:33][C:30]4=[CH:29][CH2:27][C@@:24]3([H])[C@:14]1([H])[CH2:17][CH2:9][C@:3]2([H])[C:1]1=[CH:4][O:48][C:6]([CH2:10]F)=[CH:2]1.[C@:8]12([CH3:16])[CH2:15][CH2:25][C@:26]3([H])[C@@:28]4([CH3:32])[CH2:31][CH2:34][C@H:35]([OH:36])[CH2:33][C:30]4=[CH:29][CH2:27][C@@:24]3([H])[C@:14]1([H])[CH2:17][CH2:9][C@:3]2([H])[C:1]1=[CH:4][O:48][C:6]([CH2:10][OH:49])=[CH:2]1 |w:0,34,40,a:3,7,9,15,18,20,24,47,51,53,57,63,65,69,78,82,84,88,94,96,100| -C[Si](C)(C)[C:24]1([CH2:9][O:16]1)[CH:17](OS(C)(=O)=O)[C:25]1([CH2:3][O:14]1)[C@H:18]1[CH2:4][CH2:5][C@H:22]2[C@@H:19]3[CH2:10][CH:13]=[C:23]4[CH2:6][C@H:20]([CH2:7][CH2:11][C@:27]4([CH3:1])[C@H:21]3[CH2:8][CH2:12][C@@:26]21[CH3:2])[O:15][Si](C)(C)C(C)(C)C>>[CH3:2][C@:26]12[CH2:12][CH2:8][C@H:21]3[C@@H:19]([CH2:10][CH:13]=[C:23]4[CH2:6][C@@H:20]([OH:15])[CH2:7][CH2:11][C@@:27]43[CH3:1])[C@@H:22]1[CH2:5][CH2:4][C@@H:18]2[C:25]1[CH:17]=[C:24]([CH2:9]F)[O:14][CH:3]=1.[CH3:1][C@:27]12[CH2:11][CH2:7][C@H:20]([OH:15])[CH2:6][C:23]1=[CH:13][CH2:10][C@@H:19]1[C@@H:21]2[CH2:8][CH2:12][C@:26]2([CH3:2])[C@H:18]([CH2:4][CH2:5][C@H:22]21)[C:25]1[CH:17]=[C:24]([CH2:9][OH:16])[O:14][CH:3]=1 |f:1.2,w:4,7,13,a:16,19,20,25,28,30,33,44,47,48,53,57,59,62,71,74,80,81,84,86,89| +[C@:1]1([O:48][CH2:4]1)([C@@:3]1([H])[CH2:9][CH2:17][C@@:14]2([H])[C@:24]3([H])[CH2:27][CH:29]=[C:30]4[CH2:33][C@H:35]([CH2:34][CH2:31][C@:28]4([CH3:32])[C@@:26]3([H])[CH2:25][CH2:15][C@:8]12[CH3:16])[O:36][Si](C)(C)C(C)(C)C)[CH:2](OS(=O)(=O)C)[C:6]1([Si](C)(C)C)[O:49][CH2:10]1>>[C@:8]12([CH3:16])[CH2:15][CH2:25][C@:26]3([H])[C@@:28]4([CH3:32])[CH2:31][CH2:34][C@H:35]([OH:36])[CH2:33][C:30]4=[CH:29][CH2:27][C@@:24]3([H])[C@:14]1([H])[CH2:17][CH2:9][C@:3]2([H])[C:1]1=[CH:4][O:48][C:6]([CH2:10]F)=[CH:2]1.[C@:8]12([CH3:16])[CH2:15][CH2:25][C@:26]3([H])[C@@:28]4([CH3:32])[CH2:31][CH2:34][C@H:35]([OH:36])[CH2:33][C:30]4=[CH:29][CH2:27][C@@:24]3([H])[C@:14]1([H])[CH2:17][CH2:9][C@:3]2([H])[C:1]1=[CH:4][O:48][C:6]([CH2:10][OH:49])=[CH:2]1 |a:0,3,7,9,15,18,20,24,47,51,53,57,63,65,69,78,82,84,88,94,96,100,w:34,40| +C[Si](C)(C)[C:24]1([CH2:9][O:16]1)[CH:17](OS(C)(=O)=O)[C@:25]1([CH2:3][O:14]1)[C@H:18]1[CH2:4][CH2:5][C@H:22]2[C@@H:19]3[CH2:10][CH:13]=[C:23]4[CH2:6][C@H:20]([CH2:7][CH2:11][C@:27]4([CH3:1])[C@H:21]3[CH2:8][CH2:12][C@@:26]21[CH3:2])[O:15][Si](C)(C)C(C)(C)C>>[CH3:2][C@:26]12[CH2:12][CH2:8][C@H:21]3[C@@H:19]([CH2:10][CH:13]=[C:23]4[CH2:6][C@@H:20]([OH:15])[CH2:7][CH2:11][C@@:27]43[CH3:1])[C@@H:22]1[CH2:5][CH2:4][C@@H:18]2[C:25]1[CH:17]=[C:24]([CH2:9]F)[O:14][CH:3]=1.[CH3:1][C@:27]12[CH2:11][CH2:7][C@H:20]([OH:15])[CH2:6][C:23]1=[CH:13][CH2:10][C@@H:19]1[C@@H:21]2[CH2:8][CH2:12][C@:26]2([CH3:2])[C@H:18]([CH2:4][CH2:5][C@H:22]21)[C:25]1[CH:17]=[C:24]([CH2:9][OH:16])[O:14][CH:3]=1 |f:1.2,w:4,7,a:13,16,19,20,25,28,30,33,44,47,48,53,57,59,62,71,74,80,81,84,86,89| *** 290 *** [C@H:1]1([CH2:4][C:9](=[O:13])[O:12][CH3:14])[C:3](=[O:8])[CH2:7][C@@:10]2([H])[CH:11]=[CH:6][C@:2]1([H])[O:29]2.S(=O)(=O)(C(F)(F)F)O[Si:22]([CH3:28])([CH3:27])[CH3:26]>>[CH:10]1([O:29][Si:22]([CH3:28])([CH3:27])[CH3:26])[CH2:11][CH2:6][CH:2]=[C:1]([CH2:4][C:9](=[O:13])[O:12][CH3:14])[C:3](=[O:8])[CH2:7]1.[C@@H:2]1([CH2:6][CH2:11][CH:10]=[CH:7][C:3](=[O:8])[C@@H:1]1[CH2:4][C:9](=[O:13])[O:12][CH3:14])[O:29][Si:22]([CH3:28])([CH3:27])[CH3:26].[C@@:3]12([CH:7]=[CH:10][CH2:11][CH2:6][C@H:2]([O:29][Si:22]([CH3:28])([CH3:27])[CH3:26])[C@@:1]1([H])[C@@H:4]2[C:9](=[O:13])[O:12][CH3:14])[O:8][Si:22]([CH3:28])([CH3:27])[CH3:26] |&1:0,9,13,46,53,64,69,75,77| [CH3:1][O:12][C:16](=[O:6])[CH2:8][C@@H:13]1[C@@H:14]2[CH:10]=[CH:9][C@H:15]([CH2:7][C:17]1=[O:5])[O:11]2.[CH3:2][Si:18]([CH3:3])([CH3:4])OS(=O)(=O)C(F)(F)F>>[CH3:4][Si:18]([CH3:2])([CH3:3])[O:11][C@@H:14]1[CH2:10][CH2:9][CH:15]=[CH:7][C:17](=[O:5])[C@H:13]1[CH2:8][C:16](=[O:6])[O:12][CH3:1].[CH3:4][Si:18]([CH3:2])([CH3:3])[O:11][CH:15]1[CH2:7][C:17](=[O:5])[C:13]([CH2:8][C:16](=[O:6])[O:12][CH3:1])=[CH:14][CH2:10][CH2:9]1.[CH3:3][Si:18]([CH3:2])([CH3:4])[O:11][C@@H:14]1[CH2:10][CH2:9][CH:15]=[CH:7][C@:17]2([O:5][Si:18]([CH3:3])([CH3:2])[CH3:4])[C@H:13]1[C@H:8]2[C:16](=[O:6])[O:12][CH3:1] |f:0.1,2.3.4,&1:5,6,9,31,38,67,72,78,79| diff --git a/api/tests/integration/ref/standardize/basic.py.out b/api/tests/integration/ref/standardize/basic.py.out index 55e9d14b1e..24d4e8a98b 100644 --- a/api/tests/integration/ref/standardize/basic.py.out +++ b/api/tests/integration/ref/standardize/basic.py.out @@ -1115,8 +1115,8 @@ M END 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 0.0000 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 0.0000 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 - 1 2 1 0 0 0 0 - 2 3 1 0 0 0 0 + 2 1 1 4 0 0 0 + 2 3 1 4 0 0 0 2 4 1 0 0 0 0 4 5 4 0 0 0 0 5 6 4 0 0 0 0 @@ -1153,7 +1153,7 @@ M END 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 0.0000 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 0.0000 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 - 1 2 1 0 0 0 0 + 2 1 1 0 0 0 0 2 3 1 0 0 0 0 2 4 1 0 0 0 0 4 5 4 0 0 0 0 @@ -1192,8 +1192,8 @@ M END 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 0.0000 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 0.0000 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 - 1 2 1 0 0 0 0 - 2 3 1 0 0 0 0 + 2 1 1 4 0 0 0 + 2 3 1 4 0 0 0 2 4 1 0 0 0 0 4 5 4 0 0 0 0 5 6 4 0 0 0 0 @@ -1230,8 +1230,8 @@ M END 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 0.0000 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 0.0000 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 - 1 2 1 0 0 0 0 - 2 3 1 0 0 0 0 + 2 1 1 4 0 0 0 + 2 3 1 4 0 0 0 2 4 1 0 0 0 0 4 5 4 0 0 0 0 5 6 4 0 0 0 0 diff --git a/api/tests/integration/ref/stereo/bidirectional.py.out b/api/tests/integration/ref/stereo/bidirectional.py.out index 99901048f5..6f337825d7 100644 --- a/api/tests/integration/ref/stereo/bidirectional.py.out +++ b/api/tests/integration/ref/stereo/bidirectional.py.out @@ -28,7 +28,7 @@ test2.mol stereocenters: one bond up, one bond down -- indefinite case near atom 04.mol C1CCC([C@H]2C=CC(N([H])C2=O)=O)O1 |&1:4,r| 05.mol C1CC[C@@H]([C@H]2C=CC(N([H])C2=O)=O)O1 |&1:3,4,r| 06.mol C1CC[C@@H](C2C=CC(N([H])C2=O)=O)O1 |&1:3,r| -07.mol C1CCC(C2C=CC(N([H])C2=O)=O)O1 +07.mol C1CCC(C2C=CC(N([H])C2=O)=O)O1 |&1:3,r,wU:3.2,wD:3.3,(-2.06,-0.81,;-1.79,-1.62,;-0.94,-1.62,;-0.70,-0.78,;0.04,-0.14,;-0.15,0.64,;0.46,1.24,;1.22,1.01,;1.53,0.12,;2.06,-0.05,;0.82,-0.39,;1.04,-1.18,;1.84,1.62,;-1.41,-0.31,)| 08.mol C1CC[C@@](C)(C2C=CC(N([H])C2=O)=O)O1 |&1:3,r| 09.mol C1CC[C@@](C)(C2C=CC(N([H])C2=O)=O)O1 |&1:3,r| 10.mol C1CCC(C)(C2C=CC(N([H])C2=O)=O)O1 diff --git a/api/tests/integration/tests/basic/ref/crazystereo.ket b/api/tests/integration/tests/basic/ref/crazystereo.ket index fe4a79bc83..e381f2a6b5 100644 --- a/api/tests/integration/tests/basic/ref/crazystereo.ket +++ b/api/tests/integration/tests/basic/ref/crazystereo.ket @@ -216,7 +216,8 @@ 9.062226295471192, 0.7499902248382568, 0.0 - ] + ], + "stereoLabel": "&1" }, { "label": "C", diff --git a/api/tests/integration/tests/exact/reload.py b/api/tests/integration/tests/exact/reload.py index 5b8297aee4..3297da7b09 100644 --- a/api/tests/integration/tests/exact/reload.py +++ b/api/tests/integration/tests/exact/reload.py @@ -41,7 +41,7 @@ def testMol(mol): perm_smiles = perm_mol.smiles() if not indigo.exactMatch(mol, perm_mol): msg = ( - " Exact: %s after reload from smiles %s. Permuted canonical smiles: %s\n %s %s" + " Exact: %s after reload from smiles %s. Permuted canonical smiles: %s" % (mol.name(), base_smiles, perm_smiles) ) print(msg) diff --git a/api/tests/integration/tests/formats/ref/acd2d_err.ket b/api/tests/integration/tests/formats/ref/acd2d_err.ket index 8a132ba64f..3f3f732ee1 100644 --- a/api/tests/integration/tests/formats/ref/acd2d_err.ket +++ b/api/tests/integration/tests/formats/ref/acd2d_err.ket @@ -54263,7 +54263,8 @@ 0.03449999913573265, 1.1758999824523926, 0.0 - ] + ], + "stereoLabel": "&1" }, { "label": "C", diff --git a/api/tests/integration/tests/formats/ref/acd2d_err3.sdf b/api/tests/integration/tests/formats/ref/acd2d_err3.sdf index 7f61be9c7b..ade3ac61b4 100644 --- a/api/tests/integration/tests/formats/ref/acd2d_err3.sdf +++ b/api/tests/integration/tests/formats/ref/acd2d_err3.sdf @@ -8493,6 +8493,7 @@ M V30 30 1 13 25 CFG=3 M V30 31 1 14 26 CFG=3 M V30 END BOND M V30 BEGIN COLLECTION +M V30 MDLV30/STEABS ATOMS=(1 1) M V30 MDLV30/STERAC1 ATOMS=(7 2 9 10 11 12 13 14) M V30 END COLLECTION M V30 END CTAB diff --git a/api/tests/integration/tests/formats/smiles.py b/api/tests/integration/tests/formats/smiles.py index 60885b3514..e650df5a2c 100644 --- a/api/tests/integration/tests/formats/smiles.py +++ b/api/tests/integration/tests/formats/smiles.py @@ -117,7 +117,11 @@ print(indigo.loadMolecule(sm).smiles()) print("*** Atropisomers ***") -mols_smiles = ["C1C(O)=C(C2C=CC(C)=CC=2N)C(C)=CC=1 |o1:3,r,wU:3.12|"] +mols_smiles = [ + "C1C(O)=C(C2C=CC(C)=CC=2N)C(C)=CC=1 |o1:3,r,wU:3.12|", + "C1=CC=C(C)C(C2=C(N)C=C(C)C=C2)=C1O |wU:5.4,wD:5.5|", + "C1=CC=C(C)C(C2=C(N)C=C(C)C=C2)=C1O |w:5.4,5.5|", +] for sm in mols_smiles: print("atropisomer:") mol = indigo.loadMolecule(sm) diff --git a/bingo/tests/data/molecules/checkmolecule/std.json b/bingo/tests/data/molecules/checkmolecule/std.json index 975559c2ee..a4d438ba0d 100644 --- a/bingo/tests/data/molecules/checkmolecule/std.json +++ b/bingo/tests/data/molecules/checkmolecule/std.json @@ -8352,17 +8352,17 @@ { "query_id": 1671, "query_type": "checkmolecule", - "expected": "molfile loader: direction of bond #22 makes no sense" + "expected": "molfile loader: direction of bond #185 makes no sense" }, { "query_id": 1672, "query_type": "checkmolecule", - "expected": "molfile loader: direction of bond #22 makes no sense" + "expected": "molfile loader: direction of bond #185 makes no sense" }, { "query_id": 1673, "query_type": "checkmolecule", - "expected": "molfile loader: direction of bond #177 makes no sense" + "expected": "molfile loader: direction of bond #185 makes no sense" }, { "query_id": 1674, diff --git a/bingo/tests/data/molecules/cml/std.json b/bingo/tests/data/molecules/cml/std.json index 023a75fd81..3462218872 100644 --- a/bingo/tests/data/molecules/cml/std.json +++ b/bingo/tests/data/molecules/cml/std.json @@ -3722,7 +3722,7 @@ { "query_id": 745, "query_type": "cml", - "expected": "\n\n \n \n \n \n \n 1\n \n \n 1\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n 1\n \n \n \n \n \n 1\n \n \n 1\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n 1\n \n \n 1\n \n \n \n \n \n 1\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n 1\n \n \n 1\n \n \n \n \n 1\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n T\n \n \n \n \n C\n \n \n \n C\n \n \n C\n \n \n \n C\n \n \n \n C\n \n \n \n C\n \n \n C\n \n \n \n C\n \n \n \n \n W\n \n \n \n \n \n W\n \n \n W\n \n \n \n \n \n \n \n W\n \n \n \n \n \n W\n \n \n W\n \n \n \n \n \n \n \n \n T\n \n \n \n T\n \n \n \n \n C\n \n \n \n C\n \n \n C\n \n \n \n C\n \n \n \n \n \n T\n \n \n \n T\n \n \n \n \n \n W\n \n \n \n \n \n W\n \n \n W\n \n \n \n \n \n \n \n \n T\n \n \n \n \n W\n \n \n \n \n \n W\n \n \n W\n \n \n \n \n \n \n \n \n T\n \n \n \n T\n \n \n \n \n C\n \n \n \n C\n \n \n C\n \n \n \n C\n \n \n \n \n\n" + "expected": "11111111111TCCCCCCCCWWWWWWTTCCCCTTWWWTWWWTTCCCC\n" }, { "query_id": 746, diff --git a/bingo/tests/data/molecules/compactmolecule/std.json b/bingo/tests/data/molecules/compactmolecule/std.json index 3402f39342..2a715c6499 100644 --- a/bingo/tests/data/molecules/compactmolecule/std.json +++ b/bingo/tests/data/molecules/compactmolecule/std.json @@ -3722,7 +3722,7 @@ { "query_id": 745, "query_type": "compactmolecule(0)", - "expected": "942f6642b01222a2a8d1b953c4477764" + "expected": "757a56ddfcbfe7e377b87037fb415a40" }, { "query_id": 746, diff --git a/bingo/tests/data/reactions/compactreaction/std.json b/bingo/tests/data/reactions/compactreaction/std.json index 3e71814fab..cd8d134a43 100644 --- a/bingo/tests/data/reactions/compactreaction/std.json +++ b/bingo/tests/data/reactions/compactreaction/std.json @@ -1447,7 +1447,7 @@ { "query_id": 290, "query_type": "compactreaction(0)", - "expected": "871fbada43b7c6c4b1c7a3298791bb1d" + "expected": "b0deb28fd1bd4350908254566b88b994" }, { "query_id": 291, diff --git a/bingo/tests/data/reactions/rsmiles/std.json b/bingo/tests/data/reactions/rsmiles/std.json index df1ee6bb33..d2014162c3 100644 --- a/bingo/tests/data/reactions/rsmiles/std.json +++ b/bingo/tests/data/reactions/rsmiles/std.json @@ -1447,7 +1447,7 @@ { "query_id": 290, "query_type": "rsmiles", - "expected": "[C:1]1([O:48][CH2:4]1)([C@@:3]1([H])[CH2:9][CH2:17][C@@:14]2([H])[C@:24]3([H])[CH2:27][CH:29]=[C:30]4[CH2:33][C@H:35]([CH2:34][CH2:31][C@:28]4([CH3:32])[C@@:26]3([H])[CH2:25][CH2:15][C@:8]12[CH3:16])[O:36][Si](C)(C)C(C)(C)C)[CH:2](OS(=O)(=O)C)[C:6]1([Si](C)(C)C)[O:49][CH2:10]1>>[C@:8]12([CH3:16])[CH2:15][CH2:25][C@:26]3([H])[C@@:28]4([CH3:32])[CH2:31][CH2:34][C@H:35]([OH:36])[CH2:33][C:30]4=[CH:29][CH2:27][C@@:24]3([H])[C@:14]1([H])[CH2:17][CH2:9][C@:3]2([H])[C:1]1=[CH:4][O:48][C:6]([CH2:10]F)=[CH:2]1.[C@:8]12([CH3:16])[CH2:15][CH2:25][C@:26]3([H])[C@@:28]4([CH3:32])[CH2:31][CH2:34][C@H:35]([OH:36])[CH2:33][C:30]4=[CH:29][CH2:27][C@@:24]3([H])[C@:14]1([H])[CH2:17][CH2:9][C@:3]2([H])[C:1]1=[CH:4][O:48][C:6]([CH2:10][OH:49])=[CH:2]1 |w:0,34,40,a:3,7,9,15,18,20,24,47,51,53,57,63,65,69,78,82,84,88,94,96,100|" + "expected": "[C@:1]1([O:48][CH2:4]1)([C@@:3]1([H])[CH2:9][CH2:17][C@@:14]2([H])[C@:24]3([H])[CH2:27][CH:29]=[C:30]4[CH2:33][C@H:35]([CH2:34][CH2:31][C@:28]4([CH3:32])[C@@:26]3([H])[CH2:25][CH2:15][C@:8]12[CH3:16])[O:36][Si](C)(C)C(C)(C)C)[CH:2](OS(=O)(=O)C)[C:6]1([Si](C)(C)C)[O:49][CH2:10]1>>[C@:8]12([CH3:16])[CH2:15][CH2:25][C@:26]3([H])[C@@:28]4([CH3:32])[CH2:31][CH2:34][C@H:35]([OH:36])[CH2:33][C:30]4=[CH:29][CH2:27][C@@:24]3([H])[C@:14]1([H])[CH2:17][CH2:9][C@:3]2([H])[C:1]1=[CH:4][O:48][C:6]([CH2:10]F)=[CH:2]1.[C@:8]12([CH3:16])[CH2:15][CH2:25][C@:26]3([H])[C@@:28]4([CH3:32])[CH2:31][CH2:34][C@H:35]([OH:36])[CH2:33][C:30]4=[CH:29][CH2:27][C@@:24]3([H])[C@:14]1([H])[CH2:17][CH2:9][C@:3]2([H])[C:1]1=[CH:4][O:48][C:6]([CH2:10][OH:49])=[CH:2]1 |a:0,3,7,9,15,18,20,24,47,51,53,57,63,65,69,78,82,84,88,94,96,100,w:34,40|" }, { "query_id": 291, diff --git a/bingo/tests/test_rsmiles/test_rsmiles.py b/bingo/tests/test_rsmiles/test_rsmiles.py index a6e774b14a..2d98f7639d 100644 --- a/bingo/tests/test_rsmiles/test_rsmiles.py +++ b/bingo/tests/test_rsmiles/test_rsmiles.py @@ -2,7 +2,6 @@ from ..helpers import assert_calculate_query, query_cases - class TestRsmiles: @pytest.mark.parametrize("query_id, expected", query_cases("rsmiles")) def test_molecular_weight(self, db, entities, query_id, expected): diff --git a/core/indigo-core/molecule/base_molecule.h b/core/indigo-core/molecule/base_molecule.h index 7b3256d2bd..51f33c6266 100644 --- a/core/indigo-core/molecule/base_molecule.h +++ b/core/indigo-core/molecule/base_molecule.h @@ -195,7 +195,6 @@ namespace indigo void removeAttachmentPointsFromAtom(int atom_index); int attachmentPointCount() const; void removeAttachmentPoints(); - void getAttachmentIndicesForAtom(int atom_idx, Array& res); virtual bool isSaturatedAtom(int idx) = 0; @@ -247,8 +246,6 @@ namespace indigo void clearCIP(); CIPDesc getAtomCIP(int atom_idx); CIPDesc getBondCIP(int bond_idx); - bool isAtropisomerismReferenceAtom(int atom_idx); - bool isRotationBond(int bond_idx); void setAtomCIP(int atom_idx, CIPDesc cip); void setBondCIP(int bond_idx, CIPDesc cip); @@ -421,7 +418,7 @@ namespace indigo const int* getPyramidStereocenters(int idx) const; void markBondsStereocenters(); void markBondStereocenters(int atom_idx); - bool hasAtropisomericCenter(); + bool hasAtropoStereoBonds(); void addStereocenters(int atom_idx, int type, int group, const int pyramid[4]); void addStereocenters(int atom_idx, int type, int group, bool inverse_pyramid); @@ -433,6 +430,8 @@ namespace indigo void buildFromBondsStereocenters(const StereocentersOptions& options, int* sensible_bonds_out); void buildFrom3dCoordinatesStereocenters(const StereocentersOptions& options); bool isPossibleStereocenter(int atom_idx, bool* possible_implicit_h = 0, bool* possible_lone_pair = 0); + bool isPossibleAtropocenter(int atom_idx, int& possible_atropo_bond); + void buildOnSubmoleculeStereocenters(const BaseMolecule& super, int* mapping); // proxy methods for cis_trans diff --git a/core/indigo-core/molecule/molecule_stereocenters.h b/core/indigo-core/molecule/molecule_stereocenters.h index faa1e68218..1852980de6 100644 --- a/core/indigo-core/molecule/molecule_stereocenters.h +++ b/core/indigo-core/molecule/molecule_stereocenters.h @@ -19,6 +19,8 @@ #ifndef __molecule_stereocenters__ #define __molecule_stereocenters__ +#include + #include "base_cpp/red_black.h" #include "math/algebra.h" @@ -54,6 +56,7 @@ namespace indigo void markBonds(BaseMolecule& baseMolecule); void markBond(BaseMolecule& baseMolecule, int atom_idx); + void markAtropisomericBond(BaseMolecule& baseMolecule, int atom_idx); // takes mapping from supermolecule to submolecule void buildOnSubmolecule(BaseMolecule& baseMolecule, const BaseMolecule& super, int* mapping); @@ -83,7 +86,10 @@ namespace indigo void setType(int idx, int type, int group); void setType(int idx, int type); void setAtropisomeric(int idx, bool val); - bool isAtropisomeric(int idx); + bool isAtropisomeric(int idx) const; + void setTetrahydral(int idx, bool val); + bool isTetrahydral(int idx) const; + void invertPyramid(int idx); bool sameGroup(int idx1, int idx2); @@ -111,6 +117,11 @@ namespace indigo int getAtomIndex(int i) const; bool isPossibleStereocenter(BaseMolecule& baseMolecule, int atom_idx, bool* possible_implicit_h = 0, bool* possible_lone_pair = 0); + bool isPossibleAtropocenter(BaseMolecule& baseMolecule, int atom_idx, int& possible_atropo_bond); + bool hasAtropoStereoBonds(BaseMolecule& baseMolecule, int atom_idx); + bool findAtropoStereobonds(BaseMolecule& baseMolecule, RedBlackMap& directions_map, int atom_idx, std::unordered_set& visited_bonds, + bool first_only = false, int* sensible_bonds_out = nullptr); + bool hasRing(BaseMolecule& baseMolecule, int atom_idx, std::unordered_set& visited_bonds); public: static bool checkSub(BaseMolecule& query, BaseMolecule& target, const int* mapping, bool reset_h_isotopes, Filter* stereocenters_vertex_filter = 0); @@ -134,15 +145,25 @@ namespace indigo private: struct _Atom { + _Atom() : type(-1), group(1), is_atropisomeric(false), is_tetrahydral(true), pyramid{-1, -1, -1, -1} + { + } int type; // ANY, AND, OR, ABS int group; // stereogroup index // [X, Y, Z, W] -- atom indices or -1 for implicit hydrogen // (X, Y, Z) go counterclockwise when looking from W. // if there are pure (implicit) hydrogen, it is W - bool is_atropisomeric = false; + bool is_atropisomeric; + bool is_tetrahydral; int pyramid[4]; }; + struct _AtropoCenter + { + int atropo_bond; + RedBlackMap bond_directions; + }; + struct _EdgeIndVec { int edge_idx; @@ -161,13 +182,14 @@ namespace indigo }; RedBlackMap _stereocenters; + RedBlackObjMap _atropocenters; static int _sign(const Vec3f& v1, const Vec3f& v2, const Vec3f& v3); static int _xyzzy(const Vec3f& v1, const Vec3f& v2, const Vec3f& u); static int _onPlane(const Vec3f& v1, const Vec3f& v2, const Vec3f& v3, const Vec3f& v4); bool _buildOneCenter(BaseMolecule& baseMolecule, int atom_idx, int* sensible_bonds_out, bool bidirectional_mode, bool bidirectional_either_mode, - const Array& bond_ignore); + const Array& bond_ignore, bool check_atropocenter = false); void _buildOneFrom3dCoordinates(BaseMolecule& baseMolecule, int idx); diff --git a/core/indigo-core/molecule/smiles_loader.h b/core/indigo-core/molecule/smiles_loader.h index f80adafec4..8c6ee08247 100644 --- a/core/indigo-core/molecule/smiles_loader.h +++ b/core/indigo-core/molecule/smiles_loader.h @@ -156,6 +156,8 @@ namespace indigo int _balance; int _current_compno; bool _inside_smarts_component; + bool _has_atom_coordinates = false; + bool _has_directions_on_rings = false; BaseMolecule* _bmol; QueryMolecule* _qmol; diff --git a/core/indigo-core/molecule/smiles_saver.h b/core/indigo-core/molecule/smiles_saver.h index 65981dff94..bd3c668e9c 100644 --- a/core/indigo-core/molecule/smiles_saver.h +++ b/core/indigo-core/molecule/smiles_saver.h @@ -129,6 +129,7 @@ namespace indigo void _writeUnsaturated(); void _writeSubstitutionCounts(); void _writeWedges(); + void _writeBondDirs(const std::string& tag, const std::vector>& bonds); bool _shouldWriteAromaticBond(int bond_idx); void _startExtension(); diff --git a/core/indigo-core/molecule/src/base_molecule.cpp b/core/indigo-core/molecule/src/base_molecule.cpp index 6301750736..805391d563 100644 --- a/core/indigo-core/molecule/src/base_molecule.cpp +++ b/core/indigo-core/molecule/src/base_molecule.cpp @@ -4196,12 +4196,12 @@ void BaseMolecule::markBondsStereocenters() stereocenters.markBonds(*this); } -bool BaseMolecule::hasAtropisomericCenter() +bool BaseMolecule::hasAtropoStereoBonds() { for (int i = stereocenters.begin(); i != stereocenters.end(); i = stereocenters.next(i)) { auto atom_idx = stereocenters.getAtomIndex(i); - if (stereocenters.isAtropisomeric(atom_idx)) + if (stereocenters.hasAtropoStereoBonds(*this, atom_idx)) return true; } return false; @@ -4252,6 +4252,11 @@ bool BaseMolecule::isPossibleStereocenter(int atom_idx, bool* possible_implicit_ return stereocenters.isPossibleStereocenter(*this, atom_idx, possible_implicit_h, possible_lone_pair); } +bool BaseMolecule::isPossibleAtropocenter(int atom_idx, int& possible_atropo_bond) +{ + return stereocenters.isPossibleAtropocenter(*this, atom_idx, possible_atropo_bond); +} + void BaseMolecule::buildOnSubmoleculeStereocenters(const BaseMolecule& super, int* mapping) { stereocenters.buildOnSubmolecule(*this, super, mapping); @@ -4420,54 +4425,3 @@ void BaseMolecule::removeAlias(int atom_idx) { aliases.remove(atom_idx); } - -bool BaseMolecule::isAtropisomerismReferenceAtom(int atom_idx) -{ - // TODO: implement more accurate atropisomer detection - if (vertexInRing(atom_idx)) // check if the atom belongs to ring - { - bool has_stereo = false; - const Vertex& v = getVertex(atom_idx); - // check if the atom has at least one stereo-bond - for (int i = v.neiBegin(); i != v.neiEnd(); i = v.neiNext(i)) - { - if (getBondDirection(v.neiEdge(i))) - { - has_stereo = true; - break; - } - } - if (has_stereo) - { - std::unordered_set rotation_bonds; - // looking for a rotation bond - for (int i = v.neiBegin(); i != v.neiEnd(); i = v.neiNext(i)) - { - auto bond_idx = v.neiEdge(i); - if (getBondDirection(bond_idx)) - continue; - if (isRotationBond(bond_idx)) - rotation_bonds.insert(bond_idx); - } - if (rotation_bonds.size()) - return true; - } - } - return false; -} - -bool BaseMolecule::isRotationBond(int bond_idx) -{ - // typically a rotation doesn't belong to a ring. - // but there are some exclusions to be handled. - if (getEdgeTopology(bond_idx) == TOPOLOGY_RING) - return false; - // remove the bond and check if an extra component appears. - // if so this can be a rotation bond. - std::unique_ptr mol(neu()); - mol->clone_KeepIndices(*this); - int old_count = mol->countComponents(); - mol->removeBond(bond_idx); - int new_count = mol->countComponents(); - return new_count > old_count; -} diff --git a/core/indigo-core/molecule/src/cml_loader.cpp b/core/indigo-core/molecule/src/cml_loader.cpp index d64c53e4bf..2801243d70 100644 --- a/core/indigo-core/molecule/src/cml_loader.cpp +++ b/core/indigo-core/molecule/src/cml_loader.cpp @@ -1082,11 +1082,9 @@ void CmlLoader::_loadMoleculeElement(XMLHandle& handle) if (_bmol->stereocenters.size() == 0 && BaseMolecule::hasCoord(*_bmol)) { - QS_DEF(Array, sensible_bond_orientations); - - sensible_bond_orientations.clear_resize(_bmol->vertexEnd()); - _bmol->buildFromBondsStereocenters(stereochemistry_options, sensible_bond_orientations.ptr()); - + std::vector sensible_bond_orientations; + sensible_bond_orientations.resize(_bmol->edgeEnd(), 0); + _bmol->buildFromBondsStereocenters(stereochemistry_options, sensible_bond_orientations.data()); if (!stereochemistry_options.ignore_errors) for (i = 0; i < _bmol->vertexCount(); i++) if (_bmol->getBondDirection(i) > 0 && !sensible_bond_orientations[i]) diff --git a/core/indigo-core/molecule/src/cml_saver.cpp b/core/indigo-core/molecule/src/cml_saver.cpp index fe5c90487d..f034b01d4e 100644 --- a/core/indigo-core/molecule/src/cml_saver.cpp +++ b/core/indigo-core/molecule/src/cml_saver.cpp @@ -368,7 +368,7 @@ void CmlSaver::_addMoleculeElement(XMLElement* elem, BaseMolecule& mol, bool que } } - if (_mol->stereocenters.getType(i) > MoleculeStereocenters::ATOM_ANY) + if (_mol->stereocenters.getType(i) > MoleculeStereocenters::ATOM_ANY && _mol->stereocenters.isTetrahydral(i)) { XMLElement* atomparity = _doc->NewElement("atomParity"); atom->LinkEndChild(atomparity); diff --git a/core/indigo-core/molecule/src/inchi_wrapper.cpp b/core/indigo-core/molecule/src/inchi_wrapper.cpp index 5da196f263..214a634cb9 100644 --- a/core/indigo-core/molecule/src/inchi_wrapper.cpp +++ b/core/indigo-core/molecule/src/inchi_wrapper.cpp @@ -523,6 +523,8 @@ void InchiWrapper::generateInchiInput(Molecule& mol, inchi_Input& input, Array mol(bmol.neu()); mol->clone_KeepIndices(bmol); + if (!BaseMolecule::hasCoord(*mol)) { MoleculeLayout ml(*mol, false); diff --git a/core/indigo-core/molecule/src/molecule_stereocenters.cpp b/core/indigo-core/molecule/src/molecule_stereocenters.cpp index 87797f447c..072751255d 100644 --- a/core/indigo-core/molecule/src/molecule_stereocenters.cpp +++ b/core/indigo-core/molecule/src/molecule_stereocenters.cpp @@ -48,10 +48,14 @@ void MoleculeStereocenters::buildFromBonds(BaseMolecule& baseMolecule, const Ste const Array& bonds_ignore = haworth_finder.getBondsMask(); const Array& atoms_ignore = haworth_finder.getAtomsMask(); + bool check_atropisomery = false; for (int i = baseMolecule.edgeBegin(); i != baseMolecule.edgeEnd(); i = baseMolecule.edgeNext(i)) { - if (bonds_ignore[i] && baseMolecule.getBondDirection(i)) + auto bdir = baseMolecule.getBondDirection(i); + if (bonds_ignore[i] && bdir) sensible_bonds_out[i] = 1; + if (!check_atropisomery && bdir && baseMolecule.getBondTopology(i) == TOPOLOGY_RING) + check_atropisomery = true; } for (int i = baseMolecule.vertexBegin(); i != baseMolecule.vertexEnd(); i = baseMolecule.vertexNext(i)) @@ -63,7 +67,7 @@ void MoleculeStereocenters::buildFromBonds(BaseMolecule& baseMolecule, const Ste bool found = false; try { - found = _buildOneCenter(baseMolecule, i, sensible_bonds_out, false, options.bidirectional_mode, bonds_ignore); + found = _buildOneCenter(baseMolecule, i, sensible_bonds_out, false, options.bidirectional_mode, bonds_ignore, check_atropisomery); } catch (Error&) { @@ -85,6 +89,32 @@ void MoleculeStereocenters::buildFromBonds(BaseMolecule& baseMolecule, const Ste } } } + + for (int i = _stereocenters.begin(); i != _stereocenters.end(); i = _stereocenters.next(i)) + { + _Atom& atom = _stereocenters.value(i); + if (atom.is_atropisomeric) + { + int atom_idx = _stereocenters.key(i); + _AtropoCenter& ac = _atropocenters.at(atom_idx); + std::unordered_set visited_bonds; + if (findAtropoStereobonds(baseMolecule, ac.bond_directions, atom_idx, visited_bonds, false, sensible_bonds_out)) + { + auto bdir = baseMolecule.getBondDirection(ac.atropo_bond); + // include possible atropobond itself if its direction is not sensible, but direction is set + if (bdir && !sensible_bonds_out[ac.atropo_bond]) + { + ac.bond_directions.insert(ac.atropo_bond, bdir); + sensible_bonds_out[ac.atropo_bond] = 1; + } + } + else + { + atom.is_atropisomeric = false; + _atropocenters.remove(atom_idx); + } + } + } } void MoleculeStereocenters::buildFrom3dCoordinates(BaseMolecule& baseMolecule, const StereocentersOptions& options) @@ -193,6 +223,103 @@ void MoleculeStereocenters::_buildOneFrom3dCoordinates(BaseMolecule& baseMolecul add(baseMolecule, idx, ATOM_ABS, 0, false); } +bool MoleculeStereocenters::hasAtropoStereoBonds(BaseMolecule& baseMolecule, int atom_idx) +{ + return _atropocenters.find(atom_idx) && _atropocenters.at(atom_idx).bond_directions.size(); +} + +bool MoleculeStereocenters::isPossibleAtropocenter(BaseMolecule& baseMolecule, int atom_idx, int& possible_atropo_bond) +{ + if (baseMolecule.vertexInRing(atom_idx)) // check if the atom belongs to ring + { + bool has_stereo = false; + const Vertex& v = baseMolecule.getVertex(atom_idx); + // check if the atom has at least one stereo-bond + for (int i = v.neiBegin(); i != v.neiEnd(); i = v.neiNext(i)) + { + if (baseMolecule.getBondDirection(v.neiEdge(i))) + { + for (int i = v.neiBegin(); i != v.neiEnd(); i = v.neiNext(i)) + { + auto bond_idx = v.neiEdge(i); + if (baseMolecule.getEdgeTopology(bond_idx) == TOPOLOGY_CHAIN && baseMolecule.getBondOrder(bond_idx) == BOND_SINGLE && + baseMolecule.vertexInRing(v.neiVertex(i))) + { + std::unordered_set visited; + RedBlackMap dir_map; + visited.insert(bond_idx); + if (findAtropoStereobonds(baseMolecule, dir_map, atom_idx, visited, true)) + { + possible_atropo_bond = bond_idx; + return true; + } + //{ // advanced rings search. currently not in use. + // visited.clear(); + // visited.insert(bond_idx); + // if (hasRing(baseMolecule, v.neiVertex(i), visited)) + // { + // possible_atropo_bond = bond_idx; + // return true; + // } + //} + } + } + break; + } + } + } + return false; +} + +// recursive search of for stereobonds withing connected rings +bool MoleculeStereocenters::findAtropoStereobonds(BaseMolecule& baseMolecule, RedBlackMap& directions_map, int atom_idx, + std::unordered_set& visited_bonds, bool first_only, int* sensible_bonds_out) +{ + const Vertex& v = baseMolecule.getVertex(atom_idx); + for (int i = v.neiBegin(); i != v.neiEnd(); i = v.neiNext(i)) + { + auto bond_idx = v.neiEdge(i); + if (visited_bonds.find(bond_idx) == visited_bonds.end()) + { + visited_bonds.insert(bond_idx); + auto bdir = baseMolecule.getBondDirection(bond_idx); + if (baseMolecule.getBondTopology(bond_idx) == TOPOLOGY_RING) + { + if (bdir && !directions_map.find(bond_idx)) + { + if (sensible_bonds_out) + { + if (sensible_bonds_out[bond_idx]) + continue; + else + sensible_bonds_out[bond_idx] = 1; + } + directions_map.insert(bond_idx, bdir); + if (first_only) + return true; + } + findAtropoStereobonds(baseMolecule, directions_map, v.neiVertex(i), visited_bonds, first_only, sensible_bonds_out); + } + } + } + return directions_map.size(); +} + +bool MoleculeStereocenters::hasRing(BaseMolecule& baseMolecule, int atom_idx, std::unordered_set& visited_bonds) +{ + const Vertex& v = baseMolecule.getVertex(atom_idx); + for (int i = v.neiBegin(); i != v.neiEnd(); i = v.neiNext(i)) + { + auto bond_idx = v.neiEdge(i); + if (visited_bonds.find(bond_idx) == visited_bonds.end()) + { + visited_bonds.insert(bond_idx); + return baseMolecule.getBondTopology(bond_idx) == TOPOLOGY_RING ? true : hasRing(baseMolecule, v.neiVertex(i), visited_bonds); + } + } + return false; +} + bool MoleculeStereocenters::isPossibleStereocenter(BaseMolecule& baseMolecule, int atom_idx, bool* possible_implicit_h, bool* possible_lone_pair) { const Vertex& vertex = baseMolecule.getVertex(atom_idx); @@ -264,17 +391,33 @@ bool MoleculeStereocenters::isPossibleStereocenter(BaseMolecule& baseMolecule, i // can be determined by normal direction then do not check if opposite directions // contradicts original ones. bool MoleculeStereocenters::_buildOneCenter(BaseMolecule& baseMolecule, int atom_idx, int* sensible_bonds_out, bool bidirectional_mode, - bool bidirectional_either_mode, const Array& bond_ignore) + bool bidirectional_either_mode, const Array& bond_ignore, bool check_atropocenter) { - const Vertex& vertex = baseMolecule.getVertex(atom_idx); - - int degree = vertex.degree(); - + int possible_atropobond = -1; _Atom stereocenter; - stereocenter.group = 1; stereocenter.type = ATOM_ABS; + if (check_atropocenter && isPossibleAtropocenter(baseMolecule, atom_idx, possible_atropobond)) + { + stereocenter.is_atropisomeric = true; + _AtropoCenter& ac = _atropocenters.findOrInsert(atom_idx); + ac.atropo_bond = possible_atropobond; + if (_stereocenters.find(atom_idx)) + _stereocenters.at(atom_idx).is_atropisomeric = true; + else + { + stereocenter.is_tetrahydral = false; + _stereocenters.insert(atom_idx, stereocenter); + } + } + + // check if there is a tetrahydral stereocenter already + if (_stereocenters.find(atom_idx) && _stereocenters.at(atom_idx).is_tetrahydral) + return true; + + const Vertex& vertex = baseMolecule.getVertex(atom_idx); + int degree = vertex.degree(); int* pyramid = stereocenter.pyramid; int nei_idx = 0; _EdgeIndVec edge_ids[4]; @@ -295,6 +438,7 @@ bool MoleculeStereocenters::_buildOneCenter(BaseMolecule& baseMolecule, int atom bool is_either = false; bool zero_bond_length = false; + std::unordered_set atropo_bonds_ignore; for (int i = vertex.neiBegin(); i != vertex.neiEnd(); i = vertex.neiNext(i)) { @@ -304,6 +448,8 @@ bool MoleculeStereocenters::_buildOneCenter(BaseMolecule& baseMolecule, int atom edge_ids[nei_idx].edge_idx = e_idx; edge_ids[nei_idx].nei_idx = v_idx; + if (stereocenter.is_atropisomeric && baseMolecule.getBondDirection(e_idx) && baseMolecule.getBondTopology(e_idx) == TOPOLOGY_RING) + atropo_bonds_ignore.insert(e_idx); if (baseMolecule.possibleAtomNumberAndIsotope(v_idx, ELEM_H, 0)) { if (baseMolecule.getAtomNumber(v_idx) == ELEM_H && baseMolecule.getAtomIsotope(v_idx) == 0) @@ -318,9 +464,7 @@ bool MoleculeStereocenters::_buildOneCenter(BaseMolecule& baseMolecule, int atom if (!edge_ids[nei_idx].vec.normalize()) zero_bond_length = true; - if (baseMolecule.getBondOrder(e_idx) == BOND_TRIPLE) - return false; - if (baseMolecule.getBondOrder(e_idx) == BOND_AROMATIC) + if (baseMolecule.getBondOrder(e_idx) == BOND_TRIPLE || baseMolecule.getBondOrder(e_idx) == BOND_AROMATIC) return false; if (baseMolecule.getBondOrder(e_idx) == BOND_DOUBLE) @@ -336,263 +480,283 @@ bool MoleculeStereocenters::_buildOneCenter(BaseMolecule& baseMolecule, int atom bool possible_implicit_h = false; bool possible_lone_pair = false; - int i; - if (!isPossibleStereocenter(baseMolecule, atom_idx, &possible_implicit_h, &possible_lone_pair)) + stereocenter.is_tetrahydral = isPossibleStereocenter(baseMolecule, atom_idx, &possible_implicit_h, &possible_lone_pair); + + if (!stereocenter.is_tetrahydral && !stereocenter.is_atropisomeric) return false; // Local synonym to get bond direction auto getDir = [&](int from, int to) { int idx = baseMolecule.findEdgeIndex(from, to); - if (bond_ignore[idx]) + if (bond_ignore[idx] /* || atropo_bonds_ignore.find(idx) != atropo_bonds_ignore.end()*/) return 0; return _getDirection(baseMolecule, from, to, bidirectional_mode); }; - if (is_either) - { - stereocenter.type = ATOM_ANY; - for (i = 0; i < degree; i++) - { - stereocenter.pyramid[i] = edge_ids[i].nei_idx; - if (getDir(atom_idx, edge_ids[i].nei_idx) > 0) - sensible_bonds_out[edge_ids[i].edge_idx] = 1; - } - _stereocenters.insert(atom_idx, stereocenter); - return true; - } - - if (degree == 4) + if (stereocenter.is_tetrahydral) { - // sort by neighbor atom index (ascending) - if (edge_ids[0].rank > edge_ids[1].rank) - std::swap(edge_ids[0], edge_ids[1]); - if (edge_ids[1].rank > edge_ids[2].rank) - std::swap(edge_ids[1], edge_ids[2]); - if (edge_ids[2].rank > edge_ids[3].rank) - std::swap(edge_ids[2], edge_ids[3]); - if (edge_ids[1].rank > edge_ids[2].rank) - std::swap(edge_ids[1], edge_ids[2]); - if (edge_ids[0].rank > edge_ids[1].rank) - std::swap(edge_ids[0], edge_ids[1]); - if (edge_ids[1].rank > edge_ids[2].rank) - std::swap(edge_ids[1], edge_ids[2]); - - int main1 = -1, main2 = -1, side1 = -1, side2 = -1; - int main_dir = 0; - - for (nei_idx = 0; nei_idx < 4; nei_idx++) - { - int stereo = getDir(atom_idx, edge_ids[nei_idx].nei_idx); - - if (stereo == BOND_UP || stereo == BOND_DOWN) - { - main1 = nei_idx; - main_dir = stereo; - break; - } - } - - if (main1 == -1) - return false; - - if (zero_bond_length) - throw Error("zero bond length near atom %d", atom_idx); - - if (n_pure_hydrogens > 1) - throw Error("%d hydrogens near stereocenter %d", n_pure_hydrogens, atom_idx); - - int xyz1, xyz2; - - // find main2 as opposite to main1 - if (main2 == -1) - { - xyz1 = _xyzzy(edge_ids[main1].vec, edge_ids[(main1 + 1) % 4].vec, edge_ids[(main1 + 2) % 4].vec); - xyz2 = _xyzzy(edge_ids[main1].vec, edge_ids[(main1 + 1) % 4].vec, edge_ids[(main1 + 3) % 4].vec); - - if (xyz1 + xyz2 == 3 || xyz1 + xyz2 == 12) - { - main2 = (main1 + 1) % 4; - side1 = (main1 + 2) % 4; - side2 = (main1 + 3) % 4; - } - } - if (main2 == -1) - { - xyz1 = _xyzzy(edge_ids[main1].vec, edge_ids[(main1 + 2) % 4].vec, edge_ids[(main1 + 1) % 4].vec); - xyz2 = _xyzzy(edge_ids[main1].vec, edge_ids[(main1 + 2) % 4].vec, edge_ids[(main1 + 3) % 4].vec); - - if (xyz1 + xyz2 == 3 || xyz1 + xyz2 == 12) - { - main2 = (main1 + 2) % 4; - side1 = (main1 + 1) % 4; - side2 = (main1 + 3) % 4; - } - } - if (main2 == -1) + if (is_either) { - xyz1 = _xyzzy(edge_ids[main1].vec, edge_ids[(main1 + 3) % 4].vec, edge_ids[(main1 + 1) % 4].vec); - xyz2 = _xyzzy(edge_ids[main1].vec, edge_ids[(main1 + 3) % 4].vec, edge_ids[(main1 + 2) % 4].vec); - - if (xyz1 + xyz2 == 3 || xyz1 + xyz2 == 12) + stereocenter.type = ATOM_ANY; + for (int i = 0; i < degree; i++) { - main2 = (main1 + 3) % 4; - side1 = (main1 + 2) % 4; - side2 = (main1 + 1) % 4; + stereocenter.pyramid[i] = edge_ids[i].nei_idx; + if (getDir(atom_idx, edge_ids[i].nei_idx) > 0) + sensible_bonds_out[edge_ids[i].edge_idx] = 1; } } - - if (main2 == -1) - throw Error("internal error: can not find opposite bond near atom %d", atom_idx); - - if (main_dir == BOND_UP && getDir(atom_idx, edge_ids[main2].nei_idx) == BOND_DOWN) - throw Error("stereo types of the opposite bonds mismatch near atom %d", atom_idx); - if (main_dir == BOND_DOWN && getDir(atom_idx, edge_ids[main2].nei_idx) == BOND_UP) - throw Error("stereo types of the opposite bonds mismatch near atom %d", atom_idx); - - if (main_dir == getDir(atom_idx, edge_ids[side1].nei_idx)) - throw Error("stereo types of non-opposite bonds match near atom %d", atom_idx); - if (main_dir == getDir(atom_idx, edge_ids[side2].nei_idx)) - throw Error("stereo types of non-opposite bonds match near atom %d", atom_idx); - - if (main1 == 3 || main2 == 3) - last_atom_dir = main_dir; - else - last_atom_dir = (main_dir == BOND_UP ? BOND_DOWN : BOND_UP); - - int sign = _sign(edge_ids[0].vec, edge_ids[1].vec, edge_ids[2].vec); - - if ((last_atom_dir == BOND_UP && sign > 0) || (last_atom_dir == BOND_DOWN && sign < 0)) - { - pyramid[0] = edge_ids[0].nei_idx; - pyramid[1] = edge_ids[1].nei_idx; - pyramid[2] = edge_ids[2].nei_idx; - } else { - pyramid[0] = edge_ids[0].nei_idx; - pyramid[1] = edge_ids[2].nei_idx; - pyramid[2] = edge_ids[1].nei_idx; - } - - pyramid[3] = edge_ids[3].nei_idx; - } - else if (degree == 3) - { - // sort by neighbor atom index (ascending) - if (edge_ids[0].rank > edge_ids[1].rank) - std::swap(edge_ids[0], edge_ids[1]); - if (edge_ids[1].rank > edge_ids[2].rank) - std::swap(edge_ids[1], edge_ids[2]); - if (edge_ids[0].rank > edge_ids[1].rank) - std::swap(edge_ids[0], edge_ids[1]); - - bool degenerate = true; - int dirs[3] = {0, 0, 0}; - int main_nei = -1; // will be assigned if all three neighors belong to the same half-plane - int n_up = 0, n_down = 0; - - for (nei_idx = 0; nei_idx < 3; nei_idx++) - { - dirs[nei_idx] = getDir(atom_idx, edge_ids[nei_idx].nei_idx); - if (dirs[nei_idx] == BOND_UP) - n_up++; - else if (dirs[nei_idx] == BOND_DOWN) - n_down++; - } - - if (n_down == 0 && n_up == 0) - return false; - - for (nei_idx = 0; nei_idx < 3; nei_idx++) - { - int xyzzy = _xyzzy(edge_ids[(nei_idx + 1) % 3].vec, edge_ids[(nei_idx + 2) % 3].vec, edge_ids[nei_idx].vec); - - if (xyzzy == 1) - main_nei = nei_idx; - if (xyzzy == 2) - degenerate = false; - } - - int dir = 1; - - if (main_nei != -1) - { - if (dirs[main_nei] != 0) + if (degree == 4) { - if (dirs[(main_nei + 1) % 3] == dirs[main_nei] || dirs[(main_nei + 2) % 3] == dirs[main_nei]) - throw Error("directions of neighbor stereo bonds match near atom %d", atom_idx); - if (dirs[main_nei] == BOND_UP) - dir = -1; + // sort by neighbor atom index (ascending) + if (edge_ids[0].rank > edge_ids[1].rank) + std::swap(edge_ids[0], edge_ids[1]); + if (edge_ids[1].rank > edge_ids[2].rank) + std::swap(edge_ids[1], edge_ids[2]); + if (edge_ids[2].rank > edge_ids[3].rank) + std::swap(edge_ids[2], edge_ids[3]); + if (edge_ids[1].rank > edge_ids[2].rank) + std::swap(edge_ids[1], edge_ids[2]); + if (edge_ids[0].rank > edge_ids[1].rank) + std::swap(edge_ids[0], edge_ids[1]); + if (edge_ids[1].rank > edge_ids[2].rank) + std::swap(edge_ids[1], edge_ids[2]); + + int main1 = -1, main2 = -1, side1 = -1, side2 = -1; + int main_dir = 0; + + for (nei_idx = 0; nei_idx < 4; nei_idx++) + { + int stereo = getDir(atom_idx, edge_ids[nei_idx].nei_idx); + + if (stereo == BOND_UP || stereo == BOND_DOWN) + { + main1 = nei_idx; + main_dir = stereo; + break; + } + } + + if (main1 != -1) + { + if (zero_bond_length) + throw Error("zero bond length near atom %d", atom_idx); + + if (n_pure_hydrogens > 1) + throw Error("%d hydrogens near stereocenter %d", n_pure_hydrogens, atom_idx); + + int xyz1, xyz2; + + // find main2 as opposite to main1 + if (main2 == -1) + { + xyz1 = _xyzzy(edge_ids[main1].vec, edge_ids[(main1 + 1) % 4].vec, edge_ids[(main1 + 2) % 4].vec); + xyz2 = _xyzzy(edge_ids[main1].vec, edge_ids[(main1 + 1) % 4].vec, edge_ids[(main1 + 3) % 4].vec); + + if (xyz1 + xyz2 == 3 || xyz1 + xyz2 == 12) + { + main2 = (main1 + 1) % 4; + side1 = (main1 + 2) % 4; + side2 = (main1 + 3) % 4; + } + } + if (main2 == -1) + { + xyz1 = _xyzzy(edge_ids[main1].vec, edge_ids[(main1 + 2) % 4].vec, edge_ids[(main1 + 1) % 4].vec); + xyz2 = _xyzzy(edge_ids[main1].vec, edge_ids[(main1 + 2) % 4].vec, edge_ids[(main1 + 3) % 4].vec); + + if (xyz1 + xyz2 == 3 || xyz1 + xyz2 == 12) + { + main2 = (main1 + 2) % 4; + side1 = (main1 + 1) % 4; + side2 = (main1 + 3) % 4; + } + } + if (main2 == -1) + { + xyz1 = _xyzzy(edge_ids[main1].vec, edge_ids[(main1 + 3) % 4].vec, edge_ids[(main1 + 1) % 4].vec); + xyz2 = _xyzzy(edge_ids[main1].vec, edge_ids[(main1 + 3) % 4].vec, edge_ids[(main1 + 2) % 4].vec); + + if (xyz1 + xyz2 == 3 || xyz1 + xyz2 == 12) + { + main2 = (main1 + 3) % 4; + side1 = (main1 + 2) % 4; + side2 = (main1 + 1) % 4; + } + } + + if (main2 == -1) + throw Error("internal error: can not find opposite bond near atom %d", atom_idx); + + if (main_dir == BOND_UP && getDir(atom_idx, edge_ids[main2].nei_idx) == BOND_DOWN) + throw Error("stereo types of the opposite bonds mismatch near atom %d", atom_idx); + if (main_dir == BOND_DOWN && getDir(atom_idx, edge_ids[main2].nei_idx) == BOND_UP) + throw Error("stereo types of the opposite bonds mismatch near atom %d", atom_idx); + + if (main_dir == getDir(atom_idx, edge_ids[side1].nei_idx)) + throw Error("stereo types of non-opposite bonds match near atom %d", atom_idx); + if (main_dir == getDir(atom_idx, edge_ids[side2].nei_idx)) + throw Error("stereo types of non-opposite bonds match near atom %d", atom_idx); + + if (main1 == 3 || main2 == 3) + last_atom_dir = main_dir; + else + last_atom_dir = (main_dir == BOND_UP ? BOND_DOWN : BOND_UP); + + int sign = _sign(edge_ids[0].vec, edge_ids[1].vec, edge_ids[2].vec); + + if ((last_atom_dir == BOND_UP && sign > 0) || (last_atom_dir == BOND_DOWN && sign < 0)) + { + pyramid[0] = edge_ids[0].nei_idx; + pyramid[1] = edge_ids[1].nei_idx; + pyramid[2] = edge_ids[2].nei_idx; + } + else + { + pyramid[0] = edge_ids[0].nei_idx; + pyramid[1] = edge_ids[2].nei_idx; + pyramid[2] = edge_ids[1].nei_idx; + } + + pyramid[3] = edge_ids[3].nei_idx; + } + else + stereocenter.is_tetrahydral = false; } - else + else if (degree == 3) { - int d1 = dirs[(main_nei + 1) % 3]; - int d2 = dirs[(main_nei + 2) % 3]; - - if (d1 == 0) - d1 = d2; - else if (d2 != 0 && d1 != d2) - throw Error("directions of opposite stereo bonds do not match near atom %d", atom_idx); - - if (d1 == 0) - return false; + // sort by neighbor atom index (ascending) + if (edge_ids[0].rank > edge_ids[1].rank) + std::swap(edge_ids[0], edge_ids[1]); + if (edge_ids[1].rank > edge_ids[2].rank) + std::swap(edge_ids[1], edge_ids[2]); + if (edge_ids[0].rank > edge_ids[1].rank) + std::swap(edge_ids[0], edge_ids[1]); + + bool degenerate = true; + int dirs[3] = {0, 0, 0}; + int main_nei = -1; // will be assigned if all three neighors belong to the same half-plane + int n_up = 0, n_down = 0; + + for (nei_idx = 0; nei_idx < 3; nei_idx++) + { + dirs[nei_idx] = getDir(atom_idx, edge_ids[nei_idx].nei_idx); + if (dirs[nei_idx] == BOND_UP) + n_up++; + else if (dirs[nei_idx] == BOND_DOWN) + n_down++; + } - if (d1 == BOND_DOWN) - dir = -1; + if (n_down || n_up) + { + for (nei_idx = 0; nei_idx < 3; nei_idx++) + { + int xyzzy = _xyzzy(edge_ids[(nei_idx + 1) % 3].vec, edge_ids[(nei_idx + 2) % 3].vec, edge_ids[nei_idx].vec); + + if (xyzzy == 1) + main_nei = nei_idx; + if (xyzzy == 2) + degenerate = false; + } + + int dir = 1; + + if (main_nei != -1) + { + if (dirs[main_nei] != 0) + { + if (dirs[(main_nei + 1) % 3] == dirs[main_nei] || dirs[(main_nei + 2) % 3] == dirs[main_nei]) + throw Error("directions of neighbor stereo bonds match near atom %d", atom_idx); + if (dirs[main_nei] == BOND_UP) + dir = -1; + } + else + { + int d1 = dirs[(main_nei + 1) % 3]; + int d2 = dirs[(main_nei + 2) % 3]; + + if (d1 == 0) + d1 = d2; + else if (d2 != 0 && d1 != d2) + throw Error("directions of opposite stereo bonds do not match near atom %d", atom_idx); + + if (d1 == 0) + return false; + + if (d1 == BOND_DOWN) + dir = -1; + } + } + else if (!degenerate) + { + if (n_down > 0 && n_up > 0) + throw Error("one bond up, one bond down -- indefinite case near atom %d", atom_idx); + + if (!possible_lone_pair) + { + if (n_up == 3) + throw Error("all 3 bonds up near stereoatom %d", atom_idx); + if (n_down == 3) + throw Error("all 3 bonds down near stereoatom %d", atom_idx); + } + if (n_down > 0) + dir = -1; + } + else + throw Error("degenerate case for 3 bonds near stereoatom %d", atom_idx); + + if (zero_bond_length) + throw Error("zero bond length near atom %d", atom_idx); + + if (n_pure_hydrogens > 0 && !possible_lone_pair) + throw Error("have hydrogen(s) besides implicit hydrogen near stereocenter %d", atom_idx); + + int sign = _sign(edge_ids[0].vec, edge_ids[1].vec, edge_ids[2].vec); + + if (sign == dir) + { + pyramid[0] = edge_ids[0].nei_idx; + pyramid[1] = edge_ids[2].nei_idx; + pyramid[2] = edge_ids[1].nei_idx; + } + else + { + pyramid[0] = edge_ids[0].nei_idx; + pyramid[1] = edge_ids[1].nei_idx; + pyramid[2] = edge_ids[2].nei_idx; + } + pyramid[3] = -1; + } + else + stereocenter.is_tetrahydral = false; } - } - else if (!degenerate) - { - if (n_down > 0 && n_up > 0) - throw Error("one bond up, one bond down -- indefinite case near atom %d", atom_idx); - if (!possible_lone_pair) - { - if (n_up == 3) - throw Error("all 3 bonds up near stereoatom %d", atom_idx); - if (n_down == 3) - throw Error("all 3 bonds down near stereoatom %d", atom_idx); - } - if (n_down > 0) - dir = -1; + if (stereocenter.is_tetrahydral) + for (int i = 0; i < degree; i++) + if (getDir(atom_idx, edge_ids[i].nei_idx) > 0) + sensible_bonds_out[edge_ids[i].edge_idx] = 1; } - else - throw Error("degenerate case for 3 bonds near stereoatom %d", atom_idx); - - if (zero_bond_length) - throw Error("zero bond length near atom %d", atom_idx); - - if (n_pure_hydrogens > 0 && !possible_lone_pair) - throw Error("have hydrogen(s) besides implicit hydrogen near stereocenter %d", atom_idx); - - int sign = _sign(edge_ids[0].vec, edge_ids[1].vec, edge_ids[2].vec); + } - if (sign == dir) + if (stereocenter.is_tetrahydral) + { + if (_stereocenters.find(atom_idx)) { - pyramid[0] = edge_ids[0].nei_idx; - pyramid[1] = edge_ids[2].nei_idx; - pyramid[2] = edge_ids[1].nei_idx; + auto& sc = _stereocenters.at(atom_idx); + sc.is_tetrahydral = true; + std::copy(std::begin(stereocenter.pyramid), std::end(stereocenter.pyramid), std::begin(sc.pyramid)); } else - { - pyramid[0] = edge_ids[0].nei_idx; - pyramid[1] = edge_ids[1].nei_idx; - pyramid[2] = edge_ids[2].nei_idx; - } - pyramid[3] = -1; + _stereocenters.insert(atom_idx, stereocenter); + return true; } - - for (i = 0; i < degree; i++) - if (getDir(atom_idx, edge_ids[i].nei_idx) > 0) - sensible_bonds_out[edge_ids[i].edge_idx] = 1; - - _stereocenters.insert(atom_idx, stereocenter); - return true; + return false; } // 1 -- in the smaller angle, 2 -- in the bigger angle, -// 4 -- in the 'positive' straight angle, 8 -- in the 'negative' straight angle +// 4 -- in t5he 'positive' straight angle, 8 -- in the 'negative' straight angle int MoleculeStereocenters::_xyzzy(const Vec3f& v1, const Vec3f& v2, const Vec3f& u) { const float eps = 1e-3f; @@ -713,11 +877,21 @@ void MoleculeStereocenters::setAtropisomeric(int idx, bool val) _stereocenters.at(idx).is_atropisomeric = val; } -bool MoleculeStereocenters::isAtropisomeric(int idx) +bool MoleculeStereocenters::isAtropisomeric(int idx) const { return _stereocenters.at(idx).is_atropisomeric; } +void MoleculeStereocenters::setTetrahydral(int idx, bool val) +{ + _stereocenters.at(idx).is_tetrahydral = val; +} + +bool MoleculeStereocenters::isTetrahydral(int idx) const +{ + return _stereocenters.at(idx).is_tetrahydral; +} + const int* MoleculeStereocenters::getPyramid(int idx) const { return _stereocenters.at(idx).pyramid; @@ -912,7 +1086,7 @@ bool MoleculeStereocenters::checkSub(BaseMolecule& query, BaseMolecule& target, if (stereocenters_vertex_filter != 0 && !stereocenters_vertex_filter->valid(iq)) continue; - if (cq.type < ATOM_AND) + if (cq.type < ATOM_AND || !cq.is_tetrahydral) continue; int stereo_group_and = -1; @@ -1229,41 +1403,61 @@ void MoleculeStereocenters::buildOnSubmolecule(BaseMolecule& baseMolecule, const new_stereocenter.group = super_stereocenter.group; new_stereocenter.type = super_stereocenter.type; + new_stereocenter.is_atropisomeric = super_stereocenter.is_atropisomeric; + new_stereocenter.is_tetrahydral = super_stereocenter.is_tetrahydral; - for (j = 0; j < 4; j++) + // copy tetrahydral center + if (new_stereocenter.is_tetrahydral) { - int idx = super_stereocenter.pyramid[j]; - - if (idx == -1) - new_stereocenter.pyramid[j] = -1; - else + for (j = 0; j < 4; j++) { - int val = mapping[idx]; - if (val != -1 && baseMolecule.findEdgeIndex(sub_idx, val) == -1) - val = -1; - new_stereocenter.pyramid[j] = val; - } - } + int idx = super_stereocenter.pyramid[j]; - moveMinimalToEnd(new_stereocenter.pyramid); - if (new_stereocenter.pyramid[0] == -1 || new_stereocenter.pyramid[1] == -1 || new_stereocenter.pyramid[2] == -1) - // pyramid is not mapped completely - continue; + if (idx == -1) + new_stereocenter.pyramid[j] = -1; + else + { + int val = mapping[idx]; + if (val != -1 && baseMolecule.findEdgeIndex(sub_idx, val) == -1) + val = -1; + new_stereocenter.pyramid[j] = val; + } + } - _stereocenters.insert(sub_idx, new_stereocenter); + moveMinimalToEnd(new_stereocenter.pyramid); + // copy bond directions for tetrahydral center + const Vertex& super_vertex = super.getVertex(super_idx); + for (j = super_vertex.neiBegin(); j != super_vertex.neiEnd(); j = super_vertex.neiNext(j)) + { + int super_edge = super_vertex.neiEdge(j); + if (mapping[super_vertex.neiVertex(j)] == -1) + continue; - const Vertex& super_vertex = super.getVertex(super_idx); + int bdir = super.getBondDirection(super_edge); + if (bdir) + baseMolecule.setBondDirection(baseMolecule.findEdgeIndex(sub_idx, mapping[super_vertex.neiVertex(j)]), bdir); + } + } - for (j = super_vertex.neiBegin(); j != super_vertex.neiEnd(); j = super_vertex.neiNext(j)) + // copy atropocenter + if (new_stereocenter.is_atropisomeric && super.stereocenters._atropocenters.find(super_idx)) { - int super_edge = super_vertex.neiEdge(j); - if (mapping[super_vertex.neiVertex(j)] == -1) - continue; - - int dir = super.getBondDirection(super_edge); - if (dir != 0) - baseMolecule.setBondDirection(baseMolecule.findEdgeIndex(sub_idx, mapping[super_vertex.neiVertex(j)]), dir); + const auto& ac_super = super.stereocenters._atropocenters.at(super_idx); + auto& ac_new = baseMolecule.stereocenters._atropocenters.findOrInsert(sub_idx); + const auto& e = super.getEdge(ac_super.atropo_bond); + ac_new.atropo_bond = baseMolecule.findEdgeIndex(mapping[e.beg], mapping[e.end]); + // copy bond directions for atropisomeric center + ac_new.bond_directions.clear(); + for (j = ac_super.bond_directions.begin(); j != ac_super.bond_directions.end(); j = ac_super.bond_directions.next(j)) + { + const auto& atropo_edge = super.getEdge(ac_super.bond_directions.key(j)); + int atropo_edge_idx = baseMolecule.findEdgeIndex(mapping[atropo_edge.beg], mapping[atropo_edge.end]); + int bdir = ac_super.bond_directions.value(j); + ac_new.bond_directions.insert(atropo_edge_idx, bdir); + baseMolecule.setBondDirection(atropo_edge_idx, bdir); + } } + _stereocenters.insert(sub_idx, new_stereocenter); } } @@ -1546,143 +1740,167 @@ void MoleculeStereocenters::markBond(BaseMolecule& baseMolecule, int atom_idx) return; const _Atom& atom = *atom_ptr; - int pyramid[4]; - int mult = 1; - int size = 0; - int j; - memcpy(pyramid, atom.pyramid, 4 * sizeof(int)); - - const Vertex& vertex = baseMolecule.getVertex(atom_idx); - if (atom.type <= ATOM_ANY) + if (atom.is_tetrahydral) { - // fill the pyramid - for (j = vertex.neiBegin(); j != vertex.neiEnd() && size < 4; j = vertex.neiNext(j)) - pyramid[size++] = vertex.neiVertex(j); - } - else - size = (pyramid[3] == -1 ? 3 : 4); + int pyramid[4]; + int mult = 1; + int size = 0; + int j; - // clear bond directions that goes to this atom, and not from this atom because they can - // be marked by other sterecenter - for (j = vertex.neiBegin(); j != vertex.neiEnd(); j = vertex.neiNext(j)) - if (baseMolecule.getBondDirection2(atom_idx, vertex.neiVertex(j)) != 0) - baseMolecule.setBondDirection(vertex.neiEdge(j), 0); + memcpy(pyramid, atom.pyramid, 4 * sizeof(int)); - int edge_idx = -1; + const Vertex& vertex = baseMolecule.getVertex(atom_idx); + if (atom.type <= ATOM_ANY) + { + // fill the pyramid + for (j = vertex.neiBegin(); j != vertex.neiEnd() && size < 4; j = vertex.neiNext(j)) + pyramid[size++] = vertex.neiVertex(j); + } + else + size = (pyramid[3] == -1 ? 3 : 4); - for (j = 0; j < size; j++) - { - edge_idx = baseMolecule.findEdgeIndex(atom_idx, pyramid[size - 1]); - if (baseMolecule.getBondDirection(edge_idx) == 0 && baseMolecule.getVertex(pyramid[size - 1]).degree() == 1) - break; - rotatePyramid(pyramid); - if (size == 4) - mult = -mult; - } + // clear bond directions that goes to this atom, and not from this atom because they can + // be marked by other sterecenter + for (j = vertex.neiBegin(); j != vertex.neiEnd(); j = vertex.neiNext(j)) + if (baseMolecule.getBondDirection2(atom_idx, vertex.neiVertex(j)) != 0) + baseMolecule.setBondDirection(vertex.neiEdge(j), 0); + + int edge_idx = -1; - if (j == size) - { for (j = 0; j < size; j++) { edge_idx = baseMolecule.findEdgeIndex(atom_idx, pyramid[size - 1]); - if (baseMolecule.getBondDirection(edge_idx) == 0 && baseMolecule.getBondTopology(edge_idx) == TOPOLOGY_CHAIN && getType(pyramid[size - 1]) == 0) + if (baseMolecule.getBondDirection(edge_idx) == 0 && baseMolecule.getVertex(pyramid[size - 1]).degree() == 1) break; rotatePyramid(pyramid); if (size == 4) mult = -mult; } - } - if (j == size) - { - for (j = 0; j < size; j++) + if (j == size) { - edge_idx = baseMolecule.findEdgeIndex(atom_idx, pyramid[size - 1]); - if (baseMolecule.getBondDirection(edge_idx) == 0 && getType(pyramid[size - 1]) == 0) - break; - rotatePyramid(pyramid); - if (size == 4) - mult = -mult; + for (j = 0; j < size; j++) + { + edge_idx = baseMolecule.findEdgeIndex(atom_idx, pyramid[size - 1]); + if (baseMolecule.getBondDirection(edge_idx) == 0 && baseMolecule.getBondTopology(edge_idx) == TOPOLOGY_CHAIN && getType(pyramid[size - 1]) == 0) + break; + rotatePyramid(pyramid); + if (size == 4) + mult = -mult; + } } - } - if (j == size) - { - for (j = 0; j < size; j++) + if (j == size) { - edge_idx = baseMolecule.findEdgeIndex(atom_idx, pyramid[size - 1]); - if (baseMolecule.getBondDirection(edge_idx) == 0 && baseMolecule.getBondTopology(edge_idx) == TOPOLOGY_CHAIN) - break; - rotatePyramid(pyramid); - if (size == 4) - mult = -mult; + for (j = 0; j < size; j++) + { + edge_idx = baseMolecule.findEdgeIndex(atom_idx, pyramid[size - 1]); + if (baseMolecule.getBondDirection(edge_idx) == 0 && getType(pyramid[size - 1]) == 0) + break; + rotatePyramid(pyramid); + if (size == 4) + mult = -mult; + } } - } - if (j == size) - { - for (j = 0; j < size; j++) + if (j == size) { - edge_idx = baseMolecule.findEdgeIndex(atom_idx, pyramid[size - 1]); - if (baseMolecule.getBondDirection(edge_idx) == 0) - break; - rotatePyramid(pyramid); - if (size == 4) - mult = -mult; + for (j = 0; j < size; j++) + { + edge_idx = baseMolecule.findEdgeIndex(atom_idx, pyramid[size - 1]); + if (baseMolecule.getBondDirection(edge_idx) == 0 && baseMolecule.getBondTopology(edge_idx) == TOPOLOGY_CHAIN) + break; + rotatePyramid(pyramid); + if (size == 4) + mult = -mult; + } } - } - - if (j == size) - throw Error("no bond can be marked"); - - if (baseMolecule.getEdge(edge_idx).beg != atom_idx) - baseMolecule.swapEdgeEnds(edge_idx); - if (atom.type > ATOM_ANY) - { - std::array dirs; - dirs.fill({0.0, 0.0, 0.0}); - for (j = 0; j < size; j++) + if (j == size) { - dirs[j] = baseMolecule.getAtomXyz(pyramid[j]); - dirs[j].sub(baseMolecule.getAtomXyz(atom_idx)); - if (!dirs[j].normalize()) - throw Error("zero bond length"); + for (j = 0; j < size; j++) + { + edge_idx = baseMolecule.findEdgeIndex(atom_idx, pyramid[size - 1]); + if (baseMolecule.getBondDirection(edge_idx) == 0) + break; + rotatePyramid(pyramid); + if (size == 4) + mult = -mult; + } } - int sign = _sign(dirs[0], dirs[1], dirs[2]); + if (j == size) + throw Error("no bond can be marked"); - if (size == 3) + if (baseMolecule.getEdge(edge_idx).beg != atom_idx) + baseMolecule.swapEdgeEnds(edge_idx); + + if (BaseMolecule::hasCoord(baseMolecule)) { - // Check if all the three bonds belong to the same half-plane. - // This is equal to that one of the bonds lies in the smaller - // angle formed by the other two. - if (_xyzzy(dirs[1], dirs[0], dirs[2]) == 1 || _xyzzy(dirs[2], dirs[1], dirs[0]) == 1 || _xyzzy(dirs[0], dirs[2], dirs[1]) == 1) + if (atom.type > ATOM_ANY) { - if (_xyzzy(dirs[1], dirs[0], dirs[2]) == 1) - mult = -1; - baseMolecule.setBondDirection(edge_idx, (sign * mult == 1) ? BOND_DOWN : BOND_UP); + std::array dirs; + dirs.fill({0.0, 0.0, 0.0}); + for (j = 0; j < size; j++) + { + dirs[j] = baseMolecule.getAtomXyz(pyramid[j]); + dirs[j].sub(baseMolecule.getAtomXyz(atom_idx)); + if (!dirs[j].normalize()) + throw Error("zero bond length"); + } + + int sign = _sign(dirs[0], dirs[1], dirs[2]); + + if (size == 3) + { + // Check if all the three bonds belong to the same half-plane. + // This is equal to that one of the bonds lies in the smaller + // angle formed by the other two. + if (_xyzzy(dirs[1], dirs[0], dirs[2]) == 1 || _xyzzy(dirs[2], dirs[1], dirs[0]) == 1 || _xyzzy(dirs[0], dirs[2], dirs[1]) == 1) + { + if (_xyzzy(dirs[1], dirs[0], dirs[2]) == 1) + mult = -1; + baseMolecule.setBondDirection(edge_idx, (sign * mult == 1) ? BOND_DOWN : BOND_UP); + } + else + baseMolecule.setBondDirection(edge_idx, (sign == 1) ? BOND_DOWN : BOND_UP); + } + else + baseMolecule.setBondDirection(edge_idx, (sign * mult == 1) ? BOND_UP : BOND_DOWN); } else - baseMolecule.setBondDirection(edge_idx, (sign == 1) ? BOND_DOWN : BOND_UP); + baseMolecule.setBondDirection(edge_idx, BOND_EITHER); } - else - baseMolecule.setBondDirection(edge_idx, (sign * mult == 1) ? BOND_UP : BOND_DOWN); } - else - baseMolecule.setBondDirection(edge_idx, BOND_EITHER); } -void MoleculeStereocenters::markBonds(BaseMolecule& baseMolecule) +void MoleculeStereocenters::markAtropisomericBond(BaseMolecule& baseMolecule, int atom_idx) { - for (int i = _stereocenters.begin(); i != _stereocenters.end(); i = _stereocenters.next(i)) + const _Atom* atom_ptr = _stereocenters.at2(atom_idx); + if (atom_ptr == NULL) + return; + const _Atom& atom = *atom_ptr; + if (atom.is_atropisomeric) { - if (!_stereocenters.value(i).is_atropisomeric) - markBond(baseMolecule, _stereocenters.key(i)); + const auto& ac = _atropocenters.at(atom_idx); + for (int i = ac.bond_directions.begin(); i != ac.bond_directions.end(); i = ac.bond_directions.next(i)) + { + int bond_idx = ac.bond_directions.key(i); + int bdir = ac.bond_directions.value(i); + baseMolecule.setBondDirection(bond_idx, bdir); + } } } +void MoleculeStereocenters::markBonds(BaseMolecule& baseMolecule) +{ + for (int i = _stereocenters.begin(); i != _stereocenters.end(); i = _stereocenters.next(i)) + markBond(baseMolecule, _stereocenters.key(i)); + for (int i = _stereocenters.begin(); i != _stereocenters.end(); i = _stereocenters.next(i)) + markAtropisomericBond(baseMolecule, _stereocenters.key(i)); +} + bool MoleculeStereocenters::isAutomorphism(BaseMolecule& mol, const Array& mapping, const Filter* filter) { MoleculeStereocenters& stereocenters = mol.stereocenters; diff --git a/core/indigo-core/molecule/src/molfile_loader.cpp b/core/indigo-core/molecule/src/molfile_loader.cpp index 970357a451..6384e76abf 100644 --- a/core/indigo-core/molecule/src/molfile_loader.cpp +++ b/core/indigo-core/molecule/src/molfile_loader.cpp @@ -57,9 +57,7 @@ void MolfileLoader::loadMolecule(Molecule& mol) _mol = &mol; _qmol = 0; _loadMolecule(); - mol.setIgnoreBadValenceFlag(ignore_bad_valence); - if (mol.stereocenters.size() == 0 && !skip_3d_chirality) mol.buildFrom3dCoordinatesStereocenters(stereochemistry_options); } @@ -2063,12 +2061,7 @@ void MolfileLoader::_postLoad() { if (_bmol->stereocenters.getType(i) == 0) { - if (_bmol->isAtropisomerismReferenceAtom(i)) - { - _bmol->stereocenters.add_ignore(*_bmol, i, _stereocenter_types[i], _stereocenter_groups[i], false); - _bmol->stereocenters.setAtropisomeric(i, true); - } - else if (!stereochemistry_options.ignore_errors) + if (!stereochemistry_options.ignore_errors) throw Error("stereo type specified for atom #%d, but the bond " "directions does not say that it is a stereocenter", i); @@ -2077,14 +2070,16 @@ void MolfileLoader::_postLoad() _bmol->stereocenters.setType(i, _stereocenter_types[i], _stereocenter_groups[i]); } + _bmol->buildCisTrans(_ignore_cistrans.ptr()); + for (i = 0; i < _bonds_num; i++) - if (_bmol->getBondDirection(i) > 0 && !_sensible_bond_directions[i]) + { + if (_bmol->getBondDirection(i) && !_sensible_bond_directions[i]) { if (!stereochemistry_options.ignore_errors) throw Error("direction of bond #%d makes no sense", i); } - - _bmol->buildCisTrans(_ignore_cistrans.ptr()); + } // Remove adding default R-group logic behavior /* diff --git a/core/indigo-core/molecule/src/molfile_saver.cpp b/core/indigo-core/molecule/src/molfile_saver.cpp index c39f250ff1..36e632edf5 100644 --- a/core/indigo-core/molecule/src/molfile_saver.cpp +++ b/core/indigo-core/molecule/src/molfile_saver.cpp @@ -1910,7 +1910,7 @@ void MolfileSaver::_checkSGroupIndices(BaseMolecule& mol, Array& sgs_list) int MolfileSaver::_getStereocenterParity(BaseMolecule& mol, int idx) { int type = mol.stereocenters.getType(idx); - if (type == 0) + if (type == 0 || !mol.stereocenters.isTetrahydral(idx)) return 0; if (type == MoleculeStereocenters::ATOM_ANY) return 3; diff --git a/core/indigo-core/molecule/src/smiles_loader.cpp b/core/indigo-core/molecule/src/smiles_loader.cpp index 71a519e3da..4e03d9144b 100644 --- a/core/indigo-core/molecule/src/smiles_loader.cpp +++ b/core/indigo-core/molecule/src/smiles_loader.cpp @@ -62,6 +62,7 @@ void SmilesLoader::loadMolecule(Molecule& mol) _bmol = &mol; _mol = &mol; _qmol = 0; + _has_atom_coordinates = false; _loadMolecule(); mol.setIgnoreBadValenceFlag(ignore_bad_valence); @@ -317,6 +318,7 @@ void SmilesLoader::_readOtherStuff() while (isdigit(_scanner.lookNext())) { int atom_idx = _scanner.readUnsigned(); + // handle wiggly bonds if (!wmode) { // This either bond can mark stereocenter or cis-trans double bond @@ -326,7 +328,7 @@ void SmilesLoader::_readOtherStuff() for (int nei : v.neighbors()) { int edge_idx = v.neiEdge(nei); - if (_bmol->getBondOrder(edge_idx) == BOND_DOUBLE) + if (_bmol->getBondOrder(edge_idx) == BOND_DOUBLE && _bmol->getBondTopology(edge_idx) != TOPOLOGY_RING) { cis_trans.ignore(edge_idx); found = true; @@ -335,16 +337,11 @@ void SmilesLoader::_readOtherStuff() if (!found) { - if (!_bmol->isPossibleStereocenter(atom_idx)) - { - if (!stereochemistry_options.ignore_errors) - throw Error("chirality not possible on atom #%d", atom_idx); - } - else + if (_bmol->isPossibleStereocenter(atom_idx)) { // Check if the stereocenter has already been marked as any // For example [H]C1(O)c2ccnn2[C@@H](O)c2ccnn12 |r,w:1.0,1.1| - if (_bmol->stereocenters.getType(atom_idx) != MoleculeStereocenters::ATOM_ANY) + if (!_bmol->stereocenters.exists(atom_idx)) _bmol->addStereocenters(atom_idx, MoleculeStereocenters::ATOM_ANY, 0, false); } } @@ -354,21 +351,16 @@ void SmilesLoader::_readOtherStuff() { _scanner.skip(1); auto bond_idx = _scanner.readUnsigned(); - if (wmode) + if (!_has_directions_on_rings) + _has_directions_on_rings = _bmol->getBondTopology(bond_idx) == TOPOLOGY_RING; + if (bond_idx < _bmol->edgeCount() && atom_idx < _bmol->vertexCount()) { auto& v = _bmol->getEdge(bond_idx); if (v.end == atom_idx) _bmol->swapEdgeEnds(bond_idx); + if (v.beg == atom_idx) - { - _bmol->setBondDirection(bond_idx, wmode == 'U' ? BOND_UP : BOND_DOWN); - if (_bmol->isAtropisomerismReferenceAtom(atom_idx)) - { - if (!_bmol->stereocenters.exists(atom_idx)) - _bmol->addStereocenters(atom_idx, MoleculeStereocenters::ATOM_ANY, 0, false); - _bmol->stereocenters.setAtropisomeric(atom_idx, true); - } - } + _bmol->setBondDirection(bond_idx, wmode == 'U' ? BOND_UP : (wmode == 'D' ? BOND_DOWN : BOND_EITHER)); } } @@ -391,7 +383,10 @@ void SmilesLoader::_readOtherStuff() _overtly_defined_abs.insert(idx); } else + { _bmol->addStereocenters(idx, MoleculeStereocenters::ATOM_ABS, 0, false); + _bmol->stereocenters.setTetrahydral(idx, false); + } if (_scanner.lookNext() == ',') _scanner.skip(1); @@ -411,7 +406,10 @@ void SmilesLoader::_readOtherStuff() if (_bmol->stereocenters.exists(idx)) _bmol->stereocenters.setType(idx, MoleculeStereocenters::ATOM_OR, groupno); else + { _bmol->addStereocenters(idx, MoleculeStereocenters::ATOM_OR, groupno, false); + _bmol->stereocenters.setTetrahydral(idx, false); + } if (_scanner.lookNext() == ',') _scanner.skip(1); @@ -430,8 +428,10 @@ void SmilesLoader::_readOtherStuff() if (_bmol->stereocenters.exists(idx)) _bmol->stereocenters.setType(idx, MoleculeStereocenters::ATOM_AND, groupno); else + { _bmol->addStereocenters(idx, MoleculeStereocenters::ATOM_AND, groupno, false); - + _bmol->stereocenters.setTetrahydral(idx, false); + } if (_scanner.lookNext() == ',') _scanner.skip(1); } @@ -752,8 +752,7 @@ void SmilesLoader::_readOtherStuff() } if (_scanner.readChar() != ')') throw Error("expected ')' after coordinates"); - _bmol->markBondsStereocenters(); - _bmol->markBondsAlleneStereo(); + _has_atom_coordinates = true; } else if (c == 'h') // highlighting (Indigo's own extension) { @@ -1345,11 +1344,9 @@ void SmilesLoader::_validateStereoCenters() for (int i = _bmol->stereocenters.begin(); i < _bmol->stereocenters.end(); i = _bmol->stereocenters.next(i)) { auto atom_idx = _bmol->stereocenters.getAtomIndex(i); - if (_bmol->isPossibleStereocenter(atom_idx) || _bmol->isAtropisomerismReferenceAtom(atom_idx)) + if (_bmol->isPossibleStereocenter(atom_idx) || _bmol->stereocenters.isAtropisomeric(atom_idx)) continue; - if (stereochemistry_options.ignore_errors) - _bmol->stereocenters.remove(i); - else + if (!stereochemistry_options.ignore_errors) throw Error("atom %d is not a stereocenter", atom_idx); } } @@ -1928,6 +1925,14 @@ void SmilesLoader::_loadParsedMolecule() { _scanner.skip(1); _readOtherStuff(); + if (_has_atom_coordinates || _has_directions_on_rings) + { + std::vector sensible_bond_directions; + sensible_bond_directions.resize(_bmol->edgeCount()); + _bmol->buildFromBondsStereocenters(stereochemistry_options, sensible_bond_directions.data()); + _bmol->markBondsStereocenters(); + _bmol->markBondsAlleneStereo(); + } } // Update attachment orders for rsites diff --git a/core/indigo-core/molecule/src/smiles_saver.cpp b/core/indigo-core/molecule/src/smiles_saver.cpp index f0ce525217..c75b660e98 100644 --- a/core/indigo-core/molecule/src/smiles_saver.cpp +++ b/core/indigo-core/molecule/src/smiles_saver.cpp @@ -27,6 +27,7 @@ #include "molecule/molecule.h" #include "molecule/molecule_rgroups.h" #include "molecule/molecule_savers.h" +#include "molecule/molecule_stereocenter_options.h" #include "molecule/molecule_stereocenters.h" #include "molecule/query_molecule.h" @@ -262,7 +263,7 @@ void SmilesSaver::_saveMolecule() stereocenters.get(i, atom_idx, type, group, pyramid); - if (type < MoleculeStereocenters::ATOM_AND || stereocenters.isAtropisomeric(atom_idx)) + if (type < MoleculeStereocenters::ATOM_AND || !stereocenters.isTetrahydral(atom_idx)) continue; int implicit_h_idx = -1; @@ -384,7 +385,7 @@ void SmilesSaver::_saveMolecule() int idx = _written_atoms[i]; - if (_atoms[idx].chirality == 0) + if (_atoms[idx].chirality == 0 || !stereocenters.isTetrahydral(idx)) continue; int type = stereocenters.getType(idx); @@ -625,7 +626,8 @@ void SmilesSaver::_saveMolecule() _writeRingBonds(); _writeUnsaturated(); _writeSubstitutionCounts(); - _writeWedges(); + if (_bmol->hasAtropoStereoBonds()) + _writeWedges(); if (_comma) _output.writeChar('|'); @@ -1500,7 +1502,6 @@ void SmilesSaver::_writeStereogroups() { int atom, type, group; stereocenters.get(i, atom, type, group, 0); - if (type != MoleculeStereocenters::ATOM_ABS) break; } @@ -1838,35 +1839,69 @@ void SmilesSaver::_writeSubstitutionCounts() } } -void SmilesSaver::_writeWedges() +void SmilesSaver::_writeBondDirs(const std::string& tag, const std::vector>& bonds) { bool is_first = true; + for (const auto& kvp : bonds) + { + if (is_first) + { + _startExtension(); + _output.writeString(tag.c_str()); + is_first = false; + } + else + _output.writeString(","); + _output.printf("%d.%d", kvp.first, kvp.second); + } +} +void SmilesSaver::_writeWedges() +{ if (_bmol) { + std::vector> down_dirs, up_dirs, wiggy_dirs; for (int i = 0; i < _written_bonds.size(); ++i) { auto bond_idx = _written_bonds[i]; auto& e = _bmol->getEdge(bond_idx); - if (_bmol->stereocenters.exists(e.beg) && _bmol->stereocenters.isAtropisomeric(e.beg)) + auto bdir = _bmol->getBondDirection(bond_idx); + if (bdir) { - auto bdir = _bmol->getBondDirection(bond_idx); - if (bdir && bdir < BOND_EITHER) + const auto& edge = _bmol->getEdge(bond_idx); + auto wa_idx = _written_atoms.find(edge.beg); + switch (bdir) { - if (is_first) - { - _startExtension(); - _output.writeString(bdir == BOND_UP ? "wU:" : "wD:"); - is_first = false; - } - else - _output.writeString(","); - const auto& edge = _bmol->getEdge(bond_idx); - auto wa_idx = _written_atoms.find(edge.beg); - _output.printf("%d.%d", wa_idx, i); + case BOND_UP: + up_dirs.emplace_back(wa_idx, i); + break; + case BOND_DOWN: + down_dirs.emplace_back(wa_idx, i); + break; + case BOND_EITHER: + wiggy_dirs.emplace_back(wa_idx, i); + break; } } } + + _writeBondDirs("wU:", up_dirs); + _writeBondDirs("wD:", down_dirs); + _writeBondDirs("w:", wiggy_dirs); + + if ((down_dirs.size() || up_dirs.size() || wiggy_dirs.size()) && BaseMolecule::hasCoord(*_mol)) + { + _output.writeString(",("); + for (int i = 0; i < _written_atoms.size(); ++i) + { + if (i) + _output.writeString(";"); + auto atom_idx = _written_atoms[i]; + const auto& pos = _mol->getAtomXyz(atom_idx); + _output.printf("%.2f,%.2f,", pos.x, pos.y); + } + _output.writeString(")"); + } } }