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 TestExampleStructure2InchiDiChloroethene()
        {
            // START SNIPPET: structure2inchi-dichloroethene
            // Example input - 2D E-1,2-dichloroethene
            NInchiInput input = new NInchiInput();
            //
            // Generate atoms
            NInchiAtom a1 = input.Add(new NInchiAtom(2.866, -0.250, 0.000, "C"));
            NInchiAtom a2 = input.Add(new NInchiAtom(3.732, 0.250, 0.000, "C"));
            NInchiAtom a3 = input.Add(new NInchiAtom(2.000, 2.500, 0.000, "Cl"));
            NInchiAtom a4 = input.Add(new NInchiAtom(4.598, -0.250, 0.000, "Cl"));

            a1.ImplicitH = 1;
            a2.ImplicitH = 1;
            //
            // Add bond
            input.Add(new NInchiBond(a1, a2, INCHI_BOND_TYPE.Double));
            input.Add(new NInchiBond(a1, a3, INCHI_BOND_TYPE.Single));
            input.Add(new NInchiBond(a2, a4, INCHI_BOND_TYPE.Single));
            NInchiOutput output = NInchiWrapper.GetInchi(input);
            //END SNIPPET: structure2inchi - dichloroethene
        }
Ejemplo n.º 3
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);
            }
        }