From aaf979ab6ce936cb5b5e12ea371771a882d7ea37 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Thu, 4 Dec 2025 14:03:33 +0000 Subject: [PATCH 01/69] Decoupled main from ichimain.c --- .../Geometries/data/cis_platin.mol | 26 - .../Geometries/data/mol_alkene.ds_0.mol | 18 - .../Geometries/data/mol_bidentate.ds_7.mol | 135 -- .../Geometries/data/mol_carbonyl.ds_0.mol | 41 - .../demos/mol2inchi/src/CMakeLists.txt | 4 +- .../inchi-1 => INCHI_BASE}/src/dispstru.c | 116 +- .../inchi-1 => INCHI_BASE}/src/dispstru.h | 0 INCHI-1-SRC/INCHI_BASE/src/ichimain.c | 1529 +++++++++++++++++ .../INCHI_EXE/inchi-1/src/CMakeLists.txt | 13 +- .../src/{ichimain.c => backup_ichimain.c} | 0 INCHI-1-SRC/INCHI_EXE/inchi-1/src/main.c | 266 +++ 11 files changed, 1862 insertions(+), 286 deletions(-) delete mode 100644 INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/cis_platin.mol delete mode 100644 INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_alkene.ds_0.mol delete mode 100644 INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_bidentate.ds_7.mol delete mode 100644 INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_carbonyl.ds_0.mol rename INCHI-1-SRC/{INCHI_EXE/inchi-1 => INCHI_BASE}/src/dispstru.c (98%) rename INCHI-1-SRC/{INCHI_EXE/inchi-1 => INCHI_BASE}/src/dispstru.h (100%) create mode 100644 INCHI-1-SRC/INCHI_BASE/src/ichimain.c rename INCHI-1-SRC/INCHI_EXE/inchi-1/src/{ichimain.c => backup_ichimain.c} (100%) create mode 100644 INCHI-1-SRC/INCHI_EXE/inchi-1/src/main.c diff --git a/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/cis_platin.mol b/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/cis_platin.mol deleted file mode 100644 index 92a570bd..00000000 --- a/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/cis_platin.mol +++ /dev/null @@ -1,26 +0,0 @@ - - ACCLDraw09152511572D - - 11 10 0 0 0 0 0 0 0 0999 V2000 - 13.6841 -9.2760 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 - 13.6841 -10.4428 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 - 13.1007 -9.8594 0.0000 Pt 0 0 0 0 0 0 0 0 0 0 0 0 - 12.7309 -8.4791 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 - 11.7204 -10.2293 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 - 11.7204 -9.4896 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 - 12.7308 -11.2397 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 - 12.5173 -10.4428 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 - 12.3038 -11.2397 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 - 12.5173 -9.2760 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 - 11.7204 -9.0625 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 - 3 1 1 0 0 0 0 - 3 2 1 0 0 0 0 - 3 8 1 0 0 0 0 - 3 10 1 0 0 0 0 - 10 6 1 0 0 0 0 - 10 4 1 0 0 0 0 - 8 5 1 0 0 0 0 - 8 7 1 0 0 0 0 - 8 9 1 0 0 0 0 - 10 11 1 0 0 0 0 -M END diff --git a/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_alkene.ds_0.mol b/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_alkene.ds_0.mol deleted file mode 100644 index 58be810f..00000000 --- a/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_alkene.ds_0.mol +++ /dev/null @@ -1,18 +0,0 @@ - -Generated by WebMolKit - - 6 6 0 0 1 0 0 0 0 0999 V2000 - 0.0000 0.0000 0.0000 Pt 0 5 0 0 0 0 0 0 0 0 0 0 - 1.5000 0.0000 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 - 0.0000 1.5000 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 - 0.0000 -1.5000 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 - -1.5990 0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -1.5990 -0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 1 2 1 0 0 0 0 - 1 3 1 0 0 0 0 - 1 4 1 0 0 0 0 - 1 5 0 0 0 0 0 - 5 6 2 0 0 0 0 - 6 1 0 0 0 0 0 -M CHG 1 1 -1 -M END \ No newline at end of file diff --git a/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_bidentate.ds_7.mol b/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_bidentate.ds_7.mol deleted file mode 100644 index b768f346..00000000 --- a/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_bidentate.ds_7.mol +++ /dev/null @@ -1,135 +0,0 @@ - -Generated by WebMolKit - - 55 61 0 0 1 0 0 0 0 0999 V2000 - 0.0000 0.0000 0.0000 Ru 0 0 0 0 0 0 0 0 0 0 0 0 - -1.7532 -0.4698 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 - -1.7290 0.9982 0.0000 C 0 0 0 0 0 2 0 0 0 0 0 0 - -3.0281 1.7482 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 - -2.1414 -1.9186 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -1.0807 -2.9793 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 - 3.3492 0.0125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 2.5775 1.2989 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 - 2.6210 -1.2989 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 - -2.0000 2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 0.0000 4.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 2.0000 2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -2.7500 0.7010 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -2.7500 3.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -4.2500 0.7010 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -5.0000 2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -4.2500 3.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -1.2990 4.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 1.2990 4.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -1.2990 6.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 0.0000 7.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 1.2990 6.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 2.7500 3.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 2.7500 0.7010 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 4.2500 3.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 5.0000 2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 4.2500 0.7010 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 0.0000 2.0000 0.0000 P 0 0 0 0 0 0 0 0 0 0 0 0 - 2.0000 -2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 0.0000 -4.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -2.0000 -2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 2.7500 -0.7010 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 2.7500 -3.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 4.2500 -0.7010 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 5.0000 -2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 4.2500 -3.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 1.2990 -4.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -1.2990 -4.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 1.2990 -6.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 0.0000 -7.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -1.2990 -6.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -2.7500 -3.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -2.7500 -0.7010 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -4.2500 -3.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -5.0000 -2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -4.2500 -0.7010 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 0.0000 -2.0000 0.0000 P 0 0 0 0 0 0 0 0 0 0 0 0 - -3.2020 -3.7558 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 - -3.9786 -0.8580 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 - -5.0391 -2.6952 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 - -3.5903 -2.3069 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 4.8240 1.5373 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 - 4.8740 -1.4623 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 - 6.3488 0.0625 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 - 4.8490 0.0375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 1 2 1 0 0 0 0 - 1 3 0 0 0 0 0 - 3 4 2 0 0 0 0 - 2 5 1 0 0 0 0 - 5 6 2 0 0 0 0 - 7 8 2 0 0 0 0 - 7 9 1 0 0 0 0 - 9 1 1 0 0 0 0 - 8 1 0 0 0 0 0 - 28 10 1 0 0 0 0 - 28 11 1 0 0 0 0 - 28 12 1 0 0 0 0 - 10 13 1 0 0 0 0 - 10 14 2 0 0 0 0 - 13 15 2 0 0 0 0 - 15 16 1 0 0 0 0 - 16 17 2 0 0 0 0 - 17 14 1 0 0 0 0 - 11 18 1 0 0 0 0 - 11 19 2 0 0 0 0 - 18 20 2 0 0 0 0 - 20 21 1 0 0 0 0 - 21 22 2 0 0 0 0 - 22 19 1 0 0 0 0 - 12 23 1 0 0 0 0 - 12 24 2 0 0 0 0 - 23 25 2 0 0 0 0 - 25 26 1 0 0 0 0 - 26 27 2 0 0 0 0 - 27 24 1 0 0 0 0 - 1 28 0 0 0 0 0 - 47 29 1 0 0 0 0 - 47 30 1 0 0 0 0 - 47 31 1 0 0 0 0 - 29 32 1 0 0 0 0 - 29 33 2 0 0 0 0 - 32 34 2 0 0 0 0 - 34 35 1 0 0 0 0 - 35 36 2 0 0 0 0 - 36 33 1 0 0 0 0 - 30 37 1 0 0 0 0 - 30 38 2 0 0 0 0 - 37 39 2 0 0 0 0 - 39 40 1 0 0 0 0 - 40 41 2 0 0 0 0 - 41 38 1 0 0 0 0 - 31 42 1 0 0 0 0 - 31 43 2 0 0 0 0 - 42 44 2 0 0 0 0 - 44 45 1 0 0 0 0 - 45 46 2 0 0 0 0 - 46 43 1 0 0 0 0 - 1 47 0 0 0 0 0 - 51 48 1 0 0 0 0 - 51 49 1 0 0 0 0 - 51 50 1 0 0 0 0 - 5 51 1 0 0 0 0 - 55 52 1 0 0 0 0 - 55 53 1 0 0 0 0 - 55 54 1 0 0 0 0 - 7 55 1 0 0 0 0 -M STY 1 1 SUP -M SAL 1 15 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 -M SAL 1 4 25 26 27 28 -M SMT 1 P|Ph{3} -M STY 1 2 SUP -M SAL 2 15 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 -M SAL 2 4 44 45 46 47 -M SMT 2 P|Ph{3} -M STY 1 3 SUP -M SAL 3 4 48 49 50 51 -M SMT 3 C|F{3} -M STY 1 4 SUP -M SAL 4 4 52 53 54 55 -M SMT 4 C|F{3} -M END \ No newline at end of file diff --git a/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_carbonyl.ds_0.mol b/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_carbonyl.ds_0.mol deleted file mode 100644 index 2d2ca465..00000000 --- a/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_carbonyl.ds_0.mol +++ /dev/null @@ -1,41 +0,0 @@ - -Generated by WebMolKit - - 11 10 0 0 1 0 0 0 0 0999 V2000 - 0.0000 0.0000 0.0000 Fe 0 0 0 0 0 0 0 0 0 0 0 0 - 0.0000 1.5000 0.0000 C 0 0 0 0 0 2 0 0 0 0 0 0 - 0.0000 3.0000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 - 0.0000 -1.5000 0.0000 C 0 0 0 0 0 2 0 0 0 0 0 0 - 0.0000 -3.0000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 - 1.2991 -0.7500 0.0000 C 0 0 0 0 0 2 0 0 0 0 0 0 - 2.5981 -1.5000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 - 1.2990 0.7500 0.0000 C 0 0 0 0 0 2 0 0 0 0 0 0 - 2.5980 1.5001 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 - -1.5000 0.0000 0.0000 C 0 0 0 0 0 2 0 0 0 0 0 0 - -3.0000 0.0000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 - 1 2 0 0 0 0 0 - 2 3 2 0 0 0 0 - 1 4 0 0 0 0 0 - 4 5 2 0 0 0 0 - 1 6 0 0 0 0 0 - 6 7 2 0 0 0 0 - 1 8 0 0 0 0 0 - 8 9 2 0 0 0 0 - 1 10 0 0 0 0 0 - 10 11 2 0 0 0 0 -M STY 1 1 SUP -M SAL 1 2 2 3 -M SMT 1 C|O -M STY 1 2 SUP -M SAL 2 2 4 5 -M SMT 2 C|O -M STY 1 3 SUP -M SAL 3 2 6 7 -M SMT 3 C|O -M STY 1 4 SUP -M SAL 4 2 8 9 -M SMT 4 C|O -M STY 1 5 SUP -M SAL 5 2 10 11 -M SMT 5 C|O -M END \ No newline at end of file diff --git a/INCHI-1-SRC/INCHI_API/demos/mol2inchi/src/CMakeLists.txt b/INCHI-1-SRC/INCHI_API/demos/mol2inchi/src/CMakeLists.txt index 8654f50e..1f89d99a 100644 --- a/INCHI-1-SRC/INCHI_API/demos/mol2inchi/src/CMakeLists.txt +++ b/INCHI-1-SRC/INCHI_API/demos/mol2inchi/src/CMakeLists.txt @@ -51,7 +51,7 @@ if(MATH_LIBRARY) target_link_libraries(mol2inchi PUBLIC ${MATH_LIBRARY}) endif() -target_compile_definitions(mol2inchi PRIVATE +target_compile_definitions(mol2inchi PRIVATE BUILD_LINK_AS_DLL TARGET_EXE_USING_API ) @@ -70,7 +70,7 @@ else() set(CMAKE_THREAD_PREFER_PTHREAD TRUE) set(THREADS_PREFER_PTHREAD_FLAG TRUE) find_package(Threads REQUIRED) - target_link_libraries(mol2inchi Threads::Threads) + target_link_libraries(mol2inchi PRIVATE Threads::Threads) add_custom_command(TARGET mol2inchi POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ $ COMMAND_EXPAND_LISTS diff --git a/INCHI-1-SRC/INCHI_EXE/inchi-1/src/dispstru.c b/INCHI-1-SRC/INCHI_BASE/src/dispstru.c similarity index 98% rename from INCHI-1-SRC/INCHI_EXE/inchi-1/src/dispstru.c rename to INCHI-1-SRC/INCHI_BASE/src/dispstru.c index c70ce860..f5bff79f 100644 --- a/INCHI-1-SRC/INCHI_EXE/inchi-1/src/dispstru.c +++ b/INCHI-1-SRC/INCHI_BASE/src/dispstru.c @@ -40,7 +40,7 @@ /* Draw input atom -- Win32 specific */ -#include "../../../INCHI_BASE/src/mode.h" +#include "mode.h" #ifndef COMPILE_ANSI_ONLY @@ -347,13 +347,13 @@ BOOL TextOutVert( HDC pDC, /* handle to DC */ GetTextMetrics( pDC, &TextMetric ); dy = TextMetric.tmHeight; - + for (i = 0, ret = 1; ret && i < cbString; nYStart += dy, i++) { char_width = GetOneCharInStringWidth( pDC, lpString + i ); ret = TextOut( pDC, nXStart + ( cell_width - char_width ) / 2, nYStart, lpString + i, 1 ); } - + return ret; } @@ -366,8 +366,8 @@ BOOL TextOutHoriz( HDC pDC, /* handle to DC */ int cbString, /* number of characters */ int cell_width ) { - int dX = ( cell_width && cbString == 1 ) - ? ( cell_width - GetOneCharInStringWidth( pDC, lpString ) ) / 2 + int dX = ( cell_width && cbString == 1 ) + ? ( cell_width - GetOneCharInStringWidth( pDC, lpString ) ) / 2 : 0; return TextOut( pDC, nXStart + dX, nYStart, lpString, cbString ); @@ -663,7 +663,7 @@ int DrawBond( HDC pDC, { DrawBondParity( pDC, x1, y1, x2, y2, b_parity ); } - + if (xCRU) { DrawBondCrossingCRU(pDC, x1, y1, x2, y2); @@ -726,7 +726,7 @@ void DrawPenColorFilledPolygon( HDC pDC, const POINT *pnt, int num ) ret = GetObject( penOld, sizeof( LogPen ), &LogPen ); SelectObject( pDC, penOld ); - + /* do not need to delete stock object penNew */ if (ret) { @@ -829,7 +829,7 @@ int DrawBondStereo( HDC pDC, POINT pnt[4]; - + if (b_highlight) { hHighlightPen = CreatePen( PS_SOLID, nPenWidth, clrHighlight ); @@ -1012,27 +1012,27 @@ int DrawBondParity( HDC pDC, parity_mark = parity_mark0; } - if (parity_mark == BOND_MARK_ODD) + if (parity_mark == BOND_MARK_ODD) { - p = "(-)"; + p = "(-)"; } - else if (parity_mark == BOND_MARK_EVEN) + else if (parity_mark == BOND_MARK_EVEN) { p = "(+)"; /*" |"; */ } - else if (parity_mark == BOND_MARK_UNDF) + else if (parity_mark == BOND_MARK_UNDF) { - p = "(?)"; + p = "(?)"; } - else if (parity_mark == BOND_MARK_UNKN) + else if (parity_mark == BOND_MARK_UNKN) { - p = "(u)"; + p = "(u)"; } - else if (parity_mark == BOND_MARK_ERR) + else if (parity_mark == BOND_MARK_ERR) { - p = "(!)"; + p = "(!)"; } - else + else { return 0; } @@ -1084,7 +1084,7 @@ int DrawBondCrossingCRU(HDC pDC, int x1, int y1, int x2, int y2) char *p; p = " //"; /*"(+)"; */ - + if (abs(x2 - x1) > 10 * abs(y2 - y1)) { /* almost horizontal bond; draw parity closer (1:2) to the right end */ @@ -1137,7 +1137,7 @@ int DrawBondNoStereo( HDC pDC, COLORREF clr = clrPen; switch (b_type) - { + { /* c=center, l=left, r=right */ case 0: c = 'D'; @@ -1240,8 +1240,8 @@ int DrawBondNoStereo( HDC pDC, DrawLine( pDC, x1, y1, x2, y2 ); hLongDashedPen = (HPEN) SelectObject( pDC, hSolidPen ); } - - + + /* draw lines parallel to line between bonds */ if (l || r) @@ -1252,14 +1252,14 @@ int DrawBondNoStereo( HDC pDC, bond_sep = hfont / 12.0; if (( x1 == x2 ) || ( y1 == y2 )) { - if (bond_sep < 1.0) + if (bond_sep < 1.0) { bond_sep = 1.0; } } else { - if (bond_sep < 2.0) + if (bond_sep < 2.0) { bond_sep = 2.0; } @@ -1270,14 +1270,14 @@ int DrawBondNoStereo( HDC pDC, bond_sep = hfont / 6.0; if (( x1 == x2 ) || ( y1 == y2 )) { - if (bond_sep < 2.0) + if (bond_sep < 2.0) { bond_sep = 2.0; } } else { - if (bond_sep < 4.0) + if (bond_sep < 4.0) { bond_sep = 4.0; } @@ -1397,9 +1397,9 @@ int MyTextOutABC( const char *p, int iFst, int iLst, HDC pDC ) { return 0; } - + GetCurrentPositionEx( pDC, &pt ); - + if (GetCharABCWidths( pDC, /* handle to DC */ (int) p[iFst], /* first character in range */ (int) p[iFst], /* last character in range */ @@ -1411,7 +1411,7 @@ int MyTextOutABC( const char *p, int iFst, int iLst, HDC pDC ) } TextOut( pDC, pt.x, pt.y, p + iFst, iLst - iFst + 1 ); - + if (GetCharABCWidths( pDC, /* handle to DC */ (int) p[iLst], /* first character in range */ (int) p[iLst], /* last character in range */ @@ -1422,7 +1422,7 @@ int MyTextOutABC( const char *p, int iFst, int iLst, HDC pDC ) pt.x -= abc.abcC; MoveToEx( pDC, pt.x, pt.y, NULL ); } - + return 1; } @@ -1438,15 +1438,15 @@ int DrawColorString( HDC pDC,const char *st, int xs, int ys, int bHighlightTheAt COLORREF NewBkColor=0; int bWritingAtomStringColored = 0; - /* - Draw the string character by character. - For each character within the first part of the string - make a decision if it is a subscript or a superscript - The first part ends with '/'=start of the canonical number or '(' = start of the parity mark - The superscript first character is ^ or + or - or . (. initiates double shift) - The the superscript ends with not the first character and not a digit or the end of the first part - The first character of a subscript (if it is not in the superscript) is a digit - The subscript ends a non-digit + /* + Draw the string character by character. + For each character within the first part of the string + make a decision if it is a subscript or a superscript + The first part ends with '/'=start of the canonical number or '(' = start of the parity mark + The superscript first character is ^ or + or - or . (. initiates double shift) + The the superscript ends with not the first character and not a digit or the end of the first part + The first character of a subscript (if it is not in the superscript) is a digit + The subscript ends a non-digit */ const char *p = st; UINT uPrevTextAlign = SetTextAlign( pDC, TA_UPDATECP ); @@ -1672,11 +1672,11 @@ int DrawColorString( HDC pDC,const char *st, int xs, int ys, int bHighlightTheAt /****************************************************************************/ -int DrawPreparedString( HDC pDC, - char *st1, - int shift, - int x, - int y, +int DrawPreparedString( HDC pDC, + char *st1, + int shift, + int x, + int y, int bHighlightTheAtom ) { DrawColorString( pDC, st1, x + shift, y - GetFontAscent( pDC ) / 2, bHighlightTheAtom ); @@ -1705,7 +1705,7 @@ int DrawString( HDC pDC, char *st1, int shift, int x, int y ) ys = y - afont / 2; /* Single element */ - if (strlen( st ) == 1) + if (strlen( st ) == 1) { goto draw; } @@ -1719,7 +1719,7 @@ int DrawString( HDC pDC, char *st1, int shift, int x, int y ) start = MoveHydrogenAtomToTheLeft(st, start, 'D'); start = MoveHydrogenAtomToTheLeft(st, start, 'H'); /* determine the position */ - if (( strlen( st ) == 2 ) && islower( st[1] )) + if (( strlen( st ) == 2 ) && islower( st[1] )) { goto draw; } @@ -1918,7 +1918,7 @@ void CalcTblParms( HDC hMemoryDC, tp->tblRows = inchi_max( tp->tblRows, n ); } if (tdp->nOrientation) - { + { /* here are tp->tblCols columns and tp->tblRows rows. */ tp->tblHeight = tp->thdrHeight + ( 2 * tp->tblRows + 2 )*tp->tcellHeight; /* empty lines above the header and around each cell */ tp->thdrWidth = tp->tcellWidth = inchi_max( tp->tcellWidth, tp->thdrWidth ); @@ -1930,7 +1930,7 @@ void CalcTblParms( HDC hMemoryDC, tp->ytblOffs = yoffs1; } else - { + { /* Do not believe your eyes: here are tp->tblCols rows and tp->tblRows columns. */ tp->thdrHeight = tp->tcellHeight = inchi_max( tp->thdrHeight, tp->tcellHeight ); tp->tblWidth = tp->thdrWidth + ( 2 * tp->tblRows + 2 )*tp->tcellWidth; @@ -1956,7 +1956,7 @@ int DrawTheTable( HDC hDC, int dx = tp->tcellWidth / 2; int dy = tp->tcellHeight / 2; int x1, y1, x2, y2; - + /* draw frame around the table */ ret = Rectangle( hDC, tp->xtblOffs + dx + x_offs, tp->ytblOffs + dy + y_offs, tp->xtblOffs + tp->tblWidth - dx + x_offs, tp->ytblOffs + tp->tblHeight - dy + y_offs ); /* djb-rwth: removing redundant variable *//* djb-rwth: ignoring LLVM warning: variable used to store function return value */ @@ -1979,7 +1979,7 @@ int DrawTheTable( HDC hDC, } DrawLine( hDC, x1 + x_offs, y1 + y_offs, x2 + x_offs, y2 + y_offs ); } - + /* draw lines between requested/Shown/Found types */ for (i = 0; i < tp->tblRows; i++) { @@ -2604,7 +2604,7 @@ int CreateInputStructPicture( HDC hDC, /* Calculate requested/Shown/Found table sizes */ /***********************************************/ memset(&tp, 0, sizeof(tp)); /* djb-rwth: memset_s C11/Annex K variant? */ - + #ifdef TARGET_LIB_FOR_WINCHI bDrawTbl = 0; #else @@ -2760,15 +2760,15 @@ int CreateInputStructPicture( HDC hDC, { strcat(str, ":"); } - if (bTaut) + if (bTaut) { strcat(str, " Mobile H"); } - if (bIso) + if (bIso) { strcat(str, " Isotopic"); } - if (bSter) + if (bSter) { strcat(str, " Stereo"); } @@ -2776,7 +2776,7 @@ int CreateInputStructPicture( HDC hDC, } if (pWinData->inf_at_data.szRemovedProtons[0]) { - if (str[0]) + if (str[0]) strcat( str, "; " ); /* djb-rwth: function replaced with its safe C11 variant */ strcat(str, pWinData->inf_at_data.szRemovedProtons); } @@ -3297,7 +3297,7 @@ int DisplayInputStructure( char *szOutputString, UnregisterClass( szWindowClassName, /* address of class name string */ hInstance /* handle of application instance */ ); - + /* Save window size and position */ if (WinData.rc.bottom > WinData.rc.top && WinData.rc.right > WinData.rc.left) { @@ -3306,12 +3306,12 @@ int DisplayInputStructure( char *szOutputString, dp->pdp->rcPict[2] = WinData.rc.right - WinData.rc.left; dp->pdp->rcPict[3] = WinData.rc.bottom - WinData.rc.top; } - + if (WinData.bEsc) { dp->rdp.bEsc = 1; } - + return WinData.bEsc ? 27 : 1; } #endif diff --git a/INCHI-1-SRC/INCHI_EXE/inchi-1/src/dispstru.h b/INCHI-1-SRC/INCHI_BASE/src/dispstru.h similarity index 100% rename from INCHI-1-SRC/INCHI_EXE/inchi-1/src/dispstru.h rename to INCHI-1-SRC/INCHI_BASE/src/dispstru.h diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichimain.c b/INCHI-1-SRC/INCHI_BASE/src/ichimain.c new file mode 100644 index 00000000..a575437b --- /dev/null +++ b/INCHI-1-SRC/INCHI_BASE/src/ichimain.c @@ -0,0 +1,1529 @@ +/* + * International Chemical Identifier (InChI) + * Version 1 + * Software version 1.07 + * April 30, 2024 + * + * MIT License + * + * Copyright (c) 2024 IUPAC and InChI Trust + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. +* +* The InChI library and programs are free software developed under the + * auspices of the International Union of Pure and Applied Chemistry (IUPAC). + * Originally developed at NIST. + * Modifications and additions by IUPAC and the InChI Trust. + * Some portions of code were developed/changed by external contributors + * (either contractor or volunteer) which are listed in the file + * 'External-contributors' included in this distribution. + * + * info@inchi-trust.org + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef COMPILE_ANSI_ONLY +// #include +#ifndef TARGET_LIB_FOR_WINCHI +// #include +#endif +#endif + +#include "mode.h" + +#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) +#include +#include +#endif + + +#ifdef _WIN32 +#include +#endif +#include "ichitime.h" +#include "incomdef.h" +#include "ichidrp.h" +#include "inpdef.h" +#include "ichi.h" +#include "strutil.h" +#include "util.h" +#include "ichierr.h" +#include "ichimain.h" +#include "ichicomp.h" +#include "ichi_io.h" +#ifdef TARGET_EXE_STANDALONE +#include "inchi_api.h" +#endif + +#include "bcf_s.h" +#include "permutation_util.h" + + /* Console-specific */ + + + +#ifndef TARGET_LIB_FOR_WINCHI +/* COVERS THE CODE FROM HERE TO THE END OF FILE */ + + +/* Enable/disable internal tests */ + +/* Uncomment for INCHI_LIB testing only */ +/*#define TEST_FPTRS*/ + +/* Windows-console-mode specific */ + +// int bInterrupted = 0; + + +/****************************************************************************/ +int ProcessMultipleInputFiles(int argc, char* argv[]) +{ + int i, ret = 0, nfn_ins = 0, + AMIOutStd = 0, AMILogStd = 0, AMIPrbNone = 0; + char* fn_out, * fn_log, * fn_prb; + char pNUL[] = "NUL"; + char** fn_ins = NULL, ** targv = NULL; + int ret_val; /* djb-rwth: adding return value */ /* djb-rwth: ignoring LLVM warning */ + +#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) +#ifdef _WIN64 + typedef __int64 intptr_t; /* x64 */ +#else + typedef long int intptr_t; /* VC 6.0 has no intptr_t and no x64 */ +#endif + struct _finddata_t file_info; + intptr_t hFile = -1; + int retFile, lenPath; + char* pName, * pOutPath = NULL; /* djb-rwth: ignoring LLVM warning */ + char pathname[_MAX_PATH]; + char szBlank[] = ""; /* djb-rwth: ignoring LLVM warning */ + int numFiles = 0; /* counts processed files */ +#else + int p; +#endif + + fn_ins = (char**)inchi_calloc(argc, sizeof(char*)); + if (!fn_ins) + { + fprintf(stderr, "Not enough memory.\n"); + goto exit_ami; + } + + /* Check for other options and collect inputs. */ + for (i = 1; i < argc; i++) + { + if (argv[i][0] == INCHI_OPTION_PREFX) + { + if (!inchi_stricmp(argv[i] + 1, "STDIO")) + { + fprintf(stderr, "Options AMI and STDIO are not compatible.\n"); + goto exit_ami; + } + else if (!inchi_stricmp(argv[i] + 1, "AMIOutStd")) + { + AMIOutStd = 1; + } + else if (!inchi_stricmp(argv[i] + 1, "AMILogStd")) + { + AMILogStd = 1; + } + else if (!inchi_stricmp(argv[i] + 1, "AMIPrbNone")) + { + AMIPrbNone = 1; + } +#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) + else if (!inchi_memicmp(argv[i] + 1, "OP:", 3)) + { + pOutPath = argv[i] + 4; /* output path */ + } +#endif + } + else + { + fn_ins[nfn_ins] = argv[i]; + nfn_ins++; + } + } + + if (!nfn_ins) + { + fprintf(stderr, "At least one input file is expected in AMI mode.\n"); + goto exit_ami; + } + + targv = (char**)inchi_calloc((long long)argc + 3, sizeof(char*)); /* djb-rwth: cast operator added */ + + if (!targv) + { + fprintf(stderr, "Not enough memory.\n"); + goto exit_ami; + } + +#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) + if ((pName = strrchr(fn_ins[0], INCHI_PATH_DELIM))) /* djb-rwth: addressing LLVM warning */ + { + pName++; + lenPath = pName - fn_ins[0]; + } + else + { + pName = fn_ins[0]; + lenPath = 0; + } + for (hFile = _findfirst(fn_ins[0], &file_info), retFile = 0; + !retFile && -1 != hFile; + retFile = _findnext(hFile, &file_info), numFiles++) +#else + for (p = 0; p < nfn_ins; p++) +#endif + { + int targc; +#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) + const char* fn_in; + int inlen = lenPath + strlen(file_info.name); + if (!file_info.size || (file_info.attrib & _A_SUBDIR) || inlen >= _MAX_PATH) + { + continue; + } + memcpy(pathname, fn_ins[0], lenPath); + strcpy(pathname + lenPath, file_info.name); + fn_in = pathname; + if (0 == numFiles % 5000) + { + ret_val = _heapmin(); /* reduce heap fragmentation */ /* djb-rwth: return value variable added */ + } +#else + const char* fn_in = fn_ins[p]; + int inlen = strlen(fn_in); +#endif + fn_out = fn_log = fn_prb = NULL; + + targv[0] = argv[0]; + targv[1] = (char*)fn_in; + targc = 1; + + if (AMIOutStd) + { + targv[++targc] = pNUL; + } +#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 && ALLOW_EMPTY_PATHS == 1 ) + else if (pOutPath) + { + targv[++targc] = szBlank; /* output name will be created in process_single_input(...) */ + } +#endif + else + { + /* make output name as input name plus ext. */ + fn_out = (char*)inchi_calloc((long long)inlen + 6, sizeof(char)); /* djb-rwth: cast operator added */ + if (fn_out) + { + strcpy(fn_out, fn_in); + strcat(fn_out, ".txt"); + } + targv[++targc] = fn_out; + } + + if (AMILogStd) + { + targv[++targc] = pNUL; + } +#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 && ALLOW_EMPTY_PATHS == 1 ) + else if (pOutPath) + { + targv[++targc] = szBlank; /* output name will be created in process_single_input(...) */ + } +#endif + else + { + /* Make log name as input name plus ext. */ + fn_log = (char*)inchi_calloc((long long)inlen + 6, sizeof(char)); /* djb-rwth: cast operator added */ + if (fn_log) + { + strcpy(fn_log, fn_in); + strcat(fn_log, ".log"); + } + targv[++targc] = fn_log; + } + if (AMIPrbNone) + { + targv[++targc] = pNUL; + } +#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 && ALLOW_EMPTY_PATHS == 1 ) + else if (pOutPath) + { + targv[++targc] = szBlank; /* output name will be created in process_single_input(...) */ + } +#endif + else + { + /* Make problem file name as input file name plus ext. */ + fn_prb = (char*)inchi_calloc((long long)inlen + 6, sizeof(char)); /* djb-rwth: cast operator added */ + if (fn_prb) + { + strcpy(fn_prb, fn_in); + strcat(fn_prb, ".prb"); + } + targv[++targc] = fn_prb; + } + + for (i = 1; i < argc; i++) + { + if (argv[i][0] == INCHI_OPTION_PREFX) + { + /* avoid strnicmp/strncasecmp */ + if ((strlen(argv[i]) > 3) && + (toupper(argv[i][1]) == 'A') && (toupper(argv[i][2]) == 'M') && (toupper(argv[i][3]) == 'I')) + { + continue; + } + targv[++targc] = argv[i]; + } + } + /* djb-rwth: fixing undefined index value / buffer overflow */ + ++targc; + if (targc < argc + 3) + { + targv[targc] = NULL; + } + + ret = ProcessSingleInputFile(targc, targv); /* ProcessSingleInputFile() is a former main() */ + + if (fn_out) + { + inchi_free(fn_out); + } + if (fn_log) + { + inchi_free(fn_log); + } + if (fn_prb) + { + inchi_free(fn_prb); + } + +#if ( defined( _WIN32 ) && defined( _CONSOLE ) && !defined( COMPILE_ANSI_ONLY ) ) + if (ret == CTRL_STOP_EVENT) + { + goto exit_ami; + } +#endif + } + + +exit_ami: +#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) + if (hFile != -1) + { + _findclose(hFile); + } +#endif + if (targv) + { + inchi_free(targv); + } + if (fn_ins) + { + inchi_free(fn_ins); + } + + return 0; +} + + + +/****************************************************************************/ +int ProcessSingleInputFile(int argc, char* argv[]) +{ + /**************************************/ +#endif /* #if ( BUILD_WITH_AMI == 1 ) */ +/**************************************/ + +/**** IF NOT IN AMI MODE, main() STARTS HERE ****/ + + int bReleaseVersion = bRELEASE_VERSION; + const int nStrLen = INCHI_SEGM_BUFLEN; + int nRet = 0; + int i; + long num_err, num_output, num_inp; + /* long rcPict[4] = {0,0,0,0}; */ + unsigned long ulDisplTime = 0; /* infinite, milliseconds */ + unsigned long ulTotalProcessingTime = 0; + + CANON_GLOBALS CG; + INCHI_CLOCK ic; + + char szTitle[MAX_SDF_HEADER + MAX_SDF_VALUE + 256]; + char szSdfDataValue[MAX_SDF_VALUE + 1]; + + INPUT_PARMS inp_parms; + INPUT_PARMS* ip = &inp_parms; + + STRUCT_DATA struct_data; + STRUCT_DATA* sd = &struct_data; + + ORIG_ATOM_DATA OrigAtData; /* 0=> disconnected, 1=> original */ + ORIG_ATOM_DATA* orig_inp_data = &OrigAtData; + ORIG_ATOM_DATA PrepAtData[2]; /* 0=> disconnected, 1=> original */ + ORIG_ATOM_DATA* prep_inp_data = PrepAtData; + + PINChI2* pINChI[INCHI_NUM]; + PINChI_Aux2* pINChI_Aux[INCHI_NUM]; + + char* pLF, * pTAB; + INCHI_IOS_STRING temp_string_container; + INCHI_IOS_STRING* strbuf = &temp_string_container; + INCHI_IOSTREAM outputstr, logstr, prbstr, instr; + INCHI_IOSTREAM* pout = &outputstr, * plog = &logstr, * pprb = &prbstr, * inp_file = &instr; + +#ifdef TARGET_EXE_STANDALONE + int inchi_ios_type = INCHI_IOS_TYPE_STRING; +#else + int inchi_ios_type = INCHI_IOS_TYPE_FILE; +#endif +#if ( READ_INCHI_STRING == 1 ) + const int may_get_inchi_string_input = 1; +#else + const int may_get_inchi_string_input = 0; +#endif + int bInChI2Structure = 0; + int output_error_inchi = 0; + + + /* internal tests --- */ +#ifndef TEST_FPTRS + STRUCT_FPTRS* pStructPtrs = NULL; +#else + STRUCT_FPTRS struct_fptrs, * pStructPtrs = &struct_fptrs; /* INCHI_LIB debug only */ +#endif + +#if ( defined(_WIN32) && defined(_MSC_VER) ) +#if WINVER >= 0x0501 /* XP or newer */ /* 0x0600 Vista or newer */ + DWORD tick_inchi_start, tick_inchi_stop; + tick_inchi_start = GetTickCount64(); /* djb-rwth: GetTickCount64() should be used */ +#endif +#endif + +#ifdef _WIN32 +#if ( TRACE_MEMORY_LEAKS == 1 ) + _CrtSetDbgFlag(_CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF); + /* for execution outside the VC++ debugger uncomment one of the following two */ + /*#define MY_REPORT_FILE _CRTDBG_FILE_STDERR */ + /*#define MY_REPORT_FILE _CRTDBG_FILE_STDOUT */ +#ifdef MY_REPORT_FILE + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_WARN, MY_REPORT_FILE); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ERROR, MY_REPORT_FILE); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ASSERT, MY_REPORT_FILE); +#else + _CrtSetReportMode(_CRT_WARN | _CRT_ERROR, _CRTDBG_MODE_DEBUG); +#endif + /* turn on floating point exceptions */ + { + /* Get the default control word. */ + int cw = _controlfp(0, 0); + + /* Set the exception masks OFF, turn exceptions on. */ + /*cw &=~(EM_OVERFLOW|EM_UNDERFLOW|EM_INEXACT|EM_ZERODIVIDE|EM_DENORMAL);*/ + cw &= ~(EM_OVERFLOW | EM_UNDERFLOW | EM_ZERODIVIDE | EM_DENORMAL); + + /* Set the control word. */ + _controlfp(cw, MCW_EM); +} +#endif +#endif + + sd->bUserQuit = 0; + /* djb-rwth: fixing coverity CID #499552 */ + sd->num_components[0] = 0; + sd->num_components[1] = 0; +#if ( defined( _WIN32 ) && defined( _CONSOLE ) && !defined( COMPILE_ANSI_ONLY ) ) + if (SetConsoleCtrlHandler(MyHandlerRoutine, 1)) + { + ConsoleQuit = WasInterrupted; + } +#endif + + num_inp = 0; + num_err = 0; + num_output = 0; + + inchi_ios_init(inp_file, INCHI_IOS_TYPE_FILE, NULL); + inchi_ios_init(pout, inchi_ios_type, NULL); + inchi_ios_init(plog, inchi_ios_type, stdout); + inchi_ios_init(pprb, inchi_ios_type, NULL); + memset(strbuf, 0, sizeof(*strbuf)); /* djb-rwth: memset_s C11/Annex K variant?; dereferencing strbuf */ + + if (argc == 1 || (argc == 2 && (argv[1][0] == INCHI_OPTION_PREFX) && + ((!strcmp(argv[1] + 1, "?") || !inchi_stricmp(argv[1] + 1, "help"))))) /* djb-rwth: addressing LLVM warning */ + { + HelpCommandLineParms(plog); + inchi_ios_flush(plog); + return 0; + } + + /* djb-rwth: printing out InChI version */ + if (argc == 2 && ((argv[1][0] == INCHI_OPTION_PREFX)) && (!strcmp(argv[1] + 1, "v") || !strcmp(argv[1] + 1, "V"))) + { + printf("%s\n", APP_DESCRIPTION); + return 0; + } + + /* djb-rwth: disallowing endless execution if no file(s) is given as the first argument */ + if (argc >= 2 && ((argv[1][0] == INCHI_OPTION_PREFX)) && (strcmp(argv[1] + 1, "v") || strcmp(argv[1] + 1, "V") || strcmp(argv[1] + 1, "?") || inchi_stricmp(argv[1] + 1, "help"))) + { + HelpCommandLineParms(plog); + inchi_ios_flush(plog); + return 0; + } + + /* original input structure */ + memset(orig_inp_data, 0, sizeof(*orig_inp_data)); /* djb-rwth: memset_s C11/Annex K variant? */ + memset(prep_inp_data, 0, 2 * sizeof(*prep_inp_data)); /* djb-rwth: memset_s C11/Annex K variant? */ + memset(pINChI, 0, sizeof(pINChI)); /* djb-rwth: memset_s C11/Annex K variant? */ + memset(pINChI_Aux, 0, sizeof(pINChI_Aux)); /* djb-rwth: memset_s C11/Annex K variant? */ + memset(szSdfDataValue, 0, sizeof(szSdfDataValue)); /* djb-rwth: memset_s C11/Annex K variant? */ + + memset(&CG, 0, sizeof(CG)); /* djb-rwth: memset_s C11/Annex K variant? */ + memset(&ic, 0, sizeof(ic)); /* djb-rwth: memset_s C11/Annex K variant? */ + + plog->f = stderr; + + if (0 > ReadCommandLineParms(argc, (const char**)argv, ip, + szSdfDataValue, &ulDisplTime, + bReleaseVersion, plog)) + { + goto exit_function; + } + + if (!OpenFiles(&(inp_file->f), &(pout->f), &(plog->f), &(pprb->f), ip)) + { + goto exit_function; + } + + + if (ip->bNoStructLabels) + { + ip->pSdfLabel = NULL; + ip->pSdfValue = NULL; + } + else if (ip->nInputType == INPUT_INCHI_PLAIN || + ip->nInputType == INPUT_INCHI) + { + /* the input may contain both the header and the label of the structure */ + if (!ip->pSdfLabel) + { + ip->pSdfLabel = ip->szSdfDataHeader; + } + if (!ip->pSdfValue) + { + ip->pSdfValue = szSdfDataValue; + } + } + + set_line_separators(ip->bINChIOutputOptions, &pLF, &pTAB); + + save_command_line(argc, argv, plog); + + PrintInputParms(plog, ip); + + inchi_ios_flush2(plog, stderr); + + if (0 >= inchi_strbuf_init(strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT)) + { + inchi_ios_eprint(plog, "Cannot allocate internal string buffer. Terminating\n"); + inchi_ios_flush2(plog, stderr); + goto exit_function; + } + + + /* Process InChI string as input; output may be */ + /* a) InChI string or b) structure */ + /*#if ( READ_INCHI_STRING == 1 )*/ + if (may_get_inchi_string_input && ip->nInputType == INPUT_INCHI) + { + bInChI2Structure = 0 != (ip->bReadInChIOptions & READ_INCHI_TO_STRUCTURE); + memset(sd, 0, sizeof(*sd)); /* djb-rwth: memset_s C11/Annex K variant? */ + if (bInChI2Structure) + { + /* loop through file lines here */ + INCHI_IOSTREAM tmpinpustream; + INCHI_IOS_STRING* pTmpIn = &tmpinpustream.s; + int crlf2lf = 0, preserve_lf = 1, read_result = 0; + inchi_ios_init(&tmpinpustream, INCHI_IOS_TYPE_STRING, NULL); + while (1) + { + char* p, * pi; + + read_result = inchi_strbuf_getline(pTmpIn, inp_file->f, crlf2lf, preserve_lf); + + if (read_result == -1) +#if (FIX_ONE_LINE_INCHI_INPUT_CONVERSION_ISSUE==1) + { + if (!pTmpIn->pStr) + { + break; + } + if (strlen(pTmpIn->pStr) < 8) /* 7 = strlen("InChI=1") */ + { + break; + } + } +#else + break; /* EOF or read error */ +#endif + + p = pTmpIn->pStr; + if (!p) + { + continue; + } + pi = strstr(p, "InChI=1"); + if (pi != p) + { + continue; + } + + num_inp++; + ip->lMolfileNumber = num_inp; + + ReadWriteInChI(&ic, &CG, &tmpinpustream, pout, plog, ip, sd, NULL, 0, 0, NULL, NULL, NULL, 0, NULL); + + /*fprintf( stderr, "%ld", num_inp );*/ + inchi_strbuf_reset(pTmpIn); + inchi_ios_flush2(plog, stderr); + } + fprintf(stderr, "\r"); + inchi_strbuf_close(pTmpIn); + } + else + { + /* loop through file lines within ReadWriteInChI */ + ReadWriteInChI(&ic, &CG, inp_file, pout, plog, ip, sd, NULL, 0, 0, NULL, NULL, NULL, 0, NULL); + + num_inp = sd->fPtrStart; + num_err = sd->fPtrEnd; + } + + inchi_ios_flush2(plog, stderr); + ulTotalProcessingTime = sd->ulStructTime; + /*num_inp = sd->fPtrStart; + num_err = sd->fPtrEnd; + */ + goto exit_function; + } + + + ulTotalProcessingTime = 0; + if (pStructPtrs) + { + memset(pStructPtrs, 0, sizeof(pStructPtrs[0])); /* djb-rwth: memset_s C11/Annex K variant? */ + } + output_error_inchi = ip->bINChIOutputOptions2 & INCHI_OUT_INCHI_GEN_ERROR; + + + /*************************************************************/ + /* Main cycle : read input structures and create their INChI */ + /*************************************************************/ + + + while (!sd->bUserQuit ) //&& !bInterrupted + { + int do_renumbering = 0; + int next_action; + int have_err_in_GetOneStructure = 0; + int dup_fail = 0; + ORIG_ATOM_DATA SavedOrigAtData; /* 0=> disconnected, 1=> original */ + ORIG_ATOM_DATA* saved_orig_inp_data = &SavedOrigAtData; + char ikey0[28]; + ikey0[0] = '\0'; + + + next_action = GetTheNextRecordOfInputFile(&ic, sd, ip, szTitle, + inp_file, plog, pout, pprb, + orig_inp_data, &num_inp, pStructPtrs, + &nRet, &have_err_in_GetOneStructure, + &num_err, output_error_inchi); + if (next_action == DO_EXIT_FUNCTION) + { + goto exit_function; + } + else if (next_action == DO_BREAK_MAIN_LOOP) + { + break; + } + else if (next_action == DO_CONTINUE_MAIN_LOOP) + { + if (nRet == _IS_ERROR) /* may also be _IS_SKIP ... */ + { + if (output_error_inchi) + { + Output_RecordInfo(pout, num_inp, ip->bNoStructLabels, ip->pSdfLabel, ip->pSdfValue, ip->lSdfId, + pLF, pTAB); + emit_empty_inchi(ip, num_inp, pLF, pTAB, pout); + } + } + continue; + } + + + /* Create INChI for each connected component of the structure; + optionally display them; + output INChI for the whole structure */ + +#if (RENUMBER_ATOMS_AND_RECALC_V106 == 1 ) + if (ip->bRenumber == 1) + { + do_renumbering = 1; + } +#endif + if (do_renumbering == 0) + { + /* Normal calculations */ + next_action = CalcAndPrintINCHIAndINCHIKEY(&ic, &CG, sd, ip, szTitle, + pINChI, pINChI_Aux, + inp_file, plog, pout, pprb, + orig_inp_data, prep_inp_data, &num_inp, pStructPtrs, + &nRet, have_err_in_GetOneStructure, + &num_err, output_error_inchi, + strbuf, &ulTotalProcessingTime, + pLF, pTAB, ikey0, + 0 /* not silent */); + + FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); + FreeOrigAtData(orig_inp_data); + FreeOrigAtData(prep_inp_data); + FreeOrigAtData(prep_inp_data + 1); + } + else + { + /* Internal test mode: renumber atoms and recalculate repeatedly */ + long int nrepeat = 1; + /* 2! = 2 3! = 6 4! = 24 5! = 120 6! = 520 7! = 5040 8! = 40320 */ + if (orig_inp_data->num_inp_atoms == 1) + { + nrepeat = 1; + } + else if (orig_inp_data->num_inp_atoms == 2) + { + nrepeat = 2; + } + else if (orig_inp_data->num_inp_atoms == 3) + { + nrepeat = 6; + } + else + { + nrepeat = 1000; /* 100000;*/ /*16;*/ + } + /* correct (decrease repeat number) for relatively large molecules */ + if (orig_inp_data->num_inp_atoms > 128) + { + nrepeat = 100; /* 100000;*/ /*16;*/ + } + if (orig_inp_data->num_inp_atoms > 256) + { + nrepeat = 50; /* 100000;*/ /*16;*/ + } + if (orig_inp_data->num_inp_atoms > 512) + { + nrepeat = 25; /* 100000;*/ /*16;*/ + } + if (orig_inp_data->num_inp_atoms > 1024) + { + nrepeat = 10; /* 100000;*/ /*16;*/ + } + + /*inchi_ios_eprint(plog, "Number of random atom renumberings up to: %-ld\n", nrepeat); + inchi_ios_flush2(plog, stderr);*/ + +#if 0 + else if (orig_inp_data->num_inp_atoms == 4) + { + nrepeat = 24; + } + else + { + nrepeat = 10; + } + + else if (orig_inp_data->num_inp_atoms == 4) + { + nrepeat = 24; + } + else if (orig_inp_data->num_inp_atoms == 5) + { + nrepeat = 120; + } + else if (orig_inp_data->num_inp_atoms == 6) + { + nrepeat = 520; + } + else if (orig_inp_data->num_inp_atoms == 7) + { + nrepeat = 1000; + } + else + { + nrepeat = 10000; + } +#endif + + next_action = RepeatedlyRenumberAtomsAndRecalcINCHI(&ic, &CG, sd, ip, szTitle, + pINChI, pINChI_Aux, + inp_file, plog, pout, pprb, + orig_inp_data, prep_inp_data, &num_inp, pStructPtrs, + &nRet, have_err_in_GetOneStructure, + &num_err, output_error_inchi, + strbuf, &ulTotalProcessingTime, + pLF, pTAB, nrepeat); + } /* if (ip->bRenumber == 1) */ + + if (next_action == DO_EXIT_FUNCTION) + { + goto exit_function; + } + else if (next_action == DO_BREAK_MAIN_LOOP) + { + break; + } + else if (next_action == DO_CONTINUE_MAIN_LOOP) + { + continue; + } + } /* end of main cycle - while ( !sd->bUserQuit && !bInterrupted ) */ + + +exit_function: + /* Avoid memory leaks in case of fatal error */ + if (pStructPtrs && pStructPtrs->fptr) + { + inchi_free(pStructPtrs->fptr); + } + /* Free INChI memory */ + FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); + /* Free structure data */ + FreeOrigAtData(orig_inp_data); + FreeOrigAtData(prep_inp_data); + FreeOrigAtData(prep_inp_data + 1); + /* Close files */ + inchi_ios_close(inp_file); + inchi_ios_close(pout); + inchi_ios_close(pprb); + { + int hours, minutes, seconds, mseconds; + + SplitTime(ulTotalProcessingTime, &hours, &minutes, &seconds, &mseconds); + + inchi_ios_eprint(plog, "Finished processing %ld structure%s: %ld error%s, processing time %d:%02d:%02d.%02d\n", + num_inp, num_inp == 1 ? "" : "s", + num_err, num_err == 1 ? "" : "s", + hours, minutes, seconds, mseconds / 10); + inchi_ios_flush2(plog, stderr); + } +#if ( defined(_WIN32) && defined(_MSC_VER) ) +#if WINVER >= 0x0501 /* XP or newer */ /* 0x0600 Vista or newer */ + tick_inchi_stop = GetTickCount64(); /* djb-rwth: GetTickCount64() should be used */ + inchi_ios_eprint(plog, "\nElapsed walltime: %d msec.\n", tick_inchi_stop - tick_inchi_start); + inchi_ios_flush2(plog, stderr); +#endif +#endif + /* Final cleanup */ + inchi_ios_close(plog); + inchi_strbuf_close(strbuf); + for (i = 0; i < MAX_NUM_PATHS; i++) + { + if (ip->path[i]) + { + inchi_free((void*)ip->path[i]); /* cast deliberately discards 'const' qualifier */ + ip->path[i] = NULL; + } + } + SetBitFree(&CG); +#if ( ( BUILD_WITH_AMI==1 ) && defined( _WIN32 ) && defined( _CONSOLE ) && !defined( COMPILE_ANSI_ONLY ) ) + if (bInterrupted) + { + return CTRL_STOP_EVENT; + } +#endif + + return 0; +} + + +/****************************************************************************/ +void save_command_line(int argc, char* argv[], INCHI_IOSTREAM* plog) +{ + int k; + + inchi_ios_eprint(plog, "The command line used:\n\""); + for (k = 0; k < argc - 1; k++) + { +#if( ALLOW_EMPTY_PATHS == 1 ) + inchi_ios_eprint(plog, "%-s ", argv[k][0] ? argv[k] : "\"\""); +#else + inchi_ios_eprint(plog, "%-s ", argv[k]); +#endif + } + + inchi_ios_eprint(plog, "%-s\"\n", argv[argc - 1]); + + return; +} + + +/*****************************************************************************/ +void emit_empty_inchi(INPUT_PARMS* ip, + long num_inp, + char* pLF, + char* pTAB, + INCHI_IOSTREAM* pout) +{ + if (ip->bINChIOutputOptions & INCHI_OUT_STDINCHI) + { + inchi_ios_eprint(pout, "InChI=1S//\n"); /* emit empty Std InChI */ + } + else + { + inchi_ios_eprint(pout, "InChI=1//\n"); /* emit empty InChI */ + } + inchi_ios_flush(pout); +} + + + +/*****************************************************************************/ +int GetTheNextRecordOfInputFile(struct tagINCHI_CLOCK* ic, + STRUCT_DATA* sd, INPUT_PARMS* ip, + char* szTitle, + INCHI_IOSTREAM* inp_file, + INCHI_IOSTREAM* plog, + INCHI_IOSTREAM* pout, + INCHI_IOSTREAM* pprb, + ORIG_ATOM_DATA* orig_inp_data, + long* num_inp, + STRUCT_FPTRS* pStructPtrs, + int* nRet, + int* have_err_in_GetOneStructure, + long* num_err, + int output_error_inchi) +{ + if (ip->last_struct_number && *num_inp >= ip->last_struct_number) + { + *nRet = _IS_EOF; /* simulate end of file */ + return DO_EXIT_FUNCTION; + } + + + *nRet = GetOneStructure(ic, sd, ip, szTitle, inp_file, + plog, pout, pprb, orig_inp_data, + num_inp, pStructPtrs); + + inchi_ios_flush2(plog, stderr); + + if (pStructPtrs) + pStructPtrs->cur_fptr++; + + if (sd->bUserQuit) + { + { + return DO_BREAK_MAIN_LOOP; + } + } + + *have_err_in_GetOneStructure = 0; + switch (*nRet) + { + case _IS_FATAL: + (*num_err)++; + if (output_error_inchi == 0) + { + return DO_EXIT_FUNCTION; + } + else + sd->pStrErrStruct[0] = '\0'; /* depress re-appearance of error as warning in ProcessOneStr */ + break; + case _IS_EOF: + return DO_EXIT_FUNCTION; + case _IS_ERROR: + (*num_err)++; + *have_err_in_GetOneStructure = 1; + if (output_error_inchi == 0) + { + return DO_CONTINUE_MAIN_LOOP; + } + else + sd->pStrErrStruct[0] = '\0'; /* depress re-appearance of error as warning in ProcessOneStr */ + break; + case _IS_SKIP: + return DO_CONTINUE_MAIN_LOOP; + default: + sd->pStrErrStruct[0] = '\0'; + } + + return DO_NEXT_STEP; +} + + +/****************************************************************************/ +int CalcAndPrintINCHIAndINCHIKEY(struct tagINCHI_CLOCK* ic, + CANON_GLOBALS* CG, + STRUCT_DATA* sd, + INPUT_PARMS* ip, + char* szTitle, + PINChI2* pINChI[INCHI_NUM], + PINChI_Aux2* pINChI_Aux[INCHI_NUM], + INCHI_IOSTREAM* inp_file, + INCHI_IOSTREAM* plog, + INCHI_IOSTREAM* pout, + INCHI_IOSTREAM* pprb, + ORIG_ATOM_DATA* orig_inp_data, + ORIG_ATOM_DATA* prep_inp_data, + long* num_inp, + STRUCT_FPTRS* pStructPtrs, + int* nRet, + int have_err_in_GetOneStructure, + long* num_err, + int output_error_inchi, + INCHI_IOS_STRING* strbuf, + unsigned long* pulTotalProcessingTime, + char* pLF, + char* pTAB, + char* ikey, + int silent) +{ + int nRet1; + int next_act = DO_NEXT_STEP; + /* related to hash of InChI */ + char ik_string[256]; /*^^^ Resulting InChIKey string */ + int ik_ret = 0; /*^^^ InChIKey-calc result code */ + int xhash1, xhash2; + char szXtra1[65], szXtra2[65]; + /* related to printing structure header */ + int print_record_info = 0; + INCHI_IOSTREAM temp_out; + INCHI_IOSTREAM* pout0 = &temp_out; + inchi_ios_init(pout0, INCHI_IOS_TYPE_STRING, NULL); + + + /* Calculate InChI */ + + nRet1 = ProcessOneStructureEx(ic, + CG, + sd, + ip, + szTitle, + pINChI, + pINChI_Aux, + inp_file, + plog, + pout0, /* note this */ + pprb, + orig_inp_data, + prep_inp_data, + *num_inp, strbuf, + 0 /* save_opt_bits */); + + inchi_ios_flush2(plog, stderr); + + + /* Output InChI */ + + /* print header for structure if applicable (no error arose, or have a request for empty InChI at error) */ + print_record_info = ((nRet1 == _IS_OKAY) || + (nRet1 == _IS_WARNING) || + ((nRet1 == _IS_ERROR || nRet1 == _IS_FATAL) && output_error_inchi)); + if (print_record_info) + { + Output_RecordInfo(pout, *num_inp, ip->bNoStructLabels, + ip->pSdfLabel, ip->pSdfValue, ip->lSdfId, pLF, pTAB); + } + if (pout0->s.pStr) + { + /* post-process output to correctly treat 'tabbed with InChIKey' mode */ + if (ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT) + { + if (ip->bCalcInChIHash != INCHIHASH_NONE) + { + if (pout0->s.pStr) + { + if (pout0->s.nUsedLength > 0) + { + if (pout0->s.pStr[pout0->s.nUsedLength - 1] == '\n') + { + pout0->s.pStr[pout0->s.nUsedLength - 1] = '\t'; + } + } + } + } + } + /* print InChI string (may be string for empty InChI) */ + if (!ip->bHideInChI) + { + inchi_ios_print(pout, "%-s", pout0->s.pStr); + } + } + /*inchi_ios_close(pout0);*/ /* free temporary out */ + + + *pulTotalProcessingTime += sd->ulStructTime; + + if (nRet1 == _IS_SKIP) + { + next_act = DO_CONTINUE_MAIN_LOOP; + goto exit_function; + } + + *nRet = inchi_max(*nRet, nRet1); + switch (*nRet) + { + case _IS_FATAL: + if (!have_err_in_GetOneStructure) + { + /* increment error counter only if error did not appear earlier */ + (*num_err)++; + } + if (!(ip->bINChIOutputOptions & INCHI_OUT_NO_AUX_INFO) && + (ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT)) + { + inchi_ios_print(pout, "\t"); + } + if (ip->bCalcInChIHash != INCHIHASH_NONE) + { + if (ip->bINChIOutputOptions2 & INCHI_OUT_INCHI_GEN_ERROR) + { + if (ip->bINChIOutputOptions & INCHI_OUT_STDINCHI) + { + inchi_ios_print(pout, "InChIKey=%-s\n", "MOSFIJXAXDLOML-UHFFFAOYSA-N"); + } + else + { + inchi_ios_print(pout, "InChIKey=%-s\n", "MOSFIJXAXDLOML-UHFFFAOYNA-N"); + } + } + } + inchi_ios_flush(pout); + next_act = DO_EXIT_FUNCTION; + goto exit_function; + + case _IS_ERROR: + if (!have_err_in_GetOneStructure) + { + /* increment error counter only if error did not appear earlier */ + (*num_err)++; + } + if (!(ip->bINChIOutputOptions & INCHI_OUT_NO_AUX_INFO) && + (ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT)) + { + inchi_ios_print(pout, "\t"); + } + if (ip->bCalcInChIHash != INCHIHASH_NONE) + { + if (ip->bINChIOutputOptions2 & INCHI_OUT_INCHI_GEN_ERROR) + { + if (ip->bINChIOutputOptions & INCHI_OUT_STDINCHI) + { + inchi_ios_print(pout, "InChIKey=%-s\n", "MOSFIJXAXDLOML-UHFFFAOYSA-N"); + } + else + { + inchi_ios_print(pout, "InChIKey=%-s\n", "MOSFIJXAXDLOML-UHFFFAOYNA-N"); + } + } + } + inchi_ios_flush(pout); + next_act = DO_CONTINUE_MAIN_LOOP; + goto exit_function; + + case _IS_SKIP: + next_act = DO_CONTINUE_MAIN_LOOP; + goto exit_function; + } + + + /* Calculate hash[es] of InChI */ + + if (ip->bCalcInChIHash != INCHIHASH_NONE) + { + char* buf = NULL; + size_t slen = pout0->s.nUsedLength; + + extract_inchi_substring(&buf, pout0->s.pStr, slen); + + if (NULL == buf) + { + ik_ret = INCHIKEY_INVALID_INCHI; + } + else + { + xhash1 = xhash2 = 0; + if ((ip->bCalcInChIHash == INCHIHASH_KEY_XTRA1) || + (ip->bCalcInChIHash == INCHIHASH_KEY_XTRA1_XTRA2)) + { + xhash1 = 1; + } + if ((ip->bCalcInChIHash == INCHIHASH_KEY_XTRA2) || + (ip->bCalcInChIHash == INCHIHASH_KEY_XTRA1_XTRA2)) + { + xhash2 = 1; + } + ik_ret = GetINCHIKeyFromINCHI(buf, xhash1, xhash2, ik_string, szXtra1, szXtra2); + inchi_free(buf); + } + + + /* Print hash[es] */ + + if (ik_ret == INCHIKEY_OK) + { + /* NB: correctly treat tabbed output with InChIKey & hash extensions */ + char csep = '\n'; + + if (ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT) + { + csep = '\t'; + } + if (!ip->bMergeHash) + { + inchi_ios_print(pout, "InChIKey=%-s", ik_string); + } + else + { + inchi_ios_print(pout, "InChIHash=%-s", ik_string); + } + strcpy(ikey, ik_string); + + if (szXtra1[0] && ip->bMergeHash) + { + inchi_ios_print(pout, "-%-s", szXtra1); + } + else if (szXtra1[0] && !ip->bMergeHash) + { + inchi_ios_print(pout, "%cXHash1=%-s", csep, szXtra1); + } + else if (!szXtra1[0] && ip->bMergeHash) + { + inchi_ios_print(pout, "-"); + } + + if (szXtra2[0] && ip->bMergeHash) + { + inchi_ios_print(pout, "-%-s", szXtra2); + } + else if (szXtra2[0] && !ip->bMergeHash) + { + inchi_ios_print(pout, "%cXHash2=%-s", csep, szXtra2); + } + else if (!szXtra2[0] && ip->bMergeHash) + { + inchi_ios_print(pout, "-"); + } + + inchi_ios_print(pout, "\n"); + } + else + { + inchi_ios_print(plog, "Warning (Could not compute InChIKey: ", num_inp); + switch (ik_ret) + { + case INCHIKEY_UNKNOWN_ERROR: + inchi_ios_print(plog, "unresolved error)"); + break; + case INCHIKEY_EMPTY_INPUT: + inchi_ios_print(plog, "got an empty string)"); + break; + case INCHIKEY_INVALID_INCHI_PREFIX: + case INCHIKEY_INVALID_INCHI: + case INCHIKEY_INVALID_STD_INCHI: + inchi_ios_print(plog, "no valid InChI string found)"); + break; + case INCHIKEY_NOT_ENOUGH_MEMORY: + inchi_ios_print(plog, "not enough memory to treat the string)"); + break; + default: inchi_ios_print(plog, "internal program error)"); + break; + } + inchi_ios_print(plog, " structure #%-lu.\n", *num_inp); + if (ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT) + { + inchi_ios_print(pout, "\n"); + } + } + + if (!silent) + { + inchi_ios_flush(pout); + inchi_ios_flush2(plog, stderr); + } + else + { + inchi_ios_free_str(pout); + inchi_ios_free_str(plog); + } + } + else + { + inchi_ios_flush(pout); + } + +exit_function: + inchi_ios_close(pout0); /* free temporary out */ + + return next_act; +} + + +#ifdef RENUMBER_ATOMS_AND_RECALC_V106 + +/*****************************************************************************/ + +int numbers_rrar[PERMAXATOMS]; /* djb-rwth: placed as a global variable to avoid function buffer issues */ +int RepeatedlyRenumberAtomsAndRecalcINCHI(struct tagINCHI_CLOCK* ic, + CANON_GLOBALS* CG, + STRUCT_DATA* sd, + INPUT_PARMS* ip, + char* szTitle, + PINChI2* pINChI[INCHI_NUM], + PINChI_Aux2* pINChI_Aux[INCHI_NUM], + INCHI_IOSTREAM* inp_file, + INCHI_IOSTREAM* plog, + INCHI_IOSTREAM* pout, + INCHI_IOSTREAM* pprb, + ORIG_ATOM_DATA* orig_inp_data, + ORIG_ATOM_DATA* prep_inp_data, + long* num_inp, + STRUCT_FPTRS* pStructPtrs, + int* nRet, + int have_err_in_GetOneStructure, + long* num_err, + int output_error_inchi, + INCHI_IOS_STRING* strbuf, + unsigned long* pulTotalProcessingTime, + char* pLF, + char* pTAB, + long int nrepeat) +{ + int next_action = DO_NEXT_STEP; + int dup_fail = 0; + ORIG_ATOM_DATA SavedOrigAtData; /* 0=> disconnected, 1=> original */ + ORIG_ATOM_DATA* saved_orig_inp_data = &SavedOrigAtData; + char ikey0[28]; + + const int very_silent = 2; /* 3 0;*/ + + /* Internal test mode: renumber atoms and recalculate repeatedly */ + + /* do not forget to use /key and to not use /auxnone */ + + + ikey0[0] = '\0'; + { + int k; + for (k = 0; k < orig_inp_data->num_inp_atoms; k++) + { + numbers_rrar[k] = k; + } + for (k = orig_inp_data->num_inp_atoms; k < PERMAXATOMS; k++) + { + numbers_rrar[k] = -1; + } + } + + + + +#if BIG_POLY_DEBUG + { int k; ITRACE_("\nAtoms = {"); for (k = 0; k < orig_inp_data->num_inp_atoms - 1; k++) ITRACE_(" %-03d,", numbers_rrar[k]); ITRACE_(" %-03d }", numbers_rrar[orig_inp_data->num_inp_atoms - 1]); } + OrigAtData_DebugTrace(orig_inp_data); + OrigAtDataPolymer_DebugTrace(orig_inp_data->polymer); +#endif + + memset(saved_orig_inp_data, 0, sizeof(*saved_orig_inp_data)); /* djb-rwth: memset_s C11/Annex K variant? */ + dup_fail = OrigAtData_Duplicate(saved_orig_inp_data, orig_inp_data); + + next_action = CalcAndPrintINCHIAndINCHIKEY(ic, CG, sd, ip, szTitle, + pINChI, pINChI_Aux, + inp_file, plog, pout, pprb, + orig_inp_data, prep_inp_data, num_inp, pStructPtrs, + nRet, have_err_in_GetOneStructure, + num_err, output_error_inchi, + strbuf, pulTotalProcessingTime, + pLF, pTAB, ikey0, very_silent); + FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); + FreeOrigAtData(orig_inp_data); + FreeOrigAtData(prep_inp_data); + FreeOrigAtData(prep_inp_data + 1); + + + if (ikey0[0]) + { + if (very_silent < 2) + { + inchi_ios_eprint(plog, "#%-ld-%08ld\t...\t%-s\t%s%s%s%s\n", *num_inp, 1, ikey0, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue)); + } + } + + + if (!dup_fail) + { + int irepeat = 0; + int ndiff = 0; + int n_written_problems = 0; + char ikey[28]; + ikey[0] = '\0'; + for (irepeat = 0; irepeat < nrepeat - 1; irepeat++) + { + dup_fail = OrigAtData_Duplicate(orig_inp_data, saved_orig_inp_data); + if (!dup_fail) + { + shuffle((void*)numbers_rrar, orig_inp_data->num_inp_atoms, sizeof(int)); + OrigAtData_Permute(orig_inp_data, saved_orig_inp_data, numbers_rrar); +#if BIG_POLY_DEBUG + { int k; ITRACE_("\nAtoms = {"); for (k = 0; k < orig_inp_data->num_inp_atoms - 1; k++) ITRACE_(" %-03d,", numbers_rrar[k]); ITRACE_(" %-03d }", numbers_rrar[orig_inp_data->num_inp_atoms - 1]); } + OrigAtData_DebugTrace(saved_orig_inp_data); + OrigAtData_DebugTrace(orig_inp_data); + OrigAtDataPolymer_DebugTrace(saved_orig_inp_data->polymer); + OrigAtDataPolymer_DebugTrace(orig_inp_data->polymer); +#endif + next_action = CalcAndPrintINCHIAndINCHIKEY(ic, CG, sd, ip, szTitle, + pINChI, pINChI_Aux, + inp_file, plog, pout, pprb, + orig_inp_data, + prep_inp_data, num_inp, pStructPtrs, + nRet, have_err_in_GetOneStructure, + num_err, output_error_inchi, + strbuf, pulTotalProcessingTime, + pLF, pTAB, ikey, + 0 /* 1 be silent */); + + + if (ikey0[0] && ikey[0]) + { + if (strcmp(ikey, ikey0)) + { + int result, bINChIOutputOptions = ip->bINChIOutputOptions; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ + ndiff++; + /*inchi_ios_eprint( plog, "!!! #%-ld-%05ld %s%s%s%s\tcurr %-s != %-s orig\n", *num_inp, irepeat + 2, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ), ikey, ikey0 );*/ + /*inchi_ios_eprint( plog, "!!! %s%s%s%s renum#%05ld\t%-s != %-s\n", SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ), irepeat + 2, ikey, ikey0 );*/ + inchi_ios_eprint(plog, "!!! #%-ld %s%s%s%s\t%-s --> %-s @ renum#%06d/%06ld\n", *num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue), ikey0, ikey, irepeat + 2, nrepeat); + if (!very_silent) + { + int k; + inchi_ios_eprint(plog, "Atoms = {"); + for (k = 0; k < orig_inp_data->num_inp_atoms - 1; k++) + { + inchi_ios_eprint(plog, " %-d,", numbers_rrar[k] + 1); + } + inchi_ios_eprint(plog, " %-d }\n\n", numbers_rrar[orig_inp_data->num_inp_atoms - 1] + 1); + } + ip->bINChIOutputOptions |= INCHI_OUT_SDFILE_ONLY; + result = OrigAtData_SaveMolfile(orig_inp_data, sd, ip, *num_inp, pprb); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ + inchi_ios_flush(pprb); + ip->bINChIOutputOptions = bINChIOutputOptions; + if (result == 0) + { + n_written_problems++; + } +#if 0 + /* second pass, non-silent one */ + FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); + FreeOrigAtData(orig_inp_data); + FreeOrigAtData(prep_inp_data); + FreeOrigAtData(prep_inp_data + 1); + dup_fail = OrigAtData_Duplicate(orig_inp_data, saved_orig_inp_data); + if (!dup_fail) + { + OrigAtData_Permute(orig_inp_data, saved_orig_inp_data, numbers_rrar); + next_action = CalcAndPrintINCHIAndINCHIKEY(ic, CG, sd, ip, szTitle, + pINChI, pINChI_Aux, + inp_file, plog, pout, pprb, + orig_inp_data, + prep_inp_data, num_inp, pStructPtrs, + nRet, have_err_in_GetOneStructure, + num_err, output_error_inchi, + strbuf, pulTotalProcessingTime, + pLF, pTAB, ikey, 0); + } +#endif + } + + if (irepeat == nrepeat - 2) + { + if (very_silent < 2) + { + inchi_ios_eprint(plog, "...........\n#%-ld-%08ld\t...\t%-s\t%s%s%s%s\n", *num_inp, irepeat + 2, ikey0, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue)); + } + } + + } + } + FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); + FreeOrigAtData(orig_inp_data); + FreeOrigAtData(prep_inp_data); + FreeOrigAtData(prep_inp_data + 1); + +#ifdef STOP_AFTER_FIRST_CHANGE_ON_RENUMBERING + if (ndiff == 1) + { + next_action = DO_CONTINUE_MAIN_LOOP; + break; + } +#endif + } + if (ndiff == 0) + { + if (very_silent < 3) + { + /*inchi_ios_eprint( plog, "#%-ld-%05ld\t...\tOK ALL\n", *num_inp, nrepeat );*/ + /*inchi_ios_eprint( plog, "OK #%-ld %s%s%s%s\n", *num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue));*/ + /*inchi_ios_eprint(plog, "#%-ld\n", *num_inp);*/ + inchi_ios_eprint(plog, "OK #%-ld %s%s%s%s\t%-s\t Same for %-d/%-d renums\n", *num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue), ikey0, nrepeat, nrepeat); + } + } + else + { +#ifdef STOP_AFTER_FIRST_CHANGE_ON_RENUMBERING + /*inchi_ios_eprint( plog, "#%-ld-%05ld\t...\tDIFF %-d\n", num_inp, nrepeat, ndiff );*/ +#else + inchi_ios_eprint(plog, "#%-ld-%05ld\t...\tDIFF %-d\n", num_inp, nrepeat, ndiff); +#endif + } + + FreeOrigAtData(saved_orig_inp_data); + } + + return next_action; +} + + +#endif diff --git a/INCHI-1-SRC/INCHI_EXE/inchi-1/src/CMakeLists.txt b/INCHI-1-SRC/INCHI_EXE/inchi-1/src/CMakeLists.txt index ead78dec..8b83d19d 100644 --- a/INCHI-1-SRC/INCHI_EXE/inchi-1/src/CMakeLists.txt +++ b/INCHI-1-SRC/INCHI_EXE/inchi-1/src/CMakeLists.txt @@ -25,9 +25,10 @@ include_directories(${P_BASE} ${P_CURRENT}) add_executable(inchi-1) target_sources(inchi-1 PRIVATE - dispstru.c - dispstru.h - ichimain.c + main.c + ${P_BASE}/ichimain.c + ${P_BASE}/dispstru.c + ${P_BASE}/dispstru.h ${P_BASE}/bcf_s.h ${P_BASE}/bcf_s.c ${P_BASE}/extr_ct.h @@ -132,8 +133,8 @@ if(MATH_LIBRARY) target_link_libraries(inchi-1 PUBLIC ${MATH_LIBRARY}) endif() -target_compile_definitions(inchi-1 PRIVATE - COMPILE_ANSI_ONLY +target_compile_definitions(inchi-1 PRIVATE + COMPILE_ANSI_ONLY TARGET_EXE_STANDALONE ADD_AMI_MODE ) @@ -141,4 +142,4 @@ target_compile_definitions(inchi-1 PRIVATE target_include_directories(inchi-1 PUBLIC "${PROJECT_BINARY_DIR}") string(REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") -string(REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") \ No newline at end of file +string(REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") diff --git a/INCHI-1-SRC/INCHI_EXE/inchi-1/src/ichimain.c b/INCHI-1-SRC/INCHI_EXE/inchi-1/src/backup_ichimain.c similarity index 100% rename from INCHI-1-SRC/INCHI_EXE/inchi-1/src/ichimain.c rename to INCHI-1-SRC/INCHI_EXE/inchi-1/src/backup_ichimain.c diff --git a/INCHI-1-SRC/INCHI_EXE/inchi-1/src/main.c b/INCHI-1-SRC/INCHI_EXE/inchi-1/src/main.c new file mode 100644 index 00000000..5e1f3f46 --- /dev/null +++ b/INCHI-1-SRC/INCHI_EXE/inchi-1/src/main.c @@ -0,0 +1,266 @@ +/* + * International Chemical Identifier (InChI) + * Version 1 + * Software version 1.07 + * April 30, 2024 + * + * MIT License + * + * Copyright (c) 2024 IUPAC and InChI Trust + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. +* +* The InChI library and programs are free software developed under the + * auspices of the International Union of Pure and Applied Chemistry (IUPAC). + * Originally developed at NIST. + * Modifications and additions by IUPAC and the InChI Trust. + * Some portions of code were developed/changed by external contributors + * (either contractor or volunteer) which are listed in the file + * 'External-contributors' included in this distribution. + * + * info@inchi-trust.org + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef COMPILE_ANSI_ONLY +#include +#ifndef TARGET_LIB_FOR_WINCHI +#include +#endif +#endif + +#include "../../../INCHI_BASE/src/mode.h" + +#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) +#include +#include +#endif + + +#ifdef _WIN32 +#include +#endif +#include "../../../INCHI_BASE/src/ichitime.h" +#include "../../../INCHI_BASE/src/incomdef.h" +#include "../../../INCHI_BASE/src/ichidrp.h" +#include "../../../INCHI_BASE/src/inpdef.h" +#include "../../../INCHI_BASE/src/ichi.h" +#include "../../../INCHI_BASE/src/strutil.h" +#include "../../../INCHI_BASE/src/util.h" +#include "../../../INCHI_BASE/src/ichierr.h" +#include "../../../INCHI_BASE/src/ichimain.h" +#include "../../../INCHI_BASE/src/ichicomp.h" +#include "../../../INCHI_BASE/src/ichi_io.h" +#ifdef TARGET_EXE_STANDALONE +#include "../../../INCHI_BASE/src/inchi_api.h" +#endif + +#include "../../../INCHI_BASE/src/bcf_s.h" +#include "../../../INCHI_BASE/src/permutation_util.h" + + /* Console-specific */ + +#if !defined(TARGET_API_LIB) && !defined(COMPILE_ANSI_ONLY) + +/* Use Windows additional features */ + + +/****************************************************************************/ +int user_quit(struct tagINCHI_CLOCK* ic, + const char* msg, + unsigned long ulMaxTime) +{ +#if defined(TARGET_LIB_FOR_WINCHI) + return 0; +#endif + +#if ( !defined(TARGET_LIB_FOR_WINCHI) && defined(_WIN32) ) + + int quit, enter, ret; + printf("%s", msg); /* djb-rwth: format string added for security */ + if (ulMaxTime) + { + inchiTime ulEndTime; + InchiTimeGet(&ulEndTime); + InchiTimeAddMsec(ic, &ulEndTime, ulMaxTime); + while (!_kbhit()) + { + if (bInchiTimeIsOver(ic, &ulEndTime)) + { + printf("\n"); + return 0; + } + MySleep(100); + } + } + while (1) + { + quit = ('q' == (ret = _getch()) || 'Q' == ret || /*Esc*/ 27 == ret); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ + enter = ('\r' == ret); + if (ret == 0xE0) + { + ret = _getch(); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ + } + else + { + _putch(ret); /* echo */ + } + if (quit || enter) + { + break; + } + printf("\r"); + printf("%s", msg); /* djb-rwth: format string added for security */ + } + _putch('\n'); + + return quit; +#else + return 0; + +#endif /* #if ( defined(_WIN32) && !defined(TARGET_LIB_FOR_WINCHI) ) */ +} + + +/****************************************************************************/ +void eat_keyboard_input(void) +{ + int ret_val; /* djb-rwth: adding return value */ /* djb-rwth: ignoring LLVM warning */ +#ifndef TARGET_LIB_FOR_WINCHI + + while (_kbhit()) + { + if (0xE0 == _getch()) + { + ret_val = _getch(); /* djb-rwth: return value variable added */ + } + } + +#endif +} + +#endif /* end of !COMPILE_ANSI_ONLY */ + + +// #ifndef TARGET_LIB_FOR_WINCHI +/* COVERS THE CODE FROM HERE TO THE END OF FILE */ + + +/* Enable/disable internal tests */ + +/* Uncomment for INCHI_LIB testing only */ +/*#define TEST_FPTRS*/ + +/* Windows-console-mode specific */ + +int bInterrupted = 0; + +#if ( defined( _WIN32 ) && defined( _CONSOLE ) ) +#ifndef COMPILE_ANSI_ONLY + + +/****************************************************************************/ +BOOL WINAPI MyHandlerRoutine(DWORD dwCtrlType /* control signal type */) +{ + if (dwCtrlType == CTRL_C_EVENT || + dwCtrlType == CTRL_BREAK_EVENT || + dwCtrlType == CTRL_CLOSE_EVENT || + dwCtrlType == CTRL_LOGOFF_EVENT) + { + bInterrupted = 1; + return TRUE; + } + return FALSE; +} + + +/****************************************************************************/ +int WasInterrupted(void) +{ +#ifdef _DEBUG + if (bInterrupted) + { + int stop = 1; /* for debug only */ + } +#endif + return bInterrupted; +} +#if ( BUILD_WITH_AMI == 1 ) +#define CTRL_STOP_EVENT 101 +#endif +#endif /* ifndef COMPILE_ANSI_ONLY */ +#endif /* if( defined( _WIN32 ) && defined( _CONSOLE ) ) */ + + + +/****************************************************************************/ +int main(int argc, char* argv[]) +{ +#ifdef GHI100_FIX +#if ((SPRINTF_FLAG != 1) && (SPRINTF_FLAG != 2)) + setlocale(LC_ALL, "en-US"); /* djb-rwth: setting all locales to "en-US" */ +#endif +#endif + +/*************************/ +// #if ( BUILD_WITH_AMI == 1 ) +/*************************/ + +/**** IF IN AMI MODE, main() STARTS HERE ****/ + int i, ret = 0, ami = 0; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ + + /* Check if multiple inputs expected */ + for (i = 1; i < argc; i++) + { + if (argv[i][0] == INCHI_OPTION_PREFX) + { + if (!inchi_stricmp(argv[i] + 1, "AMI")) + { + ami = 1; + break; + } + } + } + + if (ami) + { + ret = ProcessMultipleInputFiles(argc, argv); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ + } + else + { + ret = ProcessSingleInputFile(argc, argv); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ + } + + return 0; +} + + +// #endif /* ifndef TARGET_LIB_FOR_WINCHI */ + From b76a4cb5cb33ab406a66d7a5cb334e9e217f262a Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 8 Dec 2025 08:43:05 +0000 Subject: [PATCH 02/69] formatting --- INCHI-1-SRC/INCHI_BASE/src/ichimain.c | 3 +- .../INCHI_EXE/inchi-1/src/backup_ichimain.c | 1688 ----------------- 2 files changed, 2 insertions(+), 1689 deletions(-) delete mode 100644 INCHI-1-SRC/INCHI_EXE/inchi-1/src/backup_ichimain.c diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichimain.c b/INCHI-1-SRC/INCHI_BASE/src/ichimain.c index a575437b..ccdc9aeb 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichimain.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichimain.c @@ -363,7 +363,8 @@ int ProcessMultipleInputFiles(int argc, char* argv[]) /****************************************************************************/ int ProcessSingleInputFile(int argc, char* argv[]) { - /**************************************/ + +/**************************************/ #endif /* #if ( BUILD_WITH_AMI == 1 ) */ /**************************************/ diff --git a/INCHI-1-SRC/INCHI_EXE/inchi-1/src/backup_ichimain.c b/INCHI-1-SRC/INCHI_EXE/inchi-1/src/backup_ichimain.c deleted file mode 100644 index cc422b04..00000000 --- a/INCHI-1-SRC/INCHI_EXE/inchi-1/src/backup_ichimain.c +++ /dev/null @@ -1,1688 +0,0 @@ -/* - * International Chemical Identifier (InChI) - * Version 1 - * Software version 1.07 - * April 30, 2024 - * - * MIT License - * - * Copyright (c) 2024 IUPAC and InChI Trust - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. -* -* The InChI library and programs are free software developed under the - * auspices of the International Union of Pure and Applied Chemistry (IUPAC). - * Originally developed at NIST. - * Modifications and additions by IUPAC and the InChI Trust. - * Some portions of code were developed/changed by external contributors - * (either contractor or volunteer) which are listed in the file - * 'External-contributors' included in this distribution. - * - * info@inchi-trust.org - * -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef COMPILE_ANSI_ONLY -#include -#ifndef TARGET_LIB_FOR_WINCHI -#include -#endif -#endif - -#include "../../../INCHI_BASE/src/mode.h" - -#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) -#include -#include -#endif - - -#ifdef _WIN32 -#include -#endif -#include "../../../INCHI_BASE/src/ichitime.h" -#include "../../../INCHI_BASE/src/incomdef.h" -#include "../../../INCHI_BASE/src/ichidrp.h" -#include "../../../INCHI_BASE/src/inpdef.h" -#include "../../../INCHI_BASE/src/ichi.h" -#include "../../../INCHI_BASE/src/strutil.h" -#include "../../../INCHI_BASE/src/util.h" -#include "../../../INCHI_BASE/src/ichierr.h" -#include "../../../INCHI_BASE/src/ichimain.h" -#include "../../../INCHI_BASE/src/ichicomp.h" -#include "../../../INCHI_BASE/src/ichi_io.h" -#ifdef TARGET_EXE_STANDALONE -#include "../../../INCHI_BASE/src/inchi_api.h" -#endif - -#include "../../../INCHI_BASE/src/bcf_s.h" -#include "../../../INCHI_BASE/src/permutation_util.h" - - /* Console-specific */ - -#if !defined(TARGET_API_LIB) && !defined(COMPILE_ANSI_ONLY) - -/* Use Windows additional features */ - - -/****************************************************************************/ -int user_quit(struct tagINCHI_CLOCK* ic, - const char* msg, - unsigned long ulMaxTime) -{ -#if defined(TARGET_LIB_FOR_WINCHI) - return 0; -#endif - -#if ( !defined(TARGET_LIB_FOR_WINCHI) && defined(_WIN32) ) - - int quit, enter, ret; - printf("%s", msg); /* djb-rwth: format string added for security */ - if (ulMaxTime) - { - inchiTime ulEndTime; - InchiTimeGet(&ulEndTime); - InchiTimeAddMsec(ic, &ulEndTime, ulMaxTime); - while (!_kbhit()) - { - if (bInchiTimeIsOver(ic, &ulEndTime)) - { - printf("\n"); - return 0; - } - MySleep(100); - } - } - while (1) - { - quit = ('q' == (ret = _getch()) || 'Q' == ret || /*Esc*/ 27 == ret); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ - enter = ('\r' == ret); - if (ret == 0xE0) - { - ret = _getch(); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ - } - else - { - _putch(ret); /* echo */ - } - if (quit || enter) - { - break; - } - printf("\r"); - printf("%s", msg); /* djb-rwth: format string added for security */ - } - _putch('\n'); - - return quit; -#else - return 0; - -#endif /* #if ( defined(_WIN32) && !defined(TARGET_LIB_FOR_WINCHI) ) */ -} - - -/****************************************************************************/ -void eat_keyboard_input(void) -{ - int ret_val; /* djb-rwth: adding return value */ /* djb-rwth: ignoring LLVM warning */ -#ifndef TARGET_LIB_FOR_WINCHI - - while (_kbhit()) - { - if (0xE0 == _getch()) - { - ret_val = _getch(); /* djb-rwth: return value variable added */ - } - } - -#endif -} - -#endif /* end of !COMPILE_ANSI_ONLY */ - - -#ifndef TARGET_LIB_FOR_WINCHI -/* COVERS THE CODE FROM HERE TO THE END OF FILE */ - - -/* Enable/disable internal tests */ - -/* Uncomment for INCHI_LIB testing only */ -/*#define TEST_FPTRS*/ - -/* Windows-console-mode specific */ - -int bInterrupted = 0; - -#if ( defined( _WIN32 ) && defined( _CONSOLE ) ) -#ifndef COMPILE_ANSI_ONLY - - -/****************************************************************************/ -BOOL WINAPI MyHandlerRoutine(DWORD dwCtrlType /* control signal type */) -{ - if (dwCtrlType == CTRL_C_EVENT || - dwCtrlType == CTRL_BREAK_EVENT || - dwCtrlType == CTRL_CLOSE_EVENT || - dwCtrlType == CTRL_LOGOFF_EVENT) - { - bInterrupted = 1; - return TRUE; - } - return FALSE; -} - - -/****************************************************************************/ -int WasInterrupted(void) -{ -#ifdef _DEBUG - if (bInterrupted) - { - int stop = 1; /* for debug only */ - } -#endif - return bInterrupted; -} -#if ( BUILD_WITH_AMI == 1 ) -#define CTRL_STOP_EVENT 101 -#endif -#endif /* ifndef COMPILE_ANSI_ONLY */ -#endif /* if( defined( _WIN32 ) && defined( _CONSOLE ) ) */ - - - -/****************************************************************************/ -int main(int argc, char* argv[]) -{ -#ifdef GHI100_FIX -#if ((SPRINTF_FLAG != 1) && (SPRINTF_FLAG != 2)) - setlocale(LC_ALL, "en-US"); /* djb-rwth: setting all locales to "en-US" */ -#endif -#endif - - /*************************/ -#if ( BUILD_WITH_AMI == 1 ) -/*************************/ - -/**** IF IN AMI MODE, main() STARTS HERE ****/ - int i, ret = 0, ami = 0; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ - - /* Check if multiple inputs expected */ - for (i = 1; i < argc; i++) - { - if (argv[i][0] == INCHI_OPTION_PREFX) - { - if (!inchi_stricmp(argv[i] + 1, "AMI")) - { - ami = 1; - break; - } - } - } - - if (ami) - { - ret = ProcessMultipleInputFiles(argc, argv); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ - } - else - { - ret = ProcessSingleInputFile(argc, argv); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ - } - - return 0; -} - - -/****************************************************************************/ -int ProcessMultipleInputFiles(int argc, char* argv[]) -{ - int i, ret = 0, nfn_ins = 0, - AMIOutStd = 0, AMILogStd = 0, AMIPrbNone = 0; - char* fn_out, * fn_log, * fn_prb; - char pNUL[] = "NUL"; - char** fn_ins = NULL, ** targv = NULL; - int ret_val; /* djb-rwth: adding return value */ /* djb-rwth: ignoring LLVM warning */ - -#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) -#ifdef _WIN64 - typedef __int64 intptr_t; /* x64 */ -#else - typedef long int intptr_t; /* VC 6.0 has no intptr_t and no x64 */ -#endif - struct _finddata_t file_info; - intptr_t hFile = -1; - int retFile, lenPath; - char* pName, * pOutPath = NULL; /* djb-rwth: ignoring LLVM warning */ - char pathname[_MAX_PATH]; - char szBlank[] = ""; /* djb-rwth: ignoring LLVM warning */ - int numFiles = 0; /* counts processed files */ -#else - int p; -#endif - - fn_ins = (char**)inchi_calloc(argc, sizeof(char*)); - if (!fn_ins) - { - fprintf(stderr, "Not enough memory.\n"); - goto exit_ami; - } - - /* Check for other options and collect inputs. */ - for (i = 1; i < argc; i++) - { - if (argv[i][0] == INCHI_OPTION_PREFX) - { - if (!inchi_stricmp(argv[i] + 1, "STDIO")) - { - fprintf(stderr, "Options AMI and STDIO are not compatible.\n"); - goto exit_ami; - } - else if (!inchi_stricmp(argv[i] + 1, "AMIOutStd")) - { - AMIOutStd = 1; - } - else if (!inchi_stricmp(argv[i] + 1, "AMILogStd")) - { - AMILogStd = 1; - } - else if (!inchi_stricmp(argv[i] + 1, "AMIPrbNone")) - { - AMIPrbNone = 1; - } -#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) - else if (!inchi_memicmp(argv[i] + 1, "OP:", 3)) - { - pOutPath = argv[i] + 4; /* output path */ - } -#endif - } - else - { - fn_ins[nfn_ins] = argv[i]; - nfn_ins++; - } - } - - if (!nfn_ins) - { - fprintf(stderr, "At least one input file is expected in AMI mode.\n"); - goto exit_ami; - } - - targv = (char**)inchi_calloc((long long)argc + 3, sizeof(char*)); /* djb-rwth: cast operator added */ - - if (!targv) - { - fprintf(stderr, "Not enough memory.\n"); - goto exit_ami; - } - -#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) - if ((pName = strrchr(fn_ins[0], INCHI_PATH_DELIM))) /* djb-rwth: addressing LLVM warning */ - { - pName++; - lenPath = pName - fn_ins[0]; - } - else - { - pName = fn_ins[0]; - lenPath = 0; - } - for (hFile = _findfirst(fn_ins[0], &file_info), retFile = 0; - !retFile && -1 != hFile; - retFile = _findnext(hFile, &file_info), numFiles++) -#else - for (p = 0; p < nfn_ins; p++) -#endif - { - int targc; -#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) - const char* fn_in; - int inlen = lenPath + strlen(file_info.name); - if (!file_info.size || (file_info.attrib & _A_SUBDIR) || inlen >= _MAX_PATH) - { - continue; - } - memcpy(pathname, fn_ins[0], lenPath); - strcpy(pathname + lenPath, file_info.name); - fn_in = pathname; - if (0 == numFiles % 5000) - { - ret_val = _heapmin(); /* reduce heap fragmentation */ /* djb-rwth: return value variable added */ - } -#else - const char* fn_in = fn_ins[p]; - int inlen = strlen(fn_in); -#endif - fn_out = fn_log = fn_prb = NULL; - - targv[0] = argv[0]; - targv[1] = (char*)fn_in; - targc = 1; - - if (AMIOutStd) - { - targv[++targc] = pNUL; - } -#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 && ALLOW_EMPTY_PATHS == 1 ) - else if (pOutPath) - { - targv[++targc] = szBlank; /* output name will be created in process_single_input(...) */ - } -#endif - else - { - /* make output name as input name plus ext. */ - fn_out = (char*)inchi_calloc((long long)inlen + 6, sizeof(char)); /* djb-rwth: cast operator added */ - if (fn_out) - { - strcpy(fn_out, fn_in); - strcat(fn_out, ".txt"); - } - targv[++targc] = fn_out; - } - - if (AMILogStd) - { - targv[++targc] = pNUL; - } -#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 && ALLOW_EMPTY_PATHS == 1 ) - else if (pOutPath) - { - targv[++targc] = szBlank; /* output name will be created in process_single_input(...) */ - } -#endif - else - { - /* Make log name as input name plus ext. */ - fn_log = (char*)inchi_calloc((long long)inlen + 6, sizeof(char)); /* djb-rwth: cast operator added */ - if (fn_log) - { - strcpy(fn_log, fn_in); - strcat(fn_log, ".log"); - } - targv[++targc] = fn_log; - } - if (AMIPrbNone) - { - targv[++targc] = pNUL; - } -#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 && ALLOW_EMPTY_PATHS == 1 ) - else if (pOutPath) - { - targv[++targc] = szBlank; /* output name will be created in process_single_input(...) */ - } -#endif - else - { - /* Make problem file name as input file name plus ext. */ - fn_prb = (char*)inchi_calloc((long long)inlen + 6, sizeof(char)); /* djb-rwth: cast operator added */ - if (fn_prb) - { - strcpy(fn_prb, fn_in); - strcat(fn_prb, ".prb"); - } - targv[++targc] = fn_prb; - } - - for (i = 1; i < argc; i++) - { - if (argv[i][0] == INCHI_OPTION_PREFX) - { - /* avoid strnicmp/strncasecmp */ - if ((strlen(argv[i]) > 3) && - (toupper(argv[i][1]) == 'A') && (toupper(argv[i][2]) == 'M') && (toupper(argv[i][3]) == 'I')) - { - continue; - } - targv[++targc] = argv[i]; - } - } - /* djb-rwth: fixing undefined index value / buffer overflow */ - ++targc; - if (targc < argc + 3) - { - targv[targc] = NULL; - } - - ret = ProcessSingleInputFile(targc, targv); /* ProcessSingleInputFile() is a former main() */ - - if (fn_out) - { - inchi_free(fn_out); - } - if (fn_log) - { - inchi_free(fn_log); - } - if (fn_prb) - { - inchi_free(fn_prb); - } - -#if ( defined( _WIN32 ) && defined( _CONSOLE ) && !defined( COMPILE_ANSI_ONLY ) ) - if (ret == CTRL_STOP_EVENT) - { - goto exit_ami; - } -#endif - } - - -exit_ami: -#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) - if (hFile != -1) - { - _findclose(hFile); - } -#endif - if (targv) - { - inchi_free(targv); - } - if (fn_ins) - { - inchi_free(fn_ins); - } - - return 0; -} - - - -/****************************************************************************/ -int ProcessSingleInputFile(int argc, char* argv[]) -{ - /**************************************/ -#endif /* #if ( BUILD_WITH_AMI == 1 ) */ -/**************************************/ - -/**** IF NOT IN AMI MODE, main() STARTS HERE ****/ - - int bReleaseVersion = bRELEASE_VERSION; - const int nStrLen = INCHI_SEGM_BUFLEN; - int nRet = 0; - int i; - long num_err, num_output, num_inp; - /* long rcPict[4] = {0,0,0,0}; */ - unsigned long ulDisplTime = 0; /* infinite, milliseconds */ - unsigned long ulTotalProcessingTime = 0; - - CANON_GLOBALS CG; - INCHI_CLOCK ic; - - char szTitle[MAX_SDF_HEADER + MAX_SDF_VALUE + 256]; - char szSdfDataValue[MAX_SDF_VALUE + 1]; - - INPUT_PARMS inp_parms; - INPUT_PARMS* ip = &inp_parms; - - STRUCT_DATA struct_data; - STRUCT_DATA* sd = &struct_data; - - ORIG_ATOM_DATA OrigAtData; /* 0=> disconnected, 1=> original */ - ORIG_ATOM_DATA* orig_inp_data = &OrigAtData; - ORIG_ATOM_DATA PrepAtData[2]; /* 0=> disconnected, 1=> original */ - ORIG_ATOM_DATA* prep_inp_data = PrepAtData; - - PINChI2* pINChI[INCHI_NUM]; - PINChI_Aux2* pINChI_Aux[INCHI_NUM]; - - char* pLF, * pTAB; - INCHI_IOS_STRING temp_string_container; - INCHI_IOS_STRING* strbuf = &temp_string_container; - INCHI_IOSTREAM outputstr, logstr, prbstr, instr; - INCHI_IOSTREAM* pout = &outputstr, * plog = &logstr, * pprb = &prbstr, * inp_file = &instr; - -#ifdef TARGET_EXE_STANDALONE - int inchi_ios_type = INCHI_IOS_TYPE_STRING; -#else - int inchi_ios_type = INCHI_IOS_TYPE_FILE; -#endif -#if ( READ_INCHI_STRING == 1 ) - const int may_get_inchi_string_input = 1; -#else - const int may_get_inchi_string_input = 0; -#endif - int bInChI2Structure = 0; - int output_error_inchi = 0; - - - /* internal tests --- */ -#ifndef TEST_FPTRS - STRUCT_FPTRS* pStructPtrs = NULL; -#else - STRUCT_FPTRS struct_fptrs, * pStructPtrs = &struct_fptrs; /* INCHI_LIB debug only */ -#endif - -#if ( defined(_WIN32) && defined(_MSC_VER) ) -#if WINVER >= 0x0501 /* XP or newer */ /* 0x0600 Vista or newer */ - DWORD tick_inchi_start, tick_inchi_stop; - tick_inchi_start = GetTickCount64(); /* djb-rwth: GetTickCount64() should be used */ -#endif -#endif - -#ifdef _WIN32 -#if ( TRACE_MEMORY_LEAKS == 1 ) - _CrtSetDbgFlag(_CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF); - /* for execution outside the VC++ debugger uncomment one of the following two */ - /*#define MY_REPORT_FILE _CRTDBG_FILE_STDERR */ - /*#define MY_REPORT_FILE _CRTDBG_FILE_STDOUT */ -#ifdef MY_REPORT_FILE - _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_WARN, MY_REPORT_FILE); - _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ERROR, MY_REPORT_FILE); - _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ASSERT, MY_REPORT_FILE); -#else - _CrtSetReportMode(_CRT_WARN | _CRT_ERROR, _CRTDBG_MODE_DEBUG); -#endif - /* turn on floating point exceptions */ - { - /* Get the default control word. */ - int cw = _controlfp(0, 0); - - /* Set the exception masks OFF, turn exceptions on. */ - /*cw &=~(EM_OVERFLOW|EM_UNDERFLOW|EM_INEXACT|EM_ZERODIVIDE|EM_DENORMAL);*/ - cw &= ~(EM_OVERFLOW | EM_UNDERFLOW | EM_ZERODIVIDE | EM_DENORMAL); - - /* Set the control word. */ - _controlfp(cw, MCW_EM); -} -#endif -#endif - - sd->bUserQuit = 0; - /* djb-rwth: fixing coverity CID #499552 */ - sd->num_components[0] = 0; - sd->num_components[1] = 0; -#if ( defined( _WIN32 ) && defined( _CONSOLE ) && !defined( COMPILE_ANSI_ONLY ) ) - if (SetConsoleCtrlHandler(MyHandlerRoutine, 1)) - { - ConsoleQuit = WasInterrupted; - } -#endif - - num_inp = 0; - num_err = 0; - num_output = 0; - - inchi_ios_init(inp_file, INCHI_IOS_TYPE_FILE, NULL); - inchi_ios_init(pout, inchi_ios_type, NULL); - inchi_ios_init(plog, inchi_ios_type, stdout); - inchi_ios_init(pprb, inchi_ios_type, NULL); - memset(strbuf, 0, sizeof(*strbuf)); /* djb-rwth: memset_s C11/Annex K variant?; dereferencing strbuf */ - - if (argc == 1 || (argc == 2 && (argv[1][0] == INCHI_OPTION_PREFX) && - ((!strcmp(argv[1] + 1, "?") || !inchi_stricmp(argv[1] + 1, "help"))))) /* djb-rwth: addressing LLVM warning */ - { - HelpCommandLineParms(plog); - inchi_ios_flush(plog); - return 0; - } - - /* djb-rwth: printing out InChI version */ - if (argc == 2 && ((argv[1][0] == INCHI_OPTION_PREFX)) && (!strcmp(argv[1] + 1, "v") || !strcmp(argv[1] + 1, "V"))) - { - printf("%s\n", APP_DESCRIPTION); - return 0; - } - - /* djb-rwth: disallowing endless execution if no file(s) is given as the first argument */ - if (argc >= 2 && ((argv[1][0] == INCHI_OPTION_PREFX)) && (strcmp(argv[1] + 1, "v") || strcmp(argv[1] + 1, "V") || strcmp(argv[1] + 1, "?") || inchi_stricmp(argv[1] + 1, "help"))) - { - HelpCommandLineParms(plog); - inchi_ios_flush(plog); - return 0; - } - - /* original input structure */ - memset(orig_inp_data, 0, sizeof(*orig_inp_data)); /* djb-rwth: memset_s C11/Annex K variant? */ - memset(prep_inp_data, 0, 2 * sizeof(*prep_inp_data)); /* djb-rwth: memset_s C11/Annex K variant? */ - memset(pINChI, 0, sizeof(pINChI)); /* djb-rwth: memset_s C11/Annex K variant? */ - memset(pINChI_Aux, 0, sizeof(pINChI_Aux)); /* djb-rwth: memset_s C11/Annex K variant? */ - memset(szSdfDataValue, 0, sizeof(szSdfDataValue)); /* djb-rwth: memset_s C11/Annex K variant? */ - - memset(&CG, 0, sizeof(CG)); /* djb-rwth: memset_s C11/Annex K variant? */ - memset(&ic, 0, sizeof(ic)); /* djb-rwth: memset_s C11/Annex K variant? */ - - plog->f = stderr; - - if (0 > ReadCommandLineParms(argc, (const char**)argv, ip, - szSdfDataValue, &ulDisplTime, - bReleaseVersion, plog)) - { - goto exit_function; - } - - if (!OpenFiles(&(inp_file->f), &(pout->f), &(plog->f), &(pprb->f), ip)) - { - goto exit_function; - } - - - if (ip->bNoStructLabels) - { - ip->pSdfLabel = NULL; - ip->pSdfValue = NULL; - } - else if (ip->nInputType == INPUT_INCHI_PLAIN || - ip->nInputType == INPUT_INCHI) - { - /* the input may contain both the header and the label of the structure */ - if (!ip->pSdfLabel) - { - ip->pSdfLabel = ip->szSdfDataHeader; - } - if (!ip->pSdfValue) - { - ip->pSdfValue = szSdfDataValue; - } - } - - set_line_separators(ip->bINChIOutputOptions, &pLF, &pTAB); - - save_command_line(argc, argv, plog); - - PrintInputParms(plog, ip); - - inchi_ios_flush2(plog, stderr); - - if (0 >= inchi_strbuf_init(strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT)) - { - inchi_ios_eprint(plog, "Cannot allocate internal string buffer. Terminating\n"); - inchi_ios_flush2(plog, stderr); - goto exit_function; - } - - - /* Process InChI string as input; output may be */ - /* a) InChI string or b) structure */ - /*#if ( READ_INCHI_STRING == 1 )*/ - if (may_get_inchi_string_input && ip->nInputType == INPUT_INCHI) - { - bInChI2Structure = 0 != (ip->bReadInChIOptions & READ_INCHI_TO_STRUCTURE); - memset(sd, 0, sizeof(*sd)); /* djb-rwth: memset_s C11/Annex K variant? */ - if (bInChI2Structure) - { - /* loop through file lines here */ - INCHI_IOSTREAM tmpinpustream; - INCHI_IOS_STRING* pTmpIn = &tmpinpustream.s; - int crlf2lf = 0, preserve_lf = 1, read_result = 0; - inchi_ios_init(&tmpinpustream, INCHI_IOS_TYPE_STRING, NULL); - while (1) - { - char* p, * pi; - - read_result = inchi_strbuf_getline(pTmpIn, inp_file->f, crlf2lf, preserve_lf); - - if (read_result == -1) -#if (FIX_ONE_LINE_INCHI_INPUT_CONVERSION_ISSUE==1) - { - if (!pTmpIn->pStr) - { - break; - } - if (strlen(pTmpIn->pStr) < 8) /* 7 = strlen("InChI=1") */ - { - break; - } - } -#else - break; /* EOF or read error */ -#endif - - p = pTmpIn->pStr; - if (!p) - { - continue; - } - pi = strstr(p, "InChI=1"); - if (pi != p) - { - continue; - } - - num_inp++; - ip->lMolfileNumber = num_inp; - - ReadWriteInChI(&ic, &CG, &tmpinpustream, pout, plog, ip, sd, NULL, 0, 0, NULL, NULL, NULL, 0, NULL); - - /*fprintf( stderr, "%ld", num_inp );*/ - inchi_strbuf_reset(pTmpIn); - inchi_ios_flush2(plog, stderr); - } - fprintf(stderr, "\r"); - inchi_strbuf_close(pTmpIn); - } - else - { - /* loop through file lines within ReadWriteInChI */ - ReadWriteInChI(&ic, &CG, inp_file, pout, plog, ip, sd, NULL, 0, 0, NULL, NULL, NULL, 0, NULL); - - num_inp = sd->fPtrStart; - num_err = sd->fPtrEnd; - } - - inchi_ios_flush2(plog, stderr); - ulTotalProcessingTime = sd->ulStructTime; - /*num_inp = sd->fPtrStart; - num_err = sd->fPtrEnd; - */ - goto exit_function; - } - - - ulTotalProcessingTime = 0; - if (pStructPtrs) - { - memset(pStructPtrs, 0, sizeof(pStructPtrs[0])); /* djb-rwth: memset_s C11/Annex K variant? */ - } - output_error_inchi = ip->bINChIOutputOptions2 & INCHI_OUT_INCHI_GEN_ERROR; - - - /*************************************************************/ - /* Main cycle : read input structures and create their INChI */ - /*************************************************************/ - - - while (!sd->bUserQuit && !bInterrupted) - { - int do_renumbering = 0; - int next_action; - int have_err_in_GetOneStructure = 0; - int dup_fail = 0; - ORIG_ATOM_DATA SavedOrigAtData; /* 0=> disconnected, 1=> original */ - ORIG_ATOM_DATA* saved_orig_inp_data = &SavedOrigAtData; - char ikey0[28]; - ikey0[0] = '\0'; - - - next_action = GetTheNextRecordOfInputFile(&ic, sd, ip, szTitle, - inp_file, plog, pout, pprb, - orig_inp_data, &num_inp, pStructPtrs, - &nRet, &have_err_in_GetOneStructure, - &num_err, output_error_inchi); - if (next_action == DO_EXIT_FUNCTION) - { - goto exit_function; - } - else if (next_action == DO_BREAK_MAIN_LOOP) - { - break; - } - else if (next_action == DO_CONTINUE_MAIN_LOOP) - { - if (nRet == _IS_ERROR) /* may also be _IS_SKIP ... */ - { - if (output_error_inchi) - { - Output_RecordInfo(pout, num_inp, ip->bNoStructLabels, ip->pSdfLabel, ip->pSdfValue, ip->lSdfId, - pLF, pTAB); - emit_empty_inchi(ip, num_inp, pLF, pTAB, pout); - } - } - continue; - } - - - /* Create INChI for each connected component of the structure; - optionally display them; - output INChI for the whole structure */ - -#if (RENUMBER_ATOMS_AND_RECALC_V106 == 1 ) - if (ip->bRenumber == 1) - { - do_renumbering = 1; - } -#endif - if (do_renumbering == 0) - { - /* Normal calculations */ - next_action = CalcAndPrintINCHIAndINCHIKEY(&ic, &CG, sd, ip, szTitle, - pINChI, pINChI_Aux, - inp_file, plog, pout, pprb, - orig_inp_data, prep_inp_data, &num_inp, pStructPtrs, - &nRet, have_err_in_GetOneStructure, - &num_err, output_error_inchi, - strbuf, &ulTotalProcessingTime, - pLF, pTAB, ikey0, - 0 /* not silent */); - - FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); - FreeOrigAtData(orig_inp_data); - FreeOrigAtData(prep_inp_data); - FreeOrigAtData(prep_inp_data + 1); - } - else - { - /* Internal test mode: renumber atoms and recalculate repeatedly */ - long int nrepeat = 1; - /* 2! = 2 3! = 6 4! = 24 5! = 120 6! = 520 7! = 5040 8! = 40320 */ - if (orig_inp_data->num_inp_atoms == 1) - { - nrepeat = 1; - } - else if (orig_inp_data->num_inp_atoms == 2) - { - nrepeat = 2; - } - else if (orig_inp_data->num_inp_atoms == 3) - { - nrepeat = 6; - } - else - { - nrepeat = 1000; /* 100000;*/ /*16;*/ - } - /* correct (decrease repeat number) for relatively large molecules */ - if (orig_inp_data->num_inp_atoms > 128) - { - nrepeat = 100; /* 100000;*/ /*16;*/ - } - if (orig_inp_data->num_inp_atoms > 256) - { - nrepeat = 50; /* 100000;*/ /*16;*/ - } - if (orig_inp_data->num_inp_atoms > 512) - { - nrepeat = 25; /* 100000;*/ /*16;*/ - } - if (orig_inp_data->num_inp_atoms > 1024) - { - nrepeat = 10; /* 100000;*/ /*16;*/ - } - - /*inchi_ios_eprint(plog, "Number of random atom renumberings up to: %-ld\n", nrepeat); - inchi_ios_flush2(plog, stderr);*/ - -#if 0 - else if (orig_inp_data->num_inp_atoms == 4) - { - nrepeat = 24; - } - else - { - nrepeat = 10; - } - - else if (orig_inp_data->num_inp_atoms == 4) - { - nrepeat = 24; - } - else if (orig_inp_data->num_inp_atoms == 5) - { - nrepeat = 120; - } - else if (orig_inp_data->num_inp_atoms == 6) - { - nrepeat = 520; - } - else if (orig_inp_data->num_inp_atoms == 7) - { - nrepeat = 1000; - } - else - { - nrepeat = 10000; - } -#endif - - next_action = RepeatedlyRenumberAtomsAndRecalcINCHI(&ic, &CG, sd, ip, szTitle, - pINChI, pINChI_Aux, - inp_file, plog, pout, pprb, - orig_inp_data, prep_inp_data, &num_inp, pStructPtrs, - &nRet, have_err_in_GetOneStructure, - &num_err, output_error_inchi, - strbuf, &ulTotalProcessingTime, - pLF, pTAB, nrepeat); - } /* if (ip->bRenumber == 1) */ - - if (next_action == DO_EXIT_FUNCTION) - { - goto exit_function; - } - else if (next_action == DO_BREAK_MAIN_LOOP) - { - break; - } - else if (next_action == DO_CONTINUE_MAIN_LOOP) - { - continue; - } - } /* end of main cycle - while ( !sd->bUserQuit && !bInterrupted ) */ - - -exit_function: - /* Avoid memory leaks in case of fatal error */ - if (pStructPtrs && pStructPtrs->fptr) - { - inchi_free(pStructPtrs->fptr); - } - /* Free INChI memory */ - FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); - /* Free structure data */ - FreeOrigAtData(orig_inp_data); - FreeOrigAtData(prep_inp_data); - FreeOrigAtData(prep_inp_data + 1); - /* Close files */ - inchi_ios_close(inp_file); - inchi_ios_close(pout); - inchi_ios_close(pprb); - { - int hours, minutes, seconds, mseconds; - - SplitTime(ulTotalProcessingTime, &hours, &minutes, &seconds, &mseconds); - - inchi_ios_eprint(plog, "Finished processing %ld structure%s: %ld error%s, processing time %d:%02d:%02d.%02d\n", - num_inp, num_inp == 1 ? "" : "s", - num_err, num_err == 1 ? "" : "s", - hours, minutes, seconds, mseconds / 10); - inchi_ios_flush2(plog, stderr); - } -#if ( defined(_WIN32) && defined(_MSC_VER) ) -#if WINVER >= 0x0501 /* XP or newer */ /* 0x0600 Vista or newer */ - tick_inchi_stop = GetTickCount64(); /* djb-rwth: GetTickCount64() should be used */ - inchi_ios_eprint(plog, "\nElapsed walltime: %d msec.\n", tick_inchi_stop - tick_inchi_start); - inchi_ios_flush2(plog, stderr); -#endif -#endif - /* Final cleanup */ - inchi_ios_close(plog); - inchi_strbuf_close(strbuf); - for (i = 0; i < MAX_NUM_PATHS; i++) - { - if (ip->path[i]) - { - inchi_free((void*)ip->path[i]); /* cast deliberately discards 'const' qualifier */ - ip->path[i] = NULL; - } - } - SetBitFree(&CG); -#if ( ( BUILD_WITH_AMI==1 ) && defined( _WIN32 ) && defined( _CONSOLE ) && !defined( COMPILE_ANSI_ONLY ) ) - if (bInterrupted) - { - return CTRL_STOP_EVENT; - } -#endif - - return 0; -} - - -/****************************************************************************/ -void save_command_line(int argc, char* argv[], INCHI_IOSTREAM* plog) -{ - int k; - - inchi_ios_eprint(plog, "The command line used:\n\""); - for (k = 0; k < argc - 1; k++) - { -#if( ALLOW_EMPTY_PATHS == 1 ) - inchi_ios_eprint(plog, "%-s ", argv[k][0] ? argv[k] : "\"\""); -#else - inchi_ios_eprint(plog, "%-s ", argv[k]); -#endif - } - - inchi_ios_eprint(plog, "%-s\"\n", argv[argc - 1]); - - return; -} - - -/*****************************************************************************/ -void emit_empty_inchi(INPUT_PARMS* ip, - long num_inp, - char* pLF, - char* pTAB, - INCHI_IOSTREAM* pout) -{ - if (ip->bINChIOutputOptions & INCHI_OUT_STDINCHI) - { - inchi_ios_eprint(pout, "InChI=1S//\n"); /* emit empty Std InChI */ - } - else - { - inchi_ios_eprint(pout, "InChI=1//\n"); /* emit empty InChI */ - } - inchi_ios_flush(pout); -} -#endif /* ifndef TARGET_LIB_FOR_WINCHI */ - - -/*****************************************************************************/ -int GetTheNextRecordOfInputFile(struct tagINCHI_CLOCK* ic, - STRUCT_DATA* sd, INPUT_PARMS* ip, - char* szTitle, - INCHI_IOSTREAM* inp_file, - INCHI_IOSTREAM* plog, - INCHI_IOSTREAM* pout, - INCHI_IOSTREAM* pprb, - ORIG_ATOM_DATA* orig_inp_data, - long* num_inp, - STRUCT_FPTRS* pStructPtrs, - int* nRet, - int* have_err_in_GetOneStructure, - long* num_err, - int output_error_inchi) -{ - if (ip->last_struct_number && *num_inp >= ip->last_struct_number) - { - *nRet = _IS_EOF; /* simulate end of file */ - return DO_EXIT_FUNCTION; - } - - - *nRet = GetOneStructure(ic, sd, ip, szTitle, inp_file, - plog, pout, pprb, orig_inp_data, - num_inp, pStructPtrs); - - inchi_ios_flush2(plog, stderr); - - if (pStructPtrs) - pStructPtrs->cur_fptr++; - - if (sd->bUserQuit) - { - { - return DO_BREAK_MAIN_LOOP; - } - } - - *have_err_in_GetOneStructure = 0; - switch (*nRet) - { - case _IS_FATAL: - (*num_err)++; - if (output_error_inchi == 0) - { - return DO_EXIT_FUNCTION; - } - else - sd->pStrErrStruct[0] = '\0'; /* depress re-appearance of error as warning in ProcessOneStr */ - break; - case _IS_EOF: - return DO_EXIT_FUNCTION; - case _IS_ERROR: - (*num_err)++; - *have_err_in_GetOneStructure = 1; - if (output_error_inchi == 0) - { - return DO_CONTINUE_MAIN_LOOP; - } - else - sd->pStrErrStruct[0] = '\0'; /* depress re-appearance of error as warning in ProcessOneStr */ - break; - case _IS_SKIP: - return DO_CONTINUE_MAIN_LOOP; - default: - sd->pStrErrStruct[0] = '\0'; - } - - return DO_NEXT_STEP; -} - - -/****************************************************************************/ -int CalcAndPrintINCHIAndINCHIKEY(struct tagINCHI_CLOCK* ic, - CANON_GLOBALS* CG, - STRUCT_DATA* sd, - INPUT_PARMS* ip, - char* szTitle, - PINChI2* pINChI[INCHI_NUM], - PINChI_Aux2* pINChI_Aux[INCHI_NUM], - INCHI_IOSTREAM* inp_file, - INCHI_IOSTREAM* plog, - INCHI_IOSTREAM* pout, - INCHI_IOSTREAM* pprb, - ORIG_ATOM_DATA* orig_inp_data, - ORIG_ATOM_DATA* prep_inp_data, - long* num_inp, - STRUCT_FPTRS* pStructPtrs, - int* nRet, - int have_err_in_GetOneStructure, - long* num_err, - int output_error_inchi, - INCHI_IOS_STRING* strbuf, - unsigned long* pulTotalProcessingTime, - char* pLF, - char* pTAB, - char* ikey, - int silent) -{ - int nRet1; - int next_act = DO_NEXT_STEP; - /* related to hash of InChI */ - char ik_string[256]; /*^^^ Resulting InChIKey string */ - int ik_ret = 0; /*^^^ InChIKey-calc result code */ - int xhash1, xhash2; - char szXtra1[65], szXtra2[65]; - /* related to printing structure header */ - int print_record_info = 0; - INCHI_IOSTREAM temp_out; - INCHI_IOSTREAM* pout0 = &temp_out; - inchi_ios_init(pout0, INCHI_IOS_TYPE_STRING, NULL); - - - /* Calculate InChI */ - - nRet1 = ProcessOneStructureEx(ic, - CG, - sd, - ip, - szTitle, - pINChI, - pINChI_Aux, - inp_file, - plog, - pout0, /* note this */ - pprb, - orig_inp_data, - prep_inp_data, - *num_inp, strbuf, - 0 /* save_opt_bits */); - - inchi_ios_flush2(plog, stderr); - - - /* Output InChI */ - - /* print header for structure if applicable (no error arose, or have a request for empty InChI at error) */ - print_record_info = ((nRet1 == _IS_OKAY) || - (nRet1 == _IS_WARNING) || - ((nRet1 == _IS_ERROR || nRet1 == _IS_FATAL) && output_error_inchi)); - if (print_record_info) - { - Output_RecordInfo(pout, *num_inp, ip->bNoStructLabels, - ip->pSdfLabel, ip->pSdfValue, ip->lSdfId, pLF, pTAB); - } - if (pout0->s.pStr) - { - /* post-process output to correctly treat 'tabbed with InChIKey' mode */ - if (ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT) - { - if (ip->bCalcInChIHash != INCHIHASH_NONE) - { - if (pout0->s.pStr) - { - if (pout0->s.nUsedLength > 0) - { - if (pout0->s.pStr[pout0->s.nUsedLength - 1] == '\n') - { - pout0->s.pStr[pout0->s.nUsedLength - 1] = '\t'; - } - } - } - } - } - /* print InChI string (may be string for empty InChI) */ - if (!ip->bHideInChI) - { - inchi_ios_print(pout, "%-s", pout0->s.pStr); - } - } - /*inchi_ios_close(pout0);*/ /* free temporary out */ - - - *pulTotalProcessingTime += sd->ulStructTime; - - if (nRet1 == _IS_SKIP) - { - next_act = DO_CONTINUE_MAIN_LOOP; - goto exit_function; - } - - *nRet = inchi_max(*nRet, nRet1); - switch (*nRet) - { - case _IS_FATAL: - if (!have_err_in_GetOneStructure) - { - /* increment error counter only if error did not appear earlier */ - (*num_err)++; - } - if (!(ip->bINChIOutputOptions & INCHI_OUT_NO_AUX_INFO) && - (ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT)) - { - inchi_ios_print(pout, "\t"); - } - if (ip->bCalcInChIHash != INCHIHASH_NONE) - { - if (ip->bINChIOutputOptions2 & INCHI_OUT_INCHI_GEN_ERROR) - { - if (ip->bINChIOutputOptions & INCHI_OUT_STDINCHI) - { - inchi_ios_print(pout, "InChIKey=%-s\n", "MOSFIJXAXDLOML-UHFFFAOYSA-N"); - } - else - { - inchi_ios_print(pout, "InChIKey=%-s\n", "MOSFIJXAXDLOML-UHFFFAOYNA-N"); - } - } - } - inchi_ios_flush(pout); - next_act = DO_EXIT_FUNCTION; - goto exit_function; - - case _IS_ERROR: - if (!have_err_in_GetOneStructure) - { - /* increment error counter only if error did not appear earlier */ - (*num_err)++; - } - if (!(ip->bINChIOutputOptions & INCHI_OUT_NO_AUX_INFO) && - (ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT)) - { - inchi_ios_print(pout, "\t"); - } - if (ip->bCalcInChIHash != INCHIHASH_NONE) - { - if (ip->bINChIOutputOptions2 & INCHI_OUT_INCHI_GEN_ERROR) - { - if (ip->bINChIOutputOptions & INCHI_OUT_STDINCHI) - { - inchi_ios_print(pout, "InChIKey=%-s\n", "MOSFIJXAXDLOML-UHFFFAOYSA-N"); - } - else - { - inchi_ios_print(pout, "InChIKey=%-s\n", "MOSFIJXAXDLOML-UHFFFAOYNA-N"); - } - } - } - inchi_ios_flush(pout); - next_act = DO_CONTINUE_MAIN_LOOP; - goto exit_function; - - case _IS_SKIP: - next_act = DO_CONTINUE_MAIN_LOOP; - goto exit_function; - } - - - /* Calculate hash[es] of InChI */ - - if (ip->bCalcInChIHash != INCHIHASH_NONE) - { - char* buf = NULL; - size_t slen = pout0->s.nUsedLength; - - extract_inchi_substring(&buf, pout0->s.pStr, slen); - - if (NULL == buf) - { - ik_ret = INCHIKEY_INVALID_INCHI; - } - else - { - xhash1 = xhash2 = 0; - if ((ip->bCalcInChIHash == INCHIHASH_KEY_XTRA1) || - (ip->bCalcInChIHash == INCHIHASH_KEY_XTRA1_XTRA2)) - { - xhash1 = 1; - } - if ((ip->bCalcInChIHash == INCHIHASH_KEY_XTRA2) || - (ip->bCalcInChIHash == INCHIHASH_KEY_XTRA1_XTRA2)) - { - xhash2 = 1; - } - ik_ret = GetINCHIKeyFromINCHI(buf, xhash1, xhash2, ik_string, szXtra1, szXtra2); - inchi_free(buf); - } - - - /* Print hash[es] */ - - if (ik_ret == INCHIKEY_OK) - { - /* NB: correctly treat tabbed output with InChIKey & hash extensions */ - char csep = '\n'; - - if (ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT) - { - csep = '\t'; - } - if (!ip->bMergeHash) - { - inchi_ios_print(pout, "InChIKey=%-s", ik_string); - } - else - { - inchi_ios_print(pout, "InChIHash=%-s", ik_string); - } - strcpy(ikey, ik_string); - - if (szXtra1[0] && ip->bMergeHash) - { - inchi_ios_print(pout, "-%-s", szXtra1); - } - else if (szXtra1[0] && !ip->bMergeHash) - { - inchi_ios_print(pout, "%cXHash1=%-s", csep, szXtra1); - } - else if (!szXtra1[0] && ip->bMergeHash) - { - inchi_ios_print(pout, "-"); - } - - if (szXtra2[0] && ip->bMergeHash) - { - inchi_ios_print(pout, "-%-s", szXtra2); - } - else if (szXtra2[0] && !ip->bMergeHash) - { - inchi_ios_print(pout, "%cXHash2=%-s", csep, szXtra2); - } - else if (!szXtra2[0] && ip->bMergeHash) - { - inchi_ios_print(pout, "-"); - } - - inchi_ios_print(pout, "\n"); - } - else - { - inchi_ios_print(plog, "Warning (Could not compute InChIKey: ", num_inp); - switch (ik_ret) - { - case INCHIKEY_UNKNOWN_ERROR: - inchi_ios_print(plog, "unresolved error)"); - break; - case INCHIKEY_EMPTY_INPUT: - inchi_ios_print(plog, "got an empty string)"); - break; - case INCHIKEY_INVALID_INCHI_PREFIX: - case INCHIKEY_INVALID_INCHI: - case INCHIKEY_INVALID_STD_INCHI: - inchi_ios_print(plog, "no valid InChI string found)"); - break; - case INCHIKEY_NOT_ENOUGH_MEMORY: - inchi_ios_print(plog, "not enough memory to treat the string)"); - break; - default: inchi_ios_print(plog, "internal program error)"); - break; - } - inchi_ios_print(plog, " structure #%-lu.\n", *num_inp); - if (ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT) - { - inchi_ios_print(pout, "\n"); - } - } - - if (!silent) - { - inchi_ios_flush(pout); - inchi_ios_flush2(plog, stderr); - } - else - { - inchi_ios_free_str(pout); - inchi_ios_free_str(plog); - } - } - else - { - inchi_ios_flush(pout); - } - -exit_function: - inchi_ios_close(pout0); /* free temporary out */ - - return next_act; -} - - -#ifdef RENUMBER_ATOMS_AND_RECALC_V106 - -/*****************************************************************************/ - -int numbers_rrar[PERMAXATOMS]; /* djb-rwth: placed as a global variable to avoid function buffer issues */ -int RepeatedlyRenumberAtomsAndRecalcINCHI(struct tagINCHI_CLOCK* ic, - CANON_GLOBALS* CG, - STRUCT_DATA* sd, - INPUT_PARMS* ip, - char* szTitle, - PINChI2* pINChI[INCHI_NUM], - PINChI_Aux2* pINChI_Aux[INCHI_NUM], - INCHI_IOSTREAM* inp_file, - INCHI_IOSTREAM* plog, - INCHI_IOSTREAM* pout, - INCHI_IOSTREAM* pprb, - ORIG_ATOM_DATA* orig_inp_data, - ORIG_ATOM_DATA* prep_inp_data, - long* num_inp, - STRUCT_FPTRS* pStructPtrs, - int* nRet, - int have_err_in_GetOneStructure, - long* num_err, - int output_error_inchi, - INCHI_IOS_STRING* strbuf, - unsigned long* pulTotalProcessingTime, - char* pLF, - char* pTAB, - long int nrepeat) -{ - int next_action = DO_NEXT_STEP; - int dup_fail = 0; - ORIG_ATOM_DATA SavedOrigAtData; /* 0=> disconnected, 1=> original */ - ORIG_ATOM_DATA* saved_orig_inp_data = &SavedOrigAtData; - char ikey0[28]; - - const int very_silent = 2; /* 3 0;*/ - - /* Internal test mode: renumber atoms and recalculate repeatedly */ - - /* do not forget to use /key and to not use /auxnone */ - - - ikey0[0] = '\0'; - { - int k; - for (k = 0; k < orig_inp_data->num_inp_atoms; k++) - { - numbers_rrar[k] = k; - } - for (k = orig_inp_data->num_inp_atoms; k < PERMAXATOMS; k++) - { - numbers_rrar[k] = -1; - } - } - - - - -#if BIG_POLY_DEBUG - { int k; ITRACE_("\nAtoms = {"); for (k = 0; k < orig_inp_data->num_inp_atoms - 1; k++) ITRACE_(" %-03d,", numbers_rrar[k]); ITRACE_(" %-03d }", numbers_rrar[orig_inp_data->num_inp_atoms - 1]); } - OrigAtData_DebugTrace(orig_inp_data); - OrigAtDataPolymer_DebugTrace(orig_inp_data->polymer); -#endif - - memset(saved_orig_inp_data, 0, sizeof(*saved_orig_inp_data)); /* djb-rwth: memset_s C11/Annex K variant? */ - dup_fail = OrigAtData_Duplicate(saved_orig_inp_data, orig_inp_data); - - next_action = CalcAndPrintINCHIAndINCHIKEY(ic, CG, sd, ip, szTitle, - pINChI, pINChI_Aux, - inp_file, plog, pout, pprb, - orig_inp_data, prep_inp_data, num_inp, pStructPtrs, - nRet, have_err_in_GetOneStructure, - num_err, output_error_inchi, - strbuf, pulTotalProcessingTime, - pLF, pTAB, ikey0, very_silent); - FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); - FreeOrigAtData(orig_inp_data); - FreeOrigAtData(prep_inp_data); - FreeOrigAtData(prep_inp_data + 1); - - - if (ikey0[0]) - { - if (very_silent < 2) - { - inchi_ios_eprint(plog, "#%-ld-%08ld\t...\t%-s\t%s%s%s%s\n", *num_inp, 1, ikey0, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue)); - } - } - - - if (!dup_fail) - { - int irepeat = 0; - int ndiff = 0; - int n_written_problems = 0; - char ikey[28]; - ikey[0] = '\0'; - for (irepeat = 0; irepeat < nrepeat - 1; irepeat++) - { - dup_fail = OrigAtData_Duplicate(orig_inp_data, saved_orig_inp_data); - if (!dup_fail) - { - shuffle((void*)numbers_rrar, orig_inp_data->num_inp_atoms, sizeof(int)); - OrigAtData_Permute(orig_inp_data, saved_orig_inp_data, numbers_rrar); -#if BIG_POLY_DEBUG - { int k; ITRACE_("\nAtoms = {"); for (k = 0; k < orig_inp_data->num_inp_atoms - 1; k++) ITRACE_(" %-03d,", numbers_rrar[k]); ITRACE_(" %-03d }", numbers_rrar[orig_inp_data->num_inp_atoms - 1]); } - OrigAtData_DebugTrace(saved_orig_inp_data); - OrigAtData_DebugTrace(orig_inp_data); - OrigAtDataPolymer_DebugTrace(saved_orig_inp_data->polymer); - OrigAtDataPolymer_DebugTrace(orig_inp_data->polymer); -#endif - next_action = CalcAndPrintINCHIAndINCHIKEY(ic, CG, sd, ip, szTitle, - pINChI, pINChI_Aux, - inp_file, plog, pout, pprb, - orig_inp_data, - prep_inp_data, num_inp, pStructPtrs, - nRet, have_err_in_GetOneStructure, - num_err, output_error_inchi, - strbuf, pulTotalProcessingTime, - pLF, pTAB, ikey, - 0 /* 1 be silent */); - - - if (ikey0[0] && ikey[0]) - { - if (strcmp(ikey, ikey0)) - { - int result, bINChIOutputOptions = ip->bINChIOutputOptions; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ - ndiff++; - /*inchi_ios_eprint( plog, "!!! #%-ld-%05ld %s%s%s%s\tcurr %-s != %-s orig\n", *num_inp, irepeat + 2, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ), ikey, ikey0 );*/ - /*inchi_ios_eprint( plog, "!!! %s%s%s%s renum#%05ld\t%-s != %-s\n", SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ), irepeat + 2, ikey, ikey0 );*/ - inchi_ios_eprint(plog, "!!! #%-ld %s%s%s%s\t%-s --> %-s @ renum#%06d/%06ld\n", *num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue), ikey0, ikey, irepeat + 2, nrepeat); - if (!very_silent) - { - int k; - inchi_ios_eprint(plog, "Atoms = {"); - for (k = 0; k < orig_inp_data->num_inp_atoms - 1; k++) - { - inchi_ios_eprint(plog, " %-d,", numbers_rrar[k] + 1); - } - inchi_ios_eprint(plog, " %-d }\n\n", numbers_rrar[orig_inp_data->num_inp_atoms - 1] + 1); - } - ip->bINChIOutputOptions |= INCHI_OUT_SDFILE_ONLY; - result = OrigAtData_SaveMolfile(orig_inp_data, sd, ip, *num_inp, pprb); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ - inchi_ios_flush(pprb); - ip->bINChIOutputOptions = bINChIOutputOptions; - if (result == 0) - { - n_written_problems++; - } -#if 0 - /* second pass, non-silent one */ - FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); - FreeOrigAtData(orig_inp_data); - FreeOrigAtData(prep_inp_data); - FreeOrigAtData(prep_inp_data + 1); - dup_fail = OrigAtData_Duplicate(orig_inp_data, saved_orig_inp_data); - if (!dup_fail) - { - OrigAtData_Permute(orig_inp_data, saved_orig_inp_data, numbers_rrar); - next_action = CalcAndPrintINCHIAndINCHIKEY(ic, CG, sd, ip, szTitle, - pINChI, pINChI_Aux, - inp_file, plog, pout, pprb, - orig_inp_data, - prep_inp_data, num_inp, pStructPtrs, - nRet, have_err_in_GetOneStructure, - num_err, output_error_inchi, - strbuf, pulTotalProcessingTime, - pLF, pTAB, ikey, 0); - } -#endif - } - - if (irepeat == nrepeat - 2) - { - if (very_silent < 2) - { - inchi_ios_eprint(plog, "...........\n#%-ld-%08ld\t...\t%-s\t%s%s%s%s\n", *num_inp, irepeat + 2, ikey0, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue)); - } - } - - } - } - FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); - FreeOrigAtData(orig_inp_data); - FreeOrigAtData(prep_inp_data); - FreeOrigAtData(prep_inp_data + 1); - -#ifdef STOP_AFTER_FIRST_CHANGE_ON_RENUMBERING - if (ndiff == 1) - { - next_action = DO_CONTINUE_MAIN_LOOP; - break; - } -#endif - } - if (ndiff == 0) - { - if (very_silent < 3) - { - /*inchi_ios_eprint( plog, "#%-ld-%05ld\t...\tOK ALL\n", *num_inp, nrepeat );*/ - /*inchi_ios_eprint( plog, "OK #%-ld %s%s%s%s\n", *num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue));*/ - /*inchi_ios_eprint(plog, "#%-ld\n", *num_inp);*/ - inchi_ios_eprint(plog, "OK #%-ld %s%s%s%s\t%-s\t Same for %-d/%-d renums\n", *num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue), ikey0, nrepeat, nrepeat); - } - } - else - { -#ifdef STOP_AFTER_FIRST_CHANGE_ON_RENUMBERING - /*inchi_ios_eprint( plog, "#%-ld-%05ld\t...\tDIFF %-d\n", num_inp, nrepeat, ndiff );*/ -#else - inchi_ios_eprint(plog, "#%-ld-%05ld\t...\tDIFF %-d\n", num_inp, nrepeat, ndiff); -#endif - } - - FreeOrigAtData(saved_orig_inp_data); - } - - return next_action; -} - - -#endif From c34b488fb81cf8f1cb42c976f3a23d94e3a58d5f Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 8 Dec 2025 14:48:07 +0000 Subject: [PATCH 03/69] added unit test for ProcessSingleInputFile --- .gitignore | 1 + INCHI-1-SRC/INCHI_BASE/src/ichimain.c | 1 - INCHI-1-SRC/INCHI_BASE/src/ichimain.h | 5 +- .../tests/test_unit/fixtures/caffeine.mol | 55 + .../tests/test_unit/fixtures/test_mols.sdf | 1976 +++++++++++++++++ .../tests/test_unit/fixtures/test_mols_2.sdf | 320 +++ .../tests/test_unit/test_ichimain.cpp | 241 +- 7 files changed, 2583 insertions(+), 16 deletions(-) create mode 100644 INCHI-1-TEST/tests/test_unit/fixtures/caffeine.mol create mode 100644 INCHI-1-TEST/tests/test_unit/fixtures/test_mols.sdf create mode 100644 INCHI-1-TEST/tests/test_unit/fixtures/test_mols_2.sdf diff --git a/.gitignore b/.gitignore index ae1a6c21..8e8a17cd 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ build/ Testing/ googletest/ *.egg-info/ +inchi_mol_test_*/ .clang-format # Ignore core dump files core.*[0-9] diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichimain.c b/INCHI-1-SRC/INCHI_BASE/src/ichimain.c index ccdc9aeb..326dfb7b 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichimain.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichimain.c @@ -2,7 +2,6 @@ * International Chemical Identifier (InChI) * Version 1 * Software version 1.07 - * April 30, 2024 * * MIT License * diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichimain.h b/INCHI-1-SRC/INCHI_BASE/src/ichimain.h index 02f999eb..779d6b3e 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichimain.h +++ b/INCHI-1-SRC/INCHI_BASE/src/ichimain.h @@ -2,7 +2,6 @@ * International Chemical Identifier (InChI) * Version 1 * Software version 1.07 - * April 30, 2024 * * MIT License * @@ -164,7 +163,7 @@ typedef struct tagINCHI_OUT_CTL char szTag2[PRINT_INCHI_MAX_TAG_LEN]; char szTag3[PRINT_INCHI_MAX_TAG_LEN]; - int n_pzz; + int n_pzz; int n_zy; INCHI_SORT **pINChISortTautAndNonTaut; @@ -521,7 +520,7 @@ int OAD_StructureEdits_Apply( STRUCT_DATA *sd, OAD_StructureEdits *ed, int *ret); void OAD_CollectFragmentBondsAndAtoms( ORIG_ATOM_DATA *at_data, - int nforbidden, + int nforbidden, int *forbidden_orig, int *n_fragbonds, int **fragbonds, diff --git a/INCHI-1-TEST/tests/test_unit/fixtures/caffeine.mol b/INCHI-1-TEST/tests/test_unit/fixtures/caffeine.mol new file mode 100644 index 00000000..9373920c --- /dev/null +++ b/INCHI-1-TEST/tests/test_unit/fixtures/caffeine.mol @@ -0,0 +1,55 @@ +C8H10N4O2 +APtclcactv08142501153D 0 0.00000 0.00000 + + 24 25 0 0 0 0 0 0 0 0999 V2000 + 1.3120 -1.0479 0.0025 N 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2465 -2.1762 0.0031 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7906 0.2081 0.0010 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.9938 0.3838 0.0002 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.9714 1.2767 -0.0001 N 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5339 2.6294 -0.0017 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.4026 1.0989 -0.0001 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.4446 1.9342 -0.0010 N 0 0 0 0 0 0 0 0 0 0 0 0 + -2.5608 1.2510 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.2862 -0.0680 0.0015 N 0 0 0 0 0 0 0 0 0 0 0 0 + -3.2614 -1.1612 0.0029 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.9114 -0.1939 0.0014 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0163 -1.2853 -0.0022 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.4380 -2.4279 -0.0068 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2697 -1.8004 0.0022 H 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0830 -2.7828 0.8938 H 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0821 -2.7846 -0.8862 H 0 0 0 0 0 0 0 0 0 0 0 0 + 2.6223 2.5703 -0.0019 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1.1987 3.1611 -0.8923 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1.1990 3.1632 0.8877 H 0 0 0 0 0 0 0 0 0 0 0 0 + -3.5520 1.6797 -0.0001 H 0 0 0 0 0 0 0 0 0 0 0 0 + -3.5037 -1.4333 -1.0244 H 0 0 0 0 0 0 0 0 0 0 0 0 + -2.8389 -2.0244 0.5173 H 0 0 0 0 0 0 0 0 0 0 0 0 + -4.1672 -0.8395 0.5168 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 3 4 2 0 0 0 0 + 3 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 5 7 1 0 0 0 0 + 7 8 1 0 0 0 0 + 8 9 2 0 0 0 0 + 9 10 1 0 0 0 0 + 10 11 1 0 0 0 0 + 10 12 1 0 0 0 0 + 7 12 2 0 0 0 0 + 12 13 1 0 0 0 0 + 1 13 1 0 0 0 0 + 13 14 2 0 0 0 0 + 2 15 1 0 0 0 0 + 2 16 1 0 0 0 0 + 2 17 1 0 0 0 0 + 6 18 1 0 0 0 0 + 6 19 1 0 0 0 0 + 6 20 1 0 0 0 0 + 9 21 1 0 0 0 0 + 11 22 1 0 0 0 0 + 11 23 1 0 0 0 0 + 11 24 1 0 0 0 0 +M END + diff --git a/INCHI-1-TEST/tests/test_unit/fixtures/test_mols.sdf b/INCHI-1-TEST/tests/test_unit/fixtures/test_mols.sdf new file mode 100644 index 00000000..d3d970d8 --- /dev/null +++ b/INCHI-1-TEST/tests/test_unit/fixtures/test_mols.sdf @@ -0,0 +1,1976 @@ +Compound 20652 +Actelion Java MolfileCreator 1.0 + +101110 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0153 1.5192 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2737 2.2865 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3351 2.2865 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.9029 0.4297 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2277 3.8057 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3504 3.8057 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8875 -1.0589 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0614 4.5730 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.3147 3.4528 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1766 -1.7955 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5678 -1.7955 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.8518 4.8799 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -4.6344 2.7162 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4656 -1.0282 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1612 -3.2840 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5524 -3.2840 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.9541 3.4835 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -4.6498 1.2277 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4503 0.4911 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4503 -4.0206 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8415 -4.0206 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7673 -4.0206 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.2739 2.7469 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.9695 0.4911 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.3607 0.4911 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1305 1.2583 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7393 1.2583 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4349 -5.5091 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.0870 -3.2533 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7826 -5.5091 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.2892 1.2583 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -8.5936 3.5142 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.3761 -0.9975 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1152 2.7776 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.0283 0.5218 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7240 2.7776 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7240 -6.2457 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1152 -6.2457 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1024 -1.7341 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1024 -6.2457 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5064 -6.2457 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -8.6090 5.0334 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -9.9133 2.7776 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.6958 -1.7341 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4042 3.5449 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8568 3.5449 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.3174 1.2890 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.0130 3.5449 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 7.0130 -5.4784 -0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7086 -7.7342 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2686 -7.6422 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8133 -0.9668 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.4911 -7.7342 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.9287 5.8007 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.2331 3.5449 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.7111 -3.2226 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.3889 5.0641 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7955 5.0641 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 9.6064 0.5524 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 8.3020 2.8083 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.3889 -8.4708 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7801 -8.4708 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8287 -8.4708 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.2484 5.0641 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -12.5528 2.8083 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4221 -3.9592 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -6.0309 -3.9592 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 10.8955 1.3197 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 9.5911 3.5756 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.3735 -9.9594 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.7315 -7.8724 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8415 -9.7292 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -1.0282 -10.0054 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1484 -7.7036 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 10.8801 2.8390 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 12.1845 0.5831 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 10.3277 4.8953 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 8.8238 4.8953 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.6626 -10.6960 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0538 -10.6960 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1484 -10.6960 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4681 -8.4402 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 12.1692 3.6062 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0385 -12.1845 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1637 -12.1845 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4681 -9.9287 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.3275 -12.9211 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7187 -12.9211 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4835 -12.9211 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8747 -12.9211 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.7879 -10.6653 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.3990 -12.1538 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.8032 -12.1538 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4988 -14.4096 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8901 -14.4096 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.3836 -10.6346 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.2098 -15.1462 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5806 -10.1282 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.5831 -9.7906 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -2.2251 -16.6348 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 2 3 2 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 3 6 1 0 0 0 0 + 4 7 2 0 0 0 0 + 5 8 1 0 0 0 0 + 6 9 2 0 0 0 0 + 7 10 1 0 0 0 0 + 8 11 2 0 0 0 0 + 8 12 1 0 0 0 0 + 10 13 1 6 0 0 0 + 10 14 1 0 0 0 0 + 11 15 1 0 0 0 0 + 11 16 1 0 0 0 0 + 12 17 2 0 0 0 0 + 14 18 1 6 0 0 0 + 14 19 1 0 0 0 0 + 20 15 1 6 0 0 0 + 16 21 1 0 0 0 0 + 16 22 2 0 0 0 0 + 17 23 1 0 0 0 0 + 18 24 1 0 0 0 0 + 19 25 2 0 0 0 0 + 19 26 1 0 0 0 0 + 20 27 1 0 0 0 0 + 20 28 1 0 0 0 0 + 21 29 1 0 0 0 0 + 23 30 1 6 0 0 0 + 23 31 1 0 0 0 0 + 24 32 2 0 0 0 0 + 24 33 1 0 0 0 0 + 26 34 1 0 0 0 0 + 27 35 1 0 0 0 0 + 28 36 1 1 0 0 0 + 28 37 1 0 0 0 0 + 29 38 2 0 0 0 0 + 29 39 1 0 0 0 0 + 30 40 1 0 0 0 0 + 31 41 2 0 0 0 0 + 31 42 1 0 0 0 0 + 33 43 1 1 0 0 0 + 33 44 1 0 0 0 0 + 34 45 1 6 0 0 0 + 35 46 1 0 0 0 0 + 35 47 1 0 0 0 0 + 48 36 1 1 0 0 0 + 37 49 1 6 0 0 0 + 38 50 1 0 0 0 0 + 38 51 1 0 0 0 0 + 39 52 2 0 0 0 0 + 40 53 2 0 0 0 0 + 54 42 1 1 0 0 0 + 43 55 1 0 0 0 0 + 44 56 1 0 0 0 0 + 45 57 1 0 0 0 0 + 46 58 1 1 0 0 0 + 47 59 1 0 0 0 0 + 48 60 1 0 0 0 0 + 48 61 1 0 0 0 0 + 51 62 2 0 0 0 0 + 54 63 1 0 0 0 0 + 54 64 1 0 0 0 0 + 56 65 1 0 0 0 0 + 56 66 1 0 0 0 0 + 57 67 2 0 0 0 0 + 57 68 1 0 0 0 0 + 60 69 1 0 0 0 0 + 61 70 1 0 0 0 0 + 62 71 1 0 0 0 0 + 63 72 2 0 0 0 0 + 63 73 1 0 0 0 0 + 64 74 2 0 0 0 0 + 64 75 1 0 0 0 0 + 69 76 1 0 0 0 0 + 69 77 1 6 0 0 0 + 70 78 1 6 0 0 0 + 70 79 1 0 0 0 0 + 71 80 1 1 0 0 0 + 71 81 1 0 0 0 0 + 74 82 1 0 0 0 0 + 75 83 2 0 0 0 0 + 76 84 1 6 0 0 0 + 81 85 1 0 0 0 0 + 82 86 1 0 0 0 0 + 82 87 2 0 0 0 0 + 85 88 2 0 0 0 0 + 85 89 1 0 0 0 0 + 86 90 2 0 0 0 0 + 86 91 1 0 0 0 0 + 87 92 1 0 0 0 0 + 89 93 1 0 0 0 0 + 90 94 1 0 0 0 0 + 90 95 1 0 0 0 0 + 91 96 2 0 0 0 0 + 93 97 1 1 0 0 0 + 95 98 2 0 0 0 0 + 97 99 2 0 0 0 0 + 97100 1 0 0 0 0 + 98101 1 0 0 0 0 + 7 9 1 0 0 0 0 + 17 22 1 0 0 0 0 + 34 40 1 0 0 0 0 + 37 46 1 0 0 0 0 + 52 62 1 0 0 0 0 + 70 76 1 0 0 0 0 + 81 73 1 1 0 0 0 + 83 87 1 0 0 0 0 + 91 93 1 0 0 0 0 + 96 98 1 0 0 0 0 +M END +> +Compound 20652 + +> +BIO-423 + +> +VANCOMYCIN HYDROCHLORIDE + +> +Products for Life Science + +> +1404-93-9 + +> +1485.7 + +> +'93.5% (Vanomycin base) + +> +MFCD03613611 + +$$$$ +Compound 20656 +Actelion Java MolfileCreator 1.0 + + 75 78 0 0 1 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 S 0 0 0 0 0 0 0 0 0 0 0 0 + -1.4488 -0.4553 -0.0000 S 0 0 0 0 0 0 0 0 0 0 0 0 + 0.3036 1.4902 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.7799 -1.9179 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8279 2.5112 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.0631 -2.2628 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.5243 4.0013 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -2.2352 2.0559 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.3804 -3.8496 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -4.3739 -1.3384 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.4974 0.3311 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4218 3.0907 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -5.0500 -4.4153 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.5467 -1.5453 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.8910 0.2070 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -4.9258 2.6630 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.8088 -3.2563 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -5.5329 -5.6019 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.9396 1.3522 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.9803 0.8141 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.3259 0.9244 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.0158 3.6564 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.7057 -6.0158 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -4.2359 -6.7471 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.6229 1.2280 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.2635 2.5112 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.0079 2.2490 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.4429 0.0690 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5677 0.5657 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -5.7123 5.1466 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -8.1131 -5.1190 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.5671 -8.2097 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.3266 -0.1656 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -7.5060 2.3732 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -6.9541 -0.7727 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.8437 6.1676 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.2911 5.6295 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.3687 -5.6295 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -7.7405 -3.5322 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.0158 -8.6650 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4632 -9.2031 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -9.0237 2.2352 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -8.4304 -1.1866 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.0020 -1.8627 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5401 7.6577 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9875 7.1196 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -8.7616 -2.6630 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -6.2504 -2.9251 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.6584 0.8693 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.9206 3.4770 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.6032 -0.2070 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -6.3056 -3.3391 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.1190 8.1407 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.3949 -4.1807 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -8.6650 -0.2070 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -11.1762 0.7313 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -9.3135 4.8706 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.8844 -4.2083 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.4232 -3.9600 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.8154 9.6308 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.8496 -3.5460 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.8109 -0.6347 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -10.2103 6.1124 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.1328 -5.6985 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.6439 -5.2845 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.6564 -2.4146 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -2.5526 -4.7188 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -13.3286 -0.7727 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.7281 5.9744 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -6.7333 -6.4849 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -13.9633 -2.1386 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -14.2255 0.4691 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -12.6249 7.2162 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -12.0178 8.6098 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -14.1427 7.0782 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 4 6 1 0 0 0 0 + 5 7 1 1 0 0 0 + 5 8 1 0 0 0 0 + 6 9 1 0 0 0 0 + 6 10 1 6 0 0 0 + 8 11 2 0 0 0 0 + 8 12 1 0 0 0 0 + 9 13 1 0 0 0 0 + 10 14 2 0 0 0 0 + 10 15 1 0 0 0 0 + 12 16 1 0 0 0 0 + 13 17 2 0 0 0 0 + 13 18 1 0 0 0 0 + 15 19 1 0 0 0 0 + 15 20 1 0 0 0 0 + 16 21 1 0 0 0 0 + 16 22 1 6 0 0 0 + 18 23 1 0 0 0 0 + 18 24 1 6 0 0 0 + 19 25 1 6 0 0 0 + 19 26 1 0 0 0 0 + 20 27 1 0 0 0 0 + 21 28 2 0 0 0 0 + 21 29 1 0 0 0 0 + 22 30 1 0 0 0 0 + 23 31 1 0 0 0 0 + 24 32 1 0 0 0 0 + 25 33 2 0 0 0 0 + 25 34 1 0 0 0 0 + 29 35 1 0 0 0 0 + 30 36 2 0 0 0 0 + 30 37 1 0 0 0 0 + 31 38 2 0 0 0 0 + 31 39 1 0 0 0 0 + 32 40 2 0 0 0 0 + 32 41 1 0 0 0 0 + 42 34 1 6 0 0 0 + 35 43 1 0 0 0 0 + 35 44 1 1 0 0 0 + 36 45 1 0 0 0 0 + 37 46 2 0 0 0 0 + 39 47 1 0 0 0 0 + 39 48 1 1 0 0 0 + 42 49 1 0 0 0 0 + 42 50 1 0 0 0 0 + 43 51 2 0 0 0 0 + 44 52 1 0 0 0 0 + 45 53 2 0 0 0 0 + 48 54 1 0 0 0 0 + 49 55 2 0 0 0 0 + 49 56 1 0 0 0 0 + 50 57 1 0 0 0 0 + 52 58 2 0 0 0 0 + 52 59 1 0 0 0 0 + 53 60 1 0 0 0 0 + 54 61 1 0 0 0 0 + 56 62 1 0 0 0 0 + 57 63 1 0 0 0 0 + 58 64 1 0 0 0 0 + 59 65 2 0 0 0 0 + 61 66 2 0 0 0 0 + 61 67 1 0 0 0 0 + 62 68 1 0 0 0 0 + 63 69 1 0 0 0 0 + 64 70 2 0 0 0 0 + 68 71 2 0 0 0 0 + 68 72 1 0 0 0 0 + 69 73 2 0 0 0 0 + 73 74 1 0 0 0 0 + 73 75 1 0 0 0 0 + 26 27 1 0 0 0 0 + 43 47 1 0 0 0 0 + 46 53 1 0 0 0 0 + 65 70 1 0 0 0 0 +M END +> +Compound 20656 + +> +BIO-992 + +> +VASOPRESSIN + +> +Products for Life Science + +> + + +> + + +> +' + +> +MFCD03839092 + +$$$$ +Compound 20659 +Actelion Java MolfileCreator 1.0 + + 33 34 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2913 0.7582 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0118 -1.4927 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5825 0.0118 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2794 2.2745 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5707 -1.4808 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8738 0.7700 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5707 3.0327 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8620 -2.2271 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8620 2.2864 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5588 4.5491 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8501 3.8027 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2439 5.3072 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8501 5.3072 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1414 3.0564 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0711 4.5609 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2320 6.8236 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1414 4.5609 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.4327 5.3191 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.7239 4.5728 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 9.0152 5.3309 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.7121 3.0801 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 10.3065 4.5846 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 11.5977 5.3428 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 12.8890 4.5964 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 11.5859 6.8591 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 14.1803 5.3546 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 12.8772 7.6173 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 15.4715 4.6083 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 14.1684 6.8710 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 16.7628 5.3665 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 15.4597 7.6292 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 15.4478 9.1455 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 2 4 2 0 0 0 0 + 2 5 1 0 0 0 0 + 4 6 1 0 0 0 0 + 4 7 1 0 0 0 0 + 5 8 2 0 0 0 0 + 6 9 1 0 0 0 0 + 7 10 2 0 0 0 0 + 8 11 1 0 0 0 0 + 11 12 1 6 0 0 0 + 11 13 1 0 0 0 0 + 11 14 1 0 0 0 0 + 12 15 3 0 0 0 0 + 13 16 1 0 0 0 0 + 13 17 1 0 0 0 0 + 14 18 1 0 0 0 0 + 18 19 1 0 0 0 0 + 19 20 1 0 0 0 0 + 20 21 1 0 0 0 0 + 20 22 1 0 0 0 0 + 21 23 1 0 0 0 0 + 23 24 1 0 0 0 0 + 24 25 2 0 0 0 0 + 24 26 1 0 0 0 0 + 25 27 1 0 0 0 0 + 26 28 2 0 0 0 0 + 27 29 1 0 0 0 0 + 27 30 2 0 0 0 0 + 29 31 1 0 0 0 0 + 30 32 1 0 0 0 0 + 32 33 1 0 0 0 0 + 8 10 1 0 0 0 0 + 28 30 1 0 0 0 0 +M END +> +Compound 20659 + +> +BIO-424 + +> +VERAPAMIL HYDROCHLORIDE + +> +Products for Life Science + +> +152-11-4 + +> +491.1 + +> +'>99% + +> +MFCD00055208 + +$$$$ +Compound 20668 +Actelion Java MolfileCreator 1.0 + + 37 42 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.8775 -1.1977 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.3598 -1.0198 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2609 -2.5614 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2374 -2.2175 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2255 0.2135 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.6404 -1.3400 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.1384 -3.7592 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2451 -2.7156 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.6207 -3.5813 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.6604 -1.7313 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.6485 -0.2253 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5218 -5.1229 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1464 -1.4942 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.8618 -4.0793 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.4983 -4.7790 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.9843 -5.2770 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7195 -6.0004 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.3085 -4.5418 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.8736 -6.4866 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 1.9092 -7.4827 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.3085 -6.0360 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.6248 -3.7829 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.6958 -7.9689 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.9843 -8.6686 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.9646 -8.5263 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.3441 -7.0677 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.6248 -6.7831 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.9411 -4.5300 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.5099 -8.8702 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.0121 -8.7042 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.9411 -6.0241 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.0239 -10.1983 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.2574 -6.7712 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.7313 -10.9336 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.3402 -10.9336 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.2574 -8.2654 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 3 6 1 0 0 0 0 + 4 7 1 0 0 0 0 + 4 8 1 0 0 0 0 + 4 9 1 0 0 0 0 + 5 10 1 0 0 0 0 + 5 11 1 0 0 0 0 + 6 12 1 0 0 0 0 + 8 13 1 0 0 0 0 + 9 14 1 0 0 0 0 + 9 15 1 0 0 0 0 + 10 16 2 0 0 0 0 + 13 17 1 0 0 0 0 + 13 18 1 0 0 0 0 + 15 19 1 0 0 0 0 + 17 20 1 0 0 0 0 + 18 21 1 0 0 0 0 + 19 22 2 0 0 0 0 + 19 23 1 0 0 0 0 + 20 24 1 0 0 0 0 + 21 25 1 0 0 0 0 + 21 26 1 0 0 0 0 + 21 27 1 0 0 0 0 + 22 28 1 0 0 0 0 + 23 29 2 0 0 0 0 + 24 30 1 0 0 0 0 + 24 31 1 0 0 0 0 + 28 32 2 0 0 0 0 + 31 33 2 0 0 0 0 + 32 34 1 0 0 0 0 + 33 35 1 0 0 0 0 + 33 36 1 0 0 0 0 + 34 37 1 0 0 0 0 + 8 10 1 0 0 0 0 + 11 12 1 0 0 0 0 + 15 17 2 0 0 0 0 + 20 22 1 0 0 0 0 + 25 30 1 0 0 0 0 + 29 32 1 0 0 0 0 +M END +> +Compound 20668 + +> +BIO-1002 + +> +VERRUCULOGEN FROM PENICILLIUM VERRUCULOSUM + +> +Products for Life Science + +> +12771-72-1 + +> + + +> +' + +> +MFCD00079645 + +$$$$ +Compound 20680 +Actelion Java MolfileCreator 1.0 + + 67 75 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2923 -0.7469 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2804 -2.2407 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5846 0.0119 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0356 -2.9877 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5727 -2.9877 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8768 -0.7351 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5727 1.5294 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3516 -2.2289 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0474 -4.4815 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8650 -2.2289 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5609 -4.4815 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1691 0.0237 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8650 2.2882 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2449 -5.2284 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3634 -5.2284 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1573 -2.9758 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1573 -1.4701 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 6.4614 -0.7232 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1573 1.5413 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6794 -4.4696 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3753 -6.7222 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.4495 -2.2170 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 7.7537 0.0356 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1454 3.0588 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 6.4495 2.3000 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9954 -5.2165 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6913 -7.4691 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.7418 1.5531 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.0073 -6.7104 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.3114 -4.4578 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.7031 -8.9630 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 9.0341 2.3119 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 9.0341 0.8062 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.3232 -7.4573 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 10.3264 1.5650 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.3351 -8.9511 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 10.3145 0.0711 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 11.6187 2.3237 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.6511 -9.6980 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -4.0428 -9.6980 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 11.6068 -0.6758 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 12.9110 1.5768 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.6630 -11.1919 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.0547 -11.1919 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 12.8991 0.0830 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 11.5950 -2.1696 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.3707 -11.9388 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.9789 -11.9388 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 14.1914 -0.6639 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -5.3825 -13.4326 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 15.4837 0.0948 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.0902 -14.1795 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 16.7759 -0.6521 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 15.4718 1.6124 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.1021 -15.6734 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -2.7980 -13.4208 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 18.0682 0.1067 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 16.7641 2.3712 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.8098 -16.4203 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.5057 -14.1677 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 18.0564 1.6242 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 19.3605 -0.6402 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.5175 -15.6615 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.8217 -17.9141 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 19.3486 2.3830 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.2253 -16.4084 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 2 0 0 0 0 + 3 6 1 0 0 0 0 + 4 7 2 0 0 0 0 + 4 8 1 0 0 0 0 + 5 9 1 0 0 0 0 + 5 10 1 0 0 0 0 + 6 11 1 0 0 0 0 + 6 12 2 0 0 0 0 + 7 13 1 0 0 0 0 + 8 14 2 0 0 0 0 + 10 15 2 0 0 0 0 + 16 10 1 1 0 0 0 + 11 17 2 0 0 0 0 + 13 18 1 1 0 0 0 + 13 19 1 0 0 0 0 + 13 20 1 0 0 0 0 + 16 21 1 0 0 0 0 + 16 22 1 0 0 0 0 + 19 23 2 0 0 0 0 + 19 24 1 0 0 0 0 + 20 25 1 1 0 0 0 + 20 26 1 0 0 0 0 + 21 27 1 0 0 0 0 + 22 28 1 0 0 0 0 + 24 29 1 0 0 0 0 + 27 30 1 0 0 0 0 + 27 31 1 0 0 0 0 + 28 32 1 0 0 0 0 + 29 33 1 0 0 0 0 + 29 34 1 6 0 0 0 + 30 35 1 6 0 0 0 + 33 36 1 0 0 0 0 + 37 35 1 1 0 0 0 + 36 38 1 0 0 0 0 + 36 39 1 0 0 0 0 + 37 40 1 0 0 0 0 + 37 41 1 0 0 0 0 + 38 42 1 0 0 0 0 + 39 43 1 0 0 0 0 + 40 44 1 0 0 0 0 + 41 45 1 0 0 0 0 + 42 46 1 0 0 0 0 + 42 47 1 6 0 0 0 + 44 48 1 0 0 0 0 + 44 49 1 6 0 0 0 + 46 50 1 0 0 0 0 + 48 51 1 6 0 0 0 + 50 52 1 0 0 0 0 + 53 51 1 1 0 0 0 + 52 54 1 0 0 0 0 + 52 55 1 0 0 0 0 + 53 56 1 0 0 0 0 + 53 57 1 0 0 0 0 + 54 58 1 0 0 0 0 + 55 59 2 0 0 0 0 + 56 60 1 0 0 0 0 + 57 61 2 0 0 0 0 + 58 62 1 0 0 0 0 + 58 63 1 6 0 0 0 + 60 64 1 0 0 0 0 + 60 65 1 6 0 0 0 + 62 66 2 0 0 0 0 + 64 67 2 0 0 0 0 + 7 11 1 0 0 0 0 + 12 15 1 0 0 0 0 + 14 20 1 0 0 0 0 + 26 29 1 0 0 0 0 + 28 30 1 0 0 0 0 + 43 46 1 0 0 0 0 + 45 48 1 0 0 0 0 + 59 62 1 0 0 0 0 + 61 64 1 0 0 0 0 +M END +> +Compound 20680 + +> +BIO-718 + +> +VINEOMYCIN A1 + +> +Products for Life Science + +> +78164-00-8 + +> +934.98 + +> +'>80% + +> +MFCD00079639 + +$$$$ +Compound 20681 +Actelion Java MolfileCreator 1.0 + + 67 74 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3071 0.7536 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3188 2.2609 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6141 0.0118 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0353 3.0145 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6259 3.0145 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9212 0.7654 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6259 -1.4719 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2482 2.2727 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0471 4.5218 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9330 2.2727 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6377 4.5218 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2283 0.0236 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9330 -2.2138 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3542 5.2754 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2364 5.2754 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2401 3.0263 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5354 0.7772 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2401 -1.4602 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5199 4.5335 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2246 6.7826 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5471 -2.2020 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8035 5.2872 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5082 7.5363 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5589 -3.6857 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7917 6.7944 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0870 4.5453 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.4964 9.0435 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -7.8660 -4.4276 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2754 -4.4276 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2754 -2.9321 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0752 7.5480 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -9.1731 -3.6739 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2872 -5.9113 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0634 9.0553 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.1848 -2.1667 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -10.4801 -4.4158 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5942 -6.6531 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -4.0036 -6.6531 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 6.3470 9.8089 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7564 9.8089 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -10.4919 -1.4131 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.7872 -3.6622 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.3352 11.3162 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7446 11.3162 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.7990 -2.1549 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -10.5037 0.0942 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0281 12.0698 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.6187 12.0698 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -13.1061 -1.4013 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0163 13.5771 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -14.4131 -2.1431 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7093 14.3307 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -14.4249 -3.6268 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -15.7202 -1.3895 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.6975 15.8380 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.4022 13.5888 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -15.7320 -4.3687 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -17.0273 -2.1314 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.3904 16.5916 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0951 14.3425 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -17.0390 -3.6151 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -15.7437 -5.8524 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0833 15.8497 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.3786 18.0988 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -18.3461 -4.3569 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.2237 16.6034 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 2 0 0 0 0 + 3 6 1 0 0 0 0 + 4 7 2 0 0 0 0 + 4 8 1 0 0 0 0 + 5 9 1 0 0 0 0 + 5 10 1 0 0 0 0 + 6 11 1 0 0 0 0 + 6 12 2 0 0 0 0 + 7 13 1 0 0 0 0 + 8 14 2 0 0 0 0 + 10 15 2 0 0 0 0 + 16 10 1 1 0 0 0 + 11 17 2 0 0 0 0 + 13 18 1 0 0 0 0 + 13 19 2 0 0 0 0 + 16 20 1 0 0 0 0 + 16 21 1 0 0 0 0 + 19 22 1 0 0 0 0 + 20 23 1 0 0 0 0 + 21 24 1 0 0 0 0 + 22 25 1 0 0 0 0 + 23 26 1 0 0 0 0 + 23 27 1 1 0 0 0 + 24 28 1 1 0 0 0 + 25 29 1 0 0 0 0 + 25 30 1 0 0 0 0 + 25 31 1 1 0 0 0 + 26 32 1 6 0 0 0 + 33 29 1 1 0 0 0 + 30 34 1 0 0 0 0 + 35 32 1 6 0 0 0 + 33 36 1 0 0 0 0 + 33 37 1 0 0 0 0 + 34 38 2 0 0 0 0 + 34 39 1 0 0 0 0 + 35 40 1 0 0 0 0 + 35 41 1 0 0 0 0 + 36 42 1 0 0 0 0 + 37 43 1 0 0 0 0 + 40 44 1 0 0 0 0 + 41 45 1 0 0 0 0 + 42 46 1 0 0 0 0 + 42 47 1 6 0 0 0 + 44 48 1 0 0 0 0 + 44 49 1 1 0 0 0 + 46 50 1 6 0 0 0 + 48 51 1 1 0 0 0 + 52 50 1 6 0 0 0 + 53 51 1 1 0 0 0 + 52 54 1 0 0 0 0 + 52 55 1 0 0 0 0 + 53 56 1 0 0 0 0 + 53 57 1 0 0 0 0 + 54 58 1 0 0 0 0 + 55 59 2 0 0 0 0 + 56 60 1 0 0 0 0 + 57 61 2 0 0 0 0 + 58 62 1 0 0 0 0 + 58 63 1 1 0 0 0 + 60 64 1 0 0 0 0 + 60 65 1 6 0 0 0 + 62 66 2 0 0 0 0 + 64 67 2 0 0 0 0 + 7 11 1 0 0 0 0 + 12 15 1 0 0 0 0 + 14 19 1 0 0 0 0 + 24 26 1 0 0 0 0 + 43 46 1 0 0 0 0 + 45 48 1 0 0 0 0 + 59 62 1 0 0 0 0 + 61 64 1 0 0 0 0 +M END +> +Compound 20681 + +> +BIO-719 + +> +VINEOMYCIN B2 + +> +Products for Life Science + +> +80928-52-5 + +> +934.98 + +> +' + +> +MFCD09752773 + +$$$$ +Compound 20685 +Actelion Java MolfileCreator 1.0 + + 57 65 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.2264 -1.4844 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.6982 -2.3020 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.9435 -2.4027 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.8743 -3.5222 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.5032 -2.8555 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.9121 -3.5348 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0441 -0.8806 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.6731 -1.6605 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8302 -4.3147 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.3208 -4.9186 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 3.4090 -3.6355 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2895 0.1258 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3334 -0.3396 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.0820 -2.2769 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.2769 -4.7676 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.4530 -5.8872 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7487 -5.0947 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.5412 -2.6417 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.9562 1.4844 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0945 -1.1321 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.4656 0.6793 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4090 -3.7361 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.9058 -6.1388 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.4781 -7.3841 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0569 -5.7991 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.5915 -1.0315 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4531 1.5724 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.7299 -4.4783 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -4.4154 -5.9627 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.5348 -7.5099 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.4215 -6.2897 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7864 -8.0886 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0821 -7.2961 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.2582 0.3271 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1198 2.9310 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.0633 -3.8493 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.8117 -6.2646 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.4278 -8.5037 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -4.5160 -8.5414 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.1196 -7.7489 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.2896 4.2141 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.5224 -4.8557 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -7.0067 -5.3085 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.8243 -7.7615 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1637 -9.8874 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.7802 -9.9629 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.8998 -9.1704 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -8.4156 -5.7614 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -6.8181 -3.7990 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -7.1451 -8.5037 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4593 -10.6674 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.0381 -10.6674 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.9879 -2.8430 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -8.4660 -7.7364 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -8.4911 -6.3904 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -9.7868 -8.4785 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 4 2 1 1 0 0 0 + 3 5 1 0 0 0 0 + 4 6 1 0 0 0 0 + 4 7 1 0 0 0 0 + 4 8 1 0 0 0 0 + 6 9 2 0 0 0 0 + 6 10 1 0 0 0 0 + 7 11 1 0 0 0 0 + 7 12 2 0 0 0 0 + 8 13 1 0 0 0 0 + 9 14 1 0 0 0 0 + 9 15 1 0 0 0 0 + 10 16 2 0 0 0 0 + 11 17 1 0 0 0 0 + 12 18 1 0 0 0 0 + 12 19 1 0 0 0 0 + 13 20 1 0 0 0 0 + 13 21 1 0 0 0 0 + 14 22 1 0 0 0 0 + 15 23 2 0 0 0 0 + 24 16 1 1 0 0 0 + 17 25 1 0 0 0 0 + 18 26 1 0 0 0 0 + 19 27 1 0 0 0 0 + 20 28 2 0 0 0 0 + 23 29 1 0 0 0 0 + 24 30 1 0 0 0 0 + 24 31 1 0 0 0 0 + 24 32 1 0 0 0 0 + 25 33 2 0 0 0 0 + 26 34 2 0 0 0 0 + 27 35 1 0 0 0 0 + 28 36 1 0 0 0 0 + 29 37 1 0 0 0 0 + 30 38 1 0 0 0 0 + 31 39 1 6 0 0 0 + 31 40 1 0 0 0 0 + 32 41 1 0 0 0 0 + 36 42 1 0 0 0 0 + 38 43 1 6 0 0 0 + 38 44 1 0 0 0 0 + 38 45 1 0 0 0 0 + 39 46 1 0 0 0 0 + 40 47 1 0 0 0 0 + 40 48 1 1 0 0 0 + 44 49 2 0 0 0 0 + 44 50 1 0 0 0 0 + 45 51 1 6 0 0 0 + 46 52 1 0 0 0 0 + 48 53 1 0 0 0 0 + 50 54 1 0 0 0 0 + 51 55 1 0 0 0 0 + 55 56 2 0 0 0 0 + 55 57 1 0 0 0 0 + 16 23 1 0 0 0 0 + 17 18 2 0 0 0 0 + 21 27 1 0 0 0 0 + 28 35 1 0 0 0 0 + 30 29 1 1 0 0 0 + 33 34 1 0 0 0 0 + 39 41 1 0 0 0 0 + 40 45 1 0 0 0 0 + 47 52 2 0 0 0 0 +M END +> +Compound 20685 + +> +BIO-802 + +> +VINORELBINE DITARTRATE SALT + +> +Products for Life Science + +> +125317-39-7 + +> +1079.12 + +> +'98% + +> +MFCD07367166 + +$$$$ +Compound 20693 +Actelion Java MolfileCreator 1.0 + + 38 40 0 0 1 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.6991 -1.2863 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.5173 -2.1531 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0832 -0.7410 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.4401 -3.3135 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.5512 -0.5872 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 1.4820 0.6431 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.0133 -4.6837 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.7403 -2.5586 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0053 -0.8389 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8728 0.8808 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5865 1.6358 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.7896 -6.1377 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.5093 -4.5019 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.7543 -1.0486 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.0406 -3.2856 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.4247 0.6012 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 6.6690 -1.5379 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.9713 -7.6058 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.7669 -3.0060 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 8.0252 -0.9507 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3562 -8.9479 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.2069 -3.3415 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.9759 -2.0692 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6285 -9.7309 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.4055 -10.0664 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 8.6264 -5.1031 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.8109 -10.8774 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.6404 -6.5712 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2789 -10.9333 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 10.1084 -6.7249 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 8.2629 -7.9972 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.6770 -11.3807 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.5079 -9.2695 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.9633 -10.6537 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.6683 -10.1643 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 6.4313 -10.2901 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4181 -9.2416 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 4 6 1 0 0 0 0 + 4 7 2 0 0 0 0 + 5 8 1 0 0 0 0 + 5 9 1 1 0 0 0 + 6 10 1 0 0 0 0 + 6 11 1 0 0 0 0 + 7 12 1 0 0 0 0 + 8 13 1 0 0 0 0 + 8 14 1 1 0 0 0 + 9 15 1 0 0 0 0 + 9 16 1 0 0 0 0 + 10 17 2 0 0 0 0 + 10 18 1 0 0 0 0 + 13 19 2 0 0 0 0 + 18 20 1 0 0 0 0 + 18 21 2 0 0 0 0 + 19 22 1 0 0 0 0 + 20 23 2 0 0 0 0 + 21 24 1 0 0 0 0 + 22 25 2 0 0 0 0 + 22 26 1 0 0 0 0 + 23 27 1 0 0 0 0 + 26 28 1 0 0 0 0 + 27 29 1 0 0 0 0 + 28 30 1 0 0 0 0 + 29 31 2 0 0 0 0 + 29 32 1 0 0 0 0 + 30 33 2 0 0 0 0 + 32 34 1 0 0 0 0 + 33 35 1 0 0 0 0 + 34 36 1 6 0 0 0 + 34 37 1 0 0 0 0 + 35 38 1 0 0 0 0 + 11 12 1 0 0 0 0 + 23 24 1 0 0 0 0 + 35 37 2 0 0 0 0 +M END +> +Compound 20693 + +> +BIO-425 + +> +VIRGINIAMYCIN M1 + +> +Products for Life Science + +> +21411-53-0 + +> +525.59 + +> +' + +> +MFCD00869411 + +$$$$ +Compound 20694 +Actelion Java MolfileCreator 1.0 + + 60 65 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0711 1.5058 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3991 1.8497 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5533 1.6837 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6915 2.6441 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.8931 2.3358 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 1.9446 0.2490 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.6520 3.8180 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.6875 1.5296 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.9603 3.3911 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.8893 -0.8181 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.3911 -0.1067 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.9562 3.0828 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -4.1855 5.2290 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1578 2.5137 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 4.6242 4.7428 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2806 -2.2528 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7824 -1.5414 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.2605 3.8417 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.6440 4.9681 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -4.2330 6.7348 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8140 6.2368 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7981 3.8298 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.7271 -2.6085 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.2842 5.3594 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -7.5648 3.1065 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.7943 8.1814 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.5175 7.7189 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1894 6.8178 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.1735 4.4108 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -8.8691 3.8654 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -7.5767 1.6244 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.9168 9.4026 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.1460 8.8691 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.9048 8.2525 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7587 9.0232 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3632 5.9048 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.3474 3.4978 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -10.1733 3.1303 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.2961 0.8893 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -8.8809 0.8893 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9721 10.4935 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.6956 10.2682 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -6.4147 8.0628 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.6204 10.0192 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 4.9088 9.9836 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -10.1852 1.6481 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.2609 10.6832 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.5374 11.5250 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2213 10.6002 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.3793 11.2642 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.6480 11.4776 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.2134 12.1890 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.6244 12.7108 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5414 12.0705 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7981 12.4380 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2370 12.0112 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5372 13.9320 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.9761 13.5052 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.1263 14.4656 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 4 6 1 0 0 0 0 + 4 7 1 0 0 0 0 + 5 8 1 0 0 0 0 + 5 9 1 0 0 0 0 + 6 10 1 0 0 0 0 + 7 11 2 0 0 0 0 + 7 12 1 0 0 0 0 + 8 13 1 0 0 0 0 + 8 14 1 0 0 0 0 + 10 15 2 0 0 0 0 + 10 16 1 0 0 0 0 + 11 17 1 0 0 0 0 + 12 18 2 0 0 0 0 + 13 19 1 0 0 0 0 + 14 20 2 0 0 0 0 + 14 21 1 0 0 0 0 + 16 22 1 0 0 0 0 + 16 23 1 0 0 0 0 + 17 24 2 0 0 0 0 + 19 25 2 0 0 0 0 + 19 26 1 0 0 0 0 + 21 27 1 0 0 0 0 + 22 28 1 0 0 0 0 + 22 29 1 0 0 0 0 + 23 30 1 0 0 0 0 + 26 31 2 0 0 0 0 + 26 32 1 0 0 0 0 + 27 33 1 0 0 0 0 + 27 34 1 0 0 0 0 + 28 35 2 0 0 0 0 + 28 36 1 0 0 0 0 + 29 37 1 0 0 0 0 + 30 38 2 0 0 0 0 + 31 39 1 0 0 0 0 + 32 40 1 0 0 0 0 + 32 41 2 0 0 0 0 + 33 42 2 0 0 0 0 + 33 43 1 0 0 0 0 + 34 44 1 0 0 0 0 + 36 45 1 0 0 0 0 + 36 46 1 0 0 0 0 + 39 47 2 0 0 0 0 + 43 48 1 0 0 0 0 + 43 49 1 0 0 0 0 + 45 50 1 0 0 0 0 + 45 51 1 0 0 0 0 + 46 52 1 0 0 0 0 + 48 53 1 0 0 0 0 + 49 54 1 0 0 0 0 + 50 55 2 0 0 0 0 + 52 56 2 0 0 0 0 + 52 57 1 0 0 0 0 + 56 58 1 0 0 0 0 + 57 59 2 0 0 0 0 + 58 60 2 0 0 0 0 + 18 24 1 0 0 0 0 + 30 37 1 0 0 0 0 + 41 47 1 0 0 0 0 + 48 50 1 0 0 0 0 + 53 54 1 0 0 0 0 + 59 60 1 0 0 0 0 +M END +> +Compound 20694 + +> +BIO-1003 + +> +VIRGINIAMYCIN S1 + +> +Products for Life Science + +> +23152-29-6 + +> +823.9 + +> +' + +> +MFCD00864857 + +$$$$ +Compound 20697 +Actelion Java MolfileCreator 1.0 + + 33 34 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2839 0.7539 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5678 0.0118 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2721 2.2616 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8518 0.7656 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5561 -1.4724 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5561 3.0154 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0353 3.0154 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8400 2.2734 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1357 0.0236 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8400 -2.2145 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5443 4.5232 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3428 2.2734 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1239 3.0272 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1239 -1.4606 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6503 3.0272 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9578 2.2851 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6621 4.5349 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2652 3.0390 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5727 2.2969 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.8802 3.0508 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.1877 2.3087 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.8920 4.5585 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -10.4952 3.0626 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.8026 2.3205 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -13.1101 3.0743 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -14.4176 2.3323 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -13.1219 4.5821 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -15.7251 3.0861 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -17.0325 2.3440 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -18.3400 3.0979 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -18.3518 4.6056 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -19.6475 2.3558 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 2 0 0 0 0 + 3 6 1 0 0 0 0 + 4 7 2 0 0 0 0 + 4 8 1 0 0 0 0 + 5 9 1 0 0 0 0 + 5 10 1 0 0 0 0 + 6 11 2 0 0 0 0 + 7 12 1 0 0 0 0 + 8 13 1 0 0 0 0 + 9 14 2 0 0 0 0 + 10 15 2 0 0 0 0 + 13 16 2 0 0 0 0 + 16 17 1 0 0 0 0 + 16 18 1 0 0 0 0 + 17 19 1 0 0 0 0 + 19 20 1 0 0 0 0 + 20 21 1 0 0 0 0 + 21 22 1 0 0 0 0 + 21 23 1 6 0 0 0 + 22 24 1 0 0 0 0 + 24 25 1 0 0 0 0 + 25 26 1 0 0 0 0 + 26 27 1 0 0 0 0 + 26 28 1 6 0 0 0 + 27 29 1 0 0 0 0 + 29 30 1 0 0 0 0 + 30 31 1 0 0 0 0 + 31 32 1 0 0 0 0 + 31 33 1 0 0 0 0 + 7 9 1 0 0 0 0 + 11 15 1 0 0 0 0 +M END +> +Compound 20697 + +> +BIO-1005 + +> +VITAMIN K1 + +> +Products for Life Science + +> +84-80-0 + +> +450.7 + +> +' + +> +MFCD00214063 + +$$$$ +Compound 20716 +Actelion Java MolfileCreator 1.0 + + 11 12 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3095 -0.7432 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6189 0.0118 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3213 -2.2296 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9284 -0.7314 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6307 -2.9729 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2379 0.0236 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9402 -2.2178 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.9493 -4.4239 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -5.0609 -3.2088 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -4.4475 -4.5655 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 4 6 1 0 0 0 0 + 5 7 2 0 0 0 0 + 5 8 1 0 0 0 0 + 6 9 1 0 0 0 0 + 8 10 1 0 0 0 0 + 9 11 1 0 0 0 0 + 6 8 2 0 0 0 0 + 10 11 2 0 0 0 0 +M END +> +Compound 20716 + +> +BIO-1006 + +> +XANTHINE + +> +Products for Life Science + +> +69-89-6 + +> +152.11 + +> +' + +> +MFCD00078453 + +$$$$ +Compound 20727 +Actelion Java MolfileCreator 1.0 + + 44 47 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 S 0 0 0 0 0 0 0 0 0 0 0 0 + 0.1420 -1.4795 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.1657 1.5031 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.4795 0.1657 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.5031 -0.1420 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.4027 1.0889 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1541 -1.4676 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.7990 2.4737 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9058 0.9469 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.6336 -1.6452 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.3196 2.6394 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6985 3.7046 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -4.5331 -0.4143 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.2609 -3.0063 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -6.0362 -0.5563 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -5.7403 -3.3022 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -3.5152 -4.2964 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -6.9357 0.6746 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.9060 -4.7816 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.5331 -5.3971 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -2.0357 -4.4384 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.2198 -5.5273 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.1599 -3.2075 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.4321 -5.7995 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.2316 -7.0186 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -8.5336 -4.7580 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -1.7162 -1.8819 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.3196 -3.3495 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0473 -5.9415 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.8473 -5.5036 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8995 -0.6510 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.9232 -4.7106 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.6510 -7.3027 -0.0000 S 0 0 0 0 0 0 0 0 0 0 0 0 + -11.1611 -4.7343 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.8592 -6.9949 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.4027 -4.8527 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0121 -6.6754 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7338 -7.9063 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2546 -8.6638 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -12.4749 -5.4799 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.1729 -7.7406 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2785 -3.6217 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0063 -6.2138 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -12.4867 -6.9713 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 1 3 2 0 0 0 0 + 1 4 1 0 0 0 0 + 1 5 1 0 0 0 0 + 5 6 2 0 0 0 0 + 5 7 1 0 0 0 0 + 6 8 1 0 0 0 0 + 6 9 1 0 0 0 0 + 7 10 2 0 0 0 0 + 8 11 2 0 0 0 0 + 8 12 1 0 0 0 0 + 9 13 2 0 0 0 0 + 10 14 1 0 0 0 0 + 13 15 1 0 0 0 0 + 14 16 2 0 0 0 0 + 14 17 1 0 0 0 0 + 15 18 1 0 0 0 0 + 16 19 1 0 0 0 0 + 17 20 1 0 0 0 0 + 17 21 1 0 0 0 0 + 19 22 1 0 0 0 0 + 21 23 2 0 0 0 0 + 21 24 1 0 0 0 0 + 22 25 2 0 0 0 0 + 22 26 1 0 0 0 0 + 23 27 1 0 0 0 0 + 23 28 1 0 0 0 0 + 24 29 2 0 0 0 0 + 26 30 1 0 0 0 0 + 27 31 1 0 0 0 0 + 28 32 2 0 0 0 0 + 29 33 1 0 0 0 0 + 30 34 2 0 0 0 0 + 30 35 1 0 0 0 0 + 32 36 1 0 0 0 0 + 33 37 2 0 0 0 0 + 33 38 2 0 0 0 0 + 33 39 1 0 0 0 0 + 34 40 1 0 0 0 0 + 35 41 2 0 0 0 0 + 36 42 2 0 0 0 0 + 36 43 1 0 0 0 0 + 40 44 2 0 0 0 0 + 10 13 1 0 0 0 0 + 19 20 2 0 0 0 0 + 29 32 1 0 0 0 0 + 41 44 1 0 0 0 0 +M CHG 5 8 1 12 -1 14 1 36 1 43 -1 +M END +> +Compound 20727 + +> +BIO-1007 + +> +XTT SODIUM SALT + +> +Products for Life Science + +> +111072-31-2 + +> +673.53 + +> +' + +> +MFCD00083517 + +$$$$ +Compound 20743 +Actelion Java MolfileCreator 1.0 + + 23 24 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0118 -1.4873 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3221 -2.2310 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2749 -2.2310 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6323 -1.4755 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2631 -3.7183 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5615 -1.4755 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6441 0.0354 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9426 -2.2192 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0472 -4.4620 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5497 -4.4620 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5497 0.0354 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8482 -2.2192 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9544 0.7909 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8364 -3.7065 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2394 0.7909 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9662 2.3018 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1230 -4.4502 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2276 2.3018 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6796 3.0573 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0826 3.0573 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6914 4.5682 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3929 2.3136 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 4 6 2 0 0 0 0 + 4 7 1 0 0 0 0 + 5 8 1 0 0 0 0 + 5 9 1 1 0 0 0 + 6 10 1 0 0 0 0 + 6 11 1 0 0 0 0 + 7 12 1 0 0 0 0 + 7 13 2 0 0 0 0 + 8 14 1 0 0 0 0 + 11 15 2 0 0 0 0 + 12 16 2 0 0 0 0 + 14 17 1 0 0 0 0 + 15 18 1 0 0 0 0 + 16 19 1 0 0 0 0 + 17 20 1 0 0 0 0 + 19 21 1 0 0 0 0 + 20 22 2 0 0 0 0 + 20 23 1 0 0 0 0 + 13 15 1 0 0 0 0 + 21 23 1 0 0 0 0 +M END +> +Compound 20743 + +> +BIO-1009 + +> +ZEARALENONE + +> +Products for Life Science + +> +17924-92-4 + +> +318.37 + +> +' + +> +MFCD00133085 + +$$$$ +Compound 20744 +Actelion Java MolfileCreator 1.0 + + 16 17 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3057 0.7529 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6115 0.0118 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9172 0.7646 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6232 -1.4704 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2230 0.0235 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5287 0.7764 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -7.8344 0.0353 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.8462 -1.4469 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -9.1402 0.7881 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.1519 -2.1880 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.4578 2.2586 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -10.4459 0.0471 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -10.4577 -1.4351 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -10.9517 2.4233 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.5634 1.0587 -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 + 3 4 2 0 0 0 0 + 3 5 1 0 0 0 0 + 4 6 1 0 0 0 0 + 6 7 1 0 0 0 0 + 7 8 1 0 0 0 0 + 8 9 2 0 0 0 0 + 8 10 1 0 0 0 0 + 9 11 1 0 0 0 0 + 10 12 1 0 0 0 0 + 10 13 2 0 0 0 0 + 11 14 2 0 0 0 0 + 12 15 2 0 0 0 0 + 13 16 1 0 0 0 0 + 13 14 1 0 0 0 0 + 15 16 1 0 0 0 0 +M END +> +Compound 20744 + +> +BIO-428 + +> +"ZEATIN, trans ISOMER" + +> +Products for Life Science + +> +1637-39-4 + +> +219.25 + +> +'>99% trans isomer + +> +MFCD00213654 + +$$$$ +Compound 20745 +Actelion Java MolfileCreator 1.0 + + 25 27 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.4974 -0.1415 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.6013 -1.3559 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.5114 0.9786 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -1.8157 -1.5917 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.5188 -2.3463 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0516 -1.6507 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.2166 2.4524 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.0088 0.8371 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.1952 -2.1930 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.3773 -3.8201 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0420 -0.5306 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.9315 3.2070 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -3.5254 3.2070 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.6337 2.2166 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -0.9432 4.7162 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.5372 4.7162 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.2520 5.4708 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -4.8459 5.4708 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -6.1547 4.7280 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.4634 5.4826 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -8.7722 4.7398 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -10.0809 5.4944 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -8.7840 3.2542 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.3897 4.7516 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 2 4 1 1 0 0 0 + 2 5 1 0 0 0 0 + 3 6 1 0 0 0 0 + 3 7 1 1 0 0 0 + 4 8 1 0 0 0 0 + 4 9 1 0 0 0 0 + 5 10 1 6 0 0 0 + 6 11 1 6 0 0 0 + 7 12 1 0 0 0 0 + 8 13 2 0 0 0 0 + 8 14 1 0 0 0 0 + 9 15 2 0 0 0 0 + 13 16 1 0 0 0 0 + 14 17 2 0 0 0 0 + 16 18 2 0 0 0 0 + 17 19 1 0 0 0 0 + 19 20 1 0 0 0 0 + 20 21 1 0 0 0 0 + 21 22 2 0 0 0 0 + 22 23 1 0 0 0 0 + 22 24 1 0 0 0 0 + 23 25 1 0 0 0 0 + 5 6 1 0 0 0 0 + 14 15 1 0 0 0 0 + 17 18 1 0 0 0 0 +M END +> +Compound 20745 + +> +BIO-429 + +> +"ZEATIN RIBOSIDE, trans ISOMER" + +> +Products for Life Science + +> +6025-53-2 + +> +351.37 + +> +'>98% HPLC + +> +MFCD00036809 + +$$$$ +Compound 20751 +Actelion Java MolfileCreator 1.0 + + 31 33 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 S 0 0 0 0 0 0 0 0 0 0 0 0 + 0.7415 -1.2829 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7533 1.3065 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2829 0.7533 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3065 -0.7415 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6129 0.0118 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3182 -2.2245 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9194 -0.7297 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6247 -2.9660 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2258 0.0235 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9312 -2.2127 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5323 -0.7180 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2376 -2.9542 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -7.8388 0.0353 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.1452 -0.7062 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -7.8505 1.5419 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -10.4517 0.0471 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5676 2.2951 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.1570 2.2951 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.7581 -0.6944 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5794 3.8017 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.1688 3.8017 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -13.0646 0.0588 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.7699 -2.1774 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.8858 4.5550 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -13.0764 1.5654 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -14.3711 -0.6827 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -13.0764 -2.9189 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.7935 2.3187 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -14.3828 2.3187 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -14.3828 -2.1657 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 1 3 2 0 0 0 0 + 1 4 1 0 0 0 0 + 1 5 1 0 0 0 0 + 5 6 2 0 0 0 0 + 5 7 1 0 0 0 0 + 6 8 1 0 0 0 0 + 7 9 2 0 0 0 0 + 8 10 1 0 0 0 0 + 8 11 2 0 0 0 0 + 10 12 2 0 0 0 0 + 11 13 1 0 0 0 0 + 12 14 1 0 0 0 0 + 14 15 2 0 0 0 0 + 14 16 1 0 0 0 0 + 15 17 1 0 0 0 0 + 16 18 2 0 0 0 0 + 16 19 1 0 0 0 0 + 17 20 1 0 0 0 0 + 18 21 1 0 0 0 0 + 19 22 2 0 0 0 0 + 20 23 2 0 0 0 0 + 20 24 1 0 0 0 0 + 21 25 2 0 0 0 0 + 23 26 1 0 0 0 0 + 23 27 1 0 0 0 0 + 24 28 2 0 0 0 0 + 26 29 2 0 0 0 0 + 26 30 1 0 0 0 0 + 27 31 2 0 0 0 0 + 9 11 1 0 0 0 0 + 22 25 1 0 0 0 0 + 28 31 1 0 0 0 0 +M END +> +Compound 20751 + +> +BIO-700 + +> +ZINCON + +> +Products for Life Science + +> +62625-22-3 + +> + + +> +' + +> +MFCD00007507 + +$$$$ \ No newline at end of file diff --git a/INCHI-1-TEST/tests/test_unit/fixtures/test_mols_2.sdf b/INCHI-1-TEST/tests/test_unit/fixtures/test_mols_2.sdf new file mode 100644 index 00000000..4e335bd9 --- /dev/null +++ b/INCHI-1-TEST/tests/test_unit/fixtures/test_mols_2.sdf @@ -0,0 +1,320 @@ +Compound 20652 +Actelion Java MolfileCreator 1.0 + +101110 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0153 1.5192 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2737 2.2865 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3351 2.2865 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.9029 0.4297 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2277 3.8057 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3504 3.8057 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8875 -1.0589 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0614 4.5730 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.3147 3.4528 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1766 -1.7955 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5678 -1.7955 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.8518 4.8799 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -4.6344 2.7162 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4656 -1.0282 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1612 -3.2840 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5524 -3.2840 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.9541 3.4835 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -4.6498 1.2277 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4503 0.4911 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4503 -4.0206 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8415 -4.0206 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7673 -4.0206 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.2739 2.7469 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.9695 0.4911 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.3607 0.4911 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1305 1.2583 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7393 1.2583 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4349 -5.5091 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.0870 -3.2533 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7826 -5.5091 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.2892 1.2583 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -8.5936 3.5142 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.3761 -0.9975 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1152 2.7776 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.0283 0.5218 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7240 2.7776 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7240 -6.2457 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1152 -6.2457 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1024 -1.7341 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1024 -6.2457 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5064 -6.2457 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -8.6090 5.0334 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -9.9133 2.7776 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.6958 -1.7341 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4042 3.5449 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8568 3.5449 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.3174 1.2890 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.0130 3.5449 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 7.0130 -5.4784 -0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7086 -7.7342 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2686 -7.6422 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8133 -0.9668 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.4911 -7.7342 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.9287 5.8007 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.2331 3.5449 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.7111 -3.2226 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.3889 5.0641 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7955 5.0641 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 9.6064 0.5524 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 8.3020 2.8083 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.3889 -8.4708 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7801 -8.4708 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8287 -8.4708 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.2484 5.0641 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -12.5528 2.8083 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4221 -3.9592 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -6.0309 -3.9592 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 10.8955 1.3197 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 9.5911 3.5756 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.3735 -9.9594 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.7315 -7.8724 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8415 -9.7292 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -1.0282 -10.0054 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1484 -7.7036 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 10.8801 2.8390 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 12.1845 0.5831 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 10.3277 4.8953 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 8.8238 4.8953 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.6626 -10.6960 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0538 -10.6960 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1484 -10.6960 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4681 -8.4402 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 12.1692 3.6062 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0385 -12.1845 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1637 -12.1845 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4681 -9.9287 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.3275 -12.9211 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7187 -12.9211 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4835 -12.9211 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8747 -12.9211 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.7879 -10.6653 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.3990 -12.1538 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.8032 -12.1538 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4988 -14.4096 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8901 -14.4096 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.3836 -10.6346 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.2098 -15.1462 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5806 -10.1282 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.5831 -9.7906 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -2.2251 -16.6348 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 2 3 2 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 3 6 1 0 0 0 0 + 4 7 2 0 0 0 0 + 5 8 1 0 0 0 0 + 6 9 2 0 0 0 0 + 7 10 1 0 0 0 0 + 8 11 2 0 0 0 0 + 8 12 1 0 0 0 0 + 10 13 1 6 0 0 0 + 10 14 1 0 0 0 0 + 11 15 1 0 0 0 0 + 11 16 1 0 0 0 0 + 12 17 2 0 0 0 0 + 14 18 1 6 0 0 0 + 14 19 1 0 0 0 0 + 20 15 1 6 0 0 0 + 16 21 1 0 0 0 0 + 16 22 2 0 0 0 0 + 17 23 1 0 0 0 0 + 18 24 1 0 0 0 0 + 19 25 2 0 0 0 0 + 19 26 1 0 0 0 0 + 20 27 1 0 0 0 0 + 20 28 1 0 0 0 0 + 21 29 1 0 0 0 0 + 23 30 1 6 0 0 0 + 23 31 1 0 0 0 0 + 24 32 2 0 0 0 0 + 24 33 1 0 0 0 0 + 26 34 1 0 0 0 0 + 27 35 1 0 0 0 0 + 28 36 1 1 0 0 0 + 28 37 1 0 0 0 0 + 29 38 2 0 0 0 0 + 29 39 1 0 0 0 0 + 30 40 1 0 0 0 0 + 31 41 2 0 0 0 0 + 31 42 1 0 0 0 0 + 33 43 1 1 0 0 0 + 33 44 1 0 0 0 0 + 34 45 1 6 0 0 0 + 35 46 1 0 0 0 0 + 35 47 1 0 0 0 0 + 48 36 1 1 0 0 0 + 37 49 1 6 0 0 0 + 38 50 1 0 0 0 0 + 38 51 1 0 0 0 0 + 39 52 2 0 0 0 0 + 40 53 2 0 0 0 0 + 54 42 1 1 0 0 0 + 43 55 1 0 0 0 0 + 44 56 1 0 0 0 0 + 45 57 1 0 0 0 0 + 46 58 1 1 0 0 0 + 47 59 1 0 0 0 0 + 48 60 1 0 0 0 0 + 48 61 1 0 0 0 0 + 51 62 2 0 0 0 0 + 54 63 1 0 0 0 0 + 54 64 1 0 0 0 0 + 56 65 1 0 0 0 0 + 56 66 1 0 0 0 0 + 57 67 2 0 0 0 0 + 57 68 1 0 0 0 0 + 60 69 1 0 0 0 0 + 61 70 1 0 0 0 0 + 62 71 1 0 0 0 0 + 63 72 2 0 0 0 0 + 63 73 1 0 0 0 0 + 64 74 2 0 0 0 0 + 64 75 1 0 0 0 0 + 69 76 1 0 0 0 0 + 69 77 1 6 0 0 0 + 70 78 1 6 0 0 0 + 70 79 1 0 0 0 0 + 71 80 1 1 0 0 0 + 71 81 1 0 0 0 0 + 74 82 1 0 0 0 0 + 75 83 2 0 0 0 0 + 76 84 1 6 0 0 0 + 81 85 1 0 0 0 0 + 82 86 1 0 0 0 0 + 82 87 2 0 0 0 0 + 85 88 2 0 0 0 0 + 85 89 1 0 0 0 0 + 86 90 2 0 0 0 0 + 86 91 1 0 0 0 0 + 87 92 1 0 0 0 0 + 89 93 1 0 0 0 0 + 90 94 1 0 0 0 0 + 90 95 1 0 0 0 0 + 91 96 2 0 0 0 0 + 93 97 1 1 0 0 0 + 95 98 2 0 0 0 0 + 97 99 2 0 0 0 0 + 97100 1 0 0 0 0 + 98101 1 0 0 0 0 + 7 9 1 0 0 0 0 + 17 22 1 0 0 0 0 + 34 40 1 0 0 0 0 + 37 46 1 0 0 0 0 + 52 62 1 0 0 0 0 + 70 76 1 0 0 0 0 + 81 73 1 1 0 0 0 + 83 87 1 0 0 0 0 + 91 93 1 0 0 0 0 + 96 98 1 0 0 0 0 +M END +> +Compound 20652 + +> +BIO-423 + +> +VANCOMYCIN HYDROCHLORIDE + +> +Products for Life Science + +> +1404-93-9 + +> +1485.7 + +> +'93.5% (Vanomycin base) + +> +MFCD03613611 + +$$$$ +caffeine +APtclcactv08142501153D 0 0.00000 0.00000 + + 24 25 0 0 0 0 0 0 0 0999 V2000 + 1.3120 -1.0479 0.0025 N 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2465 -2.1762 0.0031 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7906 0.2081 0.0010 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.9938 0.3838 0.0002 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.9714 1.2767 -0.0001 N 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5339 2.6294 -0.0017 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.4026 1.0989 -0.0001 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.4446 1.9342 -0.0010 N 0 0 0 0 0 0 0 0 0 0 0 0 + -2.5608 1.2510 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.2862 -0.0680 0.0015 N 0 0 0 0 0 0 0 0 0 0 0 0 + -3.2614 -1.1612 0.0029 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.9114 -0.1939 0.0014 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0163 -1.2853 -0.0022 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.4380 -2.4279 -0.0068 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2697 -1.8004 0.0022 H 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0830 -2.7828 0.8938 H 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0821 -2.7846 -0.8862 H 0 0 0 0 0 0 0 0 0 0 0 0 + 2.6223 2.5703 -0.0019 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1.1987 3.1611 -0.8923 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1.1990 3.1632 0.8877 H 0 0 0 0 0 0 0 0 0 0 0 0 + -3.5520 1.6797 -0.0001 H 0 0 0 0 0 0 0 0 0 0 0 0 + -3.5037 -1.4333 -1.0244 H 0 0 0 0 0 0 0 0 0 0 0 0 + -2.8389 -2.0244 0.5173 H 0 0 0 0 0 0 0 0 0 0 0 0 + -4.1672 -0.8395 0.5168 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 3 4 2 0 0 0 0 + 3 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 5 7 1 0 0 0 0 + 7 8 1 0 0 0 0 + 8 9 2 0 0 0 0 + 9 10 1 0 0 0 0 + 10 11 1 0 0 0 0 + 10 12 1 0 0 0 0 + 7 12 2 0 0 0 0 + 12 13 1 0 0 0 0 + 1 13 1 0 0 0 0 + 13 14 2 0 0 0 0 + 2 15 1 0 0 0 0 + 2 16 1 0 0 0 0 + 2 17 1 0 0 0 0 + 6 18 1 0 0 0 0 + 6 19 1 0 0 0 0 + 6 20 1 0 0 0 0 + 9 21 1 0 0 0 0 + 11 22 1 0 0 0 0 + 11 23 1 0 0 0 0 + 11 24 1 0 0 0 0 +M END +> +caffeine + +> +XXXX + +> +CAFFEINE + +> +something something + +> + + +> + + +> +' + +> +??? + +$$$$ \ No newline at end of file diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index 912eed02..abf7ec25 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -1,12 +1,212 @@ #include #include +#include +#include +#include +#include extern "C" { +#include "../../../INCHI-1-SRC/INCHI_BASE/src/ichitime.h" #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichi_io.h" #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichimain.h" } +static char* make_arg(const char* s) { + size_t len = strlen(s) + 1; + char* p = (char*)malloc(len); + memcpy(p, s, len); + return p; +} + +// TEST(ichimain_testing, test_ProcessSingleInputFile) +// { + + +// const char *test_file_2mols = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/test_mol2.sdf"; + +// char tmpl[] = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; +// char *tmpd = mkdtemp(tmpl); +// ASSERT_NE(tmpd, nullptr); + +// std::string dst_path = std::string(tmpd) + "/caffeine.mol"; +// std::ifstream src(test_file_caffeine, std::ios::binary); +// ASSERT_TRUE(src.is_open()); +// std::ofstream dst(dst_path, std::ios::binary); +// ASSERT_TRUE(dst.is_open()); +// dst << src.rdbuf(); +// src.close(); +// dst.close(); + +// int argc = 2; +// char *a0 = make_arg("test_ichimain"); +// char *a1 = make_arg(dst_path.c_str()); +// char* argv[] = { a0, a1 }; + + + +// } + +TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) +{ + + const char *filename_caffeine = "caffeine.mol"; + + const char *path_fixtures = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures"; + char tmpl[] = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; + char *tmpd = mkdtemp(tmpl); + ASSERT_NE(tmpd, nullptr); + + std::string src_path = std::string(path_fixtures) + "/" + filename_caffeine; + std::string dst_path = std::string(tmpd) + "/" + filename_caffeine; + std::ifstream src(src_path, std::ios::binary); + ASSERT_TRUE(src.is_open()); + std::ofstream dst(dst_path, std::ios::binary); + ASSERT_TRUE(dst.is_open()); + dst << src.rdbuf(); + src.close(); + dst.close(); + + int argc = 2; + char *a0 = make_arg("test_ichimain"); + char *a1 = make_arg(dst_path.c_str()); + char* argv[] = { a0, a1 }; + + // int ProcessSingleInputFile(int argc, char* argv[]) + + int result = ProcessSingleInputFile(argc, argv); + + // Assert the expected result + EXPECT_EQ(result, 0); + + free(a0); + free(a1); + + std::string out_txt = dst_path + ".txt"; + std::string out_log = dst_path + ".log"; + std::string out_prb = dst_path + ".prb"; + + struct stat st; + // check existence and non-zero size + ASSERT_EQ(stat(out_txt.c_str(), &st), 0); + EXPECT_GT(st.st_size, 0); + ASSERT_EQ(stat(out_log.c_str(), &st), 0); + EXPECT_GT(st.st_size, 0); + ASSERT_EQ(stat(out_prb.c_str(), &st), 0); + // EXPECT_GT(st.st_size, 0); + EXPECT_EQ(st.st_size, 0); + + std::ifstream txt_in(out_txt); + ASSERT_TRUE(txt_in.is_open()); + std::string line; + std::string found_inchi; + while (std::getline(txt_in, line)) { + // trim leading/trailing whitespace + size_t start = line.find_first_not_of(" \t\r\n"); + if (start == std::string::npos) continue; + size_t end = line.find_last_not_of(" \t\r\n"); + std::string trimmed = line.substr(start, end - start + 1); + if (trimmed.rfind("InChI=", 0) == 0) { + found_inchi = trimmed; + break; + } + } + txt_in.close(); + + const std::string expected_inchi = "InChI=1S/C8H10N4O2/c1-10-4-9-6-5(10)7(13)12(3)8(14)11(6)2/h4H,1-3H3"; + ASSERT_FALSE(found_inchi.empty()); + EXPECT_EQ(found_inchi, expected_inchi); + + // cleanup + unlink(out_txt.c_str()); + unlink(out_log.c_str()); + unlink(out_prb.c_str()); + unlink(dst_path.c_str()); + rmdir(tmpd); +} +TEST(ichimain_testing, test_ProcessSingleInputFile_2mols_sdf) +{ + + const char *filename_2mols = "test_mols_2.sdf"; + + const char *path_fixtures = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures"; + char tmpl[] = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; + char *tmpd = mkdtemp(tmpl); + ASSERT_NE(tmpd, nullptr); + + std::string src_path = std::string(path_fixtures) + "/" + filename_2mols; + std::string dst_path = std::string(tmpd) + "/" + filename_2mols; + std::ifstream src(src_path, std::ios::binary); + ASSERT_TRUE(src.is_open()); + std::ofstream dst(dst_path, std::ios::binary); + ASSERT_TRUE(dst.is_open()); + dst << src.rdbuf(); + src.close(); + dst.close(); + + int argc = 2; + char *a0 = make_arg("test_ichimain"); + char *a1 = make_arg(dst_path.c_str()); + char* argv[] = { a0, a1 }; + + // int ProcessSingleInputFile(int argc, char* argv[]) + + int result = ProcessSingleInputFile(argc, argv); + + // Assert the expected result + EXPECT_EQ(result, 0); + + free(a0); + free(a1); + + std::string out_txt = dst_path + ".txt"; + std::string out_log = dst_path + ".log"; + std::string out_prb = dst_path + ".prb"; + + struct stat st; + // check existence and non-zero size + ASSERT_EQ(stat(out_txt.c_str(), &st), 0); + EXPECT_GT(st.st_size, 0); + ASSERT_EQ(stat(out_log.c_str(), &st), 0); + EXPECT_GT(st.st_size, 0); + ASSERT_EQ(stat(out_prb.c_str(), &st), 0); + // EXPECT_GT(st.st_size, 0); + EXPECT_EQ(st.st_size, 0); + + std::ifstream txt_in(out_txt); + ASSERT_TRUE(txt_in.is_open()); + std::string line; + std::vector found_inchis; + while (std::getline(txt_in, line)) { + // trim leading/trailing whitespace + size_t start = line.find_first_not_of(" \t\r\n"); + if (start == std::string::npos) continue; + size_t end = line.find_last_not_of(" \t\r\n"); + std::string trimmed = line.substr(start, end - start + 1); + if (trimmed.rfind("InChI=", 0) == 0) { + found_inchis.push_back(trimmed); + } + } + txt_in.close(); + + std::vector expected_inchis = { + "InChI=1S/C66H75Cl2N9O24/c1-23(2)12-34(71-5)58(88)76-49-51(83)26-7-10-38(32(67)14-26)97-40-16-28-17-41(55(40)101-65-56(54(86)53(85)42(22-78)99-65)100-44-21-66(4,70)57(87)24(3)96-44)98-39-11-8-27(15-33(39)68)52(84)50-63(93)75-48(64(94)95)31-18-29(79)19-37(81)45(31)30-13-25(6-9-36(30)80)46(60(90)77-50)74-61(91)47(28)73-59(89)35(20-43(69)82)72-62(49)92/h6-11,13-19,23-24,34-35,42,44,46-54,56-57,65,71,78-81,83-87H,12,20-22,70H2,1-5H3,(H2,69,82)(H,72,92)(H,73,89)(H,74,91)(H,75,93)(H,76,88)(H,77,90)(H,94,95)/t24-,34+,35-,42?,44-,46+,47+,48-,49+,50-,51+,52+,53+,54-,56+,57+,65-,66-/m0/s1", + "InChI=1S/C8H10N4O2/c1-10-4-9-6-5(10)7(13)12(3)8(14)11(6)2/h4H,1-3H3" + }; + + ASSERT_EQ(found_inchis.size(), expected_inchis.size()); + for (size_t i = 0; i < expected_inchis.size(); ++i) { + EXPECT_EQ(found_inchis[i], expected_inchis[i]); + } + + // cleanup + unlink(out_txt.c_str()); + unlink(out_log.c_str()); + unlink(out_prb.c_str()); + unlink(dst_path.c_str()); + rmdir(tmpd); +} + TEST(ichimain_testing, test_GetTheNextRecordOfInputFile) { @@ -86,24 +286,41 @@ TEST(ichimain_testing, test_GetTheNextRecordOfInputFile) // long *num_err, // int output_error_inchi ); - tagINCHI_CLOCK *ic; - STRUCT_DATA *sd; - INPUT_PARMS *ip; + INCHI_CLOCK ic = {}; + memset(&ic, 0, sizeof(ic)); + + STRUCT_DATA *sd = new STRUCT_DATA; + INPUT_PARMS *ip = new INPUT_PARMS; + char *szTitle; INCHI_IOSTREAM *inp_file; - INCHI_IOSTREAM *plog; - INCHI_IOSTREAM *pout; - INCHI_IOSTREAM *pprb; + INCHI_IOSTREAM *plog = new INCHI_IOSTREAM; + INCHI_IOSTREAM *pout = new INCHI_IOSTREAM; + INCHI_IOSTREAM *pprb = new INCHI_IOSTREAM; ORIG_ATOM_DATA orig_at_data = {}; - long *num_inp; - STRUCT_FPTRS *pStructPtrs; - int *nRet; - int *have_err_in_GetOneStructure; + long *num_inp = new long(0); + + STRUCT_FPTRS *pStructPtrs = NULL; + + int *nRet = 0; + int *have_err_in_GetOneStructure = 0; long *num_err; int output_error_inchi; + + memset(ip, 0, sizeof(*ip)); + ip->last_struct_number = 1; + ip->nInputType = INPUT_MOLFILE; + + inchi_ios_init(pout, INCHI_IOS_TYPE_STRING, nullptr); + inchi_ios_init(plog, INCHI_IOS_TYPE_STRING, stdout); + inchi_ios_init(pprb, INCHI_IOS_TYPE_STRING, nullptr); + + // PrintInputParms(plog, ip); + // inchi_ios_flush2(plog, stderr); + // int ret = GetTheNextRecordOfInputFile( - // ic, + // &ic, // sd, // ip, // szTitle, @@ -119,7 +336,7 @@ TEST(ichimain_testing, test_GetTheNextRecordOfInputFile) // num_err, // output_error_inchi); - // EXPECT_EQ(ret, 18); + // EXPECT_EQ(ret, DO_NEXT_STEP); inchi_ios_free_str(&input_stream); FreeOrigAtData(&orig_at_data); From a64a361ce8a0c0459811ece413cd8579a9efa06a Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 8 Dec 2025 15:10:53 +0000 Subject: [PATCH 04/69] Added prototype for ProcessMultipleInputFiles --- .../tests/test_unit/fixtures/naloxon.mol | 99 +++++++++++++++++++ .../tests/test_unit/test_ichimain.cpp | 26 +---- _deps/googletest-src | 1 + 3 files changed, 105 insertions(+), 21 deletions(-) create mode 100644 INCHI-1-TEST/tests/test_unit/fixtures/naloxon.mol create mode 160000 _deps/googletest-src diff --git a/INCHI-1-TEST/tests/test_unit/fixtures/naloxon.mol b/INCHI-1-TEST/tests/test_unit/fixtures/naloxon.mol new file mode 100644 index 00000000..6768159d --- /dev/null +++ b/INCHI-1-TEST/tests/test_unit/fixtures/naloxon.mol @@ -0,0 +1,99 @@ +naloxon + -OEChem-12082509532D + + 45 49 0 1 0 0 0 0 0999 V2000 + 2.2314 -0.2572 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.3794 -1.7611 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0000 -2.7122 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0000 2.0922 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1607 -1.2611 0.0000 N 0 0 3 0 0 0 0 0 0 0 0 0 + 3.6897 -0.7855 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 + 4.5133 -1.2611 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 + 5.3370 -0.7855 0.0000 C 0 0 3 0 0 0 0 0 0 0 0 0 + 2.8660 -1.2611 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 + 4.2392 -0.0881 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.6897 0.1655 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.5133 -2.2122 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.3370 0.1655 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5918 -0.0881 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.5133 0.6411 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.6897 -2.6877 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.8660 -2.2122 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.8660 0.6411 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.8418 -1.9932 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.5133 1.5922 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.8660 1.5922 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.6897 2.0677 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.8164 -1.7694 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.4976 -2.5015 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.8739 -0.4755 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0496 -1.4975 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 4.3760 0.5166 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 3.6795 0.1787 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 4.7254 -2.7948 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1239 -2.1045 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 5.9476 0.0579 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5490 0.7481 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1840 0.0957 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 5.4989 0.5249 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2912 -3.1626 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 4.0882 -3.1626 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 5.3794 -2.3811 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 6.3215 -2.3303 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 7.0834 -2.5642 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0503 1.9022 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 3.6897 2.6877 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 7.9984 -1.1766 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0000 2.7122 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 8.3157 -3.0942 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 9.1019 -2.3627 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1 9 1 0 0 0 0 + 1 18 1 0 0 0 0 + 7 2 1 1 0 0 0 + 2 37 1 0 0 0 0 + 3 17 2 0 0 0 0 + 4 21 1 0 0 0 0 + 4 43 1 0 0 0 0 + 5 8 1 0 0 0 0 + 5 14 1 0 0 0 0 + 5 19 1 0 0 0 0 + 6 7 1 0 0 0 0 + 6 9 1 0 0 0 0 + 6 10 1 1 0 0 0 + 6 11 1 0 0 0 0 + 7 8 1 0 0 0 0 + 7 12 1 0 0 0 0 + 8 13 1 0 0 0 0 + 8 25 1 0 0 0 0 + 9 17 1 0 0 0 0 + 9 26 1 1 0 0 0 + 10 14 1 0 0 0 0 + 10 27 1 0 0 0 0 + 10 28 1 0 0 0 0 + 11 15 2 0 0 0 0 + 11 18 1 0 0 0 0 + 12 16 1 0 0 0 0 + 12 29 1 0 0 0 0 + 12 30 1 0 0 0 0 + 13 15 1 0 0 0 0 + 13 31 1 0 0 0 0 + 13 32 1 0 0 0 0 + 14 33 1 0 0 0 0 + 14 34 1 0 0 0 0 + 15 20 1 0 0 0 0 + 16 17 1 0 0 0 0 + 16 35 1 0 0 0 0 + 16 36 1 0 0 0 0 + 18 21 2 0 0 0 0 + 19 23 1 0 0 0 0 + 19 38 1 0 0 0 0 + 19 39 1 0 0 0 0 + 20 22 2 0 0 0 0 + 20 40 1 0 0 0 0 + 21 22 1 0 0 0 0 + 22 41 1 0 0 0 0 + 23 24 2 0 0 0 0 + 23 42 1 0 0 0 0 + 24 44 1 0 0 0 0 + 24 45 1 0 0 0 0 +M END \ No newline at end of file diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index abf7ec25..8295f68f 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -19,33 +19,17 @@ static char* make_arg(const char* s) { return p; } -// TEST(ichimain_testing, test_ProcessSingleInputFile) -// { - - -// const char *test_file_2mols = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/test_mol2.sdf"; +TEST(ichimain_testing, test_ProcessMultipleInputFiles) +{ -// char tmpl[] = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; -// char *tmpd = mkdtemp(tmpl); -// ASSERT_NE(tmpd, nullptr); + const char *test_file_mol1 = "caffeine.mol"; + const char *test_file_mol2 = "naloxon.mol"; -// std::string dst_path = std::string(tmpd) + "/caffeine.mol"; -// std::ifstream src(test_file_caffeine, std::ios::binary); -// ASSERT_TRUE(src.is_open()); -// std::ofstream dst(dst_path, std::ios::binary); -// ASSERT_TRUE(dst.is_open()); -// dst << src.rdbuf(); -// src.close(); -// dst.close(); -// int argc = 2; -// char *a0 = make_arg("test_ichimain"); -// char *a1 = make_arg(dst_path.c_str()); -// char* argv[] = { a0, a1 }; -// } +} TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) { diff --git a/_deps/googletest-src b/_deps/googletest-src new file mode 160000 index 00000000..52eb8108 --- /dev/null +++ b/_deps/googletest-src @@ -0,0 +1 @@ +Subproject commit 52eb8108c5bdec04579160ae17225d66034bd723 From b31865bd2214bed5f61d23ea4d0e8616e3f9d196 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Tue, 9 Dec 2025 10:54:52 +0000 Subject: [PATCH 05/69] added missing free --- INCHI-1-SRC/INCHI_BASE/src/ichimake.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichimake.c b/INCHI-1-SRC/INCHI_BASE/src/ichimake.c index 80652e13..e478e55b 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichimake.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichimake.c @@ -4550,6 +4550,10 @@ int Create_INChI(CANON_GLOBALS* pCG, { inchi_free(t_group_info->nIsotopicEndpointAtomNumber); } + if (t_group_info->t_group) + { + inchi_free(t_group_info->t_group); + } memset(t_group_info, 0, sizeof(*t_group_info)); /* djb-rwth: memset_s C11/Annex K variant? */ } } From 72efe601089a31ff39b8c649aecf474a49a5fb8e Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Tue, 9 Dec 2025 13:27:51 +0000 Subject: [PATCH 06/69] Added unit tests for CalcAndPrintINCHIAndINCHIKEY, ProcessMultipleInputFiles --- CMakeLists.txt | 4 +- .../tests/test_unit/test_ichimain.cpp | 458 +++++++++++++++--- .../tests/test_unit/test_permutation_util.cpp | 7 + 3 files changed, 403 insertions(+), 66 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b324705..737bfafd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,8 +6,8 @@ set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 11) set(CMAKE_POSITION_INDEPENDENT_CODE ON) -# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") -# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") include(FetchContent) FetchContent_Declare( diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index 8295f68f..83fea5e3 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -8,6 +8,7 @@ extern "C" { #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichitime.h" +#include "../../../INCHI-1-SRC/INCHI_BASE/src/ichicant.h" #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichi_io.h" #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichimain.h" } @@ -19,16 +20,344 @@ static char* make_arg(const char* s) { return p; } -TEST(ichimain_testing, test_ProcessMultipleInputFiles) +char *read_inchi_from_file(const char *filename) { + + std::ifstream txt_in(filename); + txt_in.is_open(); + std::string line; + std::string found_inchi; + while (std::getline(txt_in, line)) { + // trim leading/trailing whitespace + size_t start = line.find_first_not_of(" \t\r\n"); + if (start == std::string::npos) continue; + size_t end = line.find_last_not_of(" \t\r\n"); + std::string trimmed = line.substr(start, end - start + 1); + if (trimmed.rfind("InChI=", 0) == 0) { + found_inchi = trimmed; + break; + } + } + txt_in.close(); + + return make_arg(found_inchi.c_str()); +} + +TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { + + + INCHI_IOSTREAM input_stream; + + const char *molblock = + "enhanc_stereo1 \n" + " ACD/LABS08242216132D \n" + " \n" + " 0 0 0 0 0 0 0 0 0 0999 V3000 \n" + "M V30 BEGIN CTAB \n" + "M V30 COUNTS 18 17 0 0 1 \n" + "M V30 BEGIN ATOM \n" + "M V30 1 C 3424.1946 -1936.7935 0 0 \n" + "M V30 2 C 3352.3145 -1895.2935 0 0 \n" + "M V30 3 C 3280.4346 -1936.7935 0 0 \n" + "M V30 4 C 3208.5542 -1895.2935 0 0 \n" + "M V30 5 C 3136.6743 -1936.7935 0 0 \n" + "M V30 6 C 3064.7944 -1895.2935 0 0 \n" + "M V30 7 Br 3136.6743 -2019.7935 0 0 \n" + "M V30 8 Cl 3208.5542 -1812.2935 0 0 \n" + "M V30 9 Cl 3280.4346 -2019.7935 0 0 \n" + "M V30 10 Cl 3352.3145 -1812.2935 0 0 \n" + "M V30 11 Cl 3424.1946 -2019.7935 0 0 \n" + "M V30 12 C 3496.075 -1895.2935 0 0 \n" + "M V30 13 C 3567.9548 -1936.7942 0 0 \n" + "M V30 14 C 3639.835 -1895.2944 0 0 \n" + "M V30 15 C 3711.7148 -1936.7942 0 0 \n" + "M V30 16 Cl 3639.835 -1812.2944 0 0 \n" + "M V30 17 Cl 3567.9548 -2019.7942 0 0 \n" + "M V30 18 Cl 3496.075 -1812.2937 0 0 \n" + "M V30 END ATOM \n" + "M V30 BEGIN BOND \n" + "M V30 1 1 1 2 \n" + "M V30 2 1 1 11 CFG=3 \n" + "M V30 3 1 1 12 \n" + "M V30 4 1 2 3 \n" + "M V30 5 1 2 10 CFG=1 \n" + "M V30 6 1 3 4 \n" + "M V30 7 1 3 9 CFG=1 \n" + "M V30 8 1 4 5 \n" + "M V30 9 1 4 8 CFG=1 \n" + "M V30 10 1 5 6 \n" + "M V30 11 1 5 7 CFG=1 \n" + "M V30 12 1 12 13 \n" + "M V30 13 1 12 18 CFG=3 \n" + "M V30 14 1 13 14 \n" + "M V30 15 1 13 17 CFG=1 \n" + "M V30 16 1 14 15 \n" + "M V30 17 1 14 16 CFG=1 \n" + "M V30 END BOND \n" + "M V30 BEGIN COLLECTION \n" + "M V30 MDLV30/STERAC2 ATOMS=(1 1) \n" + "M V30 MDLV30/STERAC1 ATOMS=(2 2 3) \n" + "M V30 MDLV30/STEABS ATOMS=(2 4 5) \n" + "M V30 MDLV30/STEREL1 ATOMS=(2 12 13) \n" + "M V30 MDLV30/STEREL2 ATOMS=(1 14) \n" + "M V30 END COLLECTION \n" + "M V30 END CTAB \n" + "M END \n"; + + inchi_ios_init(&input_stream, INCHI_IOS_TYPE_STRING, nullptr); + inchi_ios_print_nodisplay(&input_stream, molblock); + + // int GetTheNextRecordOfInputFile( struct tagINCHI_CLOCK *ic, + // STRUCT_DATA *sd, INPUT_PARMS *ip, + // char *szTitle, + // INCHI_IOSTREAM *inp_file, + // INCHI_IOSTREAM *plog, + // INCHI_IOSTREAM *pout, + // INCHI_IOSTREAM *pprb, + // ORIG_ATOM_DATA *orig_inp_data, + // long *num_inp, + // STRUCT_FPTRS *pStructPtrs, + // int *nRet, + // int *have_err_in_GetOneStructure, + // long *num_err, + // int output_error_inchi ); + + INCHI_CLOCK ic = {}; + memset(&ic, 0, sizeof(ic)); + + STRUCT_DATA *sd = new STRUCT_DATA; + // sd->ulStructTime = 0; + INPUT_PARMS *ip = new INPUT_PARMS; + + char *szTitle; + INCHI_IOSTREAM *inp_file; + INCHI_IOSTREAM *plog = new INCHI_IOSTREAM; + INCHI_IOSTREAM *pout = new INCHI_IOSTREAM; + INCHI_IOSTREAM *pprb = new INCHI_IOSTREAM; + ORIG_ATOM_DATA orig_at_data = {}; + long *num_inp = new long(0); + + STRUCT_FPTRS *pStructPtrs = nullptr; + + int nRet = 0; + int have_err_in_GetOneStructure = 0; + long num_err = 0; + int output_error_inchi; + + + memset(ip, 0, sizeof(*ip)); + ip->last_struct_number = 1; + ip->nInputType = INPUT_MOLFILE; + + inchi_ios_init(pout, INCHI_IOS_TYPE_STRING, nullptr); + inchi_ios_init(plog, INCHI_IOS_TYPE_STRING, stdout); + inchi_ios_init(pprb, INCHI_IOS_TYPE_STRING, nullptr); + + // PrintInputParms(plog, ip); + inchi_ios_flush2(plog, stderr); + + int ret = GetTheNextRecordOfInputFile( + &ic, + sd, + ip, + szTitle, + &input_stream, + plog, + pout, + pprb, + &orig_at_data, + num_inp, + pStructPtrs, + &nRet, + &have_err_in_GetOneStructure, + &num_err, + output_error_inchi); + + EXPECT_EQ(ret, DO_NEXT_STEP); + + CANON_GLOBALS CG = {}; + // STRUCT_DATA* sd; + // INPUT_PARMS* ip; + // char* szTitle; + PINChI2* pINChI[INCHI_NUM]; + PINChI_Aux2* pINChI_Aux[INCHI_NUM]; + // INCHI_IOSTREAM* inp_file; + // INCHI_IOSTREAM* plog; + // INCHI_IOSTREAM* pout; + // INCHI_IOSTREAM* pprb; + // ORIG_ATOM_DATA* orig_inp_data; + ORIG_ATOM_DATA prep_inp_data = {}; + // long* num_inp; + // STRUCT_FPTRS* pStructPtrs; + // int* nRet; + // int have_err_in_GetOneStructure; + // long* num_err; + // int output_error_inchi; + INCHI_IOS_STRING* strbuf; + unsigned long pulTotalProcessingTime = 0; + char* pLF; + char* pTAB; + char* ikey; + int silent; + + set_line_separators(ip->bINChIOutputOptions, &pLF, &pTAB); + + ret = CalcAndPrintINCHIAndINCHIKEY( + &ic, + &CG, + sd, + ip, + szTitle, + pINChI, + pINChI_Aux, + &input_stream, + plog, + pout, + pprb, + &orig_at_data, + &prep_inp_data, + num_inp, + pStructPtrs, + &nRet, + have_err_in_GetOneStructure, + &num_err, + output_error_inchi, + strbuf, + &pulTotalProcessingTime, + pLF, + pTAB, + ikey, + silent + ); + + + + + inchi_ios_free_str(&input_stream); + FreeOrigAtData(&orig_at_data); + + for (int i = 0; i < MAX_NUM_PATHS; i++) + { + if (ip->path[i]) + { + inchi_free((void*)ip->path[i]); /* cast deliberately discards 'const' qualifier */ + ip->path[i] = NULL; + } + } + delete ip; + delete sd; + + delete plog; + delete pout; + delete pprb; + delete num_inp; + + + // int CalcAndPrintINCHIAndINCHIKEY(struct tagINCHI_CLOCK* ic, + // CANON_GLOBALS* CG, + // STRUCT_DATA* sd, + // INPUT_PARMS* ip, + // char* szTitle, + // PINChI2* pINChI[INCHI_NUM], + // PINChI_Aux2* pINChI_Aux[INCHI_NUM], + // INCHI_IOSTREAM* inp_file, + // INCHI_IOSTREAM* plog, + // INCHI_IOSTREAM* pout, + // INCHI_IOSTREAM* pprb, + // ORIG_ATOM_DATA* orig_inp_data, + // ORIG_ATOM_DATA* prep_inp_data, + // long* num_inp, + // STRUCT_FPTRS* pStructPtrs, + // int* nRet, + // int have_err_in_GetOneStructure, + // long* num_err, + // int output_error_inchi, + // INCHI_IOS_STRING* strbuf, + // unsigned long* pulTotalProcessingTime, + // char* pLF, + // char* pTAB, + // char* ikey, + // int silent) + +} + +TEST(ichimain_testing, test_ProcessMultipleInputFiles_2mol_files) { - const char *test_file_mol1 = "caffeine.mol"; - const char *test_file_mol2 = "naloxon.mol"; + std::vector expected_inchis = { + "InChI=1S/C19H21NO4/c1-2-8-20-9-7-18-15-11-3-4-12(21)16(15)24-17(18)13(22)5-6-19(18,23)14(20)10-11/h2-4,14,17,21,23H,1,5-10H2/t14?,17-,18-,19+/m0/s1", + "InChI=1S/C8H10N4O2/c1-10-4-9-6-5(10)7(13)12(3)8(14)11(6)2/h4H,1-3H3" + }; + std::vector input_mols = { + "naloxon.mol", + "caffeine.mol" + }; + + const char *path_fixtures = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures"; + + char tmpl[] = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; + char *tmpd = mkdtemp(tmpl); + ASSERT_NE(tmpd, nullptr); + + std::vector dist_paths; + for (auto cur_filename : input_mols) { + std::string src_path = std::string(path_fixtures) + "/" + cur_filename; + std::string dst_path = std::string(tmpd) + "/" + cur_filename; + std::ifstream src(src_path, std::ios::binary); + ASSERT_TRUE(src.is_open()); + std::ofstream dst(dst_path, std::ios::binary); + ASSERT_TRUE(dst.is_open()); + dst << src.rdbuf(); + src.close(); + dst.close(); + + dist_paths.push_back(dst_path); + } + int argc = input_mols.size() + 2; + + char *inchi_filename = make_arg("test_ichimain"); + + std::vector argv_vec; + argv_vec.push_back(inchi_filename); + for (const auto &p : dist_paths) { + argv_vec.push_back(make_arg(p.c_str())); + } + argv_vec.push_back(make_arg("-AMI")); + char** argv = argv_vec.data(); + //int ProcessMultipleInputFiles(int argc, char* argv[]) + int ret = ProcessMultipleInputFiles(argc, argv); + // Assert the expected result + ASSERT_EQ(ret, 0); + + for (int i = 0; i < expected_inchis.size(); i++) { + std::string out_txt = dist_paths[i] + ".txt"; + char *inchi = read_inchi_from_file(out_txt.c_str()); + ASSERT_STREQ(inchi, expected_inchis[i].c_str()); + free(inchi); + } + + // Clean up + + for (auto p : dist_paths) { + + std::string out_txt = p + ".txt"; + std::string out_log = p + ".log"; + std::string out_prb = p + ".prb"; + + remove(p.c_str()); + remove(out_txt.c_str()); + remove(out_log.c_str()); + remove(out_prb.c_str()); + } + rmdir(tmpd); + + for (auto p : argv_vec) { + free(p); + } } TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) @@ -52,9 +381,9 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) dst.close(); int argc = 2; - char *a0 = make_arg("test_ichimain"); - char *a1 = make_arg(dst_path.c_str()); - char* argv[] = { a0, a1 }; + char *inchi_filename = make_arg("test_ichimain"); + char *input_file = make_arg(dst_path.c_str()); + char* argv[] = { inchi_filename, input_file }; // int ProcessSingleInputFile(int argc, char* argv[]) @@ -63,8 +392,8 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) // Assert the expected result EXPECT_EQ(result, 0); - free(a0); - free(a1); + free(inchi_filename); + free(input_file); std::string out_txt = dst_path + ".txt"; std::string out_log = dst_path + ".log"; @@ -77,35 +406,20 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) ASSERT_EQ(stat(out_log.c_str(), &st), 0); EXPECT_GT(st.st_size, 0); ASSERT_EQ(stat(out_prb.c_str(), &st), 0); - // EXPECT_GT(st.st_size, 0); EXPECT_EQ(st.st_size, 0); - std::ifstream txt_in(out_txt); - ASSERT_TRUE(txt_in.is_open()); - std::string line; - std::string found_inchi; - while (std::getline(txt_in, line)) { - // trim leading/trailing whitespace - size_t start = line.find_first_not_of(" \t\r\n"); - if (start == std::string::npos) continue; - size_t end = line.find_last_not_of(" \t\r\n"); - std::string trimmed = line.substr(start, end - start + 1); - if (trimmed.rfind("InChI=", 0) == 0) { - found_inchi = trimmed; - break; - } - } - txt_in.close(); + char *found_inchi = read_inchi_from_file(out_txt.c_str()); + std::string expected_inchi = "InChI=1S/C8H10N4O2/c1-10-4-9-6-5(10)7(13)12(3)8(14)11(6)2/h4H,1-3H3"; - const std::string expected_inchi = "InChI=1S/C8H10N4O2/c1-10-4-9-6-5(10)7(13)12(3)8(14)11(6)2/h4H,1-3H3"; - ASSERT_FALSE(found_inchi.empty()); + ASSERT_NE(found_inchi, nullptr); EXPECT_EQ(found_inchi, expected_inchi); // cleanup - unlink(out_txt.c_str()); - unlink(out_log.c_str()); - unlink(out_prb.c_str()); - unlink(dst_path.c_str()); + free(found_inchi); + remove(out_txt.c_str()); + remove(out_log.c_str()); + remove(out_prb.c_str()); + remove(dst_path.c_str()); rmdir(tmpd); } TEST(ichimain_testing, test_ProcessSingleInputFile_2mols_sdf) @@ -129,9 +443,9 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_2mols_sdf) dst.close(); int argc = 2; - char *a0 = make_arg("test_ichimain"); - char *a1 = make_arg(dst_path.c_str()); - char* argv[] = { a0, a1 }; + char *inchi_filename = make_arg("test_ichimain"); + char *input_file = make_arg(dst_path.c_str()); + char* argv[] = { inchi_filename, input_file }; // int ProcessSingleInputFile(int argc, char* argv[]) @@ -140,8 +454,8 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_2mols_sdf) // Assert the expected result EXPECT_EQ(result, 0); - free(a0); - free(a1); + free(inchi_filename); + free(input_file); std::string out_txt = dst_path + ".txt"; std::string out_log = dst_path + ".log"; @@ -184,10 +498,10 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_2mols_sdf) } // cleanup - unlink(out_txt.c_str()); - unlink(out_log.c_str()); - unlink(out_prb.c_str()); - unlink(dst_path.c_str()); + remove(out_txt.c_str()); + remove(out_log.c_str()); + remove(out_prb.c_str()); + remove(dst_path.c_str()); rmdir(tmpd); } @@ -277,17 +591,17 @@ TEST(ichimain_testing, test_GetTheNextRecordOfInputFile) INPUT_PARMS *ip = new INPUT_PARMS; char *szTitle; - INCHI_IOSTREAM *inp_file; + // INCHI_IOSTREAM *inp_file; INCHI_IOSTREAM *plog = new INCHI_IOSTREAM; INCHI_IOSTREAM *pout = new INCHI_IOSTREAM; INCHI_IOSTREAM *pprb = new INCHI_IOSTREAM; ORIG_ATOM_DATA orig_at_data = {}; long *num_inp = new long(0); - STRUCT_FPTRS *pStructPtrs = NULL; + STRUCT_FPTRS *pStructPtrs = nullptr; - int *nRet = 0; - int *have_err_in_GetOneStructure = 0; + int nRet = 0; + int have_err_in_GetOneStructure = 0; long *num_err; int output_error_inchi; @@ -301,27 +615,43 @@ TEST(ichimain_testing, test_GetTheNextRecordOfInputFile) inchi_ios_init(pprb, INCHI_IOS_TYPE_STRING, nullptr); // PrintInputParms(plog, ip); - // inchi_ios_flush2(plog, stderr); - - // int ret = GetTheNextRecordOfInputFile( - // &ic, - // sd, - // ip, - // szTitle, - // &input_stream, - // plog, - // pout, - // pprb, - // &orig_at_data, - // num_inp, - // pStructPtrs, - // nRet, - // have_err_in_GetOneStructure, - // num_err, - // output_error_inchi); - - // EXPECT_EQ(ret, DO_NEXT_STEP); + inchi_ios_flush2(plog, stderr); + + int ret = GetTheNextRecordOfInputFile( + &ic, + sd, + ip, + szTitle, + &input_stream, + plog, + pout, + pprb, + &orig_at_data, + num_inp, + pStructPtrs, + &nRet, + &have_err_in_GetOneStructure, + num_err, + output_error_inchi); + + EXPECT_EQ(ret, DO_NEXT_STEP); inchi_ios_free_str(&input_stream); FreeOrigAtData(&orig_at_data); + + for (int i = 0; i < MAX_NUM_PATHS; i++) + { + if (ip->path[i]) + { + inchi_free((void*)ip->path[i]); /* cast deliberately discards 'const' qualifier */ + ip->path[i] = NULL; + } + } + delete ip; + delete sd; + + delete plog; + delete pout; + delete pprb; + delete num_inp; } diff --git a/INCHI-1-TEST/tests/test_unit/test_permutation_util.cpp b/INCHI-1-TEST/tests/test_unit/test_permutation_util.cpp index 174bf847..ad98e559 100644 --- a/INCHI-1-TEST/tests/test_unit/test_permutation_util.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_permutation_util.cpp @@ -107,4 +107,11 @@ TEST(permutation_util_testing, test_OrigAtData_Permute) EXPECT_STREQ(molblock, output_file->s.pStr); EXPECT_STRNE(output_file->s.pStr, permuted_output_file->s.pStr); + + inchi_ios_free_str(&input_stream); + inchi_ios_free_str(&output_stream); + inchi_ios_free_str(&permuted_output_stream); + + FreeOrigAtData(&atom_data); + FreeOrigAtData(&permuted_atom_data); } From 1a453727779d654f953d4cae9c6813fc8e40aa3b Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Wed, 10 Dec 2025 14:40:19 +0000 Subject: [PATCH 07/69] Added unit test flags for initializing input params --- .../tests/test_unit/test_ichimain.cpp | 92 +++++++++++++------ 1 file changed, 62 insertions(+), 30 deletions(-) diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index 83fea5e3..7b8b77f9 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -48,9 +48,9 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { INCHI_IOSTREAM input_stream; const char *molblock = - "enhanc_stereo1 \n" + "enhanc_stereo1 \n" " ACD/LABS08242216132D \n" - " \n" + " \n" " 0 0 0 0 0 0 0 0 0 0999 V3000 \n" "M V30 BEGIN CTAB \n" "M V30 COUNTS 18 17 0 0 1 \n" @@ -147,6 +147,23 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { memset(ip, 0, sizeof(*ip)); ip->last_struct_number = 1; ip->nInputType = INPUT_MOLFILE; + ip->bINChIOutputOptions = INCHI_OUT_PLAIN_TEXT; + // ip->bINChIOutputOptions2 = INCHI_OUT_PLAIN_TEXT; + // ip->nMode = REQ_MODE_TAUT; // REQ_MODE_BASIC; + // ip->bTautFlags |= (TG_FLAG_DISCONNECT_COORD | TG_FLAG_RECONNECT_COORD); + // ip->nMode |= (REQ_MODE_BASIC | REQ_MODE_TAUT | REQ_MODE_STEREO | REQ_MODE_ISO_STEREO | REQ_MODE_ISO); + + int bReleaseVersion = bRELEASE_VERSION; + unsigned long ulDisplTime = 0; /* infinite, milliseconds */ + unsigned long ulTotalProcessingTime = 0; + + int argc = 0; + char *argv[1]; + char *szSdfDataValue = nullptr; + + ReadCommandLineParms(argc, (const char**)argv, ip, + szSdfDataValue, &ulDisplTime, + bReleaseVersion, plog); inchi_ios_init(pout, INCHI_IOS_TYPE_STRING, nullptr); inchi_ios_init(plog, INCHI_IOS_TYPE_STRING, stdout); @@ -174,6 +191,9 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { EXPECT_EQ(ret, DO_NEXT_STEP); + EXPECT_EQ(orig_at_data.num_inp_atoms, 18); + EXPECT_EQ(orig_at_data.num_inp_bonds, 17); + CANON_GLOBALS CG = {}; // STRUCT_DATA* sd; // INPUT_PARMS* ip; @@ -192,7 +212,10 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { // int have_err_in_GetOneStructure; // long* num_err; // int output_error_inchi; - INCHI_IOS_STRING* strbuf; + INCHI_IOS_STRING *strbuf = new INCHI_IOS_STRING; + memset(strbuf, 0, sizeof(*strbuf)); + inchi_strbuf_init(strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + unsigned long pulTotalProcessingTime = 0; char* pLF; char* pTAB; @@ -201,6 +224,33 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { set_line_separators(ip->bINChIOutputOptions, &pLF, &pTAB); + + // int CalcAndPrintINCHIAndINCHIKEY(struct tagINCHI_CLOCK* ic, + // CANON_GLOBALS* CG, + // STRUCT_DATA* sd, + // INPUT_PARMS* ip, + // char* szTitle, + // PINChI2* pINChI[INCHI_NUM], + // PINChI_Aux2* pINChI_Aux[INCHI_NUM], + // INCHI_IOSTREAM* inp_file, + // INCHI_IOSTREAM* plog, + // INCHI_IOSTREAM* pout, + // INCHI_IOSTREAM* pprb, + // ORIG_ATOM_DATA* orig_inp_data, + // ORIG_ATOM_DATA* prep_inp_data, + // long* num_inp, + // STRUCT_FPTRS* pStructPtrs, + // int* nRet, + // int have_err_in_GetOneStructure, + // long* num_err, + // int output_error_inchi, + // INCHI_IOS_STRING* strbuf, + // unsigned long* pulTotalProcessingTime, + // char* pLF, + // char* pTAB, + // char* ikey, + // int silent) + ret = CalcAndPrintINCHIAndINCHIKEY( &ic, &CG, @@ -229,11 +279,17 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { silent ); + EXPECT_EQ(ret, DO_NEXT_STEP); + char *inchi = "InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6+,7-,8+,9+,10-/m0/s1"; + //ios->s.pStr + EXPECT_STREQ(inchi, pout->s.pStr); + FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); inchi_ios_free_str(&input_stream); FreeOrigAtData(&orig_at_data); + FreeOrigAtData(&prep_inp_data); for (int i = 0; i < MAX_NUM_PATHS; i++) { @@ -251,33 +307,6 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { delete pprb; delete num_inp; - - // int CalcAndPrintINCHIAndINCHIKEY(struct tagINCHI_CLOCK* ic, - // CANON_GLOBALS* CG, - // STRUCT_DATA* sd, - // INPUT_PARMS* ip, - // char* szTitle, - // PINChI2* pINChI[INCHI_NUM], - // PINChI_Aux2* pINChI_Aux[INCHI_NUM], - // INCHI_IOSTREAM* inp_file, - // INCHI_IOSTREAM* plog, - // INCHI_IOSTREAM* pout, - // INCHI_IOSTREAM* pprb, - // ORIG_ATOM_DATA* orig_inp_data, - // ORIG_ATOM_DATA* prep_inp_data, - // long* num_inp, - // STRUCT_FPTRS* pStructPtrs, - // int* nRet, - // int have_err_in_GetOneStructure, - // long* num_err, - // int output_error_inchi, - // INCHI_IOS_STRING* strbuf, - // unsigned long* pulTotalProcessingTime, - // char* pLF, - // char* pTAB, - // char* ikey, - // int silent) - } TEST(ichimain_testing, test_ProcessMultipleInputFiles_2mol_files) @@ -636,6 +665,9 @@ TEST(ichimain_testing, test_GetTheNextRecordOfInputFile) EXPECT_EQ(ret, DO_NEXT_STEP); + EXPECT_EQ(orig_at_data.num_inp_atoms, 18); + EXPECT_EQ(orig_at_data.num_inp_bonds, 17); + inchi_ios_free_str(&input_stream); FreeOrigAtData(&orig_at_data); From c2d2935c7c045730028ae5f3f7dbe6cbd342a19b Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 15 Dec 2025 10:56:17 +0000 Subject: [PATCH 08/69] Added unit test for CalcAndPrintInchi... --- .../tests/test_unit/test_ichimain.cpp | 48 ++++++++++++------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index 7b8b77f9..f06648b1 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -34,6 +34,15 @@ char *read_inchi_from_file(const char *filename) { std::string trimmed = line.substr(start, end - start + 1); if (trimmed.rfind("InChI=", 0) == 0) { found_inchi = trimmed; + break; + } else if (trimmed.find("InChI=", 0) != std::string::npos) { + size_t start_pos = trimmed.find("InChI="); + if(start_pos != 0) { + found_inchi = trimmed.substr(start_pos); + } else { + found_inchi = trimmed; + } + break; } } @@ -165,7 +174,13 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { szSdfDataValue, &ulDisplTime, bReleaseVersion, plog); - inchi_ios_init(pout, INCHI_IOS_TYPE_STRING, nullptr); + + const char* inchi_filename = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/output.txt"; + + FILE *file_inchi; + file_inchi = fopen(inchi_filename, "w"); + + inchi_ios_init(pout, INCHI_IOS_TYPE_FILE, file_inchi); //nullptr INCHI_IOS_TYPE_STRING inchi_ios_init(plog, INCHI_IOS_TYPE_STRING, stdout); inchi_ios_init(pprb, INCHI_IOS_TYPE_STRING, nullptr); @@ -195,23 +210,9 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { EXPECT_EQ(orig_at_data.num_inp_bonds, 17); CANON_GLOBALS CG = {}; - // STRUCT_DATA* sd; - // INPUT_PARMS* ip; - // char* szTitle; PINChI2* pINChI[INCHI_NUM]; PINChI_Aux2* pINChI_Aux[INCHI_NUM]; - // INCHI_IOSTREAM* inp_file; - // INCHI_IOSTREAM* plog; - // INCHI_IOSTREAM* pout; - // INCHI_IOSTREAM* pprb; - // ORIG_ATOM_DATA* orig_inp_data; ORIG_ATOM_DATA prep_inp_data = {}; - // long* num_inp; - // STRUCT_FPTRS* pStructPtrs; - // int* nRet; - // int have_err_in_GetOneStructure; - // long* num_err; - // int output_error_inchi; INCHI_IOS_STRING *strbuf = new INCHI_IOS_STRING; memset(strbuf, 0, sizeof(*strbuf)); inchi_strbuf_init(strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); @@ -281,15 +282,25 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { EXPECT_EQ(ret, DO_NEXT_STEP); - char *inchi = "InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6+,7-,8+,9+,10-/m0/s1"; - //ios->s.pStr - EXPECT_STREQ(inchi, pout->s.pStr); + fclose(file_inchi); + + char *found_inchi = read_inchi_from_file(inchi_filename); + + const char *inchi = "InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6+,7-,8+,9+,10-/m0/s1"; + + EXPECT_STREQ(inchi, found_inchi); //pout->s.pStr); + + free(found_inchi); + + remove(inchi_filename); FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); + inchi_strbuf_close(strbuf); inchi_ios_free_str(&input_stream); FreeOrigAtData(&orig_at_data); FreeOrigAtData(&prep_inp_data); + SetBitFree(&CG); for (int i = 0; i < MAX_NUM_PATHS; i++) { @@ -306,6 +317,7 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { delete pout; delete pprb; delete num_inp; + delete strbuf; } From 9e08c08f756a536a7c2e2139dcc5b647ff45583f Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 15 Dec 2025 10:56:43 +0000 Subject: [PATCH 09/69] Formatting whitespace removal --- INCHI-1-SRC/INCHI_BASE/src/runichi.c | 97 ++++++++++++++-------------- 1 file changed, 48 insertions(+), 49 deletions(-) diff --git a/INCHI-1-SRC/INCHI_BASE/src/runichi.c b/INCHI-1-SRC/INCHI_BASE/src/runichi.c index a5dc9e1c..d8630a59 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/runichi.c +++ b/INCHI-1-SRC/INCHI_BASE/src/runichi.c @@ -267,7 +267,6 @@ int ProcessOneStructure( INCHI_CLOCK *ic, memset( composite_norm_data, 0, sizeof( composite_norm_data ) ); /* djb-rwth: memset_s C11/Annex K variant? */ memset( pncFlags, 0, sizeof( *pncFlags ) ); /* djb-rwth: memset_s C11/Annex K variant? */ - /* For experimental purposes only */ /*ret1 = DoOneStructureEarlyPreprocessing( num_inp, sd, ip, inp_file, log_file, out_file, prb_file, @@ -1156,7 +1155,7 @@ int CreateOneStructureINChI( CANON_GLOBALS *pCG, /* allocate pINChI[iINChI] and pINChI_Aux2[iINChI] -- arrays of pointers to INChI and INChI_Aux */ /* assign values to sd->num_components[] */ - + /* djb-rwth: MYREALLOC2 has been replaced and the whole block rewritten to address memory leaks and reading from freed memory locations */ do { if( (sd->num_components[iINChI]) <= ((long long)cur_prep_inp_data->num_components) ) { @@ -1327,7 +1326,7 @@ int CreateOneStructureINChI( CANON_GLOBALS *pCG, } #endif - /*#ifndef COMPILE_ANSI_ONLY + /*#ifndef COMPILE_ANSI_ONLY { */ /* b) Display the extracted original component structure */ @@ -2039,7 +2038,7 @@ int ProcessOneStructureEx( struct tagINCHI_CLOCK *ic, { int ret = _IS_OKAY; char *sinchi_noedits=NULL, *saux_noedits=NULL; - + /* PREPROCESS */ @@ -2048,7 +2047,7 @@ int ProcessOneStructureEx( struct tagINCHI_CLOCK *ic, if (ip->bFilterSS) { int present, ok = 0; - + present = OrigAtData_CheckForSubstructure(orig_inp_data); if (ip->bFilterSS == 1 && present) ok = 1; @@ -2073,11 +2072,11 @@ int ProcessOneStructureEx( struct tagINCHI_CLOCK *ic, &sinchi_noedits, &saux_noedits); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ /* CALCULATE INCHI */ - - /* Perform calculation as usual either for untouched (modes POLYMERS_LEGACY and POLYMERS_LEGACY_PLUS) + + /* Perform calculation as usual either for untouched (modes POLYMERS_LEGACY and POLYMERS_LEGACY_PLUS) or just edited, probably (mode POLYMERS_MODERN) structure as passed in orig_inp_data */ - ret = ProcessOneStructureExCore( ic, CG, sd, ip, szTitle, + ret = ProcessOneStructureExCore( ic, CG, sd, ip, szTitle, pINChI2, pINChI_Aux2, inp_file, log_file, out_file, prb_file, orig_inp_data, prep_inp_data, @@ -2118,7 +2117,7 @@ int ProcessOneStructureEx( struct tagINCHI_CLOCK *ic, inchi_free(sinchi_noedits); inchi_free(saux_noedits); - + #ifdef TARGET_LIB_FOR_WINCHI push_to_winchi_text_window(out_file); @@ -2135,7 +2134,7 @@ int ProcessOneStructureEx( struct tagINCHI_CLOCK *ic, /**************************************************************************** - Special treatment for polymers: perform CRU frame shift analysis + Special treatment for polymers: perform CRU frame shift analysis and make related edits in orig_inp_data whenever applicable ****************************************************************************/ int PreprocessPolymerCRUData( struct tagINCHI_CLOCK *ic, @@ -2161,7 +2160,7 @@ int PreprocessPolymerCRUData( struct tagINCHI_CLOCK *ic, char *sinchi_105p = NULL, *saux_105p = NULL; OAD_StructureEdits edits_unit_frame_shift, *ed_fs = &edits_unit_frame_shift; OAD_StructureEdits edits_unit_folding, *ed_fold = &edits_unit_folding; - + OAD_StructureEdits_Init(ed_fold); OAD_StructureEdits_Init(ed_fs); @@ -2192,7 +2191,7 @@ int PreprocessPolymerCRUData( struct tagINCHI_CLOCK *ic, sinchi_noedits, saux_noedits); if (ret == _IS_FATAL || ret == _IS_ERROR) { - ret = _IS_WARNING; + ret = _IS_WARNING; if (!ip->bNoWarnings) { AddErrorMessage(sd->pStrErrStruct, "CRU folding and frame shift analysis failed"); @@ -2205,10 +2204,10 @@ int PreprocessPolymerCRUData( struct tagINCHI_CLOCK *ic, /* CRU having both caps of indefinite nature, Zz */ goto exit_function; } - + /* Prepare and perform CRU folding related edits */ - if (ip->bFoldPolymerSRU != 0) + if (ip->bFoldPolymerSRU != 0) { /* Get interim 105+ flavour of InChI and AuxInfo and prepare */ int old_bFrameShiftScheme = ip->bFrameShiftScheme; @@ -2228,7 +2227,7 @@ int PreprocessPolymerCRUData( struct tagINCHI_CLOCK *ic, /* AddErrorMessage(sd->pStrErrStruct, "CRU fold analysis failed");*/ ; } - goto frame_shift; + goto frame_shift; } ret = OAD_Polymer_PrepareFoldCRUEdits( orig_inp_data, *sinchi_noedits, *saux_noedits, sinchi_105p, saux_105p, ed_fold); @@ -2244,7 +2243,7 @@ int PreprocessPolymerCRUData( struct tagINCHI_CLOCK *ic, if (ret == _IS_WARNING) { /* inchi_ios_eprint(log_file, "Warning (CRU fold analysis failed) structure #%ld.%s%s%s%s\n", - num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue));*/ + num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue));*/ ; } /* else */ @@ -2283,7 +2282,7 @@ int PreprocessPolymerCRUData( struct tagINCHI_CLOCK *ic, frame_shift: ; /* Prepare and perform frame shift related edits */ - if (ip->bFrameShiftScheme != FSS_NONE) + if (ip->bFrameShiftScheme != FSS_NONE) { /* Clear buffers */ if (sinchi_105p) @@ -2314,7 +2313,7 @@ frame_shift: ; } ret = OAD_Polymer_PrepareFrameShiftEdits( orig_inp_data, sinchi_105p, saux_105p, ed_fs); - + if (ret == _IS_FATAL || ret == _IS_ERROR) /* djb-rwth: logical operator corrected */ { ret = _IS_WARNING; @@ -2386,7 +2385,7 @@ frame_shift: ; OAD_StructureEdits_Clear(ed_fold); /* Clear edits collection */ OAD_StructureEdits_Clear(ed_fs); /* Clear edits collection */ - + return ret; } @@ -2395,17 +2394,17 @@ frame_shift: ; void swap_atoms_xyz( ORIG_ATOM_DATA *orig_at_data, int ia1, int ia2 ) { double x, y, z; - + if (ia1 != ia2) { - x = orig_at_data->at[ia1].x; - y = orig_at_data->at[ia1].y; + x = orig_at_data->at[ia1].x; + y = orig_at_data->at[ia1].y; z = orig_at_data->at[ia1].z; orig_at_data->at[ia1].x = orig_at_data->at[ia2].x; orig_at_data->at[ia1].y = orig_at_data->at[ia2].y; orig_at_data->at[ia1].z = orig_at_data->at[ia2].z; - + orig_at_data->at[ia2].x = x; orig_at_data->at[ia2].y = y; orig_at_data->at[ia2].z = z; @@ -2418,10 +2417,10 @@ void swap_atoms_xyz( ORIG_ATOM_DATA *orig_at_data, int ia1, int ia2 ) /**************************************************************************** OAD_StructureEdits_Edit ****************************************************************************/ -int OAD_StructureEdits_Apply( STRUCT_DATA *sd, - INPUT_PARMS *ip, - ORIG_ATOM_DATA *orig_at_data, - OAD_StructureEdits *ed, +int OAD_StructureEdits_Apply( STRUCT_DATA *sd, + INPUT_PARMS *ip, + ORIG_ATOM_DATA *orig_at_data, + OAD_StructureEdits *ed, int *ret) { int ok = 0, fail; @@ -2469,7 +2468,7 @@ int OAD_StructureEdits_Apply( STRUCT_DATA *sd, n_edits++; } } - + /* Add bonds */ if (n_new_bond) { @@ -2488,7 +2487,7 @@ int OAD_StructureEdits_Apply( STRUCT_DATA *sd, n_edits++; } } - + /* Modify bonds */ if (n_mod_bond) { @@ -2551,7 +2550,7 @@ int OAD_StructureEdits_Apply( STRUCT_DATA *sd, } } - + /* Delete atoms */ if (n_del_atom) { @@ -2572,7 +2571,7 @@ int OAD_StructureEdits_Apply( STRUCT_DATA *sd, goto exit_function; } - fail = mark_atoms_to_delete_or_renumber(orig_at_data, ed, at_renum); + fail = mark_atoms_to_delete_or_renumber(orig_at_data, ed, at_renum); if (fail) { *ret = _IS_ERROR; @@ -2594,20 +2593,20 @@ int OAD_StructureEdits_Apply( STRUCT_DATA *sd, AT_NUMB nbr0[MAXVAL]; U_CHAR btype0[MAXVAL]; int m, macc, valen; - int new_num = at_renum[i]; + int new_num = at_renum[i]; if (new_num == -1) { /* Skip removed atom */ continue; } - /* Atom to keep; copy it */ + /* Atom to keep; copy it */ new_at0 = new_at + nacc; ++nacc; memcpy(new_at0, orig_at_data->at + i, sizeof(new_at[0])); /* Correct its own number(s) */ new_at0->orig_at_number = new_num + 1; - + /* Correct its nbr number(s) */ valen = new_at0->valence; memcpy(nbr0, new_at0->neighbor, valen * sizeof(AT_NUMB)); @@ -2620,7 +2619,7 @@ int OAD_StructureEdits_Apply( STRUCT_DATA *sd, if (renum2 == num2) { /* keep old */ - new_at0->neighbor[macc++] = num2; + new_at0->neighbor[macc++] = num2; } else if (renum2 == -1) { @@ -2628,7 +2627,7 @@ int OAD_StructureEdits_Apply( STRUCT_DATA *sd, new_at0->chem_bonds_valence -= btype0[m]; new_at0->valence--; } - else + else { /* set renumbered */ new_at0->neighbor[macc++] = renum2; @@ -2746,7 +2745,7 @@ int OAD_StructureEdits_Apply( STRUCT_DATA *sd, } /* if (n_del_atom) */ - + exit_function: if (ibuf) @@ -2759,7 +2758,7 @@ int OAD_StructureEdits_Apply( STRUCT_DATA *sd, } return n_edits; } - + /**************************************************************************** Set each element of number to renum[element] or delete it if renum==(base -1) @@ -2868,7 +2867,7 @@ int ProcessOneStructureExCore( struct tagINCHI_CLOCK *ic, /**************************************************************************** - Treat pseudoelement and polymers: parse, validate and set details + Treat pseudoelement and polymers: parse, validate and set details ****************************************************************************/ int ValidateAndPreparePolymerAndPseudoatoms( struct tagINCHI_CLOCK *ic, struct tagCANON_GLOBALS *CG, @@ -2891,7 +2890,7 @@ int ValidateAndPreparePolymerAndPseudoatoms( struct tagINCHI_CLOCK *ic, int res = _IS_OKAY; int mind_pseudoelements = 0; - + *mind_polymers = orig_inp_data && orig_inp_data->polymer && orig_inp_data->polymer->n > 0; *mind_polymers = *mind_polymers && orig_inp_data->valid_polymer && (ip->nInputType == INPUT_MOLFILE || ip->nInputType == INPUT_SDFILE); @@ -2923,8 +2922,8 @@ int ValidateAndPreparePolymerAndPseudoatoms( struct tagINCHI_CLOCK *ic, ip->bPolymers != POLYMERS_MODERN && (ip->bFrameShiftScheme == FSS_STARS_CYCLED || ip->bFrameShiftScheme == FSS_STARS_CYCLED_SORTED)) { - /* Analyze and cyclize frame-shift eligible CRUs using InChI canonical numbers - (do this only at older polymer treatment modes 1.05, 1.05+) + /* Analyze and cyclize frame-shift eligible CRUs using InChI canonical numbers + (do this only at older polymer treatment modes 1.05, 1.05+) */ res = OAD_Polymer_CyclizeCloseableUnits( orig_inp_data, ip->bPolymers, @@ -2951,7 +2950,7 @@ int ValidateAndPreparePolymerAndPseudoatoms( struct tagINCHI_CLOCK *ic, /**************************************************************************** Get InChI and AuxInfo of totally unedited original structure. The intent is to preserve AuxInfo for the very original structure - in order to keep a final ability to restore that structure. + in order to keep a final ability to restore that structure. ****************************************************************************/ int OAD_ProcessOneStructureNoEdits( struct tagINCHI_CLOCK *ic, struct tagCANON_GLOBALS *CG, @@ -2970,7 +2969,7 @@ int OAD_ProcessOneStructureNoEdits( struct tagINCHI_CLOCK *ic, INCHI_IOS_STRING *strbuf, unsigned char save_opt_bits, int *n_pzz, - char **sinchi, + char **sinchi, char **saux) { size_t slen; @@ -3013,7 +3012,7 @@ int OAD_ProcessOneStructureNoEdits( struct tagINCHI_CLOCK *ic, { goto exit_function; } - + *n_pzz = dup->orig_inp_data->polymer->n_pzz; /* Extract InChI */ slen = dup->out_file->s.nUsedLength; @@ -3150,9 +3149,9 @@ int mark_atoms_to_delete_or_renumber( ORIG_ATOM_DATA *orig_at_data, size_t *atnums = NULL; /* djb-rwth: needs to be size_t type */ size_t max_atoms = orig_at_data->num_inp_atoms; - /* NB: new/old ORIG_ATOM_DATA atom numbers are 0-based (==orig_number-1) + /* NB: new/old ORIG_ATOM_DATA atom numbers are 0-based (==orig_number-1) while those in ed->... are just 1-based orig_numbers */ - + for (i = 0; (size_t)i < max_atoms; i++) { at_renum[i] = i; @@ -3219,7 +3218,7 @@ int mark_atoms_to_delete_or_renumber( ORIG_ATOM_DATA *orig_at_data, for (i = max_atoms - 1; i >= 0; i--) { int orig_num = i + 1; /* NB: ed->del_atom->item contains orig# which are (OAD# + 1) */ - if (is_in_the_ilist(ed->del_atom->item, orig_num, ed->del_atom->used)) + if (is_in_the_ilist(ed->del_atom->item, orig_num, ed->del_atom->used)) { /* mark as deleted atnum */ at_renum[i] = -1; @@ -3262,7 +3261,7 @@ int check_presence_of_the_encoded_substructure(ORIG_ATOM_DATA *oad) /* Place sub-structure filtering code below. Return 1 if structure matches some hard-coded pattern - + In this example pattern is a presence of a pseudo atom. */ From 31067d9660ca16b519f81c5f88f44bceabea0862 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 15 Dec 2025 11:10:40 +0000 Subject: [PATCH 10/69] removed sanitizing flags --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 737bfafd..2b324705 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,8 +6,8 @@ set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 11) set(CMAKE_POSITION_INDEPENDENT_CODE ON) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") +# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") +# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") include(FetchContent) FetchContent_Declare( From 2bc425678b94dbca1893cf4f3d174c1b3f86999a Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 15 Dec 2025 11:29:57 +0000 Subject: [PATCH 11/69] fixed missing initialization --- INCHI-1-TEST/tests/test_unit/test_ichimain.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index f06648b1..c3c8729e 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -210,8 +210,8 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { EXPECT_EQ(orig_at_data.num_inp_bonds, 17); CANON_GLOBALS CG = {}; - PINChI2* pINChI[INCHI_NUM]; - PINChI_Aux2* pINChI_Aux[INCHI_NUM]; + PINChI2* pINChI[INCHI_NUM] = {}; + PINChI_Aux2* pINChI_Aux[INCHI_NUM] = {}; ORIG_ATOM_DATA prep_inp_data = {}; INCHI_IOS_STRING *strbuf = new INCHI_IOS_STRING; memset(strbuf, 0, sizeof(*strbuf)); @@ -282,7 +282,9 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { EXPECT_EQ(ret, DO_NEXT_STEP); - fclose(file_inchi); + if (file_inchi != nullptr) { + fclose(file_inchi); + } char *found_inchi = read_inchi_from_file(inchi_filename); From 36cd7ca7bf91135d73bfc4490831a1f0bbc36a0c Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 15 Dec 2025 12:43:42 +0000 Subject: [PATCH 12/69] Added write permissions to workflow in ci pipeline --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b9e27ffd..85a316d6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,6 +18,9 @@ jobs: - id: setup run: ./.devcontainer/post_create_commands.sh + - name: Fix file permissions + run: chmod -R +rw ${{ github.workspace }} + - name: Run unit tests run: cd CMake_build/full_build/INCHI-1-TEST/tests/test_unit && ctest --output-on-failure From c5666fda0bb3e8caa27bfdf57caf8b768dba31e7 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 15 Dec 2025 13:06:16 +0000 Subject: [PATCH 13/69] Reverted file permissions --- .github/workflows/ci.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 85a316d6..b9e27ffd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,9 +18,6 @@ jobs: - id: setup run: ./.devcontainer/post_create_commands.sh - - name: Fix file permissions - run: chmod -R +rw ${{ github.workspace }} - - name: Run unit tests run: cd CMake_build/full_build/INCHI-1-TEST/tests/test_unit && ctest --output-on-failure From 5e355389fed499125c14db7a618e42ecbcd87a25 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 15 Dec 2025 13:22:12 +0000 Subject: [PATCH 14/69] Path fix for ci pipeline --- INCHI-1-TEST/tests/test_unit/test_ichimain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index c3c8729e..8afe3243 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -175,7 +175,7 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { bReleaseVersion, plog); - const char* inchi_filename = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/output.txt"; + const char* inchi_filename = "../../../INCHI-1-TEST/tests/test_unit/fixtures/output.txt"; FILE *file_inchi; file_inchi = fopen(inchi_filename, "w"); From 87ae02a2bdf32933fb14eab6f3c4667728a7b11b Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 15 Dec 2025 13:32:51 +0000 Subject: [PATCH 15/69] Path fix for ci pipeline --- INCHI-1-TEST/tests/test_unit/test_ichimain.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index 8afe3243..55d60776 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -335,10 +335,11 @@ TEST(ichimain_testing, test_ProcessMultipleInputFiles_2mol_files) "naloxon.mol", "caffeine.mol" }; + // ../../../ + // /workspaces/InChI/ + const char *path_fixtures = "../../../INCHI-1-TEST/tests/test_unit/fixtures"; - const char *path_fixtures = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures"; - - char tmpl[] = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; + char tmpl[] = "../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; char *tmpd = mkdtemp(tmpl); ASSERT_NE(tmpd, nullptr); From 7691e9ea1b26c94c313e828255c710c6ee08dc51 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 15 Dec 2025 13:43:23 +0000 Subject: [PATCH 16/69] Path fix for ci pipeline --- INCHI-1-TEST/tests/test_unit/test_ichimain.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index 55d60776..04315ba6 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -175,7 +175,7 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { bReleaseVersion, plog); - const char* inchi_filename = "../../../INCHI-1-TEST/tests/test_unit/fixtures/output.txt"; + const char* inchi_filename = "../../../../INCHI-1-TEST/tests/test_unit/fixtures/output.txt"; FILE *file_inchi; file_inchi = fopen(inchi_filename, "w"); @@ -337,9 +337,9 @@ TEST(ichimain_testing, test_ProcessMultipleInputFiles_2mol_files) }; // ../../../ // /workspaces/InChI/ - const char *path_fixtures = "../../../INCHI-1-TEST/tests/test_unit/fixtures"; + const char *path_fixtures = "../../../../INCHI-1-TEST/tests/test_unit/fixtures"; - char tmpl[] = "../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; + char tmpl[] = "../../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; char *tmpd = mkdtemp(tmpl); ASSERT_NE(tmpd, nullptr); @@ -409,8 +409,8 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) const char *filename_caffeine = "caffeine.mol"; - const char *path_fixtures = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures"; - char tmpl[] = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; + const char *path_fixtures = "../../../../INCHI-1-TEST/tests/test_unit/fixtures"; + char tmpl[] = "../../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; char *tmpd = mkdtemp(tmpl); ASSERT_NE(tmpd, nullptr); @@ -471,8 +471,8 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_2mols_sdf) const char *filename_2mols = "test_mols_2.sdf"; - const char *path_fixtures = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures"; - char tmpl[] = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; + const char *path_fixtures = "../../../../INCHI-1-TEST/tests/test_unit/fixtures"; + char tmpl[] = "../../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; char *tmpd = mkdtemp(tmpl); ASSERT_NE(tmpd, nullptr); From bc4e2d3d89798eabe4ef9e57f3c1d583e3cac4c8 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Tue, 16 Dec 2025 10:22:16 +0000 Subject: [PATCH 17/69] Fixed directory for fixtures --- .../tests/test_unit/test_ichimain.cpp | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index 04315ba6..7e06de36 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include extern "C" @@ -53,7 +54,6 @@ char *read_inchi_from_file(const char *filename) { TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { - INCHI_IOSTREAM input_stream; const char *molblock = @@ -174,11 +174,10 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { szSdfDataValue, &ulDisplTime, bReleaseVersion, plog); - - const char* inchi_filename = "../../../../INCHI-1-TEST/tests/test_unit/fixtures/output.txt"; - - FILE *file_inchi; + const char* inchi_filename = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures/output.txt"; + FILE *file_inchi = nullptr; file_inchi = fopen(inchi_filename, "w"); + EXPECT_NE(file_inchi, nullptr); inchi_ios_init(pout, INCHI_IOS_TYPE_FILE, file_inchi); //nullptr INCHI_IOS_TYPE_STRING inchi_ios_init(plog, INCHI_IOS_TYPE_STRING, stdout); @@ -205,7 +204,6 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { output_error_inchi); EXPECT_EQ(ret, DO_NEXT_STEP); - EXPECT_EQ(orig_at_data.num_inp_atoms, 18); EXPECT_EQ(orig_at_data.num_inp_bonds, 17); @@ -225,7 +223,6 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { set_line_separators(ip->bINChIOutputOptions, &pLF, &pTAB); - // int CalcAndPrintINCHIAndINCHIKEY(struct tagINCHI_CLOCK* ic, // CANON_GLOBALS* CG, // STRUCT_DATA* sd, @@ -288,6 +285,8 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { char *found_inchi = read_inchi_from_file(inchi_filename); + EXPECT_NE(found_inchi, nullptr); + const char *inchi = "InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6+,7-,8+,9+,10-/m0/s1"; EXPECT_STREQ(inchi, found_inchi); //pout->s.pStr); @@ -312,9 +311,9 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { ip->path[i] = NULL; } } + delete ip; delete sd; - delete plog; delete pout; delete pprb; @@ -337,9 +336,9 @@ TEST(ichimain_testing, test_ProcessMultipleInputFiles_2mol_files) }; // ../../../ // /workspaces/InChI/ - const char *path_fixtures = "../../../../INCHI-1-TEST/tests/test_unit/fixtures"; + const char *path_fixtures = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures"; - char tmpl[] = "../../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; + char tmpl[] = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; char *tmpd = mkdtemp(tmpl); ASSERT_NE(tmpd, nullptr); @@ -409,8 +408,8 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) const char *filename_caffeine = "caffeine.mol"; - const char *path_fixtures = "../../../../INCHI-1-TEST/tests/test_unit/fixtures"; - char tmpl[] = "../../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; + const char *path_fixtures = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures"; + char tmpl[] = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; char *tmpd = mkdtemp(tmpl); ASSERT_NE(tmpd, nullptr); @@ -466,13 +465,14 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) remove(dst_path.c_str()); rmdir(tmpd); } + TEST(ichimain_testing, test_ProcessSingleInputFile_2mols_sdf) { const char *filename_2mols = "test_mols_2.sdf"; - const char *path_fixtures = "../../../../INCHI-1-TEST/tests/test_unit/fixtures"; - char tmpl[] = "../../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; + const char *path_fixtures = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures"; + char tmpl[] = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; char *tmpd = mkdtemp(tmpl); ASSERT_NE(tmpd, nullptr); From a1c2f8275115b1344c154a7984b2bf2d8e9598ce Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Tue, 16 Dec 2025 15:38:28 +0000 Subject: [PATCH 18/69] Removed commented lines --- .../tests/test_unit/test_ichimain.cpp | 60 ++++--------------- _deps/googletest-src | 1 - 2 files changed, 12 insertions(+), 49 deletions(-) delete mode 160000 _deps/googletest-src diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index 7e06de36..d50a451d 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -115,21 +115,6 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { inchi_ios_init(&input_stream, INCHI_IOS_TYPE_STRING, nullptr); inchi_ios_print_nodisplay(&input_stream, molblock); - // int GetTheNextRecordOfInputFile( struct tagINCHI_CLOCK *ic, - // STRUCT_DATA *sd, INPUT_PARMS *ip, - // char *szTitle, - // INCHI_IOSTREAM *inp_file, - // INCHI_IOSTREAM *plog, - // INCHI_IOSTREAM *pout, - // INCHI_IOSTREAM *pprb, - // ORIG_ATOM_DATA *orig_inp_data, - // long *num_inp, - // STRUCT_FPTRS *pStructPtrs, - // int *nRet, - // int *have_err_in_GetOneStructure, - // long *num_err, - // int output_error_inchi ); - INCHI_CLOCK ic = {}; memset(&ic, 0, sizeof(ic)); @@ -137,6 +122,11 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { // sd->ulStructTime = 0; INPUT_PARMS *ip = new INPUT_PARMS; + memset(ip, 0, sizeof(*ip)); + ip->last_struct_number = 1; + ip->nInputType = INPUT_MOLFILE; + ip->bINChIOutputOptions = INCHI_OUT_PLAIN_TEXT; + char *szTitle; INCHI_IOSTREAM *inp_file; INCHI_IOSTREAM *plog = new INCHI_IOSTREAM; @@ -152,18 +142,8 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { long num_err = 0; int output_error_inchi; - - memset(ip, 0, sizeof(*ip)); - ip->last_struct_number = 1; - ip->nInputType = INPUT_MOLFILE; - ip->bINChIOutputOptions = INCHI_OUT_PLAIN_TEXT; - // ip->bINChIOutputOptions2 = INCHI_OUT_PLAIN_TEXT; - // ip->nMode = REQ_MODE_TAUT; // REQ_MODE_BASIC; - // ip->bTautFlags |= (TG_FLAG_DISCONNECT_COORD | TG_FLAG_RECONNECT_COORD); - // ip->nMode |= (REQ_MODE_BASIC | REQ_MODE_TAUT | REQ_MODE_STEREO | REQ_MODE_ISO_STEREO | REQ_MODE_ISO); - int bReleaseVersion = bRELEASE_VERSION; - unsigned long ulDisplTime = 0; /* infinite, milliseconds */ + unsigned long ulDisplTime = 0; unsigned long ulTotalProcessingTime = 0; int argc = 0; @@ -179,11 +159,10 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { file_inchi = fopen(inchi_filename, "w"); EXPECT_NE(file_inchi, nullptr); - inchi_ios_init(pout, INCHI_IOS_TYPE_FILE, file_inchi); //nullptr INCHI_IOS_TYPE_STRING + inchi_ios_init(pout, INCHI_IOS_TYPE_FILE, file_inchi); inchi_ios_init(plog, INCHI_IOS_TYPE_STRING, stdout); inchi_ios_init(pprb, INCHI_IOS_TYPE_STRING, nullptr); - // PrintInputParms(plog, ip); inchi_ios_flush2(plog, stderr); int ret = GetTheNextRecordOfInputFile( @@ -334,8 +313,7 @@ TEST(ichimain_testing, test_ProcessMultipleInputFiles_2mol_files) "naloxon.mol", "caffeine.mol" }; - // ../../../ - // /workspaces/InChI/ + const char *path_fixtures = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures"; char tmpl[] = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; @@ -373,7 +351,6 @@ TEST(ichimain_testing, test_ProcessMultipleInputFiles_2mol_files) int ret = ProcessMultipleInputFiles(argc, argv); - // Assert the expected result ASSERT_EQ(ret, 0); for (int i = 0; i < expected_inchis.size(); i++) { @@ -383,8 +360,6 @@ TEST(ichimain_testing, test_ProcessMultipleInputFiles_2mol_files) free(inchi); } - // Clean up - for (auto p : dist_paths) { std::string out_txt = p + ".txt"; @@ -432,18 +407,13 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) int result = ProcessSingleInputFile(argc, argv); - // Assert the expected result EXPECT_EQ(result, 0); - free(inchi_filename); - free(input_file); - std::string out_txt = dst_path + ".txt"; std::string out_log = dst_path + ".log"; std::string out_prb = dst_path + ".prb"; struct stat st; - // check existence and non-zero size ASSERT_EQ(stat(out_txt.c_str(), &st), 0); EXPECT_GT(st.st_size, 0); ASSERT_EQ(stat(out_log.c_str(), &st), 0); @@ -458,6 +428,8 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) EXPECT_EQ(found_inchi, expected_inchi); // cleanup + free(inchi_filename); + free(input_file); free(found_inchi); remove(out_txt.c_str()); remove(out_log.c_str()); @@ -492,27 +464,20 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_2mols_sdf) char* argv[] = { inchi_filename, input_file }; // int ProcessSingleInputFile(int argc, char* argv[]) - int result = ProcessSingleInputFile(argc, argv); - // Assert the expected result EXPECT_EQ(result, 0); - free(inchi_filename); - free(input_file); - std::string out_txt = dst_path + ".txt"; std::string out_log = dst_path + ".log"; std::string out_prb = dst_path + ".prb"; struct stat st; - // check existence and non-zero size ASSERT_EQ(stat(out_txt.c_str(), &st), 0); EXPECT_GT(st.st_size, 0); ASSERT_EQ(stat(out_log.c_str(), &st), 0); EXPECT_GT(st.st_size, 0); ASSERT_EQ(stat(out_prb.c_str(), &st), 0); - // EXPECT_GT(st.st_size, 0); EXPECT_EQ(st.st_size, 0); std::ifstream txt_in(out_txt); @@ -520,7 +485,6 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_2mols_sdf) std::string line; std::vector found_inchis; while (std::getline(txt_in, line)) { - // trim leading/trailing whitespace size_t start = line.find_first_not_of(" \t\r\n"); if (start == std::string::npos) continue; size_t end = line.find_last_not_of(" \t\r\n"); @@ -542,6 +506,8 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_2mols_sdf) } // cleanup + free(inchi_filename); + free(input_file); remove(out_txt.c_str()); remove(out_log.c_str()); remove(out_prb.c_str()); @@ -649,7 +615,6 @@ TEST(ichimain_testing, test_GetTheNextRecordOfInputFile) long *num_err; int output_error_inchi; - memset(ip, 0, sizeof(*ip)); ip->last_struct_number = 1; ip->nInputType = INPUT_MOLFILE; @@ -658,7 +623,6 @@ TEST(ichimain_testing, test_GetTheNextRecordOfInputFile) inchi_ios_init(plog, INCHI_IOS_TYPE_STRING, stdout); inchi_ios_init(pprb, INCHI_IOS_TYPE_STRING, nullptr); - // PrintInputParms(plog, ip); inchi_ios_flush2(plog, stderr); int ret = GetTheNextRecordOfInputFile( diff --git a/_deps/googletest-src b/_deps/googletest-src deleted file mode 160000 index 52eb8108..00000000 --- a/_deps/googletest-src +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 52eb8108c5bdec04579160ae17225d66034bd723 From a997d00f4c53705f9c4a5dba8731b7abfe70bf3a Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Thu, 4 Dec 2025 14:03:33 +0000 Subject: [PATCH 19/69] Decoupled main from ichimain.c --- .../Geometries/data/cis_platin.mol | 26 - .../Geometries/data/mol_alkene.ds_0.mol | 18 - .../Geometries/data/mol_bidentate.ds_7.mol | 135 -- .../Geometries/data/mol_carbonyl.ds_0.mol | 41 - .../demos/mol2inchi/src/CMakeLists.txt | 4 +- .../inchi-1 => INCHI_BASE}/src/dispstru.c | 116 +- .../inchi-1 => INCHI_BASE}/src/dispstru.h | 0 INCHI-1-SRC/INCHI_BASE/src/ichimain.c | 1529 +++++++++++++++++ .../INCHI_EXE/inchi-1/src/CMakeLists.txt | 13 +- .../src/{ichimain.c => backup_ichimain.c} | 0 INCHI-1-SRC/INCHI_EXE/inchi-1/src/main.c | 266 +++ 11 files changed, 1862 insertions(+), 286 deletions(-) delete mode 100644 INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/cis_platin.mol delete mode 100644 INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_alkene.ds_0.mol delete mode 100644 INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_bidentate.ds_7.mol delete mode 100644 INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_carbonyl.ds_0.mol rename INCHI-1-SRC/{INCHI_EXE/inchi-1 => INCHI_BASE}/src/dispstru.c (98%) rename INCHI-1-SRC/{INCHI_EXE/inchi-1 => INCHI_BASE}/src/dispstru.h (100%) create mode 100644 INCHI-1-SRC/INCHI_BASE/src/ichimain.c rename INCHI-1-SRC/INCHI_EXE/inchi-1/src/{ichimain.c => backup_ichimain.c} (100%) create mode 100644 INCHI-1-SRC/INCHI_EXE/inchi-1/src/main.c diff --git a/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/cis_platin.mol b/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/cis_platin.mol deleted file mode 100644 index 92a570bd..00000000 --- a/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/cis_platin.mol +++ /dev/null @@ -1,26 +0,0 @@ - - ACCLDraw09152511572D - - 11 10 0 0 0 0 0 0 0 0999 V2000 - 13.6841 -9.2760 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 - 13.6841 -10.4428 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 - 13.1007 -9.8594 0.0000 Pt 0 0 0 0 0 0 0 0 0 0 0 0 - 12.7309 -8.4791 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 - 11.7204 -10.2293 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 - 11.7204 -9.4896 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 - 12.7308 -11.2397 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 - 12.5173 -10.4428 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 - 12.3038 -11.2397 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 - 12.5173 -9.2760 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 - 11.7204 -9.0625 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 - 3 1 1 0 0 0 0 - 3 2 1 0 0 0 0 - 3 8 1 0 0 0 0 - 3 10 1 0 0 0 0 - 10 6 1 0 0 0 0 - 10 4 1 0 0 0 0 - 8 5 1 0 0 0 0 - 8 7 1 0 0 0 0 - 8 9 1 0 0 0 0 - 10 11 1 0 0 0 0 -M END diff --git a/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_alkene.ds_0.mol b/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_alkene.ds_0.mol deleted file mode 100644 index 58be810f..00000000 --- a/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_alkene.ds_0.mol +++ /dev/null @@ -1,18 +0,0 @@ - -Generated by WebMolKit - - 6 6 0 0 1 0 0 0 0 0999 V2000 - 0.0000 0.0000 0.0000 Pt 0 5 0 0 0 0 0 0 0 0 0 0 - 1.5000 0.0000 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 - 0.0000 1.5000 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 - 0.0000 -1.5000 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 - -1.5990 0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -1.5990 -0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 1 2 1 0 0 0 0 - 1 3 1 0 0 0 0 - 1 4 1 0 0 0 0 - 1 5 0 0 0 0 0 - 5 6 2 0 0 0 0 - 6 1 0 0 0 0 0 -M CHG 1 1 -1 -M END \ No newline at end of file diff --git a/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_bidentate.ds_7.mol b/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_bidentate.ds_7.mol deleted file mode 100644 index b768f346..00000000 --- a/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_bidentate.ds_7.mol +++ /dev/null @@ -1,135 +0,0 @@ - -Generated by WebMolKit - - 55 61 0 0 1 0 0 0 0 0999 V2000 - 0.0000 0.0000 0.0000 Ru 0 0 0 0 0 0 0 0 0 0 0 0 - -1.7532 -0.4698 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 - -1.7290 0.9982 0.0000 C 0 0 0 0 0 2 0 0 0 0 0 0 - -3.0281 1.7482 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 - -2.1414 -1.9186 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -1.0807 -2.9793 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 - 3.3492 0.0125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 2.5775 1.2989 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 - 2.6210 -1.2989 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 - -2.0000 2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 0.0000 4.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 2.0000 2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -2.7500 0.7010 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -2.7500 3.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -4.2500 0.7010 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -5.0000 2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -4.2500 3.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -1.2990 4.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 1.2990 4.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -1.2990 6.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 0.0000 7.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 1.2990 6.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 2.7500 3.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 2.7500 0.7010 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 4.2500 3.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 5.0000 2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 4.2500 0.7010 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 0.0000 2.0000 0.0000 P 0 0 0 0 0 0 0 0 0 0 0 0 - 2.0000 -2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 0.0000 -4.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -2.0000 -2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 2.7500 -0.7010 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 2.7500 -3.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 4.2500 -0.7010 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 5.0000 -2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 4.2500 -3.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 1.2990 -4.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -1.2990 -4.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 1.2990 -6.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 0.0000 -7.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -1.2990 -6.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -2.7500 -3.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -2.7500 -0.7010 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -4.2500 -3.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -5.0000 -2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - -4.2500 -0.7010 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 0.0000 -2.0000 0.0000 P 0 0 0 0 0 0 0 0 0 0 0 0 - -3.2020 -3.7558 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 - -3.9786 -0.8580 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 - -5.0391 -2.6952 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 - -3.5903 -2.3069 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 4.8240 1.5373 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 - 4.8740 -1.4623 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 - 6.3488 0.0625 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 - 4.8490 0.0375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 1 2 1 0 0 0 0 - 1 3 0 0 0 0 0 - 3 4 2 0 0 0 0 - 2 5 1 0 0 0 0 - 5 6 2 0 0 0 0 - 7 8 2 0 0 0 0 - 7 9 1 0 0 0 0 - 9 1 1 0 0 0 0 - 8 1 0 0 0 0 0 - 28 10 1 0 0 0 0 - 28 11 1 0 0 0 0 - 28 12 1 0 0 0 0 - 10 13 1 0 0 0 0 - 10 14 2 0 0 0 0 - 13 15 2 0 0 0 0 - 15 16 1 0 0 0 0 - 16 17 2 0 0 0 0 - 17 14 1 0 0 0 0 - 11 18 1 0 0 0 0 - 11 19 2 0 0 0 0 - 18 20 2 0 0 0 0 - 20 21 1 0 0 0 0 - 21 22 2 0 0 0 0 - 22 19 1 0 0 0 0 - 12 23 1 0 0 0 0 - 12 24 2 0 0 0 0 - 23 25 2 0 0 0 0 - 25 26 1 0 0 0 0 - 26 27 2 0 0 0 0 - 27 24 1 0 0 0 0 - 1 28 0 0 0 0 0 - 47 29 1 0 0 0 0 - 47 30 1 0 0 0 0 - 47 31 1 0 0 0 0 - 29 32 1 0 0 0 0 - 29 33 2 0 0 0 0 - 32 34 2 0 0 0 0 - 34 35 1 0 0 0 0 - 35 36 2 0 0 0 0 - 36 33 1 0 0 0 0 - 30 37 1 0 0 0 0 - 30 38 2 0 0 0 0 - 37 39 2 0 0 0 0 - 39 40 1 0 0 0 0 - 40 41 2 0 0 0 0 - 41 38 1 0 0 0 0 - 31 42 1 0 0 0 0 - 31 43 2 0 0 0 0 - 42 44 2 0 0 0 0 - 44 45 1 0 0 0 0 - 45 46 2 0 0 0 0 - 46 43 1 0 0 0 0 - 1 47 0 0 0 0 0 - 51 48 1 0 0 0 0 - 51 49 1 0 0 0 0 - 51 50 1 0 0 0 0 - 5 51 1 0 0 0 0 - 55 52 1 0 0 0 0 - 55 53 1 0 0 0 0 - 55 54 1 0 0 0 0 - 7 55 1 0 0 0 0 -M STY 1 1 SUP -M SAL 1 15 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 -M SAL 1 4 25 26 27 28 -M SMT 1 P|Ph{3} -M STY 1 2 SUP -M SAL 2 15 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 -M SAL 2 4 44 45 46 47 -M SMT 2 P|Ph{3} -M STY 1 3 SUP -M SAL 3 4 48 49 50 51 -M SMT 3 C|F{3} -M STY 1 4 SUP -M SAL 4 4 52 53 54 55 -M SMT 4 C|F{3} -M END \ No newline at end of file diff --git a/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_carbonyl.ds_0.mol b/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_carbonyl.ds_0.mol deleted file mode 100644 index 2d2ca465..00000000 --- a/INCHI-1-DOC/Notebooks/Molecular_inorganics/Geometries/data/mol_carbonyl.ds_0.mol +++ /dev/null @@ -1,41 +0,0 @@ - -Generated by WebMolKit - - 11 10 0 0 1 0 0 0 0 0999 V2000 - 0.0000 0.0000 0.0000 Fe 0 0 0 0 0 0 0 0 0 0 0 0 - 0.0000 1.5000 0.0000 C 0 0 0 0 0 2 0 0 0 0 0 0 - 0.0000 3.0000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 - 0.0000 -1.5000 0.0000 C 0 0 0 0 0 2 0 0 0 0 0 0 - 0.0000 -3.0000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 - 1.2991 -0.7500 0.0000 C 0 0 0 0 0 2 0 0 0 0 0 0 - 2.5981 -1.5000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 - 1.2990 0.7500 0.0000 C 0 0 0 0 0 2 0 0 0 0 0 0 - 2.5980 1.5001 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 - -1.5000 0.0000 0.0000 C 0 0 0 0 0 2 0 0 0 0 0 0 - -3.0000 0.0000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 - 1 2 0 0 0 0 0 - 2 3 2 0 0 0 0 - 1 4 0 0 0 0 0 - 4 5 2 0 0 0 0 - 1 6 0 0 0 0 0 - 6 7 2 0 0 0 0 - 1 8 0 0 0 0 0 - 8 9 2 0 0 0 0 - 1 10 0 0 0 0 0 - 10 11 2 0 0 0 0 -M STY 1 1 SUP -M SAL 1 2 2 3 -M SMT 1 C|O -M STY 1 2 SUP -M SAL 2 2 4 5 -M SMT 2 C|O -M STY 1 3 SUP -M SAL 3 2 6 7 -M SMT 3 C|O -M STY 1 4 SUP -M SAL 4 2 8 9 -M SMT 4 C|O -M STY 1 5 SUP -M SAL 5 2 10 11 -M SMT 5 C|O -M END \ No newline at end of file diff --git a/INCHI-1-SRC/INCHI_API/demos/mol2inchi/src/CMakeLists.txt b/INCHI-1-SRC/INCHI_API/demos/mol2inchi/src/CMakeLists.txt index 8654f50e..1f89d99a 100644 --- a/INCHI-1-SRC/INCHI_API/demos/mol2inchi/src/CMakeLists.txt +++ b/INCHI-1-SRC/INCHI_API/demos/mol2inchi/src/CMakeLists.txt @@ -51,7 +51,7 @@ if(MATH_LIBRARY) target_link_libraries(mol2inchi PUBLIC ${MATH_LIBRARY}) endif() -target_compile_definitions(mol2inchi PRIVATE +target_compile_definitions(mol2inchi PRIVATE BUILD_LINK_AS_DLL TARGET_EXE_USING_API ) @@ -70,7 +70,7 @@ else() set(CMAKE_THREAD_PREFER_PTHREAD TRUE) set(THREADS_PREFER_PTHREAD_FLAG TRUE) find_package(Threads REQUIRED) - target_link_libraries(mol2inchi Threads::Threads) + target_link_libraries(mol2inchi PRIVATE Threads::Threads) add_custom_command(TARGET mol2inchi POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ $ COMMAND_EXPAND_LISTS diff --git a/INCHI-1-SRC/INCHI_EXE/inchi-1/src/dispstru.c b/INCHI-1-SRC/INCHI_BASE/src/dispstru.c similarity index 98% rename from INCHI-1-SRC/INCHI_EXE/inchi-1/src/dispstru.c rename to INCHI-1-SRC/INCHI_BASE/src/dispstru.c index c70ce860..f5bff79f 100644 --- a/INCHI-1-SRC/INCHI_EXE/inchi-1/src/dispstru.c +++ b/INCHI-1-SRC/INCHI_BASE/src/dispstru.c @@ -40,7 +40,7 @@ /* Draw input atom -- Win32 specific */ -#include "../../../INCHI_BASE/src/mode.h" +#include "mode.h" #ifndef COMPILE_ANSI_ONLY @@ -347,13 +347,13 @@ BOOL TextOutVert( HDC pDC, /* handle to DC */ GetTextMetrics( pDC, &TextMetric ); dy = TextMetric.tmHeight; - + for (i = 0, ret = 1; ret && i < cbString; nYStart += dy, i++) { char_width = GetOneCharInStringWidth( pDC, lpString + i ); ret = TextOut( pDC, nXStart + ( cell_width - char_width ) / 2, nYStart, lpString + i, 1 ); } - + return ret; } @@ -366,8 +366,8 @@ BOOL TextOutHoriz( HDC pDC, /* handle to DC */ int cbString, /* number of characters */ int cell_width ) { - int dX = ( cell_width && cbString == 1 ) - ? ( cell_width - GetOneCharInStringWidth( pDC, lpString ) ) / 2 + int dX = ( cell_width && cbString == 1 ) + ? ( cell_width - GetOneCharInStringWidth( pDC, lpString ) ) / 2 : 0; return TextOut( pDC, nXStart + dX, nYStart, lpString, cbString ); @@ -663,7 +663,7 @@ int DrawBond( HDC pDC, { DrawBondParity( pDC, x1, y1, x2, y2, b_parity ); } - + if (xCRU) { DrawBondCrossingCRU(pDC, x1, y1, x2, y2); @@ -726,7 +726,7 @@ void DrawPenColorFilledPolygon( HDC pDC, const POINT *pnt, int num ) ret = GetObject( penOld, sizeof( LogPen ), &LogPen ); SelectObject( pDC, penOld ); - + /* do not need to delete stock object penNew */ if (ret) { @@ -829,7 +829,7 @@ int DrawBondStereo( HDC pDC, POINT pnt[4]; - + if (b_highlight) { hHighlightPen = CreatePen( PS_SOLID, nPenWidth, clrHighlight ); @@ -1012,27 +1012,27 @@ int DrawBondParity( HDC pDC, parity_mark = parity_mark0; } - if (parity_mark == BOND_MARK_ODD) + if (parity_mark == BOND_MARK_ODD) { - p = "(-)"; + p = "(-)"; } - else if (parity_mark == BOND_MARK_EVEN) + else if (parity_mark == BOND_MARK_EVEN) { p = "(+)"; /*" |"; */ } - else if (parity_mark == BOND_MARK_UNDF) + else if (parity_mark == BOND_MARK_UNDF) { - p = "(?)"; + p = "(?)"; } - else if (parity_mark == BOND_MARK_UNKN) + else if (parity_mark == BOND_MARK_UNKN) { - p = "(u)"; + p = "(u)"; } - else if (parity_mark == BOND_MARK_ERR) + else if (parity_mark == BOND_MARK_ERR) { - p = "(!)"; + p = "(!)"; } - else + else { return 0; } @@ -1084,7 +1084,7 @@ int DrawBondCrossingCRU(HDC pDC, int x1, int y1, int x2, int y2) char *p; p = " //"; /*"(+)"; */ - + if (abs(x2 - x1) > 10 * abs(y2 - y1)) { /* almost horizontal bond; draw parity closer (1:2) to the right end */ @@ -1137,7 +1137,7 @@ int DrawBondNoStereo( HDC pDC, COLORREF clr = clrPen; switch (b_type) - { + { /* c=center, l=left, r=right */ case 0: c = 'D'; @@ -1240,8 +1240,8 @@ int DrawBondNoStereo( HDC pDC, DrawLine( pDC, x1, y1, x2, y2 ); hLongDashedPen = (HPEN) SelectObject( pDC, hSolidPen ); } - - + + /* draw lines parallel to line between bonds */ if (l || r) @@ -1252,14 +1252,14 @@ int DrawBondNoStereo( HDC pDC, bond_sep = hfont / 12.0; if (( x1 == x2 ) || ( y1 == y2 )) { - if (bond_sep < 1.0) + if (bond_sep < 1.0) { bond_sep = 1.0; } } else { - if (bond_sep < 2.0) + if (bond_sep < 2.0) { bond_sep = 2.0; } @@ -1270,14 +1270,14 @@ int DrawBondNoStereo( HDC pDC, bond_sep = hfont / 6.0; if (( x1 == x2 ) || ( y1 == y2 )) { - if (bond_sep < 2.0) + if (bond_sep < 2.0) { bond_sep = 2.0; } } else { - if (bond_sep < 4.0) + if (bond_sep < 4.0) { bond_sep = 4.0; } @@ -1397,9 +1397,9 @@ int MyTextOutABC( const char *p, int iFst, int iLst, HDC pDC ) { return 0; } - + GetCurrentPositionEx( pDC, &pt ); - + if (GetCharABCWidths( pDC, /* handle to DC */ (int) p[iFst], /* first character in range */ (int) p[iFst], /* last character in range */ @@ -1411,7 +1411,7 @@ int MyTextOutABC( const char *p, int iFst, int iLst, HDC pDC ) } TextOut( pDC, pt.x, pt.y, p + iFst, iLst - iFst + 1 ); - + if (GetCharABCWidths( pDC, /* handle to DC */ (int) p[iLst], /* first character in range */ (int) p[iLst], /* last character in range */ @@ -1422,7 +1422,7 @@ int MyTextOutABC( const char *p, int iFst, int iLst, HDC pDC ) pt.x -= abc.abcC; MoveToEx( pDC, pt.x, pt.y, NULL ); } - + return 1; } @@ -1438,15 +1438,15 @@ int DrawColorString( HDC pDC,const char *st, int xs, int ys, int bHighlightTheAt COLORREF NewBkColor=0; int bWritingAtomStringColored = 0; - /* - Draw the string character by character. - For each character within the first part of the string - make a decision if it is a subscript or a superscript - The first part ends with '/'=start of the canonical number or '(' = start of the parity mark - The superscript first character is ^ or + or - or . (. initiates double shift) - The the superscript ends with not the first character and not a digit or the end of the first part - The first character of a subscript (if it is not in the superscript) is a digit - The subscript ends a non-digit + /* + Draw the string character by character. + For each character within the first part of the string + make a decision if it is a subscript or a superscript + The first part ends with '/'=start of the canonical number or '(' = start of the parity mark + The superscript first character is ^ or + or - or . (. initiates double shift) + The the superscript ends with not the first character and not a digit or the end of the first part + The first character of a subscript (if it is not in the superscript) is a digit + The subscript ends a non-digit */ const char *p = st; UINT uPrevTextAlign = SetTextAlign( pDC, TA_UPDATECP ); @@ -1672,11 +1672,11 @@ int DrawColorString( HDC pDC,const char *st, int xs, int ys, int bHighlightTheAt /****************************************************************************/ -int DrawPreparedString( HDC pDC, - char *st1, - int shift, - int x, - int y, +int DrawPreparedString( HDC pDC, + char *st1, + int shift, + int x, + int y, int bHighlightTheAtom ) { DrawColorString( pDC, st1, x + shift, y - GetFontAscent( pDC ) / 2, bHighlightTheAtom ); @@ -1705,7 +1705,7 @@ int DrawString( HDC pDC, char *st1, int shift, int x, int y ) ys = y - afont / 2; /* Single element */ - if (strlen( st ) == 1) + if (strlen( st ) == 1) { goto draw; } @@ -1719,7 +1719,7 @@ int DrawString( HDC pDC, char *st1, int shift, int x, int y ) start = MoveHydrogenAtomToTheLeft(st, start, 'D'); start = MoveHydrogenAtomToTheLeft(st, start, 'H'); /* determine the position */ - if (( strlen( st ) == 2 ) && islower( st[1] )) + if (( strlen( st ) == 2 ) && islower( st[1] )) { goto draw; } @@ -1918,7 +1918,7 @@ void CalcTblParms( HDC hMemoryDC, tp->tblRows = inchi_max( tp->tblRows, n ); } if (tdp->nOrientation) - { + { /* here are tp->tblCols columns and tp->tblRows rows. */ tp->tblHeight = tp->thdrHeight + ( 2 * tp->tblRows + 2 )*tp->tcellHeight; /* empty lines above the header and around each cell */ tp->thdrWidth = tp->tcellWidth = inchi_max( tp->tcellWidth, tp->thdrWidth ); @@ -1930,7 +1930,7 @@ void CalcTblParms( HDC hMemoryDC, tp->ytblOffs = yoffs1; } else - { + { /* Do not believe your eyes: here are tp->tblCols rows and tp->tblRows columns. */ tp->thdrHeight = tp->tcellHeight = inchi_max( tp->thdrHeight, tp->tcellHeight ); tp->tblWidth = tp->thdrWidth + ( 2 * tp->tblRows + 2 )*tp->tcellWidth; @@ -1956,7 +1956,7 @@ int DrawTheTable( HDC hDC, int dx = tp->tcellWidth / 2; int dy = tp->tcellHeight / 2; int x1, y1, x2, y2; - + /* draw frame around the table */ ret = Rectangle( hDC, tp->xtblOffs + dx + x_offs, tp->ytblOffs + dy + y_offs, tp->xtblOffs + tp->tblWidth - dx + x_offs, tp->ytblOffs + tp->tblHeight - dy + y_offs ); /* djb-rwth: removing redundant variable *//* djb-rwth: ignoring LLVM warning: variable used to store function return value */ @@ -1979,7 +1979,7 @@ int DrawTheTable( HDC hDC, } DrawLine( hDC, x1 + x_offs, y1 + y_offs, x2 + x_offs, y2 + y_offs ); } - + /* draw lines between requested/Shown/Found types */ for (i = 0; i < tp->tblRows; i++) { @@ -2604,7 +2604,7 @@ int CreateInputStructPicture( HDC hDC, /* Calculate requested/Shown/Found table sizes */ /***********************************************/ memset(&tp, 0, sizeof(tp)); /* djb-rwth: memset_s C11/Annex K variant? */ - + #ifdef TARGET_LIB_FOR_WINCHI bDrawTbl = 0; #else @@ -2760,15 +2760,15 @@ int CreateInputStructPicture( HDC hDC, { strcat(str, ":"); } - if (bTaut) + if (bTaut) { strcat(str, " Mobile H"); } - if (bIso) + if (bIso) { strcat(str, " Isotopic"); } - if (bSter) + if (bSter) { strcat(str, " Stereo"); } @@ -2776,7 +2776,7 @@ int CreateInputStructPicture( HDC hDC, } if (pWinData->inf_at_data.szRemovedProtons[0]) { - if (str[0]) + if (str[0]) strcat( str, "; " ); /* djb-rwth: function replaced with its safe C11 variant */ strcat(str, pWinData->inf_at_data.szRemovedProtons); } @@ -3297,7 +3297,7 @@ int DisplayInputStructure( char *szOutputString, UnregisterClass( szWindowClassName, /* address of class name string */ hInstance /* handle of application instance */ ); - + /* Save window size and position */ if (WinData.rc.bottom > WinData.rc.top && WinData.rc.right > WinData.rc.left) { @@ -3306,12 +3306,12 @@ int DisplayInputStructure( char *szOutputString, dp->pdp->rcPict[2] = WinData.rc.right - WinData.rc.left; dp->pdp->rcPict[3] = WinData.rc.bottom - WinData.rc.top; } - + if (WinData.bEsc) { dp->rdp.bEsc = 1; } - + return WinData.bEsc ? 27 : 1; } #endif diff --git a/INCHI-1-SRC/INCHI_EXE/inchi-1/src/dispstru.h b/INCHI-1-SRC/INCHI_BASE/src/dispstru.h similarity index 100% rename from INCHI-1-SRC/INCHI_EXE/inchi-1/src/dispstru.h rename to INCHI-1-SRC/INCHI_BASE/src/dispstru.h diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichimain.c b/INCHI-1-SRC/INCHI_BASE/src/ichimain.c new file mode 100644 index 00000000..a575437b --- /dev/null +++ b/INCHI-1-SRC/INCHI_BASE/src/ichimain.c @@ -0,0 +1,1529 @@ +/* + * International Chemical Identifier (InChI) + * Version 1 + * Software version 1.07 + * April 30, 2024 + * + * MIT License + * + * Copyright (c) 2024 IUPAC and InChI Trust + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. +* +* The InChI library and programs are free software developed under the + * auspices of the International Union of Pure and Applied Chemistry (IUPAC). + * Originally developed at NIST. + * Modifications and additions by IUPAC and the InChI Trust. + * Some portions of code were developed/changed by external contributors + * (either contractor or volunteer) which are listed in the file + * 'External-contributors' included in this distribution. + * + * info@inchi-trust.org + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef COMPILE_ANSI_ONLY +// #include +#ifndef TARGET_LIB_FOR_WINCHI +// #include +#endif +#endif + +#include "mode.h" + +#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) +#include +#include +#endif + + +#ifdef _WIN32 +#include +#endif +#include "ichitime.h" +#include "incomdef.h" +#include "ichidrp.h" +#include "inpdef.h" +#include "ichi.h" +#include "strutil.h" +#include "util.h" +#include "ichierr.h" +#include "ichimain.h" +#include "ichicomp.h" +#include "ichi_io.h" +#ifdef TARGET_EXE_STANDALONE +#include "inchi_api.h" +#endif + +#include "bcf_s.h" +#include "permutation_util.h" + + /* Console-specific */ + + + +#ifndef TARGET_LIB_FOR_WINCHI +/* COVERS THE CODE FROM HERE TO THE END OF FILE */ + + +/* Enable/disable internal tests */ + +/* Uncomment for INCHI_LIB testing only */ +/*#define TEST_FPTRS*/ + +/* Windows-console-mode specific */ + +// int bInterrupted = 0; + + +/****************************************************************************/ +int ProcessMultipleInputFiles(int argc, char* argv[]) +{ + int i, ret = 0, nfn_ins = 0, + AMIOutStd = 0, AMILogStd = 0, AMIPrbNone = 0; + char* fn_out, * fn_log, * fn_prb; + char pNUL[] = "NUL"; + char** fn_ins = NULL, ** targv = NULL; + int ret_val; /* djb-rwth: adding return value */ /* djb-rwth: ignoring LLVM warning */ + +#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) +#ifdef _WIN64 + typedef __int64 intptr_t; /* x64 */ +#else + typedef long int intptr_t; /* VC 6.0 has no intptr_t and no x64 */ +#endif + struct _finddata_t file_info; + intptr_t hFile = -1; + int retFile, lenPath; + char* pName, * pOutPath = NULL; /* djb-rwth: ignoring LLVM warning */ + char pathname[_MAX_PATH]; + char szBlank[] = ""; /* djb-rwth: ignoring LLVM warning */ + int numFiles = 0; /* counts processed files */ +#else + int p; +#endif + + fn_ins = (char**)inchi_calloc(argc, sizeof(char*)); + if (!fn_ins) + { + fprintf(stderr, "Not enough memory.\n"); + goto exit_ami; + } + + /* Check for other options and collect inputs. */ + for (i = 1; i < argc; i++) + { + if (argv[i][0] == INCHI_OPTION_PREFX) + { + if (!inchi_stricmp(argv[i] + 1, "STDIO")) + { + fprintf(stderr, "Options AMI and STDIO are not compatible.\n"); + goto exit_ami; + } + else if (!inchi_stricmp(argv[i] + 1, "AMIOutStd")) + { + AMIOutStd = 1; + } + else if (!inchi_stricmp(argv[i] + 1, "AMILogStd")) + { + AMILogStd = 1; + } + else if (!inchi_stricmp(argv[i] + 1, "AMIPrbNone")) + { + AMIPrbNone = 1; + } +#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) + else if (!inchi_memicmp(argv[i] + 1, "OP:", 3)) + { + pOutPath = argv[i] + 4; /* output path */ + } +#endif + } + else + { + fn_ins[nfn_ins] = argv[i]; + nfn_ins++; + } + } + + if (!nfn_ins) + { + fprintf(stderr, "At least one input file is expected in AMI mode.\n"); + goto exit_ami; + } + + targv = (char**)inchi_calloc((long long)argc + 3, sizeof(char*)); /* djb-rwth: cast operator added */ + + if (!targv) + { + fprintf(stderr, "Not enough memory.\n"); + goto exit_ami; + } + +#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) + if ((pName = strrchr(fn_ins[0], INCHI_PATH_DELIM))) /* djb-rwth: addressing LLVM warning */ + { + pName++; + lenPath = pName - fn_ins[0]; + } + else + { + pName = fn_ins[0]; + lenPath = 0; + } + for (hFile = _findfirst(fn_ins[0], &file_info), retFile = 0; + !retFile && -1 != hFile; + retFile = _findnext(hFile, &file_info), numFiles++) +#else + for (p = 0; p < nfn_ins; p++) +#endif + { + int targc; +#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) + const char* fn_in; + int inlen = lenPath + strlen(file_info.name); + if (!file_info.size || (file_info.attrib & _A_SUBDIR) || inlen >= _MAX_PATH) + { + continue; + } + memcpy(pathname, fn_ins[0], lenPath); + strcpy(pathname + lenPath, file_info.name); + fn_in = pathname; + if (0 == numFiles % 5000) + { + ret_val = _heapmin(); /* reduce heap fragmentation */ /* djb-rwth: return value variable added */ + } +#else + const char* fn_in = fn_ins[p]; + int inlen = strlen(fn_in); +#endif + fn_out = fn_log = fn_prb = NULL; + + targv[0] = argv[0]; + targv[1] = (char*)fn_in; + targc = 1; + + if (AMIOutStd) + { + targv[++targc] = pNUL; + } +#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 && ALLOW_EMPTY_PATHS == 1 ) + else if (pOutPath) + { + targv[++targc] = szBlank; /* output name will be created in process_single_input(...) */ + } +#endif + else + { + /* make output name as input name plus ext. */ + fn_out = (char*)inchi_calloc((long long)inlen + 6, sizeof(char)); /* djb-rwth: cast operator added */ + if (fn_out) + { + strcpy(fn_out, fn_in); + strcat(fn_out, ".txt"); + } + targv[++targc] = fn_out; + } + + if (AMILogStd) + { + targv[++targc] = pNUL; + } +#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 && ALLOW_EMPTY_PATHS == 1 ) + else if (pOutPath) + { + targv[++targc] = szBlank; /* output name will be created in process_single_input(...) */ + } +#endif + else + { + /* Make log name as input name plus ext. */ + fn_log = (char*)inchi_calloc((long long)inlen + 6, sizeof(char)); /* djb-rwth: cast operator added */ + if (fn_log) + { + strcpy(fn_log, fn_in); + strcat(fn_log, ".log"); + } + targv[++targc] = fn_log; + } + if (AMIPrbNone) + { + targv[++targc] = pNUL; + } +#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 && ALLOW_EMPTY_PATHS == 1 ) + else if (pOutPath) + { + targv[++targc] = szBlank; /* output name will be created in process_single_input(...) */ + } +#endif + else + { + /* Make problem file name as input file name plus ext. */ + fn_prb = (char*)inchi_calloc((long long)inlen + 6, sizeof(char)); /* djb-rwth: cast operator added */ + if (fn_prb) + { + strcpy(fn_prb, fn_in); + strcat(fn_prb, ".prb"); + } + targv[++targc] = fn_prb; + } + + for (i = 1; i < argc; i++) + { + if (argv[i][0] == INCHI_OPTION_PREFX) + { + /* avoid strnicmp/strncasecmp */ + if ((strlen(argv[i]) > 3) && + (toupper(argv[i][1]) == 'A') && (toupper(argv[i][2]) == 'M') && (toupper(argv[i][3]) == 'I')) + { + continue; + } + targv[++targc] = argv[i]; + } + } + /* djb-rwth: fixing undefined index value / buffer overflow */ + ++targc; + if (targc < argc + 3) + { + targv[targc] = NULL; + } + + ret = ProcessSingleInputFile(targc, targv); /* ProcessSingleInputFile() is a former main() */ + + if (fn_out) + { + inchi_free(fn_out); + } + if (fn_log) + { + inchi_free(fn_log); + } + if (fn_prb) + { + inchi_free(fn_prb); + } + +#if ( defined( _WIN32 ) && defined( _CONSOLE ) && !defined( COMPILE_ANSI_ONLY ) ) + if (ret == CTRL_STOP_EVENT) + { + goto exit_ami; + } +#endif + } + + +exit_ami: +#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) + if (hFile != -1) + { + _findclose(hFile); + } +#endif + if (targv) + { + inchi_free(targv); + } + if (fn_ins) + { + inchi_free(fn_ins); + } + + return 0; +} + + + +/****************************************************************************/ +int ProcessSingleInputFile(int argc, char* argv[]) +{ + /**************************************/ +#endif /* #if ( BUILD_WITH_AMI == 1 ) */ +/**************************************/ + +/**** IF NOT IN AMI MODE, main() STARTS HERE ****/ + + int bReleaseVersion = bRELEASE_VERSION; + const int nStrLen = INCHI_SEGM_BUFLEN; + int nRet = 0; + int i; + long num_err, num_output, num_inp; + /* long rcPict[4] = {0,0,0,0}; */ + unsigned long ulDisplTime = 0; /* infinite, milliseconds */ + unsigned long ulTotalProcessingTime = 0; + + CANON_GLOBALS CG; + INCHI_CLOCK ic; + + char szTitle[MAX_SDF_HEADER + MAX_SDF_VALUE + 256]; + char szSdfDataValue[MAX_SDF_VALUE + 1]; + + INPUT_PARMS inp_parms; + INPUT_PARMS* ip = &inp_parms; + + STRUCT_DATA struct_data; + STRUCT_DATA* sd = &struct_data; + + ORIG_ATOM_DATA OrigAtData; /* 0=> disconnected, 1=> original */ + ORIG_ATOM_DATA* orig_inp_data = &OrigAtData; + ORIG_ATOM_DATA PrepAtData[2]; /* 0=> disconnected, 1=> original */ + ORIG_ATOM_DATA* prep_inp_data = PrepAtData; + + PINChI2* pINChI[INCHI_NUM]; + PINChI_Aux2* pINChI_Aux[INCHI_NUM]; + + char* pLF, * pTAB; + INCHI_IOS_STRING temp_string_container; + INCHI_IOS_STRING* strbuf = &temp_string_container; + INCHI_IOSTREAM outputstr, logstr, prbstr, instr; + INCHI_IOSTREAM* pout = &outputstr, * plog = &logstr, * pprb = &prbstr, * inp_file = &instr; + +#ifdef TARGET_EXE_STANDALONE + int inchi_ios_type = INCHI_IOS_TYPE_STRING; +#else + int inchi_ios_type = INCHI_IOS_TYPE_FILE; +#endif +#if ( READ_INCHI_STRING == 1 ) + const int may_get_inchi_string_input = 1; +#else + const int may_get_inchi_string_input = 0; +#endif + int bInChI2Structure = 0; + int output_error_inchi = 0; + + + /* internal tests --- */ +#ifndef TEST_FPTRS + STRUCT_FPTRS* pStructPtrs = NULL; +#else + STRUCT_FPTRS struct_fptrs, * pStructPtrs = &struct_fptrs; /* INCHI_LIB debug only */ +#endif + +#if ( defined(_WIN32) && defined(_MSC_VER) ) +#if WINVER >= 0x0501 /* XP or newer */ /* 0x0600 Vista or newer */ + DWORD tick_inchi_start, tick_inchi_stop; + tick_inchi_start = GetTickCount64(); /* djb-rwth: GetTickCount64() should be used */ +#endif +#endif + +#ifdef _WIN32 +#if ( TRACE_MEMORY_LEAKS == 1 ) + _CrtSetDbgFlag(_CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF); + /* for execution outside the VC++ debugger uncomment one of the following two */ + /*#define MY_REPORT_FILE _CRTDBG_FILE_STDERR */ + /*#define MY_REPORT_FILE _CRTDBG_FILE_STDOUT */ +#ifdef MY_REPORT_FILE + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_WARN, MY_REPORT_FILE); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ERROR, MY_REPORT_FILE); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ASSERT, MY_REPORT_FILE); +#else + _CrtSetReportMode(_CRT_WARN | _CRT_ERROR, _CRTDBG_MODE_DEBUG); +#endif + /* turn on floating point exceptions */ + { + /* Get the default control word. */ + int cw = _controlfp(0, 0); + + /* Set the exception masks OFF, turn exceptions on. */ + /*cw &=~(EM_OVERFLOW|EM_UNDERFLOW|EM_INEXACT|EM_ZERODIVIDE|EM_DENORMAL);*/ + cw &= ~(EM_OVERFLOW | EM_UNDERFLOW | EM_ZERODIVIDE | EM_DENORMAL); + + /* Set the control word. */ + _controlfp(cw, MCW_EM); +} +#endif +#endif + + sd->bUserQuit = 0; + /* djb-rwth: fixing coverity CID #499552 */ + sd->num_components[0] = 0; + sd->num_components[1] = 0; +#if ( defined( _WIN32 ) && defined( _CONSOLE ) && !defined( COMPILE_ANSI_ONLY ) ) + if (SetConsoleCtrlHandler(MyHandlerRoutine, 1)) + { + ConsoleQuit = WasInterrupted; + } +#endif + + num_inp = 0; + num_err = 0; + num_output = 0; + + inchi_ios_init(inp_file, INCHI_IOS_TYPE_FILE, NULL); + inchi_ios_init(pout, inchi_ios_type, NULL); + inchi_ios_init(plog, inchi_ios_type, stdout); + inchi_ios_init(pprb, inchi_ios_type, NULL); + memset(strbuf, 0, sizeof(*strbuf)); /* djb-rwth: memset_s C11/Annex K variant?; dereferencing strbuf */ + + if (argc == 1 || (argc == 2 && (argv[1][0] == INCHI_OPTION_PREFX) && + ((!strcmp(argv[1] + 1, "?") || !inchi_stricmp(argv[1] + 1, "help"))))) /* djb-rwth: addressing LLVM warning */ + { + HelpCommandLineParms(plog); + inchi_ios_flush(plog); + return 0; + } + + /* djb-rwth: printing out InChI version */ + if (argc == 2 && ((argv[1][0] == INCHI_OPTION_PREFX)) && (!strcmp(argv[1] + 1, "v") || !strcmp(argv[1] + 1, "V"))) + { + printf("%s\n", APP_DESCRIPTION); + return 0; + } + + /* djb-rwth: disallowing endless execution if no file(s) is given as the first argument */ + if (argc >= 2 && ((argv[1][0] == INCHI_OPTION_PREFX)) && (strcmp(argv[1] + 1, "v") || strcmp(argv[1] + 1, "V") || strcmp(argv[1] + 1, "?") || inchi_stricmp(argv[1] + 1, "help"))) + { + HelpCommandLineParms(plog); + inchi_ios_flush(plog); + return 0; + } + + /* original input structure */ + memset(orig_inp_data, 0, sizeof(*orig_inp_data)); /* djb-rwth: memset_s C11/Annex K variant? */ + memset(prep_inp_data, 0, 2 * sizeof(*prep_inp_data)); /* djb-rwth: memset_s C11/Annex K variant? */ + memset(pINChI, 0, sizeof(pINChI)); /* djb-rwth: memset_s C11/Annex K variant? */ + memset(pINChI_Aux, 0, sizeof(pINChI_Aux)); /* djb-rwth: memset_s C11/Annex K variant? */ + memset(szSdfDataValue, 0, sizeof(szSdfDataValue)); /* djb-rwth: memset_s C11/Annex K variant? */ + + memset(&CG, 0, sizeof(CG)); /* djb-rwth: memset_s C11/Annex K variant? */ + memset(&ic, 0, sizeof(ic)); /* djb-rwth: memset_s C11/Annex K variant? */ + + plog->f = stderr; + + if (0 > ReadCommandLineParms(argc, (const char**)argv, ip, + szSdfDataValue, &ulDisplTime, + bReleaseVersion, plog)) + { + goto exit_function; + } + + if (!OpenFiles(&(inp_file->f), &(pout->f), &(plog->f), &(pprb->f), ip)) + { + goto exit_function; + } + + + if (ip->bNoStructLabels) + { + ip->pSdfLabel = NULL; + ip->pSdfValue = NULL; + } + else if (ip->nInputType == INPUT_INCHI_PLAIN || + ip->nInputType == INPUT_INCHI) + { + /* the input may contain both the header and the label of the structure */ + if (!ip->pSdfLabel) + { + ip->pSdfLabel = ip->szSdfDataHeader; + } + if (!ip->pSdfValue) + { + ip->pSdfValue = szSdfDataValue; + } + } + + set_line_separators(ip->bINChIOutputOptions, &pLF, &pTAB); + + save_command_line(argc, argv, plog); + + PrintInputParms(plog, ip); + + inchi_ios_flush2(plog, stderr); + + if (0 >= inchi_strbuf_init(strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT)) + { + inchi_ios_eprint(plog, "Cannot allocate internal string buffer. Terminating\n"); + inchi_ios_flush2(plog, stderr); + goto exit_function; + } + + + /* Process InChI string as input; output may be */ + /* a) InChI string or b) structure */ + /*#if ( READ_INCHI_STRING == 1 )*/ + if (may_get_inchi_string_input && ip->nInputType == INPUT_INCHI) + { + bInChI2Structure = 0 != (ip->bReadInChIOptions & READ_INCHI_TO_STRUCTURE); + memset(sd, 0, sizeof(*sd)); /* djb-rwth: memset_s C11/Annex K variant? */ + if (bInChI2Structure) + { + /* loop through file lines here */ + INCHI_IOSTREAM tmpinpustream; + INCHI_IOS_STRING* pTmpIn = &tmpinpustream.s; + int crlf2lf = 0, preserve_lf = 1, read_result = 0; + inchi_ios_init(&tmpinpustream, INCHI_IOS_TYPE_STRING, NULL); + while (1) + { + char* p, * pi; + + read_result = inchi_strbuf_getline(pTmpIn, inp_file->f, crlf2lf, preserve_lf); + + if (read_result == -1) +#if (FIX_ONE_LINE_INCHI_INPUT_CONVERSION_ISSUE==1) + { + if (!pTmpIn->pStr) + { + break; + } + if (strlen(pTmpIn->pStr) < 8) /* 7 = strlen("InChI=1") */ + { + break; + } + } +#else + break; /* EOF or read error */ +#endif + + p = pTmpIn->pStr; + if (!p) + { + continue; + } + pi = strstr(p, "InChI=1"); + if (pi != p) + { + continue; + } + + num_inp++; + ip->lMolfileNumber = num_inp; + + ReadWriteInChI(&ic, &CG, &tmpinpustream, pout, plog, ip, sd, NULL, 0, 0, NULL, NULL, NULL, 0, NULL); + + /*fprintf( stderr, "%ld", num_inp );*/ + inchi_strbuf_reset(pTmpIn); + inchi_ios_flush2(plog, stderr); + } + fprintf(stderr, "\r"); + inchi_strbuf_close(pTmpIn); + } + else + { + /* loop through file lines within ReadWriteInChI */ + ReadWriteInChI(&ic, &CG, inp_file, pout, plog, ip, sd, NULL, 0, 0, NULL, NULL, NULL, 0, NULL); + + num_inp = sd->fPtrStart; + num_err = sd->fPtrEnd; + } + + inchi_ios_flush2(plog, stderr); + ulTotalProcessingTime = sd->ulStructTime; + /*num_inp = sd->fPtrStart; + num_err = sd->fPtrEnd; + */ + goto exit_function; + } + + + ulTotalProcessingTime = 0; + if (pStructPtrs) + { + memset(pStructPtrs, 0, sizeof(pStructPtrs[0])); /* djb-rwth: memset_s C11/Annex K variant? */ + } + output_error_inchi = ip->bINChIOutputOptions2 & INCHI_OUT_INCHI_GEN_ERROR; + + + /*************************************************************/ + /* Main cycle : read input structures and create their INChI */ + /*************************************************************/ + + + while (!sd->bUserQuit ) //&& !bInterrupted + { + int do_renumbering = 0; + int next_action; + int have_err_in_GetOneStructure = 0; + int dup_fail = 0; + ORIG_ATOM_DATA SavedOrigAtData; /* 0=> disconnected, 1=> original */ + ORIG_ATOM_DATA* saved_orig_inp_data = &SavedOrigAtData; + char ikey0[28]; + ikey0[0] = '\0'; + + + next_action = GetTheNextRecordOfInputFile(&ic, sd, ip, szTitle, + inp_file, plog, pout, pprb, + orig_inp_data, &num_inp, pStructPtrs, + &nRet, &have_err_in_GetOneStructure, + &num_err, output_error_inchi); + if (next_action == DO_EXIT_FUNCTION) + { + goto exit_function; + } + else if (next_action == DO_BREAK_MAIN_LOOP) + { + break; + } + else if (next_action == DO_CONTINUE_MAIN_LOOP) + { + if (nRet == _IS_ERROR) /* may also be _IS_SKIP ... */ + { + if (output_error_inchi) + { + Output_RecordInfo(pout, num_inp, ip->bNoStructLabels, ip->pSdfLabel, ip->pSdfValue, ip->lSdfId, + pLF, pTAB); + emit_empty_inchi(ip, num_inp, pLF, pTAB, pout); + } + } + continue; + } + + + /* Create INChI for each connected component of the structure; + optionally display them; + output INChI for the whole structure */ + +#if (RENUMBER_ATOMS_AND_RECALC_V106 == 1 ) + if (ip->bRenumber == 1) + { + do_renumbering = 1; + } +#endif + if (do_renumbering == 0) + { + /* Normal calculations */ + next_action = CalcAndPrintINCHIAndINCHIKEY(&ic, &CG, sd, ip, szTitle, + pINChI, pINChI_Aux, + inp_file, plog, pout, pprb, + orig_inp_data, prep_inp_data, &num_inp, pStructPtrs, + &nRet, have_err_in_GetOneStructure, + &num_err, output_error_inchi, + strbuf, &ulTotalProcessingTime, + pLF, pTAB, ikey0, + 0 /* not silent */); + + FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); + FreeOrigAtData(orig_inp_data); + FreeOrigAtData(prep_inp_data); + FreeOrigAtData(prep_inp_data + 1); + } + else + { + /* Internal test mode: renumber atoms and recalculate repeatedly */ + long int nrepeat = 1; + /* 2! = 2 3! = 6 4! = 24 5! = 120 6! = 520 7! = 5040 8! = 40320 */ + if (orig_inp_data->num_inp_atoms == 1) + { + nrepeat = 1; + } + else if (orig_inp_data->num_inp_atoms == 2) + { + nrepeat = 2; + } + else if (orig_inp_data->num_inp_atoms == 3) + { + nrepeat = 6; + } + else + { + nrepeat = 1000; /* 100000;*/ /*16;*/ + } + /* correct (decrease repeat number) for relatively large molecules */ + if (orig_inp_data->num_inp_atoms > 128) + { + nrepeat = 100; /* 100000;*/ /*16;*/ + } + if (orig_inp_data->num_inp_atoms > 256) + { + nrepeat = 50; /* 100000;*/ /*16;*/ + } + if (orig_inp_data->num_inp_atoms > 512) + { + nrepeat = 25; /* 100000;*/ /*16;*/ + } + if (orig_inp_data->num_inp_atoms > 1024) + { + nrepeat = 10; /* 100000;*/ /*16;*/ + } + + /*inchi_ios_eprint(plog, "Number of random atom renumberings up to: %-ld\n", nrepeat); + inchi_ios_flush2(plog, stderr);*/ + +#if 0 + else if (orig_inp_data->num_inp_atoms == 4) + { + nrepeat = 24; + } + else + { + nrepeat = 10; + } + + else if (orig_inp_data->num_inp_atoms == 4) + { + nrepeat = 24; + } + else if (orig_inp_data->num_inp_atoms == 5) + { + nrepeat = 120; + } + else if (orig_inp_data->num_inp_atoms == 6) + { + nrepeat = 520; + } + else if (orig_inp_data->num_inp_atoms == 7) + { + nrepeat = 1000; + } + else + { + nrepeat = 10000; + } +#endif + + next_action = RepeatedlyRenumberAtomsAndRecalcINCHI(&ic, &CG, sd, ip, szTitle, + pINChI, pINChI_Aux, + inp_file, plog, pout, pprb, + orig_inp_data, prep_inp_data, &num_inp, pStructPtrs, + &nRet, have_err_in_GetOneStructure, + &num_err, output_error_inchi, + strbuf, &ulTotalProcessingTime, + pLF, pTAB, nrepeat); + } /* if (ip->bRenumber == 1) */ + + if (next_action == DO_EXIT_FUNCTION) + { + goto exit_function; + } + else if (next_action == DO_BREAK_MAIN_LOOP) + { + break; + } + else if (next_action == DO_CONTINUE_MAIN_LOOP) + { + continue; + } + } /* end of main cycle - while ( !sd->bUserQuit && !bInterrupted ) */ + + +exit_function: + /* Avoid memory leaks in case of fatal error */ + if (pStructPtrs && pStructPtrs->fptr) + { + inchi_free(pStructPtrs->fptr); + } + /* Free INChI memory */ + FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); + /* Free structure data */ + FreeOrigAtData(orig_inp_data); + FreeOrigAtData(prep_inp_data); + FreeOrigAtData(prep_inp_data + 1); + /* Close files */ + inchi_ios_close(inp_file); + inchi_ios_close(pout); + inchi_ios_close(pprb); + { + int hours, minutes, seconds, mseconds; + + SplitTime(ulTotalProcessingTime, &hours, &minutes, &seconds, &mseconds); + + inchi_ios_eprint(plog, "Finished processing %ld structure%s: %ld error%s, processing time %d:%02d:%02d.%02d\n", + num_inp, num_inp == 1 ? "" : "s", + num_err, num_err == 1 ? "" : "s", + hours, minutes, seconds, mseconds / 10); + inchi_ios_flush2(plog, stderr); + } +#if ( defined(_WIN32) && defined(_MSC_VER) ) +#if WINVER >= 0x0501 /* XP or newer */ /* 0x0600 Vista or newer */ + tick_inchi_stop = GetTickCount64(); /* djb-rwth: GetTickCount64() should be used */ + inchi_ios_eprint(plog, "\nElapsed walltime: %d msec.\n", tick_inchi_stop - tick_inchi_start); + inchi_ios_flush2(plog, stderr); +#endif +#endif + /* Final cleanup */ + inchi_ios_close(plog); + inchi_strbuf_close(strbuf); + for (i = 0; i < MAX_NUM_PATHS; i++) + { + if (ip->path[i]) + { + inchi_free((void*)ip->path[i]); /* cast deliberately discards 'const' qualifier */ + ip->path[i] = NULL; + } + } + SetBitFree(&CG); +#if ( ( BUILD_WITH_AMI==1 ) && defined( _WIN32 ) && defined( _CONSOLE ) && !defined( COMPILE_ANSI_ONLY ) ) + if (bInterrupted) + { + return CTRL_STOP_EVENT; + } +#endif + + return 0; +} + + +/****************************************************************************/ +void save_command_line(int argc, char* argv[], INCHI_IOSTREAM* plog) +{ + int k; + + inchi_ios_eprint(plog, "The command line used:\n\""); + for (k = 0; k < argc - 1; k++) + { +#if( ALLOW_EMPTY_PATHS == 1 ) + inchi_ios_eprint(plog, "%-s ", argv[k][0] ? argv[k] : "\"\""); +#else + inchi_ios_eprint(plog, "%-s ", argv[k]); +#endif + } + + inchi_ios_eprint(plog, "%-s\"\n", argv[argc - 1]); + + return; +} + + +/*****************************************************************************/ +void emit_empty_inchi(INPUT_PARMS* ip, + long num_inp, + char* pLF, + char* pTAB, + INCHI_IOSTREAM* pout) +{ + if (ip->bINChIOutputOptions & INCHI_OUT_STDINCHI) + { + inchi_ios_eprint(pout, "InChI=1S//\n"); /* emit empty Std InChI */ + } + else + { + inchi_ios_eprint(pout, "InChI=1//\n"); /* emit empty InChI */ + } + inchi_ios_flush(pout); +} + + + +/*****************************************************************************/ +int GetTheNextRecordOfInputFile(struct tagINCHI_CLOCK* ic, + STRUCT_DATA* sd, INPUT_PARMS* ip, + char* szTitle, + INCHI_IOSTREAM* inp_file, + INCHI_IOSTREAM* plog, + INCHI_IOSTREAM* pout, + INCHI_IOSTREAM* pprb, + ORIG_ATOM_DATA* orig_inp_data, + long* num_inp, + STRUCT_FPTRS* pStructPtrs, + int* nRet, + int* have_err_in_GetOneStructure, + long* num_err, + int output_error_inchi) +{ + if (ip->last_struct_number && *num_inp >= ip->last_struct_number) + { + *nRet = _IS_EOF; /* simulate end of file */ + return DO_EXIT_FUNCTION; + } + + + *nRet = GetOneStructure(ic, sd, ip, szTitle, inp_file, + plog, pout, pprb, orig_inp_data, + num_inp, pStructPtrs); + + inchi_ios_flush2(plog, stderr); + + if (pStructPtrs) + pStructPtrs->cur_fptr++; + + if (sd->bUserQuit) + { + { + return DO_BREAK_MAIN_LOOP; + } + } + + *have_err_in_GetOneStructure = 0; + switch (*nRet) + { + case _IS_FATAL: + (*num_err)++; + if (output_error_inchi == 0) + { + return DO_EXIT_FUNCTION; + } + else + sd->pStrErrStruct[0] = '\0'; /* depress re-appearance of error as warning in ProcessOneStr */ + break; + case _IS_EOF: + return DO_EXIT_FUNCTION; + case _IS_ERROR: + (*num_err)++; + *have_err_in_GetOneStructure = 1; + if (output_error_inchi == 0) + { + return DO_CONTINUE_MAIN_LOOP; + } + else + sd->pStrErrStruct[0] = '\0'; /* depress re-appearance of error as warning in ProcessOneStr */ + break; + case _IS_SKIP: + return DO_CONTINUE_MAIN_LOOP; + default: + sd->pStrErrStruct[0] = '\0'; + } + + return DO_NEXT_STEP; +} + + +/****************************************************************************/ +int CalcAndPrintINCHIAndINCHIKEY(struct tagINCHI_CLOCK* ic, + CANON_GLOBALS* CG, + STRUCT_DATA* sd, + INPUT_PARMS* ip, + char* szTitle, + PINChI2* pINChI[INCHI_NUM], + PINChI_Aux2* pINChI_Aux[INCHI_NUM], + INCHI_IOSTREAM* inp_file, + INCHI_IOSTREAM* plog, + INCHI_IOSTREAM* pout, + INCHI_IOSTREAM* pprb, + ORIG_ATOM_DATA* orig_inp_data, + ORIG_ATOM_DATA* prep_inp_data, + long* num_inp, + STRUCT_FPTRS* pStructPtrs, + int* nRet, + int have_err_in_GetOneStructure, + long* num_err, + int output_error_inchi, + INCHI_IOS_STRING* strbuf, + unsigned long* pulTotalProcessingTime, + char* pLF, + char* pTAB, + char* ikey, + int silent) +{ + int nRet1; + int next_act = DO_NEXT_STEP; + /* related to hash of InChI */ + char ik_string[256]; /*^^^ Resulting InChIKey string */ + int ik_ret = 0; /*^^^ InChIKey-calc result code */ + int xhash1, xhash2; + char szXtra1[65], szXtra2[65]; + /* related to printing structure header */ + int print_record_info = 0; + INCHI_IOSTREAM temp_out; + INCHI_IOSTREAM* pout0 = &temp_out; + inchi_ios_init(pout0, INCHI_IOS_TYPE_STRING, NULL); + + + /* Calculate InChI */ + + nRet1 = ProcessOneStructureEx(ic, + CG, + sd, + ip, + szTitle, + pINChI, + pINChI_Aux, + inp_file, + plog, + pout0, /* note this */ + pprb, + orig_inp_data, + prep_inp_data, + *num_inp, strbuf, + 0 /* save_opt_bits */); + + inchi_ios_flush2(plog, stderr); + + + /* Output InChI */ + + /* print header for structure if applicable (no error arose, or have a request for empty InChI at error) */ + print_record_info = ((nRet1 == _IS_OKAY) || + (nRet1 == _IS_WARNING) || + ((nRet1 == _IS_ERROR || nRet1 == _IS_FATAL) && output_error_inchi)); + if (print_record_info) + { + Output_RecordInfo(pout, *num_inp, ip->bNoStructLabels, + ip->pSdfLabel, ip->pSdfValue, ip->lSdfId, pLF, pTAB); + } + if (pout0->s.pStr) + { + /* post-process output to correctly treat 'tabbed with InChIKey' mode */ + if (ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT) + { + if (ip->bCalcInChIHash != INCHIHASH_NONE) + { + if (pout0->s.pStr) + { + if (pout0->s.nUsedLength > 0) + { + if (pout0->s.pStr[pout0->s.nUsedLength - 1] == '\n') + { + pout0->s.pStr[pout0->s.nUsedLength - 1] = '\t'; + } + } + } + } + } + /* print InChI string (may be string for empty InChI) */ + if (!ip->bHideInChI) + { + inchi_ios_print(pout, "%-s", pout0->s.pStr); + } + } + /*inchi_ios_close(pout0);*/ /* free temporary out */ + + + *pulTotalProcessingTime += sd->ulStructTime; + + if (nRet1 == _IS_SKIP) + { + next_act = DO_CONTINUE_MAIN_LOOP; + goto exit_function; + } + + *nRet = inchi_max(*nRet, nRet1); + switch (*nRet) + { + case _IS_FATAL: + if (!have_err_in_GetOneStructure) + { + /* increment error counter only if error did not appear earlier */ + (*num_err)++; + } + if (!(ip->bINChIOutputOptions & INCHI_OUT_NO_AUX_INFO) && + (ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT)) + { + inchi_ios_print(pout, "\t"); + } + if (ip->bCalcInChIHash != INCHIHASH_NONE) + { + if (ip->bINChIOutputOptions2 & INCHI_OUT_INCHI_GEN_ERROR) + { + if (ip->bINChIOutputOptions & INCHI_OUT_STDINCHI) + { + inchi_ios_print(pout, "InChIKey=%-s\n", "MOSFIJXAXDLOML-UHFFFAOYSA-N"); + } + else + { + inchi_ios_print(pout, "InChIKey=%-s\n", "MOSFIJXAXDLOML-UHFFFAOYNA-N"); + } + } + } + inchi_ios_flush(pout); + next_act = DO_EXIT_FUNCTION; + goto exit_function; + + case _IS_ERROR: + if (!have_err_in_GetOneStructure) + { + /* increment error counter only if error did not appear earlier */ + (*num_err)++; + } + if (!(ip->bINChIOutputOptions & INCHI_OUT_NO_AUX_INFO) && + (ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT)) + { + inchi_ios_print(pout, "\t"); + } + if (ip->bCalcInChIHash != INCHIHASH_NONE) + { + if (ip->bINChIOutputOptions2 & INCHI_OUT_INCHI_GEN_ERROR) + { + if (ip->bINChIOutputOptions & INCHI_OUT_STDINCHI) + { + inchi_ios_print(pout, "InChIKey=%-s\n", "MOSFIJXAXDLOML-UHFFFAOYSA-N"); + } + else + { + inchi_ios_print(pout, "InChIKey=%-s\n", "MOSFIJXAXDLOML-UHFFFAOYNA-N"); + } + } + } + inchi_ios_flush(pout); + next_act = DO_CONTINUE_MAIN_LOOP; + goto exit_function; + + case _IS_SKIP: + next_act = DO_CONTINUE_MAIN_LOOP; + goto exit_function; + } + + + /* Calculate hash[es] of InChI */ + + if (ip->bCalcInChIHash != INCHIHASH_NONE) + { + char* buf = NULL; + size_t slen = pout0->s.nUsedLength; + + extract_inchi_substring(&buf, pout0->s.pStr, slen); + + if (NULL == buf) + { + ik_ret = INCHIKEY_INVALID_INCHI; + } + else + { + xhash1 = xhash2 = 0; + if ((ip->bCalcInChIHash == INCHIHASH_KEY_XTRA1) || + (ip->bCalcInChIHash == INCHIHASH_KEY_XTRA1_XTRA2)) + { + xhash1 = 1; + } + if ((ip->bCalcInChIHash == INCHIHASH_KEY_XTRA2) || + (ip->bCalcInChIHash == INCHIHASH_KEY_XTRA1_XTRA2)) + { + xhash2 = 1; + } + ik_ret = GetINCHIKeyFromINCHI(buf, xhash1, xhash2, ik_string, szXtra1, szXtra2); + inchi_free(buf); + } + + + /* Print hash[es] */ + + if (ik_ret == INCHIKEY_OK) + { + /* NB: correctly treat tabbed output with InChIKey & hash extensions */ + char csep = '\n'; + + if (ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT) + { + csep = '\t'; + } + if (!ip->bMergeHash) + { + inchi_ios_print(pout, "InChIKey=%-s", ik_string); + } + else + { + inchi_ios_print(pout, "InChIHash=%-s", ik_string); + } + strcpy(ikey, ik_string); + + if (szXtra1[0] && ip->bMergeHash) + { + inchi_ios_print(pout, "-%-s", szXtra1); + } + else if (szXtra1[0] && !ip->bMergeHash) + { + inchi_ios_print(pout, "%cXHash1=%-s", csep, szXtra1); + } + else if (!szXtra1[0] && ip->bMergeHash) + { + inchi_ios_print(pout, "-"); + } + + if (szXtra2[0] && ip->bMergeHash) + { + inchi_ios_print(pout, "-%-s", szXtra2); + } + else if (szXtra2[0] && !ip->bMergeHash) + { + inchi_ios_print(pout, "%cXHash2=%-s", csep, szXtra2); + } + else if (!szXtra2[0] && ip->bMergeHash) + { + inchi_ios_print(pout, "-"); + } + + inchi_ios_print(pout, "\n"); + } + else + { + inchi_ios_print(plog, "Warning (Could not compute InChIKey: ", num_inp); + switch (ik_ret) + { + case INCHIKEY_UNKNOWN_ERROR: + inchi_ios_print(plog, "unresolved error)"); + break; + case INCHIKEY_EMPTY_INPUT: + inchi_ios_print(plog, "got an empty string)"); + break; + case INCHIKEY_INVALID_INCHI_PREFIX: + case INCHIKEY_INVALID_INCHI: + case INCHIKEY_INVALID_STD_INCHI: + inchi_ios_print(plog, "no valid InChI string found)"); + break; + case INCHIKEY_NOT_ENOUGH_MEMORY: + inchi_ios_print(plog, "not enough memory to treat the string)"); + break; + default: inchi_ios_print(plog, "internal program error)"); + break; + } + inchi_ios_print(plog, " structure #%-lu.\n", *num_inp); + if (ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT) + { + inchi_ios_print(pout, "\n"); + } + } + + if (!silent) + { + inchi_ios_flush(pout); + inchi_ios_flush2(plog, stderr); + } + else + { + inchi_ios_free_str(pout); + inchi_ios_free_str(plog); + } + } + else + { + inchi_ios_flush(pout); + } + +exit_function: + inchi_ios_close(pout0); /* free temporary out */ + + return next_act; +} + + +#ifdef RENUMBER_ATOMS_AND_RECALC_V106 + +/*****************************************************************************/ + +int numbers_rrar[PERMAXATOMS]; /* djb-rwth: placed as a global variable to avoid function buffer issues */ +int RepeatedlyRenumberAtomsAndRecalcINCHI(struct tagINCHI_CLOCK* ic, + CANON_GLOBALS* CG, + STRUCT_DATA* sd, + INPUT_PARMS* ip, + char* szTitle, + PINChI2* pINChI[INCHI_NUM], + PINChI_Aux2* pINChI_Aux[INCHI_NUM], + INCHI_IOSTREAM* inp_file, + INCHI_IOSTREAM* plog, + INCHI_IOSTREAM* pout, + INCHI_IOSTREAM* pprb, + ORIG_ATOM_DATA* orig_inp_data, + ORIG_ATOM_DATA* prep_inp_data, + long* num_inp, + STRUCT_FPTRS* pStructPtrs, + int* nRet, + int have_err_in_GetOneStructure, + long* num_err, + int output_error_inchi, + INCHI_IOS_STRING* strbuf, + unsigned long* pulTotalProcessingTime, + char* pLF, + char* pTAB, + long int nrepeat) +{ + int next_action = DO_NEXT_STEP; + int dup_fail = 0; + ORIG_ATOM_DATA SavedOrigAtData; /* 0=> disconnected, 1=> original */ + ORIG_ATOM_DATA* saved_orig_inp_data = &SavedOrigAtData; + char ikey0[28]; + + const int very_silent = 2; /* 3 0;*/ + + /* Internal test mode: renumber atoms and recalculate repeatedly */ + + /* do not forget to use /key and to not use /auxnone */ + + + ikey0[0] = '\0'; + { + int k; + for (k = 0; k < orig_inp_data->num_inp_atoms; k++) + { + numbers_rrar[k] = k; + } + for (k = orig_inp_data->num_inp_atoms; k < PERMAXATOMS; k++) + { + numbers_rrar[k] = -1; + } + } + + + + +#if BIG_POLY_DEBUG + { int k; ITRACE_("\nAtoms = {"); for (k = 0; k < orig_inp_data->num_inp_atoms - 1; k++) ITRACE_(" %-03d,", numbers_rrar[k]); ITRACE_(" %-03d }", numbers_rrar[orig_inp_data->num_inp_atoms - 1]); } + OrigAtData_DebugTrace(orig_inp_data); + OrigAtDataPolymer_DebugTrace(orig_inp_data->polymer); +#endif + + memset(saved_orig_inp_data, 0, sizeof(*saved_orig_inp_data)); /* djb-rwth: memset_s C11/Annex K variant? */ + dup_fail = OrigAtData_Duplicate(saved_orig_inp_data, orig_inp_data); + + next_action = CalcAndPrintINCHIAndINCHIKEY(ic, CG, sd, ip, szTitle, + pINChI, pINChI_Aux, + inp_file, plog, pout, pprb, + orig_inp_data, prep_inp_data, num_inp, pStructPtrs, + nRet, have_err_in_GetOneStructure, + num_err, output_error_inchi, + strbuf, pulTotalProcessingTime, + pLF, pTAB, ikey0, very_silent); + FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); + FreeOrigAtData(orig_inp_data); + FreeOrigAtData(prep_inp_data); + FreeOrigAtData(prep_inp_data + 1); + + + if (ikey0[0]) + { + if (very_silent < 2) + { + inchi_ios_eprint(plog, "#%-ld-%08ld\t...\t%-s\t%s%s%s%s\n", *num_inp, 1, ikey0, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue)); + } + } + + + if (!dup_fail) + { + int irepeat = 0; + int ndiff = 0; + int n_written_problems = 0; + char ikey[28]; + ikey[0] = '\0'; + for (irepeat = 0; irepeat < nrepeat - 1; irepeat++) + { + dup_fail = OrigAtData_Duplicate(orig_inp_data, saved_orig_inp_data); + if (!dup_fail) + { + shuffle((void*)numbers_rrar, orig_inp_data->num_inp_atoms, sizeof(int)); + OrigAtData_Permute(orig_inp_data, saved_orig_inp_data, numbers_rrar); +#if BIG_POLY_DEBUG + { int k; ITRACE_("\nAtoms = {"); for (k = 0; k < orig_inp_data->num_inp_atoms - 1; k++) ITRACE_(" %-03d,", numbers_rrar[k]); ITRACE_(" %-03d }", numbers_rrar[orig_inp_data->num_inp_atoms - 1]); } + OrigAtData_DebugTrace(saved_orig_inp_data); + OrigAtData_DebugTrace(orig_inp_data); + OrigAtDataPolymer_DebugTrace(saved_orig_inp_data->polymer); + OrigAtDataPolymer_DebugTrace(orig_inp_data->polymer); +#endif + next_action = CalcAndPrintINCHIAndINCHIKEY(ic, CG, sd, ip, szTitle, + pINChI, pINChI_Aux, + inp_file, plog, pout, pprb, + orig_inp_data, + prep_inp_data, num_inp, pStructPtrs, + nRet, have_err_in_GetOneStructure, + num_err, output_error_inchi, + strbuf, pulTotalProcessingTime, + pLF, pTAB, ikey, + 0 /* 1 be silent */); + + + if (ikey0[0] && ikey[0]) + { + if (strcmp(ikey, ikey0)) + { + int result, bINChIOutputOptions = ip->bINChIOutputOptions; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ + ndiff++; + /*inchi_ios_eprint( plog, "!!! #%-ld-%05ld %s%s%s%s\tcurr %-s != %-s orig\n", *num_inp, irepeat + 2, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ), ikey, ikey0 );*/ + /*inchi_ios_eprint( plog, "!!! %s%s%s%s renum#%05ld\t%-s != %-s\n", SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ), irepeat + 2, ikey, ikey0 );*/ + inchi_ios_eprint(plog, "!!! #%-ld %s%s%s%s\t%-s --> %-s @ renum#%06d/%06ld\n", *num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue), ikey0, ikey, irepeat + 2, nrepeat); + if (!very_silent) + { + int k; + inchi_ios_eprint(plog, "Atoms = {"); + for (k = 0; k < orig_inp_data->num_inp_atoms - 1; k++) + { + inchi_ios_eprint(plog, " %-d,", numbers_rrar[k] + 1); + } + inchi_ios_eprint(plog, " %-d }\n\n", numbers_rrar[orig_inp_data->num_inp_atoms - 1] + 1); + } + ip->bINChIOutputOptions |= INCHI_OUT_SDFILE_ONLY; + result = OrigAtData_SaveMolfile(orig_inp_data, sd, ip, *num_inp, pprb); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ + inchi_ios_flush(pprb); + ip->bINChIOutputOptions = bINChIOutputOptions; + if (result == 0) + { + n_written_problems++; + } +#if 0 + /* second pass, non-silent one */ + FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); + FreeOrigAtData(orig_inp_data); + FreeOrigAtData(prep_inp_data); + FreeOrigAtData(prep_inp_data + 1); + dup_fail = OrigAtData_Duplicate(orig_inp_data, saved_orig_inp_data); + if (!dup_fail) + { + OrigAtData_Permute(orig_inp_data, saved_orig_inp_data, numbers_rrar); + next_action = CalcAndPrintINCHIAndINCHIKEY(ic, CG, sd, ip, szTitle, + pINChI, pINChI_Aux, + inp_file, plog, pout, pprb, + orig_inp_data, + prep_inp_data, num_inp, pStructPtrs, + nRet, have_err_in_GetOneStructure, + num_err, output_error_inchi, + strbuf, pulTotalProcessingTime, + pLF, pTAB, ikey, 0); + } +#endif + } + + if (irepeat == nrepeat - 2) + { + if (very_silent < 2) + { + inchi_ios_eprint(plog, "...........\n#%-ld-%08ld\t...\t%-s\t%s%s%s%s\n", *num_inp, irepeat + 2, ikey0, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue)); + } + } + + } + } + FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); + FreeOrigAtData(orig_inp_data); + FreeOrigAtData(prep_inp_data); + FreeOrigAtData(prep_inp_data + 1); + +#ifdef STOP_AFTER_FIRST_CHANGE_ON_RENUMBERING + if (ndiff == 1) + { + next_action = DO_CONTINUE_MAIN_LOOP; + break; + } +#endif + } + if (ndiff == 0) + { + if (very_silent < 3) + { + /*inchi_ios_eprint( plog, "#%-ld-%05ld\t...\tOK ALL\n", *num_inp, nrepeat );*/ + /*inchi_ios_eprint( plog, "OK #%-ld %s%s%s%s\n", *num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue));*/ + /*inchi_ios_eprint(plog, "#%-ld\n", *num_inp);*/ + inchi_ios_eprint(plog, "OK #%-ld %s%s%s%s\t%-s\t Same for %-d/%-d renums\n", *num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue), ikey0, nrepeat, nrepeat); + } + } + else + { +#ifdef STOP_AFTER_FIRST_CHANGE_ON_RENUMBERING + /*inchi_ios_eprint( plog, "#%-ld-%05ld\t...\tDIFF %-d\n", num_inp, nrepeat, ndiff );*/ +#else + inchi_ios_eprint(plog, "#%-ld-%05ld\t...\tDIFF %-d\n", num_inp, nrepeat, ndiff); +#endif + } + + FreeOrigAtData(saved_orig_inp_data); + } + + return next_action; +} + + +#endif diff --git a/INCHI-1-SRC/INCHI_EXE/inchi-1/src/CMakeLists.txt b/INCHI-1-SRC/INCHI_EXE/inchi-1/src/CMakeLists.txt index ead78dec..8b83d19d 100644 --- a/INCHI-1-SRC/INCHI_EXE/inchi-1/src/CMakeLists.txt +++ b/INCHI-1-SRC/INCHI_EXE/inchi-1/src/CMakeLists.txt @@ -25,9 +25,10 @@ include_directories(${P_BASE} ${P_CURRENT}) add_executable(inchi-1) target_sources(inchi-1 PRIVATE - dispstru.c - dispstru.h - ichimain.c + main.c + ${P_BASE}/ichimain.c + ${P_BASE}/dispstru.c + ${P_BASE}/dispstru.h ${P_BASE}/bcf_s.h ${P_BASE}/bcf_s.c ${P_BASE}/extr_ct.h @@ -132,8 +133,8 @@ if(MATH_LIBRARY) target_link_libraries(inchi-1 PUBLIC ${MATH_LIBRARY}) endif() -target_compile_definitions(inchi-1 PRIVATE - COMPILE_ANSI_ONLY +target_compile_definitions(inchi-1 PRIVATE + COMPILE_ANSI_ONLY TARGET_EXE_STANDALONE ADD_AMI_MODE ) @@ -141,4 +142,4 @@ target_compile_definitions(inchi-1 PRIVATE target_include_directories(inchi-1 PUBLIC "${PROJECT_BINARY_DIR}") string(REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") -string(REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") \ No newline at end of file +string(REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") diff --git a/INCHI-1-SRC/INCHI_EXE/inchi-1/src/ichimain.c b/INCHI-1-SRC/INCHI_EXE/inchi-1/src/backup_ichimain.c similarity index 100% rename from INCHI-1-SRC/INCHI_EXE/inchi-1/src/ichimain.c rename to INCHI-1-SRC/INCHI_EXE/inchi-1/src/backup_ichimain.c diff --git a/INCHI-1-SRC/INCHI_EXE/inchi-1/src/main.c b/INCHI-1-SRC/INCHI_EXE/inchi-1/src/main.c new file mode 100644 index 00000000..5e1f3f46 --- /dev/null +++ b/INCHI-1-SRC/INCHI_EXE/inchi-1/src/main.c @@ -0,0 +1,266 @@ +/* + * International Chemical Identifier (InChI) + * Version 1 + * Software version 1.07 + * April 30, 2024 + * + * MIT License + * + * Copyright (c) 2024 IUPAC and InChI Trust + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. +* +* The InChI library and programs are free software developed under the + * auspices of the International Union of Pure and Applied Chemistry (IUPAC). + * Originally developed at NIST. + * Modifications and additions by IUPAC and the InChI Trust. + * Some portions of code were developed/changed by external contributors + * (either contractor or volunteer) which are listed in the file + * 'External-contributors' included in this distribution. + * + * info@inchi-trust.org + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef COMPILE_ANSI_ONLY +#include +#ifndef TARGET_LIB_FOR_WINCHI +#include +#endif +#endif + +#include "../../../INCHI_BASE/src/mode.h" + +#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) +#include +#include +#endif + + +#ifdef _WIN32 +#include +#endif +#include "../../../INCHI_BASE/src/ichitime.h" +#include "../../../INCHI_BASE/src/incomdef.h" +#include "../../../INCHI_BASE/src/ichidrp.h" +#include "../../../INCHI_BASE/src/inpdef.h" +#include "../../../INCHI_BASE/src/ichi.h" +#include "../../../INCHI_BASE/src/strutil.h" +#include "../../../INCHI_BASE/src/util.h" +#include "../../../INCHI_BASE/src/ichierr.h" +#include "../../../INCHI_BASE/src/ichimain.h" +#include "../../../INCHI_BASE/src/ichicomp.h" +#include "../../../INCHI_BASE/src/ichi_io.h" +#ifdef TARGET_EXE_STANDALONE +#include "../../../INCHI_BASE/src/inchi_api.h" +#endif + +#include "../../../INCHI_BASE/src/bcf_s.h" +#include "../../../INCHI_BASE/src/permutation_util.h" + + /* Console-specific */ + +#if !defined(TARGET_API_LIB) && !defined(COMPILE_ANSI_ONLY) + +/* Use Windows additional features */ + + +/****************************************************************************/ +int user_quit(struct tagINCHI_CLOCK* ic, + const char* msg, + unsigned long ulMaxTime) +{ +#if defined(TARGET_LIB_FOR_WINCHI) + return 0; +#endif + +#if ( !defined(TARGET_LIB_FOR_WINCHI) && defined(_WIN32) ) + + int quit, enter, ret; + printf("%s", msg); /* djb-rwth: format string added for security */ + if (ulMaxTime) + { + inchiTime ulEndTime; + InchiTimeGet(&ulEndTime); + InchiTimeAddMsec(ic, &ulEndTime, ulMaxTime); + while (!_kbhit()) + { + if (bInchiTimeIsOver(ic, &ulEndTime)) + { + printf("\n"); + return 0; + } + MySleep(100); + } + } + while (1) + { + quit = ('q' == (ret = _getch()) || 'Q' == ret || /*Esc*/ 27 == ret); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ + enter = ('\r' == ret); + if (ret == 0xE0) + { + ret = _getch(); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ + } + else + { + _putch(ret); /* echo */ + } + if (quit || enter) + { + break; + } + printf("\r"); + printf("%s", msg); /* djb-rwth: format string added for security */ + } + _putch('\n'); + + return quit; +#else + return 0; + +#endif /* #if ( defined(_WIN32) && !defined(TARGET_LIB_FOR_WINCHI) ) */ +} + + +/****************************************************************************/ +void eat_keyboard_input(void) +{ + int ret_val; /* djb-rwth: adding return value */ /* djb-rwth: ignoring LLVM warning */ +#ifndef TARGET_LIB_FOR_WINCHI + + while (_kbhit()) + { + if (0xE0 == _getch()) + { + ret_val = _getch(); /* djb-rwth: return value variable added */ + } + } + +#endif +} + +#endif /* end of !COMPILE_ANSI_ONLY */ + + +// #ifndef TARGET_LIB_FOR_WINCHI +/* COVERS THE CODE FROM HERE TO THE END OF FILE */ + + +/* Enable/disable internal tests */ + +/* Uncomment for INCHI_LIB testing only */ +/*#define TEST_FPTRS*/ + +/* Windows-console-mode specific */ + +int bInterrupted = 0; + +#if ( defined( _WIN32 ) && defined( _CONSOLE ) ) +#ifndef COMPILE_ANSI_ONLY + + +/****************************************************************************/ +BOOL WINAPI MyHandlerRoutine(DWORD dwCtrlType /* control signal type */) +{ + if (dwCtrlType == CTRL_C_EVENT || + dwCtrlType == CTRL_BREAK_EVENT || + dwCtrlType == CTRL_CLOSE_EVENT || + dwCtrlType == CTRL_LOGOFF_EVENT) + { + bInterrupted = 1; + return TRUE; + } + return FALSE; +} + + +/****************************************************************************/ +int WasInterrupted(void) +{ +#ifdef _DEBUG + if (bInterrupted) + { + int stop = 1; /* for debug only */ + } +#endif + return bInterrupted; +} +#if ( BUILD_WITH_AMI == 1 ) +#define CTRL_STOP_EVENT 101 +#endif +#endif /* ifndef COMPILE_ANSI_ONLY */ +#endif /* if( defined( _WIN32 ) && defined( _CONSOLE ) ) */ + + + +/****************************************************************************/ +int main(int argc, char* argv[]) +{ +#ifdef GHI100_FIX +#if ((SPRINTF_FLAG != 1) && (SPRINTF_FLAG != 2)) + setlocale(LC_ALL, "en-US"); /* djb-rwth: setting all locales to "en-US" */ +#endif +#endif + +/*************************/ +// #if ( BUILD_WITH_AMI == 1 ) +/*************************/ + +/**** IF IN AMI MODE, main() STARTS HERE ****/ + int i, ret = 0, ami = 0; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ + + /* Check if multiple inputs expected */ + for (i = 1; i < argc; i++) + { + if (argv[i][0] == INCHI_OPTION_PREFX) + { + if (!inchi_stricmp(argv[i] + 1, "AMI")) + { + ami = 1; + break; + } + } + } + + if (ami) + { + ret = ProcessMultipleInputFiles(argc, argv); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ + } + else + { + ret = ProcessSingleInputFile(argc, argv); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ + } + + return 0; +} + + +// #endif /* ifndef TARGET_LIB_FOR_WINCHI */ + From 8b0f9d84e5154177a9cb24a33100f441f7efe727 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 8 Dec 2025 08:43:05 +0000 Subject: [PATCH 20/69] formatting --- INCHI-1-SRC/INCHI_BASE/src/ichimain.c | 3 +- .../INCHI_EXE/inchi-1/src/backup_ichimain.c | 1688 ----------------- 2 files changed, 2 insertions(+), 1689 deletions(-) delete mode 100644 INCHI-1-SRC/INCHI_EXE/inchi-1/src/backup_ichimain.c diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichimain.c b/INCHI-1-SRC/INCHI_BASE/src/ichimain.c index a575437b..ccdc9aeb 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichimain.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichimain.c @@ -363,7 +363,8 @@ int ProcessMultipleInputFiles(int argc, char* argv[]) /****************************************************************************/ int ProcessSingleInputFile(int argc, char* argv[]) { - /**************************************/ + +/**************************************/ #endif /* #if ( BUILD_WITH_AMI == 1 ) */ /**************************************/ diff --git a/INCHI-1-SRC/INCHI_EXE/inchi-1/src/backup_ichimain.c b/INCHI-1-SRC/INCHI_EXE/inchi-1/src/backup_ichimain.c deleted file mode 100644 index cc422b04..00000000 --- a/INCHI-1-SRC/INCHI_EXE/inchi-1/src/backup_ichimain.c +++ /dev/null @@ -1,1688 +0,0 @@ -/* - * International Chemical Identifier (InChI) - * Version 1 - * Software version 1.07 - * April 30, 2024 - * - * MIT License - * - * Copyright (c) 2024 IUPAC and InChI Trust - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. -* -* The InChI library and programs are free software developed under the - * auspices of the International Union of Pure and Applied Chemistry (IUPAC). - * Originally developed at NIST. - * Modifications and additions by IUPAC and the InChI Trust. - * Some portions of code were developed/changed by external contributors - * (either contractor or volunteer) which are listed in the file - * 'External-contributors' included in this distribution. - * - * info@inchi-trust.org - * -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef COMPILE_ANSI_ONLY -#include -#ifndef TARGET_LIB_FOR_WINCHI -#include -#endif -#endif - -#include "../../../INCHI_BASE/src/mode.h" - -#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) -#include -#include -#endif - - -#ifdef _WIN32 -#include -#endif -#include "../../../INCHI_BASE/src/ichitime.h" -#include "../../../INCHI_BASE/src/incomdef.h" -#include "../../../INCHI_BASE/src/ichidrp.h" -#include "../../../INCHI_BASE/src/inpdef.h" -#include "../../../INCHI_BASE/src/ichi.h" -#include "../../../INCHI_BASE/src/strutil.h" -#include "../../../INCHI_BASE/src/util.h" -#include "../../../INCHI_BASE/src/ichierr.h" -#include "../../../INCHI_BASE/src/ichimain.h" -#include "../../../INCHI_BASE/src/ichicomp.h" -#include "../../../INCHI_BASE/src/ichi_io.h" -#ifdef TARGET_EXE_STANDALONE -#include "../../../INCHI_BASE/src/inchi_api.h" -#endif - -#include "../../../INCHI_BASE/src/bcf_s.h" -#include "../../../INCHI_BASE/src/permutation_util.h" - - /* Console-specific */ - -#if !defined(TARGET_API_LIB) && !defined(COMPILE_ANSI_ONLY) - -/* Use Windows additional features */ - - -/****************************************************************************/ -int user_quit(struct tagINCHI_CLOCK* ic, - const char* msg, - unsigned long ulMaxTime) -{ -#if defined(TARGET_LIB_FOR_WINCHI) - return 0; -#endif - -#if ( !defined(TARGET_LIB_FOR_WINCHI) && defined(_WIN32) ) - - int quit, enter, ret; - printf("%s", msg); /* djb-rwth: format string added for security */ - if (ulMaxTime) - { - inchiTime ulEndTime; - InchiTimeGet(&ulEndTime); - InchiTimeAddMsec(ic, &ulEndTime, ulMaxTime); - while (!_kbhit()) - { - if (bInchiTimeIsOver(ic, &ulEndTime)) - { - printf("\n"); - return 0; - } - MySleep(100); - } - } - while (1) - { - quit = ('q' == (ret = _getch()) || 'Q' == ret || /*Esc*/ 27 == ret); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ - enter = ('\r' == ret); - if (ret == 0xE0) - { - ret = _getch(); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ - } - else - { - _putch(ret); /* echo */ - } - if (quit || enter) - { - break; - } - printf("\r"); - printf("%s", msg); /* djb-rwth: format string added for security */ - } - _putch('\n'); - - return quit; -#else - return 0; - -#endif /* #if ( defined(_WIN32) && !defined(TARGET_LIB_FOR_WINCHI) ) */ -} - - -/****************************************************************************/ -void eat_keyboard_input(void) -{ - int ret_val; /* djb-rwth: adding return value */ /* djb-rwth: ignoring LLVM warning */ -#ifndef TARGET_LIB_FOR_WINCHI - - while (_kbhit()) - { - if (0xE0 == _getch()) - { - ret_val = _getch(); /* djb-rwth: return value variable added */ - } - } - -#endif -} - -#endif /* end of !COMPILE_ANSI_ONLY */ - - -#ifndef TARGET_LIB_FOR_WINCHI -/* COVERS THE CODE FROM HERE TO THE END OF FILE */ - - -/* Enable/disable internal tests */ - -/* Uncomment for INCHI_LIB testing only */ -/*#define TEST_FPTRS*/ - -/* Windows-console-mode specific */ - -int bInterrupted = 0; - -#if ( defined( _WIN32 ) && defined( _CONSOLE ) ) -#ifndef COMPILE_ANSI_ONLY - - -/****************************************************************************/ -BOOL WINAPI MyHandlerRoutine(DWORD dwCtrlType /* control signal type */) -{ - if (dwCtrlType == CTRL_C_EVENT || - dwCtrlType == CTRL_BREAK_EVENT || - dwCtrlType == CTRL_CLOSE_EVENT || - dwCtrlType == CTRL_LOGOFF_EVENT) - { - bInterrupted = 1; - return TRUE; - } - return FALSE; -} - - -/****************************************************************************/ -int WasInterrupted(void) -{ -#ifdef _DEBUG - if (bInterrupted) - { - int stop = 1; /* for debug only */ - } -#endif - return bInterrupted; -} -#if ( BUILD_WITH_AMI == 1 ) -#define CTRL_STOP_EVENT 101 -#endif -#endif /* ifndef COMPILE_ANSI_ONLY */ -#endif /* if( defined( _WIN32 ) && defined( _CONSOLE ) ) */ - - - -/****************************************************************************/ -int main(int argc, char* argv[]) -{ -#ifdef GHI100_FIX -#if ((SPRINTF_FLAG != 1) && (SPRINTF_FLAG != 2)) - setlocale(LC_ALL, "en-US"); /* djb-rwth: setting all locales to "en-US" */ -#endif -#endif - - /*************************/ -#if ( BUILD_WITH_AMI == 1 ) -/*************************/ - -/**** IF IN AMI MODE, main() STARTS HERE ****/ - int i, ret = 0, ami = 0; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ - - /* Check if multiple inputs expected */ - for (i = 1; i < argc; i++) - { - if (argv[i][0] == INCHI_OPTION_PREFX) - { - if (!inchi_stricmp(argv[i] + 1, "AMI")) - { - ami = 1; - break; - } - } - } - - if (ami) - { - ret = ProcessMultipleInputFiles(argc, argv); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ - } - else - { - ret = ProcessSingleInputFile(argc, argv); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ - } - - return 0; -} - - -/****************************************************************************/ -int ProcessMultipleInputFiles(int argc, char* argv[]) -{ - int i, ret = 0, nfn_ins = 0, - AMIOutStd = 0, AMILogStd = 0, AMIPrbNone = 0; - char* fn_out, * fn_log, * fn_prb; - char pNUL[] = "NUL"; - char** fn_ins = NULL, ** targv = NULL; - int ret_val; /* djb-rwth: adding return value */ /* djb-rwth: ignoring LLVM warning */ - -#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) -#ifdef _WIN64 - typedef __int64 intptr_t; /* x64 */ -#else - typedef long int intptr_t; /* VC 6.0 has no intptr_t and no x64 */ -#endif - struct _finddata_t file_info; - intptr_t hFile = -1; - int retFile, lenPath; - char* pName, * pOutPath = NULL; /* djb-rwth: ignoring LLVM warning */ - char pathname[_MAX_PATH]; - char szBlank[] = ""; /* djb-rwth: ignoring LLVM warning */ - int numFiles = 0; /* counts processed files */ -#else - int p; -#endif - - fn_ins = (char**)inchi_calloc(argc, sizeof(char*)); - if (!fn_ins) - { - fprintf(stderr, "Not enough memory.\n"); - goto exit_ami; - } - - /* Check for other options and collect inputs. */ - for (i = 1; i < argc; i++) - { - if (argv[i][0] == INCHI_OPTION_PREFX) - { - if (!inchi_stricmp(argv[i] + 1, "STDIO")) - { - fprintf(stderr, "Options AMI and STDIO are not compatible.\n"); - goto exit_ami; - } - else if (!inchi_stricmp(argv[i] + 1, "AMIOutStd")) - { - AMIOutStd = 1; - } - else if (!inchi_stricmp(argv[i] + 1, "AMILogStd")) - { - AMILogStd = 1; - } - else if (!inchi_stricmp(argv[i] + 1, "AMIPrbNone")) - { - AMIPrbNone = 1; - } -#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) - else if (!inchi_memicmp(argv[i] + 1, "OP:", 3)) - { - pOutPath = argv[i] + 4; /* output path */ - } -#endif - } - else - { - fn_ins[nfn_ins] = argv[i]; - nfn_ins++; - } - } - - if (!nfn_ins) - { - fprintf(stderr, "At least one input file is expected in AMI mode.\n"); - goto exit_ami; - } - - targv = (char**)inchi_calloc((long long)argc + 3, sizeof(char*)); /* djb-rwth: cast operator added */ - - if (!targv) - { - fprintf(stderr, "Not enough memory.\n"); - goto exit_ami; - } - -#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) - if ((pName = strrchr(fn_ins[0], INCHI_PATH_DELIM))) /* djb-rwth: addressing LLVM warning */ - { - pName++; - lenPath = pName - fn_ins[0]; - } - else - { - pName = fn_ins[0]; - lenPath = 0; - } - for (hFile = _findfirst(fn_ins[0], &file_info), retFile = 0; - !retFile && -1 != hFile; - retFile = _findnext(hFile, &file_info), numFiles++) -#else - for (p = 0; p < nfn_ins; p++) -#endif - { - int targc; -#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) - const char* fn_in; - int inlen = lenPath + strlen(file_info.name); - if (!file_info.size || (file_info.attrib & _A_SUBDIR) || inlen >= _MAX_PATH) - { - continue; - } - memcpy(pathname, fn_ins[0], lenPath); - strcpy(pathname + lenPath, file_info.name); - fn_in = pathname; - if (0 == numFiles % 5000) - { - ret_val = _heapmin(); /* reduce heap fragmentation */ /* djb-rwth: return value variable added */ - } -#else - const char* fn_in = fn_ins[p]; - int inlen = strlen(fn_in); -#endif - fn_out = fn_log = fn_prb = NULL; - - targv[0] = argv[0]; - targv[1] = (char*)fn_in; - targc = 1; - - if (AMIOutStd) - { - targv[++targc] = pNUL; - } -#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 && ALLOW_EMPTY_PATHS == 1 ) - else if (pOutPath) - { - targv[++targc] = szBlank; /* output name will be created in process_single_input(...) */ - } -#endif - else - { - /* make output name as input name plus ext. */ - fn_out = (char*)inchi_calloc((long long)inlen + 6, sizeof(char)); /* djb-rwth: cast operator added */ - if (fn_out) - { - strcpy(fn_out, fn_in); - strcat(fn_out, ".txt"); - } - targv[++targc] = fn_out; - } - - if (AMILogStd) - { - targv[++targc] = pNUL; - } -#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 && ALLOW_EMPTY_PATHS == 1 ) - else if (pOutPath) - { - targv[++targc] = szBlank; /* output name will be created in process_single_input(...) */ - } -#endif - else - { - /* Make log name as input name plus ext. */ - fn_log = (char*)inchi_calloc((long long)inlen + 6, sizeof(char)); /* djb-rwth: cast operator added */ - if (fn_log) - { - strcpy(fn_log, fn_in); - strcat(fn_log, ".log"); - } - targv[++targc] = fn_log; - } - if (AMIPrbNone) - { - targv[++targc] = pNUL; - } -#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 && ALLOW_EMPTY_PATHS == 1 ) - else if (pOutPath) - { - targv[++targc] = szBlank; /* output name will be created in process_single_input(...) */ - } -#endif - else - { - /* Make problem file name as input file name plus ext. */ - fn_prb = (char*)inchi_calloc((long long)inlen + 6, sizeof(char)); /* djb-rwth: cast operator added */ - if (fn_prb) - { - strcpy(fn_prb, fn_in); - strcat(fn_prb, ".prb"); - } - targv[++targc] = fn_prb; - } - - for (i = 1; i < argc; i++) - { - if (argv[i][0] == INCHI_OPTION_PREFX) - { - /* avoid strnicmp/strncasecmp */ - if ((strlen(argv[i]) > 3) && - (toupper(argv[i][1]) == 'A') && (toupper(argv[i][2]) == 'M') && (toupper(argv[i][3]) == 'I')) - { - continue; - } - targv[++targc] = argv[i]; - } - } - /* djb-rwth: fixing undefined index value / buffer overflow */ - ++targc; - if (targc < argc + 3) - { - targv[targc] = NULL; - } - - ret = ProcessSingleInputFile(targc, targv); /* ProcessSingleInputFile() is a former main() */ - - if (fn_out) - { - inchi_free(fn_out); - } - if (fn_log) - { - inchi_free(fn_log); - } - if (fn_prb) - { - inchi_free(fn_prb); - } - -#if ( defined( _WIN32 ) && defined( _CONSOLE ) && !defined( COMPILE_ANSI_ONLY ) ) - if (ret == CTRL_STOP_EVENT) - { - goto exit_ami; - } -#endif - } - - -exit_ami: -#if( BUILD_WITH_AMI == 1 && defined( _MSC_VER ) && MSC_AMI == 1 ) - if (hFile != -1) - { - _findclose(hFile); - } -#endif - if (targv) - { - inchi_free(targv); - } - if (fn_ins) - { - inchi_free(fn_ins); - } - - return 0; -} - - - -/****************************************************************************/ -int ProcessSingleInputFile(int argc, char* argv[]) -{ - /**************************************/ -#endif /* #if ( BUILD_WITH_AMI == 1 ) */ -/**************************************/ - -/**** IF NOT IN AMI MODE, main() STARTS HERE ****/ - - int bReleaseVersion = bRELEASE_VERSION; - const int nStrLen = INCHI_SEGM_BUFLEN; - int nRet = 0; - int i; - long num_err, num_output, num_inp; - /* long rcPict[4] = {0,0,0,0}; */ - unsigned long ulDisplTime = 0; /* infinite, milliseconds */ - unsigned long ulTotalProcessingTime = 0; - - CANON_GLOBALS CG; - INCHI_CLOCK ic; - - char szTitle[MAX_SDF_HEADER + MAX_SDF_VALUE + 256]; - char szSdfDataValue[MAX_SDF_VALUE + 1]; - - INPUT_PARMS inp_parms; - INPUT_PARMS* ip = &inp_parms; - - STRUCT_DATA struct_data; - STRUCT_DATA* sd = &struct_data; - - ORIG_ATOM_DATA OrigAtData; /* 0=> disconnected, 1=> original */ - ORIG_ATOM_DATA* orig_inp_data = &OrigAtData; - ORIG_ATOM_DATA PrepAtData[2]; /* 0=> disconnected, 1=> original */ - ORIG_ATOM_DATA* prep_inp_data = PrepAtData; - - PINChI2* pINChI[INCHI_NUM]; - PINChI_Aux2* pINChI_Aux[INCHI_NUM]; - - char* pLF, * pTAB; - INCHI_IOS_STRING temp_string_container; - INCHI_IOS_STRING* strbuf = &temp_string_container; - INCHI_IOSTREAM outputstr, logstr, prbstr, instr; - INCHI_IOSTREAM* pout = &outputstr, * plog = &logstr, * pprb = &prbstr, * inp_file = &instr; - -#ifdef TARGET_EXE_STANDALONE - int inchi_ios_type = INCHI_IOS_TYPE_STRING; -#else - int inchi_ios_type = INCHI_IOS_TYPE_FILE; -#endif -#if ( READ_INCHI_STRING == 1 ) - const int may_get_inchi_string_input = 1; -#else - const int may_get_inchi_string_input = 0; -#endif - int bInChI2Structure = 0; - int output_error_inchi = 0; - - - /* internal tests --- */ -#ifndef TEST_FPTRS - STRUCT_FPTRS* pStructPtrs = NULL; -#else - STRUCT_FPTRS struct_fptrs, * pStructPtrs = &struct_fptrs; /* INCHI_LIB debug only */ -#endif - -#if ( defined(_WIN32) && defined(_MSC_VER) ) -#if WINVER >= 0x0501 /* XP or newer */ /* 0x0600 Vista or newer */ - DWORD tick_inchi_start, tick_inchi_stop; - tick_inchi_start = GetTickCount64(); /* djb-rwth: GetTickCount64() should be used */ -#endif -#endif - -#ifdef _WIN32 -#if ( TRACE_MEMORY_LEAKS == 1 ) - _CrtSetDbgFlag(_CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF); - /* for execution outside the VC++ debugger uncomment one of the following two */ - /*#define MY_REPORT_FILE _CRTDBG_FILE_STDERR */ - /*#define MY_REPORT_FILE _CRTDBG_FILE_STDOUT */ -#ifdef MY_REPORT_FILE - _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_WARN, MY_REPORT_FILE); - _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ERROR, MY_REPORT_FILE); - _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ASSERT, MY_REPORT_FILE); -#else - _CrtSetReportMode(_CRT_WARN | _CRT_ERROR, _CRTDBG_MODE_DEBUG); -#endif - /* turn on floating point exceptions */ - { - /* Get the default control word. */ - int cw = _controlfp(0, 0); - - /* Set the exception masks OFF, turn exceptions on. */ - /*cw &=~(EM_OVERFLOW|EM_UNDERFLOW|EM_INEXACT|EM_ZERODIVIDE|EM_DENORMAL);*/ - cw &= ~(EM_OVERFLOW | EM_UNDERFLOW | EM_ZERODIVIDE | EM_DENORMAL); - - /* Set the control word. */ - _controlfp(cw, MCW_EM); -} -#endif -#endif - - sd->bUserQuit = 0; - /* djb-rwth: fixing coverity CID #499552 */ - sd->num_components[0] = 0; - sd->num_components[1] = 0; -#if ( defined( _WIN32 ) && defined( _CONSOLE ) && !defined( COMPILE_ANSI_ONLY ) ) - if (SetConsoleCtrlHandler(MyHandlerRoutine, 1)) - { - ConsoleQuit = WasInterrupted; - } -#endif - - num_inp = 0; - num_err = 0; - num_output = 0; - - inchi_ios_init(inp_file, INCHI_IOS_TYPE_FILE, NULL); - inchi_ios_init(pout, inchi_ios_type, NULL); - inchi_ios_init(plog, inchi_ios_type, stdout); - inchi_ios_init(pprb, inchi_ios_type, NULL); - memset(strbuf, 0, sizeof(*strbuf)); /* djb-rwth: memset_s C11/Annex K variant?; dereferencing strbuf */ - - if (argc == 1 || (argc == 2 && (argv[1][0] == INCHI_OPTION_PREFX) && - ((!strcmp(argv[1] + 1, "?") || !inchi_stricmp(argv[1] + 1, "help"))))) /* djb-rwth: addressing LLVM warning */ - { - HelpCommandLineParms(plog); - inchi_ios_flush(plog); - return 0; - } - - /* djb-rwth: printing out InChI version */ - if (argc == 2 && ((argv[1][0] == INCHI_OPTION_PREFX)) && (!strcmp(argv[1] + 1, "v") || !strcmp(argv[1] + 1, "V"))) - { - printf("%s\n", APP_DESCRIPTION); - return 0; - } - - /* djb-rwth: disallowing endless execution if no file(s) is given as the first argument */ - if (argc >= 2 && ((argv[1][0] == INCHI_OPTION_PREFX)) && (strcmp(argv[1] + 1, "v") || strcmp(argv[1] + 1, "V") || strcmp(argv[1] + 1, "?") || inchi_stricmp(argv[1] + 1, "help"))) - { - HelpCommandLineParms(plog); - inchi_ios_flush(plog); - return 0; - } - - /* original input structure */ - memset(orig_inp_data, 0, sizeof(*orig_inp_data)); /* djb-rwth: memset_s C11/Annex K variant? */ - memset(prep_inp_data, 0, 2 * sizeof(*prep_inp_data)); /* djb-rwth: memset_s C11/Annex K variant? */ - memset(pINChI, 0, sizeof(pINChI)); /* djb-rwth: memset_s C11/Annex K variant? */ - memset(pINChI_Aux, 0, sizeof(pINChI_Aux)); /* djb-rwth: memset_s C11/Annex K variant? */ - memset(szSdfDataValue, 0, sizeof(szSdfDataValue)); /* djb-rwth: memset_s C11/Annex K variant? */ - - memset(&CG, 0, sizeof(CG)); /* djb-rwth: memset_s C11/Annex K variant? */ - memset(&ic, 0, sizeof(ic)); /* djb-rwth: memset_s C11/Annex K variant? */ - - plog->f = stderr; - - if (0 > ReadCommandLineParms(argc, (const char**)argv, ip, - szSdfDataValue, &ulDisplTime, - bReleaseVersion, plog)) - { - goto exit_function; - } - - if (!OpenFiles(&(inp_file->f), &(pout->f), &(plog->f), &(pprb->f), ip)) - { - goto exit_function; - } - - - if (ip->bNoStructLabels) - { - ip->pSdfLabel = NULL; - ip->pSdfValue = NULL; - } - else if (ip->nInputType == INPUT_INCHI_PLAIN || - ip->nInputType == INPUT_INCHI) - { - /* the input may contain both the header and the label of the structure */ - if (!ip->pSdfLabel) - { - ip->pSdfLabel = ip->szSdfDataHeader; - } - if (!ip->pSdfValue) - { - ip->pSdfValue = szSdfDataValue; - } - } - - set_line_separators(ip->bINChIOutputOptions, &pLF, &pTAB); - - save_command_line(argc, argv, plog); - - PrintInputParms(plog, ip); - - inchi_ios_flush2(plog, stderr); - - if (0 >= inchi_strbuf_init(strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT)) - { - inchi_ios_eprint(plog, "Cannot allocate internal string buffer. Terminating\n"); - inchi_ios_flush2(plog, stderr); - goto exit_function; - } - - - /* Process InChI string as input; output may be */ - /* a) InChI string or b) structure */ - /*#if ( READ_INCHI_STRING == 1 )*/ - if (may_get_inchi_string_input && ip->nInputType == INPUT_INCHI) - { - bInChI2Structure = 0 != (ip->bReadInChIOptions & READ_INCHI_TO_STRUCTURE); - memset(sd, 0, sizeof(*sd)); /* djb-rwth: memset_s C11/Annex K variant? */ - if (bInChI2Structure) - { - /* loop through file lines here */ - INCHI_IOSTREAM tmpinpustream; - INCHI_IOS_STRING* pTmpIn = &tmpinpustream.s; - int crlf2lf = 0, preserve_lf = 1, read_result = 0; - inchi_ios_init(&tmpinpustream, INCHI_IOS_TYPE_STRING, NULL); - while (1) - { - char* p, * pi; - - read_result = inchi_strbuf_getline(pTmpIn, inp_file->f, crlf2lf, preserve_lf); - - if (read_result == -1) -#if (FIX_ONE_LINE_INCHI_INPUT_CONVERSION_ISSUE==1) - { - if (!pTmpIn->pStr) - { - break; - } - if (strlen(pTmpIn->pStr) < 8) /* 7 = strlen("InChI=1") */ - { - break; - } - } -#else - break; /* EOF or read error */ -#endif - - p = pTmpIn->pStr; - if (!p) - { - continue; - } - pi = strstr(p, "InChI=1"); - if (pi != p) - { - continue; - } - - num_inp++; - ip->lMolfileNumber = num_inp; - - ReadWriteInChI(&ic, &CG, &tmpinpustream, pout, plog, ip, sd, NULL, 0, 0, NULL, NULL, NULL, 0, NULL); - - /*fprintf( stderr, "%ld", num_inp );*/ - inchi_strbuf_reset(pTmpIn); - inchi_ios_flush2(plog, stderr); - } - fprintf(stderr, "\r"); - inchi_strbuf_close(pTmpIn); - } - else - { - /* loop through file lines within ReadWriteInChI */ - ReadWriteInChI(&ic, &CG, inp_file, pout, plog, ip, sd, NULL, 0, 0, NULL, NULL, NULL, 0, NULL); - - num_inp = sd->fPtrStart; - num_err = sd->fPtrEnd; - } - - inchi_ios_flush2(plog, stderr); - ulTotalProcessingTime = sd->ulStructTime; - /*num_inp = sd->fPtrStart; - num_err = sd->fPtrEnd; - */ - goto exit_function; - } - - - ulTotalProcessingTime = 0; - if (pStructPtrs) - { - memset(pStructPtrs, 0, sizeof(pStructPtrs[0])); /* djb-rwth: memset_s C11/Annex K variant? */ - } - output_error_inchi = ip->bINChIOutputOptions2 & INCHI_OUT_INCHI_GEN_ERROR; - - - /*************************************************************/ - /* Main cycle : read input structures and create their INChI */ - /*************************************************************/ - - - while (!sd->bUserQuit && !bInterrupted) - { - int do_renumbering = 0; - int next_action; - int have_err_in_GetOneStructure = 0; - int dup_fail = 0; - ORIG_ATOM_DATA SavedOrigAtData; /* 0=> disconnected, 1=> original */ - ORIG_ATOM_DATA* saved_orig_inp_data = &SavedOrigAtData; - char ikey0[28]; - ikey0[0] = '\0'; - - - next_action = GetTheNextRecordOfInputFile(&ic, sd, ip, szTitle, - inp_file, plog, pout, pprb, - orig_inp_data, &num_inp, pStructPtrs, - &nRet, &have_err_in_GetOneStructure, - &num_err, output_error_inchi); - if (next_action == DO_EXIT_FUNCTION) - { - goto exit_function; - } - else if (next_action == DO_BREAK_MAIN_LOOP) - { - break; - } - else if (next_action == DO_CONTINUE_MAIN_LOOP) - { - if (nRet == _IS_ERROR) /* may also be _IS_SKIP ... */ - { - if (output_error_inchi) - { - Output_RecordInfo(pout, num_inp, ip->bNoStructLabels, ip->pSdfLabel, ip->pSdfValue, ip->lSdfId, - pLF, pTAB); - emit_empty_inchi(ip, num_inp, pLF, pTAB, pout); - } - } - continue; - } - - - /* Create INChI for each connected component of the structure; - optionally display them; - output INChI for the whole structure */ - -#if (RENUMBER_ATOMS_AND_RECALC_V106 == 1 ) - if (ip->bRenumber == 1) - { - do_renumbering = 1; - } -#endif - if (do_renumbering == 0) - { - /* Normal calculations */ - next_action = CalcAndPrintINCHIAndINCHIKEY(&ic, &CG, sd, ip, szTitle, - pINChI, pINChI_Aux, - inp_file, plog, pout, pprb, - orig_inp_data, prep_inp_data, &num_inp, pStructPtrs, - &nRet, have_err_in_GetOneStructure, - &num_err, output_error_inchi, - strbuf, &ulTotalProcessingTime, - pLF, pTAB, ikey0, - 0 /* not silent */); - - FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); - FreeOrigAtData(orig_inp_data); - FreeOrigAtData(prep_inp_data); - FreeOrigAtData(prep_inp_data + 1); - } - else - { - /* Internal test mode: renumber atoms and recalculate repeatedly */ - long int nrepeat = 1; - /* 2! = 2 3! = 6 4! = 24 5! = 120 6! = 520 7! = 5040 8! = 40320 */ - if (orig_inp_data->num_inp_atoms == 1) - { - nrepeat = 1; - } - else if (orig_inp_data->num_inp_atoms == 2) - { - nrepeat = 2; - } - else if (orig_inp_data->num_inp_atoms == 3) - { - nrepeat = 6; - } - else - { - nrepeat = 1000; /* 100000;*/ /*16;*/ - } - /* correct (decrease repeat number) for relatively large molecules */ - if (orig_inp_data->num_inp_atoms > 128) - { - nrepeat = 100; /* 100000;*/ /*16;*/ - } - if (orig_inp_data->num_inp_atoms > 256) - { - nrepeat = 50; /* 100000;*/ /*16;*/ - } - if (orig_inp_data->num_inp_atoms > 512) - { - nrepeat = 25; /* 100000;*/ /*16;*/ - } - if (orig_inp_data->num_inp_atoms > 1024) - { - nrepeat = 10; /* 100000;*/ /*16;*/ - } - - /*inchi_ios_eprint(plog, "Number of random atom renumberings up to: %-ld\n", nrepeat); - inchi_ios_flush2(plog, stderr);*/ - -#if 0 - else if (orig_inp_data->num_inp_atoms == 4) - { - nrepeat = 24; - } - else - { - nrepeat = 10; - } - - else if (orig_inp_data->num_inp_atoms == 4) - { - nrepeat = 24; - } - else if (orig_inp_data->num_inp_atoms == 5) - { - nrepeat = 120; - } - else if (orig_inp_data->num_inp_atoms == 6) - { - nrepeat = 520; - } - else if (orig_inp_data->num_inp_atoms == 7) - { - nrepeat = 1000; - } - else - { - nrepeat = 10000; - } -#endif - - next_action = RepeatedlyRenumberAtomsAndRecalcINCHI(&ic, &CG, sd, ip, szTitle, - pINChI, pINChI_Aux, - inp_file, plog, pout, pprb, - orig_inp_data, prep_inp_data, &num_inp, pStructPtrs, - &nRet, have_err_in_GetOneStructure, - &num_err, output_error_inchi, - strbuf, &ulTotalProcessingTime, - pLF, pTAB, nrepeat); - } /* if (ip->bRenumber == 1) */ - - if (next_action == DO_EXIT_FUNCTION) - { - goto exit_function; - } - else if (next_action == DO_BREAK_MAIN_LOOP) - { - break; - } - else if (next_action == DO_CONTINUE_MAIN_LOOP) - { - continue; - } - } /* end of main cycle - while ( !sd->bUserQuit && !bInterrupted ) */ - - -exit_function: - /* Avoid memory leaks in case of fatal error */ - if (pStructPtrs && pStructPtrs->fptr) - { - inchi_free(pStructPtrs->fptr); - } - /* Free INChI memory */ - FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); - /* Free structure data */ - FreeOrigAtData(orig_inp_data); - FreeOrigAtData(prep_inp_data); - FreeOrigAtData(prep_inp_data + 1); - /* Close files */ - inchi_ios_close(inp_file); - inchi_ios_close(pout); - inchi_ios_close(pprb); - { - int hours, minutes, seconds, mseconds; - - SplitTime(ulTotalProcessingTime, &hours, &minutes, &seconds, &mseconds); - - inchi_ios_eprint(plog, "Finished processing %ld structure%s: %ld error%s, processing time %d:%02d:%02d.%02d\n", - num_inp, num_inp == 1 ? "" : "s", - num_err, num_err == 1 ? "" : "s", - hours, minutes, seconds, mseconds / 10); - inchi_ios_flush2(plog, stderr); - } -#if ( defined(_WIN32) && defined(_MSC_VER) ) -#if WINVER >= 0x0501 /* XP or newer */ /* 0x0600 Vista or newer */ - tick_inchi_stop = GetTickCount64(); /* djb-rwth: GetTickCount64() should be used */ - inchi_ios_eprint(plog, "\nElapsed walltime: %d msec.\n", tick_inchi_stop - tick_inchi_start); - inchi_ios_flush2(plog, stderr); -#endif -#endif - /* Final cleanup */ - inchi_ios_close(plog); - inchi_strbuf_close(strbuf); - for (i = 0; i < MAX_NUM_PATHS; i++) - { - if (ip->path[i]) - { - inchi_free((void*)ip->path[i]); /* cast deliberately discards 'const' qualifier */ - ip->path[i] = NULL; - } - } - SetBitFree(&CG); -#if ( ( BUILD_WITH_AMI==1 ) && defined( _WIN32 ) && defined( _CONSOLE ) && !defined( COMPILE_ANSI_ONLY ) ) - if (bInterrupted) - { - return CTRL_STOP_EVENT; - } -#endif - - return 0; -} - - -/****************************************************************************/ -void save_command_line(int argc, char* argv[], INCHI_IOSTREAM* plog) -{ - int k; - - inchi_ios_eprint(plog, "The command line used:\n\""); - for (k = 0; k < argc - 1; k++) - { -#if( ALLOW_EMPTY_PATHS == 1 ) - inchi_ios_eprint(plog, "%-s ", argv[k][0] ? argv[k] : "\"\""); -#else - inchi_ios_eprint(plog, "%-s ", argv[k]); -#endif - } - - inchi_ios_eprint(plog, "%-s\"\n", argv[argc - 1]); - - return; -} - - -/*****************************************************************************/ -void emit_empty_inchi(INPUT_PARMS* ip, - long num_inp, - char* pLF, - char* pTAB, - INCHI_IOSTREAM* pout) -{ - if (ip->bINChIOutputOptions & INCHI_OUT_STDINCHI) - { - inchi_ios_eprint(pout, "InChI=1S//\n"); /* emit empty Std InChI */ - } - else - { - inchi_ios_eprint(pout, "InChI=1//\n"); /* emit empty InChI */ - } - inchi_ios_flush(pout); -} -#endif /* ifndef TARGET_LIB_FOR_WINCHI */ - - -/*****************************************************************************/ -int GetTheNextRecordOfInputFile(struct tagINCHI_CLOCK* ic, - STRUCT_DATA* sd, INPUT_PARMS* ip, - char* szTitle, - INCHI_IOSTREAM* inp_file, - INCHI_IOSTREAM* plog, - INCHI_IOSTREAM* pout, - INCHI_IOSTREAM* pprb, - ORIG_ATOM_DATA* orig_inp_data, - long* num_inp, - STRUCT_FPTRS* pStructPtrs, - int* nRet, - int* have_err_in_GetOneStructure, - long* num_err, - int output_error_inchi) -{ - if (ip->last_struct_number && *num_inp >= ip->last_struct_number) - { - *nRet = _IS_EOF; /* simulate end of file */ - return DO_EXIT_FUNCTION; - } - - - *nRet = GetOneStructure(ic, sd, ip, szTitle, inp_file, - plog, pout, pprb, orig_inp_data, - num_inp, pStructPtrs); - - inchi_ios_flush2(plog, stderr); - - if (pStructPtrs) - pStructPtrs->cur_fptr++; - - if (sd->bUserQuit) - { - { - return DO_BREAK_MAIN_LOOP; - } - } - - *have_err_in_GetOneStructure = 0; - switch (*nRet) - { - case _IS_FATAL: - (*num_err)++; - if (output_error_inchi == 0) - { - return DO_EXIT_FUNCTION; - } - else - sd->pStrErrStruct[0] = '\0'; /* depress re-appearance of error as warning in ProcessOneStr */ - break; - case _IS_EOF: - return DO_EXIT_FUNCTION; - case _IS_ERROR: - (*num_err)++; - *have_err_in_GetOneStructure = 1; - if (output_error_inchi == 0) - { - return DO_CONTINUE_MAIN_LOOP; - } - else - sd->pStrErrStruct[0] = '\0'; /* depress re-appearance of error as warning in ProcessOneStr */ - break; - case _IS_SKIP: - return DO_CONTINUE_MAIN_LOOP; - default: - sd->pStrErrStruct[0] = '\0'; - } - - return DO_NEXT_STEP; -} - - -/****************************************************************************/ -int CalcAndPrintINCHIAndINCHIKEY(struct tagINCHI_CLOCK* ic, - CANON_GLOBALS* CG, - STRUCT_DATA* sd, - INPUT_PARMS* ip, - char* szTitle, - PINChI2* pINChI[INCHI_NUM], - PINChI_Aux2* pINChI_Aux[INCHI_NUM], - INCHI_IOSTREAM* inp_file, - INCHI_IOSTREAM* plog, - INCHI_IOSTREAM* pout, - INCHI_IOSTREAM* pprb, - ORIG_ATOM_DATA* orig_inp_data, - ORIG_ATOM_DATA* prep_inp_data, - long* num_inp, - STRUCT_FPTRS* pStructPtrs, - int* nRet, - int have_err_in_GetOneStructure, - long* num_err, - int output_error_inchi, - INCHI_IOS_STRING* strbuf, - unsigned long* pulTotalProcessingTime, - char* pLF, - char* pTAB, - char* ikey, - int silent) -{ - int nRet1; - int next_act = DO_NEXT_STEP; - /* related to hash of InChI */ - char ik_string[256]; /*^^^ Resulting InChIKey string */ - int ik_ret = 0; /*^^^ InChIKey-calc result code */ - int xhash1, xhash2; - char szXtra1[65], szXtra2[65]; - /* related to printing structure header */ - int print_record_info = 0; - INCHI_IOSTREAM temp_out; - INCHI_IOSTREAM* pout0 = &temp_out; - inchi_ios_init(pout0, INCHI_IOS_TYPE_STRING, NULL); - - - /* Calculate InChI */ - - nRet1 = ProcessOneStructureEx(ic, - CG, - sd, - ip, - szTitle, - pINChI, - pINChI_Aux, - inp_file, - plog, - pout0, /* note this */ - pprb, - orig_inp_data, - prep_inp_data, - *num_inp, strbuf, - 0 /* save_opt_bits */); - - inchi_ios_flush2(plog, stderr); - - - /* Output InChI */ - - /* print header for structure if applicable (no error arose, or have a request for empty InChI at error) */ - print_record_info = ((nRet1 == _IS_OKAY) || - (nRet1 == _IS_WARNING) || - ((nRet1 == _IS_ERROR || nRet1 == _IS_FATAL) && output_error_inchi)); - if (print_record_info) - { - Output_RecordInfo(pout, *num_inp, ip->bNoStructLabels, - ip->pSdfLabel, ip->pSdfValue, ip->lSdfId, pLF, pTAB); - } - if (pout0->s.pStr) - { - /* post-process output to correctly treat 'tabbed with InChIKey' mode */ - if (ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT) - { - if (ip->bCalcInChIHash != INCHIHASH_NONE) - { - if (pout0->s.pStr) - { - if (pout0->s.nUsedLength > 0) - { - if (pout0->s.pStr[pout0->s.nUsedLength - 1] == '\n') - { - pout0->s.pStr[pout0->s.nUsedLength - 1] = '\t'; - } - } - } - } - } - /* print InChI string (may be string for empty InChI) */ - if (!ip->bHideInChI) - { - inchi_ios_print(pout, "%-s", pout0->s.pStr); - } - } - /*inchi_ios_close(pout0);*/ /* free temporary out */ - - - *pulTotalProcessingTime += sd->ulStructTime; - - if (nRet1 == _IS_SKIP) - { - next_act = DO_CONTINUE_MAIN_LOOP; - goto exit_function; - } - - *nRet = inchi_max(*nRet, nRet1); - switch (*nRet) - { - case _IS_FATAL: - if (!have_err_in_GetOneStructure) - { - /* increment error counter only if error did not appear earlier */ - (*num_err)++; - } - if (!(ip->bINChIOutputOptions & INCHI_OUT_NO_AUX_INFO) && - (ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT)) - { - inchi_ios_print(pout, "\t"); - } - if (ip->bCalcInChIHash != INCHIHASH_NONE) - { - if (ip->bINChIOutputOptions2 & INCHI_OUT_INCHI_GEN_ERROR) - { - if (ip->bINChIOutputOptions & INCHI_OUT_STDINCHI) - { - inchi_ios_print(pout, "InChIKey=%-s\n", "MOSFIJXAXDLOML-UHFFFAOYSA-N"); - } - else - { - inchi_ios_print(pout, "InChIKey=%-s\n", "MOSFIJXAXDLOML-UHFFFAOYNA-N"); - } - } - } - inchi_ios_flush(pout); - next_act = DO_EXIT_FUNCTION; - goto exit_function; - - case _IS_ERROR: - if (!have_err_in_GetOneStructure) - { - /* increment error counter only if error did not appear earlier */ - (*num_err)++; - } - if (!(ip->bINChIOutputOptions & INCHI_OUT_NO_AUX_INFO) && - (ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT)) - { - inchi_ios_print(pout, "\t"); - } - if (ip->bCalcInChIHash != INCHIHASH_NONE) - { - if (ip->bINChIOutputOptions2 & INCHI_OUT_INCHI_GEN_ERROR) - { - if (ip->bINChIOutputOptions & INCHI_OUT_STDINCHI) - { - inchi_ios_print(pout, "InChIKey=%-s\n", "MOSFIJXAXDLOML-UHFFFAOYSA-N"); - } - else - { - inchi_ios_print(pout, "InChIKey=%-s\n", "MOSFIJXAXDLOML-UHFFFAOYNA-N"); - } - } - } - inchi_ios_flush(pout); - next_act = DO_CONTINUE_MAIN_LOOP; - goto exit_function; - - case _IS_SKIP: - next_act = DO_CONTINUE_MAIN_LOOP; - goto exit_function; - } - - - /* Calculate hash[es] of InChI */ - - if (ip->bCalcInChIHash != INCHIHASH_NONE) - { - char* buf = NULL; - size_t slen = pout0->s.nUsedLength; - - extract_inchi_substring(&buf, pout0->s.pStr, slen); - - if (NULL == buf) - { - ik_ret = INCHIKEY_INVALID_INCHI; - } - else - { - xhash1 = xhash2 = 0; - if ((ip->bCalcInChIHash == INCHIHASH_KEY_XTRA1) || - (ip->bCalcInChIHash == INCHIHASH_KEY_XTRA1_XTRA2)) - { - xhash1 = 1; - } - if ((ip->bCalcInChIHash == INCHIHASH_KEY_XTRA2) || - (ip->bCalcInChIHash == INCHIHASH_KEY_XTRA1_XTRA2)) - { - xhash2 = 1; - } - ik_ret = GetINCHIKeyFromINCHI(buf, xhash1, xhash2, ik_string, szXtra1, szXtra2); - inchi_free(buf); - } - - - /* Print hash[es] */ - - if (ik_ret == INCHIKEY_OK) - { - /* NB: correctly treat tabbed output with InChIKey & hash extensions */ - char csep = '\n'; - - if (ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT) - { - csep = '\t'; - } - if (!ip->bMergeHash) - { - inchi_ios_print(pout, "InChIKey=%-s", ik_string); - } - else - { - inchi_ios_print(pout, "InChIHash=%-s", ik_string); - } - strcpy(ikey, ik_string); - - if (szXtra1[0] && ip->bMergeHash) - { - inchi_ios_print(pout, "-%-s", szXtra1); - } - else if (szXtra1[0] && !ip->bMergeHash) - { - inchi_ios_print(pout, "%cXHash1=%-s", csep, szXtra1); - } - else if (!szXtra1[0] && ip->bMergeHash) - { - inchi_ios_print(pout, "-"); - } - - if (szXtra2[0] && ip->bMergeHash) - { - inchi_ios_print(pout, "-%-s", szXtra2); - } - else if (szXtra2[0] && !ip->bMergeHash) - { - inchi_ios_print(pout, "%cXHash2=%-s", csep, szXtra2); - } - else if (!szXtra2[0] && ip->bMergeHash) - { - inchi_ios_print(pout, "-"); - } - - inchi_ios_print(pout, "\n"); - } - else - { - inchi_ios_print(plog, "Warning (Could not compute InChIKey: ", num_inp); - switch (ik_ret) - { - case INCHIKEY_UNKNOWN_ERROR: - inchi_ios_print(plog, "unresolved error)"); - break; - case INCHIKEY_EMPTY_INPUT: - inchi_ios_print(plog, "got an empty string)"); - break; - case INCHIKEY_INVALID_INCHI_PREFIX: - case INCHIKEY_INVALID_INCHI: - case INCHIKEY_INVALID_STD_INCHI: - inchi_ios_print(plog, "no valid InChI string found)"); - break; - case INCHIKEY_NOT_ENOUGH_MEMORY: - inchi_ios_print(plog, "not enough memory to treat the string)"); - break; - default: inchi_ios_print(plog, "internal program error)"); - break; - } - inchi_ios_print(plog, " structure #%-lu.\n", *num_inp); - if (ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT) - { - inchi_ios_print(pout, "\n"); - } - } - - if (!silent) - { - inchi_ios_flush(pout); - inchi_ios_flush2(plog, stderr); - } - else - { - inchi_ios_free_str(pout); - inchi_ios_free_str(plog); - } - } - else - { - inchi_ios_flush(pout); - } - -exit_function: - inchi_ios_close(pout0); /* free temporary out */ - - return next_act; -} - - -#ifdef RENUMBER_ATOMS_AND_RECALC_V106 - -/*****************************************************************************/ - -int numbers_rrar[PERMAXATOMS]; /* djb-rwth: placed as a global variable to avoid function buffer issues */ -int RepeatedlyRenumberAtomsAndRecalcINCHI(struct tagINCHI_CLOCK* ic, - CANON_GLOBALS* CG, - STRUCT_DATA* sd, - INPUT_PARMS* ip, - char* szTitle, - PINChI2* pINChI[INCHI_NUM], - PINChI_Aux2* pINChI_Aux[INCHI_NUM], - INCHI_IOSTREAM* inp_file, - INCHI_IOSTREAM* plog, - INCHI_IOSTREAM* pout, - INCHI_IOSTREAM* pprb, - ORIG_ATOM_DATA* orig_inp_data, - ORIG_ATOM_DATA* prep_inp_data, - long* num_inp, - STRUCT_FPTRS* pStructPtrs, - int* nRet, - int have_err_in_GetOneStructure, - long* num_err, - int output_error_inchi, - INCHI_IOS_STRING* strbuf, - unsigned long* pulTotalProcessingTime, - char* pLF, - char* pTAB, - long int nrepeat) -{ - int next_action = DO_NEXT_STEP; - int dup_fail = 0; - ORIG_ATOM_DATA SavedOrigAtData; /* 0=> disconnected, 1=> original */ - ORIG_ATOM_DATA* saved_orig_inp_data = &SavedOrigAtData; - char ikey0[28]; - - const int very_silent = 2; /* 3 0;*/ - - /* Internal test mode: renumber atoms and recalculate repeatedly */ - - /* do not forget to use /key and to not use /auxnone */ - - - ikey0[0] = '\0'; - { - int k; - for (k = 0; k < orig_inp_data->num_inp_atoms; k++) - { - numbers_rrar[k] = k; - } - for (k = orig_inp_data->num_inp_atoms; k < PERMAXATOMS; k++) - { - numbers_rrar[k] = -1; - } - } - - - - -#if BIG_POLY_DEBUG - { int k; ITRACE_("\nAtoms = {"); for (k = 0; k < orig_inp_data->num_inp_atoms - 1; k++) ITRACE_(" %-03d,", numbers_rrar[k]); ITRACE_(" %-03d }", numbers_rrar[orig_inp_data->num_inp_atoms - 1]); } - OrigAtData_DebugTrace(orig_inp_data); - OrigAtDataPolymer_DebugTrace(orig_inp_data->polymer); -#endif - - memset(saved_orig_inp_data, 0, sizeof(*saved_orig_inp_data)); /* djb-rwth: memset_s C11/Annex K variant? */ - dup_fail = OrigAtData_Duplicate(saved_orig_inp_data, orig_inp_data); - - next_action = CalcAndPrintINCHIAndINCHIKEY(ic, CG, sd, ip, szTitle, - pINChI, pINChI_Aux, - inp_file, plog, pout, pprb, - orig_inp_data, prep_inp_data, num_inp, pStructPtrs, - nRet, have_err_in_GetOneStructure, - num_err, output_error_inchi, - strbuf, pulTotalProcessingTime, - pLF, pTAB, ikey0, very_silent); - FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); - FreeOrigAtData(orig_inp_data); - FreeOrigAtData(prep_inp_data); - FreeOrigAtData(prep_inp_data + 1); - - - if (ikey0[0]) - { - if (very_silent < 2) - { - inchi_ios_eprint(plog, "#%-ld-%08ld\t...\t%-s\t%s%s%s%s\n", *num_inp, 1, ikey0, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue)); - } - } - - - if (!dup_fail) - { - int irepeat = 0; - int ndiff = 0; - int n_written_problems = 0; - char ikey[28]; - ikey[0] = '\0'; - for (irepeat = 0; irepeat < nrepeat - 1; irepeat++) - { - dup_fail = OrigAtData_Duplicate(orig_inp_data, saved_orig_inp_data); - if (!dup_fail) - { - shuffle((void*)numbers_rrar, orig_inp_data->num_inp_atoms, sizeof(int)); - OrigAtData_Permute(orig_inp_data, saved_orig_inp_data, numbers_rrar); -#if BIG_POLY_DEBUG - { int k; ITRACE_("\nAtoms = {"); for (k = 0; k < orig_inp_data->num_inp_atoms - 1; k++) ITRACE_(" %-03d,", numbers_rrar[k]); ITRACE_(" %-03d }", numbers_rrar[orig_inp_data->num_inp_atoms - 1]); } - OrigAtData_DebugTrace(saved_orig_inp_data); - OrigAtData_DebugTrace(orig_inp_data); - OrigAtDataPolymer_DebugTrace(saved_orig_inp_data->polymer); - OrigAtDataPolymer_DebugTrace(orig_inp_data->polymer); -#endif - next_action = CalcAndPrintINCHIAndINCHIKEY(ic, CG, sd, ip, szTitle, - pINChI, pINChI_Aux, - inp_file, plog, pout, pprb, - orig_inp_data, - prep_inp_data, num_inp, pStructPtrs, - nRet, have_err_in_GetOneStructure, - num_err, output_error_inchi, - strbuf, pulTotalProcessingTime, - pLF, pTAB, ikey, - 0 /* 1 be silent */); - - - if (ikey0[0] && ikey[0]) - { - if (strcmp(ikey, ikey0)) - { - int result, bINChIOutputOptions = ip->bINChIOutputOptions; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ - ndiff++; - /*inchi_ios_eprint( plog, "!!! #%-ld-%05ld %s%s%s%s\tcurr %-s != %-s orig\n", *num_inp, irepeat + 2, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ), ikey, ikey0 );*/ - /*inchi_ios_eprint( plog, "!!! %s%s%s%s renum#%05ld\t%-s != %-s\n", SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ), irepeat + 2, ikey, ikey0 );*/ - inchi_ios_eprint(plog, "!!! #%-ld %s%s%s%s\t%-s --> %-s @ renum#%06d/%06ld\n", *num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue), ikey0, ikey, irepeat + 2, nrepeat); - if (!very_silent) - { - int k; - inchi_ios_eprint(plog, "Atoms = {"); - for (k = 0; k < orig_inp_data->num_inp_atoms - 1; k++) - { - inchi_ios_eprint(plog, " %-d,", numbers_rrar[k] + 1); - } - inchi_ios_eprint(plog, " %-d }\n\n", numbers_rrar[orig_inp_data->num_inp_atoms - 1] + 1); - } - ip->bINChIOutputOptions |= INCHI_OUT_SDFILE_ONLY; - result = OrigAtData_SaveMolfile(orig_inp_data, sd, ip, *num_inp, pprb); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ - inchi_ios_flush(pprb); - ip->bINChIOutputOptions = bINChIOutputOptions; - if (result == 0) - { - n_written_problems++; - } -#if 0 - /* second pass, non-silent one */ - FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); - FreeOrigAtData(orig_inp_data); - FreeOrigAtData(prep_inp_data); - FreeOrigAtData(prep_inp_data + 1); - dup_fail = OrigAtData_Duplicate(orig_inp_data, saved_orig_inp_data); - if (!dup_fail) - { - OrigAtData_Permute(orig_inp_data, saved_orig_inp_data, numbers_rrar); - next_action = CalcAndPrintINCHIAndINCHIKEY(ic, CG, sd, ip, szTitle, - pINChI, pINChI_Aux, - inp_file, plog, pout, pprb, - orig_inp_data, - prep_inp_data, num_inp, pStructPtrs, - nRet, have_err_in_GetOneStructure, - num_err, output_error_inchi, - strbuf, pulTotalProcessingTime, - pLF, pTAB, ikey, 0); - } -#endif - } - - if (irepeat == nrepeat - 2) - { - if (very_silent < 2) - { - inchi_ios_eprint(plog, "...........\n#%-ld-%08ld\t...\t%-s\t%s%s%s%s\n", *num_inp, irepeat + 2, ikey0, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue)); - } - } - - } - } - FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); - FreeOrigAtData(orig_inp_data); - FreeOrigAtData(prep_inp_data); - FreeOrigAtData(prep_inp_data + 1); - -#ifdef STOP_AFTER_FIRST_CHANGE_ON_RENUMBERING - if (ndiff == 1) - { - next_action = DO_CONTINUE_MAIN_LOOP; - break; - } -#endif - } - if (ndiff == 0) - { - if (very_silent < 3) - { - /*inchi_ios_eprint( plog, "#%-ld-%05ld\t...\tOK ALL\n", *num_inp, nrepeat );*/ - /*inchi_ios_eprint( plog, "OK #%-ld %s%s%s%s\n", *num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue));*/ - /*inchi_ios_eprint(plog, "#%-ld\n", *num_inp);*/ - inchi_ios_eprint(plog, "OK #%-ld %s%s%s%s\t%-s\t Same for %-d/%-d renums\n", *num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue), ikey0, nrepeat, nrepeat); - } - } - else - { -#ifdef STOP_AFTER_FIRST_CHANGE_ON_RENUMBERING - /*inchi_ios_eprint( plog, "#%-ld-%05ld\t...\tDIFF %-d\n", num_inp, nrepeat, ndiff );*/ -#else - inchi_ios_eprint(plog, "#%-ld-%05ld\t...\tDIFF %-d\n", num_inp, nrepeat, ndiff); -#endif - } - - FreeOrigAtData(saved_orig_inp_data); - } - - return next_action; -} - - -#endif From 03f3451b8bdaf1d3a06a0ecaa2d77392702b6af1 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 8 Dec 2025 14:48:07 +0000 Subject: [PATCH 21/69] added unit test for ProcessSingleInputFile --- .gitignore | 1 + INCHI-1-SRC/INCHI_BASE/src/ichimain.c | 1 - INCHI-1-SRC/INCHI_BASE/src/ichimain.h | 5 +- .../tests/test_unit/fixtures/caffeine.mol | 55 + .../tests/test_unit/fixtures/test_mols.sdf | 1976 +++++++++++++++++ .../tests/test_unit/fixtures/test_mols_2.sdf | 320 +++ .../tests/test_unit/test_ichimain.cpp | 241 +- 7 files changed, 2583 insertions(+), 16 deletions(-) create mode 100644 INCHI-1-TEST/tests/test_unit/fixtures/caffeine.mol create mode 100644 INCHI-1-TEST/tests/test_unit/fixtures/test_mols.sdf create mode 100644 INCHI-1-TEST/tests/test_unit/fixtures/test_mols_2.sdf diff --git a/.gitignore b/.gitignore index ae1a6c21..8e8a17cd 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ build/ Testing/ googletest/ *.egg-info/ +inchi_mol_test_*/ .clang-format # Ignore core dump files core.*[0-9] diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichimain.c b/INCHI-1-SRC/INCHI_BASE/src/ichimain.c index ccdc9aeb..326dfb7b 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichimain.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichimain.c @@ -2,7 +2,6 @@ * International Chemical Identifier (InChI) * Version 1 * Software version 1.07 - * April 30, 2024 * * MIT License * diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichimain.h b/INCHI-1-SRC/INCHI_BASE/src/ichimain.h index 02f999eb..779d6b3e 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichimain.h +++ b/INCHI-1-SRC/INCHI_BASE/src/ichimain.h @@ -2,7 +2,6 @@ * International Chemical Identifier (InChI) * Version 1 * Software version 1.07 - * April 30, 2024 * * MIT License * @@ -164,7 +163,7 @@ typedef struct tagINCHI_OUT_CTL char szTag2[PRINT_INCHI_MAX_TAG_LEN]; char szTag3[PRINT_INCHI_MAX_TAG_LEN]; - int n_pzz; + int n_pzz; int n_zy; INCHI_SORT **pINChISortTautAndNonTaut; @@ -521,7 +520,7 @@ int OAD_StructureEdits_Apply( STRUCT_DATA *sd, OAD_StructureEdits *ed, int *ret); void OAD_CollectFragmentBondsAndAtoms( ORIG_ATOM_DATA *at_data, - int nforbidden, + int nforbidden, int *forbidden_orig, int *n_fragbonds, int **fragbonds, diff --git a/INCHI-1-TEST/tests/test_unit/fixtures/caffeine.mol b/INCHI-1-TEST/tests/test_unit/fixtures/caffeine.mol new file mode 100644 index 00000000..9373920c --- /dev/null +++ b/INCHI-1-TEST/tests/test_unit/fixtures/caffeine.mol @@ -0,0 +1,55 @@ +C8H10N4O2 +APtclcactv08142501153D 0 0.00000 0.00000 + + 24 25 0 0 0 0 0 0 0 0999 V2000 + 1.3120 -1.0479 0.0025 N 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2465 -2.1762 0.0031 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7906 0.2081 0.0010 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.9938 0.3838 0.0002 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.9714 1.2767 -0.0001 N 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5339 2.6294 -0.0017 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.4026 1.0989 -0.0001 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.4446 1.9342 -0.0010 N 0 0 0 0 0 0 0 0 0 0 0 0 + -2.5608 1.2510 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.2862 -0.0680 0.0015 N 0 0 0 0 0 0 0 0 0 0 0 0 + -3.2614 -1.1612 0.0029 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.9114 -0.1939 0.0014 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0163 -1.2853 -0.0022 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.4380 -2.4279 -0.0068 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2697 -1.8004 0.0022 H 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0830 -2.7828 0.8938 H 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0821 -2.7846 -0.8862 H 0 0 0 0 0 0 0 0 0 0 0 0 + 2.6223 2.5703 -0.0019 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1.1987 3.1611 -0.8923 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1.1990 3.1632 0.8877 H 0 0 0 0 0 0 0 0 0 0 0 0 + -3.5520 1.6797 -0.0001 H 0 0 0 0 0 0 0 0 0 0 0 0 + -3.5037 -1.4333 -1.0244 H 0 0 0 0 0 0 0 0 0 0 0 0 + -2.8389 -2.0244 0.5173 H 0 0 0 0 0 0 0 0 0 0 0 0 + -4.1672 -0.8395 0.5168 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 3 4 2 0 0 0 0 + 3 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 5 7 1 0 0 0 0 + 7 8 1 0 0 0 0 + 8 9 2 0 0 0 0 + 9 10 1 0 0 0 0 + 10 11 1 0 0 0 0 + 10 12 1 0 0 0 0 + 7 12 2 0 0 0 0 + 12 13 1 0 0 0 0 + 1 13 1 0 0 0 0 + 13 14 2 0 0 0 0 + 2 15 1 0 0 0 0 + 2 16 1 0 0 0 0 + 2 17 1 0 0 0 0 + 6 18 1 0 0 0 0 + 6 19 1 0 0 0 0 + 6 20 1 0 0 0 0 + 9 21 1 0 0 0 0 + 11 22 1 0 0 0 0 + 11 23 1 0 0 0 0 + 11 24 1 0 0 0 0 +M END + diff --git a/INCHI-1-TEST/tests/test_unit/fixtures/test_mols.sdf b/INCHI-1-TEST/tests/test_unit/fixtures/test_mols.sdf new file mode 100644 index 00000000..d3d970d8 --- /dev/null +++ b/INCHI-1-TEST/tests/test_unit/fixtures/test_mols.sdf @@ -0,0 +1,1976 @@ +Compound 20652 +Actelion Java MolfileCreator 1.0 + +101110 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0153 1.5192 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2737 2.2865 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3351 2.2865 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.9029 0.4297 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2277 3.8057 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3504 3.8057 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8875 -1.0589 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0614 4.5730 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.3147 3.4528 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1766 -1.7955 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5678 -1.7955 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.8518 4.8799 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -4.6344 2.7162 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4656 -1.0282 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1612 -3.2840 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5524 -3.2840 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.9541 3.4835 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -4.6498 1.2277 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4503 0.4911 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4503 -4.0206 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8415 -4.0206 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7673 -4.0206 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.2739 2.7469 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.9695 0.4911 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.3607 0.4911 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1305 1.2583 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7393 1.2583 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4349 -5.5091 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.0870 -3.2533 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7826 -5.5091 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.2892 1.2583 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -8.5936 3.5142 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.3761 -0.9975 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1152 2.7776 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.0283 0.5218 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7240 2.7776 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7240 -6.2457 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1152 -6.2457 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1024 -1.7341 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1024 -6.2457 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5064 -6.2457 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -8.6090 5.0334 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -9.9133 2.7776 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.6958 -1.7341 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4042 3.5449 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8568 3.5449 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.3174 1.2890 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.0130 3.5449 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 7.0130 -5.4784 -0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7086 -7.7342 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2686 -7.6422 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8133 -0.9668 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.4911 -7.7342 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.9287 5.8007 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.2331 3.5449 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.7111 -3.2226 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.3889 5.0641 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7955 5.0641 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 9.6064 0.5524 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 8.3020 2.8083 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.3889 -8.4708 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7801 -8.4708 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8287 -8.4708 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.2484 5.0641 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -12.5528 2.8083 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4221 -3.9592 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -6.0309 -3.9592 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 10.8955 1.3197 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 9.5911 3.5756 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.3735 -9.9594 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.7315 -7.8724 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8415 -9.7292 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -1.0282 -10.0054 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1484 -7.7036 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 10.8801 2.8390 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 12.1845 0.5831 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 10.3277 4.8953 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 8.8238 4.8953 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.6626 -10.6960 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0538 -10.6960 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1484 -10.6960 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4681 -8.4402 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 12.1692 3.6062 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0385 -12.1845 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1637 -12.1845 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4681 -9.9287 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.3275 -12.9211 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7187 -12.9211 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4835 -12.9211 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8747 -12.9211 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.7879 -10.6653 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.3990 -12.1538 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.8032 -12.1538 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4988 -14.4096 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8901 -14.4096 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.3836 -10.6346 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.2098 -15.1462 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5806 -10.1282 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.5831 -9.7906 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -2.2251 -16.6348 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 2 3 2 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 3 6 1 0 0 0 0 + 4 7 2 0 0 0 0 + 5 8 1 0 0 0 0 + 6 9 2 0 0 0 0 + 7 10 1 0 0 0 0 + 8 11 2 0 0 0 0 + 8 12 1 0 0 0 0 + 10 13 1 6 0 0 0 + 10 14 1 0 0 0 0 + 11 15 1 0 0 0 0 + 11 16 1 0 0 0 0 + 12 17 2 0 0 0 0 + 14 18 1 6 0 0 0 + 14 19 1 0 0 0 0 + 20 15 1 6 0 0 0 + 16 21 1 0 0 0 0 + 16 22 2 0 0 0 0 + 17 23 1 0 0 0 0 + 18 24 1 0 0 0 0 + 19 25 2 0 0 0 0 + 19 26 1 0 0 0 0 + 20 27 1 0 0 0 0 + 20 28 1 0 0 0 0 + 21 29 1 0 0 0 0 + 23 30 1 6 0 0 0 + 23 31 1 0 0 0 0 + 24 32 2 0 0 0 0 + 24 33 1 0 0 0 0 + 26 34 1 0 0 0 0 + 27 35 1 0 0 0 0 + 28 36 1 1 0 0 0 + 28 37 1 0 0 0 0 + 29 38 2 0 0 0 0 + 29 39 1 0 0 0 0 + 30 40 1 0 0 0 0 + 31 41 2 0 0 0 0 + 31 42 1 0 0 0 0 + 33 43 1 1 0 0 0 + 33 44 1 0 0 0 0 + 34 45 1 6 0 0 0 + 35 46 1 0 0 0 0 + 35 47 1 0 0 0 0 + 48 36 1 1 0 0 0 + 37 49 1 6 0 0 0 + 38 50 1 0 0 0 0 + 38 51 1 0 0 0 0 + 39 52 2 0 0 0 0 + 40 53 2 0 0 0 0 + 54 42 1 1 0 0 0 + 43 55 1 0 0 0 0 + 44 56 1 0 0 0 0 + 45 57 1 0 0 0 0 + 46 58 1 1 0 0 0 + 47 59 1 0 0 0 0 + 48 60 1 0 0 0 0 + 48 61 1 0 0 0 0 + 51 62 2 0 0 0 0 + 54 63 1 0 0 0 0 + 54 64 1 0 0 0 0 + 56 65 1 0 0 0 0 + 56 66 1 0 0 0 0 + 57 67 2 0 0 0 0 + 57 68 1 0 0 0 0 + 60 69 1 0 0 0 0 + 61 70 1 0 0 0 0 + 62 71 1 0 0 0 0 + 63 72 2 0 0 0 0 + 63 73 1 0 0 0 0 + 64 74 2 0 0 0 0 + 64 75 1 0 0 0 0 + 69 76 1 0 0 0 0 + 69 77 1 6 0 0 0 + 70 78 1 6 0 0 0 + 70 79 1 0 0 0 0 + 71 80 1 1 0 0 0 + 71 81 1 0 0 0 0 + 74 82 1 0 0 0 0 + 75 83 2 0 0 0 0 + 76 84 1 6 0 0 0 + 81 85 1 0 0 0 0 + 82 86 1 0 0 0 0 + 82 87 2 0 0 0 0 + 85 88 2 0 0 0 0 + 85 89 1 0 0 0 0 + 86 90 2 0 0 0 0 + 86 91 1 0 0 0 0 + 87 92 1 0 0 0 0 + 89 93 1 0 0 0 0 + 90 94 1 0 0 0 0 + 90 95 1 0 0 0 0 + 91 96 2 0 0 0 0 + 93 97 1 1 0 0 0 + 95 98 2 0 0 0 0 + 97 99 2 0 0 0 0 + 97100 1 0 0 0 0 + 98101 1 0 0 0 0 + 7 9 1 0 0 0 0 + 17 22 1 0 0 0 0 + 34 40 1 0 0 0 0 + 37 46 1 0 0 0 0 + 52 62 1 0 0 0 0 + 70 76 1 0 0 0 0 + 81 73 1 1 0 0 0 + 83 87 1 0 0 0 0 + 91 93 1 0 0 0 0 + 96 98 1 0 0 0 0 +M END +> +Compound 20652 + +> +BIO-423 + +> +VANCOMYCIN HYDROCHLORIDE + +> +Products for Life Science + +> +1404-93-9 + +> +1485.7 + +> +'93.5% (Vanomycin base) + +> +MFCD03613611 + +$$$$ +Compound 20656 +Actelion Java MolfileCreator 1.0 + + 75 78 0 0 1 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 S 0 0 0 0 0 0 0 0 0 0 0 0 + -1.4488 -0.4553 -0.0000 S 0 0 0 0 0 0 0 0 0 0 0 0 + 0.3036 1.4902 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.7799 -1.9179 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8279 2.5112 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.0631 -2.2628 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.5243 4.0013 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -2.2352 2.0559 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.3804 -3.8496 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -4.3739 -1.3384 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.4974 0.3311 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4218 3.0907 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -5.0500 -4.4153 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.5467 -1.5453 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.8910 0.2070 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -4.9258 2.6630 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.8088 -3.2563 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -5.5329 -5.6019 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.9396 1.3522 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.9803 0.8141 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.3259 0.9244 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.0158 3.6564 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.7057 -6.0158 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -4.2359 -6.7471 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.6229 1.2280 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.2635 2.5112 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.0079 2.2490 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.4429 0.0690 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5677 0.5657 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -5.7123 5.1466 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -8.1131 -5.1190 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.5671 -8.2097 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.3266 -0.1656 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -7.5060 2.3732 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -6.9541 -0.7727 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.8437 6.1676 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.2911 5.6295 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.3687 -5.6295 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -7.7405 -3.5322 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.0158 -8.6650 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4632 -9.2031 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -9.0237 2.2352 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -8.4304 -1.1866 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.0020 -1.8627 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5401 7.6577 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9875 7.1196 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -8.7616 -2.6630 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -6.2504 -2.9251 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.6584 0.8693 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.9206 3.4770 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.6032 -0.2070 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -6.3056 -3.3391 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.1190 8.1407 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.3949 -4.1807 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -8.6650 -0.2070 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -11.1762 0.7313 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -9.3135 4.8706 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.8844 -4.2083 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.4232 -3.9600 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.8154 9.6308 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.8496 -3.5460 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.8109 -0.6347 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -10.2103 6.1124 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.1328 -5.6985 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.6439 -5.2845 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.6564 -2.4146 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -2.5526 -4.7188 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -13.3286 -0.7727 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.7281 5.9744 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -6.7333 -6.4849 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -13.9633 -2.1386 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -14.2255 0.4691 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -12.6249 7.2162 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -12.0178 8.6098 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -14.1427 7.0782 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 4 6 1 0 0 0 0 + 5 7 1 1 0 0 0 + 5 8 1 0 0 0 0 + 6 9 1 0 0 0 0 + 6 10 1 6 0 0 0 + 8 11 2 0 0 0 0 + 8 12 1 0 0 0 0 + 9 13 1 0 0 0 0 + 10 14 2 0 0 0 0 + 10 15 1 0 0 0 0 + 12 16 1 0 0 0 0 + 13 17 2 0 0 0 0 + 13 18 1 0 0 0 0 + 15 19 1 0 0 0 0 + 15 20 1 0 0 0 0 + 16 21 1 0 0 0 0 + 16 22 1 6 0 0 0 + 18 23 1 0 0 0 0 + 18 24 1 6 0 0 0 + 19 25 1 6 0 0 0 + 19 26 1 0 0 0 0 + 20 27 1 0 0 0 0 + 21 28 2 0 0 0 0 + 21 29 1 0 0 0 0 + 22 30 1 0 0 0 0 + 23 31 1 0 0 0 0 + 24 32 1 0 0 0 0 + 25 33 2 0 0 0 0 + 25 34 1 0 0 0 0 + 29 35 1 0 0 0 0 + 30 36 2 0 0 0 0 + 30 37 1 0 0 0 0 + 31 38 2 0 0 0 0 + 31 39 1 0 0 0 0 + 32 40 2 0 0 0 0 + 32 41 1 0 0 0 0 + 42 34 1 6 0 0 0 + 35 43 1 0 0 0 0 + 35 44 1 1 0 0 0 + 36 45 1 0 0 0 0 + 37 46 2 0 0 0 0 + 39 47 1 0 0 0 0 + 39 48 1 1 0 0 0 + 42 49 1 0 0 0 0 + 42 50 1 0 0 0 0 + 43 51 2 0 0 0 0 + 44 52 1 0 0 0 0 + 45 53 2 0 0 0 0 + 48 54 1 0 0 0 0 + 49 55 2 0 0 0 0 + 49 56 1 0 0 0 0 + 50 57 1 0 0 0 0 + 52 58 2 0 0 0 0 + 52 59 1 0 0 0 0 + 53 60 1 0 0 0 0 + 54 61 1 0 0 0 0 + 56 62 1 0 0 0 0 + 57 63 1 0 0 0 0 + 58 64 1 0 0 0 0 + 59 65 2 0 0 0 0 + 61 66 2 0 0 0 0 + 61 67 1 0 0 0 0 + 62 68 1 0 0 0 0 + 63 69 1 0 0 0 0 + 64 70 2 0 0 0 0 + 68 71 2 0 0 0 0 + 68 72 1 0 0 0 0 + 69 73 2 0 0 0 0 + 73 74 1 0 0 0 0 + 73 75 1 0 0 0 0 + 26 27 1 0 0 0 0 + 43 47 1 0 0 0 0 + 46 53 1 0 0 0 0 + 65 70 1 0 0 0 0 +M END +> +Compound 20656 + +> +BIO-992 + +> +VASOPRESSIN + +> +Products for Life Science + +> + + +> + + +> +' + +> +MFCD03839092 + +$$$$ +Compound 20659 +Actelion Java MolfileCreator 1.0 + + 33 34 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2913 0.7582 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0118 -1.4927 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5825 0.0118 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2794 2.2745 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5707 -1.4808 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8738 0.7700 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5707 3.0327 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8620 -2.2271 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8620 2.2864 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5588 4.5491 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8501 3.8027 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2439 5.3072 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8501 5.3072 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1414 3.0564 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0711 4.5609 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2320 6.8236 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1414 4.5609 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.4327 5.3191 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.7239 4.5728 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 9.0152 5.3309 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.7121 3.0801 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 10.3065 4.5846 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 11.5977 5.3428 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 12.8890 4.5964 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 11.5859 6.8591 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 14.1803 5.3546 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 12.8772 7.6173 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 15.4715 4.6083 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 14.1684 6.8710 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 16.7628 5.3665 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 15.4597 7.6292 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 15.4478 9.1455 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 2 4 2 0 0 0 0 + 2 5 1 0 0 0 0 + 4 6 1 0 0 0 0 + 4 7 1 0 0 0 0 + 5 8 2 0 0 0 0 + 6 9 1 0 0 0 0 + 7 10 2 0 0 0 0 + 8 11 1 0 0 0 0 + 11 12 1 6 0 0 0 + 11 13 1 0 0 0 0 + 11 14 1 0 0 0 0 + 12 15 3 0 0 0 0 + 13 16 1 0 0 0 0 + 13 17 1 0 0 0 0 + 14 18 1 0 0 0 0 + 18 19 1 0 0 0 0 + 19 20 1 0 0 0 0 + 20 21 1 0 0 0 0 + 20 22 1 0 0 0 0 + 21 23 1 0 0 0 0 + 23 24 1 0 0 0 0 + 24 25 2 0 0 0 0 + 24 26 1 0 0 0 0 + 25 27 1 0 0 0 0 + 26 28 2 0 0 0 0 + 27 29 1 0 0 0 0 + 27 30 2 0 0 0 0 + 29 31 1 0 0 0 0 + 30 32 1 0 0 0 0 + 32 33 1 0 0 0 0 + 8 10 1 0 0 0 0 + 28 30 1 0 0 0 0 +M END +> +Compound 20659 + +> +BIO-424 + +> +VERAPAMIL HYDROCHLORIDE + +> +Products for Life Science + +> +152-11-4 + +> +491.1 + +> +'>99% + +> +MFCD00055208 + +$$$$ +Compound 20668 +Actelion Java MolfileCreator 1.0 + + 37 42 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.8775 -1.1977 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.3598 -1.0198 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2609 -2.5614 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2374 -2.2175 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2255 0.2135 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.6404 -1.3400 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.1384 -3.7592 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2451 -2.7156 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.6207 -3.5813 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.6604 -1.7313 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.6485 -0.2253 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5218 -5.1229 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1464 -1.4942 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.8618 -4.0793 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.4983 -4.7790 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.9843 -5.2770 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7195 -6.0004 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.3085 -4.5418 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.8736 -6.4866 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 1.9092 -7.4827 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.3085 -6.0360 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.6248 -3.7829 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.6958 -7.9689 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.9843 -8.6686 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.9646 -8.5263 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.3441 -7.0677 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.6248 -6.7831 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.9411 -4.5300 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.5099 -8.8702 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.0121 -8.7042 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.9411 -6.0241 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.0239 -10.1983 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.2574 -6.7712 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.7313 -10.9336 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.3402 -10.9336 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.2574 -8.2654 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 3 6 1 0 0 0 0 + 4 7 1 0 0 0 0 + 4 8 1 0 0 0 0 + 4 9 1 0 0 0 0 + 5 10 1 0 0 0 0 + 5 11 1 0 0 0 0 + 6 12 1 0 0 0 0 + 8 13 1 0 0 0 0 + 9 14 1 0 0 0 0 + 9 15 1 0 0 0 0 + 10 16 2 0 0 0 0 + 13 17 1 0 0 0 0 + 13 18 1 0 0 0 0 + 15 19 1 0 0 0 0 + 17 20 1 0 0 0 0 + 18 21 1 0 0 0 0 + 19 22 2 0 0 0 0 + 19 23 1 0 0 0 0 + 20 24 1 0 0 0 0 + 21 25 1 0 0 0 0 + 21 26 1 0 0 0 0 + 21 27 1 0 0 0 0 + 22 28 1 0 0 0 0 + 23 29 2 0 0 0 0 + 24 30 1 0 0 0 0 + 24 31 1 0 0 0 0 + 28 32 2 0 0 0 0 + 31 33 2 0 0 0 0 + 32 34 1 0 0 0 0 + 33 35 1 0 0 0 0 + 33 36 1 0 0 0 0 + 34 37 1 0 0 0 0 + 8 10 1 0 0 0 0 + 11 12 1 0 0 0 0 + 15 17 2 0 0 0 0 + 20 22 1 0 0 0 0 + 25 30 1 0 0 0 0 + 29 32 1 0 0 0 0 +M END +> +Compound 20668 + +> +BIO-1002 + +> +VERRUCULOGEN FROM PENICILLIUM VERRUCULOSUM + +> +Products for Life Science + +> +12771-72-1 + +> + + +> +' + +> +MFCD00079645 + +$$$$ +Compound 20680 +Actelion Java MolfileCreator 1.0 + + 67 75 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2923 -0.7469 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2804 -2.2407 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5846 0.0119 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0356 -2.9877 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5727 -2.9877 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8768 -0.7351 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5727 1.5294 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3516 -2.2289 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0474 -4.4815 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8650 -2.2289 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5609 -4.4815 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1691 0.0237 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8650 2.2882 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2449 -5.2284 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3634 -5.2284 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1573 -2.9758 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1573 -1.4701 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 6.4614 -0.7232 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1573 1.5413 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6794 -4.4696 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3753 -6.7222 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.4495 -2.2170 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 7.7537 0.0356 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1454 3.0588 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 6.4495 2.3000 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9954 -5.2165 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6913 -7.4691 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.7418 1.5531 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.0073 -6.7104 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.3114 -4.4578 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.7031 -8.9630 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 9.0341 2.3119 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 9.0341 0.8062 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.3232 -7.4573 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 10.3264 1.5650 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.3351 -8.9511 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 10.3145 0.0711 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 11.6187 2.3237 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.6511 -9.6980 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -4.0428 -9.6980 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 11.6068 -0.6758 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 12.9110 1.5768 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.6630 -11.1919 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.0547 -11.1919 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 12.8991 0.0830 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 11.5950 -2.1696 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.3707 -11.9388 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.9789 -11.9388 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 14.1914 -0.6639 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -5.3825 -13.4326 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 15.4837 0.0948 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.0902 -14.1795 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 16.7759 -0.6521 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 15.4718 1.6124 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.1021 -15.6734 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -2.7980 -13.4208 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 18.0682 0.1067 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 16.7641 2.3712 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.8098 -16.4203 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.5057 -14.1677 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 18.0564 1.6242 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 19.3605 -0.6402 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.5175 -15.6615 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.8217 -17.9141 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 19.3486 2.3830 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.2253 -16.4084 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 2 0 0 0 0 + 3 6 1 0 0 0 0 + 4 7 2 0 0 0 0 + 4 8 1 0 0 0 0 + 5 9 1 0 0 0 0 + 5 10 1 0 0 0 0 + 6 11 1 0 0 0 0 + 6 12 2 0 0 0 0 + 7 13 1 0 0 0 0 + 8 14 2 0 0 0 0 + 10 15 2 0 0 0 0 + 16 10 1 1 0 0 0 + 11 17 2 0 0 0 0 + 13 18 1 1 0 0 0 + 13 19 1 0 0 0 0 + 13 20 1 0 0 0 0 + 16 21 1 0 0 0 0 + 16 22 1 0 0 0 0 + 19 23 2 0 0 0 0 + 19 24 1 0 0 0 0 + 20 25 1 1 0 0 0 + 20 26 1 0 0 0 0 + 21 27 1 0 0 0 0 + 22 28 1 0 0 0 0 + 24 29 1 0 0 0 0 + 27 30 1 0 0 0 0 + 27 31 1 0 0 0 0 + 28 32 1 0 0 0 0 + 29 33 1 0 0 0 0 + 29 34 1 6 0 0 0 + 30 35 1 6 0 0 0 + 33 36 1 0 0 0 0 + 37 35 1 1 0 0 0 + 36 38 1 0 0 0 0 + 36 39 1 0 0 0 0 + 37 40 1 0 0 0 0 + 37 41 1 0 0 0 0 + 38 42 1 0 0 0 0 + 39 43 1 0 0 0 0 + 40 44 1 0 0 0 0 + 41 45 1 0 0 0 0 + 42 46 1 0 0 0 0 + 42 47 1 6 0 0 0 + 44 48 1 0 0 0 0 + 44 49 1 6 0 0 0 + 46 50 1 0 0 0 0 + 48 51 1 6 0 0 0 + 50 52 1 0 0 0 0 + 53 51 1 1 0 0 0 + 52 54 1 0 0 0 0 + 52 55 1 0 0 0 0 + 53 56 1 0 0 0 0 + 53 57 1 0 0 0 0 + 54 58 1 0 0 0 0 + 55 59 2 0 0 0 0 + 56 60 1 0 0 0 0 + 57 61 2 0 0 0 0 + 58 62 1 0 0 0 0 + 58 63 1 6 0 0 0 + 60 64 1 0 0 0 0 + 60 65 1 6 0 0 0 + 62 66 2 0 0 0 0 + 64 67 2 0 0 0 0 + 7 11 1 0 0 0 0 + 12 15 1 0 0 0 0 + 14 20 1 0 0 0 0 + 26 29 1 0 0 0 0 + 28 30 1 0 0 0 0 + 43 46 1 0 0 0 0 + 45 48 1 0 0 0 0 + 59 62 1 0 0 0 0 + 61 64 1 0 0 0 0 +M END +> +Compound 20680 + +> +BIO-718 + +> +VINEOMYCIN A1 + +> +Products for Life Science + +> +78164-00-8 + +> +934.98 + +> +'>80% + +> +MFCD00079639 + +$$$$ +Compound 20681 +Actelion Java MolfileCreator 1.0 + + 67 74 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3071 0.7536 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3188 2.2609 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6141 0.0118 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0353 3.0145 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6259 3.0145 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9212 0.7654 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6259 -1.4719 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2482 2.2727 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0471 4.5218 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9330 2.2727 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6377 4.5218 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2283 0.0236 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9330 -2.2138 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3542 5.2754 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2364 5.2754 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2401 3.0263 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5354 0.7772 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2401 -1.4602 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5199 4.5335 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2246 6.7826 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5471 -2.2020 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8035 5.2872 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5082 7.5363 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5589 -3.6857 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7917 6.7944 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0870 4.5453 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.4964 9.0435 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -7.8660 -4.4276 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2754 -4.4276 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2754 -2.9321 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0752 7.5480 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -9.1731 -3.6739 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2872 -5.9113 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0634 9.0553 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.1848 -2.1667 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -10.4801 -4.4158 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5942 -6.6531 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -4.0036 -6.6531 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 6.3470 9.8089 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7564 9.8089 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -10.4919 -1.4131 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.7872 -3.6622 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.3352 11.3162 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7446 11.3162 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.7990 -2.1549 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -10.5037 0.0942 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0281 12.0698 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.6187 12.0698 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -13.1061 -1.4013 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0163 13.5771 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -14.4131 -2.1431 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7093 14.3307 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -14.4249 -3.6268 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -15.7202 -1.3895 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.6975 15.8380 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.4022 13.5888 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -15.7320 -4.3687 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -17.0273 -2.1314 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.3904 16.5916 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0951 14.3425 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -17.0390 -3.6151 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -15.7437 -5.8524 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0833 15.8497 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.3786 18.0988 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -18.3461 -4.3569 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.2237 16.6034 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 2 0 0 0 0 + 3 6 1 0 0 0 0 + 4 7 2 0 0 0 0 + 4 8 1 0 0 0 0 + 5 9 1 0 0 0 0 + 5 10 1 0 0 0 0 + 6 11 1 0 0 0 0 + 6 12 2 0 0 0 0 + 7 13 1 0 0 0 0 + 8 14 2 0 0 0 0 + 10 15 2 0 0 0 0 + 16 10 1 1 0 0 0 + 11 17 2 0 0 0 0 + 13 18 1 0 0 0 0 + 13 19 2 0 0 0 0 + 16 20 1 0 0 0 0 + 16 21 1 0 0 0 0 + 19 22 1 0 0 0 0 + 20 23 1 0 0 0 0 + 21 24 1 0 0 0 0 + 22 25 1 0 0 0 0 + 23 26 1 0 0 0 0 + 23 27 1 1 0 0 0 + 24 28 1 1 0 0 0 + 25 29 1 0 0 0 0 + 25 30 1 0 0 0 0 + 25 31 1 1 0 0 0 + 26 32 1 6 0 0 0 + 33 29 1 1 0 0 0 + 30 34 1 0 0 0 0 + 35 32 1 6 0 0 0 + 33 36 1 0 0 0 0 + 33 37 1 0 0 0 0 + 34 38 2 0 0 0 0 + 34 39 1 0 0 0 0 + 35 40 1 0 0 0 0 + 35 41 1 0 0 0 0 + 36 42 1 0 0 0 0 + 37 43 1 0 0 0 0 + 40 44 1 0 0 0 0 + 41 45 1 0 0 0 0 + 42 46 1 0 0 0 0 + 42 47 1 6 0 0 0 + 44 48 1 0 0 0 0 + 44 49 1 1 0 0 0 + 46 50 1 6 0 0 0 + 48 51 1 1 0 0 0 + 52 50 1 6 0 0 0 + 53 51 1 1 0 0 0 + 52 54 1 0 0 0 0 + 52 55 1 0 0 0 0 + 53 56 1 0 0 0 0 + 53 57 1 0 0 0 0 + 54 58 1 0 0 0 0 + 55 59 2 0 0 0 0 + 56 60 1 0 0 0 0 + 57 61 2 0 0 0 0 + 58 62 1 0 0 0 0 + 58 63 1 1 0 0 0 + 60 64 1 0 0 0 0 + 60 65 1 6 0 0 0 + 62 66 2 0 0 0 0 + 64 67 2 0 0 0 0 + 7 11 1 0 0 0 0 + 12 15 1 0 0 0 0 + 14 19 1 0 0 0 0 + 24 26 1 0 0 0 0 + 43 46 1 0 0 0 0 + 45 48 1 0 0 0 0 + 59 62 1 0 0 0 0 + 61 64 1 0 0 0 0 +M END +> +Compound 20681 + +> +BIO-719 + +> +VINEOMYCIN B2 + +> +Products for Life Science + +> +80928-52-5 + +> +934.98 + +> +' + +> +MFCD09752773 + +$$$$ +Compound 20685 +Actelion Java MolfileCreator 1.0 + + 57 65 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.2264 -1.4844 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.6982 -2.3020 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.9435 -2.4027 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.8743 -3.5222 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.5032 -2.8555 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.9121 -3.5348 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0441 -0.8806 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.6731 -1.6605 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8302 -4.3147 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.3208 -4.9186 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 3.4090 -3.6355 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2895 0.1258 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3334 -0.3396 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.0820 -2.2769 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.2769 -4.7676 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.4530 -5.8872 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7487 -5.0947 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.5412 -2.6417 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.9562 1.4844 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0945 -1.1321 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.4656 0.6793 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4090 -3.7361 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.9058 -6.1388 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.4781 -7.3841 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0569 -5.7991 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.5915 -1.0315 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4531 1.5724 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.7299 -4.4783 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -4.4154 -5.9627 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.5348 -7.5099 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.4215 -6.2897 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7864 -8.0886 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0821 -7.2961 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.2582 0.3271 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1198 2.9310 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.0633 -3.8493 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.8117 -6.2646 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.4278 -8.5037 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -4.5160 -8.5414 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.1196 -7.7489 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.2896 4.2141 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.5224 -4.8557 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -7.0067 -5.3085 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.8243 -7.7615 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1637 -9.8874 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.7802 -9.9629 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.8998 -9.1704 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -8.4156 -5.7614 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -6.8181 -3.7990 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -7.1451 -8.5037 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4593 -10.6674 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.0381 -10.6674 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.9879 -2.8430 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -8.4660 -7.7364 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -8.4911 -6.3904 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -9.7868 -8.4785 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 4 2 1 1 0 0 0 + 3 5 1 0 0 0 0 + 4 6 1 0 0 0 0 + 4 7 1 0 0 0 0 + 4 8 1 0 0 0 0 + 6 9 2 0 0 0 0 + 6 10 1 0 0 0 0 + 7 11 1 0 0 0 0 + 7 12 2 0 0 0 0 + 8 13 1 0 0 0 0 + 9 14 1 0 0 0 0 + 9 15 1 0 0 0 0 + 10 16 2 0 0 0 0 + 11 17 1 0 0 0 0 + 12 18 1 0 0 0 0 + 12 19 1 0 0 0 0 + 13 20 1 0 0 0 0 + 13 21 1 0 0 0 0 + 14 22 1 0 0 0 0 + 15 23 2 0 0 0 0 + 24 16 1 1 0 0 0 + 17 25 1 0 0 0 0 + 18 26 1 0 0 0 0 + 19 27 1 0 0 0 0 + 20 28 2 0 0 0 0 + 23 29 1 0 0 0 0 + 24 30 1 0 0 0 0 + 24 31 1 0 0 0 0 + 24 32 1 0 0 0 0 + 25 33 2 0 0 0 0 + 26 34 2 0 0 0 0 + 27 35 1 0 0 0 0 + 28 36 1 0 0 0 0 + 29 37 1 0 0 0 0 + 30 38 1 0 0 0 0 + 31 39 1 6 0 0 0 + 31 40 1 0 0 0 0 + 32 41 1 0 0 0 0 + 36 42 1 0 0 0 0 + 38 43 1 6 0 0 0 + 38 44 1 0 0 0 0 + 38 45 1 0 0 0 0 + 39 46 1 0 0 0 0 + 40 47 1 0 0 0 0 + 40 48 1 1 0 0 0 + 44 49 2 0 0 0 0 + 44 50 1 0 0 0 0 + 45 51 1 6 0 0 0 + 46 52 1 0 0 0 0 + 48 53 1 0 0 0 0 + 50 54 1 0 0 0 0 + 51 55 1 0 0 0 0 + 55 56 2 0 0 0 0 + 55 57 1 0 0 0 0 + 16 23 1 0 0 0 0 + 17 18 2 0 0 0 0 + 21 27 1 0 0 0 0 + 28 35 1 0 0 0 0 + 30 29 1 1 0 0 0 + 33 34 1 0 0 0 0 + 39 41 1 0 0 0 0 + 40 45 1 0 0 0 0 + 47 52 2 0 0 0 0 +M END +> +Compound 20685 + +> +BIO-802 + +> +VINORELBINE DITARTRATE SALT + +> +Products for Life Science + +> +125317-39-7 + +> +1079.12 + +> +'98% + +> +MFCD07367166 + +$$$$ +Compound 20693 +Actelion Java MolfileCreator 1.0 + + 38 40 0 0 1 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.6991 -1.2863 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.5173 -2.1531 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0832 -0.7410 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.4401 -3.3135 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.5512 -0.5872 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 1.4820 0.6431 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.0133 -4.6837 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.7403 -2.5586 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0053 -0.8389 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8728 0.8808 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5865 1.6358 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.7896 -6.1377 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.5093 -4.5019 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.7543 -1.0486 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.0406 -3.2856 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.4247 0.6012 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 6.6690 -1.5379 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.9713 -7.6058 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.7669 -3.0060 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 8.0252 -0.9507 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3562 -8.9479 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.2069 -3.3415 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.9759 -2.0692 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6285 -9.7309 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.4055 -10.0664 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 8.6264 -5.1031 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.8109 -10.8774 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.6404 -6.5712 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2789 -10.9333 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 10.1084 -6.7249 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 8.2629 -7.9972 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.6770 -11.3807 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.5079 -9.2695 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.9633 -10.6537 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.6683 -10.1643 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 6.4313 -10.2901 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4181 -9.2416 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 4 6 1 0 0 0 0 + 4 7 2 0 0 0 0 + 5 8 1 0 0 0 0 + 5 9 1 1 0 0 0 + 6 10 1 0 0 0 0 + 6 11 1 0 0 0 0 + 7 12 1 0 0 0 0 + 8 13 1 0 0 0 0 + 8 14 1 1 0 0 0 + 9 15 1 0 0 0 0 + 9 16 1 0 0 0 0 + 10 17 2 0 0 0 0 + 10 18 1 0 0 0 0 + 13 19 2 0 0 0 0 + 18 20 1 0 0 0 0 + 18 21 2 0 0 0 0 + 19 22 1 0 0 0 0 + 20 23 2 0 0 0 0 + 21 24 1 0 0 0 0 + 22 25 2 0 0 0 0 + 22 26 1 0 0 0 0 + 23 27 1 0 0 0 0 + 26 28 1 0 0 0 0 + 27 29 1 0 0 0 0 + 28 30 1 0 0 0 0 + 29 31 2 0 0 0 0 + 29 32 1 0 0 0 0 + 30 33 2 0 0 0 0 + 32 34 1 0 0 0 0 + 33 35 1 0 0 0 0 + 34 36 1 6 0 0 0 + 34 37 1 0 0 0 0 + 35 38 1 0 0 0 0 + 11 12 1 0 0 0 0 + 23 24 1 0 0 0 0 + 35 37 2 0 0 0 0 +M END +> +Compound 20693 + +> +BIO-425 + +> +VIRGINIAMYCIN M1 + +> +Products for Life Science + +> +21411-53-0 + +> +525.59 + +> +' + +> +MFCD00869411 + +$$$$ +Compound 20694 +Actelion Java MolfileCreator 1.0 + + 60 65 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0711 1.5058 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3991 1.8497 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5533 1.6837 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6915 2.6441 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.8931 2.3358 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 1.9446 0.2490 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.6520 3.8180 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.6875 1.5296 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.9603 3.3911 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.8893 -0.8181 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.3911 -0.1067 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.9562 3.0828 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -4.1855 5.2290 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1578 2.5137 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 4.6242 4.7428 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2806 -2.2528 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7824 -1.5414 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.2605 3.8417 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.6440 4.9681 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -4.2330 6.7348 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8140 6.2368 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7981 3.8298 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.7271 -2.6085 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.2842 5.3594 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -7.5648 3.1065 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.7943 8.1814 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.5175 7.7189 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1894 6.8178 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.1735 4.4108 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -8.8691 3.8654 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -7.5767 1.6244 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.9168 9.4026 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.1460 8.8691 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.9048 8.2525 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7587 9.0232 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3632 5.9048 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.3474 3.4978 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -10.1733 3.1303 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.2961 0.8893 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -8.8809 0.8893 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9721 10.4935 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.6956 10.2682 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -6.4147 8.0628 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.6204 10.0192 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 4.9088 9.9836 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -10.1852 1.6481 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.2609 10.6832 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.5374 11.5250 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2213 10.6002 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.3793 11.2642 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.6480 11.4776 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.2134 12.1890 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.6244 12.7108 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5414 12.0705 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7981 12.4380 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2370 12.0112 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5372 13.9320 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.9761 13.5052 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.1263 14.4656 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 4 6 1 0 0 0 0 + 4 7 1 0 0 0 0 + 5 8 1 0 0 0 0 + 5 9 1 0 0 0 0 + 6 10 1 0 0 0 0 + 7 11 2 0 0 0 0 + 7 12 1 0 0 0 0 + 8 13 1 0 0 0 0 + 8 14 1 0 0 0 0 + 10 15 2 0 0 0 0 + 10 16 1 0 0 0 0 + 11 17 1 0 0 0 0 + 12 18 2 0 0 0 0 + 13 19 1 0 0 0 0 + 14 20 2 0 0 0 0 + 14 21 1 0 0 0 0 + 16 22 1 0 0 0 0 + 16 23 1 0 0 0 0 + 17 24 2 0 0 0 0 + 19 25 2 0 0 0 0 + 19 26 1 0 0 0 0 + 21 27 1 0 0 0 0 + 22 28 1 0 0 0 0 + 22 29 1 0 0 0 0 + 23 30 1 0 0 0 0 + 26 31 2 0 0 0 0 + 26 32 1 0 0 0 0 + 27 33 1 0 0 0 0 + 27 34 1 0 0 0 0 + 28 35 2 0 0 0 0 + 28 36 1 0 0 0 0 + 29 37 1 0 0 0 0 + 30 38 2 0 0 0 0 + 31 39 1 0 0 0 0 + 32 40 1 0 0 0 0 + 32 41 2 0 0 0 0 + 33 42 2 0 0 0 0 + 33 43 1 0 0 0 0 + 34 44 1 0 0 0 0 + 36 45 1 0 0 0 0 + 36 46 1 0 0 0 0 + 39 47 2 0 0 0 0 + 43 48 1 0 0 0 0 + 43 49 1 0 0 0 0 + 45 50 1 0 0 0 0 + 45 51 1 0 0 0 0 + 46 52 1 0 0 0 0 + 48 53 1 0 0 0 0 + 49 54 1 0 0 0 0 + 50 55 2 0 0 0 0 + 52 56 2 0 0 0 0 + 52 57 1 0 0 0 0 + 56 58 1 0 0 0 0 + 57 59 2 0 0 0 0 + 58 60 2 0 0 0 0 + 18 24 1 0 0 0 0 + 30 37 1 0 0 0 0 + 41 47 1 0 0 0 0 + 48 50 1 0 0 0 0 + 53 54 1 0 0 0 0 + 59 60 1 0 0 0 0 +M END +> +Compound 20694 + +> +BIO-1003 + +> +VIRGINIAMYCIN S1 + +> +Products for Life Science + +> +23152-29-6 + +> +823.9 + +> +' + +> +MFCD00864857 + +$$$$ +Compound 20697 +Actelion Java MolfileCreator 1.0 + + 33 34 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2839 0.7539 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5678 0.0118 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2721 2.2616 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8518 0.7656 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5561 -1.4724 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5561 3.0154 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0353 3.0154 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8400 2.2734 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1357 0.0236 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8400 -2.2145 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5443 4.5232 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3428 2.2734 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1239 3.0272 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1239 -1.4606 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6503 3.0272 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9578 2.2851 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6621 4.5349 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2652 3.0390 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5727 2.2969 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.8802 3.0508 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.1877 2.3087 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.8920 4.5585 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -10.4952 3.0626 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.8026 2.3205 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -13.1101 3.0743 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -14.4176 2.3323 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -13.1219 4.5821 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -15.7251 3.0861 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -17.0325 2.3440 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -18.3400 3.0979 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -18.3518 4.6056 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -19.6475 2.3558 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 2 0 0 0 0 + 3 6 1 0 0 0 0 + 4 7 2 0 0 0 0 + 4 8 1 0 0 0 0 + 5 9 1 0 0 0 0 + 5 10 1 0 0 0 0 + 6 11 2 0 0 0 0 + 7 12 1 0 0 0 0 + 8 13 1 0 0 0 0 + 9 14 2 0 0 0 0 + 10 15 2 0 0 0 0 + 13 16 2 0 0 0 0 + 16 17 1 0 0 0 0 + 16 18 1 0 0 0 0 + 17 19 1 0 0 0 0 + 19 20 1 0 0 0 0 + 20 21 1 0 0 0 0 + 21 22 1 0 0 0 0 + 21 23 1 6 0 0 0 + 22 24 1 0 0 0 0 + 24 25 1 0 0 0 0 + 25 26 1 0 0 0 0 + 26 27 1 0 0 0 0 + 26 28 1 6 0 0 0 + 27 29 1 0 0 0 0 + 29 30 1 0 0 0 0 + 30 31 1 0 0 0 0 + 31 32 1 0 0 0 0 + 31 33 1 0 0 0 0 + 7 9 1 0 0 0 0 + 11 15 1 0 0 0 0 +M END +> +Compound 20697 + +> +BIO-1005 + +> +VITAMIN K1 + +> +Products for Life Science + +> +84-80-0 + +> +450.7 + +> +' + +> +MFCD00214063 + +$$$$ +Compound 20716 +Actelion Java MolfileCreator 1.0 + + 11 12 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3095 -0.7432 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6189 0.0118 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3213 -2.2296 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9284 -0.7314 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6307 -2.9729 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2379 0.0236 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9402 -2.2178 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.9493 -4.4239 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -5.0609 -3.2088 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -4.4475 -4.5655 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 4 6 1 0 0 0 0 + 5 7 2 0 0 0 0 + 5 8 1 0 0 0 0 + 6 9 1 0 0 0 0 + 8 10 1 0 0 0 0 + 9 11 1 0 0 0 0 + 6 8 2 0 0 0 0 + 10 11 2 0 0 0 0 +M END +> +Compound 20716 + +> +BIO-1006 + +> +XANTHINE + +> +Products for Life Science + +> +69-89-6 + +> +152.11 + +> +' + +> +MFCD00078453 + +$$$$ +Compound 20727 +Actelion Java MolfileCreator 1.0 + + 44 47 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 S 0 0 0 0 0 0 0 0 0 0 0 0 + 0.1420 -1.4795 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.1657 1.5031 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.4795 0.1657 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.5031 -0.1420 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.4027 1.0889 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1541 -1.4676 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.7990 2.4737 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9058 0.9469 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.6336 -1.6452 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.3196 2.6394 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6985 3.7046 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -4.5331 -0.4143 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.2609 -3.0063 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -6.0362 -0.5563 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -5.7403 -3.3022 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -3.5152 -4.2964 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -6.9357 0.6746 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.9060 -4.7816 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.5331 -5.3971 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -2.0357 -4.4384 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.2198 -5.5273 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.1599 -3.2075 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.4321 -5.7995 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.2316 -7.0186 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -8.5336 -4.7580 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -1.7162 -1.8819 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.3196 -3.3495 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0473 -5.9415 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.8473 -5.5036 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8995 -0.6510 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.9232 -4.7106 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.6510 -7.3027 -0.0000 S 0 0 0 0 0 0 0 0 0 0 0 0 + -11.1611 -4.7343 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.8592 -6.9949 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.4027 -4.8527 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0121 -6.6754 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7338 -7.9063 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2546 -8.6638 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -12.4749 -5.4799 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.1729 -7.7406 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2785 -3.6217 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0063 -6.2138 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -12.4867 -6.9713 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 1 3 2 0 0 0 0 + 1 4 1 0 0 0 0 + 1 5 1 0 0 0 0 + 5 6 2 0 0 0 0 + 5 7 1 0 0 0 0 + 6 8 1 0 0 0 0 + 6 9 1 0 0 0 0 + 7 10 2 0 0 0 0 + 8 11 2 0 0 0 0 + 8 12 1 0 0 0 0 + 9 13 2 0 0 0 0 + 10 14 1 0 0 0 0 + 13 15 1 0 0 0 0 + 14 16 2 0 0 0 0 + 14 17 1 0 0 0 0 + 15 18 1 0 0 0 0 + 16 19 1 0 0 0 0 + 17 20 1 0 0 0 0 + 17 21 1 0 0 0 0 + 19 22 1 0 0 0 0 + 21 23 2 0 0 0 0 + 21 24 1 0 0 0 0 + 22 25 2 0 0 0 0 + 22 26 1 0 0 0 0 + 23 27 1 0 0 0 0 + 23 28 1 0 0 0 0 + 24 29 2 0 0 0 0 + 26 30 1 0 0 0 0 + 27 31 1 0 0 0 0 + 28 32 2 0 0 0 0 + 29 33 1 0 0 0 0 + 30 34 2 0 0 0 0 + 30 35 1 0 0 0 0 + 32 36 1 0 0 0 0 + 33 37 2 0 0 0 0 + 33 38 2 0 0 0 0 + 33 39 1 0 0 0 0 + 34 40 1 0 0 0 0 + 35 41 2 0 0 0 0 + 36 42 2 0 0 0 0 + 36 43 1 0 0 0 0 + 40 44 2 0 0 0 0 + 10 13 1 0 0 0 0 + 19 20 2 0 0 0 0 + 29 32 1 0 0 0 0 + 41 44 1 0 0 0 0 +M CHG 5 8 1 12 -1 14 1 36 1 43 -1 +M END +> +Compound 20727 + +> +BIO-1007 + +> +XTT SODIUM SALT + +> +Products for Life Science + +> +111072-31-2 + +> +673.53 + +> +' + +> +MFCD00083517 + +$$$$ +Compound 20743 +Actelion Java MolfileCreator 1.0 + + 23 24 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0118 -1.4873 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3221 -2.2310 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2749 -2.2310 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6323 -1.4755 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2631 -3.7183 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5615 -1.4755 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6441 0.0354 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9426 -2.2192 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0472 -4.4620 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5497 -4.4620 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5497 0.0354 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8482 -2.2192 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9544 0.7909 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8364 -3.7065 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2394 0.7909 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9662 2.3018 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1230 -4.4502 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2276 2.3018 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6796 3.0573 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0826 3.0573 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6914 4.5682 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3929 2.3136 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 4 6 2 0 0 0 0 + 4 7 1 0 0 0 0 + 5 8 1 0 0 0 0 + 5 9 1 1 0 0 0 + 6 10 1 0 0 0 0 + 6 11 1 0 0 0 0 + 7 12 1 0 0 0 0 + 7 13 2 0 0 0 0 + 8 14 1 0 0 0 0 + 11 15 2 0 0 0 0 + 12 16 2 0 0 0 0 + 14 17 1 0 0 0 0 + 15 18 1 0 0 0 0 + 16 19 1 0 0 0 0 + 17 20 1 0 0 0 0 + 19 21 1 0 0 0 0 + 20 22 2 0 0 0 0 + 20 23 1 0 0 0 0 + 13 15 1 0 0 0 0 + 21 23 1 0 0 0 0 +M END +> +Compound 20743 + +> +BIO-1009 + +> +ZEARALENONE + +> +Products for Life Science + +> +17924-92-4 + +> +318.37 + +> +' + +> +MFCD00133085 + +$$$$ +Compound 20744 +Actelion Java MolfileCreator 1.0 + + 16 17 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3057 0.7529 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6115 0.0118 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9172 0.7646 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6232 -1.4704 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2230 0.0235 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5287 0.7764 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -7.8344 0.0353 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.8462 -1.4469 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -9.1402 0.7881 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.1519 -2.1880 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.4578 2.2586 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -10.4459 0.0471 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -10.4577 -1.4351 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -10.9517 2.4233 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.5634 1.0587 -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 + 3 4 2 0 0 0 0 + 3 5 1 0 0 0 0 + 4 6 1 0 0 0 0 + 6 7 1 0 0 0 0 + 7 8 1 0 0 0 0 + 8 9 2 0 0 0 0 + 8 10 1 0 0 0 0 + 9 11 1 0 0 0 0 + 10 12 1 0 0 0 0 + 10 13 2 0 0 0 0 + 11 14 2 0 0 0 0 + 12 15 2 0 0 0 0 + 13 16 1 0 0 0 0 + 13 14 1 0 0 0 0 + 15 16 1 0 0 0 0 +M END +> +Compound 20744 + +> +BIO-428 + +> +"ZEATIN, trans ISOMER" + +> +Products for Life Science + +> +1637-39-4 + +> +219.25 + +> +'>99% trans isomer + +> +MFCD00213654 + +$$$$ +Compound 20745 +Actelion Java MolfileCreator 1.0 + + 25 27 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.4974 -0.1415 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.6013 -1.3559 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.5114 0.9786 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -1.8157 -1.5917 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.5188 -2.3463 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0516 -1.6507 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.2166 2.4524 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.0088 0.8371 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.1952 -2.1930 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.3773 -3.8201 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0420 -0.5306 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.9315 3.2070 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -3.5254 3.2070 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.6337 2.2166 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -0.9432 4.7162 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.5372 4.7162 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.2520 5.4708 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -4.8459 5.4708 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -6.1547 4.7280 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.4634 5.4826 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -8.7722 4.7398 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -10.0809 5.4944 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -8.7840 3.2542 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.3897 4.7516 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 2 4 1 1 0 0 0 + 2 5 1 0 0 0 0 + 3 6 1 0 0 0 0 + 3 7 1 1 0 0 0 + 4 8 1 0 0 0 0 + 4 9 1 0 0 0 0 + 5 10 1 6 0 0 0 + 6 11 1 6 0 0 0 + 7 12 1 0 0 0 0 + 8 13 2 0 0 0 0 + 8 14 1 0 0 0 0 + 9 15 2 0 0 0 0 + 13 16 1 0 0 0 0 + 14 17 2 0 0 0 0 + 16 18 2 0 0 0 0 + 17 19 1 0 0 0 0 + 19 20 1 0 0 0 0 + 20 21 1 0 0 0 0 + 21 22 2 0 0 0 0 + 22 23 1 0 0 0 0 + 22 24 1 0 0 0 0 + 23 25 1 0 0 0 0 + 5 6 1 0 0 0 0 + 14 15 1 0 0 0 0 + 17 18 1 0 0 0 0 +M END +> +Compound 20745 + +> +BIO-429 + +> +"ZEATIN RIBOSIDE, trans ISOMER" + +> +Products for Life Science + +> +6025-53-2 + +> +351.37 + +> +'>98% HPLC + +> +MFCD00036809 + +$$$$ +Compound 20751 +Actelion Java MolfileCreator 1.0 + + 31 33 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 S 0 0 0 0 0 0 0 0 0 0 0 0 + 0.7415 -1.2829 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7533 1.3065 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2829 0.7533 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3065 -0.7415 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6129 0.0118 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3182 -2.2245 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9194 -0.7297 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6247 -2.9660 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2258 0.0235 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9312 -2.2127 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5323 -0.7180 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2376 -2.9542 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -7.8388 0.0353 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.1452 -0.7062 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -7.8505 1.5419 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -10.4517 0.0471 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5676 2.2951 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.1570 2.2951 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.7581 -0.6944 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5794 3.8017 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.1688 3.8017 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -13.0646 0.0588 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.7699 -2.1774 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.8858 4.5550 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -13.0764 1.5654 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -14.3711 -0.6827 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -13.0764 -2.9189 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.7935 2.3187 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -14.3828 2.3187 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -14.3828 -2.1657 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 1 3 2 0 0 0 0 + 1 4 1 0 0 0 0 + 1 5 1 0 0 0 0 + 5 6 2 0 0 0 0 + 5 7 1 0 0 0 0 + 6 8 1 0 0 0 0 + 7 9 2 0 0 0 0 + 8 10 1 0 0 0 0 + 8 11 2 0 0 0 0 + 10 12 2 0 0 0 0 + 11 13 1 0 0 0 0 + 12 14 1 0 0 0 0 + 14 15 2 0 0 0 0 + 14 16 1 0 0 0 0 + 15 17 1 0 0 0 0 + 16 18 2 0 0 0 0 + 16 19 1 0 0 0 0 + 17 20 1 0 0 0 0 + 18 21 1 0 0 0 0 + 19 22 2 0 0 0 0 + 20 23 2 0 0 0 0 + 20 24 1 0 0 0 0 + 21 25 2 0 0 0 0 + 23 26 1 0 0 0 0 + 23 27 1 0 0 0 0 + 24 28 2 0 0 0 0 + 26 29 2 0 0 0 0 + 26 30 1 0 0 0 0 + 27 31 2 0 0 0 0 + 9 11 1 0 0 0 0 + 22 25 1 0 0 0 0 + 28 31 1 0 0 0 0 +M END +> +Compound 20751 + +> +BIO-700 + +> +ZINCON + +> +Products for Life Science + +> +62625-22-3 + +> + + +> +' + +> +MFCD00007507 + +$$$$ \ No newline at end of file diff --git a/INCHI-1-TEST/tests/test_unit/fixtures/test_mols_2.sdf b/INCHI-1-TEST/tests/test_unit/fixtures/test_mols_2.sdf new file mode 100644 index 00000000..4e335bd9 --- /dev/null +++ b/INCHI-1-TEST/tests/test_unit/fixtures/test_mols_2.sdf @@ -0,0 +1,320 @@ +Compound 20652 +Actelion Java MolfileCreator 1.0 + +101110 0 0 0 0 0 0 0 0999 V2000 + 0.0000 -0.0000 -0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0153 1.5192 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2737 2.2865 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3351 2.2865 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.9029 0.4297 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2277 3.8057 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3504 3.8057 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8875 -1.0589 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0614 4.5730 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.3147 3.4528 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1766 -1.7955 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5678 -1.7955 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.8518 4.8799 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -4.6344 2.7162 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4656 -1.0282 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1612 -3.2840 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5524 -3.2840 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.9541 3.4835 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -4.6498 1.2277 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4503 0.4911 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4503 -4.0206 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8415 -4.0206 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7673 -4.0206 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.2739 2.7469 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.9695 0.4911 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.3607 0.4911 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1305 1.2583 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7393 1.2583 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4349 -5.5091 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.0870 -3.2533 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7826 -5.5091 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.2892 1.2583 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -8.5936 3.5142 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.3761 -0.9975 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1152 2.7776 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.0283 0.5218 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7240 2.7776 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7240 -6.2457 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1152 -6.2457 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1024 -1.7341 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1024 -6.2457 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5064 -6.2457 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -8.6090 5.0334 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -9.9133 2.7776 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.6958 -1.7341 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4042 3.5449 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8568 3.5449 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.3174 1.2890 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.0130 3.5449 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 7.0130 -5.4784 -0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7086 -7.7342 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2686 -7.6422 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8133 -0.9668 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.4911 -7.7342 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -9.9287 5.8007 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.2331 3.5449 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.7111 -3.2226 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.3889 5.0641 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7955 5.0641 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 9.6064 0.5524 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 8.3020 2.8083 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.3889 -8.4708 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7801 -8.4708 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8287 -8.4708 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -11.2484 5.0641 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -12.5528 2.8083 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4221 -3.9592 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -6.0309 -3.9592 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 10.8955 1.3197 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 9.5911 3.5756 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.3735 -9.9594 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.7315 -7.8724 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8415 -9.7292 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -1.0282 -10.0054 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1484 -7.7036 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 10.8801 2.8390 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 12.1845 0.5831 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 10.3277 4.8953 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 8.8238 4.8953 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.6626 -10.6960 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0538 -10.6960 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1484 -10.6960 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4681 -8.4402 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 12.1692 3.6062 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0385 -12.1845 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1637 -12.1845 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4681 -9.9287 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.3275 -12.9211 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7187 -12.9211 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4835 -12.9211 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8747 -12.9211 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.7879 -10.6653 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.3990 -12.1538 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.8032 -12.1538 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4988 -14.4096 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8901 -14.4096 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.3836 -10.6346 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.2098 -15.1462 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5806 -10.1282 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.5831 -9.7906 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -2.2251 -16.6348 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 2 3 2 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 3 6 1 0 0 0 0 + 4 7 2 0 0 0 0 + 5 8 1 0 0 0 0 + 6 9 2 0 0 0 0 + 7 10 1 0 0 0 0 + 8 11 2 0 0 0 0 + 8 12 1 0 0 0 0 + 10 13 1 6 0 0 0 + 10 14 1 0 0 0 0 + 11 15 1 0 0 0 0 + 11 16 1 0 0 0 0 + 12 17 2 0 0 0 0 + 14 18 1 6 0 0 0 + 14 19 1 0 0 0 0 + 20 15 1 6 0 0 0 + 16 21 1 0 0 0 0 + 16 22 2 0 0 0 0 + 17 23 1 0 0 0 0 + 18 24 1 0 0 0 0 + 19 25 2 0 0 0 0 + 19 26 1 0 0 0 0 + 20 27 1 0 0 0 0 + 20 28 1 0 0 0 0 + 21 29 1 0 0 0 0 + 23 30 1 6 0 0 0 + 23 31 1 0 0 0 0 + 24 32 2 0 0 0 0 + 24 33 1 0 0 0 0 + 26 34 1 0 0 0 0 + 27 35 1 0 0 0 0 + 28 36 1 1 0 0 0 + 28 37 1 0 0 0 0 + 29 38 2 0 0 0 0 + 29 39 1 0 0 0 0 + 30 40 1 0 0 0 0 + 31 41 2 0 0 0 0 + 31 42 1 0 0 0 0 + 33 43 1 1 0 0 0 + 33 44 1 0 0 0 0 + 34 45 1 6 0 0 0 + 35 46 1 0 0 0 0 + 35 47 1 0 0 0 0 + 48 36 1 1 0 0 0 + 37 49 1 6 0 0 0 + 38 50 1 0 0 0 0 + 38 51 1 0 0 0 0 + 39 52 2 0 0 0 0 + 40 53 2 0 0 0 0 + 54 42 1 1 0 0 0 + 43 55 1 0 0 0 0 + 44 56 1 0 0 0 0 + 45 57 1 0 0 0 0 + 46 58 1 1 0 0 0 + 47 59 1 0 0 0 0 + 48 60 1 0 0 0 0 + 48 61 1 0 0 0 0 + 51 62 2 0 0 0 0 + 54 63 1 0 0 0 0 + 54 64 1 0 0 0 0 + 56 65 1 0 0 0 0 + 56 66 1 0 0 0 0 + 57 67 2 0 0 0 0 + 57 68 1 0 0 0 0 + 60 69 1 0 0 0 0 + 61 70 1 0 0 0 0 + 62 71 1 0 0 0 0 + 63 72 2 0 0 0 0 + 63 73 1 0 0 0 0 + 64 74 2 0 0 0 0 + 64 75 1 0 0 0 0 + 69 76 1 0 0 0 0 + 69 77 1 6 0 0 0 + 70 78 1 6 0 0 0 + 70 79 1 0 0 0 0 + 71 80 1 1 0 0 0 + 71 81 1 0 0 0 0 + 74 82 1 0 0 0 0 + 75 83 2 0 0 0 0 + 76 84 1 6 0 0 0 + 81 85 1 0 0 0 0 + 82 86 1 0 0 0 0 + 82 87 2 0 0 0 0 + 85 88 2 0 0 0 0 + 85 89 1 0 0 0 0 + 86 90 2 0 0 0 0 + 86 91 1 0 0 0 0 + 87 92 1 0 0 0 0 + 89 93 1 0 0 0 0 + 90 94 1 0 0 0 0 + 90 95 1 0 0 0 0 + 91 96 2 0 0 0 0 + 93 97 1 1 0 0 0 + 95 98 2 0 0 0 0 + 97 99 2 0 0 0 0 + 97100 1 0 0 0 0 + 98101 1 0 0 0 0 + 7 9 1 0 0 0 0 + 17 22 1 0 0 0 0 + 34 40 1 0 0 0 0 + 37 46 1 0 0 0 0 + 52 62 1 0 0 0 0 + 70 76 1 0 0 0 0 + 81 73 1 1 0 0 0 + 83 87 1 0 0 0 0 + 91 93 1 0 0 0 0 + 96 98 1 0 0 0 0 +M END +> +Compound 20652 + +> +BIO-423 + +> +VANCOMYCIN HYDROCHLORIDE + +> +Products for Life Science + +> +1404-93-9 + +> +1485.7 + +> +'93.5% (Vanomycin base) + +> +MFCD03613611 + +$$$$ +caffeine +APtclcactv08142501153D 0 0.00000 0.00000 + + 24 25 0 0 0 0 0 0 0 0999 V2000 + 1.3120 -1.0479 0.0025 N 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2465 -2.1762 0.0031 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7906 0.2081 0.0010 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.9938 0.3838 0.0002 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.9714 1.2767 -0.0001 N 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5339 2.6294 -0.0017 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.4026 1.0989 -0.0001 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.4446 1.9342 -0.0010 N 0 0 0 0 0 0 0 0 0 0 0 0 + -2.5608 1.2510 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.2862 -0.0680 0.0015 N 0 0 0 0 0 0 0 0 0 0 0 0 + -3.2614 -1.1612 0.0029 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.9114 -0.1939 0.0014 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0163 -1.2853 -0.0022 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.4380 -2.4279 -0.0068 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2697 -1.8004 0.0022 H 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0830 -2.7828 0.8938 H 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0821 -2.7846 -0.8862 H 0 0 0 0 0 0 0 0 0 0 0 0 + 2.6223 2.5703 -0.0019 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1.1987 3.1611 -0.8923 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1.1990 3.1632 0.8877 H 0 0 0 0 0 0 0 0 0 0 0 0 + -3.5520 1.6797 -0.0001 H 0 0 0 0 0 0 0 0 0 0 0 0 + -3.5037 -1.4333 -1.0244 H 0 0 0 0 0 0 0 0 0 0 0 0 + -2.8389 -2.0244 0.5173 H 0 0 0 0 0 0 0 0 0 0 0 0 + -4.1672 -0.8395 0.5168 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 3 4 2 0 0 0 0 + 3 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 5 7 1 0 0 0 0 + 7 8 1 0 0 0 0 + 8 9 2 0 0 0 0 + 9 10 1 0 0 0 0 + 10 11 1 0 0 0 0 + 10 12 1 0 0 0 0 + 7 12 2 0 0 0 0 + 12 13 1 0 0 0 0 + 1 13 1 0 0 0 0 + 13 14 2 0 0 0 0 + 2 15 1 0 0 0 0 + 2 16 1 0 0 0 0 + 2 17 1 0 0 0 0 + 6 18 1 0 0 0 0 + 6 19 1 0 0 0 0 + 6 20 1 0 0 0 0 + 9 21 1 0 0 0 0 + 11 22 1 0 0 0 0 + 11 23 1 0 0 0 0 + 11 24 1 0 0 0 0 +M END +> +caffeine + +> +XXXX + +> +CAFFEINE + +> +something something + +> + + +> + + +> +' + +> +??? + +$$$$ \ No newline at end of file diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index 912eed02..abf7ec25 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -1,12 +1,212 @@ #include #include +#include +#include +#include +#include extern "C" { +#include "../../../INCHI-1-SRC/INCHI_BASE/src/ichitime.h" #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichi_io.h" #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichimain.h" } +static char* make_arg(const char* s) { + size_t len = strlen(s) + 1; + char* p = (char*)malloc(len); + memcpy(p, s, len); + return p; +} + +// TEST(ichimain_testing, test_ProcessSingleInputFile) +// { + + +// const char *test_file_2mols = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/test_mol2.sdf"; + +// char tmpl[] = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; +// char *tmpd = mkdtemp(tmpl); +// ASSERT_NE(tmpd, nullptr); + +// std::string dst_path = std::string(tmpd) + "/caffeine.mol"; +// std::ifstream src(test_file_caffeine, std::ios::binary); +// ASSERT_TRUE(src.is_open()); +// std::ofstream dst(dst_path, std::ios::binary); +// ASSERT_TRUE(dst.is_open()); +// dst << src.rdbuf(); +// src.close(); +// dst.close(); + +// int argc = 2; +// char *a0 = make_arg("test_ichimain"); +// char *a1 = make_arg(dst_path.c_str()); +// char* argv[] = { a0, a1 }; + + + +// } + +TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) +{ + + const char *filename_caffeine = "caffeine.mol"; + + const char *path_fixtures = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures"; + char tmpl[] = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; + char *tmpd = mkdtemp(tmpl); + ASSERT_NE(tmpd, nullptr); + + std::string src_path = std::string(path_fixtures) + "/" + filename_caffeine; + std::string dst_path = std::string(tmpd) + "/" + filename_caffeine; + std::ifstream src(src_path, std::ios::binary); + ASSERT_TRUE(src.is_open()); + std::ofstream dst(dst_path, std::ios::binary); + ASSERT_TRUE(dst.is_open()); + dst << src.rdbuf(); + src.close(); + dst.close(); + + int argc = 2; + char *a0 = make_arg("test_ichimain"); + char *a1 = make_arg(dst_path.c_str()); + char* argv[] = { a0, a1 }; + + // int ProcessSingleInputFile(int argc, char* argv[]) + + int result = ProcessSingleInputFile(argc, argv); + + // Assert the expected result + EXPECT_EQ(result, 0); + + free(a0); + free(a1); + + std::string out_txt = dst_path + ".txt"; + std::string out_log = dst_path + ".log"; + std::string out_prb = dst_path + ".prb"; + + struct stat st; + // check existence and non-zero size + ASSERT_EQ(stat(out_txt.c_str(), &st), 0); + EXPECT_GT(st.st_size, 0); + ASSERT_EQ(stat(out_log.c_str(), &st), 0); + EXPECT_GT(st.st_size, 0); + ASSERT_EQ(stat(out_prb.c_str(), &st), 0); + // EXPECT_GT(st.st_size, 0); + EXPECT_EQ(st.st_size, 0); + + std::ifstream txt_in(out_txt); + ASSERT_TRUE(txt_in.is_open()); + std::string line; + std::string found_inchi; + while (std::getline(txt_in, line)) { + // trim leading/trailing whitespace + size_t start = line.find_first_not_of(" \t\r\n"); + if (start == std::string::npos) continue; + size_t end = line.find_last_not_of(" \t\r\n"); + std::string trimmed = line.substr(start, end - start + 1); + if (trimmed.rfind("InChI=", 0) == 0) { + found_inchi = trimmed; + break; + } + } + txt_in.close(); + + const std::string expected_inchi = "InChI=1S/C8H10N4O2/c1-10-4-9-6-5(10)7(13)12(3)8(14)11(6)2/h4H,1-3H3"; + ASSERT_FALSE(found_inchi.empty()); + EXPECT_EQ(found_inchi, expected_inchi); + + // cleanup + unlink(out_txt.c_str()); + unlink(out_log.c_str()); + unlink(out_prb.c_str()); + unlink(dst_path.c_str()); + rmdir(tmpd); +} +TEST(ichimain_testing, test_ProcessSingleInputFile_2mols_sdf) +{ + + const char *filename_2mols = "test_mols_2.sdf"; + + const char *path_fixtures = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures"; + char tmpl[] = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; + char *tmpd = mkdtemp(tmpl); + ASSERT_NE(tmpd, nullptr); + + std::string src_path = std::string(path_fixtures) + "/" + filename_2mols; + std::string dst_path = std::string(tmpd) + "/" + filename_2mols; + std::ifstream src(src_path, std::ios::binary); + ASSERT_TRUE(src.is_open()); + std::ofstream dst(dst_path, std::ios::binary); + ASSERT_TRUE(dst.is_open()); + dst << src.rdbuf(); + src.close(); + dst.close(); + + int argc = 2; + char *a0 = make_arg("test_ichimain"); + char *a1 = make_arg(dst_path.c_str()); + char* argv[] = { a0, a1 }; + + // int ProcessSingleInputFile(int argc, char* argv[]) + + int result = ProcessSingleInputFile(argc, argv); + + // Assert the expected result + EXPECT_EQ(result, 0); + + free(a0); + free(a1); + + std::string out_txt = dst_path + ".txt"; + std::string out_log = dst_path + ".log"; + std::string out_prb = dst_path + ".prb"; + + struct stat st; + // check existence and non-zero size + ASSERT_EQ(stat(out_txt.c_str(), &st), 0); + EXPECT_GT(st.st_size, 0); + ASSERT_EQ(stat(out_log.c_str(), &st), 0); + EXPECT_GT(st.st_size, 0); + ASSERT_EQ(stat(out_prb.c_str(), &st), 0); + // EXPECT_GT(st.st_size, 0); + EXPECT_EQ(st.st_size, 0); + + std::ifstream txt_in(out_txt); + ASSERT_TRUE(txt_in.is_open()); + std::string line; + std::vector found_inchis; + while (std::getline(txt_in, line)) { + // trim leading/trailing whitespace + size_t start = line.find_first_not_of(" \t\r\n"); + if (start == std::string::npos) continue; + size_t end = line.find_last_not_of(" \t\r\n"); + std::string trimmed = line.substr(start, end - start + 1); + if (trimmed.rfind("InChI=", 0) == 0) { + found_inchis.push_back(trimmed); + } + } + txt_in.close(); + + std::vector expected_inchis = { + "InChI=1S/C66H75Cl2N9O24/c1-23(2)12-34(71-5)58(88)76-49-51(83)26-7-10-38(32(67)14-26)97-40-16-28-17-41(55(40)101-65-56(54(86)53(85)42(22-78)99-65)100-44-21-66(4,70)57(87)24(3)96-44)98-39-11-8-27(15-33(39)68)52(84)50-63(93)75-48(64(94)95)31-18-29(79)19-37(81)45(31)30-13-25(6-9-36(30)80)46(60(90)77-50)74-61(91)47(28)73-59(89)35(20-43(69)82)72-62(49)92/h6-11,13-19,23-24,34-35,42,44,46-54,56-57,65,71,78-81,83-87H,12,20-22,70H2,1-5H3,(H2,69,82)(H,72,92)(H,73,89)(H,74,91)(H,75,93)(H,76,88)(H,77,90)(H,94,95)/t24-,34+,35-,42?,44-,46+,47+,48-,49+,50-,51+,52+,53+,54-,56+,57+,65-,66-/m0/s1", + "InChI=1S/C8H10N4O2/c1-10-4-9-6-5(10)7(13)12(3)8(14)11(6)2/h4H,1-3H3" + }; + + ASSERT_EQ(found_inchis.size(), expected_inchis.size()); + for (size_t i = 0; i < expected_inchis.size(); ++i) { + EXPECT_EQ(found_inchis[i], expected_inchis[i]); + } + + // cleanup + unlink(out_txt.c_str()); + unlink(out_log.c_str()); + unlink(out_prb.c_str()); + unlink(dst_path.c_str()); + rmdir(tmpd); +} + TEST(ichimain_testing, test_GetTheNextRecordOfInputFile) { @@ -86,24 +286,41 @@ TEST(ichimain_testing, test_GetTheNextRecordOfInputFile) // long *num_err, // int output_error_inchi ); - tagINCHI_CLOCK *ic; - STRUCT_DATA *sd; - INPUT_PARMS *ip; + INCHI_CLOCK ic = {}; + memset(&ic, 0, sizeof(ic)); + + STRUCT_DATA *sd = new STRUCT_DATA; + INPUT_PARMS *ip = new INPUT_PARMS; + char *szTitle; INCHI_IOSTREAM *inp_file; - INCHI_IOSTREAM *plog; - INCHI_IOSTREAM *pout; - INCHI_IOSTREAM *pprb; + INCHI_IOSTREAM *plog = new INCHI_IOSTREAM; + INCHI_IOSTREAM *pout = new INCHI_IOSTREAM; + INCHI_IOSTREAM *pprb = new INCHI_IOSTREAM; ORIG_ATOM_DATA orig_at_data = {}; - long *num_inp; - STRUCT_FPTRS *pStructPtrs; - int *nRet; - int *have_err_in_GetOneStructure; + long *num_inp = new long(0); + + STRUCT_FPTRS *pStructPtrs = NULL; + + int *nRet = 0; + int *have_err_in_GetOneStructure = 0; long *num_err; int output_error_inchi; + + memset(ip, 0, sizeof(*ip)); + ip->last_struct_number = 1; + ip->nInputType = INPUT_MOLFILE; + + inchi_ios_init(pout, INCHI_IOS_TYPE_STRING, nullptr); + inchi_ios_init(plog, INCHI_IOS_TYPE_STRING, stdout); + inchi_ios_init(pprb, INCHI_IOS_TYPE_STRING, nullptr); + + // PrintInputParms(plog, ip); + // inchi_ios_flush2(plog, stderr); + // int ret = GetTheNextRecordOfInputFile( - // ic, + // &ic, // sd, // ip, // szTitle, @@ -119,7 +336,7 @@ TEST(ichimain_testing, test_GetTheNextRecordOfInputFile) // num_err, // output_error_inchi); - // EXPECT_EQ(ret, 18); + // EXPECT_EQ(ret, DO_NEXT_STEP); inchi_ios_free_str(&input_stream); FreeOrigAtData(&orig_at_data); From 4948da70f96996b836c8aa2d841973f9d17304ea Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 8 Dec 2025 15:10:53 +0000 Subject: [PATCH 22/69] Added prototype for ProcessMultipleInputFiles --- .../tests/test_unit/fixtures/naloxon.mol | 99 +++++++++++++++++++ .../tests/test_unit/test_ichimain.cpp | 26 +---- _deps/googletest-src | 1 + 3 files changed, 105 insertions(+), 21 deletions(-) create mode 100644 INCHI-1-TEST/tests/test_unit/fixtures/naloxon.mol create mode 160000 _deps/googletest-src diff --git a/INCHI-1-TEST/tests/test_unit/fixtures/naloxon.mol b/INCHI-1-TEST/tests/test_unit/fixtures/naloxon.mol new file mode 100644 index 00000000..6768159d --- /dev/null +++ b/INCHI-1-TEST/tests/test_unit/fixtures/naloxon.mol @@ -0,0 +1,99 @@ +naloxon + -OEChem-12082509532D + + 45 49 0 1 0 0 0 0 0999 V2000 + 2.2314 -0.2572 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.3794 -1.7611 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0000 -2.7122 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0000 2.0922 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1607 -1.2611 0.0000 N 0 0 3 0 0 0 0 0 0 0 0 0 + 3.6897 -0.7855 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 + 4.5133 -1.2611 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 + 5.3370 -0.7855 0.0000 C 0 0 3 0 0 0 0 0 0 0 0 0 + 2.8660 -1.2611 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 + 4.2392 -0.0881 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.6897 0.1655 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.5133 -2.2122 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.3370 0.1655 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5918 -0.0881 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.5133 0.6411 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.6897 -2.6877 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.8660 -2.2122 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.8660 0.6411 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.8418 -1.9932 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.5133 1.5922 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.8660 1.5922 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.6897 2.0677 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.8164 -1.7694 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.4976 -2.5015 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.8739 -0.4755 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0496 -1.4975 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 4.3760 0.5166 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 3.6795 0.1787 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 4.7254 -2.7948 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1239 -2.1045 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 5.9476 0.0579 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5490 0.7481 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1840 0.0957 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 5.4989 0.5249 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2912 -3.1626 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 4.0882 -3.1626 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 5.3794 -2.3811 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 6.3215 -2.3303 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 7.0834 -2.5642 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0503 1.9022 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 3.6897 2.6877 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 7.9984 -1.1766 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0000 2.7122 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 8.3157 -3.0942 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 9.1019 -2.3627 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1 9 1 0 0 0 0 + 1 18 1 0 0 0 0 + 7 2 1 1 0 0 0 + 2 37 1 0 0 0 0 + 3 17 2 0 0 0 0 + 4 21 1 0 0 0 0 + 4 43 1 0 0 0 0 + 5 8 1 0 0 0 0 + 5 14 1 0 0 0 0 + 5 19 1 0 0 0 0 + 6 7 1 0 0 0 0 + 6 9 1 0 0 0 0 + 6 10 1 1 0 0 0 + 6 11 1 0 0 0 0 + 7 8 1 0 0 0 0 + 7 12 1 0 0 0 0 + 8 13 1 0 0 0 0 + 8 25 1 0 0 0 0 + 9 17 1 0 0 0 0 + 9 26 1 1 0 0 0 + 10 14 1 0 0 0 0 + 10 27 1 0 0 0 0 + 10 28 1 0 0 0 0 + 11 15 2 0 0 0 0 + 11 18 1 0 0 0 0 + 12 16 1 0 0 0 0 + 12 29 1 0 0 0 0 + 12 30 1 0 0 0 0 + 13 15 1 0 0 0 0 + 13 31 1 0 0 0 0 + 13 32 1 0 0 0 0 + 14 33 1 0 0 0 0 + 14 34 1 0 0 0 0 + 15 20 1 0 0 0 0 + 16 17 1 0 0 0 0 + 16 35 1 0 0 0 0 + 16 36 1 0 0 0 0 + 18 21 2 0 0 0 0 + 19 23 1 0 0 0 0 + 19 38 1 0 0 0 0 + 19 39 1 0 0 0 0 + 20 22 2 0 0 0 0 + 20 40 1 0 0 0 0 + 21 22 1 0 0 0 0 + 22 41 1 0 0 0 0 + 23 24 2 0 0 0 0 + 23 42 1 0 0 0 0 + 24 44 1 0 0 0 0 + 24 45 1 0 0 0 0 +M END \ No newline at end of file diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index abf7ec25..8295f68f 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -19,33 +19,17 @@ static char* make_arg(const char* s) { return p; } -// TEST(ichimain_testing, test_ProcessSingleInputFile) -// { - - -// const char *test_file_2mols = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/test_mol2.sdf"; +TEST(ichimain_testing, test_ProcessMultipleInputFiles) +{ -// char tmpl[] = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; -// char *tmpd = mkdtemp(tmpl); -// ASSERT_NE(tmpd, nullptr); + const char *test_file_mol1 = "caffeine.mol"; + const char *test_file_mol2 = "naloxon.mol"; -// std::string dst_path = std::string(tmpd) + "/caffeine.mol"; -// std::ifstream src(test_file_caffeine, std::ios::binary); -// ASSERT_TRUE(src.is_open()); -// std::ofstream dst(dst_path, std::ios::binary); -// ASSERT_TRUE(dst.is_open()); -// dst << src.rdbuf(); -// src.close(); -// dst.close(); -// int argc = 2; -// char *a0 = make_arg("test_ichimain"); -// char *a1 = make_arg(dst_path.c_str()); -// char* argv[] = { a0, a1 }; -// } +} TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) { diff --git a/_deps/googletest-src b/_deps/googletest-src new file mode 160000 index 00000000..52eb8108 --- /dev/null +++ b/_deps/googletest-src @@ -0,0 +1 @@ +Subproject commit 52eb8108c5bdec04579160ae17225d66034bd723 From 7b93ffbc9294ef8ba92bed41eb92aa461ab59249 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Tue, 9 Dec 2025 10:54:52 +0000 Subject: [PATCH 23/69] added missing free --- INCHI-1-SRC/INCHI_BASE/src/ichimake.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichimake.c b/INCHI-1-SRC/INCHI_BASE/src/ichimake.c index 80652e13..e478e55b 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichimake.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichimake.c @@ -4550,6 +4550,10 @@ int Create_INChI(CANON_GLOBALS* pCG, { inchi_free(t_group_info->nIsotopicEndpointAtomNumber); } + if (t_group_info->t_group) + { + inchi_free(t_group_info->t_group); + } memset(t_group_info, 0, sizeof(*t_group_info)); /* djb-rwth: memset_s C11/Annex K variant? */ } } From 640a53b2db45f0372f8d171af434cd5201d53949 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Tue, 9 Dec 2025 13:27:51 +0000 Subject: [PATCH 24/69] Added unit tests for CalcAndPrintINCHIAndINCHIKEY, ProcessMultipleInputFiles --- CMakeLists.txt | 4 +- .../tests/test_unit/test_ichimain.cpp | 458 +++++++++++++++--- .../tests/test_unit/test_permutation_util.cpp | 7 + 3 files changed, 403 insertions(+), 66 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b324705..737bfafd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,8 +6,8 @@ set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 11) set(CMAKE_POSITION_INDEPENDENT_CODE ON) -# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") -# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") include(FetchContent) FetchContent_Declare( diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index 8295f68f..83fea5e3 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -8,6 +8,7 @@ extern "C" { #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichitime.h" +#include "../../../INCHI-1-SRC/INCHI_BASE/src/ichicant.h" #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichi_io.h" #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichimain.h" } @@ -19,16 +20,344 @@ static char* make_arg(const char* s) { return p; } -TEST(ichimain_testing, test_ProcessMultipleInputFiles) +char *read_inchi_from_file(const char *filename) { + + std::ifstream txt_in(filename); + txt_in.is_open(); + std::string line; + std::string found_inchi; + while (std::getline(txt_in, line)) { + // trim leading/trailing whitespace + size_t start = line.find_first_not_of(" \t\r\n"); + if (start == std::string::npos) continue; + size_t end = line.find_last_not_of(" \t\r\n"); + std::string trimmed = line.substr(start, end - start + 1); + if (trimmed.rfind("InChI=", 0) == 0) { + found_inchi = trimmed; + break; + } + } + txt_in.close(); + + return make_arg(found_inchi.c_str()); +} + +TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { + + + INCHI_IOSTREAM input_stream; + + const char *molblock = + "enhanc_stereo1 \n" + " ACD/LABS08242216132D \n" + " \n" + " 0 0 0 0 0 0 0 0 0 0999 V3000 \n" + "M V30 BEGIN CTAB \n" + "M V30 COUNTS 18 17 0 0 1 \n" + "M V30 BEGIN ATOM \n" + "M V30 1 C 3424.1946 -1936.7935 0 0 \n" + "M V30 2 C 3352.3145 -1895.2935 0 0 \n" + "M V30 3 C 3280.4346 -1936.7935 0 0 \n" + "M V30 4 C 3208.5542 -1895.2935 0 0 \n" + "M V30 5 C 3136.6743 -1936.7935 0 0 \n" + "M V30 6 C 3064.7944 -1895.2935 0 0 \n" + "M V30 7 Br 3136.6743 -2019.7935 0 0 \n" + "M V30 8 Cl 3208.5542 -1812.2935 0 0 \n" + "M V30 9 Cl 3280.4346 -2019.7935 0 0 \n" + "M V30 10 Cl 3352.3145 -1812.2935 0 0 \n" + "M V30 11 Cl 3424.1946 -2019.7935 0 0 \n" + "M V30 12 C 3496.075 -1895.2935 0 0 \n" + "M V30 13 C 3567.9548 -1936.7942 0 0 \n" + "M V30 14 C 3639.835 -1895.2944 0 0 \n" + "M V30 15 C 3711.7148 -1936.7942 0 0 \n" + "M V30 16 Cl 3639.835 -1812.2944 0 0 \n" + "M V30 17 Cl 3567.9548 -2019.7942 0 0 \n" + "M V30 18 Cl 3496.075 -1812.2937 0 0 \n" + "M V30 END ATOM \n" + "M V30 BEGIN BOND \n" + "M V30 1 1 1 2 \n" + "M V30 2 1 1 11 CFG=3 \n" + "M V30 3 1 1 12 \n" + "M V30 4 1 2 3 \n" + "M V30 5 1 2 10 CFG=1 \n" + "M V30 6 1 3 4 \n" + "M V30 7 1 3 9 CFG=1 \n" + "M V30 8 1 4 5 \n" + "M V30 9 1 4 8 CFG=1 \n" + "M V30 10 1 5 6 \n" + "M V30 11 1 5 7 CFG=1 \n" + "M V30 12 1 12 13 \n" + "M V30 13 1 12 18 CFG=3 \n" + "M V30 14 1 13 14 \n" + "M V30 15 1 13 17 CFG=1 \n" + "M V30 16 1 14 15 \n" + "M V30 17 1 14 16 CFG=1 \n" + "M V30 END BOND \n" + "M V30 BEGIN COLLECTION \n" + "M V30 MDLV30/STERAC2 ATOMS=(1 1) \n" + "M V30 MDLV30/STERAC1 ATOMS=(2 2 3) \n" + "M V30 MDLV30/STEABS ATOMS=(2 4 5) \n" + "M V30 MDLV30/STEREL1 ATOMS=(2 12 13) \n" + "M V30 MDLV30/STEREL2 ATOMS=(1 14) \n" + "M V30 END COLLECTION \n" + "M V30 END CTAB \n" + "M END \n"; + + inchi_ios_init(&input_stream, INCHI_IOS_TYPE_STRING, nullptr); + inchi_ios_print_nodisplay(&input_stream, molblock); + + // int GetTheNextRecordOfInputFile( struct tagINCHI_CLOCK *ic, + // STRUCT_DATA *sd, INPUT_PARMS *ip, + // char *szTitle, + // INCHI_IOSTREAM *inp_file, + // INCHI_IOSTREAM *plog, + // INCHI_IOSTREAM *pout, + // INCHI_IOSTREAM *pprb, + // ORIG_ATOM_DATA *orig_inp_data, + // long *num_inp, + // STRUCT_FPTRS *pStructPtrs, + // int *nRet, + // int *have_err_in_GetOneStructure, + // long *num_err, + // int output_error_inchi ); + + INCHI_CLOCK ic = {}; + memset(&ic, 0, sizeof(ic)); + + STRUCT_DATA *sd = new STRUCT_DATA; + // sd->ulStructTime = 0; + INPUT_PARMS *ip = new INPUT_PARMS; + + char *szTitle; + INCHI_IOSTREAM *inp_file; + INCHI_IOSTREAM *plog = new INCHI_IOSTREAM; + INCHI_IOSTREAM *pout = new INCHI_IOSTREAM; + INCHI_IOSTREAM *pprb = new INCHI_IOSTREAM; + ORIG_ATOM_DATA orig_at_data = {}; + long *num_inp = new long(0); + + STRUCT_FPTRS *pStructPtrs = nullptr; + + int nRet = 0; + int have_err_in_GetOneStructure = 0; + long num_err = 0; + int output_error_inchi; + + + memset(ip, 0, sizeof(*ip)); + ip->last_struct_number = 1; + ip->nInputType = INPUT_MOLFILE; + + inchi_ios_init(pout, INCHI_IOS_TYPE_STRING, nullptr); + inchi_ios_init(plog, INCHI_IOS_TYPE_STRING, stdout); + inchi_ios_init(pprb, INCHI_IOS_TYPE_STRING, nullptr); + + // PrintInputParms(plog, ip); + inchi_ios_flush2(plog, stderr); + + int ret = GetTheNextRecordOfInputFile( + &ic, + sd, + ip, + szTitle, + &input_stream, + plog, + pout, + pprb, + &orig_at_data, + num_inp, + pStructPtrs, + &nRet, + &have_err_in_GetOneStructure, + &num_err, + output_error_inchi); + + EXPECT_EQ(ret, DO_NEXT_STEP); + + CANON_GLOBALS CG = {}; + // STRUCT_DATA* sd; + // INPUT_PARMS* ip; + // char* szTitle; + PINChI2* pINChI[INCHI_NUM]; + PINChI_Aux2* pINChI_Aux[INCHI_NUM]; + // INCHI_IOSTREAM* inp_file; + // INCHI_IOSTREAM* plog; + // INCHI_IOSTREAM* pout; + // INCHI_IOSTREAM* pprb; + // ORIG_ATOM_DATA* orig_inp_data; + ORIG_ATOM_DATA prep_inp_data = {}; + // long* num_inp; + // STRUCT_FPTRS* pStructPtrs; + // int* nRet; + // int have_err_in_GetOneStructure; + // long* num_err; + // int output_error_inchi; + INCHI_IOS_STRING* strbuf; + unsigned long pulTotalProcessingTime = 0; + char* pLF; + char* pTAB; + char* ikey; + int silent; + + set_line_separators(ip->bINChIOutputOptions, &pLF, &pTAB); + + ret = CalcAndPrintINCHIAndINCHIKEY( + &ic, + &CG, + sd, + ip, + szTitle, + pINChI, + pINChI_Aux, + &input_stream, + plog, + pout, + pprb, + &orig_at_data, + &prep_inp_data, + num_inp, + pStructPtrs, + &nRet, + have_err_in_GetOneStructure, + &num_err, + output_error_inchi, + strbuf, + &pulTotalProcessingTime, + pLF, + pTAB, + ikey, + silent + ); + + + + + inchi_ios_free_str(&input_stream); + FreeOrigAtData(&orig_at_data); + + for (int i = 0; i < MAX_NUM_PATHS; i++) + { + if (ip->path[i]) + { + inchi_free((void*)ip->path[i]); /* cast deliberately discards 'const' qualifier */ + ip->path[i] = NULL; + } + } + delete ip; + delete sd; + + delete plog; + delete pout; + delete pprb; + delete num_inp; + + + // int CalcAndPrintINCHIAndINCHIKEY(struct tagINCHI_CLOCK* ic, + // CANON_GLOBALS* CG, + // STRUCT_DATA* sd, + // INPUT_PARMS* ip, + // char* szTitle, + // PINChI2* pINChI[INCHI_NUM], + // PINChI_Aux2* pINChI_Aux[INCHI_NUM], + // INCHI_IOSTREAM* inp_file, + // INCHI_IOSTREAM* plog, + // INCHI_IOSTREAM* pout, + // INCHI_IOSTREAM* pprb, + // ORIG_ATOM_DATA* orig_inp_data, + // ORIG_ATOM_DATA* prep_inp_data, + // long* num_inp, + // STRUCT_FPTRS* pStructPtrs, + // int* nRet, + // int have_err_in_GetOneStructure, + // long* num_err, + // int output_error_inchi, + // INCHI_IOS_STRING* strbuf, + // unsigned long* pulTotalProcessingTime, + // char* pLF, + // char* pTAB, + // char* ikey, + // int silent) + +} + +TEST(ichimain_testing, test_ProcessMultipleInputFiles_2mol_files) { - const char *test_file_mol1 = "caffeine.mol"; - const char *test_file_mol2 = "naloxon.mol"; + std::vector expected_inchis = { + "InChI=1S/C19H21NO4/c1-2-8-20-9-7-18-15-11-3-4-12(21)16(15)24-17(18)13(22)5-6-19(18,23)14(20)10-11/h2-4,14,17,21,23H,1,5-10H2/t14?,17-,18-,19+/m0/s1", + "InChI=1S/C8H10N4O2/c1-10-4-9-6-5(10)7(13)12(3)8(14)11(6)2/h4H,1-3H3" + }; + std::vector input_mols = { + "naloxon.mol", + "caffeine.mol" + }; + + const char *path_fixtures = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures"; + + char tmpl[] = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; + char *tmpd = mkdtemp(tmpl); + ASSERT_NE(tmpd, nullptr); + + std::vector dist_paths; + for (auto cur_filename : input_mols) { + std::string src_path = std::string(path_fixtures) + "/" + cur_filename; + std::string dst_path = std::string(tmpd) + "/" + cur_filename; + std::ifstream src(src_path, std::ios::binary); + ASSERT_TRUE(src.is_open()); + std::ofstream dst(dst_path, std::ios::binary); + ASSERT_TRUE(dst.is_open()); + dst << src.rdbuf(); + src.close(); + dst.close(); + + dist_paths.push_back(dst_path); + } + int argc = input_mols.size() + 2; + + char *inchi_filename = make_arg("test_ichimain"); + + std::vector argv_vec; + argv_vec.push_back(inchi_filename); + for (const auto &p : dist_paths) { + argv_vec.push_back(make_arg(p.c_str())); + } + argv_vec.push_back(make_arg("-AMI")); + char** argv = argv_vec.data(); + //int ProcessMultipleInputFiles(int argc, char* argv[]) + int ret = ProcessMultipleInputFiles(argc, argv); + // Assert the expected result + ASSERT_EQ(ret, 0); + + for (int i = 0; i < expected_inchis.size(); i++) { + std::string out_txt = dist_paths[i] + ".txt"; + char *inchi = read_inchi_from_file(out_txt.c_str()); + ASSERT_STREQ(inchi, expected_inchis[i].c_str()); + free(inchi); + } + + // Clean up + + for (auto p : dist_paths) { + + std::string out_txt = p + ".txt"; + std::string out_log = p + ".log"; + std::string out_prb = p + ".prb"; + + remove(p.c_str()); + remove(out_txt.c_str()); + remove(out_log.c_str()); + remove(out_prb.c_str()); + } + rmdir(tmpd); + + for (auto p : argv_vec) { + free(p); + } } TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) @@ -52,9 +381,9 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) dst.close(); int argc = 2; - char *a0 = make_arg("test_ichimain"); - char *a1 = make_arg(dst_path.c_str()); - char* argv[] = { a0, a1 }; + char *inchi_filename = make_arg("test_ichimain"); + char *input_file = make_arg(dst_path.c_str()); + char* argv[] = { inchi_filename, input_file }; // int ProcessSingleInputFile(int argc, char* argv[]) @@ -63,8 +392,8 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) // Assert the expected result EXPECT_EQ(result, 0); - free(a0); - free(a1); + free(inchi_filename); + free(input_file); std::string out_txt = dst_path + ".txt"; std::string out_log = dst_path + ".log"; @@ -77,35 +406,20 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) ASSERT_EQ(stat(out_log.c_str(), &st), 0); EXPECT_GT(st.st_size, 0); ASSERT_EQ(stat(out_prb.c_str(), &st), 0); - // EXPECT_GT(st.st_size, 0); EXPECT_EQ(st.st_size, 0); - std::ifstream txt_in(out_txt); - ASSERT_TRUE(txt_in.is_open()); - std::string line; - std::string found_inchi; - while (std::getline(txt_in, line)) { - // trim leading/trailing whitespace - size_t start = line.find_first_not_of(" \t\r\n"); - if (start == std::string::npos) continue; - size_t end = line.find_last_not_of(" \t\r\n"); - std::string trimmed = line.substr(start, end - start + 1); - if (trimmed.rfind("InChI=", 0) == 0) { - found_inchi = trimmed; - break; - } - } - txt_in.close(); + char *found_inchi = read_inchi_from_file(out_txt.c_str()); + std::string expected_inchi = "InChI=1S/C8H10N4O2/c1-10-4-9-6-5(10)7(13)12(3)8(14)11(6)2/h4H,1-3H3"; - const std::string expected_inchi = "InChI=1S/C8H10N4O2/c1-10-4-9-6-5(10)7(13)12(3)8(14)11(6)2/h4H,1-3H3"; - ASSERT_FALSE(found_inchi.empty()); + ASSERT_NE(found_inchi, nullptr); EXPECT_EQ(found_inchi, expected_inchi); // cleanup - unlink(out_txt.c_str()); - unlink(out_log.c_str()); - unlink(out_prb.c_str()); - unlink(dst_path.c_str()); + free(found_inchi); + remove(out_txt.c_str()); + remove(out_log.c_str()); + remove(out_prb.c_str()); + remove(dst_path.c_str()); rmdir(tmpd); } TEST(ichimain_testing, test_ProcessSingleInputFile_2mols_sdf) @@ -129,9 +443,9 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_2mols_sdf) dst.close(); int argc = 2; - char *a0 = make_arg("test_ichimain"); - char *a1 = make_arg(dst_path.c_str()); - char* argv[] = { a0, a1 }; + char *inchi_filename = make_arg("test_ichimain"); + char *input_file = make_arg(dst_path.c_str()); + char* argv[] = { inchi_filename, input_file }; // int ProcessSingleInputFile(int argc, char* argv[]) @@ -140,8 +454,8 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_2mols_sdf) // Assert the expected result EXPECT_EQ(result, 0); - free(a0); - free(a1); + free(inchi_filename); + free(input_file); std::string out_txt = dst_path + ".txt"; std::string out_log = dst_path + ".log"; @@ -184,10 +498,10 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_2mols_sdf) } // cleanup - unlink(out_txt.c_str()); - unlink(out_log.c_str()); - unlink(out_prb.c_str()); - unlink(dst_path.c_str()); + remove(out_txt.c_str()); + remove(out_log.c_str()); + remove(out_prb.c_str()); + remove(dst_path.c_str()); rmdir(tmpd); } @@ -277,17 +591,17 @@ TEST(ichimain_testing, test_GetTheNextRecordOfInputFile) INPUT_PARMS *ip = new INPUT_PARMS; char *szTitle; - INCHI_IOSTREAM *inp_file; + // INCHI_IOSTREAM *inp_file; INCHI_IOSTREAM *plog = new INCHI_IOSTREAM; INCHI_IOSTREAM *pout = new INCHI_IOSTREAM; INCHI_IOSTREAM *pprb = new INCHI_IOSTREAM; ORIG_ATOM_DATA orig_at_data = {}; long *num_inp = new long(0); - STRUCT_FPTRS *pStructPtrs = NULL; + STRUCT_FPTRS *pStructPtrs = nullptr; - int *nRet = 0; - int *have_err_in_GetOneStructure = 0; + int nRet = 0; + int have_err_in_GetOneStructure = 0; long *num_err; int output_error_inchi; @@ -301,27 +615,43 @@ TEST(ichimain_testing, test_GetTheNextRecordOfInputFile) inchi_ios_init(pprb, INCHI_IOS_TYPE_STRING, nullptr); // PrintInputParms(plog, ip); - // inchi_ios_flush2(plog, stderr); - - // int ret = GetTheNextRecordOfInputFile( - // &ic, - // sd, - // ip, - // szTitle, - // &input_stream, - // plog, - // pout, - // pprb, - // &orig_at_data, - // num_inp, - // pStructPtrs, - // nRet, - // have_err_in_GetOneStructure, - // num_err, - // output_error_inchi); - - // EXPECT_EQ(ret, DO_NEXT_STEP); + inchi_ios_flush2(plog, stderr); + + int ret = GetTheNextRecordOfInputFile( + &ic, + sd, + ip, + szTitle, + &input_stream, + plog, + pout, + pprb, + &orig_at_data, + num_inp, + pStructPtrs, + &nRet, + &have_err_in_GetOneStructure, + num_err, + output_error_inchi); + + EXPECT_EQ(ret, DO_NEXT_STEP); inchi_ios_free_str(&input_stream); FreeOrigAtData(&orig_at_data); + + for (int i = 0; i < MAX_NUM_PATHS; i++) + { + if (ip->path[i]) + { + inchi_free((void*)ip->path[i]); /* cast deliberately discards 'const' qualifier */ + ip->path[i] = NULL; + } + } + delete ip; + delete sd; + + delete plog; + delete pout; + delete pprb; + delete num_inp; } diff --git a/INCHI-1-TEST/tests/test_unit/test_permutation_util.cpp b/INCHI-1-TEST/tests/test_unit/test_permutation_util.cpp index 174bf847..ad98e559 100644 --- a/INCHI-1-TEST/tests/test_unit/test_permutation_util.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_permutation_util.cpp @@ -107,4 +107,11 @@ TEST(permutation_util_testing, test_OrigAtData_Permute) EXPECT_STREQ(molblock, output_file->s.pStr); EXPECT_STRNE(output_file->s.pStr, permuted_output_file->s.pStr); + + inchi_ios_free_str(&input_stream); + inchi_ios_free_str(&output_stream); + inchi_ios_free_str(&permuted_output_stream); + + FreeOrigAtData(&atom_data); + FreeOrigAtData(&permuted_atom_data); } From 18dafe91ac919c1ff331b8a491e8b88eb1092065 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Wed, 10 Dec 2025 14:40:19 +0000 Subject: [PATCH 25/69] Added unit test flags for initializing input params --- .../tests/test_unit/test_ichimain.cpp | 92 +++++++++++++------ 1 file changed, 62 insertions(+), 30 deletions(-) diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index 83fea5e3..7b8b77f9 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -48,9 +48,9 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { INCHI_IOSTREAM input_stream; const char *molblock = - "enhanc_stereo1 \n" + "enhanc_stereo1 \n" " ACD/LABS08242216132D \n" - " \n" + " \n" " 0 0 0 0 0 0 0 0 0 0999 V3000 \n" "M V30 BEGIN CTAB \n" "M V30 COUNTS 18 17 0 0 1 \n" @@ -147,6 +147,23 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { memset(ip, 0, sizeof(*ip)); ip->last_struct_number = 1; ip->nInputType = INPUT_MOLFILE; + ip->bINChIOutputOptions = INCHI_OUT_PLAIN_TEXT; + // ip->bINChIOutputOptions2 = INCHI_OUT_PLAIN_TEXT; + // ip->nMode = REQ_MODE_TAUT; // REQ_MODE_BASIC; + // ip->bTautFlags |= (TG_FLAG_DISCONNECT_COORD | TG_FLAG_RECONNECT_COORD); + // ip->nMode |= (REQ_MODE_BASIC | REQ_MODE_TAUT | REQ_MODE_STEREO | REQ_MODE_ISO_STEREO | REQ_MODE_ISO); + + int bReleaseVersion = bRELEASE_VERSION; + unsigned long ulDisplTime = 0; /* infinite, milliseconds */ + unsigned long ulTotalProcessingTime = 0; + + int argc = 0; + char *argv[1]; + char *szSdfDataValue = nullptr; + + ReadCommandLineParms(argc, (const char**)argv, ip, + szSdfDataValue, &ulDisplTime, + bReleaseVersion, plog); inchi_ios_init(pout, INCHI_IOS_TYPE_STRING, nullptr); inchi_ios_init(plog, INCHI_IOS_TYPE_STRING, stdout); @@ -174,6 +191,9 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { EXPECT_EQ(ret, DO_NEXT_STEP); + EXPECT_EQ(orig_at_data.num_inp_atoms, 18); + EXPECT_EQ(orig_at_data.num_inp_bonds, 17); + CANON_GLOBALS CG = {}; // STRUCT_DATA* sd; // INPUT_PARMS* ip; @@ -192,7 +212,10 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { // int have_err_in_GetOneStructure; // long* num_err; // int output_error_inchi; - INCHI_IOS_STRING* strbuf; + INCHI_IOS_STRING *strbuf = new INCHI_IOS_STRING; + memset(strbuf, 0, sizeof(*strbuf)); + inchi_strbuf_init(strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + unsigned long pulTotalProcessingTime = 0; char* pLF; char* pTAB; @@ -201,6 +224,33 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { set_line_separators(ip->bINChIOutputOptions, &pLF, &pTAB); + + // int CalcAndPrintINCHIAndINCHIKEY(struct tagINCHI_CLOCK* ic, + // CANON_GLOBALS* CG, + // STRUCT_DATA* sd, + // INPUT_PARMS* ip, + // char* szTitle, + // PINChI2* pINChI[INCHI_NUM], + // PINChI_Aux2* pINChI_Aux[INCHI_NUM], + // INCHI_IOSTREAM* inp_file, + // INCHI_IOSTREAM* plog, + // INCHI_IOSTREAM* pout, + // INCHI_IOSTREAM* pprb, + // ORIG_ATOM_DATA* orig_inp_data, + // ORIG_ATOM_DATA* prep_inp_data, + // long* num_inp, + // STRUCT_FPTRS* pStructPtrs, + // int* nRet, + // int have_err_in_GetOneStructure, + // long* num_err, + // int output_error_inchi, + // INCHI_IOS_STRING* strbuf, + // unsigned long* pulTotalProcessingTime, + // char* pLF, + // char* pTAB, + // char* ikey, + // int silent) + ret = CalcAndPrintINCHIAndINCHIKEY( &ic, &CG, @@ -229,11 +279,17 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { silent ); + EXPECT_EQ(ret, DO_NEXT_STEP); + char *inchi = "InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6+,7-,8+,9+,10-/m0/s1"; + //ios->s.pStr + EXPECT_STREQ(inchi, pout->s.pStr); + FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); inchi_ios_free_str(&input_stream); FreeOrigAtData(&orig_at_data); + FreeOrigAtData(&prep_inp_data); for (int i = 0; i < MAX_NUM_PATHS; i++) { @@ -251,33 +307,6 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { delete pprb; delete num_inp; - - // int CalcAndPrintINCHIAndINCHIKEY(struct tagINCHI_CLOCK* ic, - // CANON_GLOBALS* CG, - // STRUCT_DATA* sd, - // INPUT_PARMS* ip, - // char* szTitle, - // PINChI2* pINChI[INCHI_NUM], - // PINChI_Aux2* pINChI_Aux[INCHI_NUM], - // INCHI_IOSTREAM* inp_file, - // INCHI_IOSTREAM* plog, - // INCHI_IOSTREAM* pout, - // INCHI_IOSTREAM* pprb, - // ORIG_ATOM_DATA* orig_inp_data, - // ORIG_ATOM_DATA* prep_inp_data, - // long* num_inp, - // STRUCT_FPTRS* pStructPtrs, - // int* nRet, - // int have_err_in_GetOneStructure, - // long* num_err, - // int output_error_inchi, - // INCHI_IOS_STRING* strbuf, - // unsigned long* pulTotalProcessingTime, - // char* pLF, - // char* pTAB, - // char* ikey, - // int silent) - } TEST(ichimain_testing, test_ProcessMultipleInputFiles_2mol_files) @@ -636,6 +665,9 @@ TEST(ichimain_testing, test_GetTheNextRecordOfInputFile) EXPECT_EQ(ret, DO_NEXT_STEP); + EXPECT_EQ(orig_at_data.num_inp_atoms, 18); + EXPECT_EQ(orig_at_data.num_inp_bonds, 17); + inchi_ios_free_str(&input_stream); FreeOrigAtData(&orig_at_data); From 80ba6a5b4e0f54488c1f297d3566cdfbb27337ad Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 15 Dec 2025 10:56:17 +0000 Subject: [PATCH 26/69] Added unit test for CalcAndPrintInchi... --- .../tests/test_unit/test_ichimain.cpp | 48 ++++++++++++------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index 7b8b77f9..f06648b1 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -34,6 +34,15 @@ char *read_inchi_from_file(const char *filename) { std::string trimmed = line.substr(start, end - start + 1); if (trimmed.rfind("InChI=", 0) == 0) { found_inchi = trimmed; + break; + } else if (trimmed.find("InChI=", 0) != std::string::npos) { + size_t start_pos = trimmed.find("InChI="); + if(start_pos != 0) { + found_inchi = trimmed.substr(start_pos); + } else { + found_inchi = trimmed; + } + break; } } @@ -165,7 +174,13 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { szSdfDataValue, &ulDisplTime, bReleaseVersion, plog); - inchi_ios_init(pout, INCHI_IOS_TYPE_STRING, nullptr); + + const char* inchi_filename = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/output.txt"; + + FILE *file_inchi; + file_inchi = fopen(inchi_filename, "w"); + + inchi_ios_init(pout, INCHI_IOS_TYPE_FILE, file_inchi); //nullptr INCHI_IOS_TYPE_STRING inchi_ios_init(plog, INCHI_IOS_TYPE_STRING, stdout); inchi_ios_init(pprb, INCHI_IOS_TYPE_STRING, nullptr); @@ -195,23 +210,9 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { EXPECT_EQ(orig_at_data.num_inp_bonds, 17); CANON_GLOBALS CG = {}; - // STRUCT_DATA* sd; - // INPUT_PARMS* ip; - // char* szTitle; PINChI2* pINChI[INCHI_NUM]; PINChI_Aux2* pINChI_Aux[INCHI_NUM]; - // INCHI_IOSTREAM* inp_file; - // INCHI_IOSTREAM* plog; - // INCHI_IOSTREAM* pout; - // INCHI_IOSTREAM* pprb; - // ORIG_ATOM_DATA* orig_inp_data; ORIG_ATOM_DATA prep_inp_data = {}; - // long* num_inp; - // STRUCT_FPTRS* pStructPtrs; - // int* nRet; - // int have_err_in_GetOneStructure; - // long* num_err; - // int output_error_inchi; INCHI_IOS_STRING *strbuf = new INCHI_IOS_STRING; memset(strbuf, 0, sizeof(*strbuf)); inchi_strbuf_init(strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); @@ -281,15 +282,25 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { EXPECT_EQ(ret, DO_NEXT_STEP); - char *inchi = "InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6+,7-,8+,9+,10-/m0/s1"; - //ios->s.pStr - EXPECT_STREQ(inchi, pout->s.pStr); + fclose(file_inchi); + + char *found_inchi = read_inchi_from_file(inchi_filename); + + const char *inchi = "InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6+,7-,8+,9+,10-/m0/s1"; + + EXPECT_STREQ(inchi, found_inchi); //pout->s.pStr); + + free(found_inchi); + + remove(inchi_filename); FreeAllINChIArrays(pINChI, pINChI_Aux, sd->num_components); + inchi_strbuf_close(strbuf); inchi_ios_free_str(&input_stream); FreeOrigAtData(&orig_at_data); FreeOrigAtData(&prep_inp_data); + SetBitFree(&CG); for (int i = 0; i < MAX_NUM_PATHS; i++) { @@ -306,6 +317,7 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { delete pout; delete pprb; delete num_inp; + delete strbuf; } From e3db9cc6f4f296912355d12e126bacc940a9a566 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 15 Dec 2025 10:56:43 +0000 Subject: [PATCH 27/69] Formatting whitespace removal --- INCHI-1-SRC/INCHI_BASE/src/runichi.c | 97 ++++++++++++++-------------- 1 file changed, 48 insertions(+), 49 deletions(-) diff --git a/INCHI-1-SRC/INCHI_BASE/src/runichi.c b/INCHI-1-SRC/INCHI_BASE/src/runichi.c index a5dc9e1c..d8630a59 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/runichi.c +++ b/INCHI-1-SRC/INCHI_BASE/src/runichi.c @@ -267,7 +267,6 @@ int ProcessOneStructure( INCHI_CLOCK *ic, memset( composite_norm_data, 0, sizeof( composite_norm_data ) ); /* djb-rwth: memset_s C11/Annex K variant? */ memset( pncFlags, 0, sizeof( *pncFlags ) ); /* djb-rwth: memset_s C11/Annex K variant? */ - /* For experimental purposes only */ /*ret1 = DoOneStructureEarlyPreprocessing( num_inp, sd, ip, inp_file, log_file, out_file, prb_file, @@ -1156,7 +1155,7 @@ int CreateOneStructureINChI( CANON_GLOBALS *pCG, /* allocate pINChI[iINChI] and pINChI_Aux2[iINChI] -- arrays of pointers to INChI and INChI_Aux */ /* assign values to sd->num_components[] */ - + /* djb-rwth: MYREALLOC2 has been replaced and the whole block rewritten to address memory leaks and reading from freed memory locations */ do { if( (sd->num_components[iINChI]) <= ((long long)cur_prep_inp_data->num_components) ) { @@ -1327,7 +1326,7 @@ int CreateOneStructureINChI( CANON_GLOBALS *pCG, } #endif - /*#ifndef COMPILE_ANSI_ONLY + /*#ifndef COMPILE_ANSI_ONLY { */ /* b) Display the extracted original component structure */ @@ -2039,7 +2038,7 @@ int ProcessOneStructureEx( struct tagINCHI_CLOCK *ic, { int ret = _IS_OKAY; char *sinchi_noedits=NULL, *saux_noedits=NULL; - + /* PREPROCESS */ @@ -2048,7 +2047,7 @@ int ProcessOneStructureEx( struct tagINCHI_CLOCK *ic, if (ip->bFilterSS) { int present, ok = 0; - + present = OrigAtData_CheckForSubstructure(orig_inp_data); if (ip->bFilterSS == 1 && present) ok = 1; @@ -2073,11 +2072,11 @@ int ProcessOneStructureEx( struct tagINCHI_CLOCK *ic, &sinchi_noedits, &saux_noedits); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ /* CALCULATE INCHI */ - - /* Perform calculation as usual either for untouched (modes POLYMERS_LEGACY and POLYMERS_LEGACY_PLUS) + + /* Perform calculation as usual either for untouched (modes POLYMERS_LEGACY and POLYMERS_LEGACY_PLUS) or just edited, probably (mode POLYMERS_MODERN) structure as passed in orig_inp_data */ - ret = ProcessOneStructureExCore( ic, CG, sd, ip, szTitle, + ret = ProcessOneStructureExCore( ic, CG, sd, ip, szTitle, pINChI2, pINChI_Aux2, inp_file, log_file, out_file, prb_file, orig_inp_data, prep_inp_data, @@ -2118,7 +2117,7 @@ int ProcessOneStructureEx( struct tagINCHI_CLOCK *ic, inchi_free(sinchi_noedits); inchi_free(saux_noedits); - + #ifdef TARGET_LIB_FOR_WINCHI push_to_winchi_text_window(out_file); @@ -2135,7 +2134,7 @@ int ProcessOneStructureEx( struct tagINCHI_CLOCK *ic, /**************************************************************************** - Special treatment for polymers: perform CRU frame shift analysis + Special treatment for polymers: perform CRU frame shift analysis and make related edits in orig_inp_data whenever applicable ****************************************************************************/ int PreprocessPolymerCRUData( struct tagINCHI_CLOCK *ic, @@ -2161,7 +2160,7 @@ int PreprocessPolymerCRUData( struct tagINCHI_CLOCK *ic, char *sinchi_105p = NULL, *saux_105p = NULL; OAD_StructureEdits edits_unit_frame_shift, *ed_fs = &edits_unit_frame_shift; OAD_StructureEdits edits_unit_folding, *ed_fold = &edits_unit_folding; - + OAD_StructureEdits_Init(ed_fold); OAD_StructureEdits_Init(ed_fs); @@ -2192,7 +2191,7 @@ int PreprocessPolymerCRUData( struct tagINCHI_CLOCK *ic, sinchi_noedits, saux_noedits); if (ret == _IS_FATAL || ret == _IS_ERROR) { - ret = _IS_WARNING; + ret = _IS_WARNING; if (!ip->bNoWarnings) { AddErrorMessage(sd->pStrErrStruct, "CRU folding and frame shift analysis failed"); @@ -2205,10 +2204,10 @@ int PreprocessPolymerCRUData( struct tagINCHI_CLOCK *ic, /* CRU having both caps of indefinite nature, Zz */ goto exit_function; } - + /* Prepare and perform CRU folding related edits */ - if (ip->bFoldPolymerSRU != 0) + if (ip->bFoldPolymerSRU != 0) { /* Get interim 105+ flavour of InChI and AuxInfo and prepare */ int old_bFrameShiftScheme = ip->bFrameShiftScheme; @@ -2228,7 +2227,7 @@ int PreprocessPolymerCRUData( struct tagINCHI_CLOCK *ic, /* AddErrorMessage(sd->pStrErrStruct, "CRU fold analysis failed");*/ ; } - goto frame_shift; + goto frame_shift; } ret = OAD_Polymer_PrepareFoldCRUEdits( orig_inp_data, *sinchi_noedits, *saux_noedits, sinchi_105p, saux_105p, ed_fold); @@ -2244,7 +2243,7 @@ int PreprocessPolymerCRUData( struct tagINCHI_CLOCK *ic, if (ret == _IS_WARNING) { /* inchi_ios_eprint(log_file, "Warning (CRU fold analysis failed) structure #%ld.%s%s%s%s\n", - num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue));*/ + num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue));*/ ; } /* else */ @@ -2283,7 +2282,7 @@ int PreprocessPolymerCRUData( struct tagINCHI_CLOCK *ic, frame_shift: ; /* Prepare and perform frame shift related edits */ - if (ip->bFrameShiftScheme != FSS_NONE) + if (ip->bFrameShiftScheme != FSS_NONE) { /* Clear buffers */ if (sinchi_105p) @@ -2314,7 +2313,7 @@ frame_shift: ; } ret = OAD_Polymer_PrepareFrameShiftEdits( orig_inp_data, sinchi_105p, saux_105p, ed_fs); - + if (ret == _IS_FATAL || ret == _IS_ERROR) /* djb-rwth: logical operator corrected */ { ret = _IS_WARNING; @@ -2386,7 +2385,7 @@ frame_shift: ; OAD_StructureEdits_Clear(ed_fold); /* Clear edits collection */ OAD_StructureEdits_Clear(ed_fs); /* Clear edits collection */ - + return ret; } @@ -2395,17 +2394,17 @@ frame_shift: ; void swap_atoms_xyz( ORIG_ATOM_DATA *orig_at_data, int ia1, int ia2 ) { double x, y, z; - + if (ia1 != ia2) { - x = orig_at_data->at[ia1].x; - y = orig_at_data->at[ia1].y; + x = orig_at_data->at[ia1].x; + y = orig_at_data->at[ia1].y; z = orig_at_data->at[ia1].z; orig_at_data->at[ia1].x = orig_at_data->at[ia2].x; orig_at_data->at[ia1].y = orig_at_data->at[ia2].y; orig_at_data->at[ia1].z = orig_at_data->at[ia2].z; - + orig_at_data->at[ia2].x = x; orig_at_data->at[ia2].y = y; orig_at_data->at[ia2].z = z; @@ -2418,10 +2417,10 @@ void swap_atoms_xyz( ORIG_ATOM_DATA *orig_at_data, int ia1, int ia2 ) /**************************************************************************** OAD_StructureEdits_Edit ****************************************************************************/ -int OAD_StructureEdits_Apply( STRUCT_DATA *sd, - INPUT_PARMS *ip, - ORIG_ATOM_DATA *orig_at_data, - OAD_StructureEdits *ed, +int OAD_StructureEdits_Apply( STRUCT_DATA *sd, + INPUT_PARMS *ip, + ORIG_ATOM_DATA *orig_at_data, + OAD_StructureEdits *ed, int *ret) { int ok = 0, fail; @@ -2469,7 +2468,7 @@ int OAD_StructureEdits_Apply( STRUCT_DATA *sd, n_edits++; } } - + /* Add bonds */ if (n_new_bond) { @@ -2488,7 +2487,7 @@ int OAD_StructureEdits_Apply( STRUCT_DATA *sd, n_edits++; } } - + /* Modify bonds */ if (n_mod_bond) { @@ -2551,7 +2550,7 @@ int OAD_StructureEdits_Apply( STRUCT_DATA *sd, } } - + /* Delete atoms */ if (n_del_atom) { @@ -2572,7 +2571,7 @@ int OAD_StructureEdits_Apply( STRUCT_DATA *sd, goto exit_function; } - fail = mark_atoms_to_delete_or_renumber(orig_at_data, ed, at_renum); + fail = mark_atoms_to_delete_or_renumber(orig_at_data, ed, at_renum); if (fail) { *ret = _IS_ERROR; @@ -2594,20 +2593,20 @@ int OAD_StructureEdits_Apply( STRUCT_DATA *sd, AT_NUMB nbr0[MAXVAL]; U_CHAR btype0[MAXVAL]; int m, macc, valen; - int new_num = at_renum[i]; + int new_num = at_renum[i]; if (new_num == -1) { /* Skip removed atom */ continue; } - /* Atom to keep; copy it */ + /* Atom to keep; copy it */ new_at0 = new_at + nacc; ++nacc; memcpy(new_at0, orig_at_data->at + i, sizeof(new_at[0])); /* Correct its own number(s) */ new_at0->orig_at_number = new_num + 1; - + /* Correct its nbr number(s) */ valen = new_at0->valence; memcpy(nbr0, new_at0->neighbor, valen * sizeof(AT_NUMB)); @@ -2620,7 +2619,7 @@ int OAD_StructureEdits_Apply( STRUCT_DATA *sd, if (renum2 == num2) { /* keep old */ - new_at0->neighbor[macc++] = num2; + new_at0->neighbor[macc++] = num2; } else if (renum2 == -1) { @@ -2628,7 +2627,7 @@ int OAD_StructureEdits_Apply( STRUCT_DATA *sd, new_at0->chem_bonds_valence -= btype0[m]; new_at0->valence--; } - else + else { /* set renumbered */ new_at0->neighbor[macc++] = renum2; @@ -2746,7 +2745,7 @@ int OAD_StructureEdits_Apply( STRUCT_DATA *sd, } /* if (n_del_atom) */ - + exit_function: if (ibuf) @@ -2759,7 +2758,7 @@ int OAD_StructureEdits_Apply( STRUCT_DATA *sd, } return n_edits; } - + /**************************************************************************** Set each element of number to renum[element] or delete it if renum==(base -1) @@ -2868,7 +2867,7 @@ int ProcessOneStructureExCore( struct tagINCHI_CLOCK *ic, /**************************************************************************** - Treat pseudoelement and polymers: parse, validate and set details + Treat pseudoelement and polymers: parse, validate and set details ****************************************************************************/ int ValidateAndPreparePolymerAndPseudoatoms( struct tagINCHI_CLOCK *ic, struct tagCANON_GLOBALS *CG, @@ -2891,7 +2890,7 @@ int ValidateAndPreparePolymerAndPseudoatoms( struct tagINCHI_CLOCK *ic, int res = _IS_OKAY; int mind_pseudoelements = 0; - + *mind_polymers = orig_inp_data && orig_inp_data->polymer && orig_inp_data->polymer->n > 0; *mind_polymers = *mind_polymers && orig_inp_data->valid_polymer && (ip->nInputType == INPUT_MOLFILE || ip->nInputType == INPUT_SDFILE); @@ -2923,8 +2922,8 @@ int ValidateAndPreparePolymerAndPseudoatoms( struct tagINCHI_CLOCK *ic, ip->bPolymers != POLYMERS_MODERN && (ip->bFrameShiftScheme == FSS_STARS_CYCLED || ip->bFrameShiftScheme == FSS_STARS_CYCLED_SORTED)) { - /* Analyze and cyclize frame-shift eligible CRUs using InChI canonical numbers - (do this only at older polymer treatment modes 1.05, 1.05+) + /* Analyze and cyclize frame-shift eligible CRUs using InChI canonical numbers + (do this only at older polymer treatment modes 1.05, 1.05+) */ res = OAD_Polymer_CyclizeCloseableUnits( orig_inp_data, ip->bPolymers, @@ -2951,7 +2950,7 @@ int ValidateAndPreparePolymerAndPseudoatoms( struct tagINCHI_CLOCK *ic, /**************************************************************************** Get InChI and AuxInfo of totally unedited original structure. The intent is to preserve AuxInfo for the very original structure - in order to keep a final ability to restore that structure. + in order to keep a final ability to restore that structure. ****************************************************************************/ int OAD_ProcessOneStructureNoEdits( struct tagINCHI_CLOCK *ic, struct tagCANON_GLOBALS *CG, @@ -2970,7 +2969,7 @@ int OAD_ProcessOneStructureNoEdits( struct tagINCHI_CLOCK *ic, INCHI_IOS_STRING *strbuf, unsigned char save_opt_bits, int *n_pzz, - char **sinchi, + char **sinchi, char **saux) { size_t slen; @@ -3013,7 +3012,7 @@ int OAD_ProcessOneStructureNoEdits( struct tagINCHI_CLOCK *ic, { goto exit_function; } - + *n_pzz = dup->orig_inp_data->polymer->n_pzz; /* Extract InChI */ slen = dup->out_file->s.nUsedLength; @@ -3150,9 +3149,9 @@ int mark_atoms_to_delete_or_renumber( ORIG_ATOM_DATA *orig_at_data, size_t *atnums = NULL; /* djb-rwth: needs to be size_t type */ size_t max_atoms = orig_at_data->num_inp_atoms; - /* NB: new/old ORIG_ATOM_DATA atom numbers are 0-based (==orig_number-1) + /* NB: new/old ORIG_ATOM_DATA atom numbers are 0-based (==orig_number-1) while those in ed->... are just 1-based orig_numbers */ - + for (i = 0; (size_t)i < max_atoms; i++) { at_renum[i] = i; @@ -3219,7 +3218,7 @@ int mark_atoms_to_delete_or_renumber( ORIG_ATOM_DATA *orig_at_data, for (i = max_atoms - 1; i >= 0; i--) { int orig_num = i + 1; /* NB: ed->del_atom->item contains orig# which are (OAD# + 1) */ - if (is_in_the_ilist(ed->del_atom->item, orig_num, ed->del_atom->used)) + if (is_in_the_ilist(ed->del_atom->item, orig_num, ed->del_atom->used)) { /* mark as deleted atnum */ at_renum[i] = -1; @@ -3262,7 +3261,7 @@ int check_presence_of_the_encoded_substructure(ORIG_ATOM_DATA *oad) /* Place sub-structure filtering code below. Return 1 if structure matches some hard-coded pattern - + In this example pattern is a presence of a pseudo atom. */ From bb6fc2940bf10c91fe177725570de48a53be7910 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 15 Dec 2025 11:10:40 +0000 Subject: [PATCH 28/69] removed sanitizing flags --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 737bfafd..2b324705 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,8 +6,8 @@ set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 11) set(CMAKE_POSITION_INDEPENDENT_CODE ON) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") +# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") +# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") include(FetchContent) FetchContent_Declare( From 1988646eba29214881e1f1f83afbbaec92fa6e32 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 15 Dec 2025 11:29:57 +0000 Subject: [PATCH 29/69] fixed missing initialization --- INCHI-1-TEST/tests/test_unit/test_ichimain.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index f06648b1..c3c8729e 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -210,8 +210,8 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { EXPECT_EQ(orig_at_data.num_inp_bonds, 17); CANON_GLOBALS CG = {}; - PINChI2* pINChI[INCHI_NUM]; - PINChI_Aux2* pINChI_Aux[INCHI_NUM]; + PINChI2* pINChI[INCHI_NUM] = {}; + PINChI_Aux2* pINChI_Aux[INCHI_NUM] = {}; ORIG_ATOM_DATA prep_inp_data = {}; INCHI_IOS_STRING *strbuf = new INCHI_IOS_STRING; memset(strbuf, 0, sizeof(*strbuf)); @@ -282,7 +282,9 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { EXPECT_EQ(ret, DO_NEXT_STEP); - fclose(file_inchi); + if (file_inchi != nullptr) { + fclose(file_inchi); + } char *found_inchi = read_inchi_from_file(inchi_filename); From 935e58310b8e9f2b26a73831454b84ece5fda930 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 15 Dec 2025 12:43:42 +0000 Subject: [PATCH 30/69] Added write permissions to workflow in ci pipeline --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b9e27ffd..85a316d6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,6 +18,9 @@ jobs: - id: setup run: ./.devcontainer/post_create_commands.sh + - name: Fix file permissions + run: chmod -R +rw ${{ github.workspace }} + - name: Run unit tests run: cd CMake_build/full_build/INCHI-1-TEST/tests/test_unit && ctest --output-on-failure From 6505cc934b447c3e65f94c639d8f9106f0bb710e Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 15 Dec 2025 13:06:16 +0000 Subject: [PATCH 31/69] Reverted file permissions --- .github/workflows/ci.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 85a316d6..b9e27ffd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,9 +18,6 @@ jobs: - id: setup run: ./.devcontainer/post_create_commands.sh - - name: Fix file permissions - run: chmod -R +rw ${{ github.workspace }} - - name: Run unit tests run: cd CMake_build/full_build/INCHI-1-TEST/tests/test_unit && ctest --output-on-failure From 8053314a97194aaec29c118319f004881a3e8d10 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 15 Dec 2025 13:22:12 +0000 Subject: [PATCH 32/69] Path fix for ci pipeline --- INCHI-1-TEST/tests/test_unit/test_ichimain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index c3c8729e..8afe3243 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -175,7 +175,7 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { bReleaseVersion, plog); - const char* inchi_filename = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/output.txt"; + const char* inchi_filename = "../../../INCHI-1-TEST/tests/test_unit/fixtures/output.txt"; FILE *file_inchi; file_inchi = fopen(inchi_filename, "w"); From 0fcbdfcbe96b98872e9dcc81095573b4eed6b50f Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 15 Dec 2025 13:32:51 +0000 Subject: [PATCH 33/69] Path fix for ci pipeline --- INCHI-1-TEST/tests/test_unit/test_ichimain.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index 8afe3243..55d60776 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -335,10 +335,11 @@ TEST(ichimain_testing, test_ProcessMultipleInputFiles_2mol_files) "naloxon.mol", "caffeine.mol" }; + // ../../../ + // /workspaces/InChI/ + const char *path_fixtures = "../../../INCHI-1-TEST/tests/test_unit/fixtures"; - const char *path_fixtures = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures"; - - char tmpl[] = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; + char tmpl[] = "../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; char *tmpd = mkdtemp(tmpl); ASSERT_NE(tmpd, nullptr); From 86c8804b74ea43061a5fd4d2476b74fc7a786dee Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 15 Dec 2025 13:43:23 +0000 Subject: [PATCH 34/69] Path fix for ci pipeline --- INCHI-1-TEST/tests/test_unit/test_ichimain.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index 55d60776..04315ba6 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -175,7 +175,7 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { bReleaseVersion, plog); - const char* inchi_filename = "../../../INCHI-1-TEST/tests/test_unit/fixtures/output.txt"; + const char* inchi_filename = "../../../../INCHI-1-TEST/tests/test_unit/fixtures/output.txt"; FILE *file_inchi; file_inchi = fopen(inchi_filename, "w"); @@ -337,9 +337,9 @@ TEST(ichimain_testing, test_ProcessMultipleInputFiles_2mol_files) }; // ../../../ // /workspaces/InChI/ - const char *path_fixtures = "../../../INCHI-1-TEST/tests/test_unit/fixtures"; + const char *path_fixtures = "../../../../INCHI-1-TEST/tests/test_unit/fixtures"; - char tmpl[] = "../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; + char tmpl[] = "../../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; char *tmpd = mkdtemp(tmpl); ASSERT_NE(tmpd, nullptr); @@ -409,8 +409,8 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) const char *filename_caffeine = "caffeine.mol"; - const char *path_fixtures = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures"; - char tmpl[] = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; + const char *path_fixtures = "../../../../INCHI-1-TEST/tests/test_unit/fixtures"; + char tmpl[] = "../../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; char *tmpd = mkdtemp(tmpl); ASSERT_NE(tmpd, nullptr); @@ -471,8 +471,8 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_2mols_sdf) const char *filename_2mols = "test_mols_2.sdf"; - const char *path_fixtures = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures"; - char tmpl[] = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; + const char *path_fixtures = "../../../../INCHI-1-TEST/tests/test_unit/fixtures"; + char tmpl[] = "../../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; char *tmpd = mkdtemp(tmpl); ASSERT_NE(tmpd, nullptr); From 32939dad241c715edb7bdf3aa35e6c198c1595d5 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Tue, 16 Dec 2025 10:22:16 +0000 Subject: [PATCH 35/69] Fixed directory for fixtures --- .../tests/test_unit/test_ichimain.cpp | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index 04315ba6..7e06de36 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include extern "C" @@ -53,7 +54,6 @@ char *read_inchi_from_file(const char *filename) { TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { - INCHI_IOSTREAM input_stream; const char *molblock = @@ -174,11 +174,10 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { szSdfDataValue, &ulDisplTime, bReleaseVersion, plog); - - const char* inchi_filename = "../../../../INCHI-1-TEST/tests/test_unit/fixtures/output.txt"; - - FILE *file_inchi; + const char* inchi_filename = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures/output.txt"; + FILE *file_inchi = nullptr; file_inchi = fopen(inchi_filename, "w"); + EXPECT_NE(file_inchi, nullptr); inchi_ios_init(pout, INCHI_IOS_TYPE_FILE, file_inchi); //nullptr INCHI_IOS_TYPE_STRING inchi_ios_init(plog, INCHI_IOS_TYPE_STRING, stdout); @@ -205,7 +204,6 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { output_error_inchi); EXPECT_EQ(ret, DO_NEXT_STEP); - EXPECT_EQ(orig_at_data.num_inp_atoms, 18); EXPECT_EQ(orig_at_data.num_inp_bonds, 17); @@ -225,7 +223,6 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { set_line_separators(ip->bINChIOutputOptions, &pLF, &pTAB); - // int CalcAndPrintINCHIAndINCHIKEY(struct tagINCHI_CLOCK* ic, // CANON_GLOBALS* CG, // STRUCT_DATA* sd, @@ -288,6 +285,8 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { char *found_inchi = read_inchi_from_file(inchi_filename); + EXPECT_NE(found_inchi, nullptr); + const char *inchi = "InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6+,7-,8+,9+,10-/m0/s1"; EXPECT_STREQ(inchi, found_inchi); //pout->s.pStr); @@ -312,9 +311,9 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { ip->path[i] = NULL; } } + delete ip; delete sd; - delete plog; delete pout; delete pprb; @@ -337,9 +336,9 @@ TEST(ichimain_testing, test_ProcessMultipleInputFiles_2mol_files) }; // ../../../ // /workspaces/InChI/ - const char *path_fixtures = "../../../../INCHI-1-TEST/tests/test_unit/fixtures"; + const char *path_fixtures = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures"; - char tmpl[] = "../../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; + char tmpl[] = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; char *tmpd = mkdtemp(tmpl); ASSERT_NE(tmpd, nullptr); @@ -409,8 +408,8 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) const char *filename_caffeine = "caffeine.mol"; - const char *path_fixtures = "../../../../INCHI-1-TEST/tests/test_unit/fixtures"; - char tmpl[] = "../../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; + const char *path_fixtures = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures"; + char tmpl[] = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; char *tmpd = mkdtemp(tmpl); ASSERT_NE(tmpd, nullptr); @@ -466,13 +465,14 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) remove(dst_path.c_str()); rmdir(tmpd); } + TEST(ichimain_testing, test_ProcessSingleInputFile_2mols_sdf) { const char *filename_2mols = "test_mols_2.sdf"; - const char *path_fixtures = "../../../../INCHI-1-TEST/tests/test_unit/fixtures"; - char tmpl[] = "../../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; + const char *path_fixtures = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures"; + char tmpl[] = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; char *tmpd = mkdtemp(tmpl); ASSERT_NE(tmpd, nullptr); From b4fa666277cff6aaa357797cda8a4b185bd6687e Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Tue, 16 Dec 2025 15:38:28 +0000 Subject: [PATCH 36/69] Removed commented lines --- .../tests/test_unit/test_ichimain.cpp | 60 ++++--------------- _deps/googletest-src | 1 - 2 files changed, 12 insertions(+), 49 deletions(-) delete mode 160000 _deps/googletest-src diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index 7e06de36..d50a451d 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -115,21 +115,6 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { inchi_ios_init(&input_stream, INCHI_IOS_TYPE_STRING, nullptr); inchi_ios_print_nodisplay(&input_stream, molblock); - // int GetTheNextRecordOfInputFile( struct tagINCHI_CLOCK *ic, - // STRUCT_DATA *sd, INPUT_PARMS *ip, - // char *szTitle, - // INCHI_IOSTREAM *inp_file, - // INCHI_IOSTREAM *plog, - // INCHI_IOSTREAM *pout, - // INCHI_IOSTREAM *pprb, - // ORIG_ATOM_DATA *orig_inp_data, - // long *num_inp, - // STRUCT_FPTRS *pStructPtrs, - // int *nRet, - // int *have_err_in_GetOneStructure, - // long *num_err, - // int output_error_inchi ); - INCHI_CLOCK ic = {}; memset(&ic, 0, sizeof(ic)); @@ -137,6 +122,11 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { // sd->ulStructTime = 0; INPUT_PARMS *ip = new INPUT_PARMS; + memset(ip, 0, sizeof(*ip)); + ip->last_struct_number = 1; + ip->nInputType = INPUT_MOLFILE; + ip->bINChIOutputOptions = INCHI_OUT_PLAIN_TEXT; + char *szTitle; INCHI_IOSTREAM *inp_file; INCHI_IOSTREAM *plog = new INCHI_IOSTREAM; @@ -152,18 +142,8 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { long num_err = 0; int output_error_inchi; - - memset(ip, 0, sizeof(*ip)); - ip->last_struct_number = 1; - ip->nInputType = INPUT_MOLFILE; - ip->bINChIOutputOptions = INCHI_OUT_PLAIN_TEXT; - // ip->bINChIOutputOptions2 = INCHI_OUT_PLAIN_TEXT; - // ip->nMode = REQ_MODE_TAUT; // REQ_MODE_BASIC; - // ip->bTautFlags |= (TG_FLAG_DISCONNECT_COORD | TG_FLAG_RECONNECT_COORD); - // ip->nMode |= (REQ_MODE_BASIC | REQ_MODE_TAUT | REQ_MODE_STEREO | REQ_MODE_ISO_STEREO | REQ_MODE_ISO); - int bReleaseVersion = bRELEASE_VERSION; - unsigned long ulDisplTime = 0; /* infinite, milliseconds */ + unsigned long ulDisplTime = 0; unsigned long ulTotalProcessingTime = 0; int argc = 0; @@ -179,11 +159,10 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { file_inchi = fopen(inchi_filename, "w"); EXPECT_NE(file_inchi, nullptr); - inchi_ios_init(pout, INCHI_IOS_TYPE_FILE, file_inchi); //nullptr INCHI_IOS_TYPE_STRING + inchi_ios_init(pout, INCHI_IOS_TYPE_FILE, file_inchi); inchi_ios_init(plog, INCHI_IOS_TYPE_STRING, stdout); inchi_ios_init(pprb, INCHI_IOS_TYPE_STRING, nullptr); - // PrintInputParms(plog, ip); inchi_ios_flush2(plog, stderr); int ret = GetTheNextRecordOfInputFile( @@ -334,8 +313,7 @@ TEST(ichimain_testing, test_ProcessMultipleInputFiles_2mol_files) "naloxon.mol", "caffeine.mol" }; - // ../../../ - // /workspaces/InChI/ + const char *path_fixtures = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures"; char tmpl[] = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; @@ -373,7 +351,6 @@ TEST(ichimain_testing, test_ProcessMultipleInputFiles_2mol_files) int ret = ProcessMultipleInputFiles(argc, argv); - // Assert the expected result ASSERT_EQ(ret, 0); for (int i = 0; i < expected_inchis.size(); i++) { @@ -383,8 +360,6 @@ TEST(ichimain_testing, test_ProcessMultipleInputFiles_2mol_files) free(inchi); } - // Clean up - for (auto p : dist_paths) { std::string out_txt = p + ".txt"; @@ -432,18 +407,13 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) int result = ProcessSingleInputFile(argc, argv); - // Assert the expected result EXPECT_EQ(result, 0); - free(inchi_filename); - free(input_file); - std::string out_txt = dst_path + ".txt"; std::string out_log = dst_path + ".log"; std::string out_prb = dst_path + ".prb"; struct stat st; - // check existence and non-zero size ASSERT_EQ(stat(out_txt.c_str(), &st), 0); EXPECT_GT(st.st_size, 0); ASSERT_EQ(stat(out_log.c_str(), &st), 0); @@ -458,6 +428,8 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) EXPECT_EQ(found_inchi, expected_inchi); // cleanup + free(inchi_filename); + free(input_file); free(found_inchi); remove(out_txt.c_str()); remove(out_log.c_str()); @@ -492,27 +464,20 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_2mols_sdf) char* argv[] = { inchi_filename, input_file }; // int ProcessSingleInputFile(int argc, char* argv[]) - int result = ProcessSingleInputFile(argc, argv); - // Assert the expected result EXPECT_EQ(result, 0); - free(inchi_filename); - free(input_file); - std::string out_txt = dst_path + ".txt"; std::string out_log = dst_path + ".log"; std::string out_prb = dst_path + ".prb"; struct stat st; - // check existence and non-zero size ASSERT_EQ(stat(out_txt.c_str(), &st), 0); EXPECT_GT(st.st_size, 0); ASSERT_EQ(stat(out_log.c_str(), &st), 0); EXPECT_GT(st.st_size, 0); ASSERT_EQ(stat(out_prb.c_str(), &st), 0); - // EXPECT_GT(st.st_size, 0); EXPECT_EQ(st.st_size, 0); std::ifstream txt_in(out_txt); @@ -520,7 +485,6 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_2mols_sdf) std::string line; std::vector found_inchis; while (std::getline(txt_in, line)) { - // trim leading/trailing whitespace size_t start = line.find_first_not_of(" \t\r\n"); if (start == std::string::npos) continue; size_t end = line.find_last_not_of(" \t\r\n"); @@ -542,6 +506,8 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_2mols_sdf) } // cleanup + free(inchi_filename); + free(input_file); remove(out_txt.c_str()); remove(out_log.c_str()); remove(out_prb.c_str()); @@ -649,7 +615,6 @@ TEST(ichimain_testing, test_GetTheNextRecordOfInputFile) long *num_err; int output_error_inchi; - memset(ip, 0, sizeof(*ip)); ip->last_struct_number = 1; ip->nInputType = INPUT_MOLFILE; @@ -658,7 +623,6 @@ TEST(ichimain_testing, test_GetTheNextRecordOfInputFile) inchi_ios_init(plog, INCHI_IOS_TYPE_STRING, stdout); inchi_ios_init(pprb, INCHI_IOS_TYPE_STRING, nullptr); - // PrintInputParms(plog, ip); inchi_ios_flush2(plog, stderr); int ret = GetTheNextRecordOfInputFile( diff --git a/_deps/googletest-src b/_deps/googletest-src deleted file mode 160000 index 52eb8108..00000000 --- a/_deps/googletest-src +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 52eb8108c5bdec04579160ae17225d66034bd723 From 5067af038d3f1f78b74ad909bb9eb7aa905d802d Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Fri, 19 Dec 2025 09:46:04 +0000 Subject: [PATCH 37/69] Added free function for inchi_output --- INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp b/INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp index e0f7fdf9..1118c7fd 100644 --- a/INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp @@ -87,4 +87,6 @@ TEST(inchi_dll_b_testing, test_MakeINCHIFromMolfileText) // Works with other V3000 molfile. ASSERT_EQ(MakeINCHIFromMolfileText(ethanol, options, poutput), 0); + + FreeINCHI(poutput); } From d6dc2930803c5f70f53dcf1692f2f93d917a7cc1 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Fri, 19 Dec 2025 12:35:03 +0000 Subject: [PATCH 38/69] Added unit test prototype for testing OutputINCHI_StereoLayer --- INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c | 41 ++++++++++--------- .../tests/test_unit/test_ichiprt1.cpp | 30 ++++++++++++++ .../tests/test_unit/test_inchi_dll_b.cpp | 2 + 3 files changed, 53 insertions(+), 20 deletions(-) create mode 100644 INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c index 38f7debe..6ed41b1c 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c @@ -150,11 +150,11 @@ static int OutputINCHI_PolymerLayer( CANON_GLOBALS *pCG, INCHI_IOSTREAM *out_fil INCHI_OUT_CTL *io, char *pLF, char *pTAB ); static int OutputINCHI_PolymerLayer_SingleUnit( OAD_PolymerUnit *u, int bPolymers, - int total_star_atoms, + int total_star_atoms, int *n_used_stars, - OAD_AtProps *aprops, + OAD_AtProps *aprops, int *cano_nums, - ORIG_ATOM_DATA *orig_inp_data, + ORIG_ATOM_DATA *orig_inp_data, ORIG_STRUCT *pOrigStruct, INCHI_IOS_STRING *strbuf ); static int OutputAUXINFO_HeaderAndNormalization_type( CANON_GLOBALS *pCG, @@ -1160,7 +1160,7 @@ int OutputINChI1( CANON_GLOBALS *pCG, io.n_pzz = orig_inp_data->polymer->n_pzz; } } - + io.bPolymers = ip->bPolymers; @@ -2640,7 +2640,7 @@ int WriteOrigBonds( CANON_GLOBALS *pCG, num_trans = 0; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ nNeighOrder[0] = 0; } - for (kk = 0; kk < at[j].valence; kk++) + for (kk = 0; kk < at[j].valence; kk++) { k = nNeighOrder[kk]; j2 = at[j].neighbor[k]; @@ -3121,7 +3121,8 @@ void set_line_separators( int bINChIOutputOptions, char **pLF, char **pTAB ) int bPlainTabbedOutput = 0 != ( bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT ) && bPlainText && !bPlainTextCommnts; - *pTAB = bPlainTabbedOutput ? "\t" : "\n"; + const char* tab = bPlainTabbedOutput ? "\t" : "\n"; + strcpy(*pTAB, tab); } #else *pTAB = "\n"; @@ -3908,7 +3909,7 @@ static int OutputINCHI_PolymerLayer( CANON_GLOBALS *pCG, nat = orig_inp_data->num_inp_atoms; num_inp_bonds = orig_inp_data->num_inp_bonds; - + if (pOrigStruct && !pOrigStruct->polymer) { return 0; @@ -4145,7 +4146,7 @@ static int OutputINCHI_PolymerLayer_SingleUnit( OAD_PolymerUnit *u, a2 = u->blist[1]; a3 = u->blist[2]; a4 = u->blist[3]; - + if (is_in_the_ilist( u->alist, a1, u->na )) { tmp = a2; @@ -4172,7 +4173,7 @@ static int OutputINCHI_PolymerLayer_SingleUnit( OAD_PolymerUnit *u, /* The first printed is the crossing bond pointing to more senior CRU end ("head") */ swap = (OAD_Polymer_IsFirstAtomRankLower(a2, a4, aprops) == 1); } - + if (swap) { inchi_strbuf_printf( strbuf, "(%-d-%-d,%-d-%-d)", a3, a4, a1, a2 ); @@ -4288,8 +4289,8 @@ static int OutputINCHI_PolymerLayer_SingleUnit( OAD_PolymerUnit *u, here at1, at2 is the most senior bond, and at1 is more senior than at2 all other pairs at3,at4, at5,at6, ... are sorted just in increasing - order of first number in pair, then second one, e.g.: at3frame_shift_scheme != FSS_NONE && u->nbkbonds >= 1 && u->cap1 >= 1 && u->cap2 >= 1) @@ -5046,7 +5047,7 @@ void EditINCHI_HidePolymerZz(INCHI_IOSTREAM *out, int n_pzz, int n_zy) eol_was_consumed = 0, pre_eol = 0, nonprt_sym = 0, nonprt_prev = 0; - if (n_zy > 0) + if (n_zy > 0) { /* We have some placeholder pseudo atoms which should not be removed below (if anyway they are allowed) */ if (n_pzz == 0) @@ -5131,7 +5132,7 @@ void EditINCHI_HidePolymerZz(INCHI_IOSTREAM *out, int n_pzz, int n_zy) AT_NUMB ia = (AT_NUMB) inchi_strtol(p, &q, 10); /* make compiler happy: */ /* djb-rwth: removing redundant code; ignoring LLVM warning: variable used to store function return value */ if (*q != '-') { - skip = 1; + skip = 1; } } } @@ -5283,7 +5284,7 @@ int CountPseudoElementInFormula( const char *pseudo, char *s ) /* djb-rwth: igno char prev = '/'; /* - format is + format is [sequence of] [.[int_mult[Zz[int_index]]]] */ @@ -5291,8 +5292,8 @@ int CountPseudoElementInFormula( const char *pseudo, char *s ) /* djb-rwth: igno { return 0; } - - p = s; + + p = s; while (*p) /*for (p = s ; *p; p++)*/ { @@ -5317,7 +5318,7 @@ int CountPseudoElementInFormula( const char *pseudo, char *s ) /* djb-rwth: igno { mult = (int)inchi_strtol(p, &q, 10); p = q; - prev = *q--; + prev = *q--; continue; } else @@ -5326,7 +5327,7 @@ int CountPseudoElementInFormula( const char *pseudo, char *s ) /* djb-rwth: igno } if (!mult) { - break; + break; } } else if (*p== pseudo[1] && prev== pseudo[0]) @@ -5446,7 +5447,7 @@ int MergeZzInHillFormula(INCHI_IOS_STRING *strbuf) { inchi_free(scopy); /* djb-rwth: avoiding memory leak */ return -1; /* failed */ - } + } memcpy(scopy, strbuf->pStr, strbuf->nAllocatedLength); stmp = (char *)inchi_calloc((long long)strbuf->nAllocatedLength + 1, sizeof(char)); /* djb-rwth: cast operator added */ if (!stmp) @@ -5458,7 +5459,7 @@ int MergeZzInHillFormula(INCHI_IOS_STRING *strbuf) inchi_strbuf_reset(strbuf); p0 = scopy; p = p0; - do + do { /* djb-rwth: removing redundant code */ pend = strchr(p, '.'); diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp new file mode 100644 index 00000000..97e99207 --- /dev/null +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp @@ -0,0 +1,30 @@ +#include +#include +#include +#include +#include +#include +#include + +extern "C" +{ +// #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichitime.h" +// #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichicant.h" +// #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichi_io.h" +#include "../../../INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c" +} + + +TEST(ichiprt1_testing, test_OutputINCHI_StereoLayer) +{ + + + // int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, + // INCHI_IOSTREAM *out_file, + // INCHI_IOS_STRING *strbuf, + // INCHI_OUT_CTL *io, + // char *pLF, + // char *pTAB ) + + +} diff --git a/INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp b/INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp index 1118c7fd..d0a311fd 100644 --- a/INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp @@ -88,5 +88,7 @@ TEST(inchi_dll_b_testing, test_MakeINCHIFromMolfileText) // Works with other V3000 molfile. ASSERT_EQ(MakeINCHIFromMolfileText(ethanol, options, poutput), 0); + poutput->szLog = nullptr; + poutput->szMessage = nullptr; FreeINCHI(poutput); } From 8840be363350fbd924f7fc9399d429754831f544 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Fri, 19 Dec 2025 12:36:39 +0000 Subject: [PATCH 39/69] Bugfix for double free of logs and messages --- INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp b/INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp index 1118c7fd..d0a311fd 100644 --- a/INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp @@ -88,5 +88,7 @@ TEST(inchi_dll_b_testing, test_MakeINCHIFromMolfileText) // Works with other V3000 molfile. ASSERT_EQ(MakeINCHIFromMolfileText(ethanol, options, poutput), 0); + poutput->szLog = nullptr; + poutput->szMessage = nullptr; FreeINCHI(poutput); } From e5f44036bbbeec41ac9286b157b8d520aa31315a Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Fri, 19 Dec 2025 13:09:47 +0000 Subject: [PATCH 40/69] Added new unit-tests --- INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c | 3 +- .../tests/test_unit/test_ichiprt1.cpp | 53 ++++++++++++++++++- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c index 6ed41b1c..672ba198 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c @@ -3121,8 +3121,7 @@ void set_line_separators( int bINChIOutputOptions, char **pLF, char **pTAB ) int bPlainTabbedOutput = 0 != ( bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT ) && bPlainText && !bPlainTextCommnts; - const char* tab = bPlainTabbedOutput ? "\t" : "\n"; - strcpy(*pTAB, tab); + *pTAB = bPlainTabbedOutput ? (char*)"\t" : (char*)"\n"; } #else *pTAB = "\n"; diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp index 97e99207..bc89d735 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp @@ -10,7 +10,7 @@ extern "C" { // #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichitime.h" // #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichicant.h" -// #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichi_io.h" +#include "../../../INCHI-1-SRC/INCHI_BASE/src/ichi_io.h" #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c" } @@ -18,6 +18,17 @@ extern "C" TEST(ichiprt1_testing, test_OutputINCHI_StereoLayer) { + // Prepare minimal dummy arguments + CANON_GLOBALS cg = {0}; + INCHI_IOSTREAM out_file = {0}; + INCHI_IOS_STRING strbuf = {0}; + INCHI_OUT_CTL io = {0}; + char lf[] = "\n"; + char tab[] = "\t"; + + // Initialize string buffer (simulate allocation) + // inchi_strbuf_init(&strbuf, 128, 128); + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); // int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, // INCHI_IOSTREAM *out_file, @@ -26,5 +37,45 @@ TEST(ichiprt1_testing, test_OutputINCHI_StereoLayer) // char *pLF, // char *pTAB ) + // Call the function under test + int ret = OutputINCHI_StereoLayer(&cg, &out_file, &strbuf, &io, lf, tab); + + // Check that the function returns 0 (success) or expected error code + // (You may need to adjust this depending on the actual implementation) + EXPECT_EQ(ret, 0); + + // Clean up + inchi_strbuf_close(&strbuf); + +} + +TEST(ichiprt1_testing, test_set_line_separators) +{ + + // void set_line_separators( int bINChIOutputOptions, char **pLF, char **pTAB ) + + char *lf = nullptr; + char *tab = nullptr; + + // Plain text comments option + set_line_separators(INCHI_OUT_PLAIN_TEXT_COMMENTS, &lf, &tab); + EXPECT_STREQ(lf, "\n"); + EXPECT_STREQ(tab, "\n"); + + // Tabbed output option + set_line_separators(INCHI_OUT_PLAIN_TEXT | INCHI_OUT_TABBED_OUTPUT, &lf, &tab); + EXPECT_STREQ(lf, "\0"); + EXPECT_STREQ(tab, "\t"); + + // Plain text only + set_line_separators(INCHI_OUT_PLAIN_TEXT, &lf, &tab); + EXPECT_STREQ(lf, "\0"); + EXPECT_STREQ(tab, "\n"); + + // No options + set_line_separators(0, &lf, &tab); + EXPECT_STREQ(lf, "\0"); + EXPECT_STREQ(tab, "\n"); + } From c533e3a01bb896d00ddb2402cc8ff4068b3a07f8 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 22 Dec 2025 09:09:29 +0000 Subject: [PATCH 41/69] Fixed memory leakage in unit-test --- INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp b/INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp index a0fff86c..3c670e31 100644 --- a/INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp @@ -53,4 +53,6 @@ TEST(inchi_dll_b_testing, test_MakeINCHIFromMolfileText) ASSERT_EQ(MakeINCHIFromMolfileText(ferrocene, options, poutput), 1); ASSERT_STREQ(poutput->szInChI, expected_inchi); + + FreeINCHI(poutput); } From 3cff56f999ef90783974f383db1898bf3606d663 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 22 Dec 2025 09:50:38 +0000 Subject: [PATCH 42/69] Changed gtest test_suite names --- INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp index bc89d735..db96f282 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp @@ -15,7 +15,7 @@ extern "C" } -TEST(ichiprt1_testing, test_OutputINCHI_StereoLayer) +TEST(test_ichiprt1, test_OutputINCHI_StereoLayer) { // Prepare minimal dummy arguments @@ -49,7 +49,7 @@ TEST(ichiprt1_testing, test_OutputINCHI_StereoLayer) } -TEST(ichiprt1_testing, test_set_line_separators) +TEST(test_ichiprt1, test_set_line_separators) { // void set_line_separators( int bINChIOutputOptions, char **pLF, char **pTAB ) From fbf2a302677b7efe0e8cb196353d9a8e77ad4282 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 22 Dec 2025 09:57:21 +0000 Subject: [PATCH 43/69] Rename gtest test suite names to file names --- .../tests/test_unit/test_ichimain.cpp | 10 +-- .../tests/test_unit/test_inchi_dll_b.cpp | 2 +- INCHI-1-TEST/tests/test_unit/test_inpdef.cpp | 2 +- INCHI-1-TEST/tests/test_unit/test_mol_fmt.cpp | 24 +++--- .../tests/test_unit/test_permutation_util.cpp | 2 +- INCHI-1-TEST/tests/test_unit/test_strutil.cpp | 10 +-- INCHI-1-TEST/tests/test_unit/test_util.cpp | 78 +++++++++---------- 7 files changed, 64 insertions(+), 64 deletions(-) diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index d50a451d..b6f266bb 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -52,7 +52,7 @@ char *read_inchi_from_file(const char *filename) { return make_arg(found_inchi.c_str()); } -TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { +TEST(test_ichimain, test_CalcAndPrintINCHIAndINCHIKEY) { INCHI_IOSTREAM input_stream; @@ -301,7 +301,7 @@ TEST(ichimain_testing, test_CalcAndPrintINCHIAndINCHIKEY) { } -TEST(ichimain_testing, test_ProcessMultipleInputFiles_2mol_files) +TEST(test_ichimain, test_ProcessMultipleInputFiles_2mol_files) { std::vector expected_inchis = { @@ -378,7 +378,7 @@ TEST(ichimain_testing, test_ProcessMultipleInputFiles_2mol_files) } } -TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) +TEST(test_ichimain, test_ProcessSingleInputFile_caffeine) { const char *filename_caffeine = "caffeine.mol"; @@ -438,7 +438,7 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_caffeine) rmdir(tmpd); } -TEST(ichimain_testing, test_ProcessSingleInputFile_2mols_sdf) +TEST(test_ichimain, test_ProcessSingleInputFile_2mols_sdf) { const char *filename_2mols = "test_mols_2.sdf"; @@ -515,7 +515,7 @@ TEST(ichimain_testing, test_ProcessSingleInputFile_2mols_sdf) rmdir(tmpd); } -TEST(ichimain_testing, test_GetTheNextRecordOfInputFile) +TEST(test_ichimain, test_GetTheNextRecordOfInputFile) { INCHI_IOSTREAM input_stream; diff --git a/INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp b/INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp index 3c670e31..2f2ce08f 100644 --- a/INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_inchi_dll_b.cpp @@ -5,7 +5,7 @@ extern "C" #include "../../../INCHI-1-SRC/INCHI_BASE/src/inchi_api.h" } -TEST(inchi_dll_b_testing, test_MakeINCHIFromMolfileText) +TEST(test_inchi_dll_b, test_MakeINCHIFromMolfileText) { const char *ferrocene = "Ferrocene\n" diff --git a/INCHI-1-TEST/tests/test_unit/test_inpdef.cpp b/INCHI-1-TEST/tests/test_unit/test_inpdef.cpp index 16fd138b..62df9f7d 100644 --- a/INCHI-1-TEST/tests/test_unit/test_inpdef.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_inpdef.cpp @@ -7,7 +7,7 @@ extern "C" #include "../../../INCHI-1-SRC/INCHI_BASE/src/inpdef.h" } -TEST(inpdef_testing, test_CreateOrigInpDataFromMolfile_v3000_sgroup) +TEST(test_inpdef, test_CreateOrigInpDataFromMolfile_v3000_sgroup) { INCHI_IOSTREAM input_stream; diff --git a/INCHI-1-TEST/tests/test_unit/test_mol_fmt.cpp b/INCHI-1-TEST/tests/test_unit/test_mol_fmt.cpp index d663e83e..23003716 100644 --- a/INCHI-1-TEST/tests/test_unit/test_mol_fmt.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_mol_fmt.cpp @@ -7,7 +7,7 @@ extern "C" #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichi_io.h" } -TEST(mol_fmt_testing, test_MolfileStrnread) +TEST(test_mol_fmt, test_MolfileStrnread) { int string_len = 100; char dest[string_len]; @@ -26,7 +26,7 @@ TEST(mol_fmt_testing, test_MolfileStrnread) EXPECT_EQ(first_space[0], ' '); // space terminator } -TEST(mol_fmt_testing, test_MolfileReadField) +TEST(test_mol_fmt, test_MolfileReadField) { // int MolfileReadField(void *data, int field_len, int data_type, char **line_ptr) @@ -108,7 +108,7 @@ TEST(mol_fmt_testing, test_MolfileReadField) EXPECT_EQ(line_ptr8, source_data8 + 4); } -TEST(mol_fmt_testing, test_MolfileV3000ReadField) +TEST(test_mol_fmt, test_MolfileV3000ReadField) { // int MolfileV3000ReadField(void *data, @@ -126,7 +126,7 @@ TEST(mol_fmt_testing, test_MolfileV3000ReadField) EXPECT_EQ(n_coll, 2); } -TEST(mol_fmt_testing, test_MolfileExtractStrucNum) +TEST(test_mol_fmt, test_MolfileExtractStrucNum) { // long MolfileExtractStrucNum(MOL_FMT_HEADER_BLOCK *pHdr); @@ -181,7 +181,7 @@ TEST(mol_fmt_testing, test_MolfileExtractStrucNum) EXPECT_EQ(num, 0); } -TEST(mol_fmt_testing, test_MolfileV3000ReadStereoCollection) +TEST(test_mol_fmt, test_MolfileV3000ReadStereoCollection) { // int MolfileV3000ReadStereoCollection(MOL_FMT_CTAB *ctab, @@ -228,7 +228,7 @@ TEST(mol_fmt_testing, test_MolfileV3000ReadStereoCollection) inchi_free(num_list); } -TEST(mol_fmt_testing, test_MolfileV3000ReadCollections) +TEST(test_mol_fmt, test_MolfileV3000ReadCollections) { INCHI_IOSTREAM input_stream; @@ -316,7 +316,7 @@ TEST(mol_fmt_testing, test_MolfileV3000ReadCollections) inchi_ios_free_str(&input_stream); } -TEST(mol_fmt_testing, test_MolfileHasNoChemStruc) +TEST(test_mol_fmt, test_MolfileHasNoChemStruc) { MOL_FMT_DATA mfdata; MOL_FMT_CTAB ctab; @@ -360,7 +360,7 @@ TEST(mol_fmt_testing, test_MolfileHasNoChemStruc) free(atoms); } -TEST(mol_fmt_testing, test_FreeMolfileData) +TEST(test_mol_fmt, test_FreeMolfileData) { MOL_FMT_DATA *mfdata; @@ -407,7 +407,7 @@ TEST(mol_fmt_testing, test_FreeMolfileData) inchi_free(sgroups); } -TEST(mol_fmt_testing, test_ReadMolfile_v2000) +TEST(test_mol_fmt, test_ReadMolfile_v2000) { INCHI_IOSTREAM input_stream; @@ -528,7 +528,7 @@ TEST(mol_fmt_testing, test_ReadMolfile_v2000) FreeMolfileData(result); } -TEST(mol_fmt_testing, test_ReadMolfile_v3000) +TEST(test_mol_fmt, test_ReadMolfile_v3000) { INCHI_IOSTREAM input_stream; @@ -655,7 +655,7 @@ TEST(mol_fmt_testing, test_ReadMolfile_v3000) FreeMolfileData(result); } -TEST(mol_fmt_testing, test_ReadMolfile_v3000_collection_1) +TEST(test_mol_fmt, test_ReadMolfile_v3000_collection_1) { INCHI_IOSTREAM input_stream; @@ -765,7 +765,7 @@ TEST(mol_fmt_testing, test_ReadMolfile_v3000_collection_1) FreeMolfileData(result); } -TEST(mol_fmt_testing, test_ReadMolfile_v3000_collection_2) +TEST(test_mol_fmt, test_ReadMolfile_v3000_collection_2) { INCHI_IOSTREAM input_stream; diff --git a/INCHI-1-TEST/tests/test_unit/test_permutation_util.cpp b/INCHI-1-TEST/tests/test_unit/test_permutation_util.cpp index ad98e559..75da2565 100644 --- a/INCHI-1-TEST/tests/test_unit/test_permutation_util.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_permutation_util.cpp @@ -8,7 +8,7 @@ extern "C" #include "../../../INCHI-1-SRC/INCHI_BASE/src/permutation_util.h" } -TEST(permutation_util_testing, test_OrigAtData_Permute) +TEST(test_permutation_util, test_OrigAtData_Permute) { // 1. Populate atom data diff --git a/INCHI-1-TEST/tests/test_unit/test_strutil.cpp b/INCHI-1-TEST/tests/test_unit/test_strutil.cpp index d154fa4b..f09afffe 100644 --- a/INCHI-1-TEST/tests/test_unit/test_strutil.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_strutil.cpp @@ -5,7 +5,7 @@ extern "C" #include "../../../INCHI-1-SRC/INCHI_BASE/src/strutil.h" } -TEST(strutil_testing, test_ExtractConnectedComponent) +TEST(test_strutil, test_ExtractConnectedComponent) { int num_atoms = 3; @@ -27,7 +27,7 @@ TEST(strutil_testing, test_ExtractConnectedComponent) FreeInpAtom(&cmp_mol); } -TEST(strutil_testing, test_SetConnectedComponentNumber) +TEST(test_strutil, test_SetConnectedComponentNumber) { int num_atoms = 1; @@ -44,7 +44,7 @@ TEST(strutil_testing, test_SetConnectedComponentNumber) FreeInpAtom(&new_mol); } -TEST(strutil_testing, test_UnMarkRingSystemsInp) +TEST(test_strutil, test_UnMarkRingSystemsInp) { int num_atoms = 5; @@ -65,7 +65,7 @@ TEST(strutil_testing, test_UnMarkRingSystemsInp) FreeInpAtom(&new_mol); } -TEST(strutil_testing, test_CreateAndFreeInpAtom) +TEST(test_strutil, test_CreateAndFreeInpAtom) { int num_atoms = 10; @@ -96,7 +96,7 @@ TEST(strutil_testing, test_CreateAndFreeInpAtom) EXPECT_EQ(new_mol2, nullptr); } -TEST(strutil_testing, test_CreateAndFreeInpAtomData) +TEST(test_strutil, test_CreateAndFreeInpAtomData) { int num_atoms = 10; diff --git a/INCHI-1-TEST/tests/test_unit/test_util.cpp b/INCHI-1-TEST/tests/test_unit/test_util.cpp index fa9e88a8..037caa99 100644 --- a/INCHI-1-TEST/tests/test_unit/test_util.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_util.cpp @@ -5,7 +5,7 @@ extern "C" #include "../../../INCHI-1-SRC/INCHI_BASE/src/util.h" } -TEST(util_testing, test_get_chemical_symbols) +TEST(test_util, test_get_chemical_symbols) { char szElement[4]; @@ -30,7 +30,7 @@ TEST(util_testing, test_get_chemical_symbols) EXPECT_STREQ(szElement, "??"); } -TEST(util_testing, test_get_element_or_pseudoelement_symbol) +TEST(test_util, test_get_element_or_pseudoelement_symbol) { char szElement[4]; @@ -53,7 +53,7 @@ TEST(util_testing, test_get_element_or_pseudoelement_symbol) EXPECT_STREQ(szElement, "??"); } -TEST(util_testing, test_get_periodic_table_number) +TEST(test_util, test_get_periodic_table_number) { char szElement[4]; @@ -69,7 +69,7 @@ TEST(util_testing, test_get_periodic_table_number) EXPECT_EQ(get_periodic_table_number("Zz"), 120); } -TEST(util_testing, test_if_skip_add_H) +TEST(test_util, test_if_skip_add_H) { EXPECT_EQ(if_skip_add_H(-1), 0); @@ -80,7 +80,7 @@ TEST(util_testing, test_if_skip_add_H) // EXPECT_EQ(if_skip_add_H(300), 0); --> SEG FAULT } -TEST(util_testing, test_get_el_valence) +TEST(test_util, test_get_el_valence) { // nPeriodicNum, charge, val_num EXPECT_EQ(get_el_valence(0, -3, 0), 0); @@ -98,7 +98,7 @@ TEST(util_testing, test_get_el_valence) EXPECT_EQ(get_el_valence(82, -2, 2), 6); } -TEST(util_testing, test_get_atomic_mass) +TEST(test_util, test_get_atomic_mass) { EXPECT_EQ(get_atomic_mass(""), 0); EXPECT_EQ(get_atomic_mass(" "), 0); @@ -119,7 +119,7 @@ TEST(util_testing, test_get_atomic_mass) EXPECT_EQ(get_atomic_mass("Pb"), 207); } -TEST(util_testing, test_get_atomic_mass_from_elnum) +TEST(test_util, test_get_atomic_mass_from_elnum) { EXPECT_EQ(get_atomic_mass_from_elnum(-1), 0); EXPECT_EQ(get_atomic_mass_from_elnum(0), 0); @@ -140,7 +140,7 @@ TEST(util_testing, test_get_atomic_mass_from_elnum) EXPECT_EQ(get_atomic_mass_from_elnum(23423423), 0); } -TEST(util_testing, test_get_el_type) +TEST(test_util, test_get_el_type) { EXPECT_EQ(get_el_type(-1), 0); EXPECT_EQ(get_el_type(0), 0); @@ -163,7 +163,7 @@ TEST(util_testing, test_get_el_type) // EXPECT_EQ(get_el_type(23423423), 0); --> seg fault } -TEST(util_testing, test_is_el_a_metal) +TEST(test_util, test_is_el_a_metal) { EXPECT_EQ(is_el_a_metal(-1), false); EXPECT_EQ(is_el_a_metal(0), false); @@ -187,7 +187,7 @@ TEST(util_testing, test_is_el_a_metal) // --------------------------- // lrtrim -TEST(util_testing, test_lrtrim) +TEST(test_util, test_lrtrim) { char test_string1[7] = " InChI"; @@ -209,7 +209,7 @@ TEST(util_testing, test_lrtrim) // --------------------------- // extract_H_atoms( char *elname, S_CHAR num_iso_H[] ) -TEST(util_testing, test_extract_H_atoms) +TEST(test_util, test_extract_H_atoms) { S_CHAR num_iso_H[NUM_H_ISOTOPES] = {0}; @@ -247,7 +247,7 @@ TEST(util_testing, test_extract_H_atoms) EXPECT_EQ(extract_H_atoms(elname, num_iso_H), 0); } -TEST(util_testing, test_get_num_H) +TEST(test_util, test_get_num_H) { // const char *elname, int inp_num_H, S_CHAR *num_iso_H, int charge, int radical, // int chem_bonds_valence, int atom_input_valence, int bAliased, int bDoNotAddH, int bHasMetalNeighbor @@ -257,7 +257,7 @@ TEST(util_testing, test_get_num_H) EXPECT_EQ(get_num_H("C", 0, num_iso_H, 0, 0, 0, 0, 0, 0, 0), 4); } -TEST(util_testing, test_get_unusual_el_valence) +TEST(test_util, test_get_unusual_el_valence) { EXPECT_EQ(get_unusual_el_valence(0, 0, 0, 0, 0, 0), 0); EXPECT_EQ(get_unusual_el_valence(6, 0, 0, 4, 0, 0), 0); @@ -267,7 +267,7 @@ TEST(util_testing, test_get_unusual_el_valence) EXPECT_EQ(get_unusual_el_valence(82, -2, 2, 6, 3, 3), 9); } -TEST(util_testing, test_detect_unusual_el_valence) +TEST(test_util, test_detect_unusual_el_valence) { // nPeriodicNum, charge, radical, bonds_valence, num_H, num_bonds EXPECT_EQ(detect_unusual_el_valence(0, 0, 0, 0, 0, 0), 0); @@ -278,7 +278,7 @@ TEST(util_testing, test_detect_unusual_el_valence) EXPECT_EQ(detect_unusual_el_valence(82, -2, 2, 6, 3, 3), 9); } -TEST(util_testing, test_normalize_string) +TEST(test_util, test_normalize_string) { char test_string1[7] = " InChI"; EXPECT_EQ(normalize_string(test_string1), 5); @@ -297,7 +297,7 @@ TEST(util_testing, test_normalize_string) EXPECT_STREQ(test_string4, "sdfds sfsfd ew"); } -TEST(util_testing, test_read_upto_delim) +TEST(test_util, test_read_upto_delim) { // read_upto_delim(char **pstring, char *field, int maxlen, char *delims) @@ -349,7 +349,7 @@ TEST(util_testing, test_read_upto_delim) EXPECT_STREQ(test_string6_inp, "field1,field2,field3"); } -TEST(util_testing, test_is_matching_any_delim) +TEST(test_util, test_is_matching_any_delim) { char delims1[] = "abc"; @@ -366,7 +366,7 @@ TEST(util_testing, test_is_matching_any_delim) EXPECT_FALSE(is_matching_any_delim('a', delims2)); } -TEST(util_testing, test_dotify_non_printable_chars) +TEST(test_util, test_dotify_non_printable_chars) { // dotify_non_printable_chars(char *line) char test_string1[] = "Hello\x01World"; @@ -382,7 +382,7 @@ TEST(util_testing, test_dotify_non_printable_chars) EXPECT_STREQ(test_string3, "NoChange"); } -TEST(util_testing, test_remove_trailing_spaces) +TEST(test_util, test_remove_trailing_spaces) { // remove_trailing_spaces(char *p) char test_string1[] = "Hello World "; @@ -394,7 +394,7 @@ TEST(util_testing, test_remove_trailing_spaces) EXPECT_STREQ(test_string3, "NoTrailingSpaces"); } -TEST(util_testing, test_remove_one_lf) +TEST(test_util, test_remove_one_lf) { // remove_one_lf(char *p) char test_string1[] = "Hello World\n"; @@ -422,7 +422,7 @@ TEST(util_testing, test_remove_one_lf) EXPECT_STREQ(test_string6, ""); } -TEST(util_testing, test_mystrncpy) +TEST(test_util, test_mystrncpy) { // mystrncpy(char *target, const char *source, unsigned maxlen) char target[20]; @@ -440,7 +440,7 @@ TEST(util_testing, test_mystrncpy) EXPECT_EQ(mystrncpy(NULL, source, 10), 0); // target is NULL } -TEST(util_testing, test_inchi_memicmp) +TEST(test_util, test_inchi_memicmp) { // inchi_memicmp(const void *p1, const void *p2, size_t length) @@ -471,7 +471,7 @@ TEST(util_testing, test_inchi_memicmp) EXPECT_TRUE(inchi_memicmp(str9, str10, 20) > 0); } -TEST(util_testing, test_inchi_stricmp) +TEST(test_util, test_inchi_stricmp) { // inchi_stricmp(const char *s1, const char *s2) @@ -485,7 +485,7 @@ TEST(util_testing, test_inchi_stricmp) EXPECT_TRUE(inchi_stricmp("123", "12455454") < 0); } -TEST(util_testing, test_inchi_strnset) +TEST(test_util, test_inchi_strnset) { // char *inchi__strnset(char *s, int val, size_t length) @@ -499,7 +499,7 @@ TEST(util_testing, test_inchi_strnset) EXPECT_STREQ(inchi__strnset(test_string3, 'Z', 0), "NoChange"); } -TEST(util_testing, test_inchi_strdup) +TEST(test_util, test_inchi_strdup) { // char *inchi__strdup(const char *string) @@ -512,7 +512,7 @@ TEST(util_testing, test_inchi_strdup) free(dup2); } -TEST(util_testing, test_inchi_strtol) +TEST(test_util, test_inchi_strtol) { // long inchi_strtol(const char *str, const char **p, int base) @@ -525,7 +525,7 @@ TEST(util_testing, test_inchi_strtol) EXPECT_EQ(result2, 0); } -TEST(util_testing, test_inchi_strtod) +TEST(test_util, test_inchi_strtod) { // double inchi_strtod(const char *str, const char **p) @@ -539,7 +539,7 @@ TEST(util_testing, test_inchi_strtod) EXPECT_EQ(*endptr, 'a'); } -TEST(util_testing, test_is_in_the_list) +TEST(test_util, test_is_in_the_list) { // AT_NUMB *is_in_the_list(AT_NUMB *pathAtom, AT_NUMB nNextAtom, int nPathLen) @@ -559,7 +559,7 @@ TEST(util_testing, test_is_in_the_list) EXPECT_FALSE(is_in_the_list(pathAtom3, nNextAtom3, nPathLen3)); } -TEST(util_testing, test_is_in_the_ilist) +TEST(test_util, test_is_in_the_ilist) { // int *is_in_the_ilist(int *pathAtom, int nNextAtom, int nPathLen) @@ -580,7 +580,7 @@ TEST(util_testing, test_is_in_the_ilist) EXPECT_FALSE(is_in_the_ilist(pathAtom3, nNextAtom3, nPathLen3)); } -TEST(util_testing, test_is_ilist_inside) +TEST(test_util, test_is_ilist_inside) { // int is_ilist_inside(int *ilist, int nlist, int *ilist2, int nlist2) @@ -599,7 +599,7 @@ TEST(util_testing, test_is_ilist_inside) EXPECT_TRUE(is_ilist_inside(pathAtom4, 0, pathAtom5, 0)); } -TEST(util_testing, test_nBondsValToMetal) +TEST(test_util, test_nBondsValToMetal) { // int nBondsValToMetal(inp_ATOM *at, int iat) @@ -656,7 +656,7 @@ TEST(util_testing, test_nBondsValToMetal) FreeInpAtom(&atoms2); } -TEST(util_testing, test_num_of_H) +TEST(test_util, test_num_of_H) { // int num_of_H(inp_ATOM *at, int iat) @@ -734,7 +734,7 @@ TEST(util_testing, test_num_of_H) FreeInpAtom(&atoms2); } -TEST(util_testing, test_ion_el_group) +TEST(test_util, test_ion_el_group) { // U_CHAR ion_el_group(int el) @@ -744,7 +744,7 @@ TEST(util_testing, test_ion_el_group) EXPECT_EQ(ion_el_group(get_periodic_table_number("Mn")), 0); } -TEST(util_testing, test_has_other_ion_neigh) +TEST(test_util, test_has_other_ion_neigh) { // int has_other_ion_neigh(inp_ATOM *at, int iat, int iat_ion_neigh) @@ -765,7 +765,7 @@ TEST(util_testing, test_has_other_ion_neigh) FreeInpAtom(&atoms1); } -TEST(util_testing, test_extract_charges_and_radicals) +TEST(test_util, test_extract_charges_and_radicals) { // int extract_charges_and_radicals(char *elname, int *pnRadical, int *pnCharge) @@ -849,7 +849,7 @@ TEST(util_testing, test_extract_charges_and_radicals) EXPECT_EQ(nCharge, 0); } -TEST(util_testing, test_extract_inchi_substring) +TEST(test_util, test_extract_inchi_substring) { // void extract_inchi_substring(char **buf, const char *str, size_t slen) @@ -882,7 +882,7 @@ TEST(util_testing, test_extract_inchi_substring) free(buf2); } -TEST(util_testing, test_extract_auxinfo_substring) +TEST(test_util, test_extract_auxinfo_substring) { // void extract_auxinfo_substring(char **buf, const char *str, size_t slen) @@ -928,7 +928,7 @@ TEST(util_testing, test_extract_auxinfo_substring) free(buf4); } -TEST(util_testing, test_extract_stereo_info_from_inchi_string) +TEST(test_util, test_extract_stereo_info_from_inchi_string) { // int extract_stereo_info_from_inchi_string(char *sinchi, int nat, int *orig, int *at_stereo_mark); @@ -979,7 +979,7 @@ TEST(util_testing, test_extract_stereo_info_from_inchi_string) EXPECT_EQ(found_stereo2, 0); } -// TEST(util_testing, test_extract_all_backbone_bonds_from_inchi_string) +// TEST(test_util, test_extract_all_backbone_bonds_from_inchi_string) // { // // int extract_all_backbone_bonds_from_inchi_string(char *sinchi, int *n_all_bkb_orig, int *orig, int *all_bkb_orig); From bc49dcaa467c4c0d21d254d69394964c6517d9d0 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 22 Dec 2025 14:32:56 +0000 Subject: [PATCH 44/69] New units for enh stereochemistry --- INCHI-1-SRC/INCHI_BASE/src/ichimake.c | 25 ++-- INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c | 18 +-- .../tests/test_unit/test_ichimake.cpp | 90 ++++++++++++++ .../tests/test_unit/test_ichiprt1.cpp | 110 +++++++++++++++++- .../tests/test_unit/test_ichiprt2.cpp | 68 +++++++++++ .../tests/test_unit/test_ichiprt3.cpp | 52 +++++++++ 6 files changed, 341 insertions(+), 22 deletions(-) create mode 100644 INCHI-1-TEST/tests/test_unit/test_ichimake.cpp create mode 100644 INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp create mode 100644 INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichimake.c b/INCHI-1-SRC/INCHI_BASE/src/ichimake.c index e478e55b..37ddab42 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichimake.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichimake.c @@ -608,22 +608,21 @@ int GetSp3RelRacAbs(const INChI* pINChI, INChI_Stereo* Stereo) nRet = SP3_REL; #endif } - else - if (pINChI->nFlags & INCHI_FLAG_RAC_STEREO) - { + else if (pINChI->nFlags & INCHI_FLAG_RAC_STEREO) + { #if ( REL_RAC_STEREO_IGN_1_SC == 1 ) - if (1 < Stereo->nNumberOfStereoCenters) - { - nRet = SP3_REL; - } -#else - nRet = SP3_RAC; -#endif - } - else + if (1 < Stereo->nNumberOfStereoCenters) { - nRet = SP3_ABS; + nRet = SP3_REL; } +#else + nRet = SP3_RAC; +#endif + } + else + { + nRet = SP3_ABS; + } } else #if ( REL_RAC_STEREO_IGN_1_SC == 1 ) diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c index 672ba198..23aba0d8 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c @@ -3359,11 +3359,9 @@ int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, char *pTAB ) { - { - int i; - i = INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_t_SATOMS] ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ - /* djb-rwth: removing redundant code */ - } + // int i; + // i = INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_t_SATOMS] ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ + // /* djb-rwth: removing redundant code */ if (INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_b_SBONDS] ) || INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_t_SATOMS] ) || @@ -3432,7 +3430,10 @@ int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, } else { - if (io->bPlainTextTags == 1) inchi_ios_print_nodisplay( out_file, "/" ); /* sp3 */ + if (io->bPlainTextTags == 1) + { + inchi_ios_print_nodisplay( out_file, "/" ); /* sp3 */ + } } /* bStereoAbsInverted[io->iCurTautMode] */ @@ -3490,7 +3491,10 @@ int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, } else { - if (io->bPlainTextTags == 1) inchi_ios_print_nodisplay( out_file, "////" ); /* sp3, sp2, abs-inv, stereo.type */ + if (io->bPlainTextTags == 1) + { + inchi_ios_print_nodisplay( out_file, "////" ); /* sp3, sp2, abs-inv, stereo.type */ + } } return 0; diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimake.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimake.cpp new file mode 100644 index 00000000..94a2c69a --- /dev/null +++ b/INCHI-1-TEST/tests/test_unit/test_ichimake.cpp @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include +#include +#include + +extern "C" +{ +#include "../../../INCHI-1-SRC/INCHI_BASE/src/ichimake.c" +#include "../../../INCHI-1-SRC/INCHI_BASE/src/ichi_io.h" +} + +TEST(test_ichimake, test_GetSp3RelRacAbs_none) +{ + + INChI inchi = {0}; + INChI_Stereo stereo = {0}; + + stereo.nNumberOfStereoCenters = 0; + + // pINChI->bDeleted + // Stereo->nCompInv2Abs + // 0: No inversion (structure unchanged by inversion) + // Positive integer (>0): Indicates inversion changes the structure (normal/absolute stereo) + // Negative integer (<0): Indicates inversion changes the structure (inverted/absolute stereo) + + //int GetSp3RelRacAbs(const INChI* pINChI, INChI_Stereo* Stereo); + + int result = GetSp3RelRacAbs(&inchi, &stereo); + + EXPECT_EQ(result, SP3_NONE); + +} + +TEST(test_ichimake, test_GetSp3RelRacAbs_sp3) +{ + INChI inchi = {0}; + INChI_Stereo stereo = {0}; + + stereo.nNumberOfStereoCenters = 1; + stereo.nCompInv2Abs = 0; + + int result = GetSp3RelRacAbs(&inchi, &stereo); + + EXPECT_EQ(result, SP3_ONLY); +} + +TEST(test_ichimake, test_GetSp3RelRacAbs_rel) +{ + INChI inchi = {0}; + INChI_Stereo stereo = {0}; + + inchi.nFlags = INCHI_FLAG_REL_STEREO; + stereo.nNumberOfStereoCenters = 1; + stereo.nCompInv2Abs = 1; + + int result = GetSp3RelRacAbs(&inchi, &stereo); + + EXPECT_EQ(result, SP3_REL); +} + +TEST(test_ichimake, test_GetSp3RelRacAbs_rac) +{ + INChI inchi = {0}; + INChI_Stereo stereo = {0}; + + inchi.nFlags = INCHI_FLAG_RAC_STEREO; + stereo.nNumberOfStereoCenters = 1; + stereo.nCompInv2Abs = 1; + + int result = GetSp3RelRacAbs(&inchi, &stereo); + + EXPECT_EQ(result, SP3_RAC); +} + +TEST(test_ichimake, test_GetSp3RelRacAbs_abs) +{ + INChI inchi = {0}; + INChI_Stereo stereo = {0}; + + inchi.nFlags = 0x0111; + stereo.nNumberOfStereoCenters = 1; + stereo.nCompInv2Abs = 1; + + int result = GetSp3RelRacAbs(&inchi, &stereo); + + EXPECT_EQ(result, SP3_ABS); +} diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp index db96f282..866b0e98 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp @@ -8,8 +8,6 @@ extern "C" { -// #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichitime.h" -// #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichicant.h" #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichi_io.h" #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c" } @@ -49,6 +47,114 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer) } +TEST(test_ichiprt1, OutputINCHI_StereoLayer_s1) +{ + // Prepare minimal input structures + CANON_GLOBALS cg = {0}; + INCHI_IOSTREAM out_file = {0}; + INCHI_IOS_STRING strbuf = {0}; + INCHI_OUT_CTL io = {0}; + + // Set up io to trigger the /s (stereo type) segment + io.sDifSegs[0][DIFS_s_STYPE] = DIFV_OUTPUT_FILL_T; // nonzero triggers INChI_SegmentAction + + + io.nCurINChISegment = 0; + io.iCurTautMode = 0; + io.bPlainTextTags = 1; + io.bRelativeStereo[0] = 0; + io.bRacemicStereo[0] = 0; + io.bAlways = 0; + io.nTag = 2; // plain text + io.bTag1 = IL_STER; + io.bTag2 = IL_STER | IL_TYPS; + + // Allocate strbuf + char buf[16] = {0}; + strbuf.pStr = buf; + strbuf.nAllocatedLength = sizeof(buf); + strbuf.nUsedLength = 0; + + // Call function + int ret = OutputINCHI_StereoLayer(&cg, &out_file, &strbuf, &io, (char*)"", (char*)""); + + // The stereo type should be "s1" (plain tag + abs) + EXPECT_EQ(std::string(strbuf.pStr), "/s1"); + EXPECT_EQ(ret, 0); +} + +TEST(test_ichiprt1, OutputINCHI_StereoLayer_s2) +{ + // Prepare minimal input structures + CANON_GLOBALS cg = {0}; + INCHI_IOSTREAM out_file = {0}; + INCHI_IOS_STRING strbuf = {0}; + INCHI_OUT_CTL io = {0}; + + // Set up io to trigger the /s (stereo type) segment + io.sDifSegs[0][DIFS_s_STYPE] = DIFV_OUTPUT_FILL_T; // nonzero triggers INChI_SegmentAction + + + io.nCurINChISegment = 0; + io.iCurTautMode = 0; + io.bPlainTextTags = 1; + io.bRelativeStereo[0] = 1; + io.bRacemicStereo[0] = 0; + io.bAlways = 0; + io.nTag = 2; // plain text + io.bTag1 = IL_STER; + io.bTag2 = IL_STER | IL_TYPS; + + // Allocate strbuf + char buf[16] = {0}; + strbuf.pStr = buf; + strbuf.nAllocatedLength = sizeof(buf); + strbuf.nUsedLength = 0; + + // Call function + int ret = OutputINCHI_StereoLayer(&cg, &out_file, &strbuf, &io, (char*)"", (char*)""); + + // The stereo type should be "s1" (plain tag + abs) + EXPECT_EQ(std::string(strbuf.pStr), "/s2"); + EXPECT_EQ(ret, 0); +} + +TEST(test_ichiprt1, OutputINCHI_StereoLayer_s3) +{ + // Prepare minimal input structures + CANON_GLOBALS cg = {0}; + INCHI_IOSTREAM out_file = {0}; + INCHI_IOS_STRING strbuf = {0}; + INCHI_OUT_CTL io = {0}; + + // Set up io to trigger the /s (stereo type) segment + io.sDifSegs[0][DIFS_s_STYPE] = DIFV_OUTPUT_FILL_T; // nonzero triggers INChI_SegmentAction + + + io.nCurINChISegment = 0; + io.iCurTautMode = 0; + io.bPlainTextTags = 1; + io.bRelativeStereo[0] = 0; + io.bRacemicStereo[0] = 1; + io.bAlways = 0; + io.nTag = 2; // plain text + io.bTag1 = IL_STER; + io.bTag2 = IL_STER | IL_TYPS; + + // Allocate strbuf + char buf[16] = {0}; + strbuf.pStr = buf; + strbuf.nAllocatedLength = sizeof(buf); + strbuf.nUsedLength = 0; + + // Call function + int ret = OutputINCHI_StereoLayer(&cg, &out_file, &strbuf, &io, (char*)"", (char*)""); + + // The stereo type should be "s1" (plain tag + abs) + EXPECT_EQ(std::string(strbuf.pStr), "/s3"); + EXPECT_EQ(ret, 0); +} + TEST(test_ichiprt1, test_set_line_separators) { diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp new file mode 100644 index 00000000..18be185a --- /dev/null +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp @@ -0,0 +1,68 @@ +#include +#include + +extern "C" +{ +#include "../../../INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c" +#include "../../../INCHI-1-SRC/INCHI_BASE/src/ichi_io.h" +} + +TEST(test_ichiprt2, MakeStereoString_outputs_expected_sp3_string) +{ + // Prepare input arrays for 8 stereo centers + AT_NUMB at1[8] = {3,4,5,6,7,8,9,10}; + AT_NUMB at2[8] = {0}; // Not used in this test, can be NULL + // S_CHAR parity[8] = {1,-1,1,1,-1,1,1,-1}; // +,-,+,+,-,+,+,- + // S_CHAR parity[8] = {-1, -1, 1, 1, -1, 1, 1, -1}; + S_CHAR parity[8] = {1,1,2,2,1,2,2,1}; + + // Prepare strbuf (empty) + INCHI_IOS_STRING strbuf = {0}; + char buf[128] = {0}; + strbuf.pStr = buf; + strbuf.nAllocatedLength = sizeof(buf); + strbuf.nUsedLength = 0; + + // Call MakeStereoString + int bOverflow = 0; + int ret = MakeStereoString(at1, NULL, parity, 0, 8, &strbuf, 0, &bOverflow); + + // Check that strbuf contains the expected substring + EXPECT_EQ(strbuf.nUsedLength, strlen(strbuf.pStr)); + EXPECT_NE(std::string(strbuf.pStr).find("3-,4-,5+,6+,7-,8+,9+,10-"), std::string::npos); + EXPECT_EQ(strbuf.pStr[0], '3'); // Should start with 3- + EXPECT_EQ(bOverflow, 0); +} + +TEST(test_ichiprt2, MakeMult_mult_gt_1_appends_number_and_delim) +{ + INCHI_IOS_STRING strbuf = {0}; + char buf[32] = {0}; + strbuf.pStr = buf; + strbuf.nAllocatedLength = sizeof(buf); + strbuf.nUsedLength = 0; + + int bOverflow = 0; + int ret = MakeMult(5, "-", &strbuf, 0, &bOverflow); + + EXPECT_EQ(std::string(strbuf.pStr), "5-"); + EXPECT_EQ(ret, 2); // "3-".length() == 2, but MakeMult returns n (number of chars written) + EXPECT_EQ(bOverflow, 0); +} + +TEST(test_ichiprt2, MakeMult_mult_eq_1_does_nothing) +{ + INCHI_IOS_STRING strbuf = {0}; + char buf[32] = {0}; + strcpy(buf, "start"); + strbuf.pStr = buf; + strbuf.nAllocatedLength = sizeof(buf); + strbuf.nUsedLength = strlen(buf); + + int bOverflow = 0; + int ret = MakeMult(1, "-", &strbuf, 0, &bOverflow); + + EXPECT_EQ(std::string(strbuf.pStr), "start"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(bOverflow, 0); +} diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp new file mode 100644 index 00000000..4b1a8afc --- /dev/null +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp @@ -0,0 +1,52 @@ +#include +#include + +extern "C" +{ +#include "../../../INCHI-1-SRC/INCHI_BASE/src/ichiprt3.c" +#include "../../../INCHI-1-SRC/INCHI_BASE/src/ichi_io.h" +} + +TEST(test_ichiprt3, test_str_Sp3_outputs_expected_sp3_string) +{ + // Prepare INChI_Stereo with 8 stereo centers and their parities + INChI_Stereo stereo = {0}; + + stereo.nNumberOfStereoCenters = 8; + stereo.t_parity = (S_CHAR*)inchi_calloc((long long)stereo.nNumberOfStereoCenters, sizeof(S_CHAR)); + stereo.nNumber = (AT_NUMB*)inchi_calloc((long long)stereo.nNumberOfStereoCenters, sizeof(AT_NUMB)); + + int numbers[8] = {3,4,5,6,7,8,9,10}; + S_CHAR parities[8] = {1,1,2,2,1,2,2,1}; + + + for (int i = 0; i < 8; i++) { + stereo.nNumber[i] = numbers[i]; + stereo.t_parity[i] = parities[i]; + } + + // Prepare INChI and INCHI_SORT + INChI inchi = {0}; + inchi.nNumberOfAtoms = 10; + inchi.Stereo = &stereo; + + INCHI_SORT sort = {0}; + sort.pINChI[0] = &inchi; + + // Prepare strbuf (empty) + INCHI_IOS_STRING strbuf = {0}; + char buf[128] = {0}; + strbuf.pStr = buf; + strbuf.nAllocatedLength = sizeof(buf); + strbuf.nUsedLength = 0; + + // Call str_Sp3 + int bOverflow = 0; + int ret = str_Sp3(&sort, NULL, &strbuf, &bOverflow, 0, 0, 1, 0, 0, 0, 0); + + // Check that strbuf contains the expected substring + EXPECT_EQ(strbuf.nUsedLength, strlen(strbuf.pStr)); + EXPECT_NE(std::string(strbuf.pStr).find("3-,4-,5+,6+,7-,8+,9+,10-"), std::string::npos); + EXPECT_EQ(strbuf.pStr[0], '3'); // Should start with 3- + EXPECT_EQ(bOverflow, 0); +} From 0cf17b972fac9244099be9b952105e80ae56de3f Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Tue, 23 Dec 2025 15:31:33 +0000 Subject: [PATCH 45/69] Added/corrected unit tests for enh stereo --- .../tests/test_unit/test_ichimain.cpp | 1 - .../tests/test_unit/test_ichiprt1.cpp | 121 +++++++++++++++--- .../tests/test_unit/test_ichiprt2.cpp | 30 ++--- .../tests/test_unit/test_ichiprt3.cpp | 41 +++--- 4 files changed, 138 insertions(+), 55 deletions(-) diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index b6f266bb..ea2c2618 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -191,7 +191,6 @@ TEST(test_ichimain, test_CalcAndPrintINCHIAndINCHIKEY) { PINChI_Aux2* pINChI_Aux[INCHI_NUM] = {}; ORIG_ATOM_DATA prep_inp_data = {}; INCHI_IOS_STRING *strbuf = new INCHI_IOS_STRING; - memset(strbuf, 0, sizeof(*strbuf)); inchi_strbuf_init(strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); unsigned long pulTotalProcessingTime = 0; diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp index 866b0e98..b11d45bc 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp @@ -10,6 +10,9 @@ extern "C" { #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichi_io.h" #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c" +#include "../../../INCHI-1-SRC/INCHI_BASE/src/strutil.c" +#include "../../../INCHI-1-SRC/INCHI_BASE/src/ichimake.h" +#include "../../../INCHI-1-SRC/INCHI_BASE/src/ichicano.h" } @@ -27,6 +30,7 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer) // Initialize string buffer (simulate allocation) // inchi_strbuf_init(&strbuf, 128, 128); inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + inchi_ios_init(&out_file, INCHI_IOS_TYPE_STRING, nullptr); // int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, // INCHI_IOSTREAM *out_file, @@ -47,7 +51,7 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer) } -TEST(test_ichiprt1, OutputINCHI_StereoLayer_s1) +TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_s1) { // Prepare minimal input structures CANON_GLOBALS cg = {0}; @@ -58,7 +62,6 @@ TEST(test_ichiprt1, OutputINCHI_StereoLayer_s1) // Set up io to trigger the /s (stereo type) segment io.sDifSegs[0][DIFS_s_STYPE] = DIFV_OUTPUT_FILL_T; // nonzero triggers INChI_SegmentAction - io.nCurINChISegment = 0; io.iCurTautMode = 0; io.bPlainTextTags = 1; @@ -69,11 +72,8 @@ TEST(test_ichiprt1, OutputINCHI_StereoLayer_s1) io.bTag1 = IL_STER; io.bTag2 = IL_STER | IL_TYPS; - // Allocate strbuf - char buf[16] = {0}; - strbuf.pStr = buf; - strbuf.nAllocatedLength = sizeof(buf); - strbuf.nUsedLength = 0; + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + inchi_ios_init(&out_file, INCHI_IOS_TYPE_STRING, nullptr); // Call function int ret = OutputINCHI_StereoLayer(&cg, &out_file, &strbuf, &io, (char*)"", (char*)""); @@ -81,9 +81,12 @@ TEST(test_ichiprt1, OutputINCHI_StereoLayer_s1) // The stereo type should be "s1" (plain tag + abs) EXPECT_EQ(std::string(strbuf.pStr), "/s1"); EXPECT_EQ(ret, 0); + + inchi_strbuf_close(&strbuf); + inchi_ios_close(&out_file); } -TEST(test_ichiprt1, OutputINCHI_StereoLayer_s2) +TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_s2) { // Prepare minimal input structures CANON_GLOBALS cg = {0}; @@ -105,11 +108,8 @@ TEST(test_ichiprt1, OutputINCHI_StereoLayer_s2) io.bTag1 = IL_STER; io.bTag2 = IL_STER | IL_TYPS; - // Allocate strbuf - char buf[16] = {0}; - strbuf.pStr = buf; - strbuf.nAllocatedLength = sizeof(buf); - strbuf.nUsedLength = 0; + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + inchi_ios_init(&out_file, INCHI_IOS_TYPE_STRING, nullptr); // Call function int ret = OutputINCHI_StereoLayer(&cg, &out_file, &strbuf, &io, (char*)"", (char*)""); @@ -117,9 +117,12 @@ TEST(test_ichiprt1, OutputINCHI_StereoLayer_s2) // The stereo type should be "s1" (plain tag + abs) EXPECT_EQ(std::string(strbuf.pStr), "/s2"); EXPECT_EQ(ret, 0); + + inchi_strbuf_close(&strbuf); + inchi_ios_close(&out_file); } -TEST(test_ichiprt1, OutputINCHI_StereoLayer_s3) +TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_s3) { // Prepare minimal input structures CANON_GLOBALS cg = {0}; @@ -141,11 +144,8 @@ TEST(test_ichiprt1, OutputINCHI_StereoLayer_s3) io.bTag1 = IL_STER; io.bTag2 = IL_STER | IL_TYPS; - // Allocate strbuf - char buf[16] = {0}; - strbuf.pStr = buf; - strbuf.nAllocatedLength = sizeof(buf); - strbuf.nUsedLength = 0; + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + inchi_ios_init(&out_file, INCHI_IOS_TYPE_STRING, nullptr); // Call function int ret = OutputINCHI_StereoLayer(&cg, &out_file, &strbuf, &io, (char*)"", (char*)""); @@ -153,6 +153,89 @@ TEST(test_ichiprt1, OutputINCHI_StereoLayer_s3) // The stereo type should be "s1" (plain tag + abs) EXPECT_EQ(std::string(strbuf.pStr), "/s3"); EXPECT_EQ(ret, 0); + + inchi_strbuf_close(&strbuf); + inchi_ios_close(&out_file); +} + +TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_enh_stereo_1) +{ + // --- Setup CANON_GLOBALS and INChI/INChI_Stereo for enhanced stereo --- + CANON_GLOBALS cg = {0}; + INCHI_IOSTREAM out_file = {0}; + INCHI_IOS_STRING strbuf = {0}; + INCHI_OUT_CTL io = {0}; + + int num_at = 8; + int num_bonds = 0; + static AT_NUMB numbers[8] = {3,4,5,6,7,8,9,10}; + static S_CHAR parities[8] = {1,1,2,2,1,2,2,1};// -,-,+,+,-,+,+,- + + static S_CHAR m_values[1] = {0}; // /m0 + static S_CHAR s_values[1] = {1}; // /s1 + + // static INChI_Stereo stereo = {0}; + + static INChI_Stereo *stereo = Alloc_INChI_Stereo( num_at, num_bonds ); + + stereo->nNumberOfStereoCenters = 8; + + for (int i = 0; i < num_at; i++) { + stereo->nNumber[i] = numbers[i]; + stereo->t_parity[i] = parities[i]; + } + + stereo->nCompInv2Abs = 1; + stereo->nNumberOfStereoBonds = 0; + stereo->b_parity = NULL; + + // INChI *inchi = new INChI; + // inchi->nNumberOfAtoms = num_at; + // inchi->Stereo = stereo; + + int found_num_bonds = 0; + int found_num_isotopic = 0; + inp_ATOM *at = CreateInpAtom(num_at); + static INChI *inchi = Alloc_INChI(at, num_at, &found_num_bonds, &found_num_isotopic, 0); + + inchi->nNumberOfAtoms = num_at; + inchi->Stereo = stereo; + + static INCHI_SORT sort = {0}; + sort.pINChI[0] = inchi; + + io.pINChISort = &sort; + + // --- Setup io to trigger stereo output --- + io.num_components = 1; + io.bRelativeStereo[0] = 0; + io.bRacemicStereo[0] = 1; + + io.sDifSegs[0][DIFS_t_SATOMS] = DIFV_OUTPUT_FILL_T; + io.sDifSegs[0][DIFS_m_SP3INV] = DIFV_OUTPUT_FILL_T; + io.sDifSegs[0][DIFS_s_STYPE] = DIFV_OUTPUT_FILL_T; + io.nCurINChISegment = 0; + io.iCurTautMode = 0; + io.bPlainTextTags = 1; + io.nTag = 2; + io.bTag1 = IL_STER; + io.bTag2 = IL_STER | IL_TYPS; + io.bOutType = OUT_TN; + + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + inchi_ios_init(&out_file, INCHI_IOS_TYPE_STRING, nullptr); + + int ret = OutputINCHI_StereoLayer(&cg, &out_file, &strbuf, &io, (char*)"", (char*)""); + + EXPECT_EQ(std::string(out_file.s.pStr), "//t3-,4-,5+,6+,7-,8+,9+,10-/m0/s3/"); + EXPECT_EQ(ret, 0); + + inchi_strbuf_close(&strbuf); + inchi_ios_close(&out_file); + + FreeInpAtom(&at); + // Free_INChI(&inchi); + Free_INChI_Stereo(stereo); } TEST(test_ichiprt1, test_set_line_separators) diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp index 18be185a..0800ef1b 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp @@ -11,36 +11,31 @@ TEST(test_ichiprt2, MakeStereoString_outputs_expected_sp3_string) { // Prepare input arrays for 8 stereo centers AT_NUMB at1[8] = {3,4,5,6,7,8,9,10}; - AT_NUMB at2[8] = {0}; // Not used in this test, can be NULL - // S_CHAR parity[8] = {1,-1,1,1,-1,1,1,-1}; // +,-,+,+,-,+,+,- - // S_CHAR parity[8] = {-1, -1, 1, 1, -1, 1, 1, -1}; S_CHAR parity[8] = {1,1,2,2,1,2,2,1}; // Prepare strbuf (empty) INCHI_IOS_STRING strbuf = {0}; - char buf[128] = {0}; - strbuf.pStr = buf; - strbuf.nAllocatedLength = sizeof(buf); - strbuf.nUsedLength = 0; + + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); // Call MakeStereoString int bOverflow = 0; - int ret = MakeStereoString(at1, NULL, parity, 0, 8, &strbuf, 0, &bOverflow); + int ret = MakeStereoString(at1, nullptr, parity, 0, 8, &strbuf, 0, &bOverflow); // Check that strbuf contains the expected substring EXPECT_EQ(strbuf.nUsedLength, strlen(strbuf.pStr)); EXPECT_NE(std::string(strbuf.pStr).find("3-,4-,5+,6+,7-,8+,9+,10-"), std::string::npos); EXPECT_EQ(strbuf.pStr[0], '3'); // Should start with 3- EXPECT_EQ(bOverflow, 0); + EXPECT_EQ(ret, 24); + + inchi_strbuf_close(&strbuf); } TEST(test_ichiprt2, MakeMult_mult_gt_1_appends_number_and_delim) { INCHI_IOS_STRING strbuf = {0}; - char buf[32] = {0}; - strbuf.pStr = buf; - strbuf.nAllocatedLength = sizeof(buf); - strbuf.nUsedLength = 0; + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); int bOverflow = 0; int ret = MakeMult(5, "-", &strbuf, 0, &bOverflow); @@ -48,16 +43,15 @@ TEST(test_ichiprt2, MakeMult_mult_gt_1_appends_number_and_delim) EXPECT_EQ(std::string(strbuf.pStr), "5-"); EXPECT_EQ(ret, 2); // "3-".length() == 2, but MakeMult returns n (number of chars written) EXPECT_EQ(bOverflow, 0); + + inchi_strbuf_close(&strbuf); } TEST(test_ichiprt2, MakeMult_mult_eq_1_does_nothing) { INCHI_IOS_STRING strbuf = {0}; - char buf[32] = {0}; - strcpy(buf, "start"); - strbuf.pStr = buf; - strbuf.nAllocatedLength = sizeof(buf); - strbuf.nUsedLength = strlen(buf); + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + inchi_strbuf_printf(&strbuf, "start"); int bOverflow = 0; int ret = MakeMult(1, "-", &strbuf, 0, &bOverflow); @@ -65,4 +59,6 @@ TEST(test_ichiprt2, MakeMult_mult_eq_1_does_nothing) EXPECT_EQ(std::string(strbuf.pStr), "start"); EXPECT_EQ(ret, 0); EXPECT_EQ(bOverflow, 0); + + inchi_strbuf_close(&strbuf); } diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp index 4b1a8afc..2ea24423 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp @@ -4,41 +4,39 @@ extern "C" { #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichiprt3.c" +#include "../../../INCHI-1-SRC/INCHI_BASE/src/strutil.c" #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichi_io.h" } TEST(test_ichiprt3, test_str_Sp3_outputs_expected_sp3_string) { - // Prepare INChI_Stereo with 8 stereo centers and their parities - INChI_Stereo stereo = {0}; - - stereo.nNumberOfStereoCenters = 8; - stereo.t_parity = (S_CHAR*)inchi_calloc((long long)stereo.nNumberOfStereoCenters, sizeof(S_CHAR)); - stereo.nNumber = (AT_NUMB*)inchi_calloc((long long)stereo.nNumberOfStereoCenters, sizeof(AT_NUMB)); - int numbers[8] = {3,4,5,6,7,8,9,10}; S_CHAR parities[8] = {1,1,2,2,1,2,2,1}; - - - for (int i = 0; i < 8; i++) { - stereo.nNumber[i] = numbers[i]; - stereo.t_parity[i] = parities[i]; + int num_at = 8; + static INChI_Stereo *stereo = Alloc_INChI_Stereo( num_at, 0 ); + stereo->nNumberOfStereoCenters = num_at; + + // INChI_Stereo stereo = {0}; + // stereo.nNumberOfStereoCenters = 8; + // stereo.t_parity = (S_CHAR*)inchi_calloc((long long)stereo.nNumberOfStereoCenters, sizeof(S_CHAR)); + // stereo.nNumber = (AT_NUMB*)inchi_calloc((long long)stereo.nNumberOfStereoCenters, sizeof(AT_NUMB)); + + for (int i = 0; i < num_at; i++) { + stereo->nNumber[i] = numbers[i]; + stereo->t_parity[i] = parities[i]; } // Prepare INChI and INCHI_SORT INChI inchi = {0}; inchi.nNumberOfAtoms = 10; - inchi.Stereo = &stereo; + inchi.Stereo = stereo; INCHI_SORT sort = {0}; sort.pINChI[0] = &inchi; // Prepare strbuf (empty) INCHI_IOS_STRING strbuf = {0}; - char buf[128] = {0}; - strbuf.pStr = buf; - strbuf.nAllocatedLength = sizeof(buf); - strbuf.nUsedLength = 0; + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); // Call str_Sp3 int bOverflow = 0; @@ -46,7 +44,14 @@ TEST(test_ichiprt3, test_str_Sp3_outputs_expected_sp3_string) // Check that strbuf contains the expected substring EXPECT_EQ(strbuf.nUsedLength, strlen(strbuf.pStr)); - EXPECT_NE(std::string(strbuf.pStr).find("3-,4-,5+,6+,7-,8+,9+,10-"), std::string::npos); + // EXPECT_NE(std::string(strbuf.pStr).find("3-,4-,5+,6+,7-,8+,9+,10-"), std::string::npos); + EXPECT_EQ(std::string(strbuf.pStr), "3-,4-,5+,6+,7-,8+,9+,10-"); EXPECT_EQ(strbuf.pStr[0], '3'); // Should start with 3- EXPECT_EQ(bOverflow, 0); + + EXPECT_EQ(ret, 24); + + inchi_strbuf_close(&strbuf); + + Free_INChI_Stereo(stereo); } From e0b38cb75fe49084685631d7f462024ff92bde62 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Tue, 30 Dec 2025 12:57:14 +0000 Subject: [PATCH 46/69] Added unit tests for stereo-layer tags --- INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c | 2 +- .../tests/test_unit/test_ichiprt1.cpp | 147 +++++++++++++++--- .../tests/test_unit/test_ichiprt2.cpp | 4 - .../tests/test_unit/test_ichiprt3.cpp | 4 +- 4 files changed, 124 insertions(+), 33 deletions(-) diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c index 23aba0d8..839e8ed5 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c @@ -3493,7 +3493,7 @@ int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, { if (io->bPlainTextTags == 1) { - inchi_ios_print_nodisplay( out_file, "////" ); /* sp3, sp2, abs-inv, stereo.type */ + inchi_ios_print_nodisplay( out_file, "////" ); /* sp2, sp3, abs-inv, stereo.type */ } } diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp index b11d45bc..df6348f2 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp @@ -19,7 +19,6 @@ extern "C" TEST(test_ichiprt1, test_OutputINCHI_StereoLayer) { - // Prepare minimal dummy arguments CANON_GLOBALS cg = {0}; INCHI_IOSTREAM out_file = {0}; INCHI_IOS_STRING strbuf = {0}; @@ -27,8 +26,6 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer) char lf[] = "\n"; char tab[] = "\t"; - // Initialize string buffer (simulate allocation) - // inchi_strbuf_init(&strbuf, 128, 128); inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); inchi_ios_init(&out_file, INCHI_IOS_TYPE_STRING, nullptr); @@ -39,11 +36,8 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer) // char *pLF, // char *pTAB ) - // Call the function under test int ret = OutputINCHI_StereoLayer(&cg, &out_file, &strbuf, &io, lf, tab); - // Check that the function returns 0 (success) or expected error code - // (You may need to adjust this depending on the actual implementation) EXPECT_EQ(ret, 0); // Clean up @@ -53,14 +47,12 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer) TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_s1) { - // Prepare minimal input structures CANON_GLOBALS cg = {0}; INCHI_IOSTREAM out_file = {0}; INCHI_IOS_STRING strbuf = {0}; INCHI_OUT_CTL io = {0}; - // Set up io to trigger the /s (stereo type) segment - io.sDifSegs[0][DIFS_s_STYPE] = DIFV_OUTPUT_FILL_T; // nonzero triggers INChI_SegmentAction + io.sDifSegs[0][DIFS_s_STYPE] = DIFV_OUTPUT_FILL_T; io.nCurINChISegment = 0; io.iCurTautMode = 0; @@ -75,10 +67,8 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_s1) inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); inchi_ios_init(&out_file, INCHI_IOS_TYPE_STRING, nullptr); - // Call function int ret = OutputINCHI_StereoLayer(&cg, &out_file, &strbuf, &io, (char*)"", (char*)""); - // The stereo type should be "s1" (plain tag + abs) EXPECT_EQ(std::string(strbuf.pStr), "/s1"); EXPECT_EQ(ret, 0); @@ -88,15 +78,12 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_s1) TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_s2) { - // Prepare minimal input structures CANON_GLOBALS cg = {0}; INCHI_IOSTREAM out_file = {0}; INCHI_IOS_STRING strbuf = {0}; INCHI_OUT_CTL io = {0}; - // Set up io to trigger the /s (stereo type) segment - io.sDifSegs[0][DIFS_s_STYPE] = DIFV_OUTPUT_FILL_T; // nonzero triggers INChI_SegmentAction - + io.sDifSegs[0][DIFS_s_STYPE] = DIFV_OUTPUT_FILL_T; io.nCurINChISegment = 0; io.iCurTautMode = 0; @@ -111,10 +98,8 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_s2) inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); inchi_ios_init(&out_file, INCHI_IOS_TYPE_STRING, nullptr); - // Call function int ret = OutputINCHI_StereoLayer(&cg, &out_file, &strbuf, &io, (char*)"", (char*)""); - // The stereo type should be "s1" (plain tag + abs) EXPECT_EQ(std::string(strbuf.pStr), "/s2"); EXPECT_EQ(ret, 0); @@ -124,15 +109,13 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_s2) TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_s3) { - // Prepare minimal input structures CANON_GLOBALS cg = {0}; INCHI_IOSTREAM out_file = {0}; INCHI_IOS_STRING strbuf = {0}; INCHI_OUT_CTL io = {0}; - // Set up io to trigger the /s (stereo type) segment - io.sDifSegs[0][DIFS_s_STYPE] = DIFV_OUTPUT_FILL_T; // nonzero triggers INChI_SegmentAction + io.sDifSegs[0][DIFS_s_STYPE] = DIFV_OUTPUT_FILL_T; io.nCurINChISegment = 0; io.iCurTautMode = 0; @@ -147,10 +130,8 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_s3) inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); inchi_ios_init(&out_file, INCHI_IOS_TYPE_STRING, nullptr); - // Call function int ret = OutputINCHI_StereoLayer(&cg, &out_file, &strbuf, &io, (char*)"", (char*)""); - // The stereo type should be "s1" (plain tag + abs) EXPECT_EQ(std::string(strbuf.pStr), "/s3"); EXPECT_EQ(ret, 0); @@ -160,7 +141,6 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_s3) TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_enh_stereo_1) { - // --- Setup CANON_GLOBALS and INChI/INChI_Stereo for enhanced stereo --- CANON_GLOBALS cg = {0}; INCHI_IOSTREAM out_file = {0}; INCHI_IOS_STRING strbuf = {0}; @@ -206,11 +186,11 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_enh_stereo_1) io.pINChISort = &sort; - // --- Setup io to trigger stereo output --- io.num_components = 1; io.bRelativeStereo[0] = 0; io.bRacemicStereo[0] = 1; + io.sDifSegs[0][DIFS_b_SBONDS] = DIFV_OUTPUT_FILL_T; io.sDifSegs[0][DIFS_t_SATOMS] = DIFV_OUTPUT_FILL_T; io.sDifSegs[0][DIFS_m_SP3INV] = DIFV_OUTPUT_FILL_T; io.sDifSegs[0][DIFS_s_STYPE] = DIFV_OUTPUT_FILL_T; @@ -227,7 +207,7 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_enh_stereo_1) int ret = OutputINCHI_StereoLayer(&cg, &out_file, &strbuf, &io, (char*)"", (char*)""); - EXPECT_EQ(std::string(out_file.s.pStr), "//t3-,4-,5+,6+,7-,8+,9+,10-/m0/s3/"); + EXPECT_EQ(std::string(out_file.s.pStr), "/t3-,4-,5+,6+,7-,8+,9+,10-/m0/s3/"); EXPECT_EQ(ret, 0); inchi_strbuf_close(&strbuf); @@ -268,3 +248,120 @@ TEST(test_ichiprt1, test_set_line_separators) } + +TEST(test_ichiprt1, test_szGetTag_basic) +{ + + // nTag = 1: XML label (szXmlLabel) + // nTag = 2: Plain text label (szPlainLabel) + // nTag = 3: Plain label with comments (sometimes) + + // bTag: A bitmask indicating which tag (or tags) to look up in the INCHI_TAG array. + + char szTag[64] = {0}; + int bAlways = -1; + + EXPECT_STREQ(szGetTag(IdentLbl, 0, 0, szTag, &bAlways, 0), "???"); //fixed-H + EXPECT_STREQ(szTag, "???"); + +} + +TEST(test_ichiprt1, test_szGetTag_returns_unknown_for_invalid_index) +{ + char szTag[64] = {0}; + int bAlways = -1; + // nTag = 0, bTag = 0, should return "???" + EXPECT_STREQ(szGetTag(IdentLbl, 0, 0, szTag, &bAlways, 0), "???"); + EXPECT_STREQ(szTag, "???"); +} + +TEST(test_ichiprt1, test_szGetTag_stereo_1) +{ + char szTag[64] = {0}; + int bAlways = -1; + // nTag = 2 (plain text), bTag = IL_STER (stereo) + EXPECT_STREQ(szGetTag(IdentLbl, 2, IL_STER, szTag, &bAlways, 0), "/"); + EXPECT_STREQ(szTag, "/"); +} + +TEST(test_ichiprt1, test_szGetTag_stereo_2) +{ + char szTag[64] = {0}; + int bAlways = -1; + // nTag = 2 (plain text), bTag = IL_STER (stereo) + EXPECT_STREQ(szGetTag(IdentLbl, 1, IL_STER, szTag, &bAlways, 0), "stereo"); + EXPECT_STREQ(szTag, "stereo"); +} + +TEST(test_ichiprt1, test_szGetTag_stereo_3) +{ + char szTag[64] = {0}; + int bAlways = -1; + // nTag = 2 (plain text), bTag = IL_STER (stereo) + EXPECT_STREQ(szGetTag(IdentLbl, 2, IL_SP3S, szTag, &bAlways, 0), "/t"); + EXPECT_STREQ(szTag, "/t"); +} + +TEST(test_ichiprt1, test_szGetTag_stereo_4) +{ + char szTag[64] = {0}; + int bAlways = -1; + // nTag = 2 (plain text), bTag = IL_STER (stereo) + EXPECT_STREQ(szGetTag(IdentLbl, 2, IL_INVS, szTag, &bAlways, 0), "/m"); + EXPECT_STREQ(szTag, "/m"); +} + +TEST(test_ichiprt1, test_szGetTag_stereo_5) +{ + char szTag[64] = {0}; + int bAlways = -1; + // nTag = 2 (plain text), bTag = IL_STER (stereo) + EXPECT_STREQ(szGetTag(IdentLbl, 2, IL_TYPS, szTag, &bAlways, 0), "/s"); + EXPECT_STREQ(szTag, "/s"); +} + +TEST(test_ichiprt1, test_szGetTag_stereo_6) +{ + char szTag[64] = {0}; + int bAlways = -1; + // nTag = 2 (plain text), bTag = IL_STER (stereo) + EXPECT_STREQ(szGetTag(IdentLbl, 1, IL_TYPS, szTag, &bAlways, 0), "type"); + EXPECT_STREQ(szTag, "type"); +} + +TEST(test_ichiprt1, test_szGetTag_hfixed) +{ + char szTag[64] = {0}; + int bAlways = -1; + // nTag = 2 (plain text), bTag = IL_STER (stereo) + EXPECT_STREQ(szGetTag(IdentLbl, 1, IL_FIXH, szTag, &bAlways, 0), "fixed-H"); + EXPECT_STREQ(szTag, "fixed-H"); +} + +TEST(test_ichiprt1, test_szGetTag_returns_xml_label) +{ + char szTag[64] = {0}; + int bAlways = -1; + // nTag = 1 (XML), bTag = IL_CONN (connections) + EXPECT_STREQ(szGetTag(IdentLbl, 1, IL_CONN, szTag, &bAlways, 0), "connections"); + EXPECT_STREQ(szTag, "connections"); +} + +TEST(test_ichiprt1, test_szGetTag_sets_bAlways) +{ + char szTag[64] = {0}; + int bAlways = -1; + // nTag = 2 (plain text), bTag = IL_FML_ (formula), which has bAlwaysOutput = 1 + szGetTag(IdentLbl, 2, IL_FML_, szTag, &bAlways, 0); + EXPECT_EQ(bAlways, -1); + EXPECT_STREQ(szTag, "/"); +} + +TEST(test_ichiprt1, test_szGetTag_charge) +{ + char szTag[64] = {0}; + int bAlways = -1; + // nTag = 2 (plain text), bTag = IL_CHRG (charge) + EXPECT_STREQ(szGetTag(IdentLbl, 2, IL_CHRG, szTag, &bAlways, 0), "/q"); + EXPECT_STREQ(szTag, "/q"); +} diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp index 0800ef1b..ef5ed7fc 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp @@ -9,20 +9,16 @@ extern "C" TEST(test_ichiprt2, MakeStereoString_outputs_expected_sp3_string) { - // Prepare input arrays for 8 stereo centers AT_NUMB at1[8] = {3,4,5,6,7,8,9,10}; S_CHAR parity[8] = {1,1,2,2,1,2,2,1}; - // Prepare strbuf (empty) INCHI_IOS_STRING strbuf = {0}; inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); - // Call MakeStereoString int bOverflow = 0; int ret = MakeStereoString(at1, nullptr, parity, 0, 8, &strbuf, 0, &bOverflow); - // Check that strbuf contains the expected substring EXPECT_EQ(strbuf.nUsedLength, strlen(strbuf.pStr)); EXPECT_NE(std::string(strbuf.pStr).find("3-,4-,5+,6+,7-,8+,9+,10-"), std::string::npos); EXPECT_EQ(strbuf.pStr[0], '3'); // Should start with 3- diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp index 2ea24423..edbb4de2 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp @@ -26,7 +26,6 @@ TEST(test_ichiprt3, test_str_Sp3_outputs_expected_sp3_string) stereo->t_parity[i] = parities[i]; } - // Prepare INChI and INCHI_SORT INChI inchi = {0}; inchi.nNumberOfAtoms = 10; inchi.Stereo = stereo; @@ -34,11 +33,10 @@ TEST(test_ichiprt3, test_str_Sp3_outputs_expected_sp3_string) INCHI_SORT sort = {0}; sort.pINChI[0] = &inchi; - // Prepare strbuf (empty) INCHI_IOS_STRING strbuf = {0}; inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); - // Call str_Sp3 + int bOverflow = 0; int ret = str_Sp3(&sort, NULL, &strbuf, &bOverflow, 0, 0, 1, 0, 0, 0, 0); From 2e9f95ca877ce64890ef26781ae88f5d9384248f Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 5 Jan 2026 14:54:21 +0000 Subject: [PATCH 47/69] Added unit tests for m-layer --- INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c | 9 +- INCHI-1-SRC/INCHI_BASE/src/ichiprt3.c | 15 +- .../tests/test_unit/test_ichiprt1.cpp | 141 +++++++++++++++--- .../tests/test_unit/test_ichiprt2.cpp | 15 ++ .../tests/test_unit/test_ichiprt3.cpp | 87 +++++++++++ 5 files changed, 238 insertions(+), 29 deletions(-) diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c index 839e8ed5..c5664be9 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c @@ -3375,7 +3375,6 @@ int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, /* sp2 */ - /*if ( bStereoSp2[io->iCurTautMode] )*/ if ((io->nSegmAction = INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_b_SBONDS] ))) /* djb-rwth: addressing LLVM warning */ { szGetTag( IdentLbl, io->nTag, io->bTag2 = io->bTag1 | IL_DBND, io->szTag2, &io->bAlways, 1 ); @@ -3406,7 +3405,7 @@ int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, /* sp3 */ - /*if ( bStereoSp3[io->iCurTautMode] )*/ + /* t-layer */ if ((io->nSegmAction = INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_t_SATOMS] ))) /* djb-rwth: addressing LLVM warning */ { io->bRelRac = io->bRelativeStereo[io->iCurTautMode] || io->bRacemicStereo[io->iCurTautMode]; @@ -3436,9 +3435,7 @@ int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, } } - /* bStereoAbsInverted[io->iCurTautMode] */ - - /* if ( bStereoAbs[io->iCurTautMode] ) */ + /* m-layer */ if ((io->nSegmAction = INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_m_SP3INV] ))) /* djb-rwth: addressing LLVM warning */ { szGetTag( IdentLbl, io->nTag, io->bTag2 = io->bTag1 | IL_INVS, io->szTag2, &io->bAlways, 1 ); @@ -3466,7 +3463,7 @@ int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, /* stereo type */ - /*if ( io->bRacemicStereo[io->iCurTautMode] || io->bRelativeStereo[io->iCurTautMode] || bStereoAbs[io->iCurTautMode] )*/ + /* s-layer */ if ((io->nSegmAction = INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_s_STYPE] ))) /* djb-rwth: addressing LLVM warning */ { const char *p_stereo = io->bRelativeStereo[io->iCurTautMode] ? x_rel : diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt3.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt3.c index 6f51233f..309384ce 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt3.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt3.c @@ -1184,10 +1184,15 @@ int str_Sp3( INCHI_SORT *pINChISort, return ( strbuf->nUsedLength - nUsedLength0 ); } - -/**************************************************************************** - Output abs stero inversion substring of the whole structure InChI string -****************************************************************************/ +/** + * @brief Output absolute stereo inversion substring of the whole structure InChI string + * @param pINChISort Pointer to INCHI_SORT array + * @param strbuf Pointer to string buffer + * @param bOverflow Overflow flag + * @param bOutType Output type + * @param num_components Number of connected components + * @return Length of the added substring (return value '0', '1', or '.' in strbuf) + */ int str_StereoAbsInv( INCHI_SORT *pINChISort, INCHI_IOS_STRING *strbuf, int *bOverflow, @@ -4131,7 +4136,7 @@ int bin_AuxTautTrans( INCHI_SORT *pINChISort, if (nTrans_n && nTrans_s) { /* new ordering number for original non-tautomeric component number is->ord_number */ - nTrans_n[is->ord_number] = i + 1; /*nTrans_t[is2->ord_number] =*/ + nTrans_n[is->ord_number] = i + 1; /*nTrans_t[is2->ord_number] =*/ } } } diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp index df6348f2..419f4217 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp @@ -45,6 +45,114 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer) } +TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_m0) +{ + CANON_GLOBALS cg = {0}; + INCHI_IOSTREAM out_file = {0}; + INCHI_IOS_STRING strbuf = {0}; + INCHI_OUT_CTL io = {0}; + + io.sDifSegs[0][DIFS_m_SP3INV] = DIFV_OUTPUT_FILL_T; + + io.nCurINChISegment = 0; + io.iCurTautMode = 0; + io.bPlainTextTags = 1; + io.bRelativeStereo[0] = 0; + io.bRacemicStereo[0] = 0; + io.bAlways = 0; + io.nTag = 2; // plain text + io.bTag1 = IL_STER; + io.bTag2 = IL_STER | IL_TYPS; + io.bOverflow = 0; + io.bOutType = OUT_TN; + io.num_components = 1; + + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + inchi_ios_init(&out_file, INCHI_IOS_TYPE_STRING, nullptr); + + int num_at = 2; + + int found_num_bonds = 0; + int found_num_isotopic = 0; + inp_ATOM *at = CreateInpAtom(num_at); + INChI *inchi = Alloc_INChI(at, num_at, &found_num_bonds, &found_num_isotopic, 0); + inchi->Stereo->nCompInv2Abs = 1; + inchi->nNumberOfAtoms = num_at; + + INCHI_SORT *inchi_sort = (INCHI_SORT*)calloc(1, sizeof(INCHI_SORT)); + inchi_sort->pINChI[TAUT_YES] = inchi; + + io.pINChISort = inchi_sort; + + int ret = OutputINCHI_StereoLayer(&cg, &out_file, &strbuf, &io, (char*)"", (char*)""); + + EXPECT_EQ(std::string(strbuf.pStr), "/m0"); + EXPECT_EQ(ret, 0); + + inchi_strbuf_close(&strbuf); + inchi_ios_close(&out_file); + + Free_INChI( &inchi ); + + FreeInpAtom(&at); + + free(inchi_sort); +} + +TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_m1) +{ + CANON_GLOBALS cg = {0}; + INCHI_IOSTREAM out_file = {0}; + INCHI_IOS_STRING strbuf = {0}; + INCHI_OUT_CTL io = {0}; + + io.sDifSegs[0][DIFS_m_SP3INV] = DIFV_OUTPUT_FILL_T; + + io.nCurINChISegment = 0; + io.iCurTautMode = 0; + io.bPlainTextTags = 1; + io.bRelativeStereo[0] = 0; + io.bRacemicStereo[0] = 0; + io.bAlways = 0; + io.nTag = 2; // plain text + io.bTag1 = IL_STER; + io.bTag2 = IL_STER | IL_TYPS; + io.bOverflow = 0; + io.bOutType = OUT_TN; + io.num_components = 1; + + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + inchi_ios_init(&out_file, INCHI_IOS_TYPE_STRING, nullptr); + + int num_at = 2; + + int found_num_bonds = 0; + int found_num_isotopic = 0; + inp_ATOM *at = CreateInpAtom(num_at); + INChI *inchi = Alloc_INChI(at, num_at, &found_num_bonds, &found_num_isotopic, 0); + inchi->Stereo->nCompInv2Abs = -1; + inchi->nNumberOfAtoms = num_at; + + INCHI_SORT *inchi_sort = (INCHI_SORT*)calloc(1, sizeof(INCHI_SORT)); + inchi_sort->pINChI[TAUT_YES] = inchi; + + io.pINChISort = inchi_sort; + + int ret = OutputINCHI_StereoLayer(&cg, &out_file, &strbuf, &io, (char*)"", (char*)""); + + EXPECT_EQ(std::string(strbuf.pStr), "/m1"); + EXPECT_EQ(ret, 0); + + inchi_strbuf_close(&strbuf); + inchi_ios_close(&out_file); + + Free_INChI( &inchi ); + + FreeInpAtom(&at); + + free(inchi_sort); +} + TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_s1) { CANON_GLOBALS cg = {0}; @@ -137,6 +245,7 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_s3) inchi_strbuf_close(&strbuf); inchi_ios_close(&out_file); + } TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_enh_stereo_1) @@ -151,23 +260,8 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_enh_stereo_1) static AT_NUMB numbers[8] = {3,4,5,6,7,8,9,10}; static S_CHAR parities[8] = {1,1,2,2,1,2,2,1};// -,-,+,+,-,+,+,- - static S_CHAR m_values[1] = {0}; // /m0 - static S_CHAR s_values[1] = {1}; // /s1 - // static INChI_Stereo stereo = {0}; - static INChI_Stereo *stereo = Alloc_INChI_Stereo( num_at, num_bonds ); - - stereo->nNumberOfStereoCenters = 8; - - for (int i = 0; i < num_at; i++) { - stereo->nNumber[i] = numbers[i]; - stereo->t_parity[i] = parities[i]; - } - - stereo->nCompInv2Abs = 1; - stereo->nNumberOfStereoBonds = 0; - stereo->b_parity = NULL; // INChI *inchi = new INChI; // inchi->nNumberOfAtoms = num_at; @@ -179,7 +273,19 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_enh_stereo_1) static INChI *inchi = Alloc_INChI(at, num_at, &found_num_bonds, &found_num_isotopic, 0); inchi->nNumberOfAtoms = num_at; - inchi->Stereo = stereo; + + inchi->Stereo->nNumberOfStereoCenters = num_at; + + for (int i = 0; i < num_at; i++) { + inchi->Stereo->nNumber[i] = numbers[i]; + inchi->Stereo->t_parity[i] = parities[i]; + } + + inchi->Stereo->nCompInv2Abs = 1; + inchi->Stereo->nNumberOfStereoBonds = 0; + inchi->Stereo->b_parity = NULL; + + static INCHI_SORT sort = {0}; sort.pINChI[0] = inchi; @@ -214,8 +320,7 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_enh_stereo_1) inchi_ios_close(&out_file); FreeInpAtom(&at); - // Free_INChI(&inchi); - Free_INChI_Stereo(stereo); + Free_INChI(&inchi); } TEST(test_ichiprt1, test_set_line_separators) diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp index ef5ed7fc..2244420d 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp @@ -43,6 +43,21 @@ TEST(test_ichiprt2, MakeMult_mult_gt_1_appends_number_and_delim) inchi_strbuf_close(&strbuf); } +TEST(test_ichiprt2, MakeMult_mult_2) +{ + INCHI_IOS_STRING strbuf = {0}; + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + + int bOverflow = 0; + int ret = MakeMult(10, "+", &strbuf, 0, &bOverflow); + + EXPECT_EQ(std::string(strbuf.pStr), "10+"); + EXPECT_EQ(ret, 3); // "3-".length() == 2, but MakeMult returns n (number of chars written) + EXPECT_EQ(bOverflow, 0); + + inchi_strbuf_close(&strbuf); +} + TEST(test_ichiprt2, MakeMult_mult_eq_1_does_nothing) { INCHI_IOS_STRING strbuf = {0}; diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp index edbb4de2..be614485 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp @@ -6,6 +6,7 @@ extern "C" #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichiprt3.c" #include "../../../INCHI-1-SRC/INCHI_BASE/src/strutil.c" #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichi_io.h" +#include "../../../INCHI-1-SRC/INCHI_BASE/src/ichimake.h" } TEST(test_ichiprt3, test_str_Sp3_outputs_expected_sp3_string) @@ -53,3 +54,89 @@ TEST(test_ichiprt3, test_str_Sp3_outputs_expected_sp3_string) Free_INChI_Stereo(stereo); } + +TEST(test_ichiprt3, test_str_StereoAbsInv_1) +{ + + int num_at = 2; + int num_bonds = 1; + + + + int found_num_bonds = 0; + int found_num_isotopic = 0; + inp_ATOM *at = CreateInpAtom(num_at); + static INChI *inchi = Alloc_INChI(at, num_at, &found_num_bonds, &found_num_isotopic, 0); + inchi->Stereo->nCompInv2Abs = -1; + inchi->nNumberOfAtoms = num_at; + + INCHI_SORT *inchi_sort = (INCHI_SORT*)calloc(1, sizeof(INCHI_SORT)); + inchi_sort->pINChI[TAUT_YES] = inchi; + + INCHI_IOS_STRING strbuf = {0}; + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + + int bOverflow = 0; + int bOutType = OUT_TN; + int num_components = 1; + + // int test_ret0 = HAS_T(inchi_sort); + // int test_ret1 = GET_II( bOutType, inchi_sort); + + int ret = str_StereoAbsInv(inchi_sort, &strbuf, &bOverflow, bOutType, num_components); + + EXPECT_EQ(ret, 1); + EXPECT_EQ(std::string(strbuf.pStr), "1"); + EXPECT_EQ(bOverflow, 0); + + inchi_strbuf_close(&strbuf); + + Free_INChI(&inchi); + + FreeInpAtom(&at); + + free(inchi_sort); +} + +TEST(test_ichiprt3, test_str_StereoAbsInv_2) +{ + + int num_at = 2; + int num_bonds = 1; + + int found_num_bonds = 0; + int found_num_isotopic = 0; + inp_ATOM *at = CreateInpAtom(num_at); + static INChI *inchi = Alloc_INChI(at, num_at, &found_num_bonds, &found_num_isotopic, 0); + + inchi->Stereo->nCompInv2Abs = 1; + + inchi->nNumberOfAtoms = num_at; + + INCHI_SORT *inchi_sort = (INCHI_SORT*)calloc(1, sizeof(INCHI_SORT)); + inchi_sort->pINChI[TAUT_YES] = inchi; + + INCHI_IOS_STRING strbuf = {0}; + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + + int bOverflow = 0; + int bOutType = OUT_TN; + int num_components = 1; + + // int test_ret0 = HAS_T(inchi_sort); + // int test_ret1 = GET_II( bOutType, inchi_sort); + + int ret = str_StereoAbsInv(inchi_sort, &strbuf, &bOverflow, bOutType, num_components); + + EXPECT_EQ(ret, 1); + EXPECT_EQ(std::string(strbuf.pStr), "0"); + EXPECT_EQ(bOverflow, 0); + + inchi_strbuf_close(&strbuf); + + Free_INChI(&inchi); + + FreeInpAtom(&at); + + free(inchi_sort); +} From 01ca15392e749934b24e0d7efafda80d729ece6e Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Wed, 7 Jan 2026 13:46:22 +0000 Subject: [PATCH 48/69] Added doxygen comments --- INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c | 26 +++++++++++++++----------- INCHI-1-SRC/INCHI_BASE/src/ichiprt3.c | 19 +++++++++++++++---- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c index c5664be9..830aabc9 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c @@ -3347,10 +3347,17 @@ int OutputINCHI_ChargeAndRemovedAddedProtonsLayers( CANON_GLOBALS *pCG, return 0; } - -/**************************************************************************** -Output InChI: stereo layer with sublayers -****************************************************************************/ +/** + * @brief Output InChI: stereo layer with sublayers. + * + * @param pCG Pointer to the CANON_GLOBALS structure containing global canonicalization data. + * @param out_file Pointer to the INCHI_IOSTREAM output stream where the stereo layer will be written. + * @param strbuf Pointer to an INCHI_IOS_STRING buffer used for string formatting and output. + * @param io Pointer to the INCHI_OUT_CTL structure containing output control and state information. + * @param pLF Pointer to a string used as the line feed (end-of-line) character(s). + * @param pTAB Pointer to a string used as the tab or separator character(s). + * @return Returns 0 on success, or a non-zero error code on failure. + */ int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, INCHI_IOSTREAM *out_file, INCHI_IOS_STRING *strbuf, @@ -3359,10 +3366,6 @@ int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, char *pTAB ) { - // int i; - // i = INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_t_SATOMS] ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */ - // /* djb-rwth: removing redundant code */ - if (INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_b_SBONDS] ) || INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_t_SATOMS] ) || INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_m_SP3INV] ) || @@ -3375,7 +3378,7 @@ int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, /* sp2 */ - if ((io->nSegmAction = INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_b_SBONDS] ))) /* djb-rwth: addressing LLVM warning */ + if ((io->nSegmAction = INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_b_SBONDS] ))) { szGetTag( IdentLbl, io->nTag, io->bTag2 = io->bTag1 | IL_DBND, io->szTag2, &io->bAlways, 1 ); inchi_strbuf_reset( strbuf ); @@ -3464,7 +3467,7 @@ int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, /* stereo type */ /* s-layer */ - if ((io->nSegmAction = INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_s_STYPE] ))) /* djb-rwth: addressing LLVM warning */ + if ((io->nSegmAction = INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_s_STYPE] ))) { const char *p_stereo = io->bRelativeStereo[io->iCurTautMode] ? x_rel : io->bRacemicStereo[io->iCurTautMode] ? x_rac : x_abs; @@ -3499,7 +3502,8 @@ int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, /**************************************************************************** -Output InChI: isotopic layer and sublayers ****************************************************************************/ +Output InChI: isotopic layer and sublayers +****************************************************************************/ int OutputINCHI_IsotopicLayer( CANON_GLOBALS *pCG, INCHI_IOSTREAM *out_file, INCHI_IOS_STRING *strbuf, diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt3.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt3.c index 309384ce..eb338ddd 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt3.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt3.c @@ -718,10 +718,21 @@ int str_FixedH_atoms( INCHI_SORT *pINChISort, return ( strbuf->nUsedLength - nUsedLength0 ); } - -/**************************************************************************** - Produce double bond stereo substring of the whole structure InChI string. -****************************************************************************/ +/** + * @brief Produce double bond stereo substring of the whole structure InChI string. + * + * @param pINChISort Pointer to the primary INCHI_SORT structure containing input data. + * @param pINChISort2 Pointer to the secondary INCHI_SORT structure, used for comparison or additional data. + * @param strbuf Pointer to an INCHI_IOS_STRING buffer where the output string will be stored. + * @param bOverflow Pointer to an integer flag that will be set if the output overflows the buffer. + * @param bOutType Output type flag specifying the format or type of output. + * @param TAUT_MODE Tautomer mode flag indicating how tautomers are handled. + * @param num_components Number of components to process. + * @param bSecondNonTautPass Flag indicating if this is the second pass for non-tautomeric processing. + * @param bOmitRepetitions Flag to omit repeated entries in the output. + * @param bUseMulipliers Flag to use multipliers in the output representation. + * @return Returns number of characters written to strbuf + */ int str_Sp2( INCHI_SORT *pINChISort, INCHI_SORT *pINChISort2, INCHI_IOS_STRING *strbuf, From ddd3c7a32b1e11c61488690fb65c85366d156dc2 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Thu, 8 Jan 2026 15:58:52 +0000 Subject: [PATCH 49/69] Added unit tests and initial modification for enh stereo --- INCHI-1-SRC/INCHI_BASE/src/ichidrp.h | 1 + INCHI-1-SRC/INCHI_BASE/src/ichimake.h | 5 + INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c | 239 +++++++++++++++++- INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c | 73 +++++- INCHI-1-SRC/INCHI_BASE/src/strutil.h | 4 +- .../tests/test_unit/test_ichimain.cpp | 3 +- .../tests/test_unit/test_ichiprt1.cpp | 178 +++++++++++-- .../test_ichiprt1_enhancedStereo.cpp | 104 ++++++++ .../tests/test_unit/test_ichiprt2.cpp | 110 ++++++++ .../tests/test_unit/test_ichiprt3.cpp | 142 ++++++++++- 10 files changed, 811 insertions(+), 48 deletions(-) create mode 100644 INCHI-1-TEST/tests/test_unit/test_ichiprt1_enhancedStereo.cpp diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichidrp.h b/INCHI-1-SRC/INCHI_BASE/src/ichidrp.h index ff555c93..7e0e7673 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichidrp.h +++ b/INCHI-1-SRC/INCHI_BASE/src/ichidrp.h @@ -187,6 +187,7 @@ typedef struct tagInputParms { int bNoWarnings; /* v. 1.06+ suppress warning messages */ int bHideInChI; /* v. 1.06+ Do not print InChI itself */ + int bEnhancedStereo; /* */ INCHI_MODE bTautFlags; diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichimake.h b/INCHI-1-SRC/INCHI_BASE/src/ichimake.h index 4f7f9db5..0669703b 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichimake.h +++ b/INCHI-1-SRC/INCHI_BASE/src/ichimake.h @@ -208,6 +208,11 @@ const char *EquString( int EquVal ); INCHI_IOS_STRING *buf, int nCtMode, int *bOverflow ); + int MakeEnhStereoString( int **enh_stereo, + int nof_units, + INCHI_IOS_STRING *strbuf, + int nCtMode, + int *bOverflow ); int MakeCRVString( ORIG_INFO *OrigInfo, int nLenCT, int bAddDelim, diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c index 830aabc9..da530ed5 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c @@ -129,6 +129,13 @@ static int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, INCHI_OUT_CTL *io, char *pLF, char *pTAB ); +static int OutputINCHI_StereoLayer_EnhancedStereo( CANON_GLOBALS *pCG, + INCHI_IOSTREAM *out_file, + INCHI_IOS_STRING *strbuf, + INCHI_OUT_CTL *io, + ORIG_ATOM_DATA *orig_inp_data, + char *pLF, + char *pTAB ); static int OutputINCHI_IsotopicLayer( CANON_GLOBALS *pCG, INCHI_IOSTREAM *out_file, INCHI_IOS_STRING *strbuf, @@ -1032,14 +1039,29 @@ int OutputINChI2( CANON_GLOBALS *pCG, return ret; } - -/* */ -/* OutputINChI1( ... ) */ -/* */ -/* Main actual worker which serializes InChI to string. */ -/* */ -/* Called from OutputINChI2( ... ) and from itself */ -/* */ +/** + * @brief Main actual worker which serializes InChI to string. Called from OutputINChI2( ... ) and from itself. + * + * @param pCG Pointer to global canonicalization data. + * @param strbuf Pointer to the output string buffer. + * @param pINChISortTautAndNonTaut2 Array of pointers to INCHI_SORT structures for tautomeric and non-tautomeric forms. + * @param INCHI_basic_or_INCHI_reconnected Flag indicating basic or reconnected InChI output. + * @param orig_inp_data Pointer to original atom data. + * @param pOrigStruct Pointer to the original structure data. + * @param ip Pointer to input parameters. + * @param bDisconnectedCoord Flag for disconnected metal coordination. + * @param bOutputType Output type (tautomeric/non-tautomeric/both). + * @param bINChIOutputOptions Bitmask of output options. + * @param num_components2 Array of component counts for each structure type. + * @param num_non_taut2 Array of non-tautomeric component counts. + * @param num_taut2 Array of tautomeric component counts. + * @param out_file Output stream for InChI string. + * @param log_file Output stream for logging. + * @param num_input_struct Number of input structures. + * @param pSortPrintINChIFlags Pointer to flags controlling sorting and printing. + * @param save_opt_bits Encoded bits for saved InChI creation options. + * @return int + */ int OutputINChI1( CANON_GLOBALS *pCG, INCHI_IOS_STRING *strbuf, INCHI_SORT *pINChISortTautAndNonTaut2[][TAUT_NUM], @@ -1753,7 +1775,14 @@ int OutputINChI1( CANON_GLOBALS *pCG, } /* InChI output: stereo (non-isotopic) */ - intermediate_result = OutputINCHI_StereoLayer( pCG, out_file, strbuf, &io, pLF, pTAB ); + // intermediate_result = OutputINCHI_StereoLayer( pCG, out_file, strbuf, &io, pLF, pTAB ); + + if (ip->bEnhancedStereo) { + intermediate_result = OutputINCHI_StereoLayer_EnhancedStereo( pCG, out_file, strbuf, &io, orig_inp_data, pLF, pTAB ); + } else { + intermediate_result = OutputINCHI_StereoLayer( pCG, out_file, strbuf, &io, pLF, pTAB ); + } + if (intermediate_result != 0) goto exit_function; @@ -3500,6 +3529,198 @@ int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, return 0; } +/** + * @brief Output InChI: stereo layer with sublayers. + * + * @param pCG Pointer to the CANON_GLOBALS structure containing global canonicalization data. + * @param out_file Pointer to the INCHI_IOSTREAM output stream where the stereo layer will be written. + * @param strbuf Pointer to an INCHI_IOS_STRING buffer used for string formatting and output. + * @param io Pointer to the INCHI_OUT_CTL structure containing output control and state information. + * @param orig_inp_data Pointer to the ORIG_ATOM_DATA containing e.g. atom information. + * @param pLF Pointer to a string used as the line feed (end-of-line) character(s). + * @param pTAB Pointer to a string used as the tab or separator character(s). + * @return Returns 0 on success, or a non-zero error code on failure. + */ +int OutputINCHI_StereoLayer_EnhancedStereo( CANON_GLOBALS *pCG, + INCHI_IOSTREAM *out_file, + INCHI_IOS_STRING *strbuf, + INCHI_OUT_CTL *io, + ORIG_ATOM_DATA *orig_inp_data, + char *pLF, + char *pTAB ) +{ + + if (INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_b_SBONDS] ) || + INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_t_SATOMS] ) || + INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_m_SP3INV] ) || + INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_s_STYPE] )) + { + + /* stereo */ + + szGetTag( IdentLbl, io->nTag, io->bTag1 = IL_STER | io->bFhTag, io->szTag1, &io->bAlways, 1 ); + + /* sp2 */ + + if ((io->nSegmAction = INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_b_SBONDS] ))) + { + szGetTag( IdentLbl, io->nTag, io->bTag2 = io->bTag1 | IL_DBND, io->szTag2, &io->bAlways, 1 ); + inchi_strbuf_reset( strbuf ); + io->tot_len = 0; + if (INCHI_SEGM_FILL == io->nSegmAction) + { + io->tot_len = str_Sp2( io->pINChISort, io->pINChISort2, strbuf, &io->bOverflow, + io->bOutType, io->TAUT_MODE, io->num_components, + io->bSecondNonTautPass, io->bOmitRepetitions, io->bUseMulipliers ); + + io->bNonTautNonIsoIdentifierNotEmpty += io->bSecondNonTautPass; + } + + if (str_LineEnd( io->szTag2, &io->bOverflow, strbuf, -io->nSegmAction, io->bPlainTextTags )) + { + return 1; + } + inchi_ios_print_nodisplay( out_file, "%s%s", strbuf->pStr, pLF ); + } + else + { + if (io->bPlainTextTags == 1) + { + inchi_ios_print_nodisplay( out_file, "/" ); /* sp2 */ + } + } + + /* sp3 */ + + /* t-layer */ + if ((io->nSegmAction = INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_t_SATOMS] ))) /* djb-rwth: addressing LLVM warning */ + { + io->bRelRac = io->bRelativeStereo[io->iCurTautMode] || io->bRacemicStereo[io->iCurTautMode]; + szGetTag( IdentLbl, io->nTag, io->bTag2 = io->bTag1 | IL_SP3S, io->szTag2, &io->bAlways, 1 ); + inchi_strbuf_reset( strbuf ); + io->tot_len = 0; + if (INCHI_SEGM_FILL == io->nSegmAction) + { + io->tot_len = str_Sp3( io->pINChISort, io->pINChISort2, strbuf, &io->bOverflow, + io->bOutType, io->TAUT_MODE, io->num_components, io->bRelRac, + io->bSecondNonTautPass, io->bOmitRepetitions, io->bUseMulipliers ); + + io->bNonTautNonIsoIdentifierNotEmpty += io->bSecondNonTautPass; + } + + if (str_LineEnd( io->szTag2, &io->bOverflow, strbuf, -io->nSegmAction, io->bPlainTextTags )) + { + return 2; + } + inchi_ios_print_nodisplay( out_file, "%s%s", strbuf->pStr, pLF ); + } + else + { + if (io->bPlainTextTags == 1) + { + inchi_ios_print_nodisplay( out_file, "/" ); /* sp3 */ + } + } + + /* m-layer */ + if ((io->nSegmAction = INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_m_SP3INV] ))) /* djb-rwth: addressing LLVM warning */ + { + szGetTag( IdentLbl, io->nTag, io->bTag2 = io->bTag1 | IL_INVS, io->szTag2, &io->bAlways, 1 ); + inchi_strbuf_reset( strbuf ); + io->tot_len = 0; + if (INCHI_SEGM_FILL == io->nSegmAction) + { + io->tot_len = str_StereoAbsInv( io->pINChISort, strbuf, + &io->bOverflow, io->bOutType, io->num_components ); + io->bNonTautNonIsoIdentifierNotEmpty += io->bSecondNonTautPass; + } + + if (str_LineEnd( io->szTag2, &io->bOverflow, strbuf, -io->nSegmAction, io->bPlainTextTags )) + { + return 3; + } + inchi_ios_print_nodisplay( out_file, "%s%s", strbuf->pStr, pLF ); + } + else + { + if (io->bPlainTextTags == 1) + { + inchi_ios_print_nodisplay( out_file, "/" ); /* stereo-abs-inv */ + } + } + + /* stereo type */ + + /* s-layer */ + if ((io->nSegmAction = INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_s_STYPE] ))) + { + + const char *p_stereo; + if (io->bRelativeStereo[io->iCurTautMode]) { + p_stereo = x_rel; + } else if (io->bRacemicStereo[io->iCurTautMode]) { + p_stereo = x_rac; + } else { + p_stereo = x_abs; + } + + szGetTag( IdentLbl, io->nTag, io->bTag2 = io->bTag1 | IL_TYPS, io->szTag2, &io->bAlways, 1 ); + inchi_strbuf_reset( strbuf ); + io->tot_len = 0; + if (INCHI_SEGM_FILL == io->nSegmAction) + { + io->tot_len += MakeDelim( x_abs, strbuf, &io->bOverflow ); // s1 + io->tot_len += MakeEnhStereoString( + orig_inp_data->v3000->lists_steabs, + orig_inp_data->v3000->n_steabs, + strbuf, + 0, + &io->bOverflow + ); + + + io->tot_len += MakeDelim( x_rel, strbuf, &io->bOverflow ); // s2 + io->tot_len += MakeEnhStereoString( + orig_inp_data->v3000->lists_sterel, + orig_inp_data->v3000->n_sterel, + strbuf, + 0, + &io->bOverflow + ); + + + io->tot_len += MakeDelim( x_rac, strbuf, &io->bOverflow ); // s3 + io->tot_len += MakeEnhStereoString( + orig_inp_data->v3000->lists_sterac, + orig_inp_data->v3000->n_sterac, + strbuf, + 0, + &io->bOverflow + ); + + io->bNonTautNonIsoIdentifierNotEmpty += io->bSecondNonTautPass; + } + if (str_LineEnd( io->szTag2, &io->bOverflow, strbuf, -io->nSegmAction, io->bPlainTextTags )) + { + return 1; + } + inchi_ios_print_nodisplay( out_file, "%s%s", strbuf->pStr, pLF ); + } + if (io->bPlainTextTags == 1) + { + inchi_ios_print_nodisplay( out_file, "/" ); /* no abs, inv or racemic stereo */ + } + } + else + { + if (io->bPlainTextTags == 1) + { + inchi_ios_print_nodisplay( out_file, "////" ); /* sp2, sp3, abs-inv, stereo.type */ + } + } + + return 0; +} /**************************************************************************** Output InChI: isotopic layer and sublayers diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c index 51ce948c..2a40880e 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c @@ -471,6 +471,49 @@ int MakeMult( int mult, return 0; } +int MakeMult_EnhStereo( int mult, + const char *szTailingDelim, + INCHI_IOS_STRING *buf, + int nCtMode, + int *bOverflow ) +{ + char szValue[2048]; + int len = 0, len_delim, n; + + if (*bOverflow) + { + return 0; + } + if (nCtMode & CT_MODE_ABC_NUMBERS) + { + len += MakeAbcNumber( szValue, ( int )sizeof( szValue ), NULL, mult ); + } + else + { + len += MakeDecNumber( szValue, ( int )sizeof( szValue ), NULL, mult ); + } + len_delim = (int) strlen( szTailingDelim ); + + if (len + len_delim < ( int )sizeof( szValue )) + { + strcpy(szValue + len, szTailingDelim); + n = inchi_strbuf_printf( buf, "%s", szValue ); + if (-1 == n) *bOverflow |= 1; + return n; + /* + len += len_delim; + if ( len < nLen_szLinearCT ) + { + strcpy( szLinearCT, szValue ); + return len; + }*/ + } + + *bOverflow |= 1; + + return 0; +} + /****************************************************************************/ int MakeDelim( const char *szTailingDelim, @@ -1464,7 +1507,7 @@ int MakeCRVString( ORIG_INFO *OrigInfo, } /* radical */ if (OrigInfo[k].cRadical) - { + { if (len >= 2047) /* djb-rwth: fixing coverity CID #499515 */ { len = 2047; @@ -2116,6 +2159,34 @@ int MakeStereoString( AT_NUMB *at1, return nLen; } +int MakeEnhStereoString( int **enh_stereo, + int nof_units, + INCHI_IOS_STRING *strbuf, + int nCtMode, + int *bOverflow ) +{ + int tot_len = 0; + + if (nof_units > 0) { + tot_len += MakeDelim( "(", strbuf, bOverflow ); + for (int i = 0; i < nof_units; i++) { + for (int j = 0; j < enh_stereo[i][1]; j++) { + + MakeMult_EnhStereo( enh_stereo[i][2 + j], "", strbuf, nCtMode, bOverflow ); + + if ((j + 1) < enh_stereo[i][1]) { + tot_len += MakeDelim( ",", strbuf, bOverflow ); + } + } + if (i + 1 < nof_units) { + tot_len += MakeDelim( ";", strbuf, bOverflow ); + } + } + tot_len += MakeDelim( ")", strbuf, bOverflow ); + } + return tot_len; +} + #ifdef ALPHA_BASE #if ( ALPHA_BASE != 27 ) diff --git a/INCHI-1-SRC/INCHI_BASE/src/strutil.h b/INCHI-1-SRC/INCHI_BASE/src/strutil.h index 14af75ba..2fbec84b 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/strutil.h +++ b/INCHI-1-SRC/INCHI_BASE/src/strutil.h @@ -407,9 +407,9 @@ extern "C" * @brief Compares stereo information of two structures * * @param s1 Pointer to stereo information of first structure - * @param eql1 Flag for stereo information check + * @param eql1 Flag for stereo information check (EQL_EXISTS, EQL_SP3, EQL_SP3_INV, EQL_SP2) * @param s2 Pointer to stereo information of second structure - * @param eql2 Flag for stereo information check + * @param eql2 Flag for stereo information check (EQL_EXISTS, EQL_SP3, EQL_SP3_INV, EQL_SP2) * @param bRelRac Flag to compare racemic stereo information * @return int 0 if unequal, 1 if equal */ diff --git a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp index ea2c2618..1160233e 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichimain.cpp @@ -317,7 +317,8 @@ TEST(test_ichimain, test_ProcessMultipleInputFiles_2mol_files) char tmpl[] = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures/inchi_mol_test_XXXXXX"; char *tmpd = mkdtemp(tmpl); - ASSERT_NE(tmpd, nullptr); + + EXPECT_NE(tmpd, nullptr); std::vector dist_paths; for (auto cur_filename : input_mols) { diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp index 419f4217..67b5aefc 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt1.cpp @@ -45,6 +45,84 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer) } +TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_b_1) +{ + int num_at = 2; + int found_num_bonds = 0; + int found_num_isotopic = 0; + + CANON_GLOBALS cg = {0}; + INCHI_IOSTREAM out_file = {0}; + INCHI_IOS_STRING strbuf = {0}; + INCHI_OUT_CTL io = {0}; + INCHI_SORT inchi_sort = {0}; + inp_ATOM *atoms = CreateInpAtom(num_at); + + atoms[0].valence = 1; + // atoms[0].el_number = (U_CHAR)get_periodic_table_number("C"); + // atoms[0].orig_at_number = 4; + // atoms[0].neighbor[0] = 3; + // atoms[0].bond_type[0] = 2; + + atoms[1].valence = 1; + // atoms[1].el_number = (U_CHAR)get_periodic_table_number("C"); + // atoms[1].orig_at_number = 3; + // atoms[1].neighbor[0] = 4; + // atoms[1].bond_type[0] = 2; + + INChI *inchi = Alloc_INChI(atoms, num_at, &found_num_bonds, &found_num_isotopic, 0); + + inchi->nNumberOfAtoms = num_at; + + int bond_atom1[1] = {4}; + int bond_atom2[1] = {3}; + S_CHAR b_parity[1] = {1}; // 1 = -, 2 = + + + for (int i = 0; i < found_num_bonds; i++) { + inchi->Stereo->nBondAtom1[i] = bond_atom1[i]; + inchi->Stereo->nBondAtom2[i] = bond_atom2[i]; + inchi->Stereo->b_parity[i] = b_parity[i]; + } + + // inchi->Stereo->nCompInv2Abs = 1; + inchi->Stereo->nNumberOfStereoBonds = 1; + // inchi->Stereo->nNumberOfStereoCenters = 0; + + inchi_sort.pINChI[0] = inchi; + + io.pINChISort = &inchi_sort; + io.num_components = 1; + + // io.bRelativeStereo[0] = 0; + // io.bRacemicStereo[0] = 0; + + io.sDifSegs[0][DIFS_b_SBONDS] = DIFV_OUTPUT_FILL_T; // b + // io.sDifSegs[0][DIFS_t_SATOMS] = DIFV_OUTPUT_FILL_T; // t + // io.sDifSegs[0][DIFS_m_SP3INV] = DIFV_OUTPUT_FILL_T; // m + // io.sDifSegs[0][DIFS_s_STYPE] = DIFV_OUTPUT_FILL_T; // s + io.nCurINChISegment = 0; + io.iCurTautMode = 0; + io.bPlainTextTags = 2; + io.nTag = 2; + io.bTag1 = IL_STER; + io.bTag2 = IL_STER | IL_TYPS; + io.bOutType = OUT_TN; + + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + inchi_ios_init(&out_file, INCHI_IOS_TYPE_STRING, nullptr); + + int ret = OutputINCHI_StereoLayer(&cg, &out_file, &strbuf, &io, (char*)"", (char*)""); + + EXPECT_EQ(std::string(out_file.s.pStr), "/b4-3-"); + EXPECT_EQ(ret, 0); + + inchi_strbuf_close(&strbuf); + inchi_ios_close(&out_file); + + FreeInpAtom(&atoms); + Free_INChI(&inchi); +} + TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_m0) { CANON_GLOBALS cg = {0}; @@ -224,7 +302,6 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_s3) io.sDifSegs[0][DIFS_s_STYPE] = DIFV_OUTPUT_FILL_T; - io.nCurINChISegment = 0; io.iCurTautMode = 0; io.bPlainTextTags = 1; @@ -248,32 +325,86 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_s3) } -TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_enh_stereo_1) +TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_layers_t) { + + int num_at = 8; + int found_num_bonds = 0; + int found_num_isotopic = 0; + CANON_GLOBALS cg = {0}; INCHI_IOSTREAM out_file = {0}; INCHI_IOS_STRING strbuf = {0}; INCHI_OUT_CTL io = {0}; + INCHI_SORT inchi_sort = {0}; + AT_NUMB numbers[8] = {3,4,5,6,7,8,9,10}; + S_CHAR parities[8] = {1,1,2,2,1,2,2,1};// -,-,+,+,-,+,+,- + inp_ATOM *at = CreateInpAtom(num_at); + INChI *inchi = Alloc_INChI(at, num_at, &found_num_bonds, &found_num_isotopic, 0); - int num_at = 8; - int num_bonds = 0; - static AT_NUMB numbers[8] = {3,4,5,6,7,8,9,10}; - static S_CHAR parities[8] = {1,1,2,2,1,2,2,1};// -,-,+,+,-,+,+,- + inchi->nNumberOfAtoms = num_at; + inchi->Stereo->nCompInv2Abs = 1; + inchi->Stereo->nNumberOfStereoBonds = 0; + inchi->Stereo->nNumberOfStereoCenters = num_at; + + for (int i = 0; i < num_at; i++) { + inchi->Stereo->nNumber[i] = numbers[i]; + inchi->Stereo->t_parity[i] = parities[i]; + } + + inchi_sort.pINChI[0] = inchi; + + io.pINChISort = &inchi_sort; + io.num_components = 1; + io.bRelativeStereo[0] = 0; + io.bRacemicStereo[0] = 1; + // io.sDifSegs[0][DIFS_b_SBONDS] = DIFV_OUTPUT_FILL_T; // b + io.sDifSegs[0][DIFS_t_SATOMS] = DIFV_OUTPUT_FILL_T; // t + // io.sDifSegs[0][DIFS_m_SP3INV] = DIFV_OUTPUT_FILL_T; // m + // io.sDifSegs[0][DIFS_s_STYPE] = DIFV_OUTPUT_FILL_T; // s + io.nCurINChISegment = 0; + io.iCurTautMode = 0; + io.bPlainTextTags = 2; /* 0 => no plain tags, 1=> plain text tags, 2=>plaintext tags without consecutive // */ + io.nTag = 2; + io.bTag1 = IL_STER; + io.bTag2 = IL_STER | IL_TYPS; + io.bOutType = OUT_TN; + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + inchi_ios_init(&out_file, INCHI_IOS_TYPE_STRING, nullptr); + + int ret = OutputINCHI_StereoLayer(&cg, &out_file, &strbuf, &io, (char*)"", (char*)""); + + EXPECT_EQ(std::string(out_file.s.pStr), "/t3-,4-,5+,6+,7-,8+,9+,10-"); + EXPECT_EQ(ret, 0); + inchi_strbuf_close(&strbuf); + inchi_ios_close(&out_file); + FreeInpAtom(&at); + Free_INChI(&inchi); +} - // INChI *inchi = new INChI; - // inchi->nNumberOfAtoms = num_at; - // inchi->Stereo = stereo; +TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_layers_t_m_s) +{ + int num_at = 8; int found_num_bonds = 0; int found_num_isotopic = 0; + + CANON_GLOBALS cg = {0}; + INCHI_IOSTREAM out_file = {0}; + INCHI_IOS_STRING strbuf = {0}; + INCHI_OUT_CTL io = {0}; + INCHI_SORT inchi_sort = {0}; + AT_NUMB numbers[8] = {3,4,5,6,7,8,9,10}; + S_CHAR parities[8] = {1,1,2,2,1,2,2,1};// -,-,+,+,-,+,+,- inp_ATOM *at = CreateInpAtom(num_at); - static INChI *inchi = Alloc_INChI(at, num_at, &found_num_bonds, &found_num_isotopic, 0); + INChI *inchi = Alloc_INChI(at, num_at, &found_num_bonds, &found_num_isotopic, 0); inchi->nNumberOfAtoms = num_at; - + inchi->Stereo->nCompInv2Abs = 1; + inchi->Stereo->nNumberOfStereoBonds = 0; inchi->Stereo->nNumberOfStereoCenters = num_at; for (int i = 0; i < num_at; i++) { @@ -281,28 +412,19 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_enh_stereo_1) inchi->Stereo->t_parity[i] = parities[i]; } - inchi->Stereo->nCompInv2Abs = 1; - inchi->Stereo->nNumberOfStereoBonds = 0; - inchi->Stereo->b_parity = NULL; - - - - static INCHI_SORT sort = {0}; - sort.pINChI[0] = inchi; - - io.pINChISort = &sort; + inchi_sort.pINChI[0] = inchi; + io.pINChISort = &inchi_sort; io.num_components = 1; io.bRelativeStereo[0] = 0; io.bRacemicStereo[0] = 1; - - io.sDifSegs[0][DIFS_b_SBONDS] = DIFV_OUTPUT_FILL_T; - io.sDifSegs[0][DIFS_t_SATOMS] = DIFV_OUTPUT_FILL_T; - io.sDifSegs[0][DIFS_m_SP3INV] = DIFV_OUTPUT_FILL_T; - io.sDifSegs[0][DIFS_s_STYPE] = DIFV_OUTPUT_FILL_T; + io.sDifSegs[0][DIFS_b_SBONDS] = DIFV_OUTPUT_FILL_T; // b + io.sDifSegs[0][DIFS_t_SATOMS] = DIFV_OUTPUT_FILL_T; // t + io.sDifSegs[0][DIFS_m_SP3INV] = DIFV_OUTPUT_FILL_T; // m + io.sDifSegs[0][DIFS_s_STYPE] = DIFV_OUTPUT_FILL_T; // s io.nCurINChISegment = 0; io.iCurTautMode = 0; - io.bPlainTextTags = 1; + io.bPlainTextTags = 2; /* 0 => no plain tags, 1=> plain text tags, 2=>plaintext tags without consecutive // */ io.nTag = 2; io.bTag1 = IL_STER; io.bTag2 = IL_STER | IL_TYPS; @@ -313,7 +435,7 @@ TEST(test_ichiprt1, test_OutputINCHI_StereoLayer_enh_stereo_1) int ret = OutputINCHI_StereoLayer(&cg, &out_file, &strbuf, &io, (char*)"", (char*)""); - EXPECT_EQ(std::string(out_file.s.pStr), "/t3-,4-,5+,6+,7-,8+,9+,10-/m0/s3/"); + EXPECT_EQ(std::string(out_file.s.pStr), "/t3-,4-,5+,6+,7-,8+,9+,10-/m0/s3"); EXPECT_EQ(ret, 0); inchi_strbuf_close(&strbuf); diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt1_enhancedStereo.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt1_enhancedStereo.cpp new file mode 100644 index 00000000..c33fda8d --- /dev/null +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt1_enhancedStereo.cpp @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include +#include +#include + +extern "C" +{ +#include "../../../INCHI-1-SRC/INCHI_BASE/src/ichi_io.h" +#include "../../../INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c" +#include "../../../INCHI-1-SRC/INCHI_BASE/src/strutil.c" +#include "../../../INCHI-1-SRC/INCHI_BASE/src/ichimake.h" +#include "../../../INCHI-1-SRC/INCHI_BASE/src/ichicano.h" +} + + +TEST(test_ichiprt1_enhancedStereo, test_OutputINCHI_StereoLayer_enhanced_stereo_1) +{ + + CANON_GLOBALS cg = {0}; + INCHI_IOSTREAM out_file = {0}; + INCHI_IOS_STRING strbuf = {0}; + INCHI_OUT_CTL io = {0}; + ORIG_ATOM_DATA *oad; + + oad = (ORIG_ATOM_DATA *)inchi_calloc(1, sizeof(ORIG_ATOM_DATA)); + oad->v3000 = (OAD_V3000 *)inchi_calloc(1, sizeof(OAD_V3000)); + + oad->v3000->n_collections = 5; + + oad->v3000->n_steabs = 1; + + oad->v3000->lists_steabs = (int **)inchi_calloc(1, sizeof(int*)); + for (int i = 0; i < oad->v3000->n_steabs; i++) { + oad->v3000->lists_steabs[i] = (int *)inchi_calloc(1, sizeof(int)); + } + + // STEABS ATOMS=(2 4 5) + oad->v3000->lists_steabs[0][0] = 1; // - not used + oad->v3000->lists_steabs[0][1] = 2; // number of members in collection + oad->v3000->lists_steabs[0][2] = 4; // member atom numbers + oad->v3000->lists_steabs[0][3] = 5; // member atom numbers + + // STERAC2 ATOMS=(1 1) + oad->v3000->n_sterac = 2; + + oad->v3000->lists_sterac = (int **)inchi_calloc(1, sizeof(int*)); + for (int i = 0; i < oad->v3000->n_sterac; i++) { + oad->v3000->lists_sterac[i] = (int *)inchi_calloc(1, sizeof(int)); + } + + oad->v3000->lists_sterac[0][0] = 2; // n from "STERACn" tag + oad->v3000->lists_sterac[0][1] = 1; // number of members in collection + oad->v3000->lists_sterac[0][2] = 1; // member atom numbers + + // STERAC1 ATOMS=(2 2 3) + oad->v3000->lists_sterac[1][0] = 1; // STERAC1 ATOMS=(2 2 3) + oad->v3000->lists_sterac[1][1] = 2; // number of members in collection + oad->v3000->lists_sterac[1][2] = 2; // member atom numbers + oad->v3000->lists_sterac[1][3] = 3; // member atom numbers + + oad->v3000->n_sterel = 2; + oad->v3000->lists_sterel = (int **)inchi_calloc(1, sizeof(int*)); + for (int i = 0; i < oad->v3000->n_sterel; i++) { + oad->v3000->lists_sterel[i] = (int *)inchi_calloc(1, sizeof(int)); + } + + // STEREL1 ATOMS=(2 12 13) + oad->v3000->lists_sterel[0][0] = 1; // n from "STERELn" tag + oad->v3000->lists_sterel[0][1] = 2; // number of members in collection + oad->v3000->lists_sterel[0][2] = 12; // member atom numbers + oad->v3000->lists_sterel[0][3] = 13; // member atom numbers + + // STEREL2 ATOMS=(1 14) + oad->v3000->lists_sterel[1][0] = 2; // n from "STERELn" tag + oad->v3000->lists_sterel[1][1] = 1; // number of members in collection + oad->v3000->lists_sterel[1][2] = 14; // member atom numbers + + io.sDifSegs[0][DIFS_s_STYPE] = DIFV_OUTPUT_FILL_T; + + io.nCurINChISegment = 0; + io.iCurTautMode = 0; + io.bPlainTextTags = 1; + io.bRelativeStereo[0] = 0; + io.bRacemicStereo[0] = 0; + io.bAlways = 0; + io.nTag = 2; // plain text + io.bTag1 = IL_STER; + io.bTag2 = IL_STER | IL_TYPS; + + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + inchi_ios_init(&out_file, INCHI_IOS_TYPE_STRING, nullptr); + + int ret = OutputINCHI_StereoLayer_EnhancedStereo(&cg, &out_file, &strbuf, &io, oad, (char*)"", (char*)""); + + EXPECT_EQ(std::string(strbuf.pStr), "/s1(4,5)2(12,13;14)3(1;2,3)"); + EXPECT_EQ(ret, 0); + + inchi_strbuf_close(&strbuf); + inchi_ios_close(&out_file); +} + diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp index 2244420d..e9d9d4a8 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp @@ -21,6 +21,7 @@ TEST(test_ichiprt2, MakeStereoString_outputs_expected_sp3_string) EXPECT_EQ(strbuf.nUsedLength, strlen(strbuf.pStr)); EXPECT_NE(std::string(strbuf.pStr).find("3-,4-,5+,6+,7-,8+,9+,10-"), std::string::npos); + EXPECT_EQ(std::string(strbuf.pStr), "3-,4-,5+,6+,7-,8+,9+,10-"); EXPECT_EQ(strbuf.pStr[0], '3'); // Should start with 3- EXPECT_EQ(bOverflow, 0); EXPECT_EQ(ret, 24); @@ -73,3 +74,112 @@ TEST(test_ichiprt2, MakeMult_mult_eq_1_does_nothing) inchi_strbuf_close(&strbuf); } + +TEST(test_ichiprt2, Eql_INChI_Stereo_sp2_equal) +{ + // Setup two identical SP2 stereo objects + INChI_Stereo s1 = {0}, s2 = {0}; + int num_bonds = 2; + AT_NUMB bond_atom1[2] = {1, 3}; + AT_NUMB bond_atom2[2] = {2, 4}; + S_CHAR b_parity[2] = {1, 2}; + + s1.nNumberOfStereoBonds = num_bonds; + s1.nBondAtom1 = bond_atom1; + s1.nBondAtom2 = bond_atom2; + s1.b_parity = b_parity; + + s2.nNumberOfStereoBonds = num_bonds; + s2.nBondAtom1 = bond_atom1; + s2.nBondAtom2 = bond_atom2; + s2.b_parity = b_parity; + + // Should be equal + EXPECT_EQ(Eql_INChI_Stereo(&s1, EQL_SP2, &s2, EQL_SP2, 0), 1); +} + +TEST(test_ichiprt2, Eql_INChI_Stereo_sp2_not_equal) +{ + // Setup two different SP2 stereo objects + INChI_Stereo s1 = {0}, s2 = {0}; + AT_NUMB bond_atom1_1[2] = {1, 3}; + AT_NUMB bond_atom2_1[2] = {2, 4}; + S_CHAR b_parity_1[2] = {1, 2}; + + AT_NUMB bond_atom1_2[2] = {1, 5}; + AT_NUMB bond_atom2_2[2] = {2, 6}; + S_CHAR b_parity_2[2] = {1, 1}; + + s1.nNumberOfStereoBonds = 2; + s1.nBondAtom1 = bond_atom1_1; + s1.nBondAtom2 = bond_atom2_1; + s1.b_parity = b_parity_1; + + s2.nNumberOfStereoBonds = 2; + s2.nBondAtom1 = bond_atom1_2; + s2.nBondAtom2 = bond_atom2_2; + s2.b_parity = b_parity_2; + + // Should not be equal + EXPECT_EQ(Eql_INChI_Stereo(&s1, EQL_SP2, &s2, EQL_SP2, 0), 0); +} + +TEST(test_ichiprt2, Eql_INChI_Stereo_sp2_exists) +{ + // s1 has stereo, s2 is nullptr, eql2 is EQL_EXISTS + INChI_Stereo s1 = {0}; + AT_NUMB bond_atom1[1] = {1}; + AT_NUMB bond_atom2[1] = {2}; + S_CHAR b_parity[1] = {1}; + + s1.nNumberOfStereoBonds = 1; + s1.nBondAtom1 = bond_atom1; + s1.nBondAtom2 = bond_atom2; + s1.b_parity = b_parity; + + EXPECT_EQ(Eql_INChI_Stereo(&s1, EQL_SP2, nullptr, EQL_EXISTS, 0), 1); +} + +TEST(test_ichiprt2, Eql_INChI_Stereo_sp3_equal) +{ + // Setup two identical SP3 stereo objects + INChI_Stereo s1 = {0}, s2 = {0}; + int num_centers = 2; + AT_NUMB nNumber1[2] = {5, 6}; + S_CHAR t_parity1[2] = {1, 2}; + + s1.nNumberOfStereoCenters = num_centers; + s1.nNumber = nNumber1; + s1.t_parity = t_parity1; + + s2.nNumberOfStereoCenters = num_centers; + s2.nNumber = nNumber1; + s2.t_parity = t_parity1; + + // Should be equal + EXPECT_EQ(Eql_INChI_Stereo(&s1, EQL_SP3, &s2, EQL_SP3, 0), 1); +} + +TEST(test_ichiprt2, Eql_INChI_Stereo_sp3_not_equal) +{ + // Setup two different SP3 stereo objects + INChI_Stereo s1 = {0}, s2 = {0}; + int num_centers = 2; + AT_NUMB nNumber1[2] = {5, 6}; + S_CHAR t_parity1[2] = {1, 2}; + + AT_NUMB nNumber2[2] = {7, 8}; + S_CHAR t_parity2[2] = {2, 1}; + + s1.nNumberOfStereoCenters = num_centers; + s1.nNumber = nNumber1; + s1.t_parity = t_parity1; + + s2.nNumberOfStereoCenters = num_centers; + s2.nNumber = nNumber2; + s2.t_parity = t_parity2; + + // Should not be equal + EXPECT_EQ(Eql_INChI_Stereo(&s1, EQL_SP3, &s2, EQL_SP3, 0), 0); +} + diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp index be614485..c98a9b9f 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp @@ -9,10 +9,132 @@ extern "C" #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichimake.h" } +TEST(test_ichiprt3, test_str_Sp2_outputs_expected_sp2_string_1) +{ + int num_at = 2; + int num_bonds = 1; + int bond_atom1[1] = {4}; + int bond_atom2[1] = {3}; + S_CHAR b_parity[1] = {1}; // 1 = -, 2 = + + + INChI_Stereo* stereo = Alloc_INChI_Stereo(num_at, num_bonds); + stereo->nNumberOfStereoBonds = num_bonds; + for (int i = 0; i < num_bonds; i++) { + stereo->nBondAtom1[i] = bond_atom1[i]; + stereo->nBondAtom2[i] = bond_atom2[i]; + stereo->b_parity[i] = b_parity[i]; + } + + INChI inchi = {0}; + inchi.nNumberOfAtoms = num_at; + inchi.Stereo = stereo; + + INCHI_SORT inchi_sort = {0}; + inchi_sort.pINChI[0] = &inchi; + + INCHI_IOS_STRING strbuf = {0}; + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + + int bOverflow = 0; + int bOutputType = OUT_N1; // OUT_TN + int taut_mode = 0; // CT_MODE_ABC_NUMBERS + int num_components = 1; + + int bSecondNonTautPass = 0; + int bOmitRepetitions = 0; + int bUseMulipliers = 1; + + int ret = str_Sp2( + &inchi_sort, + NULL, + &strbuf, + &bOverflow, + bOutputType, + taut_mode, + num_components, + bSecondNonTautPass, + bOmitRepetitions, + bUseMulipliers + ); + + // The expected output is "1-2Z,3-4E" + EXPECT_EQ(strbuf.nUsedLength, strlen(strbuf.pStr)); + EXPECT_EQ(std::string(strbuf.pStr), "4-3-"); + EXPECT_EQ(strbuf.pStr[0], '4'); + EXPECT_EQ(bOverflow, 0); + + // The return value should be the length of the output string + EXPECT_EQ(ret, 4); + + inchi_strbuf_close(&strbuf); + Free_INChI_Stereo(stereo); +} + +TEST(test_ichiprt3, test_str_Sp2_outputs_expected_sp2_string_2) +{ + int num_at = 4; + int num_bonds = 2; + int bond_atom1[2] = {1, 3}; + int bond_atom2[2] = {2, 4}; + S_CHAR b_parity[2] = {1, 2}; // 1 = -, 2 = + + + INChI_Stereo* stereo = Alloc_INChI_Stereo(num_at, num_bonds); + stereo->nNumberOfStereoBonds = num_bonds; + for (int i = 0; i < num_bonds; i++) { + stereo->nBondAtom1[i] = bond_atom1[i]; + stereo->nBondAtom2[i] = bond_atom2[i]; + stereo->b_parity[i] = b_parity[i]; + } + + INChI inchi = {0}; + inchi.nNumberOfAtoms = num_at; + inchi.Stereo = stereo; + + INCHI_SORT inchi_sort = {0}; + inchi_sort.pINChI[0] = &inchi; + + INCHI_IOS_STRING strbuf = {0}; + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + + int bOverflow = 0; + int bOutputType = OUT_N1; // OUT_TN + int taut_mode = 0; // CT_MODE_ABC_NUMBERS + int num_components = 1; + + int bSecondNonTautPass = 0; + int bOmitRepetitions = 0; + int bUseMulipliers = 1; + + int ret = str_Sp2( + &inchi_sort, + NULL, + &strbuf, + &bOverflow, + bOutputType, + taut_mode, + num_components, + bSecondNonTautPass, + bOmitRepetitions, + bUseMulipliers + ); + + // The expected output is "1-2Z,3-4E" + EXPECT_EQ(strbuf.nUsedLength, strlen(strbuf.pStr)); + EXPECT_EQ(std::string(strbuf.pStr), "1-2-,3-4+"); + EXPECT_EQ(strbuf.pStr[0], '1'); + EXPECT_EQ(bOverflow, 0); + + // The return value should be the length of the output string + EXPECT_EQ(ret, 9); + + inchi_strbuf_close(&strbuf); + Free_INChI_Stereo(stereo); +} + TEST(test_ichiprt3, test_str_Sp3_outputs_expected_sp3_string) { int numbers[8] = {3,4,5,6,7,8,9,10}; - S_CHAR parities[8] = {1,1,2,2,1,2,2,1}; + S_CHAR parities[8] = {1,1,2,2,1,2,2,1}; // 1 = -, 2 = + int num_at = 8; static INChI_Stereo *stereo = Alloc_INChI_Stereo( num_at, 0 ); stereo->nNumberOfStereoCenters = num_at; @@ -31,21 +153,27 @@ TEST(test_ichiprt3, test_str_Sp3_outputs_expected_sp3_string) inchi.nNumberOfAtoms = 10; inchi.Stereo = stereo; - INCHI_SORT sort = {0}; - sort.pINChI[0] = &inchi; + INCHI_SORT inchi_sort = {0}; + inchi_sort.pINChI[0] = &inchi; INCHI_IOS_STRING strbuf = {0}; inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); int bOverflow = 0; - int ret = str_Sp3(&sort, NULL, &strbuf, &bOverflow, 0, 0, 1, 0, 0, 0, 0); + int num_components = 1; + + //io->bRelRac = io->bRelativeStereo[io->iCurTautMode] || io->bRacemicStereo[io->iCurTautMode]; + int bIsotopicRelativeStereo = 0; // INCHI_FLAG_REL_STEREO + int bIsotopicRacemicStereo = 0; // INCHI_FLAG_RAC_STEREO + + int bRelRac = bIsotopicRelativeStereo || bIsotopicRacemicStereo; + + int ret = str_Sp3(&inchi_sort, NULL, &strbuf, &bOverflow, 0, 0, num_components, bRelRac, 0, 0, 0); - // Check that strbuf contains the expected substring EXPECT_EQ(strbuf.nUsedLength, strlen(strbuf.pStr)); - // EXPECT_NE(std::string(strbuf.pStr).find("3-,4-,5+,6+,7-,8+,9+,10-"), std::string::npos); EXPECT_EQ(std::string(strbuf.pStr), "3-,4-,5+,6+,7-,8+,9+,10-"); - EXPECT_EQ(strbuf.pStr[0], '3'); // Should start with 3- + EXPECT_EQ(strbuf.pStr[0], '3'); EXPECT_EQ(bOverflow, 0); EXPECT_EQ(ret, 24); From 892521aebfb366743541bb164a218c5c1b5a21e0 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Fri, 9 Jan 2026 14:40:58 +0000 Subject: [PATCH 50/69] Added functions for changing parities based on abs, rel, rac --- INCHI-1-SRC/INCHI_BASE/src/ichimain.h | 2 +- INCHI-1-SRC/INCHI_BASE/src/ichimake.h | 5 +- INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c | 94 ++++++++++--------- INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c | 34 ++++++- INCHI-1-SRC/INCHI_BASE/src/strutil.c | 88 ++++++++++++++--- INCHI-1-SRC/INCHI_BASE/src/strutil.h | 22 +++++ INCHI-1-SRC/INCHI_BASE/src/util.c | 85 +++++++++-------- .../test_ichiprt1_enhancedStereo.cpp | 39 +++++++- .../tests/test_unit/test_ichiprt3.cpp | 6 +- 9 files changed, 263 insertions(+), 112 deletions(-) diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichimain.h b/INCHI-1-SRC/INCHI_BASE/src/ichimain.h index 779d6b3e..c7f45018 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichimain.h +++ b/INCHI-1-SRC/INCHI_BASE/src/ichimain.h @@ -125,7 +125,7 @@ typedef struct tagINCHI_OUT_CTL int iCurTautMode; int num_components; - int nNumRemovedProtons; + int nNumRemovedProtons; int nTag; int bTag1; int bTag2; diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichimake.h b/INCHI-1-SRC/INCHI_BASE/src/ichimake.h index 0669703b..03d55237 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichimake.h +++ b/INCHI-1-SRC/INCHI_BASE/src/ichimake.h @@ -208,7 +208,10 @@ const char *EquString( int EquVal ); INCHI_IOS_STRING *buf, int nCtMode, int *bOverflow ); - int MakeEnhStereoString( int **enh_stereo, + int MakeEnhStereoString( INCHI_SORT *pINChISort, + int bOutType, + int num_components, + int **enh_stereo, int nof_units, INCHI_IOS_STRING *strbuf, int nCtMode, diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c index da530ed5..928f7fb9 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c @@ -1637,6 +1637,11 @@ int OutputINChI1( CANON_GLOBALS *pCG, io.bChargesRadVal[ii] |= 1; } } + + if (ip->bEnhancedStereo) + { + set_EnhancedStereo_t_m_layers(orig_inp_data, pINChI, pINChI_Aux); + } } } if (bCompExists) @@ -1775,14 +1780,11 @@ int OutputINChI1( CANON_GLOBALS *pCG, } /* InChI output: stereo (non-isotopic) */ - // intermediate_result = OutputINCHI_StereoLayer( pCG, out_file, strbuf, &io, pLF, pTAB ); - if (ip->bEnhancedStereo) { intermediate_result = OutputINCHI_StereoLayer_EnhancedStereo( pCG, out_file, strbuf, &io, orig_inp_data, pLF, pTAB ); } else { intermediate_result = OutputINCHI_StereoLayer( pCG, out_file, strbuf, &io, pLF, pTAB ); } - if (intermediate_result != 0) goto exit_function; @@ -3396,9 +3398,9 @@ int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, { if (INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_b_SBONDS] ) || - INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_t_SATOMS] ) || - INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_m_SP3INV] ) || - INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_s_STYPE] )) + INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_t_SATOMS] ) || + INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_m_SP3INV] ) || + INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_s_STYPE] )) { /* stereo */ @@ -3415,8 +3417,8 @@ int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, if (INCHI_SEGM_FILL == io->nSegmAction) { io->tot_len = str_Sp2( io->pINChISort, io->pINChISort2, strbuf, &io->bOverflow, - io->bOutType, io->TAUT_MODE, io->num_components, - io->bSecondNonTautPass, io->bOmitRepetitions, io->bUseMulipliers ); + io->bOutType, io->TAUT_MODE, io->num_components, + io->bSecondNonTautPass, io->bOmitRepetitions, io->bUseMulipliers ); io->bNonTautNonIsoIdentifierNotEmpty += io->bSecondNonTautPass; } @@ -3448,7 +3450,7 @@ int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, { io->tot_len = str_Sp3( io->pINChISort, io->pINChISort2, strbuf, &io->bOverflow, io->bOutType, io->TAUT_MODE, io->num_components, io->bRelRac, - io->bSecondNonTautPass, io->bOmitRepetitions, io->bUseMulipliers ); + io->bSecondNonTautPass, io->bOmitRepetitions, io->bUseMulipliers ); io->bNonTautNonIsoIdentifierNotEmpty += io->bSecondNonTautPass; } @@ -3475,7 +3477,7 @@ int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, if (INCHI_SEGM_FILL == io->nSegmAction) { io->tot_len = str_StereoAbsInv( io->pINChISort, strbuf, - &io->bOverflow, io->bOutType, io->num_components ); + &io->bOverflow, io->bOutType, io->num_components ); io->bNonTautNonIsoIdentifierNotEmpty += io->bSecondNonTautPass; } @@ -3541,19 +3543,20 @@ int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, * @param pTAB Pointer to a string used as the tab or separator character(s). * @return Returns 0 on success, or a non-zero error code on failure. */ -int OutputINCHI_StereoLayer_EnhancedStereo( CANON_GLOBALS *pCG, - INCHI_IOSTREAM *out_file, - INCHI_IOS_STRING *strbuf, - INCHI_OUT_CTL *io, - ORIG_ATOM_DATA *orig_inp_data, - char *pLF, - char *pTAB ) +int OutputINCHI_StereoLayer_EnhancedStereo( + CANON_GLOBALS *pCG, + INCHI_IOSTREAM *out_file, + INCHI_IOS_STRING *strbuf, + INCHI_OUT_CTL *io, + ORIG_ATOM_DATA *orig_inp_data, + char *pLF, + char *pTAB ) { if (INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_b_SBONDS] ) || - INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_t_SATOMS] ) || - INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_m_SP3INV] ) || - INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_s_STYPE] )) + INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_t_SATOMS] ) || + INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_m_SP3INV] ) || + INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_s_STYPE] )) { /* stereo */ @@ -3570,8 +3573,8 @@ int OutputINCHI_StereoLayer_EnhancedStereo( CANON_GLOBALS *pCG, if (INCHI_SEGM_FILL == io->nSegmAction) { io->tot_len = str_Sp2( io->pINChISort, io->pINChISort2, strbuf, &io->bOverflow, - io->bOutType, io->TAUT_MODE, io->num_components, - io->bSecondNonTautPass, io->bOmitRepetitions, io->bUseMulipliers ); + io->bOutType, io->TAUT_MODE, io->num_components, + io->bSecondNonTautPass, io->bOmitRepetitions, io->bUseMulipliers ); io->bNonTautNonIsoIdentifierNotEmpty += io->bSecondNonTautPass; } @@ -3603,7 +3606,7 @@ int OutputINCHI_StereoLayer_EnhancedStereo( CANON_GLOBALS *pCG, { io->tot_len = str_Sp3( io->pINChISort, io->pINChISort2, strbuf, &io->bOverflow, io->bOutType, io->TAUT_MODE, io->num_components, io->bRelRac, - io->bSecondNonTautPass, io->bOmitRepetitions, io->bUseMulipliers ); + io->bSecondNonTautPass, io->bOmitRepetitions, io->bUseMulipliers ); io->bNonTautNonIsoIdentifierNotEmpty += io->bSecondNonTautPass; } @@ -3670,33 +3673,36 @@ int OutputINCHI_StereoLayer_EnhancedStereo( CANON_GLOBALS *pCG, if (INCHI_SEGM_FILL == io->nSegmAction) { io->tot_len += MakeDelim( x_abs, strbuf, &io->bOverflow ); // s1 - io->tot_len += MakeEnhStereoString( - orig_inp_data->v3000->lists_steabs, - orig_inp_data->v3000->n_steabs, - strbuf, - 0, - &io->bOverflow - ); + io->tot_len += MakeEnhStereoString( io->pINChISort, + io->bOutType, + io->num_components, + orig_inp_data->v3000->lists_steabs, + orig_inp_data->v3000->n_steabs, + strbuf, + 0, + &io->bOverflow); io->tot_len += MakeDelim( x_rel, strbuf, &io->bOverflow ); // s2 - io->tot_len += MakeEnhStereoString( - orig_inp_data->v3000->lists_sterel, - orig_inp_data->v3000->n_sterel, - strbuf, - 0, - &io->bOverflow - ); + io->tot_len += MakeEnhStereoString( io->pINChISort, + io->bOutType, + io->num_components, + orig_inp_data->v3000->lists_sterel, + orig_inp_data->v3000->n_sterel, + strbuf, + 0, + &io->bOverflow); io->tot_len += MakeDelim( x_rac, strbuf, &io->bOverflow ); // s3 - io->tot_len += MakeEnhStereoString( - orig_inp_data->v3000->lists_sterac, - orig_inp_data->v3000->n_sterac, - strbuf, - 0, - &io->bOverflow - ); + io->tot_len += MakeEnhStereoString( io->pINChISort, + io->bOutType, + io->num_components, + orig_inp_data->v3000->lists_sterac, + orig_inp_data->v3000->n_sterac, + strbuf, + 0, + &io->bOverflow); io->bNonTautNonIsoIdentifierNotEmpty += io->bSecondNonTautPass; } diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c index 2a40880e..0960fdc1 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c @@ -2159,20 +2159,46 @@ int MakeStereoString( AT_NUMB *at1, return nLen; } -int MakeEnhStereoString( int **enh_stereo, +int MakeEnhStereoString( INCHI_SORT *pINChISort, + int bOutType, + int num_components, + int **enh_stereo, int nof_units, INCHI_IOS_STRING *strbuf, int nCtMode, int *bOverflow ) { int tot_len = 0; + int ii, nUsedLength0; + INCHI_SORT *is, *is0; + INChI_Stereo *Stereo; + INChI *pINChI; + INChI_Aux *pAux; + + if (nof_units <= 0) { + return 0; + } + + is = NULL; + is0 = pINChISort; + + /* For each connected component... */ + for (int cur_c = 0; !*bOverflow && cur_c < num_components; cur_c++) + { + + is = is0 + cur_c; + // pINChI = ( 0 <= ( ii = GET_II( bOutType, is ) ) ) ? is->pINChI[ii] : NULL; + pAux = ( 0 <= ( ii = GET_II( bOutType, is ) ) ) ? is->pINChI_Aux[ii] : NULL; - if (nof_units > 0) { tot_len += MakeDelim( "(", strbuf, bOverflow ); for (int i = 0; i < nof_units; i++) { for (int j = 0; j < enh_stereo[i][1]; j++) { - MakeMult_EnhStereo( enh_stereo[i][2 + j], "", strbuf, nCtMode, bOverflow ); + int orig_atom_num = enh_stereo[i][2 + j]; + int canon_atom_num = get_canonical_atom_number(pAux, orig_atom_num); + + //tot_len += MakeMult_EnhStereo( enh_stereo[i][2 + j], "", strbuf, nCtMode, bOverflow ); + tot_len += MakeMult_EnhStereo( canon_atom_num, "", strbuf, nCtMode, bOverflow ); if ((j + 1) < enh_stereo[i][1]) { tot_len += MakeDelim( ",", strbuf, bOverflow ); @@ -2183,7 +2209,9 @@ int MakeEnhStereoString( int **enh_stereo, } } tot_len += MakeDelim( ")", strbuf, bOverflow ); + } + return tot_len; } diff --git a/INCHI-1-SRC/INCHI_BASE/src/strutil.c b/INCHI-1-SRC/INCHI_BASE/src/strutil.c index 89f8d7d1..4df9e9ed 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/strutil.c +++ b/INCHI-1-SRC/INCHI_BASE/src/strutil.c @@ -1096,12 +1096,12 @@ int remove_ion_pairs( int num_atoms, inp_ATOM *at ) num_N_minus++; } #ifdef FIX_P_IV_Plus_O_Minus - num_P_IV_plus += a->el_number != EL_NUMBER_N && + num_P_IV_plus += a->el_number != EL_NUMBER_N && chrg == 1 && - a->valence == 4 && + a->valence == 4 && a->chem_bonds_valence == 4; /* added 2010-03-17 DT */ -#endif - break; +#endif + break; } } else if (!chrg && a->chem_bonds_valence + NUMH( a, 0 ) == 2 && @@ -3674,7 +3674,7 @@ int move_explicit_Hcation( inp_ATOM *at, /* connect H to at[iat] */ val = at[iat].valence; - + #pragma warning (push) #pragma warning (disable: 6386) if (val < MAXVAL) @@ -4269,6 +4269,70 @@ int cmp_components( const void *a1, const void *a2 ) return ret; } +int get_canonical_atom_number( INChI_Aux *aux, + int orig_atom_num) +{ + for (int canon_num = 1; canon_num <= aux->nNumberOfAtoms; canon_num++) { + if (aux->nOrigAtNosInCanonOrd[canon_num - 1] == orig_atom_num) { + return canon_num; // Found canonical atom number + } + } + return -1; // Not found +} + + +int set_EnhancedStereo_t_m_layers( ORIG_ATOM_DATA *orig_inp_data, + INChI *inchi, + INChI_Aux *aux) +{ + int ret = 0; + + if (orig_inp_data->v3000->n_steabs > 0) + { + + int **enh_stereo = orig_inp_data->v3000->lists_steabs; + for (int i = 0; i < orig_inp_data->v3000->n_steabs; i++) { + for (int j = 0; j < enh_stereo[i][1]; j++) { + int orig_atom_num = enh_stereo[i][2 + j]; + AT_NUMB canon_atom_num = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num); + + const AT_NUMB *atom_idx_pos = is_in_the_list(inchi->Stereo->nNumber, canon_atom_num, inchi->Stereo->nNumberOfStereoCenters); + if (atom_idx_pos) + { + int idx = (int)(*atom_idx_pos); + if (inchi->Stereo->t_parity[idx] == 2) + { + inchi->Stereo->t_parity[idx] = 1; + inchi->Stereo->nCompInv2Abs = -1; + } + } + } + } + } + // orig_inp_data->v3000->n_steabs; + // orig_inp_data->v3000->lists_steabs; + + // pINChI->Stereo->nCompInv2Abs; + // -1 --> 1 + // 1 --> 0 + + // orig_inp_data->v3000->n_sterel; + // orig_inp_data->v3000->lists_sterel; + + // orig_inp_data->v3000->n_sterac; + // orig_inp_data->v3000->lists_sterac; + + // get_canonical_atom_number; + + + // pINChI->Stereo->nNumber; + // pINChI->Stereo->t_parity + // 1 --> - + // 2 --> + + + + return ret; +} /**************************************************************************** Set the (disconnected) component numbers in ORIG_ATOM_DATA 'at[*].component' @@ -4324,7 +4388,7 @@ int MarkDisconnectedComponents( ORIG_ATOM_DATA *orig_at_data, nPrevAtom = (AT_NUMB*)inchi_calloc(num_at, sizeof(nPrevAtom[0])); iNeigh = (S_CHAR*)inchi_calloc(num_at, sizeof(iNeigh[0])); - if (!nNewCompNumber || !nPrevAtom || !iNeigh) /* nNewCompNumber: for non-recursive DFS only: */ + if (!nNewCompNumber || !nPrevAtom || !iNeigh) /* nNewCompNumber: for non-recursive DFS only: */ { goto exit_function; } @@ -4333,7 +4397,7 @@ int MarkDisconnectedComponents( ORIG_ATOM_DATA *orig_at_data, /* Mark and count; avoid deep DFS recursion: it may make verifying software unhappy */ /* nNewCompNumber[i] will contain new component number for atoms at[i], i=0..num_at-1 */ - + for (j = 0; j < num_at; j++) { if (!nNewCompNumber[j]) @@ -4709,7 +4773,7 @@ int Free_INChI_Members( INChI *pINChI ) qzfree(pINChI->IsotopicAtom); qzfree(pINChI->IsotopicTGroup); qzfree(pINChI->nPossibleLocationsOfIsotopicH); - qzfree( pINChI->Stereo ); + qzfree( pINChI->Stereo ); qzfree( pINChI->StereoIsotopic ); qzfree( pINChI->szHillFormula ); } @@ -5004,7 +5068,7 @@ void CompAtomData_GetNumMapping( COMP_ATOM_DATA *adata, int *orig_num, int *curr ****************************************************************************/ int imat_new( int m, int n, int ***a ) { - int i; + int i; if (m == 0 || n == 0) { return 0; @@ -5106,7 +5170,7 @@ subgraf *subgraf_new( ORIG_ATOM_DATA *orig_inp_data, sg->orig2node[sg->nodes[i]] = i; } - /* Create and fill subgraph adjacency matrix based on nodes/orig atom numbers + /* Create and fill subgraph adjacency matrix based on nodes/orig atom numbers and connections stored in orig_inp_data */ sg->adj = (subgraf_edge **) inchi_calloc( nnodes, sizeof( subgraf_edge * ) ); if (!sg->adj) @@ -5266,7 +5330,7 @@ void subgraf_pathfinder_free( subgraf_pathfinder *spf ) /**************************************************************************** - Find path(s) from subgraf node spf->start to spf->end + Find path(s) from subgraf node spf->start to spf->end and fill bonds[nbonds] and atoms[natoms] Do not traverse through supplied forbidden edges (if not zero/NULL) ****************************************************************************/ @@ -5298,7 +5362,7 @@ void subgraf_pathfinder_run( subgraf_pathfinder *spf, continue; } if (nforbidden && forbidden) - { + { skip = 0; for (f = 0; f < nforbidden; f++) { diff --git a/INCHI-1-SRC/INCHI_BASE/src/strutil.h b/INCHI-1-SRC/INCHI_BASE/src/strutil.h index 2fbec84b..b57aed17 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/strutil.h +++ b/INCHI-1-SRC/INCHI_BASE/src/strutil.h @@ -57,6 +57,28 @@ extern "C" struct tagTautomerGroupsInfo; struct tagCANON_GLOBALS; + /** + * @brief Set the enhanced stereochemistry for t- and m-layers + * + * @param orig_inp_data + * @param inchi + * @param aux + * @return int + */ + int set_EnhancedStereo_t_m_layers(ORIG_ATOM_DATA *orig_inp_data, + INChI *inchi, + INChI_Aux *aux); + + /** + * @brief Get the canonical atom number object + * + * @param aux Pointer to INChI_Aux data structure + * @param orig_atom_num Original atom number + * @return Returns canonical atom number if found, -1 if not + */ + int get_canonical_atom_number(INChI_Aux *aux, + int orig_atom_num); + /** * @brief Extract one (connected) component * diff --git a/INCHI-1-SRC/INCHI_BASE/src/util.c b/INCHI-1-SRC/INCHI_BASE/src/util.c index 72a518bb..e72f89e8 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/util.c +++ b/INCHI-1-SRC/INCHI_BASE/src/util.c @@ -263,10 +263,10 @@ const ELDATA ElData[] = { "Zy", 0, 0, 0.000000000, 0 , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }}, { "Zz", 0, 0, 0.000000000, 0 , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }}, #ifdef INCHI_ZFRAG -{ "Zu", 0, 0, 0.000000000, 0 , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }}, -{ "Zv", 0, 0, 0.000000000, 0 , 0, 1, {{0,}, {0,}, {2,}, {0,}, {0,} }}, -{ "Zw", 0, 0, 0.000000000, 0 , 0, 1, {{0,}, {0,}, {3,}, {0,}, {0,} }}, -{ "Zx", 0, 0, 0.000000000, 0 , 0, 1, {{0,}, {0,}, {1,2,}, {0,}, {0,} }}, +{ "Zu", 0, 0, 0.000000000, 0 , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }}, +{ "Zv", 0, 0, 0.000000000, 0 , 0, 1, {{0,}, {0,}, {2,}, {0,}, {0,} }}, +{ "Zw", 0, 0, 0.000000000, 0 , 0, 1, {{0,}, {0,}, {3,}, {0,}, {0,} }}, +{ "Zx", 0, 0, 0.000000000, 0 , 0, 1, {{0,}, {0,}, {1,2,}, {0,}, {0,} }}, #endif { "", 0, 0, 0.000000000, 0 , 0, 0, {{0,}, {0,}, {0,}, {0,}, {0,} }}, @@ -376,36 +376,36 @@ int get_periodic_table_number( const char* elname ) } /* the single letter (common) elements */ - if (!elname[1]) + if (!elname[1]) { - switch (elname[0]) + switch (elname[0]) { - case 'H': - return EL_NUMBER_H; + case 'H': + return EL_NUMBER_H; break; - case 'B': - return EL_NUMBER_B; + case 'B': + return EL_NUMBER_B; break; - case 'C': - return EL_NUMBER_C; + case 'C': + return EL_NUMBER_C; break; - case 'N': - return EL_NUMBER_N; + case 'N': + return EL_NUMBER_N; break; - case 'O': - return EL_NUMBER_O; + case 'O': + return EL_NUMBER_O; break; - case 'P': - return EL_NUMBER_P; + case 'P': + return EL_NUMBER_P; break; - case 'S': - return EL_NUMBER_S; + case 'S': + return EL_NUMBER_S; break; - case 'F': - return EL_NUMBER_F; + case 'F': + return EL_NUMBER_F; break; - case 'I': - return EL_NUMBER_I; + case 'I': + return EL_NUMBER_I; break; } } @@ -1065,7 +1065,6 @@ AT_NUMB *is_in_the_list( AT_NUMB *pathAtom, AT_NUMB nNextAtom, int nPathLen ) return nPathLen ? pathAtom : NULL; } - /**************************************************************************** Check if integer is in the list ****************************************************************************/ @@ -1150,12 +1149,12 @@ int num_of_H( inp_ATOM *at, int iat ) /****************************************************************************/ U_CHAR ion_el_group( int el ) { - switch ( el ) + switch ( el ) { case EL_NUMBER_C: /* fallthrough */ -#if ( FIX_REM_ION_PAIRS_Si_BUG == 1 ) +#if ( FIX_REM_ION_PAIRS_Si_BUG == 1 ) case EL_NUMBER_SI: -#endif +#endif return EL_NUMBER_C; case EL_NUMBER_N: /* fallthrough */ case EL_NUMBER_P: @@ -1507,17 +1506,17 @@ int MakeRemovedProtonsString( int nNumRemovedProtons, /****************************************************************************/ int get_endpoint_valence( U_CHAR el_number ) -{ - switch (el_number) +{ + switch (el_number) { case EL_NUMBER_O: /* fallthrough */ - case EL_NUMBER_S: - case EL_NUMBER_SE: - case EL_NUMBER_TE: + case EL_NUMBER_S: + case EL_NUMBER_SE: + case EL_NUMBER_TE: return 2; - case EL_NUMBER_N: + case EL_NUMBER_N: return 3; - default: + default: return 0; } } @@ -1529,13 +1528,13 @@ int get_endpoint_valence( U_CHAR el_number ) /****************************************************************************/ int get_endpoint_valence_KET( U_CHAR el_number ) { - switch (el_number) + switch (el_number) { - case EL_NUMBER_C: + case EL_NUMBER_C: return 4; - case EL_NUMBER_O: + case EL_NUMBER_O: return 2; - default: + default: return 0; } } @@ -1768,7 +1767,7 @@ int mystrncpy( char *target, const char *source, unsigned maxlen ) } /* giallu: PR #163 */ - /* Find actual source length first to limit memchr search */ + /* Find actual source length first to limit memchr search */ source_len = (unsigned)strlen(source); if (source_len < maxlen) @@ -1777,12 +1776,12 @@ int mystrncpy( char *target, const char *source, unsigned maxlen ) len = source_len; } else if ((p = (const char*)memchr(source, 0, maxlen))) /* djb-rwth: addressing LLVM warning */ - { + { /* maxlen does not include the found zero termination */ len = (int) ( p - source ); } else - { + { /* reduced length does not include one more byte for zero termination */ len = maxlen - 1; } @@ -1816,7 +1815,7 @@ char* lrtrim( char *p, int* nLen ) len -= i; /* djb-rwth: variable has to be decreased before memmove */ (memmove)(p, p + i, ((long long)len + 1)); /* djb-rwth: now cast operator can be added */ } - + for (; 0 < len && is_ascii( p[len - 1] ) && isspace( p[len - 1] ); len--) { ; diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt1_enhancedStereo.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt1_enhancedStereo.cpp index c33fda8d..fffb967b 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichiprt1_enhancedStereo.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt1_enhancedStereo.cpp @@ -29,7 +29,6 @@ TEST(test_ichiprt1_enhancedStereo, test_OutputINCHI_StereoLayer_enhanced_stereo_ oad->v3000 = (OAD_V3000 *)inchi_calloc(1, sizeof(OAD_V3000)); oad->v3000->n_collections = 5; - oad->v3000->n_steabs = 1; oad->v3000->lists_steabs = (int **)inchi_calloc(1, sizeof(int*)); @@ -78,8 +77,41 @@ TEST(test_ichiprt1_enhancedStereo, test_OutputINCHI_StereoLayer_enhanced_stereo_ oad->v3000->lists_sterel[1][1] = 1; // number of members in collection oad->v3000->lists_sterel[1][2] = 14; // member atom numbers - io.sDifSegs[0][DIFS_s_STYPE] = DIFV_OUTPUT_FILL_T; + INCHI_SORT *inchi_sort = (INCHI_SORT*)inchi_calloc(1, sizeof(INCHI_SORT)); + + int num_at = 8; + int num_iso_at = 1; + int alloc_mode = 0; + int bOrigatomflag = 0; + int found_num_bonds = 0; + int found_num_isotopic = 0; + + inp_ATOM *atoms = CreateInpAtom(num_at); + INChI *inchi = Alloc_INChI(atoms, num_at, &found_num_bonds, &found_num_isotopic, 0); + inchi->nNumberOfAtoms = num_at; + + INChI_Aux *pAux = Alloc_INChI_Aux(num_at, num_iso_at, alloc_mode, bOrigatomflag); + pAux->nNumberOfAtoms = num_at; + pAux->nOrigAtNosInCanonOrd = (AT_NUMB*)inchi_calloc(num_at, sizeof(AT_NUMB)); + + // canonical atom i+1 maps to original atom i+1 + pAux->nOrigAtNosInCanonOrd[0] = 4; + pAux->nOrigAtNosInCanonOrd[1] = 5; + pAux->nOrigAtNosInCanonOrd[2] = 1; + pAux->nOrigAtNosInCanonOrd[3] = 2; + pAux->nOrigAtNosInCanonOrd[4] = 3; + pAux->nOrigAtNosInCanonOrd[5] = 12; + pAux->nOrigAtNosInCanonOrd[6] = 13; + pAux->nOrigAtNosInCanonOrd[7] = 14; + + inchi_sort->pINChI[0] = inchi; + inchi_sort->pINChI_Aux[0] = pAux; + io.pINChISort = inchi_sort; + + io.bOutType = OUT_TN; + io.num_components = 1; + io.sDifSegs[0][DIFS_s_STYPE] = DIFV_OUTPUT_FILL_T; io.nCurINChISegment = 0; io.iCurTautMode = 0; io.bPlainTextTags = 1; @@ -95,7 +127,8 @@ TEST(test_ichiprt1_enhancedStereo, test_OutputINCHI_StereoLayer_enhanced_stereo_ int ret = OutputINCHI_StereoLayer_EnhancedStereo(&cg, &out_file, &strbuf, &io, oad, (char*)"", (char*)""); - EXPECT_EQ(std::string(strbuf.pStr), "/s1(4,5)2(12,13;14)3(1;2,3)"); + // EXPECT_EQ(std::string(strbuf.pStr), "/s1(4,5)2(12,13;14)3(1;2,3)"); + EXPECT_EQ(std::string(strbuf.pStr), "/s1(1,2)2(6,7;8)3(3;4,5)"); EXPECT_EQ(ret, 0); inchi_strbuf_close(&strbuf); diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp index c98a9b9f..b2cf3692 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp @@ -188,13 +188,10 @@ TEST(test_ichiprt3, test_str_StereoAbsInv_1) int num_at = 2; int num_bonds = 1; - - - int found_num_bonds = 0; int found_num_isotopic = 0; inp_ATOM *at = CreateInpAtom(num_at); - static INChI *inchi = Alloc_INChI(at, num_at, &found_num_bonds, &found_num_isotopic, 0); + INChI *inchi = Alloc_INChI(at, num_at, &found_num_bonds, &found_num_isotopic, 0); inchi->Stereo->nCompInv2Abs = -1; inchi->nNumberOfAtoms = num_at; @@ -231,7 +228,6 @@ TEST(test_ichiprt3, test_str_StereoAbsInv_2) int num_at = 2; int num_bonds = 1; - int found_num_bonds = 0; int found_num_isotopic = 0; inp_ATOM *at = CreateInpAtom(num_at); From 65e5eb5c1ff15d749a0e018c3497c7a281f8c3bf Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 12 Jan 2026 13:59:11 +0000 Subject: [PATCH 51/69] prototypes and unit-test for t and m-layer changes --- INCHI-1-SRC/INCHI_BASE/src/strutil.c | 96 ++++++++++- .../test_unit/test_strutil_enhancedStereo.cpp | 156 ++++++++++++++++++ INCHI-1-TEST/tests/test_unit/test_util.cpp | 16 -- 3 files changed, 247 insertions(+), 21 deletions(-) create mode 100644 INCHI-1-TEST/tests/test_unit/test_strutil_enhancedStereo.cpp diff --git a/INCHI-1-SRC/INCHI_BASE/src/strutil.c b/INCHI-1-SRC/INCHI_BASE/src/strutil.c index 4df9e9ed..9226bd22 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/strutil.c +++ b/INCHI-1-SRC/INCHI_BASE/src/strutil.c @@ -4274,12 +4274,17 @@ int get_canonical_atom_number( INChI_Aux *aux, { for (int canon_num = 1; canon_num <= aux->nNumberOfAtoms; canon_num++) { if (aux->nOrigAtNosInCanonOrd[canon_num - 1] == orig_atom_num) { - return canon_num; // Found canonical atom number + return canon_num; } } - return -1; // Not found + return -1; } +int cmp_asc(const void *a, const void *b) { + AT_NUMB va = *(const AT_NUMB*)a; + AT_NUMB vb = *(const AT_NUMB*)b; + return (va > vb) - (va < vb); // returns -1, 0, or 1 +} int set_EnhancedStereo_t_m_layers( ORIG_ATOM_DATA *orig_inp_data, INChI *inchi, @@ -4292,11 +4297,16 @@ int set_EnhancedStereo_t_m_layers( ORIG_ATOM_DATA *orig_inp_data, int **enh_stereo = orig_inp_data->v3000->lists_steabs; for (int i = 0; i < orig_inp_data->v3000->n_steabs; i++) { - for (int j = 0; j < enh_stereo[i][1]; j++) { - int orig_atom_num = enh_stereo[i][2 + j]; + int nof_atoms = enh_stereo[i][1]; + + if (nof_atoms == 1) { + // + >> - + // - >> - ? + + int orig_atom_num = enh_stereo[i][2]; AT_NUMB canon_atom_num = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num); - const AT_NUMB *atom_idx_pos = is_in_the_list(inchi->Stereo->nNumber, canon_atom_num, inchi->Stereo->nNumberOfStereoCenters); + AT_NUMB *atom_idx_pos = is_in_the_list(inchi->Stereo->nNumber, canon_atom_num, inchi->Stereo->nNumberOfStereoCenters); if (atom_idx_pos) { int idx = (int)(*atom_idx_pos); @@ -4306,7 +4316,83 @@ int set_EnhancedStereo_t_m_layers( ORIG_ATOM_DATA *orig_inp_data, inchi->Stereo->nCompInv2Abs = -1; } } + + } else if (nof_atoms == 2) { + // smaller atom number gets - + // -- >> -- + // -+ >> -+ + // +- >> -+ + // ++ >> -+ + + int orig_atom_num_1 = enh_stereo[i][2]; + AT_NUMB canon_atom_num_1 = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num_1); + AT_NUMB *atom_idx_pos_1 = is_in_the_list(inchi->Stereo->nNumber, canon_atom_num_1, inchi->Stereo->nNumberOfStereoCenters); + int idx_1 = -1; + + int orig_atom_num_2 = enh_stereo[i][3]; + AT_NUMB canon_atom_num_2 = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num_2); + AT_NUMB *atom_idx_pos_2 = is_in_the_list(inchi->Stereo->nNumber, canon_atom_num_2, inchi->Stereo->nNumberOfStereoCenters); + int idx_2 = -1; + + if (atom_idx_pos_1 && atom_idx_pos_2) + { + int idx_1 = (int)(*atom_idx_pos_1); + int idx_2 = (int)(*atom_idx_pos_2); + + if (canon_atom_num_1 > canon_atom_num_2) { + idx_2 = (int)(*atom_idx_pos_1); + idx_1 = (int)(*atom_idx_pos_2); + } + + if (inchi->Stereo->t_parity[idx_1] == 2) + { + inchi->Stereo->t_parity[idx_1] = 1; + inchi->Stereo->nCompInv2Abs = -1; + } + if (inchi->Stereo->t_parity[idx_2] == 1) + { + inchi->Stereo->t_parity[idx_2] = 2; + inchi->Stereo->nCompInv2Abs = -1; + } + } + } else { + // ---, ----, ....? + + // AT_NUMB *arr_cat = (AT_NUMB*)inchi_calloc(nof_atoms, sizeof(AT_NUMB)); + + // for (int j = 0; j < nof_atoms; j++) { + // int orig_atom_num = enh_stereo[i][2 + j]; + // AT_NUMB canon_atom_num = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num); + + // arr_cat[j] = canon_atom_num; + // } + // qsort(arr_cat, nof_atoms, sizeof(AT_NUMB), cmp_asc); + + // AT_NUMB *arr_cat_idx = (AT_NUMB*)inchi_calloc(nof_atoms, sizeof(AT_NUMB)); + // for (int j = 0; j < nof_atoms; j++) { + // AT_NUMB cur_atom = arr_cat[j]; + // AT_NUMB *atom_idx_pos = is_in_the_list(inchi->Stereo->nNumber, cur_atom, inchi->Stereo->nNumberOfStereoCenters); + // arr_cat_idx[j] = -1; + // if (atom_idx_pos) + // { + // arr_cat_idx[j] = atom_idx_pos[0]; + // printf("arr idx %d\n", arr_cat_idx[j]); + // } + // } + + // int idx = (int)(*atom_idx_pos); + // if (inchi->Stereo->t_parity[idx] == 2) + // { + // inchi->Stereo->t_parity[idx] = 1; + // inchi->Stereo->nCompInv2Abs = -1; + // } + + // free(arr_cat_idx); + // free(arr_cat); + } + + } } // orig_inp_data->v3000->n_steabs; diff --git a/INCHI-1-TEST/tests/test_unit/test_strutil_enhancedStereo.cpp b/INCHI-1-TEST/tests/test_unit/test_strutil_enhancedStereo.cpp new file mode 100644 index 00000000..8acabf84 --- /dev/null +++ b/INCHI-1-TEST/tests/test_unit/test_strutil_enhancedStereo.cpp @@ -0,0 +1,156 @@ +#include + +extern "C" +{ +#include "../../../INCHI-1-SRC/INCHI_BASE/src/strutil.h" +#include "../../../INCHI-1-SRC/INCHI_BASE/src/ichi_io.h" +// #include "../../../INCHI-1-SRC/INCHI_BASE/src/inpdef.h" +} + + +TEST(test_strutil_enhancedStereo, test_set_EnhancedStereo_t_m_layers_1) +{ + + INCHI_IOSTREAM input_stream; + + const char *molblock = + "enhanc_stereo1 \n" + " ACD/LABS08242216132D \n" + " \n" + " 0 0 0 0 0 0 0 0 0 0999 V3000 \n" + "M V30 BEGIN CTAB \n" + "M V30 COUNTS 18 17 0 0 1 \n" + "M V30 BEGIN ATOM \n" + "M V30 1 C 3424.1946 -1936.7935 0 0 \n" + "M V30 2 C 3352.3145 -1895.2935 0 0 \n" + "M V30 3 C 3280.4346 -1936.7935 0 0 \n" + "M V30 4 C 3208.5542 -1895.2935 0 0 \n" + "M V30 5 C 3136.6743 -1936.7935 0 0 \n" + "M V30 6 C 3064.7944 -1895.2935 0 0 \n" + "M V30 7 Br 3136.6743 -2019.7935 0 0 \n" + "M V30 8 Cl 3208.5542 -1812.2935 0 0 \n" + "M V30 9 Cl 3280.4346 -2019.7935 0 0 \n" + "M V30 10 Cl 3352.3145 -1812.2935 0 0 \n" + "M V30 11 Cl 3424.1946 -2019.7935 0 0 \n" + "M V30 12 C 3496.075 -1895.2935 0 0 \n" + "M V30 13 C 3567.9548 -1936.7942 0 0 \n" + "M V30 14 C 3639.835 -1895.2944 0 0 \n" + "M V30 15 C 3711.7148 -1936.7942 0 0 \n" + "M V30 16 Cl 3639.835 -1812.2944 0 0 \n" + "M V30 17 Cl 3567.9548 -2019.7942 0 0 \n" + "M V30 18 Cl 3496.075 -1812.2937 0 0 \n" + "M V30 END ATOM \n" + "M V30 BEGIN BOND \n" + "M V30 1 1 1 2 \n" + "M V30 2 1 1 11 CFG=3 \n" + "M V30 3 1 1 12 \n" + "M V30 4 1 2 3 \n" + "M V30 5 1 2 10 CFG=1 \n" + "M V30 6 1 3 4 \n" + "M V30 7 1 3 9 CFG=1 \n" + "M V30 8 1 4 5 \n" + "M V30 9 1 4 8 CFG=1 \n" + "M V30 10 1 5 6 \n" + "M V30 11 1 5 7 CFG=1 \n" + "M V30 12 1 12 13 \n" + "M V30 13 1 12 18 CFG=3 \n" + "M V30 14 1 13 14 \n" + "M V30 15 1 13 17 CFG=1 \n" + "M V30 16 1 14 15 \n" + "M V30 17 1 14 16 CFG=1 \n" + "M V30 END BOND \n" + "M V30 BEGIN COLLECTION \n" + "M V30 MDLV30/STERAC2 ATOMS=(1 1) \n" + "M V30 MDLV30/STERAC1 ATOMS=(2 2 3) \n" + "M V30 MDLV30/STEABS ATOMS=(2 4 5) \n" + "M V30 MDLV30/STEREL1 ATOMS=(2 12 13) \n" + "M V30 MDLV30/STEREL2 ATOMS=(1 14) \n" + "M V30 END COLLECTION \n" + "M V30 END CTAB \n" + "M END \n"; + + inchi_ios_init(&input_stream, INCHI_IOS_TYPE_STRING, nullptr); + inchi_ios_print_nodisplay(&input_stream, molblock); + + ORIG_ATOM_DATA orig_inp_data = {}; + int bMergeAllInputStructures = 0; + int bGetOrigCoord = 0; + int bDoNotAddH = 0; + int treat_polymers = 0; + int treat_NPZz = 0; + const char *pSdfLabel = nullptr; + char *pSdfValue = nullptr; + unsigned long *lSdfId = nullptr; + long *lMolfileNumber = nullptr; + INCHI_MODE pInpAtomFlags = 0; + int err = 0; + char *pStrErr = nullptr; + int bNoWarnings = 0; + + int ret = CreateOrigInpDataFromMolfile( + &input_stream, + &orig_inp_data, + bMergeAllInputStructures, + bGetOrigCoord, + bDoNotAddH, + treat_polymers, + treat_NPZz, + pSdfLabel, + pSdfValue, + lSdfId, + lMolfileNumber, + &pInpAtomFlags, + &err, + pStrErr, + bNoWarnings); + + + + int num_at = orig_inp_data.num_inp_atoms; + + int found_num_bonds = 0; + int found_num_isotopic = 0; + + inp_ATOM *at = CreateInpAtom(num_at); + INChI *inchi = Alloc_INChI(at, num_at, &found_num_bonds, &found_num_isotopic, 0); + + + AT_NUMB at1[9] = {1,3,4,5,6,7,8,9,10}; + S_CHAR parity[9] = {2,1,1,2,2,1,2,2,1}; + inchi->Stereo->t_parity = parity; + inchi->Stereo->nNumber = at1; + inchi->Stereo->nNumberOfStereoCenters = 9; + + inchi->Stereo->nCompInv2Abs = -1; + inchi->nNumberOfAtoms = num_at; + + int nAllocMode = 0; + int bOrigCoord = 0; + + INChI_Aux *pAux = Alloc_INChI_Aux( num_at, + 0, // inp_cur_data->num_isotopic, + nAllocMode, + bOrigCoord ); + + + pAux->nNumberOfAtoms = 9; + + pAux->nOrigAtNosInCanonOrd = (AT_NUMB*)inchi_calloc(num_at, sizeof(AT_NUMB)); + + pAux->nOrigAtNosInCanonOrd[0] = 4; + pAux->nOrigAtNosInCanonOrd[1] = 5; + pAux->nOrigAtNosInCanonOrd[2] = 1; + pAux->nOrigAtNosInCanonOrd[3] = 2; + pAux->nOrigAtNosInCanonOrd[4] = 3; + pAux->nOrigAtNosInCanonOrd[5] = 12; + pAux->nOrigAtNosInCanonOrd[6] = 13; + pAux->nOrigAtNosInCanonOrd[7] = 14; + + std::cout << "Test started\n"; + ret = set_EnhancedStereo_t_m_layers(&orig_inp_data, inchi, pAux); + std::cout << "Test finished\n"; + + EXPECT_EQ(ret, 1); + + +} diff --git a/INCHI-1-TEST/tests/test_unit/test_util.cpp b/INCHI-1-TEST/tests/test_unit/test_util.cpp index 037caa99..f4eb26ca 100644 --- a/INCHI-1-TEST/tests/test_unit/test_util.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_util.cpp @@ -978,19 +978,3 @@ TEST(test_util, test_extract_stereo_info_from_inchi_string) EXPECT_EQ(found_stereo2, 0); } - -// TEST(test_util, test_extract_all_backbone_bonds_from_inchi_string) -// { - -// // int extract_all_backbone_bonds_from_inchi_string(char *sinchi, int *n_all_bkb_orig, int *orig, int *all_bkb_orig); - -// char inchi1[] = "InChI=1S/C2H6/c1-2/h1-2H3"; - -// int n_all_bkb_orig[2] = {0, 0}; -// int orig[2] = {0, 1}; -// int all_bkb_orig[2] = {0, 0}; - -// int ret1 = extract_all_backbone_bonds_from_inchi_string(inchi1, n_all_bkb_orig, orig, all_bkb_orig); - -// EXPECT_EQ(ret1, 0); -// } From 0555b4f1a574aba96a02935135ff073b1241e8c4 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Wed, 21 Jan 2026 17:15:38 +0000 Subject: [PATCH 52/69] added code for parity change (t+m-layer) --- INCHI-1-SRC/INCHI_BASE/src/strutil.c | 153 +++++++-------------------- 1 file changed, 38 insertions(+), 115 deletions(-) diff --git a/INCHI-1-SRC/INCHI_BASE/src/strutil.c b/INCHI-1-SRC/INCHI_BASE/src/strutil.c index 9226bd22..83e64a32 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/strutil.c +++ b/INCHI-1-SRC/INCHI_BASE/src/strutil.c @@ -4280,142 +4280,65 @@ int get_canonical_atom_number( INChI_Aux *aux, return -1; } -int cmp_asc(const void *a, const void *b) { - AT_NUMB va = *(const AT_NUMB*)a; - AT_NUMB vb = *(const AT_NUMB*)b; - return (va > vb) - (va < vb); // returns -1, 0, or 1 -} - -int set_EnhancedStereo_t_m_layers( ORIG_ATOM_DATA *orig_inp_data, - INChI *inchi, - INChI_Aux *aux) +int invert_parities(INChI *inchi, + INChI_Aux *aux, + int **list_atoms, + int nof_lists, + int is_absolute) { - int ret = 0; - if (orig_inp_data->v3000->n_steabs > 0) + if (nof_lists > 0) { + for (int i = 0; i < nof_lists; i++) { + int nof_atoms = list_atoms[i][1]; - int **enh_stereo = orig_inp_data->v3000->lists_steabs; - for (int i = 0; i < orig_inp_data->v3000->n_steabs; i++) { - int nof_atoms = enh_stereo[i][1]; - - if (nof_atoms == 1) { - // + >> - - // - >> - ? - - int orig_atom_num = enh_stereo[i][2]; + AT_NUMB min_c_atom_num = (AT_NUMB)9999999; + for (int j = 0; j < nof_atoms; j++) { + int orig_atom_num = list_atoms[i][2 + j]; AT_NUMB canon_atom_num = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num); - - AT_NUMB *atom_idx_pos = is_in_the_list(inchi->Stereo->nNumber, canon_atom_num, inchi->Stereo->nNumberOfStereoCenters); - if (atom_idx_pos) - { - int idx = (int)(*atom_idx_pos); - if (inchi->Stereo->t_parity[idx] == 2) - { - inchi->Stereo->t_parity[idx] = 1; - inchi->Stereo->nCompInv2Abs = -1; - } + if (canon_atom_num < min_c_atom_num) { + min_c_atom_num = canon_atom_num; } + } - } else if (nof_atoms == 2) { - // smaller atom number gets - - // -- >> -- - // -+ >> -+ - // +- >> -+ - // ++ >> -+ - - int orig_atom_num_1 = enh_stereo[i][2]; - AT_NUMB canon_atom_num_1 = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num_1); - AT_NUMB *atom_idx_pos_1 = is_in_the_list(inchi->Stereo->nNumber, canon_atom_num_1, inchi->Stereo->nNumberOfStereoCenters); - int idx_1 = -1; - - int orig_atom_num_2 = enh_stereo[i][3]; - AT_NUMB canon_atom_num_2 = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num_2); - AT_NUMB *atom_idx_pos_2 = is_in_the_list(inchi->Stereo->nNumber, canon_atom_num_2, inchi->Stereo->nNumberOfStereoCenters); - int idx_2 = -1; - - if (atom_idx_pos_1 && atom_idx_pos_2) - { - int idx_1 = (int)(*atom_idx_pos_1); - int idx_2 = (int)(*atom_idx_pos_2); + int needs_inversion = (inchi->Stereo->t_parity[min_c_atom_num] == 2); + if (needs_inversion) { - if (canon_atom_num_1 > canon_atom_num_2) { - idx_2 = (int)(*atom_idx_pos_1); - idx_1 = (int)(*atom_idx_pos_2); + for (int j = 0; j < nof_atoms; j++) { + int orig_atom_num = list_atoms[i][2 + j]; + AT_NUMB canon_atom_num = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num); + if (inchi->Stereo->t_parity[canon_atom_num] == 2) { + inchi->Stereo->t_parity[canon_atom_num] = 1; + } else if(inchi->Stereo->t_parity[canon_atom_num] == 1) { + inchi->Stereo->t_parity[canon_atom_num] = 2; } + } - if (inchi->Stereo->t_parity[idx_1] == 2) - { - inchi->Stereo->t_parity[idx_1] = 1; - inchi->Stereo->nCompInv2Abs = -1; - } - if (inchi->Stereo->t_parity[idx_2] == 1) - { - inchi->Stereo->t_parity[idx_2] = 2; - inchi->Stereo->nCompInv2Abs = -1; - } + if (is_absolute) { + inchi->Stereo->nCompInv2Abs = -1; } } else { - // ---, ----, ....? - - // AT_NUMB *arr_cat = (AT_NUMB*)inchi_calloc(nof_atoms, sizeof(AT_NUMB)); - - // for (int j = 0; j < nof_atoms; j++) { - // int orig_atom_num = enh_stereo[i][2 + j]; - // AT_NUMB canon_atom_num = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num); - - // arr_cat[j] = canon_atom_num; - // } - // qsort(arr_cat, nof_atoms, sizeof(AT_NUMB), cmp_asc); - - // AT_NUMB *arr_cat_idx = (AT_NUMB*)inchi_calloc(nof_atoms, sizeof(AT_NUMB)); - // for (int j = 0; j < nof_atoms; j++) { - // AT_NUMB cur_atom = arr_cat[j]; - // AT_NUMB *atom_idx_pos = is_in_the_list(inchi->Stereo->nNumber, cur_atom, inchi->Stereo->nNumberOfStereoCenters); - // arr_cat_idx[j] = -1; - // if (atom_idx_pos) - // { - // arr_cat_idx[j] = atom_idx_pos[0]; - // printf("arr idx %d\n", arr_cat_idx[j]); - // } - // } - - // int idx = (int)(*atom_idx_pos); - // if (inchi->Stereo->t_parity[idx] == 2) - // { - // inchi->Stereo->t_parity[idx] = 1; - // inchi->Stereo->nCompInv2Abs = -1; - // } - - // free(arr_cat_idx); - // free(arr_cat); - + if(is_absolute && inchi->Stereo->t_parity[min_c_atom_num] == 1) { + inchi->Stereo->nCompInv2Abs = 0; + } } - - } } - // orig_inp_data->v3000->n_steabs; - // orig_inp_data->v3000->lists_steabs; - - // pINChI->Stereo->nCompInv2Abs; - // -1 --> 1 - // 1 --> 0 - // orig_inp_data->v3000->n_sterel; - // orig_inp_data->v3000->lists_sterel; +} - // orig_inp_data->v3000->n_sterac; - // orig_inp_data->v3000->lists_sterac; +int set_EnhancedStereo_t_m_layers( ORIG_ATOM_DATA *orig_inp_data, + INChI *inchi, + INChI_Aux *aux) +{ + int ret = 0; - // get_canonical_atom_number; + int ret_abs = invert_parities(inchi, aux, orig_inp_data->v3000->lists_steabs, orig_inp_data->v3000->n_steabs, 1); - // pINChI->Stereo->nNumber; - // pINChI->Stereo->t_parity - // 1 --> - - // 2 --> + + int ret_rel = invert_parities(inchi, aux, orig_inp_data->v3000->lists_sterel, orig_inp_data->v3000->n_sterel, 0); + int ret_rac = invert_parities(inchi, aux, orig_inp_data->v3000->lists_sterac, orig_inp_data->v3000->n_sterac, 0); return ret; } From 79885842388ae79c2934b30ec5005ca30c2175c1 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Thu, 22 Jan 2026 16:02:52 +0000 Subject: [PATCH 53/69] added unit test and param for enh stereochem --- CMakeLists.txt | 4 +- INCHI-1-SRC/INCHI_BASE/src/ichiparm.c | 20 ++++- INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c | 28 ++++++- INCHI-1-SRC/INCHI_BASE/src/strutil.c | 18 ++--- .../tests/test_unit/test_enhancedStereo.cpp | 75 +++++++++++++++++++ 5 files changed, 125 insertions(+), 20 deletions(-) create mode 100644 INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b324705..5ac0ecc7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,8 +6,8 @@ set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 11) set(CMAKE_POSITION_INDEPENDENT_CODE ON) -# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") -# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -O0 -g") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -O0 -g") include(FetchContent) FetchContent_Declare( diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiparm.c b/INCHI-1-SRC/INCHI_BASE/src/ichiparm.c index ffc6e1a9..0a2a4204 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiparm.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiparm.c @@ -122,7 +122,8 @@ int set_common_options_by_parg(const char* pArg, int* pbNPZz, int* pbNoWarnings, int* pbMergeHash, - int* pbHideInChI); + int* pbHideInChI, + int* pbEnhancedStereochemistry); /**************************************************************************** @@ -165,7 +166,8 @@ int set_common_options_by_parg(const char* pArg, int* pbNPZz, int* pbNoWarnings, int* pbMergeHash, - int* pbHideInChI + int* pbHideInChI, + int* pbEnhancedStereochemistry ) { int got = 0; @@ -266,6 +268,11 @@ int set_common_options_by_parg(const char* pArg, (*pbLooseTSACheck) = 1; got = 1; } + else if (!inchi_stricmp(pArg, "EnhancedStereochemistry")) + { + *pbEnhancedStereochemistry = 1; + got = 1; + } #ifndef USE_STDINCHI_API /* These options DO TURN OFF Std flag */ @@ -643,6 +650,7 @@ int ReadCommandLineParms(int argc, int bAcidTautomerism = (DISCONNECT_SALTS == 1) ? (TEST_REMOVE_S_ATOMS == 1 ? 2 : 1) : 0; int bUnchargedAcidTaut = (CHARGED_SALTS_ONLY == 0); int bMergeSaltTGroups = (DISCONNECT_SALTS == 1); + int bEnhancedStereochemistry = 0; #if ( MIN_SB_RING_SIZE > 0 ) int nMinDbRinSize = MIN_SB_RING_SIZE, mdbr = 0; #endif @@ -795,7 +803,8 @@ int ReadCommandLineParms(int argc, &bLargeMolecules, &bPolymers, &bFoldPolymerSRU, &bFrameShiftScheme, &bStereoAtZz, &bNPZz, - &bNoWarnings, &bMergeHash, &bHideInChI); + &bNoWarnings, &bMergeHash, &bHideInChI, + &bEnhancedStereochemistry); if (got) { ; @@ -1243,7 +1252,8 @@ int ReadCommandLineParms(int argc, &bLargeMolecules, &bPolymers, &bFoldPolymerSRU, &bFrameShiftScheme, &bStereoAtZz, &bNPZz, - &bNoWarnings, &bMergeHash, &bHideInChI); + &bNoWarnings, &bMergeHash, &bHideInChI, + &bEnhancedStereochemistry); if (got) { @@ -2120,6 +2130,8 @@ int ReadCommandLineParms(int argc, ip->bINChIOutputOptions2 = bINChIOutputOptions2; + ip->bEnhancedStereo = bEnhancedStereochemistry; + return 0; } diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c index 0960fdc1..977a995f 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c @@ -2159,6 +2159,12 @@ int MakeStereoString( AT_NUMB *at1, return nLen; } +int compare_ints(const void *a, const void *b) { + int arg1 = *(const int *)a; + int arg2 = *(const int *)b; + return (arg1 > arg2) - (arg1 < arg2); +} + int MakeEnhStereoString( INCHI_SORT *pINChISort, int bOutType, int num_components, @@ -2192,20 +2198,34 @@ int MakeEnhStereoString( INCHI_SORT *pINChISort, tot_len += MakeDelim( "(", strbuf, bOverflow ); for (int i = 0; i < nof_units; i++) { - for (int j = 0; j < enh_stereo[i][1]; j++) { - int orig_atom_num = enh_stereo[i][2 + j]; + int *atom_numbers = &enh_stereo[i][2]; + int nof_atoms = enh_stereo[i][1]; + int c_atom_numbers[nof_atoms]; + for (int j = 0; j < nof_atoms; j++) { + + int orig_atom_num = atom_numbers[j]; //enh_stereo[i][2 + j]; int canon_atom_num = get_canonical_atom_number(pAux, orig_atom_num); + c_atom_numbers[j] = canon_atom_num; + + } + + if (nof_atoms > 1) { + qsort(c_atom_numbers, nof_atoms, sizeof(int), compare_ints); + } + for (int j = 0; j < nof_atoms; j++) { //tot_len += MakeMult_EnhStereo( enh_stereo[i][2 + j], "", strbuf, nCtMode, bOverflow ); - tot_len += MakeMult_EnhStereo( canon_atom_num, "", strbuf, nCtMode, bOverflow ); + tot_len += MakeMult_EnhStereo( c_atom_numbers[j], "", strbuf, nCtMode, bOverflow ); if ((j + 1) < enh_stereo[i][1]) { tot_len += MakeDelim( ",", strbuf, bOverflow ); } } if (i + 1 < nof_units) { - tot_len += MakeDelim( ";", strbuf, bOverflow ); + // tot_len += MakeDelim( ";", strbuf, bOverflow ); + tot_len += MakeDelim( ")", strbuf, bOverflow ); + tot_len += MakeDelim( "(", strbuf, bOverflow ); } } tot_len += MakeDelim( ")", strbuf, bOverflow ); diff --git a/INCHI-1-SRC/INCHI_BASE/src/strutil.c b/INCHI-1-SRC/INCHI_BASE/src/strutil.c index 83e64a32..f7759614 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/strutil.c +++ b/INCHI-1-SRC/INCHI_BASE/src/strutil.c @@ -4287,6 +4287,10 @@ int invert_parities(INChI *inchi, int is_absolute) { + // parities + // 2 = + + // 1 = - + if (nof_lists > 0) { for (int i = 0; i < nof_lists; i++) { @@ -4300,9 +4304,11 @@ int invert_parities(INChI *inchi, min_c_atom_num = canon_atom_num; } } + int min_c_atom_parity = inchi->Stereo->t_parity[min_c_atom_num]; - int needs_inversion = (inchi->Stereo->t_parity[min_c_atom_num] == 2); - if (needs_inversion) { + if ((is_absolute == 1) && (min_c_atom_parity == 1)) { + inchi->Stereo->nCompInv2Abs = 0; + } else if (min_c_atom_parity == 2) { for (int j = 0; j < nof_atoms; j++) { int orig_atom_num = list_atoms[i][2 + j]; @@ -4317,14 +4323,9 @@ int invert_parities(INChI *inchi, if (is_absolute) { inchi->Stereo->nCompInv2Abs = -1; } - } else { - if(is_absolute && inchi->Stereo->t_parity[min_c_atom_num] == 1) { - inchi->Stereo->nCompInv2Abs = 0; - } } } } - } int set_EnhancedStereo_t_m_layers( ORIG_ATOM_DATA *orig_inp_data, @@ -4333,11 +4334,8 @@ int set_EnhancedStereo_t_m_layers( ORIG_ATOM_DATA *orig_inp_data, { int ret = 0; - int ret_abs = invert_parities(inchi, aux, orig_inp_data->v3000->lists_steabs, orig_inp_data->v3000->n_steabs, 1); - int ret_rel = invert_parities(inchi, aux, orig_inp_data->v3000->lists_sterel, orig_inp_data->v3000->n_sterel, 0); - int ret_rac = invert_parities(inchi, aux, orig_inp_data->v3000->lists_sterac, orig_inp_data->v3000->n_sterac, 0); return ret; diff --git a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp new file mode 100644 index 00000000..73d985bd --- /dev/null +++ b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp @@ -0,0 +1,75 @@ +#include + +extern "C" +{ +#include "../../../INCHI-1-SRC/INCHI_BASE/src/inchi_api.h" +} + +TEST(test_enhancedStereo, test_EnhancedStereochemistry_1) +{ + const char *molblock = + "enhanc_stereo1 \n" + " ACD/LABS08242216132D \n" + " \n" + " 0 0 0 0 0 0 0 0 0 0999 V3000 \n" + "M V30 BEGIN CTAB \n" + "M V30 COUNTS 18 17 0 0 1 \n" + "M V30 BEGIN ATOM \n" + "M V30 1 C 3424.1946 -1936.7935 0 0 \n" + "M V30 2 C 3352.3145 -1895.2935 0 0 \n" + "M V30 3 C 3280.4346 -1936.7935 0 0 \n" + "M V30 4 C 3208.5542 -1895.2935 0 0 \n" + "M V30 5 C 3136.6743 -1936.7935 0 0 \n" + "M V30 6 C 3064.7944 -1895.2935 0 0 \n" + "M V30 7 Br 3136.6743 -2019.7935 0 0 \n" + "M V30 8 Cl 3208.5542 -1812.2935 0 0 \n" + "M V30 9 Cl 3280.4346 -2019.7935 0 0 \n" + "M V30 10 Cl 3352.3145 -1812.2935 0 0 \n" + "M V30 11 Cl 3424.1946 -2019.7935 0 0 \n" + "M V30 12 C 3496.075 -1895.2935 0 0 \n" + "M V30 13 C 3567.9548 -1936.7942 0 0 \n" + "M V30 14 C 3639.835 -1895.2944 0 0 \n" + "M V30 15 C 3711.7148 -1936.7942 0 0 \n" + "M V30 16 Cl 3639.835 -1812.2944 0 0 \n" + "M V30 17 Cl 3567.9548 -2019.7942 0 0 \n" + "M V30 18 Cl 3496.075 -1812.2937 0 0 \n" + "M V30 END ATOM \n" + "M V30 BEGIN BOND \n" + "M V30 1 1 1 2 \n" + "M V30 2 1 1 11 CFG=3 \n" + "M V30 3 1 1 12 \n" + "M V30 4 1 2 3 \n" + "M V30 5 1 2 10 CFG=1 \n" + "M V30 6 1 3 4 \n" + "M V30 7 1 3 9 CFG=1 \n" + "M V30 8 1 4 5 \n" + "M V30 9 1 4 8 CFG=1 \n" + "M V30 10 1 5 6 \n" + "M V30 11 1 5 7 CFG=1 \n" + "M V30 12 1 12 13 \n" + "M V30 13 1 12 18 CFG=3 \n" + "M V30 14 1 13 14 \n" + "M V30 15 1 13 17 CFG=1 \n" + "M V30 16 1 14 15 \n" + "M V30 17 1 14 16 CFG=1 \n" + "M V30 END BOND \n" + "M V30 BEGIN COLLECTION \n" + "M V30 MDLV30/STERAC2 ATOMS=(1 1) \n" + "M V30 MDLV30/STERAC1 ATOMS=(2 2 3) \n" + "M V30 MDLV30/STEABS ATOMS=(2 4 5) \n" + "M V30 MDLV30/STEREL1 ATOMS=(2 12 13) \n" + "M V30 MDLV30/STEREL2 ATOMS=(1 14) \n" + "M V30 END COLLECTION \n" + "M V30 END CTAB \n" + "M END \n"; + + char options[] = "-EnhancedStereochemistry"; + inchi_Output output; + inchi_Output *poutput = &output; + const char expected_inchi[] = "InChI=1S/2C5H5.Fe/c2*1-2-4-5-3-1;/h2*1-5H;/q2*-1;"; + + EXPECT_EQ(MakeINCHIFromMolfileText(molblock, options, poutput), 1); + EXPECT_STREQ(poutput->szInChI, expected_inchi); + + FreeINCHI(poutput); +} From 2d12b3b2f3517772fff7653203c1c1c85d5427b8 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Fri, 23 Jan 2026 12:15:04 +0000 Subject: [PATCH 54/69] fixed parity change bug for enhanced stereochemistry --- INCHI-1-SRC/INCHI_BASE/src/ichiprt3.c | 20 ++++++-- INCHI-1-SRC/INCHI_BASE/src/mol2atom.c | 11 +++++ INCHI-1-SRC/INCHI_BASE/src/strutil.c | 39 ++++++++++++--- .../tests/test_unit/test_enhancedStereo.cpp | 2 +- .../test_ichiprt1_enhancedStereo.cpp | 48 +++++++++++++------ .../tests/test_unit/test_ichiprt3.cpp | 2 + .../test_unit/test_strutil_enhancedStereo.cpp | 28 +++++++---- 7 files changed, 114 insertions(+), 36 deletions(-) diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt3.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt3.c index eb338ddd..a17b0324 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt3.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt3.c @@ -961,10 +961,22 @@ int str_Sp2( INCHI_SORT *pINChISort, return ( strbuf->nUsedLength - nUsedLength0 ); } - -/**************************************************************************** - Produce tetrahedral stereo substring of the whole structure InChI string. -****************************************************************************/ +/** + * @brief Produce tetrahedral stereo substring of the whole structure InChI string. + * + * @param pINChISort Pointer to the primary INCHI_SORT structure containing input data. + * @param pINChISort2 Pointer to the secondary INCHI_SORT structure, used for comparison or additional data. + * @param strbuf Pointer to an INCHI_IOS_STRING buffer where the output string will be stored. + * @param bOverflow Pointer to an integer flag that will be set if the output overflows the buffer. + * @param bOutType Output type flag specifying the format or type of output. + * @param TAUT_MODE Tautomer mode flag indicating how tautomers are handled. + * @param num_components The number of components to process. + * @param bRelRac Flag for relative or racemic stereochemistry. + * @param bSecondNonTautPass Flag indicating if this is the second pass for non-tautomeric processing. + * @param bOmitRepetitions Flag to omit repeated entries in the output. + * @param bUseMulipliers Flag to use multipliers in the output representation. + * @return int + */ int str_Sp3( INCHI_SORT *pINChISort, INCHI_SORT *pINChISort2, INCHI_IOS_STRING *strbuf, diff --git a/INCHI-1-SRC/INCHI_BASE/src/mol2atom.c b/INCHI-1-SRC/INCHI_BASE/src/mol2atom.c index ca519c0a..6f1dd8e4 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/mol2atom.c +++ b/INCHI-1-SRC/INCHI_BASE/src/mol2atom.c @@ -1337,6 +1337,15 @@ void FreeExtOrigAtData(OAD_Polymer *pd, OAD_V3000 *v3k) } /****************************************************************************/ +static int cmp_int_list_first_elem(const void *a, const void *b) +{ + int * const *list_a = (int * const *)a; + int * const *list_b = (int * const *)b; + int val_a = (*list_a)[0]; + int val_b = (*list_b)[0]; + return (val_a > val_b) - (val_a < val_b); +} + int SetExtOrigAtDataByMolfileExtInput(MOL_FMT_DATA *mfdata, OAD_Polymer **ppPolymer, OAD_V3000 **ppV3000, @@ -1568,6 +1577,7 @@ int SetExtOrigAtDataByMolfileExtInput(MOL_FMT_DATA *mfdata, lst[k] = mol_lst[k]; } } + qsort(pv->lists_sterac, mpv->n_sterac, sizeof(int *), cmp_int_list_first_elem); } if (mpv->n_sterel && mpv->sterel) { @@ -1593,6 +1603,7 @@ int SetExtOrigAtDataByMolfileExtInput(MOL_FMT_DATA *mfdata, lst[k] = mol_lst[k]; } } + qsort(pv->lists_sterel, mpv->n_sterel, sizeof(int *), cmp_int_list_first_elem); } } diff --git a/INCHI-1-SRC/INCHI_BASE/src/strutil.c b/INCHI-1-SRC/INCHI_BASE/src/strutil.c index f7759614..86efdb93 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/strutil.c +++ b/INCHI-1-SRC/INCHI_BASE/src/strutil.c @@ -4280,6 +4280,18 @@ int get_canonical_atom_number( INChI_Aux *aux, return -1; } +int get_parity_idx_from_canonical_atom_number( int canon_atom_num, + AT_NUMB *nNumber, + int nof_atoms) +{ + for (int i = 0; i < nof_atoms; i++) { + if (nNumber[i] == canon_atom_num) { + return i; + } + } + return -1; +} + int invert_parities(INChI *inchi, INChI_Aux *aux, int **list_atoms, @@ -4291,6 +4303,8 @@ int invert_parities(INChI *inchi, // 2 = + // 1 = - + S_CHAR *t_parity = inchi->Stereo->t_parity; + if (nof_lists > 0) { for (int i = 0; i < nof_lists; i++) { @@ -4304,19 +4318,30 @@ int invert_parities(INChI *inchi, min_c_atom_num = canon_atom_num; } } - int min_c_atom_parity = inchi->Stereo->t_parity[min_c_atom_num]; + int min_c_parity_idx = get_parity_idx_from_canonical_atom_number(min_c_atom_num, + inchi->Stereo->nNumber, + inchi->Stereo->nNumberOfStereoCenters); + + if (min_c_parity_idx == -1) { + // return -1; + printf("ERROR %d: cannot find parity idx for atom %d %d\n", __LINE__, min_c_atom_num, min_c_parity_idx); + } + int min_c_atom_parity = t_parity[min_c_parity_idx]; if ((is_absolute == 1) && (min_c_atom_parity == 1)) { - inchi->Stereo->nCompInv2Abs = 0; + inchi->Stereo->nCompInv2Abs = 1; } else if (min_c_atom_parity == 2) { for (int j = 0; j < nof_atoms; j++) { int orig_atom_num = list_atoms[i][2 + j]; AT_NUMB canon_atom_num = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num); - if (inchi->Stereo->t_parity[canon_atom_num] == 2) { - inchi->Stereo->t_parity[canon_atom_num] = 1; - } else if(inchi->Stereo->t_parity[canon_atom_num] == 1) { - inchi->Stereo->t_parity[canon_atom_num] = 2; + int parity_idx = get_parity_idx_from_canonical_atom_number(canon_atom_num, + inchi->Stereo->nNumber, + inchi->Stereo->nNumberOfStereoCenters); + if (t_parity[parity_idx] == 2) { + t_parity[parity_idx] = 1; + } else if(t_parity[parity_idx] == 1) { + t_parity[parity_idx] = 2; } } @@ -4335,8 +4360,8 @@ int set_EnhancedStereo_t_m_layers( ORIG_ATOM_DATA *orig_inp_data, int ret = 0; int ret_abs = invert_parities(inchi, aux, orig_inp_data->v3000->lists_steabs, orig_inp_data->v3000->n_steabs, 1); - int ret_rel = invert_parities(inchi, aux, orig_inp_data->v3000->lists_sterel, orig_inp_data->v3000->n_sterel, 0); int ret_rac = invert_parities(inchi, aux, orig_inp_data->v3000->lists_sterac, orig_inp_data->v3000->n_sterac, 0); + int ret_rel = invert_parities(inchi, aux, orig_inp_data->v3000->lists_sterel, orig_inp_data->v3000->n_sterel, 0); return ret; } diff --git a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp index 73d985bd..1e6b5042 100644 --- a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp @@ -66,7 +66,7 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_1) char options[] = "-EnhancedStereochemistry"; inchi_Output output; inchi_Output *poutput = &output; - const char expected_inchi[] = "InChI=1S/2C5H5.Fe/c2*1-2-4-5-3-1;/h2*1-5H;/q2*-1;"; + const char expected_inchi[] = "InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(6,8)(4)3(7,9)(10)"; EXPECT_EQ(MakeINCHIFromMolfileText(molblock, options, poutput), 1); EXPECT_STREQ(poutput->szInChI, expected_inchi); diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt1_enhancedStereo.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt1_enhancedStereo.cpp index fffb967b..7c5f7bef 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichiprt1_enhancedStereo.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt1_enhancedStereo.cpp @@ -31,10 +31,8 @@ TEST(test_ichiprt1_enhancedStereo, test_OutputINCHI_StereoLayer_enhanced_stereo_ oad->v3000->n_collections = 5; oad->v3000->n_steabs = 1; - oad->v3000->lists_steabs = (int **)inchi_calloc(1, sizeof(int*)); - for (int i = 0; i < oad->v3000->n_steabs; i++) { - oad->v3000->lists_steabs[i] = (int *)inchi_calloc(1, sizeof(int)); - } + oad->v3000->lists_steabs = (int **)inchi_calloc(oad->v3000->n_steabs, sizeof(int*)); + oad->v3000->lists_steabs[0] = (int *)inchi_calloc(2+2, sizeof(int)); // STEABS ATOMS=(2 4 5) oad->v3000->lists_steabs[0][0] = 1; // - not used @@ -45,10 +43,9 @@ TEST(test_ichiprt1_enhancedStereo, test_OutputINCHI_StereoLayer_enhanced_stereo_ // STERAC2 ATOMS=(1 1) oad->v3000->n_sterac = 2; - oad->v3000->lists_sterac = (int **)inchi_calloc(1, sizeof(int*)); - for (int i = 0; i < oad->v3000->n_sterac; i++) { - oad->v3000->lists_sterac[i] = (int *)inchi_calloc(1, sizeof(int)); - } + oad->v3000->lists_sterac = (int **)inchi_calloc(oad->v3000->n_sterac, sizeof(int*)); + oad->v3000->lists_sterac[0] = (int *)inchi_calloc(2 + 1, sizeof(int)); + oad->v3000->lists_sterac[1] = (int *)inchi_calloc(2 + 2, sizeof(int)); oad->v3000->lists_sterac[0][0] = 2; // n from "STERACn" tag oad->v3000->lists_sterac[0][1] = 1; // number of members in collection @@ -61,10 +58,9 @@ TEST(test_ichiprt1_enhancedStereo, test_OutputINCHI_StereoLayer_enhanced_stereo_ oad->v3000->lists_sterac[1][3] = 3; // member atom numbers oad->v3000->n_sterel = 2; - oad->v3000->lists_sterel = (int **)inchi_calloc(1, sizeof(int*)); - for (int i = 0; i < oad->v3000->n_sterel; i++) { - oad->v3000->lists_sterel[i] = (int *)inchi_calloc(1, sizeof(int)); - } + oad->v3000->lists_sterel = (int **)inchi_calloc(oad->v3000->n_sterel, sizeof(int*)); + oad->v3000->lists_sterel[0] = (int *)inchi_calloc(2 + 2, sizeof(int)); + oad->v3000->lists_sterel[1] = (int *)inchi_calloc(2 + 1, sizeof(int)); // STEREL1 ATOMS=(2 12 13) oad->v3000->lists_sterel[0][0] = 1; // n from "STERELn" tag @@ -93,7 +89,7 @@ TEST(test_ichiprt1_enhancedStereo, test_OutputINCHI_StereoLayer_enhanced_stereo_ INChI_Aux *pAux = Alloc_INChI_Aux(num_at, num_iso_at, alloc_mode, bOrigatomflag); pAux->nNumberOfAtoms = num_at; - pAux->nOrigAtNosInCanonOrd = (AT_NUMB*)inchi_calloc(num_at, sizeof(AT_NUMB)); + // pAux->nOrigAtNosInCanonOrd = (AT_NUMB*)inchi_calloc(num_at, sizeof(AT_NUMB)); // canonical atom i+1 maps to original atom i+1 pAux->nOrigAtNosInCanonOrd[0] = 4; @@ -128,9 +124,33 @@ TEST(test_ichiprt1_enhancedStereo, test_OutputINCHI_StereoLayer_enhanced_stereo_ int ret = OutputINCHI_StereoLayer_EnhancedStereo(&cg, &out_file, &strbuf, &io, oad, (char*)"", (char*)""); // EXPECT_EQ(std::string(strbuf.pStr), "/s1(4,5)2(12,13;14)3(1;2,3)"); - EXPECT_EQ(std::string(strbuf.pStr), "/s1(1,2)2(6,7;8)3(3;4,5)"); + EXPECT_EQ(std::string(strbuf.pStr), "/s1(1,2)2(6,7)(8)3(3)(4,5)"); EXPECT_EQ(ret, 0); + for (int i = 0; i < oad->v3000->n_steabs; i++) { + inchi_free(oad->v3000->lists_steabs[i]); + } + inchi_free(oad->v3000->lists_steabs); + + for (int i = 0; i < oad->v3000->n_sterel; i++) { + inchi_free(oad->v3000->lists_sterel[i]); + } + inchi_free(oad->v3000->lists_sterel); + + for (int i = 0; i < oad->v3000->n_sterac; i++) { + inchi_free(oad->v3000->lists_sterac[i]); + } + inchi_free(oad->v3000->lists_sterac); + + inchi_free(oad->v3000); + inchi_free(oad); + + inchi_free(inchi_sort); + + FreeInpAtom(&atoms); + Free_INChI_Aux(&pAux); + Free_INChI(&inchi); + inchi_strbuf_close(&strbuf); inchi_ios_close(&out_file); } diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp index b2cf3692..c4b51c77 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt3.cpp @@ -68,6 +68,7 @@ TEST(test_ichiprt3, test_str_Sp2_outputs_expected_sp2_string_1) inchi_strbuf_close(&strbuf); Free_INChI_Stereo(stereo); + inchi_free(stereo); } TEST(test_ichiprt3, test_str_Sp2_outputs_expected_sp2_string_2) @@ -129,6 +130,7 @@ TEST(test_ichiprt3, test_str_Sp2_outputs_expected_sp2_string_2) inchi_strbuf_close(&strbuf); Free_INChI_Stereo(stereo); + inchi_free(stereo); } TEST(test_ichiprt3, test_str_Sp3_outputs_expected_sp3_string) diff --git a/INCHI-1-TEST/tests/test_unit/test_strutil_enhancedStereo.cpp b/INCHI-1-TEST/tests/test_unit/test_strutil_enhancedStereo.cpp index 8acabf84..07b1b288 100644 --- a/INCHI-1-TEST/tests/test_unit/test_strutil_enhancedStereo.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_strutil_enhancedStereo.cpp @@ -72,7 +72,7 @@ TEST(test_strutil_enhancedStereo, test_set_EnhancedStereo_t_m_layers_1) inchi_ios_init(&input_stream, INCHI_IOS_TYPE_STRING, nullptr); inchi_ios_print_nodisplay(&input_stream, molblock); - ORIG_ATOM_DATA orig_inp_data = {}; + ORIG_ATOM_DATA *orig_inp_data = (ORIG_ATOM_DATA*)inchi_calloc(1, sizeof(ORIG_ATOM_DATA)); int bMergeAllInputStructures = 0; int bGetOrigCoord = 0; int bDoNotAddH = 0; @@ -89,7 +89,7 @@ TEST(test_strutil_enhancedStereo, test_set_EnhancedStereo_t_m_layers_1) int ret = CreateOrigInpDataFromMolfile( &input_stream, - &orig_inp_data, + orig_inp_data, bMergeAllInputStructures, bGetOrigCoord, bDoNotAddH, @@ -106,7 +106,7 @@ TEST(test_strutil_enhancedStereo, test_set_EnhancedStereo_t_m_layers_1) - int num_at = orig_inp_data.num_inp_atoms; + int num_at = orig_inp_data->num_inp_atoms; int found_num_bonds = 0; int found_num_isotopic = 0; @@ -114,13 +114,14 @@ TEST(test_strutil_enhancedStereo, test_set_EnhancedStereo_t_m_layers_1) inp_ATOM *at = CreateInpAtom(num_at); INChI *inchi = Alloc_INChI(at, num_at, &found_num_bonds, &found_num_isotopic, 0); + AT_NUMB at_tmp[] = {0,1,2,3,4,5,6,7,8}; + S_CHAR parity_tmp[] = {2,1,1,2,2,1,2,2,1}; + for (int i = 0; i < 9; i++) { + inchi->Stereo->nNumber[i] = at_tmp[i]; + inchi->Stereo->t_parity[i] = parity_tmp[i]; + } - AT_NUMB at1[9] = {1,3,4,5,6,7,8,9,10}; - S_CHAR parity[9] = {2,1,1,2,2,1,2,2,1}; - inchi->Stereo->t_parity = parity; - inchi->Stereo->nNumber = at1; inchi->Stereo->nNumberOfStereoCenters = 9; - inchi->Stereo->nCompInv2Abs = -1; inchi->nNumberOfAtoms = num_at; @@ -135,7 +136,7 @@ TEST(test_strutil_enhancedStereo, test_set_EnhancedStereo_t_m_layers_1) pAux->nNumberOfAtoms = 9; - pAux->nOrigAtNosInCanonOrd = (AT_NUMB*)inchi_calloc(num_at, sizeof(AT_NUMB)); + // pAux->nOrigAtNosInCanonOrd = (AT_NUMB*)inchi_calloc(num_at, sizeof(AT_NUMB)); pAux->nOrigAtNosInCanonOrd[0] = 4; pAux->nOrigAtNosInCanonOrd[1] = 5; @@ -147,10 +148,17 @@ TEST(test_strutil_enhancedStereo, test_set_EnhancedStereo_t_m_layers_1) pAux->nOrigAtNosInCanonOrd[7] = 14; std::cout << "Test started\n"; - ret = set_EnhancedStereo_t_m_layers(&orig_inp_data, inchi, pAux); + ret = set_EnhancedStereo_t_m_layers(orig_inp_data, inchi, pAux); std::cout << "Test finished\n"; EXPECT_EQ(ret, 1); + FreeOrigAtData(orig_inp_data); + inchi_free(orig_inp_data); + Free_INChI_Aux(&pAux); + Free_INChI(&inchi); + FreeInpAtom(&at); + + inchi_ios_free_str(&input_stream); } From 0784a9888683cb5196d5f886db769193d81b8b93 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Fri, 23 Jan 2026 15:13:22 +0000 Subject: [PATCH 55/69] Removed inchi warning about enh stereo and added test for multiple fragmets --- CMakeLists.txt | 10 +- INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c | 3 + INCHI-1-SRC/INCHI_BASE/src/mol_fmt3.c | 14 +- INCHI-1-SRC/INCHI_BASE/src/strutil.c | 17 ++ .../tests/test_unit/test_enhancedStereo.cpp | 220 +++++++++++++++++- INCHI-1-TEST/tests/test_unit/test_inpdef.cpp | 14 +- 6 files changed, 261 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ac0ecc7..6b78c4d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,8 +6,14 @@ set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 11) set(CMAKE_POSITION_INDEPENDENT_CODE ON) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -O0 -g") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -O0 -g") +# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -O0 -g") +# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -O0 -g") + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g") + +# set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fsanitize=address -O0 -g") +# set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -O0 -g") include(FetchContent) FetchContent_Declare( diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c index 977a995f..045694f5 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c @@ -2206,6 +2206,9 @@ int MakeEnhStereoString( INCHI_SORT *pINChISort, int orig_atom_num = atom_numbers[j]; //enh_stereo[i][2 + j]; int canon_atom_num = get_canonical_atom_number(pAux, orig_atom_num); + if (canon_atom_num == -1) { + printf("Error: could not find canonical atom number for original atom number %d\n", orig_atom_num); + } c_atom_numbers[j] = canon_atom_num; } diff --git a/INCHI-1-SRC/INCHI_BASE/src/mol_fmt3.c b/INCHI-1-SRC/INCHI_BASE/src/mol_fmt3.c index 2369663a..c2debef5 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/mol_fmt3.c +++ b/INCHI-1-SRC/INCHI_BASE/src/mol_fmt3.c @@ -842,13 +842,13 @@ int MolfileV3000ReadCollections(MOL_FMT_CTAB *ctab, goto err_fin; } - /* Error: No V3000 Collection end marker */ - if (ctab->v3000->n_steabs || - ctab->v3000->n_sterel || - ctab->v3000->n_sterac) - { - AddErrorMessage(pStrErr, "V3000 enhanced stereo read/stored but ignored"); - } + // /* Error: No V3000 Collection end marker */ + // if (ctab->v3000->n_steabs || + // ctab->v3000->n_sterel || + // ctab->v3000->n_sterac) + // { + // AddErrorMessage(pStrErr, "V3000 enhanced stereo read/stored but ignored"); + // } err_fin: diff --git a/INCHI-1-SRC/INCHI_BASE/src/strutil.c b/INCHI-1-SRC/INCHI_BASE/src/strutil.c index 86efdb93..db569af9 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/strutil.c +++ b/INCHI-1-SRC/INCHI_BASE/src/strutil.c @@ -4318,6 +4318,11 @@ int invert_parities(INChI *inchi, min_c_atom_num = canon_atom_num; } } + if (min_c_atom_num == (AT_NUMB)9999999) { + // return -1; + printf("ERROR %d: cannot find min canonical atom num\n", __LINE__); + continue; + } int min_c_parity_idx = get_parity_idx_from_canonical_atom_number(min_c_atom_num, inchi->Stereo->nNumber, inchi->Stereo->nNumberOfStereoCenters); @@ -4325,6 +4330,18 @@ int invert_parities(INChI *inchi, if (min_c_parity_idx == -1) { // return -1; printf("ERROR %d: cannot find parity idx for atom %d %d\n", __LINE__, min_c_atom_num, min_c_parity_idx); + for (int j = 0; j < nof_atoms; j++) { + int orig_atom_num = list_atoms[i][2 + j]; + AT_NUMB canon_atom_num = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num); + int parity_idx = get_parity_idx_from_canonical_atom_number(canon_atom_num, + inchi->Stereo->nNumber, + inchi->Stereo->nNumberOfStereoCenters); + printf(" atom %d -> canon %d -> parity idx %d -> parity %d\n", + orig_atom_num, + canon_atom_num, + parity_idx, + (parity_idx != -1) ? t_parity[parity_idx] : -1); + } } int min_c_atom_parity = t_parity[min_c_parity_idx]; diff --git a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp index 1e6b5042..1294638a 100644 --- a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp @@ -68,8 +68,226 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_1) inchi_Output *poutput = &output; const char expected_inchi[] = "InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(6,8)(4)3(7,9)(10)"; - EXPECT_EQ(MakeINCHIFromMolfileText(molblock, options, poutput), 1); + EXPECT_EQ(MakeINCHIFromMolfileText(molblock, options, poutput), 0); EXPECT_STREQ(poutput->szInChI, expected_inchi); + poutput->szLog = nullptr; + poutput->szMessage = nullptr; + + FreeINCHI(poutput); +} + +TEST(test_enhancedStereo, test_EnhancedStereochemistry_2_mols) +{ + const char *molblock = + "test_mol \n" + " -INDIGO-01232613552D \n" + " \n" + " 0 0 0 0 0 0 0 0 0 0 0 V3000 \n" + "M V30 BEGIN CTAB \n" + "M V30 COUNTS 36 34 0 0 0 \n" + "M V30 BEGIN ATOM \n" + "M V30 1 C 5.83301 -3.275 0.0 0 CFG=1 \n" + "M V30 2 C 4.96699 -2.775 0.0 0 CFG=1 \n" + "M V30 3 C 4.10096 -3.275 0.0 0 CFG=2 \n" + "M V30 4 C 3.23493 -2.775 0.0 0 CFG=1 \n" + "M V30 5 C 2.36891 -3.275 0.0 0 CFG=2 \n" + "M V30 6 C 1.50289 -2.775 0.0 0 \n" + "M V30 7 Br 2.36891 -4.275 0.0 0 \n" + "M V30 8 Cl 3.23493 -1.775 0.0 0 \n" + "M V30 9 Cl 4.10096 -4.275 0.0 0 \n" + "M V30 10 Cl 4.96699 -1.775 0.0 0 \n" + "M V30 11 Cl 5.83301 -4.275 0.0 0 \n" + "M V30 12 C 6.69904 -2.775 0.0 0 CFG=1 \n" + "M V30 13 C 7.56506 -3.275 0.0 0 CFG=1 \n" + "M V30 14 C 8.43109 -2.77501 0.0 0 CFG=2 \n" + "M V30 15 C 9.29711 -3.275 0.0 0 \n" + "M V30 16 Cl 8.43109 -1.77501 0.0 0 \n" + "M V30 17 Cl 7.56506 -4.275 0.0 0 \n" + "M V30 18 Cl 6.69904 -1.775 0.0 0 \n" + "M V30 19 C 6.13302 -7.62502 0.0 0 CFG=2 \n" + "M V30 20 C 5.26698 -7.12498 0.0 0 CFG=1 \n" + "M V30 21 C 4.40101 -7.62502 0.0 0 CFG=2 \n" + "M V30 22 C 3.53496 -7.12498 0.0 0 CFG=1 \n" + "M V30 23 C 2.66891 -7.62502 0.0 0 CFG=2 \n" + "M V30 24 C 6.99899 -7.12498 0.0 0 CFG=2 \n" + "M V30 25 C 7.86504 -7.62502 0.0 0 CFG=2 \n" + "M V30 26 C 8.73109 -7.12498 0.0 0 CFG=2 \n" + "M V30 27 C 1.80295 -7.12498 0.0 0 \n" + "M V30 28 Br 2.66891 -8.62501 0.0 0 \n" + "M V30 29 Cl 3.53496 -6.12499 0.0 0 \n" + "M V30 30 Cl 4.40101 -8.62501 0.0 0 \n" + "M V30 31 Cl 5.26698 -6.12499 0.0 0 \n" + "M V30 32 Cl 6.13302 -8.62501 0.0 0 \n" + "M V30 33 C 9.59705 -7.62502 0.0 0 \n" + "M V30 34 Cl 8.73109 -6.12499 0.0 0 \n" + "M V30 35 Cl 7.86504 -8.62501 0.0 0 \n" + "M V30 36 Cl 6.99899 -6.12499 0.0 0 \n" + "M V30 END ATOM \n" + "M V30 BEGIN BOND \n" + "M V30 1 1 1 2 \n" + "M V30 2 1 1 11 CFG=3 \n" + "M V30 3 1 1 12 \n" + "M V30 4 1 2 3 \n" + "M V30 5 1 2 10 CFG=1 \n" + "M V30 6 1 3 4 \n" + "M V30 7 1 3 9 CFG=1 \n" + "M V30 8 1 4 5 \n" + "M V30 9 1 4 8 CFG=1 \n" + "M V30 10 1 5 6 \n" + "M V30 11 1 5 7 CFG=1 \n" + "M V30 12 1 12 13 \n" + "M V30 13 1 12 18 CFG=3 \n" + "M V30 14 1 13 14 \n" + "M V30 15 1 13 17 CFG=1 \n" + "M V30 16 1 14 15 \n" + "M V30 17 1 14 16 CFG=1 \n" + "M V30 18 1 19 20 \n" + "M V30 19 1 20 21 \n" + "M V30 20 1 21 22 \n" + "M V30 21 1 22 23 \n" + "M V30 22 1 19 24 \n" + "M V30 23 1 24 25 \n" + "M V30 24 1 25 26 \n" + "M V30 25 1 23 27 \n" + "M V30 26 1 23 28 CFG=1 \n" + "M V30 27 1 22 29 CFG=1 \n" + "M V30 28 1 21 30 CFG=1 \n" + "M V30 29 1 20 31 CFG=1 \n" + "M V30 30 1 19 32 CFG=3 \n" + "M V30 31 1 26 33 \n" + "M V30 32 1 26 34 CFG=1 \n" + "M V30 33 1 25 35 CFG=3 \n" + "M V30 34 1 24 36 CFG=1 \n" + "M V30 END BOND \n" + "M V30 BEGIN COLLECTION \n" + "M V30 MDLV30/STERAC2 ATOMS=(1 1) \n" + "M V30 MDLV30/STERAC1 ATOMS=(2 2 3) \n" + "M V30 MDLV30/STEABS ATOMS=(4 4 5 22 23) \n" + "M V30 MDLV30/STEREL1 ATOMS=(2 12 13) \n" + "M V30 MDLV30/STEREL2 ATOMS=(1 14) \n" + "M V30 MDLV30/STERAC4 ATOMS=(1 19) \n" + "M V30 MDLV30/STERAC3 ATOMS=(2 20 21) \n" + "M V30 MDLV30/STEREL3 ATOMS=(2 24 25) \n" + "M V30 MDLV30/STEREL4 ATOMS=(1 26) \n" + "M V30 END COLLECTION \n" + "M V30 END CTAB \n" + "M END \n"; + + char options[] = "-EnhancedStereochemistry"; + inchi_Output output; + inchi_Output *poutput = &output; + const char expected_inchi[] = "InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(6,8)(4)3(7,9)(10)"; + + EXPECT_EQ(MakeINCHIFromMolfileText(molblock, options, poutput), 0); + EXPECT_STREQ(poutput->szInChI, expected_inchi); + + poutput->szLog = nullptr; + poutput->szMessage = nullptr; + + FreeINCHI(poutput); +} + +TEST(test_enhancedStereo, test_EnhancedStereochemistry_3_mols_molblock_wrong) +{ + const char *molblock = + "my_test_mol \n" + " -INDIGO-01232613442D \n" + " \n" + " 0 0 0 0 0 0 0 0 0 0 0 V3000 \n" + "M V30 BEGIN CTAB \n" + "M V30 COUNTS 36 34 0 0 0 \n" + "M V30 BEGIN ATOM \n" + "M V30 1 C 5.83301 -3.275 0.0 0 CFG=1 \n" + "M V30 2 C 4.96699 -2.775 0.0 0 CFG=1 \n" + "M V30 3 C 4.10096 -3.275 0.0 0 CFG=2 \n" + "M V30 4 C 3.23493 -2.775 0.0 0 CFG=1 \n" + "M V30 5 C 2.36891 -3.275 0.0 0 CFG=2 \n" + "M V30 6 C 1.50289 -2.775 0.0 0 \n" + "M V30 7 Br 2.36891 -4.275 0.0 0 \n" + "M V30 8 Cl 3.23493 -1.775 0.0 0 \n" + "M V30 9 Cl 4.10096 -4.275 0.0 0 \n" + "M V30 10 Cl 4.96699 -1.775 0.0 0 \n" + "M V30 11 Cl 5.83301 -4.275 0.0 0 \n" + "M V30 12 C 6.69904 -2.775 0.0 0 CFG=1 \n" + "M V30 13 C 7.56506 -3.275 0.0 0 CFG=1 \n" + "M V30 14 C 8.43109 -2.77501 0.0 0 CFG=2 \n" + "M V30 15 C 9.29711 -3.275 0.0 0 \n" + "M V30 16 Cl 8.43109 -1.77501 0.0 0 \n" + "M V30 17 Cl 7.56506 -4.275 0.0 0 \n" + "M V30 18 Cl 6.69904 -1.775 0.0 0 \n" + "M V30 19 C 6.13302 -7.62502 0.0 0 CFG=2 \n" + "M V30 20 C 5.26698 -7.12498 0.0 0 CFG=1 \n" + "M V30 21 C 4.40101 -7.62502 0.0 0 CFG=2 \n" + "M V30 22 C 3.53496 -7.12498 0.0 0 CFG=1 \n" + "M V30 23 C 2.66891 -7.62502 0.0 0 CFG=2 \n" + "M V30 24 C 6.99899 -7.12498 0.0 0 CFG=2 \n" + "M V30 25 C 7.86504 -7.62502 0.0 0 CFG=2 \n" + "M V30 26 C 8.73109 -7.12498 0.0 0 CFG=2 \n" + "M V30 27 C 1.80295 -7.12498 0.0 0 \n" + "M V30 28 Br 2.66891 -8.62501 0.0 0 \n" + "M V30 29 Cl 3.53496 -6.12499 0.0 0 \n" + "M V30 30 Cl 4.40101 -8.62501 0.0 0 \n" + "M V30 31 Cl 5.26698 -6.12499 0.0 0 \n" + "M V30 32 Cl 6.13302 -8.62501 0.0 0 \n" + "M V30 33 C 9.59705 -7.62502 0.0 0 \n" + "M V30 34 Cl 8.73109 -6.12499 0.0 0 \n" + "M V30 35 Cl 7.86504 -8.62501 0.0 0 \n" + "M V30 36 Cl 6.99899 -6.12499 0.0 0 \n" + "M V30 END ATOM \n" + "M V30 BEGIN BOND \n" + "M V30 1 1 1 2 \n" + "M V30 2 1 1 11 CFG=3 \n" + "M V30 3 1 1 12 \n" + "M V30 4 1 2 3 \n" + "M V30 5 1 2 10 CFG=1 \n" + "M V30 6 1 3 4 \n" + "M V30 7 1 3 9 CFG=1 \n" + "M V30 8 1 4 5 \n" + "M V30 9 1 4 8 CFG=1 \n" + "M V30 10 1 5 6 \n" + "M V30 11 1 5 7 CFG=1 \n" + "M V30 12 1 12 13 \n" + "M V30 13 1 12 18 CFG=3 \n" + "M V30 14 1 13 14 \n" + "M V30 15 1 13 17 CFG=1 \n" + "M V30 16 1 14 15 \n" + "M V30 17 1 14 16 CFG=1 \n" + "M V30 18 1 19 20 \n" + "M V30 19 1 20 21 \n" + "M V30 20 1 21 22 \n" + "M V30 21 1 22 23 \n" + "M V30 22 1 19 24 \n" + "M V30 23 1 24 25 \n" + "M V30 24 1 25 26 \n" + "M V30 25 1 23 27 \n" + "M V30 26 1 23 28 CFG=1 \n" + "M V30 27 1 22 29 CFG=1 \n" + "M V30 28 1 21 30 CFG=1 \n" + "M V30 29 1 20 31 CFG=1 \n" + "M V30 30 1 19 32 CFG=3 \n" + "M V30 31 1 26 33 \n" + "M V30 32 1 26 34 CFG=1 \n" + "M V30 33 1 25 35 CFG=3 \n" + "M V30 34 1 24 36 CFG=1 \n" + "M V30 END BOND \n" + "M V30 BEGIN COLLECTION \n" + "M V30 MDLV30/STERAC2 ATOMS=(2 1 19) \n" + "M V30 MDLV30/STERAC1 ATOMS=(4 2 3 20 21) \n" + "M V30 MDLV30/STEABS ATOMS=(4 4 5 22 23) \n" + "M V30 MDLV30/STEREL1 ATOMS=(4 12 13 24 25) \n" + "M V30 MDLV30/STEREL2 ATOMS=(2 14 26) \n" + "M V30 END COLLECTION \n" + "M V30 END CTAB \n" + "M END \n"; + + char options[] = "-EnhancedStereochemistry"; + inchi_Output output; + inchi_Output *poutput = &output; + const char expected_inchi[] = "InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(6,8)(4)3(7,9)(10)"; + + // EXPECT_EQ(MakeINCHIFromMolfileText(molblock, options, poutput), 1); + // EXPECT_STREQ(poutput->szInChI, expected_inchi); + FreeINCHI(poutput); } diff --git a/INCHI-1-TEST/tests/test_unit/test_inpdef.cpp b/INCHI-1-TEST/tests/test_unit/test_inpdef.cpp index 62df9f7d..b886314d 100644 --- a/INCHI-1-TEST/tests/test_unit/test_inpdef.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_inpdef.cpp @@ -135,15 +135,15 @@ TEST(test_inpdef, test_CreateOrigInpDataFromMolfile_v3000_sgroup) // STERAC2 ATOMS=(1 1) EXPECT_EQ(orig_at_data.v3000->n_sterac, 2); - EXPECT_EQ(orig_at_data.v3000->lists_sterac[0][0], 2); // n from "STERACn" tag - EXPECT_EQ(orig_at_data.v3000->lists_sterac[0][1], 1); // number of members in collection - EXPECT_EQ(orig_at_data.v3000->lists_sterac[0][2], 1); // member atom numbers + EXPECT_EQ(orig_at_data.v3000->lists_sterac[1][0], 2); // n from "STERACn" tag + EXPECT_EQ(orig_at_data.v3000->lists_sterac[1][1], 1); // number of members in collection + EXPECT_EQ(orig_at_data.v3000->lists_sterac[1][2], 1); // member atom numbers // STERAC1 ATOMS=(2 2 3) - EXPECT_EQ(orig_at_data.v3000->lists_sterac[1][0], 1); // STERAC1 ATOMS=(2 2 3) - EXPECT_EQ(orig_at_data.v3000->lists_sterac[1][1], 2); // number of members in collection - EXPECT_EQ(orig_at_data.v3000->lists_sterac[1][2], 2); // member atom numbers - EXPECT_EQ(orig_at_data.v3000->lists_sterac[1][3], 3); // member atom numbers + EXPECT_EQ(orig_at_data.v3000->lists_sterac[0][0], 1); // STERAC1 ATOMS=(2 2 3) + EXPECT_EQ(orig_at_data.v3000->lists_sterac[0][1], 2); // number of members in collection + EXPECT_EQ(orig_at_data.v3000->lists_sterac[0][2], 2); // member atom numbers + EXPECT_EQ(orig_at_data.v3000->lists_sterac[0][3], 3); // member atom numbers EXPECT_EQ(orig_at_data.v3000->n_sterel, 2); From 9dacaa2bd6fbbeac6e101f972e9529fb9809941c Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 26 Jan 2026 13:38:37 +0000 Subject: [PATCH 56/69] fixed s-layer duplication and unknown canonical atom mapping --- CMakeLists.txt | 7 +- .../INCHI_API/libinchi/src/CMakeLists.txt | 10 +- INCHI-1-SRC/INCHI_BASE/src/ichimake.h | 12 +- INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c | 57 ++---- INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c | 165 ++++++++++++++---- INCHI-1-SRC/INCHI_BASE/src/strutil.c | 34 ++-- 6 files changed, 179 insertions(+), 106 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b78c4d8..cb2d5133 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,11 +6,8 @@ set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 11) set(CMAKE_POSITION_INDEPENDENT_CODE ON) -# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -O0 -g") -# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -O0 -g") - -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g") +# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -O0 -g" CACHE STRING "Flags" FORCE) +# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -O0 -g" CACHE STRING "Flags" FORCE) # set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fsanitize=address -O0 -g") # set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -O0 -g") diff --git a/INCHI-1-SRC/INCHI_API/libinchi/src/CMakeLists.txt b/INCHI-1-SRC/INCHI_API/libinchi/src/CMakeLists.txt index 33648da5..79952a6a 100644 --- a/INCHI-1-SRC/INCHI_API/libinchi/src/CMakeLists.txt +++ b/INCHI-1-SRC/INCHI_API/libinchi/src/CMakeLists.txt @@ -8,8 +8,10 @@ target_compile_features(libinchi_compiler_flags INTERFACE c_std_11) set(gcc_like_cxx "$") set(msvc_cxx "$") target_compile_options(libinchi_compiler_flags INTERFACE - "$<${gcc_like_cxx}:$>" - "$<${msvc_cxx}:$>" + # "$<${gcc_like_cxx}:$>" + # "$<${msvc_cxx}:$>" + "$<${gcc_like_cxx}:$>" + "$<${msvc_cxx}:$>" ) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib/static") @@ -151,7 +153,7 @@ if(MATH_LIBRARY) target_link_libraries(libinchi PUBLIC ${MATH_LIBRARY}) endif() -target_compile_definitions(libinchi PRIVATE +target_compile_definitions(libinchi PRIVATE fPIC COMPILE_ANSI_ONLY TARGET_API_LIB @@ -170,4 +172,4 @@ if(UNIX AND NOT APPLE) target_link_options(libinchi PRIVATE "LINKER:--version-script=${P_LIBINCHI_MAP}/libinchi.map,-z,relro") elseif(WIN32 AND NOT MSVC) target_link_options(libinchi PRIVATE "LINKER:--version-script=${P_LIBINCHI_MAP}/libinchi.map") -endif() \ No newline at end of file +endif() diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichimake.h b/INCHI-1-SRC/INCHI_BASE/src/ichimake.h index 03d55237..421fd2ca 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichimake.h +++ b/INCHI-1-SRC/INCHI_BASE/src/ichimake.h @@ -208,14 +208,20 @@ const char *EquString( int EquVal ); INCHI_IOS_STRING *buf, int nCtMode, int *bOverflow ); - int MakeEnhStereoString( INCHI_SORT *pINChISort, + int MakeEnhStereoString( INChI_Aux *pAux, int bOutType, - int num_components, int **enh_stereo, - int nof_units, + int nof_stereo_groups, INCHI_IOS_STRING *strbuf, int nCtMode, int *bOverflow ); + int MakeSlayerString( ORIG_ATOM_DATA *orig_inp_data, + INCHI_SORT *pINChISort, + int bOutType, + int num_components, + INCHI_IOS_STRING *strbuf, + int nCtMode, + int *bOverflow ); int MakeCRVString( ORIG_INFO *OrigInfo, int nLenCT, int bAddDelim, diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c index 928f7fb9..b4c62cae 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c @@ -3658,51 +3658,30 @@ int OutputINCHI_StereoLayer_EnhancedStereo( if ((io->nSegmAction = INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_s_STYPE] ))) { - const char *p_stereo; - if (io->bRelativeStereo[io->iCurTautMode]) { - p_stereo = x_rel; - } else if (io->bRacemicStereo[io->iCurTautMode]) { - p_stereo = x_rac; - } else { - p_stereo = x_abs; - } + // const char *p_stereo; + // if (io->bRelativeStereo[io->iCurTautMode]) { + // p_stereo = x_rel; + // } else if (io->bRacemicStereo[io->iCurTautMode]) { + // p_stereo = x_rac; + // } else { + // p_stereo = x_abs; + // } szGetTag( IdentLbl, io->nTag, io->bTag2 = io->bTag1 | IL_TYPS, io->szTag2, &io->bAlways, 1 ); inchi_strbuf_reset( strbuf ); io->tot_len = 0; if (INCHI_SEGM_FILL == io->nSegmAction) { - io->tot_len += MakeDelim( x_abs, strbuf, &io->bOverflow ); // s1 - io->tot_len += MakeEnhStereoString( io->pINChISort, - io->bOutType, - io->num_components, - orig_inp_data->v3000->lists_steabs, - orig_inp_data->v3000->n_steabs, - strbuf, - 0, - &io->bOverflow); - - - io->tot_len += MakeDelim( x_rel, strbuf, &io->bOverflow ); // s2 - io->tot_len += MakeEnhStereoString( io->pINChISort, - io->bOutType, - io->num_components, - orig_inp_data->v3000->lists_sterel, - orig_inp_data->v3000->n_sterel, - strbuf, - 0, - &io->bOverflow); - - - io->tot_len += MakeDelim( x_rac, strbuf, &io->bOverflow ); // s3 - io->tot_len += MakeEnhStereoString( io->pINChISort, - io->bOutType, - io->num_components, - orig_inp_data->v3000->lists_sterac, - orig_inp_data->v3000->n_sterac, - strbuf, - 0, - &io->bOverflow); + + io->tot_len += MakeSlayerString( + orig_inp_data, + io->pINChISort, + io->bOutType, + io->num_components, + strbuf, + 0, + &io->bOverflow + ); io->bNonTautNonIsoIdentifierNotEmpty += io->bSecondNonTautPass; } diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c index 045694f5..36207e85 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c @@ -2165,30 +2165,91 @@ int compare_ints(const void *a, const void *b) { return (arg1 > arg2) - (arg1 < arg2); } -int MakeEnhStereoString( INCHI_SORT *pINChISort, +int MakeEnhStereoString( INChI_Aux *pAux, int bOutType, - int num_components, int **enh_stereo, - int nof_units, + int nof_stereo_groups, INCHI_IOS_STRING *strbuf, int nCtMode, int *bOverflow ) { int tot_len = 0; + + if (nof_stereo_groups <= 0) { + return 0; + } + + for (int i = 0; i < nof_stereo_groups; i++) { + int count_found_atoms = 0; + const int *atom_numbers = &enh_stereo[i][2]; + int nof_atoms = enh_stereo[i][1]; + int c_atom_numbers[nof_atoms]; + for (int j = 0; j < nof_atoms; j++) { + + int orig_atom_num = atom_numbers[j]; + int canon_atom_num = get_canonical_atom_number(pAux, orig_atom_num); + if (canon_atom_num != -1) { + count_found_atoms++; + } + c_atom_numbers[j] = canon_atom_num; + } + + if (count_found_atoms == 0) { + continue; + } + + if (nof_atoms > 1) { + qsort(c_atom_numbers, nof_atoms, sizeof(int), compare_ints); + } + + tot_len += MakeDelim( "(", strbuf, bOverflow ); + for (int j = 0; j < nof_atoms; j++) { + if (c_atom_numbers[j] == -1) { + continue; + } + tot_len += MakeMult_EnhStereo( c_atom_numbers[j], "", strbuf, nCtMode, bOverflow ); + + if ((j + 1) < enh_stereo[i][1]) { + tot_len += MakeDelim( ",", strbuf, bOverflow ); + } + } + tot_len += MakeDelim( ")", strbuf, bOverflow ); + + } + + return tot_len; +} + +int MakeSlayerString( ORIG_ATOM_DATA *orig_inp_data, + INCHI_SORT *pINChISort, + int bOutType, + int num_components, + INCHI_IOS_STRING *strbuf, + int nCtMode, + int *bOverflow ) +{ + + int tot_len = 0; int ii, nUsedLength0; INCHI_SORT *is, *is0; INChI_Stereo *Stereo; INChI *pINChI; INChI_Aux *pAux; - if (nof_units <= 0) { - return 0; + int DICT_SIZE = 100; + char *dictionary[DICT_SIZE]; // array of string pointers + int counts[DICT_SIZE]; // parallel array of counts + + for (int i = 0; i < DICT_SIZE; i++) { + dictionary[i] = NULL; + counts[i] = 0; } is = NULL; is0 = pINChISort; - /* For each connected component... */ + INCHI_IOS_STRING tmpbuf = {0}; + for (int cur_c = 0; !*bOverflow && cur_c < num_components; cur_c++) { @@ -2196,49 +2257,77 @@ int MakeEnhStereoString( INCHI_SORT *pINChISort, // pINChI = ( 0 <= ( ii = GET_II( bOutType, is ) ) ) ? is->pINChI[ii] : NULL; pAux = ( 0 <= ( ii = GET_II( bOutType, is ) ) ) ? is->pINChI_Aux[ii] : NULL; - tot_len += MakeDelim( "(", strbuf, bOverflow ); - for (int i = 0; i < nof_units; i++) { - - int *atom_numbers = &enh_stereo[i][2]; - int nof_atoms = enh_stereo[i][1]; - int c_atom_numbers[nof_atoms]; - for (int j = 0; j < nof_atoms; j++) { - - int orig_atom_num = atom_numbers[j]; //enh_stereo[i][2 + j]; - int canon_atom_num = get_canonical_atom_number(pAux, orig_atom_num); - if (canon_atom_num == -1) { - printf("Error: could not find canonical atom number for original atom number %d\n", orig_atom_num); - } - c_atom_numbers[j] = canon_atom_num; - + inchi_strbuf_init(&tmpbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + + tot_len += MakeDelim( "1", &tmpbuf, bOverflow ); // s1 + tot_len += MakeEnhStereoString( pAux, + bOutType, + orig_inp_data->v3000->lists_steabs, + orig_inp_data->v3000->n_steabs, + &tmpbuf, + nCtMode, + bOverflow); + + tot_len += MakeDelim( "2", &tmpbuf, bOverflow ); // s2 + tot_len += MakeEnhStereoString( pAux, + bOutType, + orig_inp_data->v3000->lists_sterel, + orig_inp_data->v3000->n_sterel, + &tmpbuf, + 0, + bOverflow); + + tot_len += MakeDelim( "3", &tmpbuf, bOverflow ); // s3 + + tot_len += MakeEnhStereoString( pAux, + bOutType, + orig_inp_data->v3000->lists_sterac, + orig_inp_data->v3000->n_sterac, + &tmpbuf, + 0, + bOverflow); + + + + int found = 0; + for (int i = 0; i < DICT_SIZE; i++) { + if (dictionary[i] && strcmp(tmpbuf.pStr, dictionary[i]) == 0) { + counts[i]++; + found = 1; + break; } - - if (nof_atoms > 1) { - qsort(c_atom_numbers, nof_atoms, sizeof(int), compare_ints); + } + if (!found) { + for (int i = 0; i < DICT_SIZE; i++) { + if (dictionary[i] == NULL) { + dictionary[i] = strdup(tmpbuf.pStr); // remember to free later + counts[i] = 1; + break; + } } + } + inchi_strbuf_close(&tmpbuf); + } - for (int j = 0; j < nof_atoms; j++) { - //tot_len += MakeMult_EnhStereo( enh_stereo[i][2 + j], "", strbuf, nCtMode, bOverflow ); - tot_len += MakeMult_EnhStereo( c_atom_numbers[j], "", strbuf, nCtMode, bOverflow ); - - if ((j + 1) < enh_stereo[i][1]) { - tot_len += MakeDelim( ",", strbuf, bOverflow ); - } + int count = 0; + for (int i = 0; i < DICT_SIZE; i++) { + if (dictionary[i]) { + if (count > 0) { + tot_len += MakeDelim( ";", strbuf, bOverflow ); } - if (i + 1 < nof_units) { - // tot_len += MakeDelim( ";", strbuf, bOverflow ); - tot_len += MakeDelim( ")", strbuf, bOverflow ); - tot_len += MakeDelim( "(", strbuf, bOverflow ); + if (counts[i] > 1) { + tot_len += inchi_strbuf_printf(strbuf, "%d*%s", counts[i], dictionary[i]); + } else { + tot_len += inchi_strbuf_printf(strbuf, "%s", dictionary[i]); } + inchi_free(dictionary[i]); + count++; } - tot_len += MakeDelim( ")", strbuf, bOverflow ); - } return tot_len; } - #ifdef ALPHA_BASE #if ( ALPHA_BASE != 27 ) #error ALPHA_BASE definitions mismatch diff --git a/INCHI-1-SRC/INCHI_BASE/src/strutil.c b/INCHI-1-SRC/INCHI_BASE/src/strutil.c index db569af9..bea34ac0 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/strutil.c +++ b/INCHI-1-SRC/INCHI_BASE/src/strutil.c @@ -4320,29 +4320,29 @@ int invert_parities(INChI *inchi, } if (min_c_atom_num == (AT_NUMB)9999999) { // return -1; - printf("ERROR %d: cannot find min canonical atom num\n", __LINE__); + // printf("ERROR %d: cannot find min canonical atom num\n", __LINE__); continue; } int min_c_parity_idx = get_parity_idx_from_canonical_atom_number(min_c_atom_num, inchi->Stereo->nNumber, inchi->Stereo->nNumberOfStereoCenters); - if (min_c_parity_idx == -1) { - // return -1; - printf("ERROR %d: cannot find parity idx for atom %d %d\n", __LINE__, min_c_atom_num, min_c_parity_idx); - for (int j = 0; j < nof_atoms; j++) { - int orig_atom_num = list_atoms[i][2 + j]; - AT_NUMB canon_atom_num = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num); - int parity_idx = get_parity_idx_from_canonical_atom_number(canon_atom_num, - inchi->Stereo->nNumber, - inchi->Stereo->nNumberOfStereoCenters); - printf(" atom %d -> canon %d -> parity idx %d -> parity %d\n", - orig_atom_num, - canon_atom_num, - parity_idx, - (parity_idx != -1) ? t_parity[parity_idx] : -1); - } - } + // if (min_c_parity_idx == -1) { + // // return -1; + // printf("ERROR %d: cannot find parity idx for atom %d %d\n", __LINE__, min_c_atom_num, min_c_parity_idx); + // for (int j = 0; j < nof_atoms; j++) { + // int orig_atom_num = list_atoms[i][2 + j]; + // AT_NUMB canon_atom_num = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num); + // int parity_idx = get_parity_idx_from_canonical_atom_number(canon_atom_num, + // inchi->Stereo->nNumber, + // inchi->Stereo->nNumberOfStereoCenters); + // printf(" atom %d -> canon %d -> parity idx %d -> parity %d\n", + // orig_atom_num, + // canon_atom_num, + // parity_idx, + // (parity_idx != -1) ? t_parity[parity_idx] : -1); + // } + // } int min_c_atom_parity = t_parity[min_c_parity_idx]; if ((is_absolute == 1) && (min_c_atom_parity == 1)) { From 7c62770a38f89d923497d8bc092ffbaece0a7680 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Tue, 27 Jan 2026 10:41:07 +0000 Subject: [PATCH 57/69] Fixed enh stereochem, added more unit-tests and modified CMakeLists for debug testing --- CMakeLists.txt | 6 - .../INCHI_API/libinchi/src/CMakeLists.txt | 17 +- INCHI-1-SRC/INCHI_BASE/src/ichi_io.c | 2 +- INCHI-1-SRC/INCHI_BASE/src/ichimake.h | 1 + INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c | 30 +- INCHI-1-SRC/INCHI_BASE/src/strutil.c | 36 +- INCHI-1-TEST/tests/test_unit/CMakeLists.txt | 6 + .../tests/test_unit/test_enhancedStereo.cpp | 403 +++++++++++++++++- .../test_unit/test_strutil_enhancedStereo.cpp | 2 +- 9 files changed, 463 insertions(+), 40 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cb2d5133..e2b7e9f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,12 +6,6 @@ set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 11) set(CMAKE_POSITION_INDEPENDENT_CODE ON) -# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -O0 -g" CACHE STRING "Flags" FORCE) -# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -O0 -g" CACHE STRING "Flags" FORCE) - -# set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fsanitize=address -O0 -g") -# set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -O0 -g") - include(FetchContent) FetchContent_Declare( googletest diff --git a/INCHI-1-SRC/INCHI_API/libinchi/src/CMakeLists.txt b/INCHI-1-SRC/INCHI_API/libinchi/src/CMakeLists.txt index 79952a6a..2d7cca9b 100644 --- a/INCHI-1-SRC/INCHI_API/libinchi/src/CMakeLists.txt +++ b/INCHI-1-SRC/INCHI_API/libinchi/src/CMakeLists.txt @@ -8,10 +8,15 @@ target_compile_features(libinchi_compiler_flags INTERFACE c_std_11) set(gcc_like_cxx "$") set(msvc_cxx "$") target_compile_options(libinchi_compiler_flags INTERFACE - # "$<${gcc_like_cxx}:$>" - # "$<${msvc_cxx}:$>" - "$<${gcc_like_cxx}:$>" - "$<${msvc_cxx}:$>" + # "$<$:<${gcc_like_cxx}:$>" + # "$<$:<${msvc_cxx}:$>" + # "$<$:<${gcc_like_cxx}:$>" + # "$<$:<${msvc_cxx}:$>" + + "$<$,$>:-g;-O1;-c;-fno-strict-aliasing;-Wno-all>" + "$<$,$>:-W3;-MT;-O2>" + "$<$,$>:-g;-O0;-fsanitize=address;-c;-fno-strict-aliasing;-Wno-all>" + "$<$,$>:-W3;-MT;-g;-O0>" ) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib/static") @@ -167,6 +172,10 @@ string(REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAG set_target_properties(libinchi PROPERTIES PREFIX "") # set_target_properties(libinchi PROPERTIES SOVERSION 1.07 PREFIX "") +target_link_options(libinchi PRIVATE + "$<$,$>:-fsanitize=address>" +) + if(UNIX AND NOT APPLE) # set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--version-script=${P_LIBINCHI_MAP}/libinchi.map,-z,relro") target_link_options(libinchi PRIVATE "LINKER:--version-script=${P_LIBINCHI_MAP}/libinchi.map,-z,relro") diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichi_io.c b/INCHI-1-SRC/INCHI_BASE/src/ichi_io.c index 0575eace..3c0bdba9 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichi_io.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichi_io.c @@ -1679,7 +1679,7 @@ int inchi_strbuf_addline(INCHI_IOS_STRING* buf, /****************************************************************************/ /* djb-rwth: placed as a global variable to avoid function buffer issues */ char it_buffer[32767]; -int _inchi_trace(char* format, ...) +int _inchi_trace(const char* format, ...) { /* TCHAR buffer[32767]; diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichimake.h b/INCHI-1-SRC/INCHI_BASE/src/ichimake.h index 421fd2ca..d3015ea6 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichimake.h +++ b/INCHI-1-SRC/INCHI_BASE/src/ichimake.h @@ -209,6 +209,7 @@ const char *EquString( int EquVal ); int nCtMode, int *bOverflow ); int MakeEnhStereoString( INChI_Aux *pAux, + char* conf_stereo_string, int bOutType, int **enh_stereo, int nof_stereo_groups, diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c index 36207e85..8426e640 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c @@ -2165,7 +2165,8 @@ int compare_ints(const void *a, const void *b) { return (arg1 > arg2) - (arg1 < arg2); } -int MakeEnhStereoString( INChI_Aux *pAux, +int MakeEnhStereoString( INChI_Aux *pAux, + char* conf_stereo_string, int bOutType, int **enh_stereo, int nof_stereo_groups, @@ -2174,11 +2175,13 @@ int MakeEnhStereoString( INChI_Aux *pAux, int *bOverflow ) { int tot_len = 0; - - if (nof_stereo_groups <= 0) { + int count_added = 0; + if (nof_stereo_groups < 1) { return 0; } + tot_len += MakeDelim( conf_stereo_string, strbuf, bOverflow ); + for (int i = 0; i < nof_stereo_groups; i++) { int count_found_atoms = 0; const int *atom_numbers = &enh_stereo[i][2]; @@ -2208,13 +2211,22 @@ int MakeEnhStereoString( INChI_Aux *pAux, continue; } tot_len += MakeMult_EnhStereo( c_atom_numbers[j], "", strbuf, nCtMode, bOverflow ); + count_added++; if ((j + 1) < enh_stereo[i][1]) { tot_len += MakeDelim( ",", strbuf, bOverflow ); } } tot_len += MakeDelim( ")", strbuf, bOverflow ); + } + if (count_added == 0) { + if (strbuf && strbuf->nUsedLength > 0) { + strbuf->nUsedLength--; + strbuf->pStr[strbuf->nUsedLength] = '\0'; + } + + tot_len = tot_len - 1; } return tot_len; @@ -2232,7 +2244,7 @@ int MakeSlayerString( ORIG_ATOM_DATA *orig_inp_data, int tot_len = 0; int ii, nUsedLength0; INCHI_SORT *is, *is0; - INChI_Stereo *Stereo; + // INChI_Stereo *Stereo; INChI *pINChI; INChI_Aux *pAux; @@ -2259,8 +2271,9 @@ int MakeSlayerString( ORIG_ATOM_DATA *orig_inp_data, inchi_strbuf_init(&tmpbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); - tot_len += MakeDelim( "1", &tmpbuf, bOverflow ); // s1 + // s1 tot_len += MakeEnhStereoString( pAux, + "1", bOutType, orig_inp_data->v3000->lists_steabs, orig_inp_data->v3000->n_steabs, @@ -2268,8 +2281,9 @@ int MakeSlayerString( ORIG_ATOM_DATA *orig_inp_data, nCtMode, bOverflow); - tot_len += MakeDelim( "2", &tmpbuf, bOverflow ); // s2 + // s2 tot_len += MakeEnhStereoString( pAux, + "2", bOutType, orig_inp_data->v3000->lists_sterel, orig_inp_data->v3000->n_sterel, @@ -2277,9 +2291,9 @@ int MakeSlayerString( ORIG_ATOM_DATA *orig_inp_data, 0, bOverflow); - tot_len += MakeDelim( "3", &tmpbuf, bOverflow ); // s3 - + // s3 tot_len += MakeEnhStereoString( pAux, + "3", bOutType, orig_inp_data->v3000->lists_sterac, orig_inp_data->v3000->n_sterac, diff --git a/INCHI-1-SRC/INCHI_BASE/src/strutil.c b/INCHI-1-SRC/INCHI_BASE/src/strutil.c index bea34ac0..4d20d72e 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/strutil.c +++ b/INCHI-1-SRC/INCHI_BASE/src/strutil.c @@ -4327,22 +4327,23 @@ int invert_parities(INChI *inchi, inchi->Stereo->nNumber, inchi->Stereo->nNumberOfStereoCenters); - // if (min_c_parity_idx == -1) { + if (min_c_parity_idx == -1) { + continue; // // return -1; - // printf("ERROR %d: cannot find parity idx for atom %d %d\n", __LINE__, min_c_atom_num, min_c_parity_idx); - // for (int j = 0; j < nof_atoms; j++) { - // int orig_atom_num = list_atoms[i][2 + j]; - // AT_NUMB canon_atom_num = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num); - // int parity_idx = get_parity_idx_from_canonical_atom_number(canon_atom_num, - // inchi->Stereo->nNumber, - // inchi->Stereo->nNumberOfStereoCenters); - // printf(" atom %d -> canon %d -> parity idx %d -> parity %d\n", - // orig_atom_num, - // canon_atom_num, - // parity_idx, - // (parity_idx != -1) ? t_parity[parity_idx] : -1); - // } - // } + // printf("ERROR %d: cannot find parity idx for atom %d %d\n", __LINE__, min_c_atom_num, min_c_parity_idx); + // for (int j = 0; j < nof_atoms; j++) { + // int orig_atom_num = list_atoms[i][2 + j]; + // AT_NUMB canon_atom_num = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num); + // int parity_idx = get_parity_idx_from_canonical_atom_number(canon_atom_num, + // inchi->Stereo->nNumber, + // inchi->Stereo->nNumberOfStereoCenters); + // printf(" atom %d -> canon %d -> parity idx %d -> parity %d\n", + // orig_atom_num, + // canon_atom_num, + // parity_idx, + // (parity_idx != -1) ? t_parity[parity_idx] : -1); + // } + } int min_c_atom_parity = t_parity[min_c_parity_idx]; if ((is_absolute == 1) && (min_c_atom_parity == 1)) { @@ -4355,6 +4356,11 @@ int invert_parities(INChI *inchi, int parity_idx = get_parity_idx_from_canonical_atom_number(canon_atom_num, inchi->Stereo->nNumber, inchi->Stereo->nNumberOfStereoCenters); + + if (parity_idx == -1) { + continue; + } + if (t_parity[parity_idx] == 2) { t_parity[parity_idx] = 1; } else if(t_parity[parity_idx] == 1) { diff --git a/INCHI-1-TEST/tests/test_unit/CMakeLists.txt b/INCHI-1-TEST/tests/test_unit/CMakeLists.txt index 248af435..0419209c 100644 --- a/INCHI-1-TEST/tests/test_unit/CMakeLists.txt +++ b/INCHI-1-TEST/tests/test_unit/CMakeLists.txt @@ -13,6 +13,12 @@ file(GLOB TEST_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/test_*.cpp foreach(test_src ${TEST_SOURCES}) get_filename_component(test_name "${test_src}" NAME_WE) add_executable(${test_name} ${test_src}) + target_compile_options(${test_name} PRIVATE + "$<$:-g;-O0;-fsanitize=address>" + ) + target_link_options(${test_name} PRIVATE + "$<$:-g;-O0;-fsanitize=address>" + ) target_link_libraries(${test_name} PRIVATE gtest_main gmock_main test_dependencies libinchi) add_test(NAME ${test_name} COMMAND $) endforeach() diff --git a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp index 1294638a..448cee6b 100644 --- a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp @@ -177,7 +177,7 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_2_mols) char options[] = "-EnhancedStereochemistry"; inchi_Output output; inchi_Output *poutput = &output; - const char expected_inchi[] = "InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(6,8)(4)3(7,9)(10)"; + const char expected_inchi[] = "InChI=1S/2C10H14BrCl7/c2*1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h2*3-10H,1-2H3/t2*3-,4-,5+,6-,7-,8-,9+,10-/m00/s2*1(3,5)2(6,8)(4)3(7,9)(10)"; EXPECT_EQ(MakeINCHIFromMolfileText(molblock, options, poutput), 0); EXPECT_STREQ(poutput->szInChI, expected_inchi); @@ -188,7 +188,288 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_2_mols) FreeINCHI(poutput); } -TEST(test_enhancedStereo, test_EnhancedStereochemistry_3_mols_molblock_wrong) +TEST(test_enhancedStereo, test_EnhancedStereochemistry_3_mols) +{ + const char *molblock = + "test mol \n" + " -INDIGO-01272609172D \n" + " \n" + " 0 0 0 0 0 0 0 0 0 0 0 V3000 \n" + "M V30 BEGIN CTAB \n" + "M V30 COUNTS 44 41 0 0 0 \n" + "M V30 BEGIN ATOM \n" + "M V30 1 C 5.48304 -3.77499 0.0 0 CFG=1 \n" + "M V30 2 C 4.61702 -3.27499 0.0 0 CFG=1 \n" + "M V30 3 C 3.75099 -3.77499 0.0 0 CFG=2 \n" + "M V30 4 C 2.88496 -3.27499 0.0 0 CFG=1 \n" + "M V30 5 C 2.01894 -3.77499 0.0 0 CFG=2 \n" + "M V30 6 C 1.15292 -3.27499 0.0 0 \n" + "M V30 7 Br 2.01894 -4.77499 0.0 0 \n" + "M V30 8 Cl 2.88496 -2.27499 0.0 0 \n" + "M V30 9 Cl 3.75099 -4.77499 0.0 0 \n" + "M V30 10 Cl 4.61702 -2.27499 0.0 0 \n" + "M V30 11 Cl 5.48304 -4.77499 0.0 0 \n" + "M V30 12 C 6.34907 -3.27499 0.0 0 CFG=1 \n" + "M V30 13 C 7.21509 -3.77499 0.0 0 CFG=1 \n" + "M V30 14 C 8.08112 -3.275 0.0 0 CFG=2 \n" + "M V30 15 C 8.94714 -3.77499 0.0 0 \n" + "M V30 16 Cl 8.08112 -2.275 0.0 0 \n" + "M V30 17 Cl 7.21509 -4.77499 0.0 0 \n" + "M V30 18 Cl 6.34907 -2.27499 0.0 0 \n" + "M V30 19 C 5.78305 -8.12502 0.0 0 CFG=2 \n" + "M V30 20 C 4.91701 -7.62498 0.0 0 CFG=1 \n" + "M V30 21 C 4.05104 -8.12502 0.0 0 CFG=2 \n" + "M V30 22 C 3.18499 -7.62498 0.0 0 CFG=1 \n" + "M V30 23 C 2.31894 -8.12502 0.0 0 CFG=2 \n" + "M V30 24 C 6.64902 -7.62498 0.0 0 CFG=2 \n" + "M V30 25 C 7.51507 -8.12502 0.0 0 CFG=2 \n" + "M V30 26 C 8.38112 -7.62498 0.0 0 CFG=2 \n" + "M V30 27 C 1.45298 -7.62498 0.0 0 \n" + "M V30 28 Br 2.31894 -9.12501 0.0 0 \n" + "M V30 29 Cl 3.18499 -6.62499 0.0 0 \n" + "M V30 30 Cl 4.05104 -9.12501 0.0 0 \n" + "M V30 31 Cl 4.91701 -6.62499 0.0 0 \n" + "M V30 32 Cl 5.78305 -9.12501 0.0 0 \n" + "M V30 33 C 9.24708 -8.12502 0.0 0 \n" + "M V30 34 Cl 8.38112 -6.62499 0.0 0 \n" + "M V30 35 Cl 7.51507 -9.12501 0.0 0 \n" + "M V30 36 Cl 6.64902 -6.62499 0.0 0 \n" + "M V30 37 C 14.367 -4.45 0.0 0 CFG=1 \n" + "M V30 38 C 15.233 -3.95 0.0 0 CFG=2 \n" + "M V30 39 C 16.099 -4.45 0.0 0 \n" + "M V30 40 C 15.233 -2.95 0.0 0 \n" + "M V30 41 C 13.501 -3.95 0.0 0 CFG=1 \n" + "M V30 42 C 12.6349 -4.45 0.0 0 \n" + "M V30 43 C 13.501 -2.95 0.0 0 \n" + "M V30 44 C 14.367 -5.45 0.0 0 \n" + "M V30 END ATOM \n" + "M V30 BEGIN BOND \n" + "M V30 1 1 1 2 \n" + "M V30 2 1 1 11 CFG=3 \n" + "M V30 3 1 1 12 \n" + "M V30 4 1 2 3 \n" + "M V30 5 1 2 10 CFG=1 \n" + "M V30 6 1 3 4 \n" + "M V30 7 1 3 9 CFG=1 \n" + "M V30 8 1 4 5 \n" + "M V30 9 1 4 8 CFG=1 \n" + "M V30 10 1 5 6 \n" + "M V30 11 1 5 7 CFG=1 \n" + "M V30 12 1 12 13 \n" + "M V30 13 1 12 18 CFG=3 \n" + "M V30 14 1 13 14 \n" + "M V30 15 1 13 17 CFG=1 \n" + "M V30 16 1 14 15 \n" + "M V30 17 1 14 16 CFG=1 \n" + "M V30 18 1 19 20 \n" + "M V30 19 1 20 21 \n" + "M V30 20 1 21 22 \n" + "M V30 21 1 22 23 \n" + "M V30 22 1 19 24 \n" + "M V30 23 1 24 25 \n" + "M V30 24 1 25 26 \n" + "M V30 25 1 23 27 \n" + "M V30 26 1 23 28 CFG=1 \n" + "M V30 27 1 22 29 CFG=1 \n" + "M V30 28 1 21 30 CFG=1 \n" + "M V30 29 1 20 31 CFG=1 \n" + "M V30 30 1 19 32 CFG=3 \n" + "M V30 31 1 26 33 \n" + "M V30 32 1 26 34 CFG=1 \n" + "M V30 33 1 25 35 CFG=3 \n" + "M V30 34 1 24 36 CFG=1 \n" + "M V30 35 1 37 38 \n" + "M V30 36 1 38 39 \n" + "M V30 37 1 38 40 CFG=1 \n" + "M V30 38 1 37 41 \n" + "M V30 39 1 41 42 \n" + "M V30 40 1 41 43 CFG=1 \n" + "M V30 41 1 37 44 CFG=3 \n" + "M V30 END BOND \n" + "M V30 BEGIN COLLECTION \n" + "M V30 MDLV30/STERAC2 ATOMS=(1 1) \n" + "M V30 MDLV30/STERAC1 ATOMS=(2 2 3) \n" + "M V30 MDLV30/STEABS ATOMS=(5 4 5 22 23 38) \n" + "M V30 MDLV30/STEREL1 ATOMS=(2 12 13) \n" + "M V30 MDLV30/STEREL2 ATOMS=(1 14) \n" + "M V30 MDLV30/STERAC4 ATOMS=(1 19) \n" + "M V30 MDLV30/STERAC3 ATOMS=(2 20 21) \n" + "M V30 MDLV30/STEREL3 ATOMS=(2 24 25) \n" + "M V30 MDLV30/STEREL4 ATOMS=(1 26) \n" + "M V30 MDLV30/STERAC5 ATOMS=(2 37 41) \n" + "M V30 END COLLECTION \n" + "M V30 END CTAB \n" + "M END \n"; + + + char options[] = "-EnhancedStereochemistry"; + inchi_Output output; + inchi_Output *poutput = &output; + const char expected_inchi[] = "InChI=1S/2C10H14BrCl7.C8H18/c2*1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12;1-6(2)8(5)7(3)4/h2*3-10H,1-2H3;6-8H,1-5H3/t2*3-,4-,5+,6-,7-,8-,9+,10-;/m00./s2*1(3,5)2(6,8)(4)3(7,9)(10);1(6)3(7,8)"; + + EXPECT_EQ(MakeINCHIFromMolfileText(molblock, options, poutput), 0); + EXPECT_STREQ(poutput->szInChI, expected_inchi); + + poutput->szLog = nullptr; + poutput->szMessage = nullptr; + + FreeINCHI(poutput); +} + +TEST(test_enhancedStereo, test_EnhancedStereochemistry_4_mols) +{ + const char *molblock = + "test_mol \n" + " -INDIGO-01272609502D \n" + " \n" + " 0 0 0 0 0 0 0 0 0 0 0 V3000 \n" + "M V30 BEGIN CTAB \n" + "M V30 COUNTS 57 53 0 0 0 \n" + "M V30 BEGIN ATOM \n" + "M V30 1 C 5.48304 -3.77499 0.0 0 CFG=1 \n" + "M V30 2 C 4.61702 -3.27499 0.0 0 CFG=1 \n" + "M V30 3 C 3.75099 -3.77499 0.0 0 CFG=2 \n" + "M V30 4 C 2.88496 -3.27499 0.0 0 CFG=1 \n" + "M V30 5 C 2.01894 -3.77499 0.0 0 CFG=2 \n" + "M V30 6 C 1.15292 -3.27499 0.0 0 \n" + "M V30 7 Br 2.01894 -4.77499 0.0 0 \n" + "M V30 8 Cl 2.88496 -2.27499 0.0 0 \n" + "M V30 9 Cl 3.75099 -4.77499 0.0 0 \n" + "M V30 10 Cl 4.61702 -2.27499 0.0 0 \n" + "M V30 11 Cl 5.48304 -4.77499 0.0 0 \n" + "M V30 12 C 6.34907 -3.27499 0.0 0 CFG=1 \n" + "M V30 13 C 7.21509 -3.77499 0.0 0 CFG=1 \n" + "M V30 14 C 8.08112 -3.275 0.0 0 CFG=2 \n" + "M V30 15 C 8.94714 -3.77499 0.0 0 \n" + "M V30 16 Cl 8.08112 -2.275 0.0 0 \n" + "M V30 17 Cl 7.21509 -4.77499 0.0 0 \n" + "M V30 18 Cl 6.34907 -2.27499 0.0 0 \n" + "M V30 19 C 5.78305 -8.12502 0.0 0 CFG=2 \n" + "M V30 20 C 4.91701 -7.62498 0.0 0 CFG=1 \n" + "M V30 21 C 4.05104 -8.12502 0.0 0 CFG=2 \n" + "M V30 22 C 3.18499 -7.62498 0.0 0 CFG=1 \n" + "M V30 23 C 2.31894 -8.12502 0.0 0 CFG=2 \n" + "M V30 24 C 6.64902 -7.62498 0.0 0 CFG=2 \n" + "M V30 25 C 7.51507 -8.12502 0.0 0 CFG=2 \n" + "M V30 26 C 8.38112 -7.62498 0.0 0 CFG=2 \n" + "M V30 27 C 1.45298 -7.62498 0.0 0 \n" + "M V30 28 Br 2.31894 -9.12501 0.0 0 \n" + "M V30 29 Cl 3.18499 -6.62499 0.0 0 \n" + "M V30 30 Cl 4.05104 -9.12501 0.0 0 \n" + "M V30 31 Cl 4.91701 -6.62499 0.0 0 \n" + "M V30 32 Cl 5.78305 -9.12501 0.0 0 \n" + "M V30 33 C 9.24708 -8.12502 0.0 0 \n" + "M V30 34 Cl 8.38112 -6.62499 0.0 0 \n" + "M V30 35 Cl 7.51507 -9.12501 0.0 0 \n" + "M V30 36 Cl 6.64902 -6.62499 0.0 0 \n" + "M V30 37 C 14.367 -4.45 0.0 0 CFG=1 \n" + "M V30 38 C 15.233 -3.95 0.0 0 CFG=2 \n" + "M V30 39 C 16.099 -4.45 0.0 0 \n" + "M V30 40 C 15.233 -2.95 0.0 0 \n" + "M V30 41 C 13.501 -3.95 0.0 0 CFG=1 \n" + "M V30 42 C 12.6349 -4.45 0.0 0 \n" + "M V30 43 C 13.501 -2.95 0.0 0 \n" + "M V30 44 C 14.367 -5.45 0.0 0 \n" + "M V30 45 C 11.7689 -3.95 0.0 0 \n" + "M V30 46 C 11.417 -7.75 0.0 0 \n" + "M V30 47 C 12.283 -7.25 0.0 0 CFG=2 \n" + "M V30 48 C 13.149 -7.75 0.0 0 \n" + "M V30 49 C 14.0151 -7.25 0.0 0 CFG=2 \n" + "M V30 50 C 14.8811 -7.75 0.0 0 \n" + "M V30 51 C 13.149 -8.75 0.0 0 CFG=2 \n" + "M V30 52 C 12.283 -9.25 0.0 0 \n" + "M V30 53 C 14.0151 -9.25 0.0 0 CFG=2 \n" + "M V30 54 C 14.0151 -10.25 0.0 0 \n" + "M V30 55 C 14.8811 -8.75 0.0 0 \n" + "M V30 56 C 14.0151 -6.25 0.0 0 \n" + "M V30 57 C 12.283 -6.25 0.0 0 \n" + "M V30 END ATOM \n" + "M V30 BEGIN BOND \n" + "M V30 1 1 1 2 \n" + "M V30 2 1 1 11 CFG=3 \n" + "M V30 3 1 1 12 \n" + "M V30 4 1 2 3 \n" + "M V30 5 1 2 10 CFG=1 \n" + "M V30 6 1 3 4 \n" + "M V30 7 1 3 9 CFG=1 \n" + "M V30 8 1 4 5 \n" + "M V30 9 1 4 8 CFG=1 \n" + "M V30 10 1 5 6 \n" + "M V30 11 1 5 7 CFG=1 \n" + "M V30 12 1 12 13 \n" + "M V30 13 1 12 18 CFG=3 \n" + "M V30 14 1 13 14 \n" + "M V30 15 1 13 17 CFG=1 \n" + "M V30 16 1 14 15 \n" + "M V30 17 1 14 16 CFG=1 \n" + "M V30 18 1 19 20 \n" + "M V30 19 1 20 21 \n" + "M V30 20 1 21 22 \n" + "M V30 21 1 22 23 \n" + "M V30 22 1 19 24 \n" + "M V30 23 1 24 25 \n" + "M V30 24 1 25 26 \n" + "M V30 25 1 23 27 \n" + "M V30 26 1 23 28 CFG=1 \n" + "M V30 27 1 22 29 CFG=1 \n" + "M V30 28 1 21 30 CFG=1 \n" + "M V30 29 1 20 31 CFG=1 \n" + "M V30 30 1 19 32 CFG=3 \n" + "M V30 31 1 26 33 \n" + "M V30 32 1 26 34 CFG=1 \n" + "M V30 33 1 25 35 CFG=3 \n" + "M V30 34 1 24 36 CFG=1 \n" + "M V30 35 1 37 38 \n" + "M V30 36 1 38 39 \n" + "M V30 37 1 38 40 CFG=1 \n" + "M V30 38 1 37 41 \n" + "M V30 39 1 41 42 \n" + "M V30 40 1 41 43 CFG=1 \n" + "M V30 41 1 37 44 CFG=3 \n" + "M V30 42 1 42 45 \n" + "M V30 43 1 46 47 \n" + "M V30 44 1 47 48 \n" + "M V30 45 1 48 49 \n" + "M V30 46 1 49 50 \n" + "M V30 47 1 48 51 \n" + "M V30 48 1 51 52 CFG=1 \n" + "M V30 49 1 51 53 \n" + "M V30 50 1 53 54 \n" + "M V30 51 1 53 55 CFG=1 \n" + "M V30 52 1 49 56 CFG=1 \n" + "M V30 53 1 47 57 CFG=1 \n" + "M V30 END BOND \n" + "M V30 BEGIN COLLECTION \n" + "M V30 MDLV30/STERAC2 ATOMS=(1 1) \n" + "M V30 MDLV30/STERAC1 ATOMS=(2 2 3) \n" + "M V30 MDLV30/STEABS ATOMS=(9 4 5 22 23 38 47 49 51 53) \n" + "M V30 MDLV30/STEREL1 ATOMS=(2 12 13) \n" + "M V30 MDLV30/STEREL2 ATOMS=(1 14) \n" + "M V30 MDLV30/STERAC4 ATOMS=(1 19) \n" + "M V30 MDLV30/STERAC3 ATOMS=(2 20 21) \n" + "M V30 MDLV30/STEREL3 ATOMS=(2 24 25) \n" + "M V30 MDLV30/STEREL4 ATOMS=(1 26) \n" + "M V30 MDLV30/STERAC5 ATOMS=(2 37 41) \n" + "M V30 END COLLECTION \n" + "M V30 END CTAB \n" + "M END \n"; + + + char options[] = "-EnhancedStereochemistry"; + inchi_Output output; + inchi_Output *poutput = &output; + const char expected_inchi[] = "InChI=1S/C12H26.2C10H14BrCl7.C9H20/c1-8(2)11(7)12(9(3)4)10(5)6;2*1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12;1-6-8(4)9(5)7(2)3/h8-12H,1-7H3;2*3-10H,1-2H3;7-9H,6H2,1-5H3/t11-;2*3-,4-,5+,6-,7-,8-,9+,10-;8-,9+/m1001/s1(8,9,10,11);2*1(3,5)2(6,8)(4)3(7,9)(10);1(7)3(8,9)"; + + EXPECT_EQ(MakeINCHIFromMolfileText(molblock, options, poutput), 0); + EXPECT_STREQ(poutput->szInChI, expected_inchi); + + poutput->szLog = nullptr; + poutput->szMessage = nullptr; + + FreeINCHI(poutput); +} + +TEST(test_enhancedStereo, test_EnhancedStereochemistry_2_mols_inter_enhstereo_grps) { const char *molblock = "my_test_mol \n" @@ -284,10 +565,122 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_3_mols_molblock_wrong) char options[] = "-EnhancedStereochemistry"; inchi_Output output; inchi_Output *poutput = &output; - const char expected_inchi[] = "InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(6,8)(4)3(7,9)(10)"; + const char expected_inchi[] = "InChI=1S/2C10H14BrCl7/c2*1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h2*3-10H,1-2H3/t2*3-,4-,5+,6-,7-,8-,9+,10-/m00/s2*1(3,5)2(6,8)(4)3(7,9)(10)"; + + EXPECT_EQ(MakeINCHIFromMolfileText(molblock, options, poutput), 0); + EXPECT_STREQ(poutput->szInChI, expected_inchi); + + poutput->szLog = nullptr; + poutput->szMessage = nullptr; + + FreeINCHI(poutput); +} + +TEST(test_enhancedStereo, test_EnhancedStereochemistry_2_different_mols_inter_enhstereo_grps) +{ + const char *molblock = + "test_mols \n" + " -INDIGO-01272610042D \n" + " \n" + " 0 0 0 0 0 0 0 0 0 0 0 V3000 \n" + "M V30 BEGIN CTAB \n" + "M V30 COUNTS 37 35 0 0 0 \n" + "M V30 BEGIN ATOM \n" + "M V30 1 C 5.43304 -3.47499 0.0 0 CFG=1 \n" + "M V30 2 C 4.56702 -2.97499 0.0 0 CFG=1 \n" + "M V30 3 C 3.70099 -3.47499 0.0 0 CFG=2 \n" + "M V30 4 C 2.83496 -2.97499 0.0 0 CFG=1 \n" + "M V30 5 C 1.96894 -3.47499 0.0 0 CFG=2 \n" + "M V30 6 C 1.10292 -2.97499 0.0 0 \n" + "M V30 7 Br 1.96894 -4.47499 0.0 0 \n" + "M V30 8 Cl 2.83496 -1.97499 0.0 0 \n" + "M V30 9 Cl 3.70099 -4.47499 0.0 0 \n" + "M V30 10 Cl 4.56702 -1.97499 0.0 0 \n" + "M V30 11 Cl 5.43304 -4.47499 0.0 0 \n" + "M V30 12 C 6.29907 -2.97499 0.0 0 CFG=1 \n" + "M V30 13 C 7.16509 -3.47499 0.0 0 CFG=1 \n" + "M V30 14 C 8.03112 -2.975 0.0 0 CFG=2 \n" + "M V30 15 C 8.89714 -3.47499 0.0 0 \n" + "M V30 16 Cl 8.03112 -1.975 0.0 0 \n" + "M V30 17 Cl 7.16509 -4.47499 0.0 0 \n" + "M V30 18 Cl 6.29907 -1.97499 0.0 0 \n" + "M V30 19 C 5.73305 -7.82502 0.0 0 CFG=2 \n" + "M V30 20 C 4.86701 -7.32498 0.0 0 CFG=1 \n" + "M V30 21 C 4.00104 -7.82502 0.0 0 CFG=2 \n" + "M V30 22 C 3.13499 -7.32498 0.0 0 CFG=1 \n" + "M V30 23 C 2.26894 -7.82502 0.0 0 CFG=2 \n" + "M V30 24 C 6.59902 -7.32498 0.0 0 CFG=2 \n" + "M V30 25 C 7.46507 -7.82502 0.0 0 CFG=2 \n" + "M V30 26 C 8.33112 -7.32498 0.0 0 CFG=2 \n" + "M V30 27 C 1.40298 -7.32498 0.0 0 \n" + "M V30 28 Br 2.26894 -8.82501 0.0 0 \n" + "M V30 29 Cl 3.13499 -6.32499 0.0 0 \n" + "M V30 30 Cl 4.00104 -8.82501 0.0 0 \n" + "M V30 31 Cl 4.86701 -6.32499 0.0 0 \n" + "M V30 32 Cl 5.73305 -8.82501 0.0 0 \n" + "M V30 33 C 9.19708 -7.82502 0.0 0 \n" + "M V30 34 Cl 8.33112 -6.32499 0.0 0 \n" + "M V30 35 Cl 7.46507 -8.82501 0.0 0 \n" + "M V30 36 Cl 6.59902 -6.32499 0.0 0 \n" + "M V30 37 C 9.19702 -8.82502 0.0 0 \n" + "M V30 END ATOM \n" + "M V30 BEGIN BOND \n" + "M V30 1 1 1 2 \n" + "M V30 2 1 1 11 CFG=3 \n" + "M V30 3 1 1 12 \n" + "M V30 4 1 2 3 \n" + "M V30 5 1 2 10 CFG=1 \n" + "M V30 6 1 3 4 \n" + "M V30 7 1 3 9 CFG=1 \n" + "M V30 8 1 4 5 \n" + "M V30 9 1 4 8 CFG=1 \n" + "M V30 10 1 5 6 \n" + "M V30 11 1 5 7 CFG=1 \n" + "M V30 12 1 12 13 \n" + "M V30 13 1 12 18 CFG=3 \n" + "M V30 14 1 13 14 \n" + "M V30 15 1 13 17 CFG=1 \n" + "M V30 16 1 14 15 \n" + "M V30 17 1 14 16 CFG=1 \n" + "M V30 18 1 19 20 \n" + "M V30 19 1 20 21 \n" + "M V30 20 1 21 22 \n" + "M V30 21 1 22 23 \n" + "M V30 22 1 19 24 \n" + "M V30 23 1 24 25 \n" + "M V30 24 1 25 26 \n" + "M V30 25 1 23 27 \n" + "M V30 26 1 23 28 CFG=1 \n" + "M V30 27 1 22 29 CFG=1 \n" + "M V30 28 1 21 30 CFG=1 \n" + "M V30 29 1 20 31 CFG=1 \n" + "M V30 30 1 19 32 CFG=3 \n" + "M V30 31 1 26 33 \n" + "M V30 32 1 26 34 CFG=1 \n" + "M V30 33 1 25 35 CFG=3 \n" + "M V30 34 1 24 36 CFG=1 \n" + "M V30 35 1 33 37 \n" + "M V30 END BOND \n" + "M V30 BEGIN COLLECTION \n" + "M V30 MDLV30/STERAC2 ATOMS=(2 1 19) \n" + "M V30 MDLV30/STERAC1 ATOMS=(4 2 3 20 21) \n" + "M V30 MDLV30/STEABS ATOMS=(4 4 5 22 23) \n" + "M V30 MDLV30/STEREL1 ATOMS=(4 12 13 24 25) \n" + "M V30 MDLV30/STEREL2 ATOMS=(2 14 26) \n" + "M V30 END COLLECTION \n" + "M V30 END CTAB \n" + "M END \n"; + + char options[] = "-EnhancedStereochemistry"; + inchi_Output output; + inchi_Output *poutput = &output; + const char expected_inchi[] = "InChI=1S/C11H16BrCl7.C10H14BrCl7/c1-3-5(13)7(15)9(17)11(19)10(18)8(16)6(14)4(2)12;1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h4-11H,3H2,1-2H3;3-10H,1-2H3/t4-,5-,6+,7-,8-,9-,10+,11-;3-,4-,5+,6-,7-,8-,9+,10-/m00/s1(4,6)2(7,9)(5)3(8,10)(11);1(3,5)2(6,8)(4)3(7,9)(10)"; - // EXPECT_EQ(MakeINCHIFromMolfileText(molblock, options, poutput), 1); - // EXPECT_STREQ(poutput->szInChI, expected_inchi); + EXPECT_EQ(MakeINCHIFromMolfileText(molblock, options, poutput), 0); + EXPECT_STREQ(poutput->szInChI, expected_inchi); + + poutput->szLog = nullptr; + poutput->szMessage = nullptr; FreeINCHI(poutput); } diff --git a/INCHI-1-TEST/tests/test_unit/test_strutil_enhancedStereo.cpp b/INCHI-1-TEST/tests/test_unit/test_strutil_enhancedStereo.cpp index 07b1b288..0ff3c8ee 100644 --- a/INCHI-1-TEST/tests/test_unit/test_strutil_enhancedStereo.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_strutil_enhancedStereo.cpp @@ -151,7 +151,7 @@ TEST(test_strutil_enhancedStereo, test_set_EnhancedStereo_t_m_layers_1) ret = set_EnhancedStereo_t_m_layers(orig_inp_data, inchi, pAux); std::cout << "Test finished\n"; - EXPECT_EQ(ret, 1); + EXPECT_EQ(ret, 0); FreeOrigAtData(orig_inp_data); inchi_free(orig_inp_data); From 5766fec46338cf8da859938c4162df1602cf22e6 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Tue, 27 Jan 2026 11:02:53 +0000 Subject: [PATCH 58/69] Adjusted assert to account for missing enh stereo chem message --- INCHI-1-TEST/tests/test_executable/test_io.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/INCHI-1-TEST/tests/test_executable/test_io.py b/INCHI-1-TEST/tests/test_executable/test_io.py index d507960f..dd38d1ed 100644 --- a/INCHI-1-TEST/tests/test_executable/test_io.py +++ b/INCHI-1-TEST/tests/test_executable/test_io.py @@ -59,7 +59,8 @@ def test_executable_rejects_more_than_999_atoms( result = run_inchi_exe(molfile_v3000_more_than_999_atoms_and_bonds) assert ( - "Error 170 (no InChI; V3000 enhanced stereo read/stored but ignored; Too many atoms [did you forget 'LargeMolecules' switch?])" + # "Error 170 (no InChI; V3000 enhanced stereo read/stored but ignored; Too many atoms [did you forget 'LargeMolecules' switch?])" + "Error 170 (no InChI; Too many atoms [did you forget 'LargeMolecules' switch?])" in result.stderr ) @@ -72,7 +73,8 @@ def test_executable_accepts_more_than_999_atoms_with_flag( ) assert ( - "Error 170 (no InChI; V3000 enhanced stereo read/stored but ignored; Too many atoms [did you forget 'LargeMolecules' switch?])" + # "Error 170 (no InChI; V3000 enhanced stereo read/stored but ignored; Too many atoms [did you forget 'LargeMolecules' switch?])" + "Error 170 (no InChI; Too many atoms [did you forget 'LargeMolecules' switch?])" not in result.stderr ) assert "Experimental mode: Up to 32766 atoms per structure" in result.stderr From 4ddd959dc6a35c55117a98f2b7588f3a5a83877f Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Wed, 28 Jan 2026 08:22:15 +0000 Subject: [PATCH 59/69] added fix if no collection available, standard functionality will be applied --- .../INCHI_API/libinchi/src/CMakeLists.txt | 4 +- INCHI-1-SRC/INCHI_BASE/src/ichimake.h | 4 +- INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c | 39 +++++++++---------- INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c | 29 +++++++------- 4 files changed, 39 insertions(+), 37 deletions(-) diff --git a/INCHI-1-SRC/INCHI_API/libinchi/src/CMakeLists.txt b/INCHI-1-SRC/INCHI_API/libinchi/src/CMakeLists.txt index 2d7cca9b..43928ff5 100644 --- a/INCHI-1-SRC/INCHI_API/libinchi/src/CMakeLists.txt +++ b/INCHI-1-SRC/INCHI_API/libinchi/src/CMakeLists.txt @@ -5,8 +5,8 @@ project(LibInChI_API VERSION 1.7) add_library(libinchi_compiler_flags INTERFACE) target_compile_features(libinchi_compiler_flags INTERFACE c_std_11) -set(gcc_like_cxx "$") -set(msvc_cxx "$") +# set(gcc_like_cxx "$") +# set(msvc_cxx "$") target_compile_options(libinchi_compiler_flags INTERFACE # "$<$:<${gcc_like_cxx}:$>" # "$<$:<${msvc_cxx}:$>" diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichimake.h b/INCHI-1-SRC/INCHI_BASE/src/ichimake.h index d3015ea6..8bc4faf4 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichimake.h +++ b/INCHI-1-SRC/INCHI_BASE/src/ichimake.h @@ -208,8 +208,8 @@ const char *EquString( int EquVal ); INCHI_IOS_STRING *buf, int nCtMode, int *bOverflow ); - int MakeEnhStereoString( INChI_Aux *pAux, - char* conf_stereo_string, + int MakeEnhStereoString( INChI_Aux *pAux, + const char* conf_stereo_string, int bOutType, int **enh_stereo, int nof_stereo_groups, diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c index b4c62cae..99726d8b 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c @@ -3657,31 +3657,30 @@ int OutputINCHI_StereoLayer_EnhancedStereo( /* s-layer */ if ((io->nSegmAction = INChI_SegmentAction( io->sDifSegs[io->nCurINChISegment][DIFS_s_STYPE] ))) { - - // const char *p_stereo; - // if (io->bRelativeStereo[io->iCurTautMode]) { - // p_stereo = x_rel; - // } else if (io->bRacemicStereo[io->iCurTautMode]) { - // p_stereo = x_rac; - // } else { - // p_stereo = x_abs; - // } + const char *p_stereo = io->bRelativeStereo[io->iCurTautMode] ? x_rel : + io->bRacemicStereo[io->iCurTautMode] ? x_rac : x_abs; szGetTag( IdentLbl, io->nTag, io->bTag2 = io->bTag1 | IL_TYPS, io->szTag2, &io->bAlways, 1 ); - inchi_strbuf_reset( strbuf ); + inchi_strbuf_reset( strbuf ); io->tot_len = 0; + io->tot_len = 0; if (INCHI_SEGM_FILL == io->nSegmAction) { - - io->tot_len += MakeSlayerString( - orig_inp_data, - io->pINChISort, - io->bOutType, - io->num_components, - strbuf, - 0, - &io->bOverflow - ); + if (orig_inp_data->v3000->n_steabs > 0 || + orig_inp_data->v3000->n_sterel > 0 || + orig_inp_data->v3000->n_sterac > 0) { + io->tot_len += MakeSlayerString( + orig_inp_data, + io->pINChISort, + io->bOutType, + io->num_components, + strbuf, + io->TAUT_MODE, + &io->bOverflow + ); + } else { + ( io->tot_len ) += MakeDelim( p_stereo, strbuf, &io->bOverflow ); + } io->bNonTautNonIsoIdentifierNotEmpty += io->bSecondNonTautPass; } diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c index 8426e640..3fbca441 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c @@ -2166,7 +2166,7 @@ int compare_ints(const void *a, const void *b) { } int MakeEnhStereoString( INChI_Aux *pAux, - char* conf_stereo_string, + const char* conf_stereo_string, int bOutType, int **enh_stereo, int nof_stereo_groups, @@ -2242,9 +2242,15 @@ int MakeSlayerString( ORIG_ATOM_DATA *orig_inp_data, { int tot_len = 0; - int ii, nUsedLength0; - INCHI_SORT *is, *is0; - // INChI_Stereo *Stereo; + int ii; + + const char* x_abs = "1"; + const char* x_rel = "2"; + const char* x_rac = "3"; + + INCHI_SORT *is = NULL; + INCHI_SORT *is0 = pINChISort; + INChI *pINChI; INChI_Aux *pAux; @@ -2257,9 +2263,6 @@ int MakeSlayerString( ORIG_ATOM_DATA *orig_inp_data, counts[i] = 0; } - is = NULL; - is0 = pINChISort; - INCHI_IOS_STRING tmpbuf = {0}; for (int cur_c = 0; !*bOverflow && cur_c < num_components; cur_c++) @@ -2273,7 +2276,7 @@ int MakeSlayerString( ORIG_ATOM_DATA *orig_inp_data, // s1 tot_len += MakeEnhStereoString( pAux, - "1", + x_abs, bOutType, orig_inp_data->v3000->lists_steabs, orig_inp_data->v3000->n_steabs, @@ -2283,22 +2286,22 @@ int MakeSlayerString( ORIG_ATOM_DATA *orig_inp_data, // s2 tot_len += MakeEnhStereoString( pAux, - "2", + x_rel, bOutType, orig_inp_data->v3000->lists_sterel, orig_inp_data->v3000->n_sterel, &tmpbuf, - 0, + nCtMode, bOverflow); // s3 tot_len += MakeEnhStereoString( pAux, - "3", + x_rac, bOutType, orig_inp_data->v3000->lists_sterac, orig_inp_data->v3000->n_sterac, &tmpbuf, - 0, + nCtMode, bOverflow); @@ -2314,7 +2317,7 @@ int MakeSlayerString( ORIG_ATOM_DATA *orig_inp_data, if (!found) { for (int i = 0; i < DICT_SIZE; i++) { if (dictionary[i] == NULL) { - dictionary[i] = strdup(tmpbuf.pStr); // remember to free later + dictionary[i] = strdup(tmpbuf.pStr); counts[i] = 1; break; } From 7e2da23920c2c087bc744cb7d2b983dd73b6157d Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Thu, 29 Jan 2026 16:57:01 +0000 Subject: [PATCH 60/69] added m-layer change to 0 if no abs center present --- INCHI-1-SRC/INCHI_BASE/src/strutil.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/INCHI-1-SRC/INCHI_BASE/src/strutil.c b/INCHI-1-SRC/INCHI_BASE/src/strutil.c index 4d20d72e..b5d4a985 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/strutil.c +++ b/INCHI-1-SRC/INCHI_BASE/src/strutil.c @@ -4386,6 +4386,12 @@ int set_EnhancedStereo_t_m_layers( ORIG_ATOM_DATA *orig_inp_data, int ret_rac = invert_parities(inchi, aux, orig_inp_data->v3000->lists_sterac, orig_inp_data->v3000->n_sterac, 0); int ret_rel = invert_parities(inchi, aux, orig_inp_data->v3000->lists_sterel, orig_inp_data->v3000->n_sterel, 0); + if ((orig_inp_data->v3000->n_steabs == 0) && + (orig_inp_data->v3000->n_sterel > 0 || + orig_inp_data->v3000->n_sterac)) { + inchi->Stereo->nCompInv2Abs = 1; + } + return ret; } From 37ad158ebda2e67f63a784b2bf99cb1f3f593ff2 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Fri, 30 Jan 2026 08:16:27 +0000 Subject: [PATCH 61/69] changed m layer based on feedback (no abs) --- INCHI-1-SRC/INCHI_BASE/src/strutil.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/INCHI-1-SRC/INCHI_BASE/src/strutil.c b/INCHI-1-SRC/INCHI_BASE/src/strutil.c index b5d4a985..7c00fefb 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/strutil.c +++ b/INCHI-1-SRC/INCHI_BASE/src/strutil.c @@ -4303,6 +4303,10 @@ int invert_parities(INChI *inchi, // 2 = + // 1 = - + // m - layer + // -1 = m0 + // 1 = m1 + S_CHAR *t_parity = inchi->Stereo->t_parity; if (nof_lists > 0) @@ -4347,7 +4351,7 @@ int invert_parities(INChI *inchi, int min_c_atom_parity = t_parity[min_c_parity_idx]; if ((is_absolute == 1) && (min_c_atom_parity == 1)) { - inchi->Stereo->nCompInv2Abs = 1; + // inchi->Stereo->nCompInv2Abs = 1; } else if (min_c_atom_parity == 2) { for (int j = 0; j < nof_atoms; j++) { @@ -4369,7 +4373,7 @@ int invert_parities(INChI *inchi, } if (is_absolute) { - inchi->Stereo->nCompInv2Abs = -1; + inchi->Stereo->nCompInv2Abs = -1; //m1 } } } @@ -4389,7 +4393,7 @@ int set_EnhancedStereo_t_m_layers( ORIG_ATOM_DATA *orig_inp_data, if ((orig_inp_data->v3000->n_steabs == 0) && (orig_inp_data->v3000->n_sterel > 0 || orig_inp_data->v3000->n_sterac)) { - inchi->Stereo->nCompInv2Abs = 1; + inchi->Stereo->nCompInv2Abs = 1; //m0 } return ret; From e6fb59cb2bd550cba7845a5a022a65062f892dbc Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Fri, 30 Jan 2026 10:09:12 +0000 Subject: [PATCH 62/69] Bugfix for mol v2 files --- INCHI-1-SRC/INCHI_BASE/src/strutil.c | 9 ++++ .../tests/test_unit/test_enhancedStereo.cpp | 46 +++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/INCHI-1-SRC/INCHI_BASE/src/strutil.c b/INCHI-1-SRC/INCHI_BASE/src/strutil.c index 7c00fefb..7d00cb3b 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/strutil.c +++ b/INCHI-1-SRC/INCHI_BASE/src/strutil.c @@ -4307,6 +4307,10 @@ int invert_parities(INChI *inchi, // -1 = m0 // 1 = m1 + if (list_atoms == NULL) { + return 1; + } + S_CHAR *t_parity = inchi->Stereo->t_parity; if (nof_lists > 0) @@ -4386,6 +4390,11 @@ int set_EnhancedStereo_t_m_layers( ORIG_ATOM_DATA *orig_inp_data, { int ret = 0; + if (!orig_inp_data->v3000) + { + return 1; + } + int ret_abs = invert_parities(inchi, aux, orig_inp_data->v3000->lists_steabs, orig_inp_data->v3000->n_steabs, 1); int ret_rac = invert_parities(inchi, aux, orig_inp_data->v3000->lists_sterac, orig_inp_data->v3000->n_sterac, 0); int ret_rel = invert_parities(inchi, aux, orig_inp_data->v3000->lists_sterel, orig_inp_data->v3000->n_sterel, 0); diff --git a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp index 448cee6b..15b2dcc4 100644 --- a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp @@ -5,6 +5,52 @@ extern "C" #include "../../../INCHI-1-SRC/INCHI_BASE/src/inchi_api.h" } +TEST(test_enhancedStereo, test_EnhancedStereochemistry_no_collection_information) +{ + const char *molblock = + "test_mol_2 \n" + " Ketcher 1302610202D 1 1.00000 0.00000 0 \n" + " \n" + " 13 12 0 0 0 0 0 0 0 0999 V2000 \n" + " 2.9420 -4.1000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 \n" + " 3.8080 -3.6000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 \n" + " 4.6740 -4.1000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 \n" + " 5.5401 -3.6000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 \n" + " 6.4061 -4.1000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 \n" + " 7.2721 -3.6000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 \n" + " 8.1381 -4.1000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 \n" + " 6.4061 -5.1000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 \n" + " 5.5401 -2.6000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 \n" + " 5.5401 -5.6000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 \n" + " 5.5401 -6.6000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 \n" + " 6.4061 -2.1000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 \n" + " 6.4061 -1.1000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 \n" + " 1 2 1 0 0 0 \n" + " 2 3 1 0 0 0 \n" + " 3 4 1 0 0 0 \n" + " 4 5 1 0 0 0 \n" + " 5 6 1 0 0 0 \n" + " 6 7 1 0 0 0 \n" + " 5 8 1 0 0 0 \n" + " 4 9 1 0 0 0 \n" + " 8 10 1 0 0 0 \n" + " 10 11 1 0 0 0 \n" + " 9 12 1 0 0 0 \n" + " 12 13 1 0 0 0 \n" + "M END \n"; + + char options[] = "-EnhancedStereochemistry"; + inchi_Output output; + inchi_Output *poutput = &output; + const char expected_inchi[] = "InChI=1S/C13H28/c1-5-9-12(8-4)13(10-6-2)11-7-3/h12-13H,5-11H2,1-4H3"; + + EXPECT_EQ(MakeINCHIFromMolfileText(molblock, options, poutput), 1); + EXPECT_STREQ(poutput->szInChI, expected_inchi); + + FreeINCHI(poutput); +} + + TEST(test_enhancedStereo, test_EnhancedStereochemistry_1) { const char *molblock = From 99628bcf97bb078a279eedb09207ca2fe2afd12f Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Fri, 30 Jan 2026 13:45:52 +0000 Subject: [PATCH 63/69] changed InChI-Prefix to InChI=1B (beta) --- INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c | 4 ++++ .../tests/test_unit/test_enhancedStereo.cpp | 16 ++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c index 99726d8b..b9e5d014 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c @@ -1728,6 +1728,10 @@ int OutputINChI1( CANON_GLOBALS *pCG, { is_beta = 1; } + else if (ip->bEnhancedStereo) + { + is_beta = 1; + } OutputINCHI_VersionAndKind( out_file, strbuf, bINChIOutputOptions, is_beta, pLF, pTAB ); } diff --git a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp index 15b2dcc4..7127c739 100644 --- a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp @@ -5,7 +5,7 @@ extern "C" #include "../../../INCHI-1-SRC/INCHI_BASE/src/inchi_api.h" } -TEST(test_enhancedStereo, test_EnhancedStereochemistry_no_collection_information) +TEST(test_enhancedStereo, test_EnhancedStereochemistry_molfile_v2) { const char *molblock = "test_mol_2 \n" @@ -42,7 +42,7 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_no_collection_information char options[] = "-EnhancedStereochemistry"; inchi_Output output; inchi_Output *poutput = &output; - const char expected_inchi[] = "InChI=1S/C13H28/c1-5-9-12(8-4)13(10-6-2)11-7-3/h12-13H,5-11H2,1-4H3"; + const char expected_inchi[] = "InChI=1B/C13H28/c1-5-9-12(8-4)13(10-6-2)11-7-3/h12-13H,5-11H2,1-4H3"; EXPECT_EQ(MakeINCHIFromMolfileText(molblock, options, poutput), 1); EXPECT_STREQ(poutput->szInChI, expected_inchi); @@ -112,7 +112,7 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_1) char options[] = "-EnhancedStereochemistry"; inchi_Output output; inchi_Output *poutput = &output; - const char expected_inchi[] = "InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(6,8)(4)3(7,9)(10)"; + const char expected_inchi[] = "InChI=1B/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(6,8)(4)3(7,9)(10)"; EXPECT_EQ(MakeINCHIFromMolfileText(molblock, options, poutput), 0); EXPECT_STREQ(poutput->szInChI, expected_inchi); @@ -223,7 +223,7 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_2_mols) char options[] = "-EnhancedStereochemistry"; inchi_Output output; inchi_Output *poutput = &output; - const char expected_inchi[] = "InChI=1S/2C10H14BrCl7/c2*1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h2*3-10H,1-2H3/t2*3-,4-,5+,6-,7-,8-,9+,10-/m00/s2*1(3,5)2(6,8)(4)3(7,9)(10)"; + const char expected_inchi[] = "InChI=1B/2C10H14BrCl7/c2*1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h2*3-10H,1-2H3/t2*3-,4-,5+,6-,7-,8-,9+,10-/m00/s2*1(3,5)2(6,8)(4)3(7,9)(10)"; EXPECT_EQ(MakeINCHIFromMolfileText(molblock, options, poutput), 0); EXPECT_STREQ(poutput->szInChI, expected_inchi); @@ -351,7 +351,7 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_3_mols) char options[] = "-EnhancedStereochemistry"; inchi_Output output; inchi_Output *poutput = &output; - const char expected_inchi[] = "InChI=1S/2C10H14BrCl7.C8H18/c2*1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12;1-6(2)8(5)7(3)4/h2*3-10H,1-2H3;6-8H,1-5H3/t2*3-,4-,5+,6-,7-,8-,9+,10-;/m00./s2*1(3,5)2(6,8)(4)3(7,9)(10);1(6)3(7,8)"; + const char expected_inchi[] = "InChI=1B/2C10H14BrCl7.C8H18/c2*1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12;1-6(2)8(5)7(3)4/h2*3-10H,1-2H3;6-8H,1-5H3/t2*3-,4-,5+,6-,7-,8-,9+,10-;/m00./s2*1(3,5)2(6,8)(4)3(7,9)(10);1(6)3(7,8)"; EXPECT_EQ(MakeINCHIFromMolfileText(molblock, options, poutput), 0); EXPECT_STREQ(poutput->szInChI, expected_inchi); @@ -504,7 +504,7 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_4_mols) char options[] = "-EnhancedStereochemistry"; inchi_Output output; inchi_Output *poutput = &output; - const char expected_inchi[] = "InChI=1S/C12H26.2C10H14BrCl7.C9H20/c1-8(2)11(7)12(9(3)4)10(5)6;2*1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12;1-6-8(4)9(5)7(2)3/h8-12H,1-7H3;2*3-10H,1-2H3;7-9H,6H2,1-5H3/t11-;2*3-,4-,5+,6-,7-,8-,9+,10-;8-,9+/m1001/s1(8,9,10,11);2*1(3,5)2(6,8)(4)3(7,9)(10);1(7)3(8,9)"; + const char expected_inchi[] = "InChI=1B/C12H26.2C10H14BrCl7.C9H20/c1-8(2)11(7)12(9(3)4)10(5)6;2*1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12;1-6-8(4)9(5)7(2)3/h8-12H,1-7H3;2*3-10H,1-2H3;7-9H,6H2,1-5H3/t11-;2*3-,4-,5+,6-,7-,8-,9+,10-;8-,9+/m1001/s1(8,9,10,11);2*1(3,5)2(6,8)(4)3(7,9)(10);1(7)3(8,9)"; EXPECT_EQ(MakeINCHIFromMolfileText(molblock, options, poutput), 0); EXPECT_STREQ(poutput->szInChI, expected_inchi); @@ -611,7 +611,7 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_2_mols_inter_enhstereo_gr char options[] = "-EnhancedStereochemistry"; inchi_Output output; inchi_Output *poutput = &output; - const char expected_inchi[] = "InChI=1S/2C10H14BrCl7/c2*1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h2*3-10H,1-2H3/t2*3-,4-,5+,6-,7-,8-,9+,10-/m00/s2*1(3,5)2(6,8)(4)3(7,9)(10)"; + const char expected_inchi[] = "InChI=1B/2C10H14BrCl7/c2*1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h2*3-10H,1-2H3/t2*3-,4-,5+,6-,7-,8-,9+,10-/m00/s2*1(3,5)2(6,8)(4)3(7,9)(10)"; EXPECT_EQ(MakeINCHIFromMolfileText(molblock, options, poutput), 0); EXPECT_STREQ(poutput->szInChI, expected_inchi); @@ -720,7 +720,7 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_2_different_mols_inter_en char options[] = "-EnhancedStereochemistry"; inchi_Output output; inchi_Output *poutput = &output; - const char expected_inchi[] = "InChI=1S/C11H16BrCl7.C10H14BrCl7/c1-3-5(13)7(15)9(17)11(19)10(18)8(16)6(14)4(2)12;1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h4-11H,3H2,1-2H3;3-10H,1-2H3/t4-,5-,6+,7-,8-,9-,10+,11-;3-,4-,5+,6-,7-,8-,9+,10-/m00/s1(4,6)2(7,9)(5)3(8,10)(11);1(3,5)2(6,8)(4)3(7,9)(10)"; + const char expected_inchi[] = "InChI=1B/C11H16BrCl7.C10H14BrCl7/c1-3-5(13)7(15)9(17)11(19)10(18)8(16)6(14)4(2)12;1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h4-11H,3H2,1-2H3;3-10H,1-2H3/t4-,5-,6+,7-,8-,9-,10+,11-;3-,4-,5+,6-,7-,8-,9+,10-/m00/s1(4,6)2(7,9)(5)3(8,10)(11);1(3,5)2(6,8)(4)3(7,9)(10)"; EXPECT_EQ(MakeINCHIFromMolfileText(molblock, options, poutput), 0); EXPECT_STREQ(poutput->szInChI, expected_inchi); From 2ca5281db198f63903501d03c9c4e64780bf0831 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 2 Feb 2026 13:56:30 +0000 Subject: [PATCH 64/69] added unit tests and doxygen for functions used in enhanced stereochemistry --- INCHI-1-SRC/INCHI_BASE/src/ichimake.h | 5 +- INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c | 4 +- INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c | 106 +- INCHI-1-SRC/INCHI_BASE/src/strutil.c | 167 +- INCHI-1-SRC/INCHI_BASE/src/strutil.h | 33 +- .../fixtures/enh_stereo_test_file_1.sdf | 1016 +++++++++ .../fixtures/enh_stereo_test_file_2.sdf | 1972 +++++++++++++++++ .../tests/test_unit/test_enhancedStereo.cpp | 101 +- .../tests/test_unit/test_ichiprt2.cpp | 201 ++ .../test_unit/test_strutil_enhancedStereo.cpp | 108 +- 10 files changed, 3608 insertions(+), 105 deletions(-) create mode 100644 INCHI-1-TEST/tests/test_unit/fixtures/enh_stereo_test_file_1.sdf create mode 100644 INCHI-1-TEST/tests/test_unit/fixtures/enh_stereo_test_file_2.sdf diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichimake.h b/INCHI-1-SRC/INCHI_BASE/src/ichimake.h index 8bc4faf4..fd35db2a 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichimake.h +++ b/INCHI-1-SRC/INCHI_BASE/src/ichimake.h @@ -209,18 +209,17 @@ const char *EquString( int EquVal ); int nCtMode, int *bOverflow ); int MakeEnhStereoString( INChI_Aux *pAux, + INCHI_IOS_STRING *strbuf, const char* conf_stereo_string, - int bOutType, int **enh_stereo, int nof_stereo_groups, - INCHI_IOS_STRING *strbuf, int nCtMode, int *bOverflow ); int MakeSlayerString( ORIG_ATOM_DATA *orig_inp_data, INCHI_SORT *pINChISort, + INCHI_IOS_STRING *strbuf, int bOutType, int num_components, - INCHI_IOS_STRING *strbuf, int nCtMode, int *bOverflow ); int MakeCRVString( ORIG_INFO *OrigInfo, diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c index b9e5d014..e829c84c 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c @@ -3536,7 +3536,7 @@ int OutputINCHI_StereoLayer( CANON_GLOBALS *pCG, } /** - * @brief Output InChI: stereo layer with sublayers. + * @brief Output InChI: stereo layer with sublayers for enhanced stereochemistry (absolute, relative, racemic). * * @param pCG Pointer to the CANON_GLOBALS structure containing global canonicalization data. * @param out_file Pointer to the INCHI_IOSTREAM output stream where the stereo layer will be written. @@ -3676,9 +3676,9 @@ int OutputINCHI_StereoLayer_EnhancedStereo( io->tot_len += MakeSlayerString( orig_inp_data, io->pINChISort, + strbuf, io->bOutType, io->num_components, - strbuf, io->TAUT_MODE, &io->bOverflow ); diff --git a/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c b/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c index 3fbca441..4d6d620b 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c +++ b/INCHI-1-SRC/INCHI_BASE/src/ichiprt2.c @@ -471,14 +471,26 @@ int MakeMult( int mult, return 0; } -int MakeMult_EnhStereo( int mult, - const char *szTailingDelim, - INCHI_IOS_STRING *buf, - int nCtMode, - int *bOverflow ) +/** + * @brief Adds the number to the string buffer. + * + * @param number Input number to be added + * @param szTailingDelim Pointer to the trailing delimiter string + * @param buf Pointer to the output string buffer + * @param nCtMode Mode flag for string representation + * @param bOverflow Pointer to overflow flag + * @return Returns the number of characters added to the buffer + */ +int MakeNumber_EnhStereo( int number, + const char *szTailingDelim, + INCHI_IOS_STRING *buf, + int nCtMode, + int *bOverflow ) { char szValue[2048]; - int len = 0, len_delim, n; + int len = 0; + int len_delim; + int n; if (*bOverflow) { @@ -486,11 +498,11 @@ int MakeMult_EnhStereo( int mult, } if (nCtMode & CT_MODE_ABC_NUMBERS) { - len += MakeAbcNumber( szValue, ( int )sizeof( szValue ), NULL, mult ); + len += MakeAbcNumber( szValue, ( int )sizeof( szValue ), NULL, number ); } else { - len += MakeDecNumber( szValue, ( int )sizeof( szValue ), NULL, mult ); + len += MakeDecNumber( szValue, ( int )sizeof( szValue ), NULL, number ); } len_delim = (int) strlen( szTailingDelim ); @@ -500,13 +512,6 @@ int MakeMult_EnhStereo( int mult, n = inchi_strbuf_printf( buf, "%s", szValue ); if (-1 == n) *bOverflow |= 1; return n; - /* - len += len_delim; - if ( len < nLen_szLinearCT ) - { - strcpy( szLinearCT, szValue ); - return len; - }*/ } *bOverflow |= 1; @@ -2159,23 +2164,50 @@ int MakeStereoString( AT_NUMB *at1, return nLen; } +/** + * @brief Compares two integers for qsort. + * + * @param a First integer pointer. + * @param b Second integer pointer. + * @return Returns negative, zero, or positive value based on comparison. + */ int compare_ints(const void *a, const void *b) { int arg1 = *(const int *)a; int arg2 = *(const int *)b; return (arg1 > arg2) - (arg1 < arg2); } +/** + * @brief Creates the enhanced stereochemistry string for the s - layer. + * + * @param pAux Pointer to the INCHI_AUX structure. + * @param conf_stereo_string Pointer to the configuration stereochemistry string (abs, rel, rac). + * @param enh_stereo Pointer to list of enhanced stereochemistry groups. + * @param nof_stereo_groups Number of enhanced stereochemistry groups. + * @param strbuf Pointer to the output string buffer. + * @param nCtMode Mode flag for string representation. + * @param bOverflow Pointer to overflow flag. + * @return Returns the length of the created string. + */ int MakeEnhStereoString( INChI_Aux *pAux, + INCHI_IOS_STRING *strbuf, const char* conf_stereo_string, - int bOutType, int **enh_stereo, int nof_stereo_groups, - INCHI_IOS_STRING *strbuf, int nCtMode, int *bOverflow ) { int tot_len = 0; int count_added = 0; + + if (pAux == NULL) { + return 0; + } + + if (enh_stereo == NULL) { + return 0; + } + if (nof_stereo_groups < 1) { return 0; } @@ -2210,7 +2242,7 @@ int MakeEnhStereoString( INChI_Aux *pAux, if (c_atom_numbers[j] == -1) { continue; } - tot_len += MakeMult_EnhStereo( c_atom_numbers[j], "", strbuf, nCtMode, bOverflow ); + tot_len += MakeNumber_EnhStereo( c_atom_numbers[j], "", strbuf, nCtMode, bOverflow ); count_added++; if ((j + 1) < enh_stereo[i][1]) { @@ -2232,11 +2264,23 @@ int MakeEnhStereoString( INChI_Aux *pAux, return tot_len; } +/** + * @brief Creates the string for the s - layer based on the enhanced stereochemistry information. + * + * @param orig_inp_data Pointer to the original atom data. + * @param pINChISort Pointer to the INCHI_SORT structure. + * @param bOutType Output type flag. + * @param num_components Number of components in the molecule. + * @param strbuf Pointer to the output string buffer. + * @param nCtMode Mode flag for string representation. + * @param bOverflow Pointer to overflow flag. + * @return Returns the length of the created string. + */ int MakeSlayerString( ORIG_ATOM_DATA *orig_inp_data, INCHI_SORT *pINChISort, + INCHI_IOS_STRING *strbuf, int bOutType, int num_components, - INCHI_IOS_STRING *strbuf, int nCtMode, int *bOverflow ) { @@ -2248,11 +2292,11 @@ int MakeSlayerString( ORIG_ATOM_DATA *orig_inp_data, const char* x_rel = "2"; const char* x_rac = "3"; - INCHI_SORT *is = NULL; - INCHI_SORT *is0 = pINChISort; + const INCHI_SORT *is = NULL; + const INCHI_SORT *is0 = pINChISort; - INChI *pINChI; - INChI_Aux *pAux; + // INChI *pINChI = NULL; + INChI_Aux *pAux = NULL; int DICT_SIZE = 100; char *dictionary[DICT_SIZE]; // array of string pointers @@ -2276,36 +2320,31 @@ int MakeSlayerString( ORIG_ATOM_DATA *orig_inp_data, // s1 tot_len += MakeEnhStereoString( pAux, + &tmpbuf, x_abs, - bOutType, orig_inp_data->v3000->lists_steabs, orig_inp_data->v3000->n_steabs, - &tmpbuf, nCtMode, bOverflow); // s2 tot_len += MakeEnhStereoString( pAux, + &tmpbuf, x_rel, - bOutType, orig_inp_data->v3000->lists_sterel, orig_inp_data->v3000->n_sterel, - &tmpbuf, nCtMode, bOverflow); // s3 tot_len += MakeEnhStereoString( pAux, + &tmpbuf, x_rac, - bOutType, orig_inp_data->v3000->lists_sterac, orig_inp_data->v3000->n_sterac, - &tmpbuf, nCtMode, bOverflow); - - int found = 0; for (int i = 0; i < DICT_SIZE; i++) { if (dictionary[i] && strcmp(tmpbuf.pStr, dictionary[i]) == 0) { @@ -2326,6 +2365,7 @@ int MakeSlayerString( ORIG_ATOM_DATA *orig_inp_data, inchi_strbuf_close(&tmpbuf); } + // String deduplication based on dictionary and counts int count = 0; for (int i = 0; i < DICT_SIZE; i++) { if (dictionary[i]) { @@ -2333,9 +2373,9 @@ int MakeSlayerString( ORIG_ATOM_DATA *orig_inp_data, tot_len += MakeDelim( ";", strbuf, bOverflow ); } if (counts[i] > 1) { - tot_len += inchi_strbuf_printf(strbuf, "%d*%s", counts[i], dictionary[i]); + tot_len = inchi_strbuf_printf(strbuf, "%d*%s", counts[i], dictionary[i]); } else { - tot_len += inchi_strbuf_printf(strbuf, "%s", dictionary[i]); + tot_len = inchi_strbuf_printf(strbuf, "%s", dictionary[i]); } inchi_free(dictionary[i]); count++; diff --git a/INCHI-1-SRC/INCHI_BASE/src/strutil.c b/INCHI-1-SRC/INCHI_BASE/src/strutil.c index 7d00cb3b..8be6ccdd 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/strutil.c +++ b/INCHI-1-SRC/INCHI_BASE/src/strutil.c @@ -4269,9 +4269,24 @@ int cmp_components( const void *a1, const void *a2 ) return ret; } -int get_canonical_atom_number( INChI_Aux *aux, +/** + * @brief Get the canonical atom number from original atom number + * + * @param aux Pointer to INChI auxiliary data + * @param orig_atom_num Original atom number + * @return Returns the canonical atom number, or -1 if not found + */ +int get_canonical_atom_number( const INChI_Aux *aux, int orig_atom_num) { + if (aux == NULL) { + return -1; + } + + if (aux->nOrigAtNosInCanonOrd == NULL) { + return -1; + } + for (int canon_num = 1; canon_num <= aux->nNumberOfAtoms; canon_num++) { if (aux->nOrigAtNosInCanonOrd[canon_num - 1] == orig_atom_num) { return canon_num; @@ -4280,10 +4295,26 @@ int get_canonical_atom_number( INChI_Aux *aux, return -1; } +/** + * @brief Get the parity idx from canonical atom number object + * + * @param canon_atom_num Canonical atom number + * @param nNumber Pointer to array of canonical atom numbers + * @param nof_atoms Number of atoms + * @return Returns the parity index, or -1 if not found + */ int get_parity_idx_from_canonical_atom_number( int canon_atom_num, - AT_NUMB *nNumber, + const AT_NUMB *nNumber, int nof_atoms) { + if (nNumber == NULL) { + return -1; + } + + if (nof_atoms <= 0) { + return -1; + } + for (int i = 0; i < nof_atoms; i++) { if (nNumber[i] == canon_atom_num) { return i; @@ -4292,14 +4323,25 @@ int get_parity_idx_from_canonical_atom_number( int canon_atom_num, return -1; } -int invert_parities(INChI *inchi, - INChI_Aux *aux, +/** + * @brief Invert the parities for enhanced stereochemistry t- and m-layers + * + * @param inchi Pointer to INChI structure + * @param aux Pointer to INChI auxiliary data + * @param list_atoms Pointer to list of atom lists for abs, rel or rac information + * @param nof_lists Number of lists + * @param is_absolute Flag indicating if processing absolute stereochemistry + * @return Returns 0 on success, 1 if list_atoms is NULL + */ + +int invert_parities(const INChI *inchi, + const INChI_Aux *aux, int **list_atoms, int nof_lists, int is_absolute) { - // parities + // t - layer: parities // 2 = + // 1 = - @@ -4311,79 +4353,82 @@ int invert_parities(INChI *inchi, return 1; } - S_CHAR *t_parity = inchi->Stereo->t_parity; + if (inchi->Stereo == NULL || + inchi->Stereo->t_parity == NULL) { + return 1; + } - if (nof_lists > 0) + if (nof_lists == 0) { - for (int i = 0; i < nof_lists; i++) { - int nof_atoms = list_atoms[i][1]; + return 1; + } - AT_NUMB min_c_atom_num = (AT_NUMB)9999999; - for (int j = 0; j < nof_atoms; j++) { - int orig_atom_num = list_atoms[i][2 + j]; - AT_NUMB canon_atom_num = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num); - if (canon_atom_num < min_c_atom_num) { - min_c_atom_num = canon_atom_num; - } - } - if (min_c_atom_num == (AT_NUMB)9999999) { - // return -1; - // printf("ERROR %d: cannot find min canonical atom num\n", __LINE__); - continue; - } - int min_c_parity_idx = get_parity_idx_from_canonical_atom_number(min_c_atom_num, - inchi->Stereo->nNumber, - inchi->Stereo->nNumberOfStereoCenters); + S_CHAR *t_parity = inchi->Stereo->t_parity; - if (min_c_parity_idx == -1) { - continue; - // // return -1; - // printf("ERROR %d: cannot find parity idx for atom %d %d\n", __LINE__, min_c_atom_num, min_c_parity_idx); - // for (int j = 0; j < nof_atoms; j++) { - // int orig_atom_num = list_atoms[i][2 + j]; - // AT_NUMB canon_atom_num = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num); - // int parity_idx = get_parity_idx_from_canonical_atom_number(canon_atom_num, - // inchi->Stereo->nNumber, - // inchi->Stereo->nNumberOfStereoCenters); - // printf(" atom %d -> canon %d -> parity idx %d -> parity %d\n", - // orig_atom_num, - // canon_atom_num, - // parity_idx, - // (parity_idx != -1) ? t_parity[parity_idx] : -1); - // } + for (int i = 0; i < nof_lists; i++) { + int nof_atoms = list_atoms[i][1]; + + AT_NUMB min_c_atom_num = (AT_NUMB)9999999; + for (int j = 0; j < nof_atoms; j++) { + int orig_atom_num = list_atoms[i][2 + j]; + AT_NUMB canon_atom_num = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num); + if (canon_atom_num < min_c_atom_num) { + min_c_atom_num = canon_atom_num; } - int min_c_atom_parity = t_parity[min_c_parity_idx]; + } + if (min_c_atom_num == (AT_NUMB)9999999) { + // return -1; + // printf("ERROR %d: cannot find min canonical atom num\n", __LINE__); + continue; + } + int min_c_parity_idx = get_parity_idx_from_canonical_atom_number(min_c_atom_num, + inchi->Stereo->nNumber, + inchi->Stereo->nNumberOfStereoCenters); - if ((is_absolute == 1) && (min_c_atom_parity == 1)) { - // inchi->Stereo->nCompInv2Abs = 1; - } else if (min_c_atom_parity == 2) { + if (min_c_parity_idx == -1) { + continue; + } + int min_c_atom_parity = t_parity[min_c_parity_idx]; - for (int j = 0; j < nof_atoms; j++) { - int orig_atom_num = list_atoms[i][2 + j]; - AT_NUMB canon_atom_num = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num); - int parity_idx = get_parity_idx_from_canonical_atom_number(canon_atom_num, - inchi->Stereo->nNumber, - inchi->Stereo->nNumberOfStereoCenters); + if ((is_absolute == 1) && (min_c_atom_parity == 1)) { + // inchi->Stereo->nCompInv2Abs = 1; + } else if (min_c_atom_parity == 2) { - if (parity_idx == -1) { - continue; - } + for (int j = 0; j < nof_atoms; j++) { + int orig_atom_num = list_atoms[i][2 + j]; + AT_NUMB canon_atom_num = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num); + int parity_idx = get_parity_idx_from_canonical_atom_number(canon_atom_num, + inchi->Stereo->nNumber, + inchi->Stereo->nNumberOfStereoCenters); - if (t_parity[parity_idx] == 2) { - t_parity[parity_idx] = 1; - } else if(t_parity[parity_idx] == 1) { - t_parity[parity_idx] = 2; - } + if (parity_idx == -1) { + continue; } - if (is_absolute) { - inchi->Stereo->nCompInv2Abs = -1; //m1 + if (t_parity[parity_idx] == 2) { + t_parity[parity_idx] = 1; + } else if(t_parity[parity_idx] == 1) { + t_parity[parity_idx] = 2; } } + + if (is_absolute) { + inchi->Stereo->nCompInv2Abs = -1; //m1 + } } } + return 0; } +/** + * @brief Set the enhanced stereochemistry information for t- and m-layers + * + * @param orig_inp_data Pointer to original input atom data + * @param inchi Pointer to INChI structure + * @param aux Pointer to INChI auxiliary data + * @return Retruns 1 if not V3000, otherwise 0 + */ + int set_EnhancedStereo_t_m_layers( ORIG_ATOM_DATA *orig_inp_data, INChI *inchi, INChI_Aux *aux) diff --git a/INCHI-1-SRC/INCHI_BASE/src/strutil.h b/INCHI-1-SRC/INCHI_BASE/src/strutil.h index b57aed17..fc6ff812 100644 --- a/INCHI-1-SRC/INCHI_BASE/src/strutil.h +++ b/INCHI-1-SRC/INCHI_BASE/src/strutil.h @@ -76,8 +76,37 @@ extern "C" * @param orig_atom_num Original atom number * @return Returns canonical atom number if found, -1 if not */ - int get_canonical_atom_number(INChI_Aux *aux, - int orig_atom_num); + int get_canonical_atom_number( const INChI_Aux *aux, + int orig_atom_num); + + /** + * @brief Get the parity index from canonical atom number + * + * @param canon_atom_num Canonical atom number + * @param nNumber Pointer to atom number array + * @param nof_atoms Number of atoms + * @return Returns parity index if found, -1 if not + */ + int get_parity_idx_from_canonical_atom_number( int canon_atom_num, + const AT_NUMB *nNumber, + int nof_atoms); + + /** + * @brief Invert the parities for enhanced stereochemistry t- and m-layers + * + * @param inchi Pointer to INChI structure + * @param aux Pointer to INChI auxiliary data + * @param list_atoms Pointer to list of atom lists for abs, rel or rac information + * @param nof_lists Number of lists + * @param is_absolute Flag indicating if processing absolute stereochemistry + * @return Returns 0 on success, 1 if list_atoms is NULL + */ + + int invert_parities(const INChI *inchi, + const INChI_Aux *aux, + int **list_atoms, + int nof_lists, + int is_absolute); /** * @brief Extract one (connected) component diff --git a/INCHI-1-TEST/tests/test_unit/fixtures/enh_stereo_test_file_1.sdf b/INCHI-1-TEST/tests/test_unit/fixtures/enh_stereo_test_file_1.sdf new file mode 100644 index 00000000..1bffa89f --- /dev/null +++ b/INCHI-1-TEST/tests/test_unit/fixtures/enh_stereo_test_file_1.sdf @@ -0,0 +1,1016 @@ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 7 6 0 0 1 +M V30 BEGIN ATOM +M V30 1 C -1.429260 -0.206189 0.000000 0 +M V30 2 C -0.714790 0.206311 0.000000 0 +M V30 3 O -0.714790 1.031557 0.000000 0 +M V30 4 C -0.000107 -0.206312 0.000000 0 +M V30 5 C 0.714577 0.206311 0.000000 0 +M V30 6 C 1.429260 -0.206312 0.000000 0 +M V30 7 N -0.000107 -1.031557 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 2 3 CFG=1 +M V30 3 1 2 4 +M V30 4 1 4 5 +M V30 5 1 5 6 +M V30 6 1 4 7 CFG=1 +M V30 END BOND +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 5 4 0 0 0 +M V30 BEGIN ATOM +M V30 1 C 1.071918 -0.206311 0.000000 0 +M V30 2 C 0.357235 -0.618934 0.000000 0 +M V30 3 C -0.357448 -0.206311 0.000000 0 +M V30 4 O -0.357448 0.618934 0.000000 0 +M V30 5 C -1.071918 -0.618811 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 +M V30 2 1 3 2 +M V30 3 1 3 4 CFG=1 +M V30 4 1 5 3 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEREL1 ATOMS=(1 3) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 7 6 0 0 0 +M V30 BEGIN ATOM +M V30 1 C 1.429260 -0.206311 0.000000 0 +M V30 2 C 0.714576 0.206311 0.000000 0 +M V30 3 C -0.000107 -0.206311 0.000000 0 +M V30 4 N -0.000107 -1.031556 0.000000 0 +M V30 5 C -0.714790 0.206311 0.000000 0 +M V30 6 O -0.714790 1.031556 0.000000 0 +M V30 7 C -1.429260 -0.206189 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 +M V30 2 1 3 2 +M V30 3 1 3 4 CFG=1 +M V30 4 1 5 3 +M V30 5 1 5 6 CFG=1 +M V30 6 1 7 5 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEREL1 ATOMS=(2 3 5) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 5 4 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 1.071919 -0.206311 0.000000 0 +M V30 2 C 0.357235 -0.618934 0.000000 0 +M V30 3 C -0.357448 -0.206311 0.000000 0 +M V30 4 O -0.357448 0.618934 0.000000 0 +M V30 5 C -1.071919 -0.618811 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 +M V30 2 1 3 2 +M V30 3 1 3 4 CFG=1 +M V30 4 1 5 3 +M V30 END BOND +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 7 6 0 0 0 +M V30 BEGIN ATOM +M V30 1 C 1.429261 -0.206311 0.000000 0 +M V30 2 C 0.714577 0.206311 0.000000 0 +M V30 3 C -0.000106 -0.206311 0.000000 0 +M V30 4 N -0.000106 -1.031556 0.000000 0 +M V30 5 C -0.714790 0.206311 0.000000 0 +M V30 6 O -0.714790 1.031556 0.000000 0 +M V30 7 C -1.429261 -0.206189 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 +M V30 2 1 3 2 +M V30 3 1 3 4 CFG=1 +M V30 4 1 5 3 +M V30 5 1 5 6 CFG=1 +M V30 6 1 7 5 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEREL2 ATOMS=(1 3) +M V30 MDLV30/STEREL1 ATOMS=(1 5) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 7 6 0 0 0 +M V30 BEGIN ATOM +M V30 1 C 1.429261 -0.206311 0.000000 0 +M V30 2 C 0.714578 0.206311 0.000000 0 +M V30 3 C -0.000106 -0.206311 0.000000 0 +M V30 4 N -0.000106 -1.031556 0.000000 0 +M V30 5 C -0.714790 0.206311 0.000000 0 +M V30 6 O -0.714790 1.031556 0.000000 0 +M V30 7 C -1.429261 -0.206189 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 +M V30 2 1 3 2 +M V30 3 1 3 4 +M V30 4 1 5 3 +M V30 5 1 5 6 +M V30 6 1 7 5 +M V30 END BOND +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 7 6 0 0 0 +M V30 BEGIN ATOM +M V30 1 N -0.000106 -1.031556 0.000000 0 +M V30 2 C -0.000106 -0.206311 0.000000 0 +M V30 3 C 0.714578 0.206311 0.000000 0 +M V30 4 C 1.429261 -0.206311 0.000000 0 +M V30 5 C -0.714789 0.206311 0.000000 0 +M V30 6 O -0.714789 1.031556 0.000000 0 +M V30 7 C -1.429261 -0.206189 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 CFG=1 +M V30 2 1 2 3 +M V30 3 1 3 4 +M V30 4 1 5 2 +M V30 5 1 5 6 CFG=1 +M V30 6 1 7 5 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC1 ATOMS=(2 2 5) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 5 4 0 0 0 +M V30 BEGIN ATOM +M V30 1 C 1.071919 -0.206311 0.000000 0 +M V30 2 C 0.357236 -0.618934 0.000000 0 +M V30 3 C -0.357448 -0.206311 0.000000 0 +M V30 4 O -0.357448 0.618934 0.000000 0 +M V30 5 C -1.071919 -0.618811 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 +M V30 2 1 3 2 +M V30 3 1 3 4 CFG=1 +M V30 4 1 5 3 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC1 ATOMS=(1 3) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 5 4 0 0 0 +M V30 BEGIN ATOM +M V30 1 C 1.071919 -0.206311 0.000000 0 +M V30 2 C 0.357236 -0.618934 0.000000 0 +M V30 3 C -0.357448 -0.206311 0.000000 0 +M V30 4 O -0.357448 0.618934 0.000000 0 +M V30 5 C -1.071919 -0.618811 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 +M V30 2 1 3 2 +M V30 3 1 3 4 +M V30 4 1 5 3 +M V30 END BOND +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 7 6 0 0 0 +M V30 BEGIN ATOM +M V30 1 N -0.000106 -1.031556 0.000000 0 +M V30 2 C -0.000106 -0.206311 0.000000 0 +M V30 3 C 0.714578 0.206311 0.000000 0 +M V30 4 C 1.429261 -0.206311 0.000000 0 +M V30 5 C -0.714789 0.206311 0.000000 0 +M V30 6 O -0.714789 1.031556 0.000000 0 +M V30 7 C -1.429261 -0.206189 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 CFG=1 +M V30 2 1 2 3 +M V30 3 1 3 4 +M V30 4 1 5 2 +M V30 5 1 5 6 CFG=1 +M V30 6 1 7 5 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC2 ATOMS=(1 2) +M V30 MDLV30/STERAC1 ATOMS=(1 5) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 9 9 0 0 0 +M V30 BEGIN ATOM +M V30 1 C -0.412473 1.071585 0.000000 0 +M V30 2 C -0.824982 0.357119 0.000000 0 +M V30 3 C -0.412509 -0.357346 0.000000 0 +M V30 4 C 0.412473 -0.357346 0.000000 0 +M V30 5 C 0.824982 0.357119 0.000000 0 +M V30 6 C 0.412509 1.071585 0.000000 0 +M V30 7 O 1.649713 0.357119 0.000000 0 +M V30 8 O 0.824839 -1.071585 0.000000 0 +M V30 9 O -1.649713 0.357119 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 2 3 +M V30 3 1 3 4 +M V30 4 1 4 5 +M V30 5 1 5 6 +M V30 6 1 1 6 +M V30 7 1 5 7 CFG=1 +M V30 8 1 4 8 CFG=1 +M V30 9 1 2 9 CFG=1 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEABS ATOMS=(2 2 5) +M V30 MDLV30/STEREL1 ATOMS=(1 4) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 9 9 0 0 1 +M V30 BEGIN ATOM +M V30 1 O 0.824838 -1.071585 0.000000 0 +M V30 2 C 0.412472 -0.357346 0.000000 0 +M V30 3 C -0.412509 -0.357346 0.000000 0 +M V30 4 C -0.824982 0.357119 0.000000 0 +M V30 5 O -1.649714 0.357119 0.000000 0 +M V30 6 C -0.412473 1.071585 0.000000 0 +M V30 7 C 0.412509 1.071585 0.000000 0 +M V30 8 C 0.824982 0.357119 0.000000 0 +M V30 9 O 1.649714 0.357119 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 +M V30 2 1 3 2 +M V30 3 1 4 3 +M V30 4 1 4 5 CFG=1 +M V30 5 1 6 4 +M V30 6 1 6 7 +M V30 7 1 8 7 +M V30 8 1 8 9 CFG=1 +M V30 9 1 2 8 +M V30 END BOND +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 9 9 0 0 0 +M V30 BEGIN ATOM +M V30 1 O 0.824838 -1.071585 0.000000 0 +M V30 2 C 0.412472 -0.357346 0.000000 0 +M V30 3 C -0.412509 -0.357346 0.000000 0 +M V30 4 C -0.824982 0.357119 0.000000 0 +M V30 5 O -1.649714 0.357119 0.000000 0 +M V30 6 C -0.412473 1.071585 0.000000 0 +M V30 7 C 0.412509 1.071585 0.000000 0 +M V30 8 C 0.824982 0.357119 0.000000 0 +M V30 9 O 1.649714 0.357119 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 CFG=1 +M V30 2 1 3 2 +M V30 3 1 4 3 +M V30 4 1 4 5 CFG=1 +M V30 5 1 6 4 +M V30 6 1 6 7 +M V30 7 1 8 7 +M V30 8 1 8 9 CFG=1 +M V30 9 1 2 8 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEREL1 ATOMS=(2 2 8) +M V30 MDLV30/STEABS ATOMS=(1 4) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 9 9 0 0 1 +M V30 BEGIN ATOM +M V30 1 O 0.824838 -1.071585 0.000000 0 +M V30 2 C 0.412473 -0.357346 0.000000 0 +M V30 3 C -0.412508 -0.357346 0.000000 0 +M V30 4 C -0.824981 0.357119 0.000000 0 +M V30 5 O -1.649713 0.357119 0.000000 0 +M V30 6 C -0.412472 1.071585 0.000000 0 +M V30 7 C 0.412510 1.071585 0.000000 0 +M V30 8 C 0.824983 0.357119 0.000000 0 +M V30 9 O 1.649713 0.357119 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 +M V30 2 1 3 2 +M V30 3 1 4 3 +M V30 4 1 4 5 CFG=1 +M V30 5 1 6 4 +M V30 6 1 6 7 +M V30 7 1 8 7 +M V30 8 1 8 9 +M V30 9 1 2 8 +M V30 END BOND +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 9 9 0 0 0 +M V30 BEGIN ATOM +M V30 1 O 0.824839 -1.071585 0.000000 0 +M V30 2 C 0.412473 -0.357346 0.000000 0 +M V30 3 C -0.412508 -0.357346 0.000000 0 +M V30 4 C -0.824981 0.357119 0.000000 0 +M V30 5 O -1.649713 0.357119 0.000000 0 +M V30 6 C -0.412472 1.071585 0.000000 0 +M V30 7 C 0.412510 1.071585 0.000000 0 +M V30 8 C 0.824982 0.357119 0.000000 0 +M V30 9 O 1.649713 0.357119 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 CFG=1 +M V30 2 1 3 2 +M V30 3 1 4 3 +M V30 4 1 4 5 CFG=1 +M V30 5 1 6 4 +M V30 6 1 6 7 +M V30 7 1 8 7 +M V30 8 1 8 9 CFG=3 +M V30 9 1 2 8 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEREL1 ATOMS=(2 2 8) +M V30 MDLV30/STEABS ATOMS=(1 4) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 9 8 0 0 0 +M V30 BEGIN ATOM +M V30 1 C 1.071919 -0.206312 0.000000 0 +M V30 2 C 0.357236 0.206310 0.000000 0 +M V30 3 C -0.357448 -0.206312 0.000000 0 +M V30 4 N -0.357448 -1.031557 0.000000 0 +M V30 5 C -1.072131 0.206310 0.000000 0 +M V30 6 O -1.072131 1.031557 0.000000 0 +M V30 7 C -1.786602 -0.206188 0.000000 0 +M V30 8 C 0.357236 1.031557 0.000000 0 +M V30 9 C 1.786602 0.206310 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 +M V30 2 1 3 2 +M V30 3 1 3 4 CFG=1 +M V30 4 1 5 3 +M V30 5 1 5 6 CFG=1 +M V30 6 1 7 5 +M V30 7 1 2 8 CFG=1 +M V30 8 1 1 9 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEREL1 ATOMS=(2 2 3) +M V30 MDLV30/STEABS ATOMS=(1 5) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 9 8 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 1.786602 0.206312 0.000000 0 +M V30 2 C 1.071918 -0.206312 0.000000 0 +M V30 3 C 0.357235 0.206312 0.000000 0 +M V30 4 C 0.357235 1.031557 0.000000 0 +M V30 5 C -0.357448 -0.206312 0.000000 0 +M V30 6 N -0.357448 -1.031557 0.000000 0 +M V30 7 C -1.072132 0.206312 0.000000 0 +M V30 8 O -1.072132 1.031557 0.000000 0 +M V30 9 C -1.786602 -0.206188 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 +M V30 2 1 3 2 +M V30 3 1 3 4 +M V30 4 1 5 3 +M V30 5 1 5 6 +M V30 6 1 7 5 +M V30 7 1 7 8 CFG=1 +M V30 8 1 9 7 +M V30 END BOND +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 9 8 0 0 0 +M V30 BEGIN ATOM +M V30 1 C 1.786602 0.206312 0.000000 0 +M V30 2 C 1.071919 -0.206312 0.000000 0 +M V30 3 C 0.357236 0.206312 0.000000 0 +M V30 4 C 0.357236 1.031557 0.000000 0 +M V30 5 C -0.357448 -0.206312 0.000000 0 +M V30 6 N -0.357448 -1.031557 0.000000 0 +M V30 7 C -1.072131 0.206312 0.000000 0 +M V30 8 O -1.072131 1.031557 0.000000 0 +M V30 9 C -1.786602 -0.206188 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 +M V30 2 1 3 2 +M V30 3 1 3 4 CFG=3 +M V30 4 1 5 3 +M V30 5 1 5 6 CFG=1 +M V30 6 1 7 5 +M V30 7 1 7 8 CFG=1 +M V30 8 1 9 7 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEREL1 ATOMS=(2 3 5) +M V30 MDLV30/STEABS ATOMS=(1 7) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 9 9 0 0 0 +M V30 BEGIN ATOM +M V30 1 O 0.824839 -1.071585 0.000000 0 +M V30 2 C 0.412473 -0.357346 0.000000 0 +M V30 3 C -0.412508 -0.357346 0.000000 0 +M V30 4 C -0.824981 0.357119 0.000000 0 +M V30 5 O -1.649713 0.357119 0.000000 0 +M V30 6 C -0.412472 1.071585 0.000000 0 +M V30 7 C 0.412510 1.071585 0.000000 0 +M V30 8 C 0.824982 0.357119 0.000000 0 +M V30 9 O 1.649713 0.357119 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 CFG=1 +M V30 2 1 3 2 +M V30 3 1 4 3 +M V30 4 1 4 5 CFG=1 +M V30 5 1 6 4 +M V30 6 1 6 7 +M V30 7 1 8 7 +M V30 8 1 8 9 CFG=1 +M V30 9 1 2 8 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEREL1 ATOMS=(1 2) +M V30 MDLV30/STEABS ATOMS=(1 4) +M V30 MDLV30/STEREL2 ATOMS=(1 8) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 7 6 0 0 0 +M V30 BEGIN ATOM +M V30 1 C -1.429261 -0.206189 0.000000 0 +M V30 2 C -0.714790 0.206311 0.000000 0 +M V30 3 C -0.000107 -0.206311 0.000000 0 +M V30 4 N -0.000107 -1.031556 0.000000 0 +M V30 5 C 0.714577 0.206311 0.000000 0 +M V30 6 C 1.429261 -0.206311 0.000000 0 +M V30 7 O -0.714790 1.031556 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 2 3 +M V30 3 1 3 4 CFG=1 +M V30 4 1 3 5 +M V30 5 1 5 6 +M V30 6 1 2 7 CFG=1 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEABS ATOMS=(1 2) +M V30 MDLV30/STERAC1 ATOMS=(1 3) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 7 6 0 0 0 +M V30 BEGIN ATOM +M V30 1 C 1.429260 -0.206311 0.000000 0 +M V30 2 C 0.714577 0.206311 0.000000 0 +M V30 3 C -0.000107 -0.206311 0.000000 0 +M V30 4 N -0.000107 -1.031556 0.000000 0 +M V30 5 C -0.714790 0.206311 0.000000 0 +M V30 6 O -0.714790 1.031556 0.000000 0 +M V30 7 C -1.429260 -0.206189 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 +M V30 2 1 3 2 +M V30 3 1 3 4 +M V30 4 1 5 3 +M V30 5 1 5 6 CFG=1 +M V30 6 1 7 5 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC1 ATOMS=(1 5) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 9 9 0 0 0 +M V30 BEGIN ATOM +M V30 1 O 0.824838 -1.071585 0.000000 0 +M V30 2 C 0.412472 -0.357346 0.000000 0 +M V30 3 C -0.412509 -0.357346 0.000000 0 +M V30 4 C -0.824982 0.357119 0.000000 0 +M V30 5 O -1.649714 0.357119 0.000000 0 +M V30 6 C -0.412473 1.071585 0.000000 0 +M V30 7 C 0.412509 1.071585 0.000000 0 +M V30 8 C 0.824982 0.357119 0.000000 0 +M V30 9 O 1.649714 0.357119 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 CFG=1 +M V30 2 1 3 2 +M V30 3 1 4 3 +M V30 4 1 4 5 CFG=1 +M V30 5 1 6 4 +M V30 6 1 6 7 +M V30 7 1 8 7 +M V30 8 1 8 9 CFG=3 +M V30 9 1 2 8 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC1 ATOMS=(2 2 8) +M V30 MDLV30/STEABS ATOMS=(1 4) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 9 9 0 0 0 +M V30 BEGIN ATOM +M V30 1 O 0.824839 -1.071585 0.000000 0 +M V30 2 C 0.412473 -0.357346 0.000000 0 +M V30 3 C -0.412509 -0.357346 0.000000 0 +M V30 4 C -0.824982 0.357119 0.000000 0 +M V30 5 O -1.649713 0.357119 0.000000 0 +M V30 6 C -0.412473 1.071585 0.000000 0 +M V30 7 C 0.412509 1.071585 0.000000 0 +M V30 8 C 0.824982 0.357119 0.000000 0 +M V30 9 O 1.649713 0.357119 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 CFG=1 +M V30 2 1 3 2 +M V30 3 1 4 3 +M V30 4 1 4 5 CFG=1 +M V30 5 1 6 4 +M V30 6 1 6 7 +M V30 7 1 8 7 +M V30 8 1 8 9 CFG=1 +M V30 9 1 2 8 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC1 ATOMS=(2 2 8) +M V30 MDLV30/STEABS ATOMS=(1 4) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 9 9 0 0 0 +M V30 BEGIN ATOM +M V30 1 O 0.824839 -1.071585 0.000000 0 +M V30 2 C 0.412473 -0.357346 0.000000 0 +M V30 3 C -0.412508 -0.357346 0.000000 0 +M V30 4 C -0.824981 0.357119 0.000000 0 +M V30 5 O -1.649713 0.357119 0.000000 0 +M V30 6 C -0.412472 1.071585 0.000000 0 +M V30 7 C 0.412510 1.071585 0.000000 0 +M V30 8 C 0.824982 0.357119 0.000000 0 +M V30 9 O 1.649713 0.357119 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 +M V30 2 1 3 2 +M V30 3 1 4 3 +M V30 4 1 4 5 CFG=1 +M V30 5 1 6 4 +M V30 6 1 6 7 +M V30 7 1 8 7 +M V30 8 1 8 9 +M V30 9 1 2 8 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC1 ATOMS=(1 4) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 9 8 0 0 0 +M V30 BEGIN ATOM +M V30 1 C 1.786602 0.206312 0.000000 0 +M V30 2 C 1.071918 -0.206310 0.000000 0 +M V30 3 C 0.357235 0.206312 0.000000 0 +M V30 4 C 0.357235 1.031557 0.000000 0 +M V30 5 C -0.357448 -0.206310 0.000000 0 +M V30 6 N -0.357448 -1.031557 0.000000 0 +M V30 7 C -1.072132 0.206312 0.000000 0 +M V30 8 O -1.072132 1.031557 0.000000 0 +M V30 9 C -1.786602 -0.206188 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 +M V30 2 1 3 2 +M V30 3 1 3 4 +M V30 4 1 5 3 +M V30 5 1 5 6 +M V30 6 1 7 5 +M V30 7 1 7 8 CFG=1 +M V30 8 1 9 7 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC1 ATOMS=(1 7) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 9 8 0 0 0 +M V30 BEGIN ATOM +M V30 1 C 1.786602 0.206312 0.000000 0 +M V30 2 C 1.071918 -0.206310 0.000000 0 +M V30 3 C 0.357235 0.206312 0.000000 0 +M V30 4 C 0.357235 1.031557 0.000000 0 +M V30 5 C -0.357448 -0.206310 0.000000 0 +M V30 6 N -0.357448 -1.031557 0.000000 0 +M V30 7 C -1.072132 0.206312 0.000000 0 +M V30 8 O -1.072132 1.031557 0.000000 0 +M V30 9 C -1.786602 -0.206188 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 +M V30 2 1 3 2 +M V30 3 1 3 4 CFG=3 +M V30 4 1 5 3 +M V30 5 1 5 6 CFG=1 +M V30 6 1 7 5 +M V30 7 1 7 8 CFG=1 +M V30 8 1 9 7 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC1 ATOMS=(2 3 5) +M V30 MDLV30/STEABS ATOMS=(1 7) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 9 8 0 0 0 +M V30 BEGIN ATOM +M V30 1 C 1.786602 0.206311 0.000000 0 +M V30 2 C 1.071919 -0.206312 0.000000 0 +M V30 3 C 0.357236 0.206311 0.000000 0 +M V30 4 C 0.357236 1.031557 0.000000 0 +M V30 5 C -0.357448 -0.206312 0.000000 0 +M V30 6 N -0.357448 -1.031557 0.000000 0 +M V30 7 C -1.072132 0.206311 0.000000 0 +M V30 8 O -1.072132 1.031557 0.000000 0 +M V30 9 C -1.786602 -0.206188 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 +M V30 2 1 3 2 +M V30 3 1 3 4 CFG=1 +M V30 4 1 5 3 +M V30 5 1 5 6 CFG=1 +M V30 6 1 7 5 +M V30 7 1 7 8 CFG=1 +M V30 8 1 9 7 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC1 ATOMS=(2 3 5) +M V30 MDLV30/STEABS ATOMS=(1 7) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 9 9 0 0 0 +M V30 BEGIN ATOM +M V30 1 O 0.824839 -1.071585 0.000000 0 +M V30 2 C 0.412473 -0.357346 0.000000 0 +M V30 3 C -0.412509 -0.357346 0.000000 0 +M V30 4 C -0.824981 0.357119 0.000000 0 +M V30 5 O -1.649713 0.357119 0.000000 0 +M V30 6 C -0.412472 1.071585 0.000000 0 +M V30 7 C 0.412510 1.071585 0.000000 0 +M V30 8 C 0.824982 0.357119 0.000000 0 +M V30 9 O 1.649713 0.357119 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 CFG=1 +M V30 2 1 3 2 +M V30 3 1 4 3 +M V30 4 1 4 5 CFG=1 +M V30 5 1 6 4 +M V30 6 1 6 7 +M V30 7 1 8 7 +M V30 8 1 8 9 CFG=1 +M V30 9 1 2 8 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC1 ATOMS=(1 2) +M V30 MDLV30/STEABS ATOMS=(1 4) +M V30 MDLV30/STERAC2 ATOMS=(1 8) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 9 9 0 0 0 +M V30 BEGIN ATOM +M V30 1 O 0.824839 -1.071585 0.000000 0 +M V30 2 C 0.412473 -0.357346 0.000000 0 +M V30 3 C -0.412508 -0.357346 0.000000 0 +M V30 4 C -0.824981 0.357119 0.000000 0 +M V30 5 O -1.649713 0.357119 0.000000 0 +M V30 6 C -0.412472 1.071585 0.000000 0 +M V30 7 C 0.412510 1.071585 0.000000 0 +M V30 8 C 0.824982 0.357119 0.000000 0 +M V30 9 O 1.649713 0.357119 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 CFG=1 +M V30 2 1 3 2 +M V30 3 1 4 3 +M V30 4 1 4 5 CFG=1 +M V30 5 1 6 4 +M V30 6 1 6 7 +M V30 7 1 8 7 +M V30 8 1 8 9 CFG=1 +M V30 9 1 2 8 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC1 ATOMS=(1 2) +M V30 MDLV30/STEABS ATOMS=(1 4) +M V30 MDLV30/STEREL1 ATOMS=(1 8) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 7 6 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 1.429261 -0.206312 0.000000 0 +M V30 2 C 0.714577 0.206310 0.000000 0 +M V30 3 C -0.000106 -0.206312 0.000000 0 +M V30 4 N -0.000106 -1.031557 0.000000 0 +M V30 5 C -0.714790 0.206310 0.000000 0 +M V30 6 O -0.714790 1.031557 0.000000 0 +M V30 7 C -1.429261 -0.206188 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 +M V30 2 1 3 2 +M V30 3 1 3 4 +M V30 4 1 5 3 +M V30 5 1 5 6 CFG=1 +M V30 6 1 7 5 +M V30 END BOND +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 7 6 0 0 0 +M V30 BEGIN ATOM +M V30 1 N -0.000106 -1.031556 0.000000 0 +M V30 2 C -0.000106 -0.206312 0.000000 0 +M V30 3 C 0.714577 0.206311 0.000000 0 +M V30 4 C 1.429261 -0.206312 0.000000 0 +M V30 5 C -0.714789 0.206311 0.000000 0 +M V30 6 O -0.714789 1.031556 0.000000 0 +M V30 7 C -1.429261 -0.206189 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 +M V30 2 1 2 3 +M V30 3 1 3 4 +M V30 4 1 5 2 +M V30 5 1 5 6 CFG=1 +M V30 6 1 7 5 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC1 ATOMS=(1 5) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 7 6 0 0 0 +M V30 BEGIN ATOM +M V30 1 N -0.000106 -1.031556 0.000000 0 +M V30 2 C -0.000106 -0.206312 0.000000 0 +M V30 3 C 0.714577 0.206311 0.000000 0 +M V30 4 C 1.429261 -0.206312 0.000000 0 +M V30 5 C -0.714789 0.206311 0.000000 0 +M V30 6 O -0.714789 1.031556 0.000000 0 +M V30 7 C -1.429261 -0.206189 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 +M V30 2 1 2 3 +M V30 3 1 3 4 +M V30 4 1 5 2 +M V30 5 1 5 6 CFG=1 +M V30 6 1 7 5 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEREL1 ATOMS=(1 5) +M V30 END COLLECTION +M V30 END CTAB +M END +$$$$ +Structure drawings enhanced stereochemistry.sdf + ChemDraw01282608392D + + 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 9 9 0 0 0 +M V30 BEGIN ATOM +M V30 1 O 0.824839 -1.071585 0.000000 0 +M V30 2 C 0.412473 -0.357346 0.000000 0 +M V30 3 C -0.412508 -0.357346 0.000000 0 +M V30 4 C -0.824981 0.357119 0.000000 0 +M V30 5 O -1.649713 0.357119 0.000000 0 +M V30 6 C -0.412472 1.071585 0.000000 0 +M V30 7 C 0.412510 1.071585 0.000000 0 +M V30 8 C 0.824982 0.357119 0.000000 0 +M V30 9 O 1.649713 0.357119 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 2 1 +M V30 2 1 3 2 +M V30 3 1 4 3 +M V30 4 1 4 5 +M V30 5 1 6 4 +M V30 6 1 6 7 +M V30 7 1 8 7 +M V30 8 1 8 9 +M V30 9 1 2 8 +M V30 END BOND +M V30 END CTAB +M END +$$$$ diff --git a/INCHI-1-TEST/tests/test_unit/fixtures/enh_stereo_test_file_2.sdf b/INCHI-1-TEST/tests/test_unit/fixtures/enh_stereo_test_file_2.sdf new file mode 100644 index 00000000..ef407954 --- /dev/null +++ b/INCHI-1-TEST/tests/test_unit/fixtures/enh_stereo_test_file_2.sdf @@ -0,0 +1,1972 @@ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 18 17 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 3424.1946 -1936.7935 0 0 +M V30 2 C 3352.3145 -1895.2935 0 0 +M V30 3 C 3280.4346 -1936.7935 0 0 +M V30 4 C 3208.5542 -1895.2935 0 0 +M V30 5 C 3136.6743 -1936.7935 0 0 +M V30 6 C 3064.7944 -1895.2935 0 0 +M V30 7 Br 3136.6743 -2019.7935 0 0 +M V30 8 Cl 3208.5542 -1812.2935 0 0 +M V30 9 Cl 3280.4346 -2019.7935 0 0 +M V30 10 Cl 3352.3145 -1812.2935 0 0 +M V30 11 Cl 3424.1946 -2019.7935 0 0 +M V30 12 C 3496.075 -1895.2935 0 0 +M V30 13 C 3567.9548 -1936.7942 0 0 +M V30 14 C 3639.835 -1895.2944 0 0 +M V30 15 C 3711.7148 -1936.7942 0 0 +M V30 16 Cl 3639.835 -1812.2944 0 0 +M V30 17 Cl 3567.9548 -2019.7942 0 0 +M V30 18 Cl 3496.075 -1812.2937 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 CFG=3 +M V30 3 1 1 12 +M V30 4 1 2 3 +M V30 5 1 2 10 CFG=1 +M V30 6 1 3 4 +M V30 7 1 3 9 CFG=1 +M V30 8 1 4 5 +M V30 9 1 4 8 CFG=1 +M V30 10 1 5 6 +M V30 11 1 5 7 CFG=1 +M V30 12 1 12 13 +M V30 13 1 12 18 CFG=3 +M V30 14 1 13 14 +M V30 15 1 13 17 CFG=1 +M V30 16 1 14 15 +M V30 17 1 14 16 CFG=1 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC2 ATOMS=(1 1) +M V30 MDLV30/STERAC1 ATOMS=(2 2 3) +M V30 MDLV30/STEABS ATOMS=(2 4 5) +M V30 MDLV30/STEREL1 ATOMS=(2 12 13) +M V30 MDLV30/STEREL2 ATOMS=(1 14) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6+,7-,8+,9+,10-/m0/s1 + +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(4)(6,8)3(7,9)(10) + +> +1EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 18 17 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 2617.5557 -1933.6348 0 0 +M V30 2 C 2545.6758 -1892.1348 0 0 +M V30 3 C 2473.7957 -1933.6348 0 0 +M V30 4 C 2401.9155 -1892.1348 0 0 +M V30 5 C 2330.0354 -1933.6348 0 0 +M V30 6 C 2258.1553 -1892.1348 0 0 +M V30 7 Br 2330.0354 -2016.6348 0 0 +M V30 8 Cl 2401.9155 -1809.1348 0 0 +M V30 9 Cl 2473.7957 -2016.6348 0 0 +M V30 10 Cl 2545.6758 -1809.1348 0 0 +M V30 11 Cl 2617.5557 -2016.6348 0 0 +M V30 12 C 2689.436 -1892.1348 0 0 +M V30 13 C 2761.3159 -1933.6355 0 0 +M V30 14 C 2833.1958 -1892.1357 0 0 +M V30 15 C 2905.0759 -1933.6355 0 0 +M V30 16 Cl 2833.1958 -1809.1357 0 0 +M V30 17 Cl 2761.3159 -2016.6355 0 0 +M V30 18 Cl 2689.436 -1809.135 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 CFG=1 +M V30 3 1 1 12 +M V30 4 1 2 3 +M V30 5 1 2 10 CFG=1 +M V30 6 1 3 4 +M V30 7 1 3 9 CFG=1 +M V30 8 1 4 5 +M V30 9 1 4 8 CFG=1 +M V30 10 1 5 6 +M V30 11 1 5 7 CFG=1 +M V30 12 1 12 13 +M V30 13 1 12 18 CFG=3 +M V30 14 1 13 14 +M V30 15 1 13 17 CFG=1 +M V30 16 1 14 15 +M V30 17 1 14 16 CFG=1 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC2 ATOMS=(1 1) +M V30 MDLV30/STERAC1 ATOMS=(2 2 3) +M V30 MDLV30/STEABS ATOMS=(2 4 5) +M V30 MDLV30/STEREL1 ATOMS=(2 12 13) +M V30 MDLV30/STEREL2 ATOMS=(1 14) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6+,7-,8+,9+,10+/m0/s1 + +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(4)(6,8)3(7,9)(10) + +> +1EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 18 17 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 1652.5557 -1930.6348 0 0 +M V30 2 C 1580.6757 -1889.1348 0 0 +M V30 3 C 1508.7957 -1930.6348 0 0 +M V30 4 C 1436.9154 -1889.1348 0 0 +M V30 5 C 1365.0354 -1930.6348 0 0 +M V30 6 C 1293.1554 -1889.1348 0 0 +M V30 7 Br 1365.0354 -2013.6348 0 0 +M V30 8 Cl 1436.9154 -1806.1348 0 0 +M V30 9 Cl 1508.7957 -2013.6348 0 0 +M V30 10 Cl 1580.6757 -1806.1348 0 0 +M V30 11 Cl 1652.5557 -2013.6348 0 0 +M V30 12 C 1724.436 -1889.1348 0 0 +M V30 13 C 1796.3159 -1930.6355 0 0 +M V30 14 C 1868.196 -1889.1357 0 0 +M V30 15 C 1940.0759 -1930.6355 0 0 +M V30 16 Cl 1868.196 -1806.1357 0 0 +M V30 17 Cl 1796.3159 -2013.6355 0 0 +M V30 18 Cl 1724.436 -1806.135 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 CFG=3 +M V30 3 1 1 12 +M V30 4 1 2 3 +M V30 5 1 2 10 CFG=1 +M V30 6 1 3 4 +M V30 7 1 3 9 CFG=1 +M V30 8 1 4 5 +M V30 9 1 4 8 CFG=1 +M V30 10 1 5 6 +M V30 11 1 5 7 CFG=1 +M V30 12 1 12 13 +M V30 13 1 12 18 CFG=1 +M V30 14 1 13 14 +M V30 15 1 13 17 CFG=3 +M V30 16 1 14 15 +M V30 17 1 14 16 CFG=1 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC2 ATOMS=(1 1) +M V30 MDLV30/STERAC1 ATOMS=(2 2 3) +M V30 MDLV30/STEABS ATOMS=(2 4 5) +M V30 MDLV30/STEREL1 ATOMS=(2 12 13) +M V30 MDLV30/STEREL2 ATOMS=(1 14) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1 + +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(4)(6,8)3(7,9)(10) + +> +1EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 18 17 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 845.9167 -1927.4761 0 0 +M V30 2 C 774.0367 -1885.9761 0 0 +M V30 3 C 702.1567 -1927.4761 0 0 +M V30 4 C 630.2765 -1885.9761 0 0 +M V30 5 C 558.3965 -1927.4761 0 0 +M V30 6 C 486.5165 -1885.9761 0 0 +M V30 7 Br 558.3965 -2010.4761 0 0 +M V30 8 Cl 630.2765 -1802.9761 0 0 +M V30 9 Cl 702.1567 -2010.4761 0 0 +M V30 10 Cl 774.0367 -1802.9761 0 0 +M V30 11 Cl 845.9167 -2010.4761 0 0 +M V30 12 C 917.7971 -1885.9761 0 0 +M V30 13 C 989.677 -1927.4768 0 0 +M V30 14 C 1061.557 -1885.9771 0 0 +M V30 15 C 1133.437 -1927.4768 0 0 +M V30 16 Cl 1061.557 -1802.9771 0 0 +M V30 17 Cl 989.677 -2010.4768 0 0 +M V30 18 Cl 917.7971 -1802.9763 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 CFG=1 +M V30 3 1 1 12 +M V30 4 1 2 3 +M V30 5 1 2 10 CFG=1 +M V30 6 1 3 4 +M V30 7 1 3 9 CFG=1 +M V30 8 1 4 5 +M V30 9 1 4 8 CFG=1 +M V30 10 1 5 6 +M V30 11 1 5 7 CFG=1 +M V30 12 1 12 13 +M V30 13 1 12 18 CFG=1 +M V30 14 1 13 14 +M V30 15 1 13 17 CFG=3 +M V30 16 1 14 15 +M V30 17 1 14 16 CFG=1 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC2 ATOMS=(1 1) +M V30 MDLV30/STERAC1 ATOMS=(2 2 3) +M V30 MDLV30/STEABS ATOMS=(2 4 5) +M V30 MDLV30/STEREL1 ATOMS=(2 12 13) +M V30 MDLV30/STEREL2 ATOMS=(1 14) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10+/m0/s1 + +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(4)(6,8)3(7,9)(10) + +> +1EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 18 17 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 3436.5557 -1571.6348 0 0 +M V30 2 C 3364.6758 -1530.1348 0 0 +M V30 3 C 3292.7957 -1571.6348 0 0 +M V30 4 C 3220.9155 -1530.1348 0 0 +M V30 5 C 3149.0354 -1571.6348 0 0 +M V30 6 C 3077.1553 -1530.1348 0 0 +M V30 7 Br 3149.0354 -1654.6346 0 0 +M V30 8 Cl 3220.9155 -1447.1348 0 0 +M V30 9 Cl 3292.7957 -1654.6346 0 0 +M V30 10 Cl 3364.6758 -1447.1348 0 0 +M V30 11 Cl 3436.5557 -1654.6346 0 0 +M V30 12 C 3508.436 -1530.1349 0 0 +M V30 13 C 3580.3159 -1571.6355 0 0 +M V30 14 C 3652.1958 -1530.1356 0 0 +M V30 15 C 3724.0759 -1571.6355 0 0 +M V30 16 Cl 3652.1958 -1447.1356 0 0 +M V30 17 Cl 3580.3159 -1654.6355 0 0 +M V30 18 Cl 3508.436 -1447.135 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 CFG=3 +M V30 3 1 1 12 +M V30 4 1 2 3 +M V30 5 1 2 10 CFG=1 +M V30 6 1 3 4 +M V30 7 1 3 9 CFG=1 +M V30 8 1 4 5 +M V30 9 1 4 8 CFG=1 +M V30 10 1 5 6 +M V30 11 1 5 7 CFG=1 +M V30 12 1 12 13 +M V30 13 1 12 18 CFG=3 +M V30 14 1 13 14 +M V30 15 1 13 17 CFG=1 +M V30 16 1 14 15 +M V30 17 1 14 16 CFG=3 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC2 ATOMS=(1 1) +M V30 MDLV30/STERAC1 ATOMS=(2 2 3) +M V30 MDLV30/STEABS ATOMS=(2 4 5) +M V30 MDLV30/STEREL1 ATOMS=(2 12 13) +M V30 MDLV30/STEREL2 ATOMS=(1 14) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4+,5+,6+,7-,8+,9+,10-/m0/s1 + +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(4)(6,8)3(7,9)(10) + +> +1EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 18 17 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 2629.9167 -1568.4761 0 0 +M V30 2 C 2558.0366 -1526.9761 0 0 +M V30 3 C 2486.1567 -1568.4761 0 0 +M V30 4 C 2414.2764 -1526.9761 0 0 +M V30 5 C 2342.3965 -1568.4761 0 0 +M V30 6 C 2270.5166 -1526.9761 0 0 +M V30 7 Br 2342.3965 -1651.476 0 0 +M V30 8 Cl 2414.2764 -1443.9761 0 0 +M V30 9 Cl 2486.1567 -1651.476 0 0 +M V30 10 Cl 2558.0366 -1443.9761 0 0 +M V30 11 Cl 2629.9167 -1651.476 0 0 +M V30 12 C 2701.7971 -1526.9762 0 0 +M V30 13 C 2773.677 -1568.4768 0 0 +M V30 14 C 2845.5571 -1526.9769 0 0 +M V30 15 C 2917.437 -1568.4768 0 0 +M V30 16 Cl 2845.5571 -1443.9769 0 0 +M V30 17 Cl 2773.677 -1651.4768 0 0 +M V30 18 Cl 2701.7971 -1443.9763 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 CFG=1 +M V30 3 1 1 12 +M V30 4 1 2 3 +M V30 5 1 2 10 CFG=1 +M V30 6 1 3 4 +M V30 7 1 3 9 CFG=1 +M V30 8 1 4 5 +M V30 9 1 4 8 CFG=1 +M V30 10 1 5 6 +M V30 11 1 5 7 CFG=1 +M V30 12 1 12 13 +M V30 13 1 12 18 CFG=3 +M V30 14 1 13 14 +M V30 15 1 13 17 CFG=1 +M V30 16 1 14 15 +M V30 17 1 14 16 CFG=3 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC2 ATOMS=(1 1) +M V30 MDLV30/STERAC1 ATOMS=(2 2 3) +M V30 MDLV30/STEABS ATOMS=(2 4 5) +M V30 MDLV30/STEREL1 ATOMS=(2 12 13) +M V30 MDLV30/STEREL2 ATOMS=(1 14) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4+,5+,6+,7-,8+,9+,10+/m0/s1 + +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(4)(6,8)3(7,9)(10) + +> +1EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 18 17 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 1664.9167 -1565.4761 0 0 +M V30 2 C 1593.0367 -1523.9761 0 0 +M V30 3 C 1521.1567 -1565.4761 0 0 +M V30 4 C 1449.2765 -1523.9761 0 0 +M V30 5 C 1377.3965 -1565.4761 0 0 +M V30 6 C 1305.5165 -1523.9761 0 0 +M V30 7 Br 1377.3965 -1648.476 0 0 +M V30 8 Cl 1449.2765 -1440.9761 0 0 +M V30 9 Cl 1521.1567 -1648.476 0 0 +M V30 10 Cl 1593.0367 -1440.9761 0 0 +M V30 11 Cl 1664.9167 -1648.476 0 0 +M V30 12 C 1736.7971 -1523.9762 0 0 +M V30 13 C 1808.677 -1565.4768 0 0 +M V30 14 C 1880.5569 -1523.9769 0 0 +M V30 15 C 1952.437 -1565.4768 0 0 +M V30 16 Cl 1880.5569 -1440.9769 0 0 +M V30 17 Cl 1808.677 -1648.4768 0 0 +M V30 18 Cl 1736.7971 -1440.9763 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 CFG=3 +M V30 3 1 1 12 +M V30 4 1 2 3 +M V30 5 1 2 10 CFG=1 +M V30 6 1 3 4 +M V30 7 1 3 9 CFG=1 +M V30 8 1 4 5 +M V30 9 1 4 8 CFG=1 +M V30 10 1 5 6 +M V30 11 1 5 7 CFG=1 +M V30 12 1 12 13 +M V30 13 1 12 18 CFG=1 +M V30 14 1 13 14 +M V30 15 1 13 17 CFG=3 +M V30 16 1 14 15 +M V30 17 1 14 16 CFG=3 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC2 ATOMS=(1 1) +M V30 MDLV30/STERAC1 ATOMS=(2 2 3) +M V30 MDLV30/STEABS ATOMS=(2 4 5) +M V30 MDLV30/STEREL1 ATOMS=(2 12 13) +M V30 MDLV30/STEREL2 ATOMS=(1 14) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4+,5+,6-,7-,8-,9+,10-/m0/s1 + +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(4)(6,8)3(7,9)(10) + +> +1EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 18 17 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 858.2778 -1562.3174 0 0 +M V30 2 C 786.3978 -1520.8174 0 0 +M V30 3 C 714.5178 -1562.3174 0 0 +M V30 4 C 642.6376 -1520.8174 0 0 +M V30 5 C 570.7576 -1562.3174 0 0 +M V30 6 C 498.8776 -1520.8174 0 0 +M V30 7 Br 570.7576 -1645.3173 0 0 +M V30 8 Cl 642.6376 -1437.8174 0 0 +M V30 9 Cl 714.5178 -1645.3173 0 0 +M V30 10 Cl 786.3978 -1437.8174 0 0 +M V30 11 Cl 858.2778 -1645.3173 0 0 +M V30 12 C 930.1582 -1520.8175 0 0 +M V30 13 C 1002.0381 -1562.3181 0 0 +M V30 14 C 1073.9181 -1520.8182 0 0 +M V30 15 C 1145.7981 -1562.3181 0 0 +M V30 16 Cl 1073.9181 -1437.8182 0 0 +M V30 17 Cl 1002.0381 -1645.3181 0 0 +M V30 18 Cl 930.1582 -1437.8176 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 CFG=1 +M V30 3 1 1 12 +M V30 4 1 2 3 +M V30 5 1 2 10 CFG=1 +M V30 6 1 3 4 +M V30 7 1 3 9 CFG=1 +M V30 8 1 4 5 +M V30 9 1 4 8 CFG=1 +M V30 10 1 5 6 +M V30 11 1 5 7 CFG=1 +M V30 12 1 12 13 +M V30 13 1 12 18 CFG=1 +M V30 14 1 13 14 +M V30 15 1 13 17 CFG=3 +M V30 16 1 14 15 +M V30 17 1 14 16 CFG=3 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC2 ATOMS=(1 1) +M V30 MDLV30/STERAC1 ATOMS=(2 2 3) +M V30 MDLV30/STEABS ATOMS=(2 4 5) +M V30 MDLV30/STEREL1 ATOMS=(2 12 13) +M V30 MDLV30/STEREL2 ATOMS=(1 14) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4+,5+,6-,7-,8-,9+,10+/m0/s1 + +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(4)(6,8)3(7,9)(10) + +> +1EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 18 17 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 3428.5557 -1046.6348 0 0 +M V30 2 C 3356.6758 -1005.1348 0 0 +M V30 3 C 3284.7957 -1046.6348 0 0 +M V30 4 C 3212.9155 -1005.1348 0 0 +M V30 5 C 3141.0354 -1046.6348 0 0 +M V30 6 C 3069.1553 -1005.1348 0 0 +M V30 7 Br 3141.0354 -1129.6346 0 0 +M V30 8 Cl 3212.9155 -922.1348 0 0 +M V30 9 Cl 3284.7957 -1129.6346 0 0 +M V30 10 Cl 3356.6758 -922.1348 0 0 +M V30 11 Cl 3428.5557 -1129.6346 0 0 +M V30 12 C 3500.436 -1005.1349 0 0 +M V30 13 C 3572.3159 -1046.6355 0 0 +M V30 14 C 3644.196 -1005.1356 0 0 +M V30 15 C 3716.0759 -1046.6355 0 0 +M V30 16 Cl 3644.196 -922.1356 0 0 +M V30 17 Cl 3572.3159 -1129.6355 0 0 +M V30 18 Cl 3500.436 -922.135 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 CFG=3 +M V30 3 1 1 12 +M V30 4 1 2 3 +M V30 5 1 2 10 CFG=3 +M V30 6 1 3 4 +M V30 7 1 3 9 CFG=3 +M V30 8 1 4 5 +M V30 9 1 4 8 CFG=1 +M V30 10 1 5 6 +M V30 11 1 5 7 CFG=1 +M V30 12 1 12 13 +M V30 13 1 12 18 CFG=3 +M V30 14 1 13 14 +M V30 15 1 13 17 CFG=1 +M V30 16 1 14 15 +M V30 17 1 14 16 CFG=1 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC2 ATOMS=(1 1) +M V30 MDLV30/STERAC1 ATOMS=(2 2 3) +M V30 MDLV30/STEABS ATOMS=(2 4 5) +M V30 MDLV30/STEREL1 ATOMS=(2 12 13) +M V30 MDLV30/STEREL2 ATOMS=(1 14) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6+,7+,8+,9-,10-/m0/s1 + +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(4)(6,8)3(7,9)(10) + +> +1EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 18 17 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 2621.9167 -1043.4761 0 0 +M V30 2 C 2550.0366 -1001.9761 0 0 +M V30 3 C 2478.1567 -1043.4761 0 0 +M V30 4 C 2406.2764 -1001.9761 0 0 +M V30 5 C 2334.3965 -1043.4761 0 0 +M V30 6 C 2262.5166 -1001.9761 0 0 +M V30 7 Br 2334.3965 -1126.476 0 0 +M V30 8 Cl 2406.2764 -918.9761 0 0 +M V30 9 Cl 2478.1567 -1126.476 0 0 +M V30 10 Cl 2550.0366 -918.9761 0 0 +M V30 11 Cl 2621.9167 -1126.476 0 0 +M V30 12 C 2693.7971 -1001.9762 0 0 +M V30 13 C 2765.677 -1043.4768 0 0 +M V30 14 C 2837.5571 -1001.9769 0 0 +M V30 15 C 2909.437 -1043.4768 0 0 +M V30 16 Cl 2837.5571 -918.9769 0 0 +M V30 17 Cl 2765.677 -1126.4768 0 0 +M V30 18 Cl 2693.7971 -918.9763 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 CFG=1 +M V30 3 1 1 12 +M V30 4 1 2 3 +M V30 5 1 2 10 CFG=3 +M V30 6 1 3 4 +M V30 7 1 3 9 CFG=3 +M V30 8 1 4 5 +M V30 9 1 4 8 CFG=1 +M V30 10 1 5 6 +M V30 11 1 5 7 CFG=1 +M V30 12 1 12 13 +M V30 13 1 12 18 CFG=3 +M V30 14 1 13 14 +M V30 15 1 13 17 CFG=1 +M V30 16 1 14 15 +M V30 17 1 14 16 CFG=1 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC2 ATOMS=(1 1) +M V30 MDLV30/STERAC1 ATOMS=(2 2 3) +M V30 MDLV30/STEABS ATOMS=(2 4 5) +M V30 MDLV30/STEREL1 ATOMS=(2 12 13) +M V30 MDLV30/STEREL2 ATOMS=(1 14) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6+,7+,8+,9-,10+/m0/s1 + +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(4)(6,8)3(7,9)(10) + +> +1EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 18 17 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 1656.9167 -1040.4761 0 0 +M V30 2 C 1585.0367 -998.9761 0 0 +M V30 3 C 1513.1567 -1040.4761 0 0 +M V30 4 C 1441.2765 -998.9761 0 0 +M V30 5 C 1369.3965 -1040.4761 0 0 +M V30 6 C 1297.5165 -998.9761 0 0 +M V30 7 Br 1369.3965 -1123.476 0 0 +M V30 8 Cl 1441.2765 -915.9761 0 0 +M V30 9 Cl 1513.1567 -1123.476 0 0 +M V30 10 Cl 1585.0367 -915.9761 0 0 +M V30 11 Cl 1656.9167 -1123.476 0 0 +M V30 12 C 1728.7971 -998.9762 0 0 +M V30 13 C 1800.677 -1040.4768 0 0 +M V30 14 C 1872.5571 -998.9769 0 0 +M V30 15 C 1944.437 -1040.4768 0 0 +M V30 16 Cl 1872.5571 -915.9769 0 0 +M V30 17 Cl 1800.677 -1123.4768 0 0 +M V30 18 Cl 1728.7971 -915.9763 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 CFG=3 +M V30 3 1 1 12 +M V30 4 1 2 3 +M V30 5 1 2 10 CFG=3 +M V30 6 1 3 4 +M V30 7 1 3 9 CFG=3 +M V30 8 1 4 5 +M V30 9 1 4 8 CFG=1 +M V30 10 1 5 6 +M V30 11 1 5 7 CFG=1 +M V30 12 1 12 13 +M V30 13 1 12 18 CFG=1 +M V30 14 1 13 14 +M V30 15 1 13 17 CFG=3 +M V30 16 1 14 15 +M V30 17 1 14 16 CFG=1 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC2 ATOMS=(1 1) +M V30 MDLV30/STERAC1 ATOMS=(2 2 3) +M V30 MDLV30/STEABS ATOMS=(2 4 5) +M V30 MDLV30/STEREL1 ATOMS=(2 12 13) +M V30 MDLV30/STEREL2 ATOMS=(1 14) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7+,8-,9-,10-/m0/s1 + +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(4)(6,8)3(7,9)(10) + +> +1EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 18 17 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 850.2778 -1037.3174 0 0 +M V30 2 C 778.3978 -995.8174 0 0 +M V30 3 C 706.5178 -1037.3174 0 0 +M V30 4 C 634.6376 -995.8174 0 0 +M V30 5 C 562.7576 -1037.3174 0 0 +M V30 6 C 490.8776 -995.8174 0 0 +M V30 7 Br 562.7576 -1120.3173 0 0 +M V30 8 Cl 634.6376 -912.8174 0 0 +M V30 9 Cl 706.5178 -1120.3173 0 0 +M V30 10 Cl 778.3978 -912.8174 0 0 +M V30 11 Cl 850.2778 -1120.3173 0 0 +M V30 12 C 922.1582 -995.8175 0 0 +M V30 13 C 994.0381 -1037.3181 0 0 +M V30 14 C 1065.9181 -995.8182 0 0 +M V30 15 C 1137.7981 -1037.3181 0 0 +M V30 16 Cl 1065.9181 -912.8182 0 0 +M V30 17 Cl 994.0381 -1120.3181 0 0 +M V30 18 Cl 922.1582 -912.8176 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 CFG=1 +M V30 3 1 1 12 +M V30 4 1 2 3 +M V30 5 1 2 10 CFG=3 +M V30 6 1 3 4 +M V30 7 1 3 9 CFG=3 +M V30 8 1 4 5 +M V30 9 1 4 8 CFG=1 +M V30 10 1 5 6 +M V30 11 1 5 7 CFG=1 +M V30 12 1 12 13 +M V30 13 1 12 18 CFG=1 +M V30 14 1 13 14 +M V30 15 1 13 17 CFG=3 +M V30 16 1 14 15 +M V30 17 1 14 16 CFG=1 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC2 ATOMS=(1 1) +M V30 MDLV30/STERAC1 ATOMS=(2 2 3) +M V30 MDLV30/STEABS ATOMS=(2 4 5) +M V30 MDLV30/STEREL1 ATOMS=(2 12 13) +M V30 MDLV30/STEREL2 ATOMS=(1 14) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7+,8-,9-,10+/m0/s1 + +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(4)(6,8)3(7,9)(10) + +> +1EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 18 17 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 3440.9167 -681.4761 0 0 +M V30 2 C 3369.0366 -639.976 0 0 +M V30 3 C 3297.1567 -681.4761 0 0 +M V30 4 C 3225.2764 -639.976 0 0 +M V30 5 C 3153.3965 -681.4761 0 0 +M V30 6 C 3081.5166 -639.976 0 0 +M V30 7 Br 3153.3965 -764.476 0 0 +M V30 8 Cl 3225.2764 -556.976 0 0 +M V30 9 Cl 3297.1567 -764.476 0 0 +M V30 10 Cl 3369.0366 -556.976 0 0 +M V30 11 Cl 3440.9167 -764.476 0 0 +M V30 12 C 3512.7971 -639.9762 0 0 +M V30 13 C 3584.677 -681.4769 0 0 +M V30 14 C 3656.5569 -639.9769 0 0 +M V30 15 C 3728.437 -681.4769 0 0 +M V30 16 Cl 3656.5569 -556.9769 0 0 +M V30 17 Cl 3584.677 -764.4768 0 0 +M V30 18 Cl 3512.7971 -556.9764 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 CFG=3 +M V30 3 1 1 12 +M V30 4 1 2 3 +M V30 5 1 2 10 CFG=3 +M V30 6 1 3 4 +M V30 7 1 3 9 CFG=3 +M V30 8 1 4 5 +M V30 9 1 4 8 CFG=1 +M V30 10 1 5 6 +M V30 11 1 5 7 CFG=1 +M V30 12 1 12 13 +M V30 13 1 12 18 CFG=3 +M V30 14 1 13 14 +M V30 15 1 13 17 CFG=1 +M V30 16 1 14 15 +M V30 17 1 14 16 CFG=3 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC2 ATOMS=(1 1) +M V30 MDLV30/STERAC1 ATOMS=(2 2 3) +M V30 MDLV30/STEABS ATOMS=(2 4 5) +M V30 MDLV30/STEREL1 ATOMS=(2 12 13) +M V30 MDLV30/STEREL2 ATOMS=(1 14) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4+,5+,6+,7+,8+,9-,10-/m0/s1 + +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(4)(6,8)3(7,9)(10) + +> +1EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 18 17 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 2634.2778 -678.3174 0 0 +M V30 2 C 2562.3979 -636.8173 0 0 +M V30 3 C 2490.5178 -678.3174 0 0 +M V30 4 C 2418.6377 -636.8173 0 0 +M V30 5 C 2346.7576 -678.3174 0 0 +M V30 6 C 2274.8774 -636.8173 0 0 +M V30 7 Br 2346.7576 -761.3173 0 0 +M V30 8 Cl 2418.6377 -553.8173 0 0 +M V30 9 Cl 2490.5178 -761.3173 0 0 +M V30 10 Cl 2562.3979 -553.8173 0 0 +M V30 11 Cl 2634.2778 -761.3173 0 0 +M V30 12 C 2706.1582 -636.8175 0 0 +M V30 13 C 2778.0381 -678.3182 0 0 +M V30 14 C 2849.918 -636.8182 0 0 +M V30 15 C 2921.7981 -678.3182 0 0 +M V30 16 Cl 2849.918 -553.8182 0 0 +M V30 17 Cl 2778.0381 -761.3181 0 0 +M V30 18 Cl 2706.1582 -553.8177 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 CFG=1 +M V30 3 1 1 12 +M V30 4 1 2 3 +M V30 5 1 2 10 CFG=3 +M V30 6 1 3 4 +M V30 7 1 3 9 CFG=3 +M V30 8 1 4 5 +M V30 9 1 4 8 CFG=1 +M V30 10 1 5 6 +M V30 11 1 5 7 CFG=1 +M V30 12 1 12 13 +M V30 13 1 12 18 CFG=3 +M V30 14 1 13 14 +M V30 15 1 13 17 CFG=1 +M V30 16 1 14 15 +M V30 17 1 14 16 CFG=3 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC2 ATOMS=(1 1) +M V30 MDLV30/STERAC1 ATOMS=(2 2 3) +M V30 MDLV30/STEABS ATOMS=(2 4 5) +M V30 MDLV30/STEREL1 ATOMS=(2 12 13) +M V30 MDLV30/STEREL2 ATOMS=(1 14) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4+,5+,6+,7+,8+,9-,10+/m0/s1 + +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(4)(6,8)3(7,9)(10) + +> +1EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 18 17 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 1669.2778 -675.3174 0 0 +M V30 2 C 1597.3978 -633.8173 0 0 +M V30 3 C 1525.5178 -675.3174 0 0 +M V30 4 C 1453.6376 -633.8173 0 0 +M V30 5 C 1381.7576 -675.3174 0 0 +M V30 6 C 1309.8776 -633.8173 0 0 +M V30 7 Br 1381.7576 -758.3173 0 0 +M V30 8 Cl 1453.6376 -550.8173 0 0 +M V30 9 Cl 1525.5178 -758.3173 0 0 +M V30 10 Cl 1597.3978 -550.8173 0 0 +M V30 11 Cl 1669.2778 -758.3173 0 0 +M V30 12 C 1741.1582 -633.8175 0 0 +M V30 13 C 1813.0381 -675.3182 0 0 +M V30 14 C 1884.918 -633.8182 0 0 +M V30 15 C 1956.7981 -675.3182 0 0 +M V30 16 Cl 1884.918 -550.8182 0 0 +M V30 17 Cl 1813.0381 -758.3181 0 0 +M V30 18 Cl 1741.1582 -550.8177 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 CFG=3 +M V30 3 1 1 12 +M V30 4 1 2 3 +M V30 5 1 2 10 CFG=3 +M V30 6 1 3 4 +M V30 7 1 3 9 CFG=3 +M V30 8 1 4 5 +M V30 9 1 4 8 CFG=1 +M V30 10 1 5 6 +M V30 11 1 5 7 CFG=1 +M V30 12 1 12 13 +M V30 13 1 12 18 CFG=1 +M V30 14 1 13 14 +M V30 15 1 13 17 CFG=3 +M V30 16 1 14 15 +M V30 17 1 14 16 CFG=3 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC2 ATOMS=(1 1) +M V30 MDLV30/STERAC1 ATOMS=(2 2 3) +M V30 MDLV30/STEABS ATOMS=(2 4 5) +M V30 MDLV30/STEREL1 ATOMS=(2 12 13) +M V30 MDLV30/STEREL2 ATOMS=(1 14) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4+,5+,6-,7+,8-,9-,10-/m0/s1 + +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(4)(6,8)3(7,9)(10) + +> +1EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 18 17 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 719.8806 -405.6257 0 0 +M V30 2 C 638.4742 -358.6256 0 0 +M V30 3 C 557.0679 -405.6257 0 0 +M V30 4 C 475.6614 -358.6256 0 0 +M V30 5 C 394.255 -405.6257 0 0 +M V30 6 C 312.8487 -358.6256 0 0 +M V30 7 Br 394.255 -499.6256 0 0 +M V30 8 Cl 475.6614 -264.6255 0 0 +M V30 9 Cl 557.0679 -499.6256 0 0 +M V30 10 Cl 638.4742 -264.6255 0 0 +M V30 11 Cl 719.8806 -499.6256 0 0 +M V30 12 C 801.2872 -358.6258 0 0 +M V30 13 C 882.6934 -405.6266 0 0 +M V30 14 C 964.0997 -358.6266 0 0 +M V30 15 C 1045.5061 -405.6266 0 0 +M V30 16 Cl 964.0997 -264.6266 0 0 +M V30 17 Cl 882.6934 -499.6266 0 0 +M V30 18 Cl 801.2872 -264.626 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 CFG=1 +M V30 3 1 1 12 +M V30 4 1 2 3 +M V30 5 1 2 10 CFG=3 +M V30 6 1 3 4 +M V30 7 1 3 9 CFG=3 +M V30 8 1 4 5 +M V30 9 1 4 8 CFG=1 +M V30 10 1 5 6 +M V30 11 1 5 7 CFG=1 +M V30 12 1 12 13 +M V30 13 1 12 18 CFG=1 +M V30 14 1 13 14 +M V30 15 1 13 17 CFG=3 +M V30 16 1 14 15 +M V30 17 1 14 16 CFG=3 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC2 ATOMS=(1 1) +M V30 MDLV30/STERAC1 ATOMS=(2 2 3) +M V30 MDLV30/STEABS ATOMS=(2 4 5) +M V30 MDLV30/STEREL1 ATOMS=(2 12 13) +M V30 MDLV30/STEREL2 ATOMS=(1 14) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4+,5+,6-,7+,8-,9-,10+/m0/s1 + +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m0/s1(3,5)2(4)(6,8)3(7,9)(10) + +> +1EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 18 17 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 1789.6389 -266.1587 0 0 +M V30 2 C 1717.7589 -224.6586 0 0 +M V30 3 C 1645.8789 -266.1587 0 0 +M V30 4 C 1573.9987 -224.6586 0 0 +M V30 5 C 1502.1187 -266.1587 0 0 +M V30 6 C 1430.2386 -224.6586 0 0 +M V30 7 Br 1502.1187 -349.1586 0 0 +M V30 8 Cl 1573.9987 -141.6586 0 0 +M V30 9 Cl 1645.8789 -349.1586 0 0 +M V30 10 Cl 1717.7589 -141.6586 0 0 +M V30 11 Cl 1789.6389 -349.1586 0 0 +M V30 12 C 1861.5193 -224.6588 0 0 +M V30 13 C 1933.3992 -266.1595 0 0 +M V30 14 C 2005.2792 -224.6595 0 0 +M V30 15 C 2077.1592 -266.1595 0 0 +M V30 16 Cl 2005.2792 -141.6595 0 0 +M V30 17 Cl 1933.3992 -349.1595 0 0 +M V30 18 Cl 1861.5193 -141.659 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 CFG=1 +M V30 3 1 1 12 +M V30 4 1 2 3 +M V30 5 1 2 10 CFG=3 +M V30 6 1 3 4 +M V30 7 1 3 9 CFG=3 +M V30 8 1 4 5 +M V30 9 1 4 8 CFG=3 +M V30 10 1 5 6 +M V30 11 1 5 7 CFG=3 +M V30 12 1 12 13 +M V30 13 1 12 18 CFG=3 +M V30 14 1 13 14 +M V30 15 1 13 17 CFG=1 +M V30 16 1 14 15 +M V30 17 1 14 16 CFG=3 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC2 ATOMS=(1 1) +M V30 MDLV30/STEABS ATOMS=(2 2 3) +M V30 MDLV30/STERAC1 ATOMS=(2 4 5) +M V30 MDLV30/STEREL2 ATOMS=(2 12 13) +M V30 MDLV30/STEREL1 ATOMS=(1 14) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m1/s1 + +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m1/s1(7,9)2(4)(6,8)3(3,5)(10) + +> +2EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 18 17 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 1789.6389 -266.1587 0 0 +M V30 2 C 1717.7589 -224.6586 0 0 +M V30 3 C 1645.8789 -266.1587 0 0 +M V30 4 C 1573.9987 -224.6586 0 0 +M V30 5 C 1502.1187 -266.1587 0 0 +M V30 6 C 1430.2386 -224.6586 0 0 +M V30 7 Br 1502.1187 -349.1586 0 0 +M V30 8 Cl 1573.9987 -141.6586 0 0 +M V30 9 Cl 1645.8789 -349.1586 0 0 +M V30 10 Cl 1717.7589 -141.6586 0 0 +M V30 11 Cl 1789.6389 -349.1586 0 0 +M V30 12 C 1861.5193 -224.6588 0 0 +M V30 13 C 1933.3992 -266.1595 0 0 +M V30 14 C 2005.2792 -224.6595 0 0 +M V30 15 C 2077.1592 -266.1595 0 0 +M V30 16 Cl 2005.2792 -141.6595 0 0 +M V30 17 Cl 1933.3992 -349.1595 0 0 +M V30 18 Cl 1861.5193 -141.659 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 CFG=1 +M V30 3 1 1 12 +M V30 4 1 2 3 +M V30 5 1 2 10 CFG=3 +M V30 6 1 3 4 +M V30 7 1 3 9 CFG=3 +M V30 8 1 4 5 +M V30 9 1 4 8 CFG=3 +M V30 10 1 5 6 +M V30 11 1 5 7 CFG=3 +M V30 12 1 12 13 +M V30 13 1 12 18 CFG=3 +M V30 14 1 13 14 +M V30 15 1 13 17 CFG=1 +M V30 16 1 14 15 +M V30 17 1 14 16 CFG=3 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC1 ATOMS=(1 1) +M V30 MDLV30/STEABS ATOMS=(2 2 3) +M V30 MDLV30/STERAC2 ATOMS=(2 4 5) +M V30 MDLV30/STEREL2 ATOMS=(2 12 13) +M V30 MDLV30/STEREL1 ATOMS=(1 14) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4+,5+,6-,7+,8-,9-,10+/m0/s1 + +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m1/s1(7,9)2(4)(6,8)3(3,5)(10) + +> +2EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 18 17 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 1789.6389 -266.1587 0 0 +M V30 2 C 1717.7589 -224.6586 0 0 +M V30 3 C 1645.8789 -266.1587 0 0 +M V30 4 C 1573.9987 -224.6586 0 0 +M V30 5 C 1502.1187 -266.1587 0 0 +M V30 6 C 1430.2386 -224.6586 0 0 +M V30 7 Br 1502.1187 -349.1586 0 0 +M V30 8 Cl 1573.9987 -141.6586 0 0 +M V30 9 Cl 1645.8789 -349.1586 0 0 +M V30 10 Cl 1717.7589 -141.6586 0 0 +M V30 11 Cl 1789.6389 -349.1586 0 0 +M V30 12 C 1861.5193 -224.6588 0 0 +M V30 13 C 1933.3992 -266.1595 0 0 +M V30 14 C 2005.2792 -224.6595 0 0 +M V30 15 C 2077.1592 -266.1595 0 0 +M V30 16 Cl 2005.2792 -141.6595 0 0 +M V30 17 Cl 1933.3992 -349.1595 0 0 +M V30 18 Cl 1861.5193 -141.659 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 CFG=1 +M V30 3 1 1 12 +M V30 4 1 2 3 +M V30 5 1 2 10 CFG=3 +M V30 6 1 3 4 +M V30 7 1 3 9 CFG=3 +M V30 8 1 4 5 +M V30 9 1 4 8 CFG=3 +M V30 10 1 5 6 +M V30 11 1 5 7 CFG=3 +M V30 12 1 12 13 +M V30 13 1 12 18 CFG=3 +M V30 14 1 13 14 +M V30 15 1 13 17 CFG=1 +M V30 16 1 14 15 +M V30 17 1 14 16 CFG=3 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC1 ATOMS=(1 1) +M V30 MDLV30/STEABS ATOMS=(2 2 3) +M V30 MDLV30/STERAC2 ATOMS=(2 4 5) +M V30 MDLV30/STEREL1 ATOMS=(2 12 13) +M V30 MDLV30/STEREL2 ATOMS=(1 14) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4+,5+,6-,7+,8-,9-,10+/m0/s1 + +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m1/s1(7,9)2(4)(6,8)3(3,5)(10) + +> +2EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 18 17 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 1789.6389 -266.1587 0 0 +M V30 2 C 1717.7589 -224.6586 0 0 +M V30 3 C 1645.8789 -266.1587 0 0 +M V30 4 C 1573.9987 -224.6586 0 0 +M V30 5 C 1502.1187 -266.1587 0 0 +M V30 6 C 1430.2386 -224.6586 0 0 +M V30 7 Br 1502.1187 -349.1586 0 0 +M V30 8 Cl 1573.9987 -141.6586 0 0 +M V30 9 Cl 1645.8789 -349.1586 0 0 +M V30 10 Cl 1717.7589 -141.6586 0 0 +M V30 11 Cl 1789.6389 -349.1586 0 0 +M V30 12 C 1861.5193 -224.6588 0 0 +M V30 13 C 1933.3992 -266.1595 0 0 +M V30 14 C 2005.2792 -224.6595 0 0 +M V30 15 C 2077.1592 -266.1595 0 0 +M V30 16 Cl 2005.2792 -141.6595 0 0 +M V30 17 Cl 1933.3992 -349.1595 0 0 +M V30 18 Cl 1861.5193 -141.659 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 CFG=3 +M V30 3 1 1 12 +M V30 4 1 2 3 +M V30 5 1 2 10 CFG=3 +M V30 6 1 3 4 +M V30 7 1 3 9 CFG=3 +M V30 8 1 4 5 +M V30 9 1 4 8 CFG=1 +M V30 10 1 5 6 +M V30 11 1 5 7 CFG=1 +M V30 12 1 12 13 +M V30 13 1 12 18 CFG=3 +M V30 14 1 13 14 +M V30 15 1 13 17 CFG=1 +M V30 16 1 14 15 +M V30 17 1 14 16 CFG=3 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC1 ATOMS=(1 1) +M V30 MDLV30/STEABS ATOMS=(2 2 3) +M V30 MDLV30/STERAC2 ATOMS=(2 4 5) +M V30 MDLV30/STEREL1 ATOMS=(2 12 13) +M V30 MDLV30/STEREL2 ATOMS=(1 14) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4+,5+,6-,7+,8-,9-,10+/m0/s1 + +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m1/s1(7,9)2(4)(6,8)3(3,5)(10) + +> +2EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 18 17 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 1789.6389 -266.1587 0 0 +M V30 2 C 1717.7589 -224.6586 0 0 +M V30 3 C 1645.8789 -266.1587 0 0 +M V30 4 C 1573.9987 -224.6586 0 0 +M V30 5 C 1502.1187 -266.1587 0 0 +M V30 6 C 1430.2386 -224.6586 0 0 +M V30 7 Br 1502.1187 -349.1586 0 0 +M V30 8 Cl 1573.9987 -141.6586 0 0 +M V30 9 Cl 1645.8789 -349.1586 0 0 +M V30 10 Cl 1717.7589 -141.6586 0 0 +M V30 11 Cl 1789.6389 -349.1586 0 0 +M V30 12 C 1861.5193 -224.6588 0 0 +M V30 13 C 1933.3992 -266.1595 0 0 +M V30 14 C 2005.2792 -224.6595 0 0 +M V30 15 C 2077.1592 -266.1595 0 0 +M V30 16 Cl 2005.2792 -141.6595 0 0 +M V30 17 Cl 1933.3992 -349.1595 0 0 +M V30 18 Cl 1861.5193 -141.659 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 CFG=1 +M V30 3 1 1 12 +M V30 4 1 2 3 +M V30 5 1 2 10 CFG=3 +M V30 6 1 3 4 +M V30 7 1 3 9 CFG=3 +M V30 8 1 4 5 +M V30 9 1 4 8 CFG=1 +M V30 10 1 5 6 +M V30 11 1 5 7 CFG=1 +M V30 12 1 12 13 +M V30 13 1 12 18 CFG=1 +M V30 14 1 13 14 +M V30 15 1 13 17 CFG=3 +M V30 16 1 14 15 +M V30 17 1 14 16 CFG=3 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC1 ATOMS=(1 1) +M V30 MDLV30/STEABS ATOMS=(2 2 3) +M V30 MDLV30/STERAC2 ATOMS=(2 4 5) +M V30 MDLV30/STEREL1 ATOMS=(2 12 13) +M V30 MDLV30/STEREL2 ATOMS=(1 14) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4+,5+,6-,7+,8-,9-,10+/m0/s1 + +> +InChI=1S/C10H14BrCl7/c1-3(11)5(13)7(15)9(17)10(18)8(16)6(14)4(2)12/h3-10H,1-2H3/t3-,4-,5+,6-,7-,8-,9+,10-/m1/s1(7,9)2(4)(6,8)3(3,5)(10) + +> +2EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 8 8 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 858.7786 -570.2803 0 0 +M V30 2 C 907.3196 -535.0132 0 0 +M V30 3 C 877.3196 -627.3436 0 0 +M V30 4 O 801.7153 -551.7392 0 0 +M V30 5 O 907.3197 -475.0132 0 0 +M V30 6 C 955.8607 -570.2803 0 0 +M V30 7 Cl 1012.9241 -551.7394 0 0 +M V30 8 C 937.3196 -627.3438 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 3 +M V30 3 1 1 4 CFG=1 +M V30 4 1 2 5 CFG=1 +M V30 5 1 2 6 +M V30 6 1 3 8 +M V30 7 1 6 7 CFG=1 +M V30 8 1 6 8 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEREL1 ATOMS=(3 1 2 6) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C5H9ClO2/c6-3-1-2-4(7)5(3)8/h3-5,7-8H,1-2H2/t3-,4+,5-/m0/s1 + +> +InChI=1/C5H9ClO2/c6-3-1-2-4(7)5(3)8/h3-5,7-8H,1-2H2/t3-,4+,5-/m0/s2 + +> +3EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 8 8 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 413.74 -573.2996 0 0 +M V30 2 C 462.2811 -538.0325 0 0 +M V30 3 C 432.2809 -630.3629 0 0 +M V30 4 O 356.6766 -554.7585 0 0 +M V30 5 O 462.2811 -478.0325 0 0 +M V30 6 C 510.822 -573.2996 0 0 +M V30 7 Cl 567.8854 -554.7587 0 0 +M V30 8 C 492.281 -630.363 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 3 +M V30 3 1 1 4 CFG=3 +M V30 4 1 2 5 CFG=3 +M V30 5 1 2 6 +M V30 6 1 3 8 +M V30 7 1 6 7 CFG=3 +M V30 8 1 6 8 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEREL1 ATOMS=(3 1 2 6) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1/C5H9ClO2/c6-3-1-2-4(7)5(3)8/h3-5,7-8H,1-2H2/t3-,4+,5-/m1/s1 + +> +InChI=1/C5H9ClO2/c6-3-1-2-4(7)5(3)8/h3-5,7-8H,1-2H2/t3-,4+,5-/m0/s2 + +> +3EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 8 8 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 1839.8173 -572.261 0 0 +M V30 2 C 1888.3582 -536.9939 0 0 +M V30 3 C 1858.3582 -629.3243 0 0 +M V30 4 O 1782.7539 -553.7199 0 0 +M V30 5 O 1888.3583 -476.9939 0 0 +M V30 6 C 1936.8992 -572.261 0 0 +M V30 7 Cl 1993.9626 -553.7202 0 0 +M V30 8 C 1918.358 -629.3245 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 3 +M V30 3 1 1 4 CFG=1 +M V30 4 1 2 5 CFG=1 +M V30 5 1 2 6 +M V30 6 1 3 8 +M V30 7 1 6 7 CFG=1 +M V30 8 1 6 8 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC1 ATOMS=(3 1 2 6) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C5H9ClO2/c6-3-1-2-4(7)5(3)8/h3-5,7-8H,1-2H2/t3-,4+,5-/m0/s1 + +> +InChI=1/C5H9ClO2/c6-3-1-2-4(7)5(3)8/h3-5,7-8H,1-2H2/t3-,4+,5-/m0/s3 + +> +4EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 8 8 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 1394.7787 -575.2803 0 0 +M V30 2 C 1443.3196 -540.0132 0 0 +M V30 3 C 1413.3196 -632.3436 0 0 +M V30 4 O 1337.7153 -556.7392 0 0 +M V30 5 O 1443.3197 -480.0132 0 0 +M V30 6 C 1491.8606 -575.2803 0 0 +M V30 7 Cl 1548.9241 -556.7394 0 0 +M V30 8 C 1473.3195 -632.3438 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 3 +M V30 3 1 1 4 CFG=3 +M V30 4 1 2 5 CFG=3 +M V30 5 1 2 6 +M V30 6 1 3 8 +M V30 7 1 6 7 CFG=3 +M V30 8 1 6 8 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STERAC1 ATOMS=(3 1 2 6) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C5H9ClO2/c6-3-1-2-4(7)5(3)8/h3-5,7-8H,1-2H2/t3-,4+,5-/m1/s1 + +> +InChI=1/C5H9ClO2/c6-3-1-2-4(7)5(3)8/h3-5,7-8H,1-2H2/t3-,4+,5-/m0/s3 + +> +4EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 11 10 0 0 0 +M V30 BEGIN ATOM +M V30 1 C 5.15734 -5.49189 0.0 0 +M V30 2 C 6.02876 -5.00137 0.0 0 CFG=2 +M V30 3 C 6.88929 -5.51079 0.0 0 +M V30 4 C 7.76071 -5.02026 0.0 0 CFG=2 +M V30 5 C 8.62123 -5.52968 0.0 0 +M V30 6 C 9.49266 -5.03916 0.0 0 CFG=2 +M V30 7 C 10.3532 -5.54857 0.0 0 +M V30 8 Cl 6.03968 -4.00143 0.0 0 +M V30 9 Br 7.77162 -4.02032 0.0 0 +M V30 10 O 9.50357 -4.03922 0.0 0 +M V30 11 C 4.29682 -4.98247 0.0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 +M V30 3 1 2 3 +M V30 4 1 2 8 CFG=1 +M V30 5 1 3 4 +M V30 6 1 4 5 +M V30 7 1 4 9 CFG=1 +M V30 8 1 5 6 +M V30 9 1 6 7 +M V30 10 1 6 10 CFG=1 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEABS ATOMS=(3 2 4 6) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C7H14BrClO/c1-5(9)3-7(8)4-6(2)10/h5-7,10H,3-4H2,1-2H3/t5-,6+,7-/m1/s1 + +> +InChI=1S/C7H14BrClO/c1-5(9)3-7(8)4-6(2)10/h5-7,10H,3-4H2,1-2H3/t5-,6+,7-/m1/s1 + +> +5EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 10 9 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 250 -700 0 0 +M V30 2 C 302.2857 -670.5686 0 0 +M V30 3 C 353.9169 -701.1337 0 0 +M V30 4 C 406.2026 -671.7023 0 0 +M V30 5 C 457.8337 -702.2673 0 0 +M V30 6 C 510.1194 -672.8359 0 0 +M V30 7 C 561.7506 -703.4009 0 0 +M V30 8 Cl 302.9404 -610.5721 0 0 +M V30 9 Br 406.8572 -611.7058 0 0 +M V30 10 O 510.7741 -612.8395 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 2 3 +M V30 3 1 2 8 CFG=1 +M V30 4 1 3 4 +M V30 5 1 4 5 +M V30 6 1 4 9 CFG=1 +M V30 7 1 5 6 +M V30 8 1 6 7 +M V30 9 1 6 10 CFG=3 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEABS ATOMS=(1 2) +M V30 MDLV30/STEREL1 ATOMS=(1 4) +M V30 MDLV30/STERAC1 ATOMS=(1 6) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C7H14BrClO/c1-5(9)3-7(8)4-6(2)10/h5-7,10H,3-4H2,1-2H3/t5-,6-,7-/m1/s1 + +> +InChI=1S/C7H14BrClO/c1-5(9)3-7(8)4-6(2)10/h5-7,10H,3-4H2,1-2H3/t5-,6-,7-/m1/s1(5)2(7)3(6) + +> +6EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 10 9 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 250 -700 0 0 +M V30 2 C 302.2857 -670.5686 0 0 +M V30 3 C 353.9169 -701.1337 0 0 +M V30 4 C 406.2026 -671.7023 0 0 +M V30 5 C 457.8337 -702.2673 0 0 +M V30 6 C 510.1194 -672.8359 0 0 +M V30 7 C 561.7506 -703.4009 0 0 +M V30 8 Cl 302.9404 -610.5721 0 0 +M V30 9 Br 406.8572 -611.7058 0 0 +M V30 10 O 510.7741 -612.8395 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 2 3 +M V30 3 1 2 8 CFG=1 +M V30 4 1 3 4 +M V30 5 1 4 5 +M V30 6 1 4 9 CFG=3 +M V30 7 1 5 6 +M V30 8 1 6 7 +M V30 9 1 6 10 CFG=3 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEABS ATOMS=(1 2) +M V30 MDLV30/STEREL1 ATOMS=(1 4) +M V30 MDLV30/STERAC1 ATOMS=(1 6) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C7H14BrClO/c1-5(9)3-7(8)4-6(2)10/h5-7,10H,3-4H2,1-2H3/t5-,6-,7+/m1/s1 + +> +InChI=1S/C7H14BrClO/c1-5(9)3-7(8)4-6(2)10/h5-7,10H,3-4H2,1-2H3/t5-,6-,7-/m1/s1(5)2(7)3(6) + +> +6EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 10 9 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 250 -700 0 0 +M V30 2 C 302.2857 -670.5686 0 0 +M V30 3 C 353.9169 -701.1337 0 0 +M V30 4 C 406.2026 -671.7023 0 0 +M V30 5 C 457.8337 -702.2673 0 0 +M V30 6 C 510.1194 -672.8359 0 0 +M V30 7 C 561.7506 -703.4009 0 0 +M V30 8 Cl 302.9404 -610.5721 0 0 +M V30 9 Br 406.8572 -611.7058 0 0 +M V30 10 O 510.7741 -612.8395 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 2 3 +M V30 3 1 2 8 CFG=1 +M V30 4 1 3 4 +M V30 5 1 4 5 +M V30 6 1 4 9 CFG=3 +M V30 7 1 5 6 +M V30 8 1 6 7 +M V30 9 1 6 10 CFG=1 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEABS ATOMS=(1 2) +M V30 MDLV30/STEREL1 ATOMS=(1 4) +M V30 MDLV30/STERAC1 ATOMS=(1 6) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C7H14BrClO/c1-5(9)3-7(8)4-6(2)10/h5-7,10H,3-4H2,1-2H3/t5-,6+,7+/m1/s1 + +> +InChI=1S/C7H14BrClO/c1-5(9)3-7(8)4-6(2)10/h5-7,10H,3-4H2,1-2H3/t5-,6-,7-/m1/s1(5)2(7)3(6) + +> +6EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 10 9 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 250 -700 0 0 +M V30 2 C 302.2857 -670.5686 0 0 +M V30 3 C 353.9169 -701.1337 0 0 +M V30 4 C 406.2026 -671.7023 0 0 +M V30 5 C 457.8337 -702.2673 0 0 +M V30 6 C 510.1194 -672.8359 0 0 +M V30 7 C 561.7506 -703.4009 0 0 +M V30 8 Cl 302.9404 -610.5721 0 0 +M V30 9 Br 406.8572 -611.7058 0 0 +M V30 10 O 510.7741 -612.8395 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 2 3 +M V30 3 1 2 8 CFG=1 +M V30 4 1 3 4 +M V30 5 1 4 5 +M V30 6 1 4 9 CFG=1 +M V30 7 1 5 6 +M V30 8 1 6 7 +M V30 9 1 6 10 CFG=1 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEABS ATOMS=(1 2) +M V30 MDLV30/STEREL1 ATOMS=(1 4) +M V30 MDLV30/STERAC1 ATOMS=(1 6) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C7H14BrClO/c1-5(9)3-7(8)4-6(2)10/h5-7,10H,3-4H2,1-2H3/t5-,6+,7-/m1/s1 + +> +InChI=1S/C7H14BrClO/c1-5(9)3-7(8)4-6(2)10/h5-7,10H,3-4H2,1-2H3/t5-,6-,7-/m1/s1(5)2(7)3(6) + +> +6EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0 0 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 11 10 0 0 0 +M V30 BEGIN ATOM +M V30 1 C 3.40734 -5.94189 0.0 0 +M V30 2 C 4.27876 -5.45137 0.0 0 CFG=2 +M V30 3 C 5.13929 -5.96079 0.0 0 +M V30 4 C 6.01071 -5.47026 0.0 0 CFG=2 +M V30 5 C 6.87123 -5.97968 0.0 0 +M V30 6 C 7.74266 -5.48916 0.0 0 CFG=2 +M V30 7 C 8.60318 -5.99857 0.0 0 +M V30 8 Cl 4.28968 -4.45143 0.0 0 +M V30 9 Br 6.02162 -4.47032 0.0 0 +M V30 10 O 7.75357 -4.48922 0.0 0 +M V30 11 C 2.54682 -5.43247 0.0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 +M V30 3 1 2 3 +M V30 4 1 2 8 CFG=1 +M V30 5 1 3 4 +M V30 6 1 4 5 +M V30 7 1 4 9 CFG=1 +M V30 8 1 5 6 +M V30 9 1 6 7 +M V30 10 1 6 10 CFG=1 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEABS ATOMS=(3 2 4 6) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C8H16BrClO/c1-3-8(10)5-7(9)4-6(2)11/h6-8,11H,3-5H2,1-2H3/t6-,7-,8+/m0/s1 + +> +InChI=1S/C8H16BrClO/c1-3-8(10)5-7(9)4-6(2)11/h6-8,11H,3-5H2,1-2H3/t6-,7-,8+/m0/s1 + +> +7EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 11 10 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 1012 -1609 0 0 +M V30 2 C 1064.2856 -1579.5686 0 0 +M V30 3 C 1115.9169 -1610.1337 0 0 +M V30 4 C 1168.2026 -1580.7023 0 0 +M V30 5 C 1219.8337 -1611.2673 0 0 +M V30 6 C 1272.1194 -1581.8359 0 0 +M V30 7 C 1323.7506 -1612.4009 0 0 +M V30 8 Cl 1064.9404 -1519.5721 0 0 +M V30 9 Br 1168.8572 -1520.7058 0 0 +M V30 10 O 1272.7742 -1521.8395 0 0 +M V30 11 C 960.3689 -1578.4348 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 +M V30 3 1 2 3 +M V30 4 1 2 8 CFG=3 +M V30 5 1 3 4 +M V30 6 1 4 5 +M V30 7 1 4 9 CFG=3 +M V30 8 1 5 6 +M V30 9 1 6 7 +M V30 10 1 6 10 CFG=3 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEREL1 ATOMS=(2 2 4) +M V30 MDLV30/STERAC1 ATOMS=(1 6) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C8H16BrClO/c1-3-8(10)5-7(9)4-6(2)11/h6-8,11H,3-5H2,1-2H3/t6-,7-,8+/m1/s1 + +> +InChI=1S/C8H16BrClO/c1-3-8(10)5-7(9)4-6(2)11/h6-8,11H,3-5H2,1-2H3/t6-,7-,8+/m0/s2(7,8)3(6) + +> +8EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 11 10 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 1012 -1609 0 0 +M V30 2 C 1064.2856 -1579.5686 0 0 +M V30 3 C 1115.9169 -1610.1337 0 0 +M V30 4 C 1168.2026 -1580.7023 0 0 +M V30 5 C 1219.8337 -1611.2673 0 0 +M V30 6 C 1272.1194 -1581.8359 0 0 +M V30 7 C 1323.7506 -1612.4009 0 0 +M V30 8 Cl 1064.9404 -1519.5721 0 0 +M V30 9 Br 1168.8572 -1520.7058 0 0 +M V30 10 O 1272.7742 -1521.8395 0 0 +M V30 11 C 960.3689 -1578.4348 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 +M V30 3 1 2 3 +M V30 4 1 2 8 CFG=1 +M V30 5 1 3 4 +M V30 6 1 4 5 +M V30 7 1 4 9 CFG=1 +M V30 8 1 5 6 +M V30 9 1 6 7 +M V30 10 1 6 10 CFG=3 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEREL1 ATOMS=(2 2 4) +M V30 MDLV30/STERAC1 ATOMS=(1 6) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C8H16BrClO/c1-3-8(10)5-7(9)4-6(2)11/h6-8,11H,3-5H2,1-2H3/t6-,7+,8-/m1/s1 + +> +InChI=1S/C8H16BrClO/c1-3-8(10)5-7(9)4-6(2)11/h6-8,11H,3-5H2,1-2H3/t6-,7-,8+/m0/s2(7,8)3(6) + +> +8EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 11 10 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 1012 -1609 0 0 +M V30 2 C 1064.2856 -1579.5686 0 0 +M V30 3 C 1115.9169 -1610.1337 0 0 +M V30 4 C 1168.2026 -1580.7023 0 0 +M V30 5 C 1219.8337 -1611.2673 0 0 +M V30 6 C 1272.1194 -1581.8359 0 0 +M V30 7 C 1323.7506 -1612.4009 0 0 +M V30 8 Cl 1064.9404 -1519.5721 0 0 +M V30 9 Br 1168.8572 -1520.7058 0 0 +M V30 10 O 1272.7742 -1521.8395 0 0 +M V30 11 C 960.3689 -1578.4348 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 +M V30 3 1 2 3 +M V30 4 1 2 8 CFG=3 +M V30 5 1 3 4 +M V30 6 1 4 5 +M V30 7 1 4 9 CFG=3 +M V30 8 1 5 6 +M V30 9 1 6 7 +M V30 10 1 6 10 CFG=1 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEREL1 ATOMS=(2 2 4) +M V30 MDLV30/STERAC1 ATOMS=(1 6) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C8H16BrClO/c1-3-8(10)5-7(9)4-6(2)11/h6-8,11H,3-5H2,1-2H3/t6-,7+,8-/m0/s1 + +> +InChI=1S/C8H16BrClO/c1-3-8(10)5-7(9)4-6(2)11/h6-8,11H,3-5H2,1-2H3/t6-,7-,8+/m0/s2(7,8)3(6) + +> +8EN + +$$$$ + + ACD/LABS08242216132D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 11 10 0 0 1 +M V30 BEGIN ATOM +M V30 1 C 1016 -1151 0 0 +M V30 2 C 1068.2856 -1121.5686 0 0 +M V30 3 C 1119.9169 -1152.1337 0 0 +M V30 4 C 1172.2026 -1122.7023 0 0 +M V30 5 C 1223.8337 -1153.2673 0 0 +M V30 6 C 1276.1194 -1123.8359 0 0 +M V30 7 C 1327.7506 -1154.4009 0 0 +M V30 8 Cl 1068.9404 -1061.5721 0 0 +M V30 9 Br 1172.8572 -1062.7058 0 0 +M V30 10 O 1276.7742 -1063.8395 0 0 +M V30 11 C 964.3689 -1120.4348 0 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 11 +M V30 3 1 2 3 +M V30 4 1 2 8 CFG=1 +M V30 5 1 3 4 +M V30 6 1 4 5 +M V30 7 1 4 9 CFG=1 +M V30 8 1 5 6 +M V30 9 1 6 7 +M V30 10 1 6 10 CFG=1 +M V30 END BOND +M V30 BEGIN COLLECTION +M V30 MDLV30/STEREL1 ATOMS=(2 2 4) +M V30 MDLV30/STERAC1 ATOMS=(1 6) +M V30 END COLLECTION +M V30 END CTAB +M END +> +InChI=1S/C8H16BrClO/c1-3-8(10)5-7(9)4-6(2)11/h6-8,11H,3-5H2,1-2H3/t6-,7-,8+/m0/s1 + +> +InChI=1S/C8H16BrClO/c1-3-8(10)5-7(9)4-6(2)11/h6-8,11H,3-5H2,1-2H3/t6-,7-,8+/m0/s2(7,8)3(6) + +> +8EN + +$$$$ diff --git a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp index 7127c739..247a8c97 100644 --- a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp @@ -1,4 +1,5 @@ #include +#include extern "C" { @@ -50,7 +51,6 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_molfile_v2) FreeINCHI(poutput); } - TEST(test_enhancedStereo, test_EnhancedStereochemistry_1) { const char *molblock = @@ -730,3 +730,102 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_2_different_mols_inter_en FreeINCHI(poutput); } + +TEST(test_enhancedStereo, test_EnhancedStereochemistry_test_file_1) +{ + + const char* inchi_filename = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures/enh_stereo_test_file_1.sdf"; + std::ifstream file_inchi(inchi_filename); + + bool file_is_open = file_inchi.is_open(); + EXPECT_EQ(true, file_is_open); + + // Read the whole file into a string + std::stringstream buffer; + buffer << file_inchi.rdbuf(); + std::string file_content = buffer.str(); + + // Split on "$$$$" + std::vector molblocks; + size_t pos = 0; + size_t prev = 0; + const std::string delimiter = "$$$$"; + while ((pos = file_content.find(delimiter, prev)) != std::string::npos) { + std::string mol = file_content.substr(prev, pos - prev); + // Optionally trim whitespace + size_t first_non_ws = mol.find_first_not_of(" \t\r\n"); + if (first_non_ws != std::string::npos) { + mol = mol.substr(first_non_ws); + molblocks.push_back(mol); + } + prev = pos + delimiter.length(); + } + // Add the last block if any + std::string mol = file_content.substr(prev); + size_t first_non_ws = mol.find_first_not_of(" \t\r\n"); + if (first_non_ws != std::string::npos) { + mol = mol.substr(first_non_ws); + molblocks.push_back(mol); + } + + std::vector list_expected_inchis = { + "InChI=1B/C5H13NO/c1-3-5(6)4(2)7/h4-5,7H,3,6H2,1-2H3/t4-,5-/m1/s1", + "InChI=1B/C4H10O/c1-3-4(2)5/h4-5H,3H2,1-2H3/t4-/m0/s2(4)", + "InChI=1B/C5H13NO/c1-3-5(6)4(2)7/h4-5,7H,3,6H2,1-2H3/t4-,5-/m0/s2(4,5)", + "InChI=1B/C4H10O/c1-3-4(2)5/h4-5H,3H2,1-2H3/t4-/m1/s1", + "InChI=1B/C5H13NO/c1-3-5(6)4(2)7/h4-5,7H,3,6H2,1-2H3/t4-,5-/m0/s2(4)(5)", + "InChI=1B/C5H13NO/c1-3-5(6)4(2)7/h4-5,7H,3,6H2,1-2H3", + "InChI=1B/C5H13NO/c1-3-5(6)4(2)7/h4-5,7H,3,6H2,1-2H3/t4-,5-/m0/s3(4,5)", + "InChI=1B/C4H10O/c1-3-4(2)5/h4-5H,3H2,1-2H3/t4-/m0/s3(4)", + "InChI=1B/C4H10O/c1-3-4(2)5/h4-5H,3H2,1-2H3", + "InChI=1B/C5H13NO/c1-3-5(6)4(2)7/h4-5,7H,3,6H2,1-2H3/t4-,5-/m0/s3(4)(5)", + "InChI=1B/C6H12O3/c7-4-1-2-5(8)6(9)3-4/h4-9H,1-3H2/t4-,5+,6-/m0/s1(4,5)2(6)", + "InChI=1B/C6H12O3/c7-4-1-2-5(8)6(9)3-4/h4-9H,1-3H2/t4-,5+,6?/m0/s1", + "InChI=1B/C6H12O3/c7-4-1-2-5(8)6(9)3-4/h4-9H,1-3H2/t4-,5-,6+/m0/s1(4)2(5,6)", + "InChI=1B/C6H12O3/c7-4-1-2-5(8)6(9)3-4/h4-9H,1-3H2/t4-,5?,6?/m0/s1", + "InChI=1B/C6H12O3/c7-4-1-2-5(8)6(9)3-4/h4-9H,1-3H2/t4-,5-,6-/m0/s1(4)2(5,6)", + "InChI=1B/C7H17NO/c1-4-5(2)7(8)6(3)9/h5-7,9H,4,8H2,1-3H3/t5-,6-,7+/m1/s1(6)2(5,7)", + "InChI=1B/C7H17NO/c1-4-5(2)7(8)6(3)9/h5-7,9H,4,8H2,1-3H3/t5?,6-,7?/m1/s1", + "InChI=1B/C7H17NO/c1-4-5(2)7(8)6(3)9/h5-7,9H,4,8H2,1-3H3/t5-,6-,7-/m1/s1(6)2(5,7)", + "InChI=1B/C6H12O3/c7-4-1-2-5(8)6(9)3-4/h4-9H,1-3H2/t4-,5-,6-/m0/s1(4)2(6)(5)", + "InChI=1B/C5H13NO/c1-3-5(6)4(2)7/h4-5,7H,3,6H2,1-2H3/t4-,5-/m1/s1(4)3(5)", + "InChI=1B/C5H13NO/c1-3-5(6)4(2)7/h4-5,7H,3,6H2,1-2H3/t4-,5?/m0/s3(4)", + "InChI=1B/C6H12O3/c7-4-1-2-5(8)6(9)3-4/h4-9H,1-3H2/t4-,5-,6-/m0/s1(4)3(5,6)", + "InChI=1B/C6H12O3/c7-4-1-2-5(8)6(9)3-4/h4-9H,1-3H2/t4-,5-,6+/m0/s1(4)3(5,6)", + "InChI=1B/C6H12O3/c7-4-1-2-5(8)6(9)3-4/h4-9H,1-3H2/t4-,5?,6?/m0/s3(4)", + "InChI=1B/C7H17NO/c1-4-5(2)7(8)6(3)9/h5-7,9H,4,8H2,1-3H3/t5?,6-,7?/m0/s3(6)", + "InChI=1B/C7H17NO/c1-4-5(2)7(8)6(3)9/h5-7,9H,4,8H2,1-3H3/t5-,6-,7-/m1/s1(6)3(5,7)", + "InChI=1B/C7H17NO/c1-4-5(2)7(8)6(3)9/h5-7,9H,4,8H2,1-3H3/t5-,6-,7+/m1/s1(6)3(5,7)", + "InChI=1B/C6H12O3/c7-4-1-2-5(8)6(9)3-4/h4-9H,1-3H2/t4-,5-,6-/m0/s1(4)3(6)(5)", + "InChI=1B/C6H12O3/c7-4-1-2-5(8)6(9)3-4/h4-9H,1-3H2/t4-,5-,6-/m0/s1(4)2(5)3(6)", + "InChI=1B/C5H13NO/c1-3-5(6)4(2)7/h4-5,7H,3,6H2,1-2H3/t4-,5?/m1/s1", + "InChI=1B/C5H13NO/c1-3-5(6)4(2)7/h4-5,7H,3,6H2,1-2H3/t4-,5?/m0/s3(4)", + "InChI=1B/C5H13NO/c1-3-5(6)4(2)7/h4-5,7H,3,6H2,1-2H3/t4-,5?/m0/s2(4)", + "InChI=1B/C6H12O3/c7-4-1-2-5(8)6(9)3-4/h4-9H,1-3H2", + }; + + int nof_inchis = 33; + + EXPECT_EQ(nof_inchis, molblocks.size()); + EXPECT_EQ(nof_inchis, list_expected_inchis.size()); + + char options[] = "-EnhancedStereochemistry"; + for (int i = 0; i < nof_inchis; ++i) { + inchi_Output output; + inchi_Output* poutput = &output; + int ret = MakeINCHIFromMolfileText(molblocks[i].c_str(), options, poutput); + // Use your expected return code and InChI string + if (poutput->szLog && strlen(poutput->szLog) > 0) { + printf("ret: %d %s\n", i, list_expected_inchis[i].c_str()); + printf("%s\n", poutput->szLog); + EXPECT_EQ(ret, 1); + } else { + EXPECT_EQ(ret, 0); + } + + EXPECT_STREQ(poutput->szInChI, list_expected_inchis[i].c_str()); + FreeINCHI(poutput); + } + + file_inchi.close(); +} diff --git a/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp b/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp index e9d9d4a8..64e5c066 100644 --- a/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_ichiprt2.cpp @@ -183,3 +183,204 @@ TEST(test_ichiprt2, Eql_INChI_Stereo_sp3_not_equal) EXPECT_EQ(Eql_INChI_Stereo(&s1, EQL_SP3, &s2, EQL_SP3, 0), 0); } +TEST(test_ichiprt2, test_compare_ints_basic) +{ + int a = 5, b = 10, c = 5; + + // a < b + EXPECT_LT(compare_ints(&a, &b), 0); + + // b > a + EXPECT_GT(compare_ints(&b, &a), 0); + + // a == c + EXPECT_EQ(compare_ints(&a, &c), 0); +} + +TEST(test_ichiprt2, MakeNumber_EnhStereo_decimal) +{ + INCHI_IOS_STRING strbuf = {0}; + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + + int bOverflow = 0; + int nCtMode = 0; // decimal mode + + int n = MakeNumber_EnhStereo(42, ",", &strbuf, nCtMode, &bOverflow); + + EXPECT_EQ(bOverflow, 0); + EXPECT_EQ(std::string(strbuf.pStr), "42,"); + EXPECT_EQ(n, 3); + + inchi_strbuf_close(&strbuf); +} + +TEST(test_ichiprt2, MakeNumber_EnhStereo_abc) +{ + INCHI_IOS_STRING strbuf = {0}; + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + int bOverflow = 0; + int nCtMode = CT_MODE_ABC_NUMBERS; // alphabetic mode + + int n = MakeNumber_EnhStereo(28, ";", &strbuf, nCtMode, &bOverflow); + + EXPECT_EQ(bOverflow, 0); + // 28 in base-27 is "aa", so expect "Aa;" + EXPECT_EQ(std::string(strbuf.pStr), "Aa;"); + EXPECT_EQ(n, 3); + + inchi_strbuf_close(&strbuf); +} + +TEST(test_ichiprt2, MakeEnhStereoString_basic) +{ + // Setup INChI_Aux with 3 atoms, canonical numbers 1, 2, 3 + INChI_Aux aux = {0}; + AT_NUMB orig_atoms[] = {1, 2, 3}; + aux.nNumberOfAtoms = 3; + aux.nOrigAtNosInCanonOrd = orig_atoms; + + // Enhanced stereo group: one group, 3 atoms (original numbers 1,2,3) + int group1[] = {0, 3, 1, 2, 3}; // [unused, n_atoms, orig_atom1, orig_atom2, orig_atom3] + int* enh_stereo[1] = {group1}; + + INCHI_IOS_STRING strbuf = {0}; + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + int bOverflow = 0; + int nCtMode = 0; + + int len = MakeEnhStereoString(&aux, &strbuf, "1", enh_stereo, 1, nCtMode, &bOverflow); + + EXPECT_EQ(bOverflow, 0); + EXPECT_EQ(std::string(strbuf.pStr), "1(1,2,3)"); + EXPECT_EQ(len, 8); + + inchi_strbuf_close(&strbuf); +} + +TEST(test_ichiprt2, MakeEnhStereoString_multiple_groups) +{ + INChI_Aux aux = {0}; + AT_NUMB orig_atoms[] = {1, 2, 3, 4}; + aux.nNumberOfAtoms = 4; + aux.nOrigAtNosInCanonOrd = orig_atoms; + + int group1[] = {0, 2, 1, 2}; // [unused, n_atoms, orig_atom1, orig_atom2] + int group2[] = {0, 2, 3, 4}; // [unused, n_atoms, orig_atom3, orig_atom4] + int* enh_stereo[2] = {group1, group2}; + + INCHI_IOS_STRING strbuf = {0}; + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + int bOverflow = 0; + int nCtMode = 0; + + int len = MakeEnhStereoString(&aux, &strbuf, "2", enh_stereo, 2, nCtMode, &bOverflow); + + EXPECT_EQ(bOverflow, 0); + EXPECT_EQ(std::string(strbuf.pStr), "2(1,2)(3,4)"); + EXPECT_EQ(len, 11); + + inchi_strbuf_close(&strbuf); +} + +TEST(test_ichiprt2, MakeEnhStereoString_empty_group) +{ + INChI_Aux aux = {0}; + AT_NUMB orig_atoms[] = {1, 2, 3}; + aux.nNumberOfAtoms = 3; + aux.nOrigAtNosInCanonOrd = orig_atoms; + + // Group with no valid atoms + int group1[] = {0, 2, 99, 100}; // [unused, n_atoms, orig_atom99, orig_atom100] + int* enh_stereo[1] = {group1}; + + INCHI_IOS_STRING strbuf = {0}; + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + int bOverflow = 0; + int nCtMode = 0; + + int len = MakeEnhStereoString(&aux, &strbuf, "3", enh_stereo, 1, nCtMode, &bOverflow); + + EXPECT_EQ(bOverflow, 0); + EXPECT_EQ(std::string(strbuf.pStr), ""); + EXPECT_EQ(len, 0); + + inchi_strbuf_close(&strbuf); +} + +TEST(test_ichiprt2, MakeSlayerString_basic) +{ + // Setup minimal ORIG_ATOM_DATA with V3000 stereo lists + ORIG_ATOM_DATA *oad; + + oad = (ORIG_ATOM_DATA *)inchi_calloc(1, sizeof(ORIG_ATOM_DATA)); + + OAD_V3000 *v3000; + + v3000 = (OAD_V3000 *)inchi_calloc(1, sizeof(OAD_V3000)); + + // One absolute group: 2 atoms (original numbers 1,2) + int group_abs[] = {0, 2, 1, 2}; + v3000->n_steabs = 1; + v3000->lists_steabs = (int**)inchi_calloc(1, sizeof(int*)); + v3000->lists_steabs[0] = group_abs; + + // One relative group: 1 atom (original number 3) + int group_rel[] = {0, 1, 3}; + v3000->n_sterel = 1; + v3000->lists_sterel = (int**)inchi_calloc(1, sizeof(int*)); + v3000->lists_sterel[0] = group_rel; + + // No racemic groups + v3000->n_sterac = 0; + + oad->v3000 = v3000; + + // Setup INCHI_SORT and INChI_Aux + + INCHI_SORT *inchi_sort = (INCHI_SORT*)inchi_calloc(1, sizeof(INCHI_SORT)); + + int num_at = 8; + int num_iso_at = 1; + int alloc_mode = 0; + int bOrigatomflag = 0; + int found_num_bonds = 0; + int found_num_isotopic = 0; + + inp_ATOM *atoms = CreateInpAtom(num_at); + INChI *inchi = Alloc_INChI(atoms, num_at, &found_num_bonds, &found_num_isotopic, 0); + inchi->nNumberOfAtoms = num_at; + + INChI_Aux *pAux = Alloc_INChI_Aux(num_at, num_iso_at, alloc_mode, bOrigatomflag); + pAux->nNumberOfAtoms = 3; + pAux->nOrigAtNosInCanonOrd[0] = 1; + pAux->nOrigAtNosInCanonOrd[1] = 2; + pAux->nOrigAtNosInCanonOrd[2] = 3; + + inchi_sort->pINChI_Aux[0] = pAux; + inchi_sort->pINChI[0] = inchi; + + INCHI_IOS_STRING strbuf = {0}; + inchi_strbuf_init(&strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT); + int bOverflow = 0; + int nCtMode = 0; + + int len = MakeSlayerString(oad, inchi_sort, &strbuf, OUT_TN, 1, nCtMode, &bOverflow); + + EXPECT_EQ(bOverflow, 0); + // Should produce: 1(1,2)2(3) + EXPECT_EQ(std::string(strbuf.pStr), "1(1,2)2(3)"); + EXPECT_EQ(len, 10); + + inchi_free(oad->v3000->lists_steabs); + inchi_free(oad->v3000->lists_sterel); + inchi_free(oad->v3000); + inchi_free(oad); + + inchi_free(inchi_sort); + + inchi_strbuf_close(&strbuf); + + FreeInpAtom(&atoms); + Free_INChI_Aux(&pAux); + Free_INChI(&inchi); +} diff --git a/INCHI-1-TEST/tests/test_unit/test_strutil_enhancedStereo.cpp b/INCHI-1-TEST/tests/test_unit/test_strutil_enhancedStereo.cpp index 0ff3c8ee..328f50f1 100644 --- a/INCHI-1-TEST/tests/test_unit/test_strutil_enhancedStereo.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_strutil_enhancedStereo.cpp @@ -4,10 +4,8 @@ extern "C" { #include "../../../INCHI-1-SRC/INCHI_BASE/src/strutil.h" #include "../../../INCHI-1-SRC/INCHI_BASE/src/ichi_io.h" -// #include "../../../INCHI-1-SRC/INCHI_BASE/src/inpdef.h" } - TEST(test_strutil_enhancedStereo, test_set_EnhancedStereo_t_m_layers_1) { @@ -104,7 +102,7 @@ TEST(test_strutil_enhancedStereo, test_set_EnhancedStereo_t_m_layers_1) pStrErr, bNoWarnings); - + EXPECT_EQ(ret, orig_inp_data->num_inp_atoms); int num_at = orig_inp_data->num_inp_atoms; @@ -162,3 +160,107 @@ TEST(test_strutil_enhancedStereo, test_set_EnhancedStereo_t_m_layers_1) inchi_ios_free_str(&input_stream); } + +TEST(test_strutil_enhancedStereo, test_get_canonical_atom_number_1) +{ + + INChI_Aux aux; + int n_atoms = 5; + AT_NUMB orig_atoms[] = {10, 20, 30, 40, 50}; + aux.nNumberOfAtoms = n_atoms; + aux.nOrigAtNosInCanonOrd = orig_atoms; + + // Should return 1-based canonical atom number for each original atom number + EXPECT_EQ(get_canonical_atom_number(&aux, 10), 1); + EXPECT_EQ(get_canonical_atom_number(&aux, 20), 2); + EXPECT_EQ(get_canonical_atom_number(&aux, 30), 3); + EXPECT_EQ(get_canonical_atom_number(&aux, 40), 4); + EXPECT_EQ(get_canonical_atom_number(&aux, 50), 5); + + // Should return -1 for atom numbers not present + EXPECT_EQ(get_canonical_atom_number(&aux, 99), -1); + EXPECT_EQ(get_canonical_atom_number(&aux, 0), -1); + +} + +TEST(test_strutil_enhancedStereo, test_get_parity_idx_from_canonical_atom_number) +{ + + // Example: canonical atom numbers for a molecule with 4 stereo centers + AT_NUMB nNumber[] = {3, 1, 4, 2}; + int nof_atoms = 4; + + // Should return the index where the canonical atom number is found + EXPECT_EQ(get_parity_idx_from_canonical_atom_number(3, nNumber, nof_atoms), 0); + EXPECT_EQ(get_parity_idx_from_canonical_atom_number(1, nNumber, nof_atoms), 1); + EXPECT_EQ(get_parity_idx_from_canonical_atom_number(4, nNumber, nof_atoms), 2); + EXPECT_EQ(get_parity_idx_from_canonical_atom_number(2, nNumber, nof_atoms), 3); + + // Should return -1 for a canonical atom number not present + EXPECT_EQ(get_parity_idx_from_canonical_atom_number(5, nNumber, nof_atoms), -1); + EXPECT_EQ(get_parity_idx_from_canonical_atom_number(0, nNumber, nof_atoms), -1); +} + +TEST(test_strutil_enhancedStereo, invert_parities_basic) +{ + // Setup INChI_Stereo + INChI_Stereo stereo; + AT_NUMB nNumber[] = {1, 2, 3}; + S_CHAR t_parity[] = {2, 1, 2}; // 2=+, 1=- + stereo.nNumber = nNumber; + stereo.t_parity = t_parity; + stereo.nNumberOfStereoCenters = 3; + stereo.nCompInv2Abs = 1; + + // Setup INChI + INChI inchi = {0}; + inchi.Stereo = &stereo; + + // Setup INChI_Aux + INChI_Aux aux = {0}; + AT_NUMB orig_atoms[] = {1, 2, 3}; + aux.nNumberOfAtoms = 3; + aux.nOrigAtNosInCanonOrd = orig_atoms; + + // Setup list_atoms: one group, 3 atoms (original numbers 1,2,3) + int group1[] = {0, 3, 1, 2, 3}; // [unused, n_atoms, orig_atom1, orig_atom2, orig_atom3] + int* lists[1] = {group1}; + + // Call invert_parities for absolute group + int ret = invert_parities(&inchi, &aux, lists, 1, 1); + + EXPECT_EQ(ret, 0); + + EXPECT_EQ(stereo.t_parity[0], 1); + EXPECT_EQ(stereo.t_parity[1], 2); + EXPECT_EQ(stereo.t_parity[2], 1); + + EXPECT_EQ(stereo.nCompInv2Abs, -1); + + t_parity[0] = 2; + t_parity[1] = 1; + t_parity[2] = 2; + + stereo.nCompInv2Abs = 1; + + ret = invert_parities(&inchi, &aux, lists, 1, 0); + + EXPECT_EQ(ret, 0); + + EXPECT_EQ(stereo.t_parity[0], 1); + EXPECT_EQ(stereo.t_parity[1], 2); + EXPECT_EQ(stereo.t_parity[2], 1); + + EXPECT_EQ(stereo.nCompInv2Abs, 1); + + ret = invert_parities(&inchi, &aux, lists, 1, 0); + + EXPECT_EQ(ret, 0); + + EXPECT_EQ(stereo.t_parity[0], 1); + EXPECT_EQ(stereo.t_parity[1], 2); + EXPECT_EQ(stereo.t_parity[2], 1); + + EXPECT_EQ(stereo.nCompInv2Abs, 1); +} + From 588644623810fc69c83e138c95545bc8c91d23e4 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 2 Feb 2026 14:08:25 +0000 Subject: [PATCH 65/69] added unit test fix for log message in MakeINCHIFromMolfileText --- INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp index 247a8c97..1862bb9d 100644 --- a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp @@ -816,9 +816,12 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_test_file_1) int ret = MakeINCHIFromMolfileText(molblocks[i].c_str(), options, poutput); // Use your expected return code and InChI string if (poutput->szLog && strlen(poutput->szLog) > 0) { - printf("ret: %d %s\n", i, list_expected_inchis[i].c_str()); - printf("%s\n", poutput->szLog); - EXPECT_EQ(ret, 1); + if (strstr(poutput->szLog, "Warning")) { + printf("log: %s", poutput->szLog); + EXPECT_EQ(ret, 1); + } else { + EXPECT_EQ(ret, 0); + } } else { EXPECT_EQ(ret, 0); } From 556adde0a9fdbc78f3a213c179a4b8a1589ed5a9 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Mon, 2 Feb 2026 14:44:36 +0000 Subject: [PATCH 66/69] bug when switching from debug and release... --- .../tests/test_unit/test_enhancedStereo.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp index 1862bb9d..29ec554c 100644 --- a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp @@ -810,9 +810,13 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_test_file_1) EXPECT_EQ(nof_inchis, list_expected_inchis.size()); char options[] = "-EnhancedStereochemistry"; + + for (int i = 0; i < nof_inchis; ++i) { + inchi_Output output; inchi_Output* poutput = &output; + int ret = MakeINCHIFromMolfileText(molblocks[i].c_str(), options, poutput); // Use your expected return code and InChI string if (poutput->szLog && strlen(poutput->szLog) > 0) { @@ -827,8 +831,23 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_test_file_1) } EXPECT_STREQ(poutput->szInChI, list_expected_inchis[i].c_str()); + + if (poutput->szLog) { + free(poutput->szLog); + poutput->szLog = nullptr; + } + if (poutput->szMessage) { + free(poutput->szMessage); + poutput->szMessage = nullptr; + } + // poutput->szMessage = nullptr; + // poutput->szInChI = nullptr; + FreeINCHI(poutput); } + + + file_inchi.close(); } From 7d1fde3dcbef4047502928db4f6103d3b219d760 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Tue, 3 Feb 2026 10:17:37 +0000 Subject: [PATCH 67/69] Fixed unit test for testing batch test_file_1 (sdf) --- .../tests/test_unit/test_enhancedStereo.cpp | 47 +++++++++---------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp index 29ec554c..5709463a 100644 --- a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp @@ -4,6 +4,7 @@ extern "C" { #include "../../../INCHI-1-SRC/INCHI_BASE/src/inchi_api.h" +#include "../../../INCHI-1-SRC/INCHI_BASE/src/mode.h" } TEST(test_enhancedStereo, test_EnhancedStereochemistry_molfile_v2) @@ -734,16 +735,17 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_2_different_mols_inter_en TEST(test_enhancedStereo, test_EnhancedStereochemistry_test_file_1) { - const char* inchi_filename = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures/enh_stereo_test_file_1.sdf"; - std::ifstream file_inchi(inchi_filename); + // const char* inchi_filename = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures/enh_stereo_test_file_1.sdf"; + const char* inchi_filename = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/enh_stereo_test_file_1.sdf"; - bool file_is_open = file_inchi.is_open(); - EXPECT_EQ(true, file_is_open); + std::ifstream file_inchi(inchi_filename, std::ios::binary); + ASSERT_TRUE(file_inchi.is_open()); // Read the whole file into a string std::stringstream buffer; buffer << file_inchi.rdbuf(); std::string file_content = buffer.str(); + file_inchi.close(); // Split on "$$$$" std::vector molblocks; @@ -811,43 +813,36 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_test_file_1) char options[] = "-EnhancedStereochemistry"; - for (int i = 0; i < nof_inchis; ++i) { inchi_Output output; inchi_Output* poutput = &output; + poutput->szLog = nullptr; + poutput->szMessage = nullptr; + poutput->szInChI = nullptr; + int ret = MakeINCHIFromMolfileText(molblocks[i].c_str(), options, poutput); - // Use your expected return code and InChI string - if (poutput->szLog && strlen(poutput->szLog) > 0) { - if (strstr(poutput->szLog, "Warning")) { - printf("log: %s", poutput->szLog); - EXPECT_EQ(ret, 1); - } else { - EXPECT_EQ(ret, 0); - } - } else { - EXPECT_EQ(ret, 0); - } + + EXPECT_LT(ret, 2); EXPECT_STREQ(poutput->szInChI, list_expected_inchis[i].c_str()); if (poutput->szLog) { - free(poutput->szLog); + inchi_free(poutput->szLog); poutput->szLog = nullptr; } if (poutput->szMessage) { - free(poutput->szMessage); + inchi_free(poutput->szMessage); poutput->szMessage = nullptr; } - // poutput->szMessage = nullptr; - // poutput->szInChI = nullptr; + if (poutput->szInChI) { + inchi_free(poutput->szInChI); + poutput->szInChI = nullptr; + } + // // poutput->szMessage = nullptr; + // // poutput->szInChI = nullptr; - FreeINCHI(poutput); + // FreeINCHI(poutput); } - - - - - file_inchi.close(); } From 6f163206b81cbd1c1d3ce05622cebe68bfb08e18 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Tue, 3 Feb 2026 10:32:59 +0000 Subject: [PATCH 68/69] changed directory --- INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp index 5709463a..a4f06fda 100644 --- a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp @@ -735,8 +735,8 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_2_different_mols_inter_en TEST(test_enhancedStereo, test_EnhancedStereochemistry_test_file_1) { - // const char* inchi_filename = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures/enh_stereo_test_file_1.sdf"; - const char* inchi_filename = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/enh_stereo_test_file_1.sdf"; + const char* inchi_filename = "../../../../../INCHI-1-TEST/tests/test_unit/fixtures/enh_stereo_test_file_1.sdf"; + // const char* inchi_filename = "/workspaces/InChI/INCHI-1-TEST/tests/test_unit/fixtures/enh_stereo_test_file_1.sdf"; std::ifstream file_inchi(inchi_filename, std::ios::binary); ASSERT_TRUE(file_inchi.is_open()); @@ -840,9 +840,5 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_test_file_1) inchi_free(poutput->szInChI); poutput->szInChI = nullptr; } - // // poutput->szMessage = nullptr; - // // poutput->szInChI = nullptr; - - // FreeINCHI(poutput); } } From 5cd2aa7891199b048a795477dbf71eb173b807f9 Mon Sep 17 00:00:00 2001 From: Christoph Mueller Date: Wed, 4 Feb 2026 13:48:30 +0000 Subject: [PATCH 69/69] added another unit test for testing enh stereo grps stretching over 2 fragments --- CMakeLists.txt | 1 - .../tests/test_unit/test_enhancedStereo.cpp | 71 ++++++++++++++++++- 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e2b7e9f6..6c407d4c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,4 +22,3 @@ enable_testing() add_subdirectory(INCHI-1-SRC/INCHI_EXE/inchi-1/src) add_subdirectory(INCHI-1-SRC/INCHI_API/libinchi/src) add_subdirectory(INCHI-1-TEST/tests/test_unit) - diff --git a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp index a4f06fda..e35b9cb7 100644 --- a/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp +++ b/INCHI-1-TEST/tests/test_unit/test_enhancedStereo.cpp @@ -516,7 +516,7 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_4_mols) FreeINCHI(poutput); } -TEST(test_enhancedStereo, test_EnhancedStereochemistry_2_mols_inter_enhstereo_grps) +TEST(test_enhancedStereo, test_EnhancedStereochemistry_2_mols_inter_enhstereo_grps_1) { const char *molblock = "my_test_mol \n" @@ -623,6 +623,75 @@ TEST(test_enhancedStereo, test_EnhancedStereochemistry_2_mols_inter_enhstereo_gr FreeINCHI(poutput); } +TEST(test_enhancedStereo, test_EnhancedStereochemistry_2_mols_inter_enhstereo_grps_2) +{ + const char *molblock = + "test_mol \n" + " -INDIGO-02042609012D \n" + " \n" + " 0 0 0 0 0 0 0 0 0 0 0 V3000 \n" + "M V30 BEGIN CTAB \n" + "M V30 COUNTS 18 16 0 0 0 \n" + "M V30 BEGIN ATOM \n" + "M V30 1 C 3.06699 -3.575 0.0 0 \n" + "M V30 2 C 3.93301 -3.075 0.0 0 \n" + "M V30 3 C 4.79904 -3.575 0.0 0 CFG=1 \n" + "M V30 4 C 5.66506 -3.075 0.0 0 CFG=2 \n" + "M V30 5 C 6.53109 -3.575 0.0 0 \n" + "M V30 6 C 7.39711 -3.075 0.0 0 \n" + "M V30 7 C 4.79904 -4.575 0.0 0 \n" + "M V30 8 C 5.66506 -2.075 0.0 0 \n" + "M V30 9 C 3.06699 -8.475 0.0 0 \n" + "M V30 10 C 3.93301 -7.975 0.0 0 CFG=2 \n" + "M V30 11 C 4.79904 -8.475 0.0 0 CFG=2 \n" + "M V30 12 C 5.66506 -7.975 0.0 0 \n" + "M V30 13 C 6.53109 -8.475 0.0 0 \n" + "M V30 14 C 3.93301 -6.975 0.0 0 \n" + "M V30 15 C 4.79904 -9.475 0.0 0 \n" + "M V30 16 C 7.39711 -7.975 0.0 0 \n" + "M V30 17 C 8.26314 -8.475 0.0 0 \n" + "M V30 18 C 9.12916 -7.975 0.0 0 \n" + "M V30 END ATOM \n" + "M V30 BEGIN BOND \n" + "M V30 1 1 1 2 \n" + "M V30 2 1 2 3 \n" + "M V30 3 1 3 4 \n" + "M V30 4 1 4 5 \n" + "M V30 5 1 5 6 \n" + "M V30 6 1 3 7 CFG=1 \n" + "M V30 7 1 4 8 CFG=1 \n" + "M V30 8 1 9 10 \n" + "M V30 9 1 10 11 \n" + "M V30 10 1 11 12 \n" + "M V30 11 1 12 13 \n" + "M V30 12 1 10 14 CFG=1 \n" + "M V30 13 1 11 15 CFG=3 \n" + "M V30 14 1 13 16 \n" + "M V30 15 1 16 17 \n" + "M V30 16 1 17 18 \n" + "M V30 END BOND \n" + "M V30 BEGIN COLLECTION \n" + "M V30 MDLV30/STEABS ATOMS=(2 3 11) \n" + "M V30 MDLV30/STERAC1 ATOMS=(2 4 10) \n" + "M V30 END COLLECTION \n" + "M V30 END CTAB \n" + "M END \n"; + + + char options[] = "-EnhancedStereochemistry"; + inchi_Output output; + inchi_Output *poutput = &output; + const char expected_inchi[] = "InChI=1B/C10H22.C8H18/c1-5-6-7-8-10(4)9(2)3;1-5-7(3)8(4)6-2/h9-10H,5-8H2,1-4H3;7-8H,5-6H2,1-4H3/t10-;7-,8-/m00/s1(10)3(9);1(7)3(8)"; + + EXPECT_EQ(MakeINCHIFromMolfileText(molblock, options, poutput), 0); + EXPECT_STREQ(poutput->szInChI, expected_inchi); + + poutput->szLog = nullptr; + poutput->szMessage = nullptr; + + FreeINCHI(poutput); +} + TEST(test_enhancedStereo, test_EnhancedStereochemistry_2_different_mols_inter_enhstereo_grps) { const char *molblock =