public void S_penta_2_3_diene_expl_h() { var m = new AtomContainer(); m.Atoms.Add(new Atom("C")); m.Atoms.Add(new Atom("C")); m.Atoms.Add(new Atom("C")); m.Atoms.Add(new Atom("C")); m.Atoms.Add(new Atom("C")); m.Atoms.Add(new Atom("H")); m.Atoms.Add(new Atom("H")); m.AddBond(m.Atoms[0], m.Atoms[1], BondOrder.Single); m.AddBond(m.Atoms[1], m.Atoms[2], BondOrder.Double); m.AddBond(m.Atoms[2], m.Atoms[3], BondOrder.Double); m.AddBond(m.Atoms[3], m.Atoms[4], BondOrder.Single); m.AddBond(m.Atoms[1], m.Atoms[5], BondOrder.Single); m.AddBond(m.Atoms[3], m.Atoms[6], BondOrder.Single); var atoms = new int[][] { new[] { 0, 5, 6, 4 }, new[] { 5, 0, 6, 4 }, new[] { 5, 0, 4, 6 }, new[] { 0, 5, 4, 6 }, new[] { 4, 6, 5, 0 }, new[] { 4, 6, 0, 5 }, new[] { 6, 4, 0, 5 }, new[] { 6, 4, 5, 0 }, }; var stereos = new TetrahedralStereo[] { TetrahedralStereo.Clockwise, TetrahedralStereo.AntiClockwise, TetrahedralStereo.Clockwise, TetrahedralStereo.AntiClockwise, TetrahedralStereo.Clockwise, TetrahedralStereo.AntiClockwise, TetrahedralStereo.Clockwise, TetrahedralStereo.AntiClockwise }; for (int i = 0; i < atoms.Length; i++) { var element = new ExtendedTetrahedral(m.Atoms[2], new IAtom[] { m.Atoms[atoms[i][0]], m.Atoms[atoms[i][1]], m.Atoms[atoms[i][2]], m.Atoms[atoms[i][3]] }, stereos[i]); m.SetStereoElements(new[] { element }); Assert.AreEqual("CC(=[C@]=C(C)[H])[H]", Convert(m, SmiFlavors.Stereo).ToSmiles()); } }
public void R_penta_2_3_diene() { var parser = new InChIToStructure("InChI=1S/C5H8/c1-3-5-4-2/h3-4H,1-2H3/t5-/m0/s1", CDK.Builder); var container = parser.AtomContainer; var ses = container.StereoElements.GetEnumerator(); Assert.IsInstanceOfType(container, CDK.Builder.NewAtomContainer().GetType()); var f = ses.MoveNext(); Assert.IsTrue(f); var se = ses.Current; Assert.IsInstanceOfType(se, typeof(ExtendedTetrahedral)); ExtendedTetrahedral element = (ExtendedTetrahedral)se; Assert.IsTrue( Compares.AreEqual( new IAtom[] { container.Atoms[5], container.Atoms[0], container.Atoms[1], container.Atoms[6] }, element.Peripherals)); Assert.AreEqual(container.Atoms[4], element.Focus); Assert.AreEqual(TetrahedralStereo.AntiClockwise, element.Winding); }
/// <summary> /// Add extended tetrahedral stereo configuration to the Beam GraphBuilder. /// </summary> /// <param name="et">stereo element specifying tetrahedral configuration</param> /// <param name="gb">the current graph builder</param> /// <param name="indices">atom indices</param> private static void AddExtendedTetrahedralConfiguration(ExtendedTetrahedral et, GraphBuilder gb, Dictionary <IAtom, int> indices) { var ligands = et.Peripherals; var u = indices[et.Focus]; var vs = new int[] { indices[ligands[0]], indices[ligands[1]], indices[ligands[2]], indices[ligands[3]], }; gb.CreateExtendedTetrahedral(u).LookingFrom(vs[0]).Neighbors(vs[1], vs[2], vs[3]) .Winding(et.Winding == TetrahedralStereo.Clockwise ? Beam.Configuration.Clockwise : Beam.Configuration.AntiClockwise).Build(); }
// why it does not work? [TestMethod()] public void S_penta_2_3_diene_expl_h() { var m = builder.NewAtomContainer(); m.Atoms.Add(builder.NewAtom("CH3")); m.Atoms.Add(builder.NewAtom("C")); m.Atoms.Add(builder.NewAtom("C")); m.Atoms.Add(builder.NewAtom("C")); m.Atoms.Add(builder.NewAtom("CH3")); m.Atoms.Add(builder.NewAtom("H")); m.Atoms.Add(builder.NewAtom("H")); m.AddBond(m.Atoms[0], m.Atoms[1], BondOrder.Single); m.AddBond(m.Atoms[1], m.Atoms[2], BondOrder.Double); m.AddBond(m.Atoms[2], m.Atoms[3], BondOrder.Double); m.AddBond(m.Atoms[3], m.Atoms[4], BondOrder.Single); m.AddBond(m.Atoms[1], m.Atoms[5], BondOrder.Single); m.AddBond(m.Atoms[3], m.Atoms[6], BondOrder.Single); int[][] atoms = new int[][] { new[] { 0, 5, 6, 4 }, new[] { 5, 0, 6, 4 }, new[] { 5, 0, 4, 6 }, new[] { 0, 5, 4, 6 }, new[] { 4, 6, 5, 0 }, new[] { 4, 6, 0, 5 }, new[] { 6, 4, 0, 5 }, new[] { 6, 4, 5, 0 }, }; var stereos = new TetrahedralStereo[] { TetrahedralStereo.Clockwise, TetrahedralStereo.Clockwise, TetrahedralStereo.Clockwise, TetrahedralStereo.AntiClockwise, TetrahedralStereo.Clockwise, TetrahedralStereo.AntiClockwise, TetrahedralStereo.Clockwise, TetrahedralStereo.Clockwise, }; for (int i = 0; i < atoms.Length; i++) { var element = new ExtendedTetrahedral( m.Atoms[2], new IAtom[] { m.Atoms[atoms[i][0]], m.Atoms[atoms[i][1]], m.Atoms[atoms[i][2]], m.Atoms[atoms[i][3]] }, stereos[i]); m.SetStereoElements(new[] { element }); var generator = factory.GetInChIGenerator(m); Assert.AreEqual("InChI=1S/C5H8/c1-3-5-4-2/h3-4H,1-2H3/t5-/m1/s1", generator.InChI); } }
public void ExtendedTetrahedral_cw() { IAtomContainer ac = Convert("CC=[C@@]=CC"); var elements = ac.StereoElements.GetEnumerator(); Assert.IsTrue(elements.MoveNext()); var element = elements.Current; Assert.IsInstanceOfType(element, typeof(ExtendedTetrahedral)); ExtendedTetrahedral extendedTetrahedral = (ExtendedTetrahedral)element; Assert.AreEqual(TetrahedralStereo.Clockwise, extendedTetrahedral.Winding); Assert.AreEqual(ac.Atoms[2], extendedTetrahedral.Focus); Assert.IsTrue(Compares.AreEqual( new IAtom[] { ac.Atoms[0], ac.Atoms[1], ac.Atoms[3], ac.Atoms[4] }, extendedTetrahedral.Peripherals)); }
public void S_penta_2_3_diene_impl_h() { var m = new AtomContainer(); m.Atoms.Add(new Atom("C")); m.Atoms.Add(new Atom("C")); m.Atoms.Add(new Atom("C")); m.Atoms.Add(new Atom("C")); m.Atoms.Add(new Atom("C")); m.AddBond(m.Atoms[0], m.Atoms[1], BondOrder.Single); m.AddBond(m.Atoms[1], m.Atoms[2], BondOrder.Double); m.AddBond(m.Atoms[2], m.Atoms[3], BondOrder.Double); m.AddBond(m.Atoms[3], m.Atoms[4], BondOrder.Single); var element = new ExtendedTetrahedral(m.Atoms[2], new IAtom[] { m.Atoms[0], m.Atoms[1], m.Atoms[3], m.Atoms[4] }, TetrahedralStereo.Clockwise); m.SetStereoElements(new[] { element }); Assert.AreEqual("CC=[C@@]=CC", Convert(m, SmiFlavors.Stereo).ToSmiles()); }
/// <summary> /// Gets structure from InChI, and converts InChI library data structure into an IAtomContainer. /// </summary> /// <param name="builder"></param> private void GenerateAtomContainerFromInChI(IChemObjectBuilder builder) { try { output = NInchiWrapper.GetStructureFromInchi(input); } catch (NInchiException jie) { throw new CDKException("Failed to convert InChI to molecule: " + jie.Message, jie); } //molecule = new AtomContainer(); AtomContainer = builder.NewAtomContainer(); var inchiCdkAtomMap = new Dictionary <NInchiAtom, IAtom>(); for (int i = 0; i < output.Atoms.Count; i++) { var iAt = output.Atoms[i]; var cAt = builder.NewAtom(); inchiCdkAtomMap[iAt] = cAt; cAt.Id = "a" + i; cAt.Symbol = iAt.ElementType; cAt.AtomicNumber = PeriodicTable.GetAtomicNumber(cAt.Symbol); // Ignore coordinates - all zero - unless aux info was given... but // the CDK doesn't have an API to provide that // InChI does not have unset properties so we set charge, // hydrogen count (implicit) and isotopic mass cAt.FormalCharge = iAt.Charge; cAt.ImplicitHydrogenCount = iAt.ImplicitH; var isotopicMass = iAt.IsotopicMass; if (isotopicMass != 0) { if (ISOTOPIC_SHIFT_FLAG == (isotopicMass & ISOTOPIC_SHIFT_FLAG)) { try { var massNumber = CDK.IsotopeFactory.GetMajorIsotope(cAt.AtomicNumber).MassNumber.Value; cAt.MassNumber = massNumber + (isotopicMass - ISOTOPIC_SHIFT_FLAG); } catch (IOException e) { throw new CDKException("Could not load Isotopes data", e); } } else { cAt.MassNumber = isotopicMass; } } AtomContainer.Atoms.Add(cAt); cAt = AtomContainer.Atoms[AtomContainer.Atoms.Count - 1]; for (int j = 0; j < iAt.ImplicitDeuterium; j++) { var deut = builder.NewAtom(); deut.AtomicNumber = 1; deut.Symbol = "H"; deut.MassNumber = 2; deut.ImplicitHydrogenCount = 0; AtomContainer.Atoms.Add(deut); deut = AtomContainer.Atoms[AtomContainer.Atoms.Count - 1]; var bond = builder.NewBond(cAt, deut, BondOrder.Single); AtomContainer.Bonds.Add(bond); } for (int j = 0; j < iAt.ImplicitTritium; j++) { var trit = builder.NewAtom(); trit.AtomicNumber = 1; trit.Symbol = "H"; trit.MassNumber = 3; trit.ImplicitHydrogenCount = 0; AtomContainer.Atoms.Add(trit); trit = AtomContainer.Atoms[AtomContainer.Atoms.Count - 1]; var bond = builder.NewBond(cAt, trit, BondOrder.Single); AtomContainer.Bonds.Add(bond); } } for (int i = 0; i < output.Bonds.Count; i++) { var iBo = output.Bonds[i]; var atO = inchiCdkAtomMap[iBo.OriginAtom]; var atT = inchiCdkAtomMap[iBo.TargetAtom]; var cBo = builder.NewBond(atO, atT); var type = iBo.BondType; switch (type) { case INCHI_BOND_TYPE.Single: cBo.Order = BondOrder.Single; break; case INCHI_BOND_TYPE.Double: cBo.Order = BondOrder.Double; break; case INCHI_BOND_TYPE.Triple: cBo.Order = BondOrder.Triple; break; case INCHI_BOND_TYPE.Altern: cBo.IsAromatic = true; break; default: throw new CDKException("Unknown bond type: " + type); } var stereo = iBo.BondStereo; switch (stereo) { // No stereo definition case INCHI_BOND_STEREO.None: cBo.Stereo = BondStereo.None; break; // Bond ending (fat end of wedge) below the plane case INCHI_BOND_STEREO.Single1Down: cBo.Stereo = BondStereo.Down; break; // Bond ending (fat end of wedge) above the plane case INCHI_BOND_STEREO.Single1Up: cBo.Stereo = BondStereo.Up; break; // Bond starting (pointy end of wedge) below the plane case INCHI_BOND_STEREO.Single2Down: cBo.Stereo = BondStereo.DownInverted; break; // Bond starting (pointy end of wedge) above the plane case INCHI_BOND_STEREO.Single2Up: cBo.Stereo = BondStereo.UpInverted; break; // Bond with undefined stereochemistry case INCHI_BOND_STEREO.Single1Either: case INCHI_BOND_STEREO.DoubleEither: cBo.Stereo = BondStereo.None; break; } AtomContainer.Bonds.Add(cBo); } for (int i = 0; i < output.Stereos.Count; i++) { var stereo0d = output.Stereos[i]; if (stereo0d.StereoType == INCHI_STEREOTYPE.Tetrahedral || stereo0d.StereoType == INCHI_STEREOTYPE.Allene) { var central = stereo0d.CentralAtom; var neighbours = stereo0d.Neighbors; var focus = inchiCdkAtomMap[central]; var neighbors = new IAtom[] { inchiCdkAtomMap[neighbours[0]], inchiCdkAtomMap[neighbours[1]], inchiCdkAtomMap[neighbours[2]], inchiCdkAtomMap[neighbours[3]] }; TetrahedralStereo stereo; // as per JNI InChI doc even is clockwise and odd is // anti-clockwise switch (stereo0d.Parity) { case INCHI_PARITY.Odd: stereo = TetrahedralStereo.AntiClockwise; break; case INCHI_PARITY.Even: stereo = TetrahedralStereo.Clockwise; break; default: // CDK Only supports parities of + or - continue; } IStereoElement <IChemObject, IChemObject> stereoElement = null; switch (stereo0d.StereoType) { case INCHI_STEREOTYPE.Tetrahedral: stereoElement = builder.NewTetrahedralChirality(focus, neighbors, stereo); break; case INCHI_STEREOTYPE.Allene: { // The periphals (p<i>) and terminals (t<i>) are refering to // the following atoms. The focus (f) is also shown. // // p0 p2 // \ / // t0 = f = t1 // / \ // p1 p3 var peripherals = neighbors; var terminals = ExtendedTetrahedral.FindTerminalAtoms(AtomContainer, focus); // InChI always provides the terminal atoms t0 and t1 as // periphals, here we find where they are and then add in // the other explicit atom. As the InChI create hydrogens // for stereo elements, there will always we an explicit // atom that can be found - it may be optionally suppressed // later. // not much documentation on this (at all) but they appear // to always be the middle two atoms (index 1, 2) we therefore // test these first - but handle the other indices just in // case foreach (var terminal in terminals) { if (peripherals[1].Equals(terminal)) { peripherals[1] = FindOtherSinglyBonded(AtomContainer, terminal, peripherals[0]); } else if (peripherals[2].Equals(terminal)) { peripherals[2] = FindOtherSinglyBonded(AtomContainer, terminal, peripherals[3]); } else if (peripherals[0].Equals(terminal)) { peripherals[0] = FindOtherSinglyBonded(AtomContainer, terminal, peripherals[1]); } else if (peripherals[3].Equals(terminal)) { peripherals[3] = FindOtherSinglyBonded(AtomContainer, terminal, peripherals[2]); } } stereoElement = new ExtendedTetrahedral(focus, peripherals, stereo); } break; } Trace.Assert(stereoElement != null); AtomContainer.StereoElements.Add(stereoElement); } else if (stereo0d.StereoType == INCHI_STEREOTYPE.DoubleBond) { NInchiAtom[] neighbors = stereo0d.Neighbors; // from JNI InChI doc // neighbor[4] : {#X,#A,#B,#Y} in this order // X central_atom : NO_ATOM // \ X Y type : INCHI_StereoType_DoubleBond // A == B \ / // \ A == B // Y var x = inchiCdkAtomMap[neighbors[0]]; var a = inchiCdkAtomMap[neighbors[1]]; var b = inchiCdkAtomMap[neighbors[2]]; var y = inchiCdkAtomMap[neighbors[3]]; // XXX: AtomContainer is doing slow lookup var stereoBond = AtomContainer.GetBond(a, b); stereoBond.SetAtoms(new[] { a, b }); // ensure a is first atom var conformation = DoubleBondConformation.Unset; switch (stereo0d.Parity) { case INCHI_PARITY.Odd: conformation = DoubleBondConformation.Together; break; case INCHI_PARITY.Even: conformation = DoubleBondConformation.Opposite; break; } // unspecified not stored if (conformation.IsUnset()) { continue; } AtomContainer.StereoElements.Add(new DoubleBondStereochemistry(stereoBond, new IBond[] { AtomContainer.GetBond(x, a), AtomContainer.GetBond(b, y) }, conformation)); } else { // TODO - other types of atom parity - double bond, etc } } }
void Main() { IAtomContainer someMolecule = null; StereoElementFactory someFactory = null; { #region IAtomContainer container = someMolecule; StereoElementFactory stereo = StereoElementFactory.Using2DCoordinates(container).InterpretProjections(Projection.Haworth); // set the elements replacing any existing elements container.SetStereoElements(stereo.CreateAll()); // adding elements individually is also possible but existing elements are // are not removed foreach (var element in stereo.CreateAll()) { container.StereoElements.Add(element); } #endregion } { #region CreateTetrahedral_int StereoElementFactory factory = someFactory; // 2D/3D IAtomContainer container = someMolecule; // container for (int v = 0; v < container.Atoms.Count; v++) { // ... verify v is a stereo atom ... ITetrahedralChirality element = factory.CreateTetrahedral(v, null); if (element != null) { container.StereoElements.Add(element); } } #endregion } { #region CreateTetrahedral_IAtom StereoElementFactory factory = someFactory; // 2D/3D IAtomContainer container = someMolecule; // container foreach (var atom in container.Atoms) { // ... verify atom is a stereo atom ... ITetrahedralChirality element = factory.CreateTetrahedral(atom, null); if (element != null) { container.StereoElements.Add(element); } } #endregion } { #region CreateGeometric_IBond StereoElementFactory factory = someFactory; // 2D/3D IAtomContainer container = someMolecule; // container foreach (var bond in container.Bonds) { if (bond.Order != BondOrder.Double) { continue; } // ... verify bond is a stereo bond... IDoubleBondStereochemistry element = factory.CreateGeometric(bond, null); if (element != null) { container.StereoElements.Add(element); } } #endregion } { #region CreateExtendedTetrahedral StereoElementFactory factory = someFactory; // 2D/3D IAtomContainer container = someMolecule; // container for (int v = 0; v < container.Atoms.Count; v++) { // ... verify v is a stereo atom ... ExtendedTetrahedral element = factory.CreateExtendedTetrahedral(v, null); if (element != null) { container.StereoElements.Add(element); } } #endregion } { IAtomContainer container = someMolecule; // container #region InterpretProjections StereoElementFactory factory = StereoElementFactory.Using2DCoordinates(container) .InterpretProjections(Projection.Fischer, Projection.Haworth); #endregion } }