Skip to content

Commit

Permalink
Allow reading of cumulated double bonds from InChI's
Browse files Browse the repository at this point in the history
  • Loading branch information
johnmay authored and egonw committed Dec 5, 2021
1 parent 5471fae commit 6e01e55
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.openscience.cdk.interfaces.IBond;
import org.openscience.cdk.interfaces.IStereoElement;

import java.util.ArrayList;
import java.util.List;

import static org.openscience.cdk.interfaces.ITetrahedralChirality.Stereo;
Expand Down Expand Up @@ -92,6 +93,45 @@ public static IAtom[] findTerminalAtoms(IAtomContainer container, IBond focus) {
return null;
}

/**
* Locate the central double-bond in a chain of cumulated double bonds.
*
* <pre>
* A = C = C = B
* ^
* A = C = C = C = C = B
* ^
* </pre>
*
* @param mol molecule
* @param atom at atom from either end of the cumulated chains
* @return the central bond, or null if not found
*/
public static IBond findCentralBond(IAtomContainer mol, IAtom atom) {
List<IBond> bonds = new ArrayList<>();
IAtom prevAtom = atom;
IBond prevBond = null;
boolean found;
do {
found = false;
for (IBond bond : mol.getConnectedBondsList(prevAtom)) {
if (prevBond == bond)
continue;
if (bond.getOrder() == IBond.Order.DOUBLE) {
bonds.add(bond);
found = true;
prevBond = bond;
prevAtom = bond.getOther(prevAtom);
break;
}
}
} while (found);
int nbonds = bonds.size();
if ((nbonds&0x1) == 0)
return null; // is even => false
return bonds.get(nbonds/2);
}

/**
* {@inheritDoc}
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import org.openscience.cdk.interfaces.IStereoElement;
import org.openscience.cdk.interfaces.ITetrahedralChirality;
import org.openscience.cdk.stereo.DoubleBondStereochemistry;
import org.openscience.cdk.stereo.ExtendedCisTrans;
import org.openscience.cdk.stereo.ExtendedTetrahedral;
import org.openscience.cdk.tools.periodictable.PeriodicTable;

Expand Down Expand Up @@ -156,6 +157,14 @@ protected InChIToStructure(String inchi, IChemObjectBuilder builder, List<String
generateAtomContainerFromInchi(builder);
}

/**
* Flip the storage order of atoms in a bond.
* @param bond the bond
*/
private void flip(IBond bond) {
bond.setAtoms(new IAtom[]{bond.getEnd(), bond.getBegin()});
}

/**
* Gets structure from InChI, and converts InChI library data structure
* into an IAtomContainer.
Expand Down Expand Up @@ -355,6 +364,7 @@ else if (stereo == INCHI_BOND_STEREO.SINGLE_1EITHER || stereo == INCHI_BOND_STER
assert stereoElement != null;
molecule.addStereoElement(stereoElement);
} else if (stereo0d.getStereoType() == INCHI_STEREOTYPE.DOUBLEBOND) {
boolean extended = false;
JniInchiAtom[] neighbors = stereo0d.getNeighbors();

// from JNI InChI doc
Expand All @@ -369,28 +379,35 @@ else if (stereo == INCHI_BOND_STEREO.SINGLE_1EITHER || stereo == INCHI_BOND_STER
IAtom b = inchiCdkAtomMap.get(neighbors[2]);
IAtom y = inchiCdkAtomMap.get(neighbors[3]);

// XXX: AtomContainer is doing slow lookup
IBond stereoBond = molecule.getBond(a, b);
stereoBond.setAtoms(new IAtom[]{a, b}); // ensure a is first atom

Conformation conformation = null;

switch (stereo0d.getParity()) {
case ODD:
conformation = Conformation.TOGETHER;
break;
case EVEN:
conformation = Conformation.OPPOSITE;
break;
if (stereoBond == null) {
extended = true;
IBond tmp = null;
// A = C = C = B
stereoBond = ExtendedCisTrans.findCentralBond(molecule, a);
if (stereoBond == null)
continue; // warn on invalid input?
IAtom[] ends = ExtendedCisTrans.findTerminalAtoms(molecule, stereoBond);
assert ends != null;
if (ends[0] != a)
flip(stereoBond);
} else {
flip(stereoBond);
}

// unspecified not stored
if (conformation == null) continue;
int config = IStereoElement.TOGETHER;
if (stereo0d.getParity() == INCHI_PARITY.EVEN)
config = IStereoElement.OPPOSITE;

molecule.addStereoElement(new DoubleBondStereochemistry(stereoBond, new IBond[]{molecule.getBond(x, a),
molecule.getBond(b, y)}, conformation));
} else {
// TODO - other types of atom parity - double bond, etc
if (extended) {
molecule.addStereoElement(new ExtendedCisTrans(stereoBond,
new IBond[]{molecule.getBond(x, a),
molecule.getBond(b, y)}, config));
} else {
molecule.addStereoElement(new DoubleBondStereochemistry(stereoBond,
new IBond[]{molecule.getBond(x, a),
molecule.getBond(b, y)}, config));
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,4 +265,20 @@ public void isotope() throws Exception{
assertThat(mol.getAtomCount(), is(1));
assertThat(mol.getAtom(0).getMassNumber(), is(121));
}

@Test
public void testExtendedCisTrans() throws Exception {
IAtomContainer mol = InChIGeneratorFactory.getInstance()
.getInChIToStructure("InChI=1/C4BrClFI/c5-3(8)1-2-4(6)7/b4-3-",
SilentChemObjectBuilder.getInstance()).getAtomContainer();
assertNotNull(mol);
int nExtendedCisTrans = 0;
for (IStereoElement se : mol.stereoElements()) {
if (se.getConfig() != IStereoElement.CU)
nExtendedCisTrans++;
else
Assert.fail("Expected onl extended cis/trans");
}
Assert.assertEquals(1, nExtendedCisTrans);
}
}

0 comments on commit 6e01e55

Please sign in to comment.