Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions INCHI-1-SRC/INCHI_API/libinchi/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ target_sources(libinchi PRIVATE
${P_IXA}/ixa_read_mol.c
${P_IXA}/ixa_status.c
${P_IXA}/ixa_status.h
${P_BASE}/atropisomers.h
${P_BASE}/atropisomers.c
${P_BASE}/bcf_s.h
${P_BASE}/bcf_s.c
${P_BASE}/extr_ct.h
Expand Down Expand Up @@ -127,6 +129,8 @@ target_sources(libinchi PRIVATE
${P_BASE}/permutation_util.c
${P_BASE}/readinch.c
${P_BASE}/readinch.h
${P_BASE}/ring_detection.c
${P_BASE}/ring_detection.h
${P_BASE}/runichi.c
${P_BASE}/runichi2.c
${P_BASE}/runichi3.c
Expand Down
132 changes: 132 additions & 0 deletions INCHI-1-SRC/INCHI_BASE/src/atropisomers.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@


#include "inpdef.h"
#include "ring_detection.h"


void find_atropisomeric_atoms_and_bonds(inp_ATOM* out_at,
int num_atoms,
RingSystems *ring_result,
ORIG_ATOM_DATA *orig_inp_data,
int *fused_atom_partner) {


printf("-------------------\n");

for (int i = 0; i < num_atoms; i++) {

int atom_id1 = i;
const inp_ATOM atom_i = out_at[atom_id1];

int num_neighbors_i = atom_i.valence;

const AT_NUMB *neighbors = atom_i.neighbor;

if (num_neighbors_i == 3) {
for (int j = 0; j < num_neighbors_i; j++) {

int atom_id2 = neighbors[j];

if (atom_id1 >= atom_id2) {
continue;
}

const inp_ATOM atom_j = out_at[atom_id2];



int num_neighbors_j = atom_j.valence;

if (num_neighbors_j == 3 &&
atom_i.bond_stereo[j] == 0 &&
atom_i.bond_type[j] == 1) {

if (ring_result->atom_to_ring_mapping[atom_id1].ring_count > 0 ||
ring_result->atom_to_ring_mapping[atom_id2].ring_count > 0) {

int nof_wedge_bonds_i = 0;
int has_double_bond_i = 0;
for (int k = 0; k < num_neighbors_i; k++) {
if (atom_i.bond_stereo[k] == 1 ||
atom_i.bond_stereo[k] == 4 ||
atom_i.bond_stereo[k] == 6) {
nof_wedge_bonds_i++;
}
if (atom_i.bond_type[k] == 2) {
has_double_bond_i = 1;
}
}
int nof_wedge_bonds_j = 0;
int has_double_bond_j = 0;
for (int k = 0; k < num_neighbors_j; k++) {
if (atom_j.bond_stereo[k] == 1 ||
atom_j.bond_stereo[k] == 4 ||
atom_j.bond_stereo[k] == 6) {
nof_wedge_bonds_j++;
}
if (atom_j.bond_type[k] == 2) {
has_double_bond_j = 1;
}
}

if (nof_wedge_bonds_i > 0 ||
nof_wedge_bonds_j > 0) {

if ((has_double_bond_i || has_double_bond_j)) {
if ((fused_atom_partner[atom_id1] != j &&
fused_atom_partner[atom_id2] != i) ||
(fused_atom_partner[atom_id1] == -1 ||
fused_atom_partner[atom_id2] == -1)) {

if (are_atoms_in_same_small_ring(out_at,
ring_result,
atom_id1, atom_id2,
6) == 0) {
printf(">>> is atropisomer\n");
printf("infos: atom %d with atom %d; bond type %d; bond stereo %d\n",
atom_id1, atom_id2, atom_i.bond_type[j], atom_i.bond_stereo[j]);
// printf("atom type %d %d\n", atom_i.el_number, atom_j.el_number);
// printf("has double bond %d %d\n", has_double_bond_i, has_double_bond_j);
// printf("fused pivot atoms %d %d\n", fused_atom_partner[atom_id1], fused_atom_partner[atom_id2]);

//TODO set atoms with atropisomeric bonds in out_at
orig_inp_data->is_atropisomer = 1;
}
}
}
}
}
}
}
}
}

for (int i = 0; i < ring_result->count; i++) {
const Ring *cur_ring = &ring_result->rings[i];
if (cur_ring->size >= 8) {
int count_single_bonds = 0;
int count_double_bonds = 0;
for (int j = 0; j < cur_ring->size; j++) {
int atom_id1 = cur_ring->atom_ids[j];
int atom_id2 = cur_ring->atom_ids[(j + 1) % cur_ring->size];
const inp_ATOM atom1 = out_at[atom_id1];
for (int k = 0; k < atom1.valence; k++) {
if (atom1.neighbor[k] == atom_id2) {
if (atom1.bond_type[k] == 1) {
count_single_bonds++;
} else if (atom1.bond_type[k] == 2) {
count_double_bonds++;
}
}
}
}

if (cur_ring->is_fused_ring == 0) {
printf(">>> ring id %d size %d nof single bonds %d nof double bonds %d fused ring %d\n",
cur_ring->id, cur_ring->size,
count_single_bonds, count_double_bonds,
cur_ring->is_fused_ring);
}
}
}
}
9 changes: 9 additions & 0 deletions INCHI-1-SRC/INCHI_BASE/src/atropisomers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

#include "inpdef.h"
#include "ring_detection.h"

void find_atropisomeric_atoms_and_bonds(inp_ATOM* out_at,
int num_atoms,
RingSystems *ring_result,
ORIG_ATOM_DATA *orig_inp_data,
int *fused_atom_partner);
3 changes: 2 additions & 1 deletion INCHI-1-SRC/INCHI_BASE/src/ichidrp.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@ typedef struct tagInputParms {
int bMolecularInorganics; /* (@nnuk : Nauman Ullah Khan) :: Varaible for Molecular Inorganics parameter */
int bMolecularInorganicsReconnectedInChI; /* (@nnuk : Nauman Ullah Khan) :: Custom flag to indicate reconnected InChI requirement */

int bEnhancedStereo;
int bEnhancedStereo; /* v. 1.0?+ enable enhanced stereochemistry */
int Atropisomers; /* v. 1.0?+ enable atropisomeric stereochemistry */

/* */
INCHI_MODE bTautFlags;
Expand Down
35 changes: 35 additions & 0 deletions INCHI-1-SRC/INCHI_BASE/src/ichimake.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@

#include "bcf_s.h"

#include "atropisomers.h"
#include "ring_detection.h"

/*
Local functions
*/
Expand Down Expand Up @@ -3901,6 +3904,38 @@ int Create_INChI(CANON_GLOBALS* pCG,
/*fix_odd_things( num_atoms, out_at );*/
#if ( FIND_RING_SYSTEMS == 1 )
MarkRingSystemsInp(out_at, num_atoms, 0);

orig_inp_data->is_atropisomer = 0;
if (ip->Atropisomers) {
RingSystems *ring_result = find_rings(out_at, num_atoms);

// print_ring_result(ring_result);
int fused_atom_partner[num_atoms];
for (i = 0; i < num_atoms; i++) {
// out_at[i].fused_partner_atom_id = -1;
fused_atom_partner[i] = -1;
}
for (i = 0; i < num_atoms; i++) {
for (int j = i + 1; j < num_atoms; j++) {
if(is_fused_ring_pivot(ring_result, out_at, i, j)) {
fused_atom_partner[i] = j;
fused_atom_partner[j] = i;
}
}
}

find_atropisomeric_atoms_and_bonds(out_at, num_atoms, ring_result, orig_inp_data, fused_atom_partner);

//map values to orig_inp_data
if (orig_inp_data->is_atropisomer) {
for (i = 0; i < num_atoms; i++) {
//todo set atoms with atropisomeric bonds in orig_atom_data
}
}

free_ring_system(ring_result);
}

#endif
/* duplicate the preprocessed structure so that all supplied out_norm_data[]->at buffers are filled */
if (out_at != out_norm_data[TAUT_YES]->at && out_norm_data[TAUT_YES]->at)
Expand Down
18 changes: 14 additions & 4 deletions INCHI-1-SRC/INCHI_BASE/src/ichiparm.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ int set_common_options_by_parg(const char* pArg,
int* pbMergeHash,
int* pbHideInChI,
int* pbMolecularInorganics, /* @nnuk */
int* pbEnhancedStereochemistry);
int* pbEnhancedStereochemistry,
int* pbAtropisomers);


/****************************************************************************
Expand Down Expand Up @@ -169,7 +170,8 @@ int set_common_options_by_parg(const char* pArg,
int* pbMergeHash,
int* pbHideInChI,
int* pbMolecularInorganics, /*@nnuk*/
int* pbEnhancedStereochemistry
int* pbEnhancedStereochemistry,
int* pbAtropisomers
)
{
int got = 0;
Expand Down Expand Up @@ -275,6 +277,11 @@ int set_common_options_by_parg(const char* pArg,
*pbEnhancedStereochemistry = 1;
got = 1;
}
else if (!inchi_stricmp(pArg, "Atropisomers"))
{
*pbAtropisomers = 1;
got = 1;
}

#ifndef USE_STDINCHI_API
/* These options DO TURN OFF Std flag */
Expand Down Expand Up @@ -664,6 +671,7 @@ int ReadCommandLineParms(int argc,
int bUnchargedAcidTaut = (CHARGED_SALTS_ONLY == 0);
int bMergeSaltTGroups = (DISCONNECT_SALTS == 1);
int bEnhancedStereochemistry = 0;
int bAtropisomers = 0;
#if ( MIN_SB_RING_SIZE > 0 )
int nMinDbRinSize = MIN_SB_RING_SIZE, mdbr = 0;
#endif
Expand Down Expand Up @@ -816,7 +824,7 @@ int ReadCommandLineParms(int argc,
&bLargeMolecules, &bPolymers,
&bFoldPolymerSRU, &bFrameShiftScheme,
&bStereoAtZz, &bNPZz,
&bNoWarnings, &bMergeHash, &bHideInChI, &bMolecularInorganics, &bEnhancedStereochemistry);
&bNoWarnings, &bMergeHash, &bHideInChI, &bMolecularInorganics, &bEnhancedStereochemistry, &bAtropisomers);
if (got)
{
;
Expand Down Expand Up @@ -1264,7 +1272,7 @@ int ReadCommandLineParms(int argc,
&bLargeMolecules, &bPolymers,
&bFoldPolymerSRU, &bFrameShiftScheme,
&bStereoAtZz, &bNPZz,
&bNoWarnings, &bMergeHash, &bHideInChI, &bMolecularInorganics, &bEnhancedStereochemistry);
&bNoWarnings, &bMergeHash, &bHideInChI, &bMolecularInorganics, &bEnhancedStereochemistry, &bAtropisomers);

if ( got )
{
Expand Down Expand Up @@ -2143,6 +2151,8 @@ int ReadCommandLineParms(int argc,

ip->bEnhancedStereo = bEnhancedStereochemistry;

ip->Atropisomers = bAtropisomers;

return 0;
}

Expand Down
9 changes: 9 additions & 0 deletions INCHI-1-SRC/INCHI_BASE/src/ichiprt1.c
Original file line number Diff line number Diff line change
Expand Up @@ -1623,6 +1623,11 @@ int OutputINChI1( CANON_GLOBALS *pCG,
{
set_EnhancedStereo_t_m_layers(orig_inp_data, pINChI, pINChI_Aux);
}

if (ip->Atropisomers)
{
set_Atropisomer_t_m_layers(orig_inp_data, pINChI, pINChI_Aux);
}
}
}
if (bCompExists)
Expand Down Expand Up @@ -1714,6 +1719,10 @@ int OutputINChI1( CANON_GLOBALS *pCG,
{
is_beta = 1;
}
else if (ip->Atropisomers)
{
is_beta = 1;
}

OutputINCHI_VersionAndKind(out_file, strbuf, bINChIOutputOptions, is_beta, pLF, pTAB);
}
Expand Down
4 changes: 3 additions & 1 deletion INCHI-1-SRC/INCHI_BASE/src/inpdef.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,9 @@ typedef struct tagOrigAtom
OAD_Polymer *polymer;
OAD_V3000 *v3000;
int valid_polymer;
int n_zy; /* number of non-polymeric pseudoatoms (Zy) */
int n_zy; /* number of non-polymeric pseudoatoms (Zy) */

int is_atropisomer; /* flag indicating whether the structure is an atropisomer; it is set to 1 if the structure has been identified as an atropisomer during input processing, and 0 otherwise */

} ORIG_ATOM_DATA;

Expand Down
Loading
Loading