IAtom[] neighbours = stereo.getLigands(); int[] neighbourIdx = new int[neighbours.length]; assert neighbours.length == 4; for (int i = 0; i < 4; i++) { if (stereo.getChiralAtom().equals(neighbours[i])) { neighbourIdx[i] = Integer.MAX_VALUE; } else { return inverted ? stereo.getStereo() : stereo.getStereo().invert();
ITetrahedralChirality mapped = original.map(mapping, Collections.EMPTY_MAP); Assert.assertThat("mapped chiral atom was the same as the original", mapped.getChiralAtom(), is(not(sameInstance(original.getChiralAtom())))); Assert.assertThat("mapped chiral atom was not the clone", mapped.getChiralAtom(), is(sameInstance(c1clone))); IAtom[] originalLigands = original.getLigands(); IAtom[] mappedLigands = mapped.getLigands(); Assert.assertThat("forth mapped ligand was not the clone", mappedLigands[3], is(sameInstance(h5clone))); Assert.assertThat("stereo was not mapped", mapped.getStereo(), is(original.getStereo()));
/** * Verify the tetrahedral stereochemistry (clockwise/anticlockwise) of atom * {@code u} is preserved in the target when the {@code mapping} is used. * * @param u tetrahedral index in the target * @param mapping mapping of vertices * @return the tetrahedral configuration is preserved */ private boolean checkTetrahedral(int u, int[] mapping) { int v = mapping[u]; if (targetTypes[v] != Type.Tetrahedral) return false; ITetrahedralChirality queryElement = (ITetrahedralChirality) queryElements[u]; ITetrahedralChirality targetElement = (ITetrahedralChirality) targetElements[v]; // access neighbors of each element, then map the query to the target int[] us = neighbors(queryElement, queryMap); int[] vs = neighbors(targetElement, targetMap); us = map(u, v, us, mapping); if (us == null) return false; int p = permutationParity(us) * parity(queryElement.getStereo()); int q = permutationParity(vs) * parity(targetElement.getStereo()); return p == q; }
@Override public int compare(IStereoElement o1, IStereoElement o2) { return Ints.compare(mol.indexOf(((ITetrahedralChirality) o1).getChiralAtom()), mol.indexOf(((ITetrahedralChirality) o2).getChiralAtom())); } });
/** * Obtain the number of centres adjacent to the atom at the index, i. * * @param i atom index * @return number of adjacent centres */ private int nAdjacentCentres(int i) { int n = 0; for (IAtom atom : tetrahedralElements[i].getLigands()) if (tetrahedralElements[atomToIndex.get(atom)] != null) n++; return n; }
@Test public void testReading0DStereochemistryWithHydrogen() throws Exception { try (MDLV2000Reader mdlr = new MDLV2000Reader(getClass().getResourceAsStream("/data/mdl/tetrahedral-parity-withExpH.mol"))) { IAtomContainer container = mdlr.read(new AtomContainer()); Iterable<IStereoElement> selements = container.stereoElements(); Iterator<IStereoElement> siter = selements.iterator(); assertTrue(siter.hasNext()); IStereoElement se = siter.next(); assertThat(se, is(instanceOf(ITetrahedralChirality.class))); assertThat(((ITetrahedralChirality) se).getStereo(), is(ITetrahedralChirality.Stereo.ANTI_CLOCKWISE)); assertThat(((ITetrahedralChirality) se).getLigands(), is(new IAtom[]{container.getAtom(0), container.getAtom(2), container.getAtom(3), container.getAtom(4)})); assertFalse(siter.hasNext()); } }
assertThat(se, is(instanceOf(ITetrahedralChirality.class))); ITetrahedralChirality tc = (ITetrahedralChirality) se; assertThat(tc.getChiralAtom(), is(a1)); assertThat(tc.getLigands(), is(new IAtom[]{a2, aNew, a4, a5})); assertFalse(siter.hasNext());
ITetrahedralChirality tc = (ITetrahedralChirality) stereo; IAtom focus = tc.getFocus(); IAtom[] carriers = tc.getCarriers().toArray(new IAtom[4]); IAtom hydrogen = hNeighbor.get(focus); stereos.add(new TetrahedralChirality(focus, carriers, tc.getStereo())); } else { stereos.add(stereo);
@Test public void roundtripAtomParityImplModified() throws Exception { StringWriter sw = new StringWriter(); try (MDLV2000Reader mdlr = new MDLV2000Reader(getClass().getResourceAsStream("/data/mdl/tetrahedral-parity-withImplH.mol")); MDLV2000Writer mdlw = new MDLV2000Writer(sw)) { AtomContainer mol = mdlr.read(new AtomContainer()); ITetrahedralChirality tc = (ITetrahedralChirality) mol.stereoElements().iterator().next(); tc.setStereo(tc.getStereo().invert()); mdlw.write(mol); String output = sw.toString(); assertThat(output, containsString(" 0.0000 0.0000 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0\n")); } }
@Test public void contains() throws Exception { IChemObjectBuilder builder = DefaultChemObjectBuilder.getInstance(); IAtom c1 = builder.newInstance(IAtom.class, "C"); IAtom o2 = builder.newInstance(IAtom.class, "O"); IAtom n3 = builder.newInstance(IAtom.class, "N"); IAtom c4 = builder.newInstance(IAtom.class, "C"); IAtom h5 = builder.newInstance(IAtom.class, "H"); // new stereo element ITetrahedralChirality element = new TetrahedralChirality(c1, new IAtom[]{o2, n3, c4, h5}, Stereo.CLOCKWISE); assertTrue(element.contains(c1)); assertTrue(element.contains(o2)); assertTrue(element.contains(n3)); assertTrue(element.contains(c4)); assertTrue(element.contains(h5)); assertFalse(element.contains(builder.newInstance(IAtom.class))); assertFalse(element.contains(null)); }
/** * Returns the R or S chirality according to the CIP rules, based on the given * chirality information. * * @param container {@link IAtomContainer} to which the <code>stereoCenter</code> * belongs. * @param stereoCenter Chiral center for which the CIP chirality is to be * determined as {@link ITetrahedralChirality} object. * @return A {@link CIP_CHIRALITY} value. */ public static CIP_CHIRALITY getCIPChirality(IAtomContainer container, ITetrahedralChirality stereoCenter) { // the LigancyFourChirality is kind of redundant but we keep for an // easy way to get the ILigands array LigancyFourChirality tmp = new LigancyFourChirality(container, stereoCenter); Stereo stereo = stereoCenter.getStereo(); int parity = permParity(tmp.getLigands()); if (parity == 0) return CIP_CHIRALITY.NONE; if (parity < 0) stereo = stereo.invert(); if (stereo == Stereo.CLOCKWISE) return CIP_CHIRALITY.R; if (stereo == Stereo.ANTI_CLOCKWISE) return CIP_CHIRALITY.S; return CIP_CHIRALITY.NONE; }
if (element instanceof ITetrahedralChirality) { ITetrahedralChirality tc = (ITetrahedralChirality) element; int idx = map.get(tc.getChiralAtom()); elements[idx] = element; types[idx] = Type.Tetrahedral;
/** * Obtain the number of centres adjacent to the atom at the index, i. * * @param i atom index * @return number of adjacent centres */ private int nAdjacentCentres(int i) { int n = 0; for (IAtom atom : tetrahedralElements[i].getLigands()) if (tetrahedralElements[atomToIndex.get(atom)] != null) n++; return n; }
@Test public void testReading0DStereochemistry() throws Exception { try (MDLV2000Reader mdlr = new MDLV2000Reader(getClass().getResourceAsStream("/data/mdl/tetrahedral-parity-withImplH.mol"))) { IAtomContainer container = mdlr.read(new AtomContainer()); Iterable<IStereoElement> selements = container.stereoElements(); Iterator<IStereoElement> siter = selements.iterator(); assertTrue(siter.hasNext()); IStereoElement se = siter.next(); assertThat(se, is(instanceOf(ITetrahedralChirality.class))); assertThat(((ITetrahedralChirality) se).getStereo(), is(ITetrahedralChirality.Stereo.CLOCKWISE)); assertThat(((ITetrahedralChirality) se).getLigands(), is(new IAtom[]{container.getAtom(1), container.getAtom(3), container.getAtom(4), container.getAtom(0)})); assertFalse(siter.hasNext()); } }
/** * Add tetrahedral stereo configuration to the Beam GraphBuilder. * * @param tc stereo element specifying tetrahedral configuration * @param gb the current graph builder * @param indices atom indices */ private static void addTetrahedralConfiguration(ITetrahedralChirality tc, GraphBuilder gb, Map<IAtom, Integer> indices) { IAtom[] ligands = tc.getLigands(); int u = indices.get(tc.getChiralAtom()); int vs[] = new int[]{indices.get(ligands[0]), indices.get(ligands[1]), indices.get(ligands[2]), indices.get(ligands[3])}; gb.tetrahedral(u).lookingFrom(vs[0]).neighbors(vs[1], vs[2], vs[3]) .winding(tc.getStereo() == CLOCKWISE ? Configuration.CLOCKWISE : Configuration.ANTI_CLOCKWISE).build(); }
/** * Returns the R or S chirality according to the CIP rules, based on the given * chirality information. * * @param container {@link IAtomContainer} to which the <code>stereoCenter</code> * belongs. * @param stereoCenter Chiral center for which the CIP chirality is to be * determined as {@link ITetrahedralChirality} object. * @return A {@link CIP_CHIRALITY} value. */ public static CIP_CHIRALITY getCIPChirality(IAtomContainer container, ITetrahedralChirality stereoCenter) { // the LigancyFourChirality is kind of redundant but we keep for an // easy way to get the ILigands array LigancyFourChirality tmp = new LigancyFourChirality(container, stereoCenter); Stereo stereo = stereoCenter.getStereo(); int parity = permParity(tmp.getLigands()); if (parity == 0) return CIP_CHIRALITY.NONE; if (parity < 0) stereo = stereo.invert(); if (stereo == Stereo.CLOCKWISE) return CIP_CHIRALITY.R; if (stereo == Stereo.ANTI_CLOCKWISE) return CIP_CHIRALITY.S; return CIP_CHIRALITY.NONE; }
if (element instanceof ITetrahedralChirality) { ITetrahedralChirality tc = (ITetrahedralChirality) element; int idx = map.get(tc.getChiralAtom()); elements[idx] = element; types[idx] = Type.Tetrahedral;
/** * Access the neighbors of {@code element} as their indices. * * @param element tetrahedral element * @param map atom index lookup * @return the neighbors */ private int[] neighbors(ITetrahedralChirality element, Map<IAtom, Integer> map) { IAtom[] atoms = element.getLigands(); int[] vs = new int[atoms.length]; for (int i = 0; i < atoms.length; i++) vs[i] = map.get(atoms[i]); return vs; }
/** * Creates a new data model for chirality for the CIP rules based on a chirality definition * in the CDK data model with {@link ITetrahedralChirality}. * * @param container {@link IAtomContainer} to which the chiral atom belongs. * @param cdkChirality {@link ITetrahedralChirality} object specifying the chirality. */ public LigancyFourChirality(IAtomContainer container, ITetrahedralChirality cdkChirality) { this.chiralAtom = cdkChirality.getChiralAtom(); IAtom[] ligandAtoms = cdkChirality.getLigands(); this.ligands = new ILigand[ligandAtoms.length]; VisitedAtoms visitedAtoms = new VisitedAtoms(); for (int i = 0; i < ligandAtoms.length; i++) { // ITetrahedralChirality stores a impl hydrogen as the central atom if (ligandAtoms[i].equals(chiralAtom)) { this.ligands[i] = new ImplicitHydrogenLigand(container, visitedAtoms, chiralAtom); } else { this.ligands[i] = new Ligand(container, visitedAtoms, chiralAtom, ligandAtoms[i]); } } this.stereo = cdkChirality.getStereo(); }
* parity(targetElement.getStereo());