Ejemplo n.º 1
0
        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
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        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);
        }
Ejemplo n.º 4
0
        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);
        }
Ejemplo n.º 5
0
        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);
        }
Ejemplo n.º 6
0
        public void TestGetStereo0D()
        {
            NInchiStructure structure = new NInchiStructure();
            NInchiStereo0D  stereo    = TestNInchiStereo0D.GetTestStereo0D();

            structure.Stereos.Add(stereo);
            Assert.AreEqual(stereo, structure.Stereos[0]);
        }
Ejemplo n.º 7
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 &gt;A=B&lt; or cumulene &gt;A=C=C=B&lt;
        ///  =============================================
        ///
        ///                              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)      &lt;=&gt; INCHI_PARITY_ODD
        ///  CML 'T' (trans)    &lt;=&gt; 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);
        }
Ejemplo n.º 8
0
        /// <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 &gt; 0 &lt;=&gt; INCHI_PARITY_EVEN
        ///  CML atomParity &lt; 0 &lt;=&gt; 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);
        }
Ejemplo n.º 9
0
        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]);
            }
        }
Ejemplo n.º 10
0
        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);
        }
Ejemplo n.º 11
0
        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);
            }
        }
Ejemplo n.º 12
0
        /// <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);
            }
        }