/** * Adjust all double bond elements in the provided structure. <b>IMPORTANT: * up/down labels should be adjusted before adjust double-bond * configurations. coordinates are reflected by this method which can lead * to incorrect tetrahedral specification.</b> * * @param container the structure to adjust * @throws IllegalArgumentException an atom had unset coordinates */ public static IAtomContainer correct(IAtomContainer container) { if (!Iterables.isEmpty(container.stereoElements())) new CorrectGeometricConfiguration(container); return container; }
/** * Adjust all double bond elements in the provided structure. * * @param container the structure to adjust * @param graph the adjacency list representation of the structure * @throws IllegalArgumentException an atom had unset coordinates */ CorrectGeometricConfiguration(IAtomContainer container, int[][] graph) { this.container = container; this.graph = graph; this.visited = new boolean[graph.length]; this.atomToIndex = Maps.newHashMapWithExpectedSize(container.getAtomCount()); this.ringSearch = new RingSearch(container, graph); for (int i = 0; i < container.getAtomCount(); i++) { IAtom atom = container.getAtom(i); atomToIndex.put(atom, i); if (atom.getPoint2d() == null) throw new IllegalArgumentException("atom " + i + " had unset coordinates"); } for (IStereoElement element : container.stereoElements()) { if (element instanceof IDoubleBondStereochemistry) { adjust((IDoubleBondStereochemistry) element); } else if (element instanceof ExtendedCisTrans) { adjust((ExtendedCisTrans) element); } } }
CorrectGeometricConfiguration.correct(mol);
/** * Reflect the atom at index {@code v} and any then reflect any unvisited * neighbors. * * @param v index of the atom to reflect * @param bond bond */ private void reflect(int v, IBond bond) { visited[v] = true; IAtom atom = container.getAtom(v); atom.setPoint2d(reflect(atom.getPoint2d(), bond)); for (int w : graph[v]) { if (!visited[w]) reflect(w, bond); } }
/** * Determine the parity (odd/even) of the triangle formed by the 3 atoms. * * @param atoms array of 3 atoms * @return the parity of the triangle formed by 3 points, odd = -1, even = * +1 */ private static int parity(IAtom[] atoms) { return parity(atoms[0].getPoint2d(), atoms[1].getPoint2d(), atoms[2].getPoint2d()); }
CorrectGeometricConfiguration.correct(mol);
/** * Reflect the atom at index {@code v} and any then reflect any unvisited * neighbors. * * @param v index of the atom to reflect * @param bond bond */ private void reflect(int v, IBond bond) { visited[v] = true; IAtom atom = container.getAtom(v); atom.setPoint2d(reflect(atom.getPoint2d(), bond)); for (int w : graph[v]) { if (!visited[w]) reflect(w, bond); } }
/** * Determine the parity (odd/even) of the triangle formed by the 3 atoms. * * @param atoms array of 3 atoms * @return the parity of the triangle formed by 3 points, odd = -1, even = * +1 */ private static int parity(IAtom[] atoms) { return parity(atoms[0].getPoint2d(), atoms[1].getPoint2d(), atoms[2].getPoint2d()); }
CorrectGeometricConfiguration.correct(molecule);
/** * Reflect the point {@code p} over the {@code bond}. * * @param p the point to reflect * @param bond bond * @return the reflected point */ private Point2d reflect(Point2d p, IBond bond) { IAtom a = bond.getBegin(); IAtom b = bond.getEnd(); return reflect(p, a.getPoint2d().x, a.getPoint2d().y, b.getPoint2d().x, b.getPoint2d().y); }
/** * Adjust all double bond elements in the provided structure. <b>IMPORTANT: * up/down labels should be adjusted before adjust double-bond * configurations. coordinates are reflected by this method which can lead * to incorrect tetrahedral specification.</b> * * @param container the structure to adjust * @throws IllegalArgumentException an atom had unset coordinates */ public static IAtomContainer correct(IAtomContainer container) { if (!Iterables.isEmpty(container.stereoElements())) new CorrectGeometricConfiguration(container); return container; }
/** * Adjust all double bond elements in the provided structure. * * @param container the structure to adjust * @param graph the adjacency list representation of the structure * @throws IllegalArgumentException an atom had unset coordinates */ CorrectGeometricConfiguration(IAtomContainer container, int[][] graph) { this.container = container; this.graph = graph; this.visited = new boolean[graph.length]; this.atomToIndex = Maps.newHashMapWithExpectedSize(container.getAtomCount()); this.ringSearch = new RingSearch(container, graph); for (int i = 0; i < container.getAtomCount(); i++) { IAtom atom = container.getAtom(i); atomToIndex.put(atom, i); if (atom.getPoint2d() == null) throw new IllegalArgumentException("atom " + i + " had unset coordinates"); } for (IStereoElement element : container.stereoElements()) { if (element instanceof IDoubleBondStereochemistry) { adjust((IDoubleBondStereochemistry) element); } else if (element instanceof ExtendedCisTrans) { adjust((ExtendedCisTrans) element); } } }
CorrectGeometricConfiguration.correct(molecule);
/** * Reflect the point {@code p} over the {@code bond}. * * @param p the point to reflect * @param bond bond * @return the reflected point */ private Point2d reflect(Point2d p, IBond bond) { IAtom a = bond.getBegin(); IAtom b = bond.getEnd(); return reflect(p, a.getPoint2d().x, a.getPoint2d().y, b.getPoint2d().x, b.getPoint2d().y); }
@Test public void trans() { IAtomContainer m = new AtomContainer(5, 4, 0, 0); m.addAtom(atom("C", 3, -0.74d, 5.00d)); m.addAtom(atom("C", 1, -1.49d, 3.70d)); m.addAtom(atom("C", 1, -0.74d, 2.40d)); m.addAtom(atom("C", 2, 0.76d, 2.40d)); m.addAtom(atom("C", 3, 1.51d, 1.10d)); m.addBond(0, 1, IBond.Order.SINGLE); m.addBond(1, 2, IBond.Order.DOUBLE); m.addBond(2, 3, IBond.Order.SINGLE); m.addBond(3, 4, IBond.Order.SINGLE); m.addStereoElement(new DoubleBondStereochemistry(m.getBond(1), new IBond[]{m.getBond(0), m.getBond(2)}, OPPOSITE)); CorrectGeometricConfiguration.correct(m); assertPoint(m.getAtom(0), -0.74, 5.0, 0.1); assertPoint(m.getAtom(1), -1.49, 3.7, 0.1); assertPoint(m.getAtom(2), -0.74d, 2.40d, 0.1); assertPoint(m.getAtom(3), -1.49d, 1.10d, 0.1); assertPoint(m.getAtom(4), -0.74d, -0.20d, 0.1); }
@Test public void cis() { IAtomContainer m = new AtomContainer(5, 4, 0, 0); m.addAtom(atom("C", 3, -0.74d, 5.00d)); m.addAtom(atom("C", 1, -1.49d, 3.70d)); m.addAtom(atom("C", 1, -0.74d, 2.40d)); m.addAtom(atom("C", 2, -1.49d, 1.10d)); m.addAtom(atom("C", 3, -0.74d, -0.20d)); m.addBond(0, 1, IBond.Order.SINGLE); m.addBond(1, 2, IBond.Order.DOUBLE); m.addBond(2, 3, IBond.Order.SINGLE); m.addBond(3, 4, IBond.Order.SINGLE); m.addStereoElement(new DoubleBondStereochemistry(m.getBond(1), new IBond[]{m.getBond(0), m.getBond(2)}, TOGETHER)); CorrectGeometricConfiguration.correct(m); assertPoint(m.getAtom(0), -0.74, 5.0, 0.1); assertPoint(m.getAtom(1), -1.49, 3.7, 0.1); assertPoint(m.getAtom(2), -0.74, 2.4, 0.1); assertPoint(m.getAtom(3), 0.76, 2.4, 0.1); assertPoint(m.getAtom(4), 1.51, 1.10, 0.1); }