public void TestExampleStructure2InchiAlanine() { // START SNIPPET: structure2inchi-alanine // Example input - 0D D-Alanine NInchiInput input = new NInchiInput(); // // Generate atoms NInchiAtom a1 = input.Add(new NInchiAtom(0.0, 0.0, 0.0, "C")); NInchiAtom a2 = input.Add(new NInchiAtom(0.0, 0.0, 0.0, "C")); NInchiAtom a3 = input.Add(new NInchiAtom(0.0, 0.0, 0.0, "N")); NInchiAtom a4 = input.Add(new NInchiAtom(0.0, 0.0, 0.0, "C")); NInchiAtom a5 = input.Add(new NInchiAtom(0.0, 0.0, 0.0, "O")); NInchiAtom a6 = input.Add(new NInchiAtom(0.0, 0.0, 0.0, "O")); NInchiAtom a7 = input.Add(new NInchiAtom(0.0, 0.0, 0.0, "H")); a3.ImplicitH = 2; a4.ImplicitH = 3; a5.ImplicitH = 1; // // Add bonds input.Add(new NInchiBond(a1, a2, INCHI_BOND_TYPE.Single)); input.Add(new NInchiBond(a1, a3, INCHI_BOND_TYPE.Single)); input.Add(new NInchiBond(a1, a4, INCHI_BOND_TYPE.Single)); input.Add(new NInchiBond(a2, a5, INCHI_BOND_TYPE.Single)); input.Add(new NInchiBond(a2, a6, INCHI_BOND_TYPE.Double)); input.Add(new NInchiBond(a1, a7, INCHI_BOND_TYPE.Single)); // // Add stereo parities input.Stereos.Add(NInchiStereo0D .CreateNewTetrahedralStereo0D(a1, a3, a4, a7, a2, INCHI_PARITY.Even)); // NInchiOutput output = NInchiWrapper.GetInchi(input); // END SNIPPET: structure2inchi-alanine }
public void TestGetParity() { NInchiStereo0D stereo = new NInchiStereo0D(atC, at0, at1, at2, at3, INCHI_STEREOTYPE.Tetrahedral, INCHI_PARITY.Even); Assert.AreEqual(INCHI_PARITY.Even, stereo.Parity); stereo = new NInchiStereo0D(atC, at0, at1, at2, at3, INCHI_STEREOTYPE.Tetrahedral, INCHI_PARITY.Odd); Assert.AreEqual(INCHI_PARITY.Odd, stereo.Parity); }
public void TestGetCentralAtom() { NInchiStereo0D stereo = new NInchiStereo0D(null, null, null, null, null, INCHI_STEREOTYPE.None, INCHI_PARITY.None); Assert.IsNull(stereo.CentralAtom); stereo = new NInchiStereo0D(atC, null, null, null, null, INCHI_STEREOTYPE.None, INCHI_PARITY.None); Assert.AreEqual(atC, stereo.CentralAtom); }
public void TestSetDisconnectedParity() { NInchiStereo0D stereo = GetTestStereo0D(); Assert.AreEqual(INCHI_PARITY.None, stereo.DisconnectedParity); stereo.DisconnectedParity = INCHI_PARITY.Even; Assert.AreEqual(INCHI_PARITY.Even, stereo.DisconnectedParity); }
public void TestGetStereoType() { NInchiStereo0D stereo = new NInchiStereo0D(atC, at0, at1, at2, at3, INCHI_STEREOTYPE.Tetrahedral, INCHI_PARITY.Even); Assert.AreEqual(INCHI_STEREOTYPE.Tetrahedral, stereo.StereoType); stereo = new NInchiStereo0D(atC, at0, at1, at2, at3, INCHI_STEREOTYPE.Allene, INCHI_PARITY.Even); Assert.AreEqual(INCHI_STEREOTYPE.Allene, stereo.StereoType); }
public void TestGetStereo0D() { NInchiStructure structure = new NInchiStructure(); NInchiStereo0D stereo = TestNInchiStereo0D.GetTestStereo0D(); structure.Stereos.Add(stereo); Assert.AreEqual(stereo, structure.Stereos[0]); }
/// <summary> /// Convenience method for generating 0D stereo parities at stereogenic /// double bonds. /// </summary> /// <remarks> /// <b>Usage notes from <i>inchi_api.h</i>:</b> /// <pre> /// ============================================= /// stereogenic bond >A=B< or cumulene >A=C=C=B< /// ============================================= /// /// 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 /// /// parity= 'e' parity= 'o' unknown parity = 'u' /// /// ============================================== /// Note. Correspondence to CML 0D stereo parities /// ============================================== /// /// stereogenic double bond and (not yet defined in CML) cumulenes /// ============================================================== /// CML 'C' (cis) <=> INCHI_PARITY_ODD /// CML 'T' (trans) <=> INCHI_PARITY_EVEN /// </pre> /// </remarks> /// <param name="at0">Neighbour atom 0</param> /// <param name="at1">Neighbour atom 1</param> /// <param name="at2">Neighbour atom 2</param> /// <param name="at3">Neighbour atom 3</param> /// <param name="parity">Parity</param> /// <returns></returns> public static NInchiStereo0D CreateNewDoublebondStereo0D(NInchiAtom at0, NInchiAtom at1, NInchiAtom at2, NInchiAtom at3, INCHI_PARITY parity) { NInchiStereo0D stereo = new NInchiStereo0D(null, at0, at1, at2, at3, INCHI_STEREOTYPE.DoubleBond, parity); return(stereo); }
/// <summary> /// Convenience method for generating 0D stereo parities at tetrahedral /// atom centres. ///</summary> /// <remarks> /// <b>Usage notes from <i>inchi_api.h</i>:</b> /// <pre> /// 4 neighbors /// /// X neighbor[4] : {#W, #X, #Y, #Z} /// | central_atom: #A /// W--A--Y type : INCHI_StereoType_Tetrahedral /// | /// Z /// parity: if (X,Y,Z) are clockwize when seen from W then parity is 'e' otherwise 'o' /// Example (see AXYZW above): if W is above the plane XYZ then parity = 'e' /// /// 3 neighbors /// /// Y Y neighbor[4] : {#A, #X, #Y, #Z} /// / / central_atom: #A /// X--A (e.g. O=S ) type : INCHI_StereoType_Tetrahedral /// \ \ /// Z Z /// /// parity: if (X,Y,Z) are clockwize when seen from A then parity is 'e', /// otherwise 'o' /// unknown parity = 'u' /// Example (see AXYZ above): if A is above the plane XYZ then parity = 'e' /// This approach may be used also in case of an implicit H attached to A. /// /// ============================================== /// Note. Correspondence to CML 0D stereo parities /// ============================================== /// a list of 4 atoms corresponds to CML atomRefs4 /// /// tetrahedral atom /// ================ /// CML atomParity > 0 <=> INCHI_PARITY_EVEN /// CML atomParity < 0 <=> INCHI_PARITY_ODD /// /// | 1 1 1 1 | where xW is x-coordinate of /// | xW xX xY xZ | atom W, etc. (xyz is a /// CML atomParity = determinant | yW yX yY yZ | 'right-handed' Cartesian /// | zW zX xY zZ | coordinate system) /// </pre> /// </remarks> /// <param name="atC">Central atom</param> /// <param name="at0">Neighbour atom 0</param> /// <param name="at1">Neighbour atom 1</param> /// <param name="at2">Neighbour atom 2</param> /// <param name="at3">Neighbour atom 3</param> /// <param name="parity">Parity</param> public static NInchiStereo0D CreateNewTetrahedralStereo0D(NInchiAtom atC, NInchiAtom at0, NInchiAtom at1, NInchiAtom at2, NInchiAtom at3, INCHI_PARITY parity) { NInchiStereo0D stereo = new NInchiStereo0D(atC, at0, at1, at2, at3, INCHI_STEREOTYPE.Tetrahedral, parity); return(stereo); }
public void TestGetNeighbors() { NInchiStereo0D stereo = new NInchiStereo0D(atC, at0, at1, at2, at3, INCHI_STEREOTYPE.Tetrahedral, INCHI_PARITY.Even); NInchiAtom[] neighbours = { at0, at1, at2, at3 }; for (int i = 0; i < neighbours.Length; i++) { Assert.AreEqual(neighbours[i], stereo.Neighbors[i]); } }
public void TestJniInchiStereo0D() { NInchiStereo0D stereo = new NInchiStereo0D(atC, at0, at1, at2, at3, INCHI_STEREOTYPE.Tetrahedral, INCHI_PARITY.Odd); Assert.AreEqual(atC, stereo.CentralAtom); NInchiAtom[] neighbors = stereo.Neighbors; Assert.AreEqual(at0, neighbors[0]); Assert.AreEqual(at1, neighbors[1]); Assert.AreEqual(at2, neighbors[2]); Assert.AreEqual(at3, neighbors[3]); Assert.AreEqual(INCHI_STEREOTYPE.Tetrahedral, stereo.StereoType); Assert.AreEqual(INCHI_PARITY.Odd, stereo.Parity); }
private static void CreateStereos(NInchiStructure output, int numstereo, IntPtr intPtrStereos) { var istereos = (Inchi_Stereo0D *)intPtrStereos.ToPointer(); for (int i = 0; i < numstereo; i++) { // jobject atC, an0, an1, an2, an3, stereo; Inchi_Stereo0D istereo = istereos[i]; NInchiAtom atC = null; if (istereo.central_atom != NO_ATOM) { atC = output.Atoms[istereo.central_atom]; } var an0 = output.Atoms[istereo.neighbor[0]]; var an1 = output.Atoms[istereo.neighbor[1]]; var an2 = output.Atoms[istereo.neighbor[2]]; var an3 = output.Atoms[istereo.neighbor[3]]; var stereo = new NInchiStereo0D(atC, an0, an1, an2, an3, (INCHI_STEREOTYPE)istereo.type, (INCHI_PARITY)istereo.parity); output.Stereos.Add(stereo); } }
/// <summary> /// Reads atoms, bonds etc from atom container and converts to format /// InChI library requires, then places call for the library to generate /// the InChI. /// </summary> /// <param name="atomContainer">AtomContainer to generate InChI for.</param> /// <param name="ignore"></param> private void GenerateInChIFromCDKAtomContainer(IAtomContainer atomContainer, bool ignore) { this.ReferringAtomContainer = atomContainer; // Check for 3d coordinates bool all3d = true; bool all2d = true; foreach (var atom in atomContainer.Atoms) { if (all3d && atom.Point3D == null) { all3d = false; } if (all2d && atom.Point2D == null) { all2d = false; } } var atomMap = new Dictionary <IAtom, NInchiAtom>(); foreach (var atom in atomContainer.Atoms) { // Get coordinates // Use 3d if possible, otherwise 2d or none double x, y, z; if (all3d) { var p = atom.Point3D.Value; x = p.X; y = p.Y; z = p.Z; } else if (all2d) { var p = atom.Point2D.Value; x = p.X; y = p.Y; z = 0.0; } else { x = 0.0; y = 0.0; z = 0.0; } // Chemical element symbol var el = atom.Symbol; // Generate InChI atom var iatom = Input.Add(new NInchiAtom(x, y, z, el)); atomMap[atom] = iatom; // Check if charged var charge = atom.FormalCharge.Value; if (charge != 0) { iatom.Charge = charge; } // Check whether isotopic var isotopeNumber = atom.MassNumber; if (isotopeNumber != null) { iatom.IsotopicMass = isotopeNumber.Value; } // Check for implicit hydrogens // atom.HydrogenCount returns number of implicit hydrogens, not // total number // Ref: Posting to cdk-devel list by Egon Willighagen 2005-09-17 int?implicitH = atom.ImplicitHydrogenCount; // set implicit hydrogen count, -1 tells the inchi to determine it iatom.ImplicitH = implicitH ?? -1; // Check if radical int count = atomContainer.GetConnectedSingleElectrons(atom).Count(); if (count == 0) { // TODO - how to check whether singlet or undefined multiplicity } else if (count == 1) { iatom.Radical = INCHI_RADICAL.Doublet; } else if (count == 2) { iatom.Radical = INCHI_RADICAL.Triplet; } else { throw new CDKException("Unrecognised radical type"); } } // Process bonds var bondMap = new Dictionary <IBond, NInchiBond>(); foreach (var bond in atomContainer.Bonds) { // Assumes 2 centre bond var at0 = atomMap[bond.Begin]; var at1 = atomMap[bond.End]; // Get bond order INCHI_BOND_TYPE order; var bo = bond.Order; if (!ignore && bond.IsAromatic) { order = INCHI_BOND_TYPE.Altern; } else if (bo == BondOrder.Single) { order = INCHI_BOND_TYPE.Single; } else if (bo == BondOrder.Double) { order = INCHI_BOND_TYPE.Double; } else if (bo == BondOrder.Triple) { order = INCHI_BOND_TYPE.Triple; } else { throw new CDKException("Failed to generate InChI: Unsupported bond type"); } // Create InChI bond var ibond = new NInchiBond(at0, at1, order); bondMap[bond] = ibond; Input.Add(ibond); // Check for bond stereo definitions var stereo = bond.Stereo; // No stereo definition if (stereo == BondStereo.None) { ibond.BondStereo = INCHI_BOND_STEREO.None; } // Bond ending (fat end of wedge) below the plane else if (stereo == BondStereo.Down) { ibond.BondStereo = INCHI_BOND_STEREO.Single1Down; } // Bond ending (fat end of wedge) above the plane else if (stereo == BondStereo.Up) { ibond.BondStereo = INCHI_BOND_STEREO.Single1Up; } // Bond starting (pointy end of wedge) below the plane else if (stereo == BondStereo.DownInverted) { ibond.BondStereo = INCHI_BOND_STEREO.Single2Down; } // Bond starting (pointy end of wedge) above the plane else if (stereo == BondStereo.UpInverted) { ibond.BondStereo = INCHI_BOND_STEREO.Single2Up; } else if (stereo == BondStereo.EOrZ) { ibond.BondStereo = INCHI_BOND_STEREO.DoubleEither; } else if (stereo == BondStereo.UpOrDown) { ibond.BondStereo = INCHI_BOND_STEREO.Single1Either; } else if (stereo == BondStereo.UpOrDownInverted) { ibond.BondStereo = INCHI_BOND_STEREO.Single2Either; } // Bond with undefined stereochemistry else if (stereo == BondStereo.None) { if (order == INCHI_BOND_TYPE.Single) { ibond.BondStereo = INCHI_BOND_STEREO.Single1Either; } else if (order == INCHI_BOND_TYPE.Double) { ibond.BondStereo = INCHI_BOND_STEREO.DoubleEither; } } } // Process tetrahedral stereo elements foreach (var stereoElem in atomContainer.StereoElements) { if (stereoElem is ITetrahedralChirality chirality) { var stereoType = chirality.Stereo; var atC = atomMap[chirality.ChiralAtom]; var at0 = atomMap[chirality.Ligands[0]]; var at1 = atomMap[chirality.Ligands[1]]; var at2 = atomMap[chirality.Ligands[2]]; var at3 = atomMap[chirality.Ligands[3]]; var p = INCHI_PARITY.Unknown; if (stereoType == TetrahedralStereo.AntiClockwise) { p = INCHI_PARITY.Odd; } else if (stereoType == TetrahedralStereo.Clockwise) { p = INCHI_PARITY.Even; } else { throw new CDKException("Unknown tetrahedral chirality"); } var jniStereo = new NInchiStereo0D(atC, at0, at1, at2, at3, INCHI_STEREOTYPE.Tetrahedral, p); Input.Stereos.Add(jniStereo); } else if (stereoElem is IDoubleBondStereochemistry dbStereo) { var surroundingBonds = dbStereo.Bonds; if (surroundingBonds[0] == null || surroundingBonds[1] == null) { throw new CDKException("Cannot generate an InChI with incomplete double bond info"); } var stereoType = dbStereo.Stereo; IBond stereoBond = dbStereo.StereoBond; NInchiAtom at0 = null; NInchiAtom at1 = null; NInchiAtom at2 = null; NInchiAtom at3 = null; // TODO: I should check for two atom bonds... or maybe that should happen when you // create a double bond stereochemistry if (stereoBond.Contains(surroundingBonds[0].Begin)) { // first atom is A at1 = atomMap[surroundingBonds[0].Begin]; at0 = atomMap[surroundingBonds[0].End]; } else { // first atom is X at0 = atomMap[surroundingBonds[0].Begin]; at1 = atomMap[surroundingBonds[0].End]; } if (stereoBond.Contains(surroundingBonds[1].Begin)) { // first atom is B at2 = atomMap[surroundingBonds[1].Begin]; at3 = atomMap[surroundingBonds[1].End]; } else { // first atom is Y at2 = atomMap[surroundingBonds[1].End]; at3 = atomMap[surroundingBonds[1].Begin]; } var p = INCHI_PARITY.Unknown; if (stereoType == DoubleBondConformation.Together) { p = INCHI_PARITY.Odd; } else if (stereoType == DoubleBondConformation.Opposite) { p = INCHI_PARITY.Even; } else { throw new CDKException("Unknown double bond stereochemistry"); } var jniStereo = new NInchiStereo0D(null, at0, at1, at2, at3, INCHI_STEREOTYPE.DoubleBond, p); Input.Stereos.Add(jniStereo); } else if (stereoElem is ExtendedTetrahedral extendedTetrahedral) { TetrahedralStereo winding = extendedTetrahedral.Winding; // The peripherals (p<i>) and terminals (t<i>) are referring to // the following atoms. The focus (f) is also shown. // // p0 p2 // \ / // t0 = f = t1 // / \ // p1 p3 var terminals = extendedTetrahedral.FindTerminalAtoms(atomContainer); var peripherals = extendedTetrahedral.Peripherals.ToArray(); // InChI API is particular about the input, each terminal atom // needs to be present in the list of neighbors and they must // be at index 1 and 2 (i.e. in the middle). This is true even // of explicit atoms. For the implicit atoms, the terminals may // be in the peripherals already and so we correct the winding // and reposition as needed. var t0Bonds = OnlySingleBonded(atomContainer.GetConnectedBonds(terminals[0])); var t1Bonds = OnlySingleBonded(atomContainer.GetConnectedBonds(terminals[1])); // first if there are two explicit atoms we need to replace one // with the terminal atom - the configuration does not change if (t0Bonds.Count == 2) { var orgBond = t0Bonds[0]; t0Bonds.RemoveAt(0); var replace = orgBond.GetOther(terminals[0]); for (int i = 0; i < peripherals.Length; i++) { if (replace == peripherals[i]) { peripherals[i] = terminals[0]; } } } if (t1Bonds.Count == 2) { var orgBond = t0Bonds[0]; t1Bonds.RemoveAt(0); var replace = orgBond.GetOther(terminals[1]); for (int i = 0; i < peripherals.Length; i++) { if (replace == peripherals[i]) { peripherals[i] = terminals[1]; } } } // the neighbor attached to each terminal atom that we will // define the configuration of var t0Neighbor = t0Bonds[0].GetOther(terminals[0]); var t1Neighbor = t1Bonds[0].GetOther(terminals[1]); // we now need to move all the atoms into the correct positions // everytime we exchange atoms the configuration inverts for (int i = 0; i < peripherals.Length; i++) { if (i != 0 && t0Neighbor == peripherals[i]) { Swap(peripherals, i, 0); winding = winding.Invert(); } else if (i != 1 && terminals[0] == peripherals[i]) { Swap(peripherals, i, 1); winding = winding.Invert(); } else if (i != 2 && terminals[1] == peripherals[i]) { Swap(peripherals, i, 2); winding = winding.Invert(); } else if (i != 3 && t1Neighbor == peripherals[i]) { Swap(peripherals, i, 3); winding = winding.Invert(); } } var parity = INCHI_PARITY.Unknown; if (winding == TetrahedralStereo.AntiClockwise) { parity = INCHI_PARITY.Odd; } else if (winding == TetrahedralStereo.Clockwise) { parity = INCHI_PARITY.Even; } else { throw new CDKException("Unknown extended tetrahedral chirality"); } NInchiStereo0D jniStereo = new NInchiStereo0D(atomMap[extendedTetrahedral.Focus], atomMap[peripherals[0]], atomMap[peripherals[1]], atomMap[peripherals[2]], atomMap[peripherals[3]], INCHI_STEREOTYPE.Allene, parity); Input.Stereos.Add(jniStereo); } } try { Output = NInchiWrapper.GetInchi(Input); } catch (NInchiException jie) { throw new CDKException("Failed to generate InChI: " + jie.Message, jie); } }