Skip to content

Commit 4738464

Browse files
committed
When deciding which side to place a double bond also consider if a ring contains a metal.
1 parent 834e70e commit 4738464

File tree

2 files changed

+61
-9
lines changed

2 files changed

+61
-9
lines changed

display/renderbasic/src/main/java/org/openscience/cdk/renderer/generators/standard/StandardBondGenerator.java

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1599,7 +1599,7 @@ static Map<IBond, IAtomContainer> ringPreferenceMap(IAtomContainer container,
15991599

16001600
final List<IAtomContainer> rings = AtomContainerSetManipulator.getAllAtomContainers(smallest);
16011601

1602-
Collections.sort(rings, new RingBondOffsetComparator());
1602+
Collections.sort(rings, new RingBondOffsetComparator(container));
16031603

16041604
final Map<IBond, IAtomContainer> ringMap = new HashMap<IBond, IAtomContainer>();
16051605

@@ -1689,29 +1689,52 @@ static final class RingBondOffsetComparator implements Comparator<IAtomContainer
16891689
}
16901690
}
16911691

1692+
private final boolean hasMetal;
1693+
16921694
/**
16931695
* Create a new comparator.
16941696
*/
1695-
RingBondOffsetComparator() {}
1697+
RingBondOffsetComparator(IAtomContainer mol) {
1698+
hasMetal = hasMetal(mol);
1699+
}
1700+
1701+
RingBondOffsetComparator() {
1702+
hasMetal = false;
1703+
}
1704+
1705+
private static boolean hasMetal(IAtomContainer mol) {
1706+
for (IAtom atom : mol.atoms())
1707+
if (Elements.isMetal(atom))
1708+
return true;
1709+
return false;
1710+
}
16961711

16971712
/**
16981713
*{@inheritDoc}
16991714
*/
17001715
@Override
1701-
public int compare(IAtomContainer containerA, IAtomContainer containerB) {
1716+
public int compare(IAtomContainer ringa, IAtomContainer ringb) {
1717+
1718+
// non-metal rings (e.g. carbo/hetro cycles first)
1719+
if (hasMetal) {
1720+
int cmp = Boolean.compare(hasMetal(ringa),
1721+
hasMetal(ringb));
1722+
if (cmp != 0)
1723+
return cmp;
1724+
}
17021725

1703-
// first order by size
1704-
int sizeCmp = Ints.compare(sizePreference(containerA.getAtomCount()),
1705-
sizePreference(containerB.getAtomCount()));
1726+
// order by size 6,5,7,4,3,rest
1727+
int sizeCmp = Ints.compare(sizePreference(ringa.getAtomCount()),
1728+
sizePreference(ringb.getAtomCount()));
17061729
if (sizeCmp != 0) return sizeCmp;
17071730

17081731
// now order by number of double bonds
1709-
int piBondCmp = Ints.compare(nDoubleBonds(containerA), nDoubleBonds(containerB));
1732+
int piBondCmp = Ints.compare(nDoubleBonds(ringa), nDoubleBonds(ringb));
17101733
if (piBondCmp != 0) return -piBondCmp;
17111734

17121735
// order by element frequencies, all carbon rings are preferred
1713-
int[] freqA = countLightElements(containerA);
1714-
int[] freqB = countLightElements(containerB);
1736+
int[] freqA = countLightElements(ringa);
1737+
int[] freqB = countLightElements(ringb);
17151738

17161739
for (Elements element : Arrays.asList(Elements.Carbon, Elements.Nitrogen, Elements.Oxygen, Elements.Sulfur,
17171740
Elements.Phosphorus)) {

display/renderbasic/src/test/java/org/openscience/cdk/renderer/generators/standard/StandardBondGeneratorTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,14 @@
2525
package org.openscience.cdk.renderer.generators.standard;
2626

2727
import org.junit.Test;
28+
import org.openscience.cdk.interfaces.IAtom;
2829
import org.openscience.cdk.interfaces.IAtomContainer;
2930
import org.openscience.cdk.interfaces.IBond;
31+
import org.openscience.cdk.silent.SilentChemObjectBuilder;
32+
import org.openscience.cdk.smiles.SmilesParser;
3033
import org.openscience.cdk.templates.TestMoleculeFactory;
3134

35+
import javax.vecmath.Point2d;
3236
import java.util.Map;
3337

3438
import static org.hamcrest.CoreMatchers.is;
@@ -59,6 +63,31 @@ public void adenineRingPreference() throws Exception {
5963
assertThat(nSize6, is(6));
6064
}
6165

66+
@Test
67+
public void metalRingPreference() throws Exception {
68+
69+
SmilesParser smipar = new SmilesParser(SilentChemObjectBuilder.getInstance());
70+
IAtomContainer mol = smipar.parseSmiles("C1[Fe]C=CC2=C1C=CN2");
71+
for (IAtom atom : mol.atoms())
72+
atom.setPoint2d(new Point2d(0,0));
73+
Map<IBond, IAtomContainer> ringMap = StandardBondGenerator.ringPreferenceMap(mol);
74+
75+
int nSize5 = 0, nSize6 = 0;
76+
for (IBond bond : mol.bonds()) {
77+
IAtomContainer ring = ringMap.get(bond);
78+
// exocyclic bond
79+
if (ring == null) continue;
80+
int size = ring.getAtomCount();
81+
if (size == 5) nSize5++;
82+
if (size == 6) nSize6++;
83+
}
84+
85+
// 5 bonds should point to the six member ring
86+
// 5 bonds should point to the five member ring
87+
assertThat(nSize5, is(5));
88+
assertThat(nSize6, is(5));
89+
}
90+
6291
@Test
6392
public void ringSizePriority() {
6493
assertThat(RingBondOffsetComparator.sizePreference(6), is(0));

0 commit comments

Comments
 (0)