Пример #1
0
        private static ISet <IBond> FindCutBonds(IAtomContainer mol, EdgeToBondMap bmap, int[][] adjlist)
        {
            var cuts     = new HashSet <IBond>();
            var numAtoms = mol.Atoms.Count;

            for (int i = 0; i < numAtoms; i++)
            {
                var atom = mol.Atoms[i];
                var deg  = adjlist[i].Length;
                var elem = atom.AtomicNumber;

                if (elem == 6 && deg <= 2 || deg < 2)
                {
                    continue;
                }

                foreach (var w in adjlist[i])
                {
                    var bond = bmap[i, w];
                    if (adjlist[w].Length >= 2 && !bond.IsInRing)
                    {
                        cuts.Add(bond);
                    }
                }
            }
            return(cuts);
        }
Пример #2
0
        private static List <IAtomContainer> GenerateFragments(IAtomContainer mol)
        {
            var bmap    = EdgeToBondMap.WithSpaceFor(mol);
            var adjlist = GraphUtil.ToAdjList(mol, bmap);

            Cycles.MarkRingAtomsAndBonds(mol, adjlist, bmap);

            var cuts = FindCutBonds(mol, bmap, adjlist);

            var atmidx = new Dictionary <IAtom, int>();

            foreach (var atom in mol.Atoms)
            {
                atmidx[atom] = atmidx.Count;
            }

            // frags are ordered by biggest to smallest
            var frags = new List <IAtomContainer>();

            foreach (var cut in cuts)
            {
                if (frags.Count >= MaxFragment)
                {
                    break;
                }
                frags.AddRange(MakeCut(cut, mol, atmidx, adjlist));
            }

            frags.Sort(delegate(IAtomContainer a, IAtomContainer b)
            {
                return(-a.Bonds.Count.CompareTo(b.Bonds.Count));
            });

            return(frags);
        }
Пример #3
0
        /// <summary>
        /// Computes <see cref="SMARTSAtomInvariants"/> and stores on the <see cref="Key"/> or
        /// each <see cref="IAtom"/> in the <paramref name="container"/>. The <see cref="IMolecularEntity.IsInRing"/>
        /// is also set for each bond. This configuration
        /// includes the ring information as used by the Daylight implementation.
        /// That is the Smallest Set of Smallest Rings (SSSR) is used and only the
        /// smallest ring is stored for the <see cref="RingSize"/> .
        /// </summary>
        /// <example>
        /// <code>
        ///     IAtomContainer container = ...;
        ///     SMARTSAtomInvariants.ConfigureDaylightWithRingInfo(container);
        ///     foreach (var atom in container.Atoms) {
        ///         SMARTSAtomInvariants inv = atom.GetProperty&lt;SMARTSAtomInvariants&gt;(SMARTSAtomInvariants.Key);
        ///     }
        /// </code>
        /// </example>
        /// <param name="container">the container to configure</param>
        public static void ConfigureDaylightWithRingInfo(IAtomContainer container)
        {
            var map   = EdgeToBondMap.WithSpaceFor(container);
            var graph = GraphUtil.ToAdjList(container, map);

            ConfigureDaylight(container, graph, map, true);
        }
Пример #4
0
        /// <summary>
        /// Obtain the MMFF symbolic types to the atoms of the provided structure.
        /// </summary>
        /// <param name="container">container structure representation</param>
        /// <returns>MMFF symbolic types for each atom index</returns>
        public string[] SymbolicTypes(IAtomContainer container)
        {
            var bonds = EdgeToBondMap.WithSpaceFor(container);
            var graph = GraphUtil.ToAdjList(container, bonds);

            return(SymbolicTypes(container, graph, bonds, new HashSet <IBond>()));
        }
Пример #5
0
        /// <summary>
        /// Create a state for matching subgraphs using the Ullmann refinement
        /// procedure.
        /// </summary>
        /// <param name="container1">query container</param>
        /// <param name="container2">target container</param>
        /// <param name="g1">query container adjacency list</param>
        /// <param name="g2">target container adjacency list</param>
        /// <param name="bonds1">query container bond map</param>
        /// <param name="bonds2">target container bond map</param>
        /// <param name="atomMatcher">method of matching atom semantics</param>
        /// <param name="bondMatcher">method of matching bond semantics</param>
        public UllmannState(IAtomContainer container1, IAtomContainer container2, int[][] g1, int[][] g2,
                            EdgeToBondMap bonds1, EdgeToBondMap bonds2, AtomMatcher atomMatcher, BondMatcher bondMatcher)
        {
            this.bondMatcher = bondMatcher;
            this.g1          = g1;
            this.g2          = g2;
            this.bond1       = bonds1;
            this.bonds2      = bonds2;
            this.m1          = new int[g1.Length];
            this.m2          = new int[g2.Length];
            Arrays.Fill(m1, UNMAPPED);
            Arrays.Fill(m2, UNMAPPED);

            // build up compatibility matrix
            matrix = new CompatibilityMatrix(g1.Length, g2.Length);
            for (int i = 0; i < g1.Length; i++)
            {
                for (int j = 0; j < g2.Length; j++)
                {
                    if (g1[i].Length <= g2[j].Length && atomMatcher.Matches(container1.Atoms[i], container2.Atoms[j]))
                    {
                        matrix.Set1(i, j);
                    }
                }
            }
        }
Пример #6
0
 /// <summary>
 /// Use the provided query and target to obtain the bond instances.
 /// </summary>
 /// <param name="query">the structure to be found</param>
 /// <param name="target">the structure being searched</param>
 public BondMaper(IAtomContainer query, IAtomContainer target)
 {
     this.bonds1 = EdgeToBondMap.WithSpaceFor(query);
     this.bonds2 = EdgeToBondMap.WithSpaceFor(target);
     this.g1     = GraphUtil.ToAdjList(query, bonds1);
     GraphUtil.ToAdjList(target, bonds2);
 }
Пример #7
0
        /// <summary>
        /// Given the assigned preliminary MMFF atom types (symbs[]) update these to the aromatic types.
        /// To begin, all the 5 and 6 member aromatic cycles are discovered. The symbolic types of five
        /// and six member cycles are then update with <see cref="UpdateAromaticTypesInFiveMemberRing(int[], string[])"/>
        /// and <see cref="UpdateAromaticTypesInSixMemberRing(int[], string[])"/>.
        /// </summary>
        /// <param name="container">structure representation</param>
        /// <param name="symbs">vector of symbolic types for the whole structure</param>
        /// <param name="bonds">edge to bond map lookup</param>
        /// <param name="graph">adjacency list graph representation of structure</param>
        /// <param name="mmffArom">set of bonds that are aromatic</param>
        public void Assign(IAtomContainer container, string[] symbs, EdgeToBondMap bonds, int[][] graph, ISet <IBond> mmffArom)
        {
            var contribution = new int[graph.Length];
            var doubleBonds  = new int[graph.Length];

            Arrays.Fill(doubleBonds, -1);
            SetupContributionAndDoubleBonds(container, bonds, graph, contribution, doubleBonds);

            var cycles = FindAromaticRings(CyclesOfSizeFiveOrSix(container, graph), contribution, doubleBonds);

            foreach (var cycle in cycles)
            {
                int len = cycle.Length - 1;
                if (len == 6)
                {
                    UpdateAromaticTypesInSixMemberRing(cycle, symbs);
                }
                if (len == 5 && NormaliseCycle(cycle, contribution))
                {
                    UpdateAromaticTypesInFiveMemberRing(cycle, symbs);
                }
                // mark aromatic bonds
                for (int i = 1; i < cycle.Length; i++)
                {
                    mmffArom.Add(bonds[cycle[i], cycle[i - 1]]);
                }
            }
        }
Пример #8
0
        public void RecogniseLeftHandedGlyceraldehyde()
        {
            var m = new AtomContainer();

            m.Atoms.Add(Atom("C", 0, 0.80d, 1.24d));
            m.Atoms.Add(Atom("C", 0, 0.80d, 0.42d));
            m.Atoms.Add(Atom("O", 1, 0.09d, 1.66d));
            m.Atoms.Add(Atom("O", 0, 1.52d, 1.66d));
            m.Atoms.Add(Atom("O", 0, -0.02d, 0.42d));
            m.Atoms.Add(Atom("C", 2, 0.80d, -0.41d));
            m.Atoms.Add(Atom("H", 1, 1.63d, 0.42d));
            m.Atoms.Add(Atom("O", 1, 1.52d, -0.82d));
            m.AddBond(m.Atoms[0], m.Atoms[1], BondOrder.Single);
            m.AddBond(m.Atoms[0], m.Atoms[2], BondOrder.Single);
            m.AddBond(m.Atoms[0], m.Atoms[3], BondOrder.Double, BondStereo.EZByCoordinates);
            m.AddBond(m.Atoms[1], m.Atoms[4], BondOrder.Single);
            m.AddBond(m.Atoms[1], m.Atoms[5], BondOrder.Single);
            m.AddBond(m.Atoms[1], m.Atoms[6], BondOrder.Single);
            m.AddBond(m.Atoms[5], m.Atoms[7], BondOrder.Single);

            EdgeToBondMap bondMap = EdgeToBondMap.WithSpaceFor(m);

            int[][]            graph      = GraphUtil.ToAdjList(m, bondMap);
            FischerRecognition recogniser = new FischerRecognition(m,
                                                                   graph,
                                                                   bondMap,
                                                                   Stereocenters.Of(m));
            var elements = recogniser.Recognise(new[] { Projection.Fischer }).ToReadOnlyList();

            Assert.AreEqual(1, elements.Count);
            AssertTetrahedralCenter(elements[0],
                                    m.Atoms[1],
                                    TetrahedralStereo.AntiClockwise,
                                    m.Atoms[0], m.Atoms[6], m.Atoms[5], m.Atoms[4]);
        }
Пример #9
0
        /// <summary>
        /// Find the bonds of a <paramref name="molecule"/> which this model determined were aromatic.
        /// </summary>
        /// <example>
        /// <include file='IncludeExamples.xml' path='Comments/Codes[@id="NCDK.Aromaticities.Aromaticity_Example.cs+FindBonds"]/*' />
        /// </example>
        /// <param name="molecule">the molecule to apply the model to</param>
        /// <returns>the set of bonds which are aromatic</returns>
        /// <exception cref="CDKException">a problem occurred with the cycle perception - one can retry with a simpler cycle set</exception>
        public IEnumerable <IBond> FindBonds(IAtomContainer molecule)
        {
            // build graph data-structures for fast cycle perception
            var bondMap = EdgeToBondMap.WithSpaceFor(molecule);
            var graph   = GraphUtil.ToAdjList(molecule, bondMap);

            // initial ring/cycle search and get the contribution from each atom
            RingSearch ringSearch = new RingSearch(molecule, graph);
            var        electrons  = model.Contribution(molecule, ringSearch);

            // obtain the subset of electron contributions which are >= 0 (i.e.
            // allowed to be aromatic) - we then find the cycles in this subgraph
            // and 'lift' the indices back to the original graph using the subset
            // as a lookup
            var subset   = Subset(electrons);
            var subgraph = GraphUtil.Subgraph(graph, subset);

            // for each cycle if the electron sum is valid add the bonds of the
            // cycle to the set or aromatic bonds
            foreach (var cycle in cycles.Find(molecule, subgraph, subgraph.Length).GetPaths())
            {
                if (CheckElectronSum(cycle, electrons, subset))
                {
                    for (int i = 1; i < cycle.Length; i++)
                    {
                        yield return(bondMap[subset[cycle[i]], subset[cycle[i - 1]]]);
                    }
                }
            }
            yield break;
        }
Пример #10
0
        public void RequireAtLeastTwoProjectedSubstituents()
        {
            var m = new AtomContainer();

            m.Atoms.Add(Atom("O", 0, -0.71d, 1.24d));
            m.Atoms.Add(Atom("C", 0, 0.00d, 0.83d));
            m.Atoms.Add(Atom("O", 0, 0.71d, 1.24d));
            m.Atoms.Add(Atom("C", 1, 0.00d, 0.00d));
            m.Atoms.Add(Atom("C", 2, -0.67d, -0.48d));
            m.Atoms.Add(Atom("C", 2, -0.41d, -1.27d));
            m.Atoms.Add(Atom("C", 2, 0.41d, -1.27d));
            m.Atoms.Add(Atom("N", 1, 0.67d, -0.48d));
            m.AddBond(m.Atoms[6], m.Atoms[5], BondOrder.Single);
            m.AddBond(m.Atoms[1], m.Atoms[0], BondOrder.Double, BondStereo.EZByCoordinates);
            m.AddBond(m.Atoms[2], m.Atoms[1], BondOrder.Single);
            m.AddBond(m.Atoms[3], m.Atoms[1], BondOrder.Single);
            m.AddBond(m.Atoms[5], m.Atoms[4], BondOrder.Single);
            m.AddBond(m.Atoms[4], m.Atoms[3], BondOrder.Single);
            m.AddBond(m.Atoms[3], m.Atoms[7], BondOrder.Single);
            m.AddBond(m.Atoms[6], m.Atoms[7], BondOrder.Single);
            EdgeToBondMap bondMap = EdgeToBondMap.WithSpaceFor(m);

            int[][]       graph         = GraphUtil.ToAdjList(m, bondMap);
            Stereocenters stereocenters = new Stereocenters(m, graph, bondMap);

            stereocenters.CheckSymmetry();
            CyclicCarbohydrateRecognition recon = new CyclicCarbohydrateRecognition(m, graph, bondMap,
                                                                                    stereocenters);

            var elements = recon.Recognise(new[] { Projection.Haworth }).ToReadOnlyList();

            Assert.IsTrue(elements.Count == 0);
        }
Пример #11
0
 internal AdjListCache(IAtomContainer mol)
 {
     this.bmap     = EdgeToBondMap.WithSpaceFor(mol);
     this.g        = GraphUtil.ToAdjList(mol, bmap);
     this.numAtoms = mol.Atoms.Count;
     this.numBonds = mol.Bonds.Count;
     this.tInit    = DateTime.Now.Ticks;
 }
Пример #12
0
        public override Mappings MatchAll(IAtomContainer target)
        {
            var bonds2   = EdgeToBondMap.WithSpaceFor(target);
            var g2       = GraphUtil.ToAdjList(target, bonds2);
            var iterable = new UllmannIterable(query, target, g1, g2, bonds1, bonds2, atomMatcher, bondMatcher);
            var mappings = new Mappings(query, target, iterable);

            return(Filter(mappings, query, target));
        }
Пример #13
0
        /// <summary>
        /// Determine the stereocenter atoms in the provided container based on connectivity.
        /// </summary>
        /// <example>
        /// <include file='IncludeExamples.xml' path='Comments/Codes[@id="NCDK.Stereo.Stereocenters_Example.cs+Of"]/*' />
        /// </example>
        /// <param name="container">input container</param>
        /// <returns>the stereocenters</returns>
        public static Stereocenters Of(IAtomContainer container)
        {
            var bondMap       = EdgeToBondMap.WithSpaceFor(container);
            var g             = GraphUtil.ToAdjList(container, bondMap);
            var stereocenters = new Stereocenters(container, g, bondMap);

            stereocenters.CheckSymmetry();
            return(stereocenters);
        }
Пример #14
0
 /// <summary>
 /// Non-public constructor for-now the atom/bond semantics are fixed.
 /// </summary>
 /// <param name="query">the query structure</param>
 /// <param name="atomMatcher">how atoms should be matched</param>
 /// <param name="bondMatcher">how bonds should be matched</param>
 private Ullmann(IAtomContainer query, AtomMatcher atomMatcher, BondMatcher bondMatcher)
 {
     this.query       = query;
     this.atomMatcher = atomMatcher;
     this.bondMatcher = bondMatcher;
     this.bonds1      = EdgeToBondMap.WithSpaceFor(query);
     this.g1          = GraphUtil.ToAdjList(query, bonds1);
     DetermineFilters(query);
 }
Пример #15
0
        public void Mannitol()
        {
            var m = new AtomContainer();

            m.Atoms.Add(Atom("C", 2, -0.53d, 6.25d));
            m.Atoms.Add(Atom("C", 1, -0.53d, 5.42d));
            m.Atoms.Add(Atom("O", 1, 0.18d, 6.66d));
            m.Atoms.Add(Atom("O", 1, -1.36d, 5.42d));
            m.Atoms.Add(Atom("C", 1, -0.53d, 4.60d));
            m.Atoms.Add(Atom("O", 1, -1.36d, 4.60d));
            m.Atoms.Add(Atom("C", 1, -0.53d, 3.77d));
            m.Atoms.Add(Atom("O", 1, 0.29d, 3.77d));
            m.Atoms.Add(Atom("C", 1, -0.53d, 2.95d));
            m.Atoms.Add(Atom("O", 1, 0.29d, 2.95d));
            m.Atoms.Add(Atom("C", 2, -0.53d, 2.12d));
            m.Atoms.Add(Atom("O", 1, 0.05d, 1.54d));
            m.AddBond(m.Atoms[0], m.Atoms[1], BondOrder.Single);
            m.AddBond(m.Atoms[0], m.Atoms[2], BondOrder.Single);
            m.AddBond(m.Atoms[1], m.Atoms[3], BondOrder.Single);
            m.AddBond(m.Atoms[1], m.Atoms[4], BondOrder.Single);
            m.AddBond(m.Atoms[4], m.Atoms[5], BondOrder.Single);
            m.AddBond(m.Atoms[4], m.Atoms[6], BondOrder.Single);
            m.AddBond(m.Atoms[6], m.Atoms[7], BondOrder.Single);
            m.AddBond(m.Atoms[6], m.Atoms[8], BondOrder.Single);
            m.AddBond(m.Atoms[8], m.Atoms[9], BondOrder.Single);
            m.AddBond(m.Atoms[8], m.Atoms[10], BondOrder.Single);
            m.AddBond(m.Atoms[10], m.Atoms[11], BondOrder.Single);

            EdgeToBondMap bondMap = EdgeToBondMap.WithSpaceFor(m);

            int[][]            graph      = GraphUtil.ToAdjList(m, bondMap);
            FischerRecognition recogniser = new FischerRecognition(m,
                                                                   graph,
                                                                   bondMap,
                                                                   Stereocenters.Of(m));
            var elements = recogniser.Recognise(new[] { Projection.Fischer }).ToReadOnlyList();

            Assert.AreEqual(4, elements.Count);
            AssertTetrahedralCenter(elements[0],
                                    m.Atoms[1],
                                    TetrahedralStereo.AntiClockwise,
                                    m.Atoms[0], m.Atoms[1], m.Atoms[4], m.Atoms[3]);
            AssertTetrahedralCenter(elements[1],
                                    m.Atoms[4],
                                    TetrahedralStereo.AntiClockwise,
                                    m.Atoms[1], m.Atoms[4], m.Atoms[6], m.Atoms[5]);
            AssertTetrahedralCenter(elements[2],
                                    m.Atoms[6],
                                    TetrahedralStereo.AntiClockwise,
                                    m.Atoms[4], m.Atoms[7], m.Atoms[8], m.Atoms[6]);
            AssertTetrahedralCenter(elements[3],
                                    m.Atoms[8],
                                    TetrahedralStereo.AntiClockwise,
                                    m.Atoms[6], m.Atoms[9], m.Atoms[10], m.Atoms[8]);

            m.SetStereoElements(elements);
        }
Пример #16
0
        /// <summary>
        /// Assign MMFF Symbolic atom types. The symbolic type can be accessed with
        /// <see cref="IAtomType.AtomTypeName"/>. An atom of unknown type is assigned the
        /// symbolic type <c>"UNK"</c>.
        /// All atoms, including hydrogens must be explicitly represented.
        /// </summary>
        /// <param name="mol">molecule</param>
        /// <returns>all atoms had a type assigned</returns>
        public virtual bool AssignAtomTypes(IAtomContainer mol)
        {
            // preconditions need explicit hydrogens
            foreach (var atom in mol.Atoms)
            {
                if (atom.ImplicitHydrogenCount == null || atom.ImplicitHydrogenCount > 0)
                {
                    throw new ArgumentException("Hydrogens must be explicit nodes, each must have a zero (non-null) impl H count.");
                }
            }

            // conversion to faster data structures
            var edgeMap = EdgeToBondMap.WithSpaceFor(mol);
            var adjList = GraphUtil.ToAdjList(mol, edgeMap);

            mol.SetProperty(MMFF_ADJLIST_CACHE, adjList);
            mol.SetProperty(MMFF_EDGEMAP_CACHE, edgeMap);

            var aromBonds = new HashSet <IBond>();
            var oldArom   = GetAromatics(mol);

            // note: for MMFF we need to remove current aromatic flags for type
            // assignment (they are restored after)
            foreach (var chemObj in oldArom)
            {
                chemObj.IsAromatic = false;
            }
            var atomTypes = mmffAtomTyper.SymbolicTypes(mol, adjList, edgeMap, aromBonds);

            bool hasUnkType = false;

            for (int i = 0; i < mol.Atoms.Count; i++)
            {
                if (atomTypes[i] == null)
                {
                    mol.Atoms[i].AtomTypeName = "UNK";
                    hasUnkType = true;
                }
                else
                {
                    mol.Atoms[i].AtomTypeName = atomTypes[i];
                }
            }

            // restore aromatic flags and mark the MMFF aromatic bonds
            foreach (var chemObj in oldArom)
            {
                chemObj.IsAromatic = true;
            }
            foreach (var bond in aromBonds)
            {
                bond.SetProperty(MMFF_AROM, true);
            }

            return(!hasUnkType);
        }
Пример #17
0
 /// <summary>
 /// Required information to recognise stereochemistry.
 /// </summary>
 /// <param name="container">input structure</param>
 /// <param name="graph">adjacency list representation</param>
 /// <param name="bonds">edge to bond index</param>
 /// <param name="stereocenters">location and type of asymmetries</param>
 public FischerRecognition(IAtomContainer container,
                           int[][] graph,
                           EdgeToBondMap bonds,
                           Stereocenters stereocenters)
 {
     this.container     = container;
     this.graph         = graph;
     this.bonds         = bonds;
     this.stereocenters = stereocenters;
 }
Пример #18
0
 /// <summary>
 /// Create a perception method for the provided container, graph
 /// representation and bond map.
 /// </summary>
 /// <param name="container">native CDK structure representation</param>
 /// <param name="graph">graph representation (adjacency list)</param>
 /// <param name="bondMap">fast lookup bonds by atom index</param>
 internal Stereocenters(IAtomContainer container, int[][] graph, EdgeToBondMap bondMap)
 {
     this.container         = container;
     this.bondMap           = bondMap;
     this.g                 = graph;
     this.ringSearch        = new RingSearch(container, graph);
     this.elements          = new StereoElement[g.Length];
     this.stereocenters     = new CenterType[g.Length];
     this.numStereoElements = CreateElements();
 }
Пример #19
0
 /// <summary>
 /// Non-public constructor for-now the atom/bond semantics are fixed.
 /// </summary>
 /// <param name="query">the query structure</param>
 /// <param name="atomMatcher">how atoms should be matched</param>
 /// <param name="bondMatcher">how bonds should be matched</param>
 /// <param name="substructure">substructure search</param>
 private VentoFoggia(IAtomContainer query, AtomMatcher atomMatcher, BondMatcher bondMatcher, bool substructure)
 {
     this.query       = query;
     this.atomMatcher = atomMatcher;
     this.bondMatcher = bondMatcher;
     this.bonds1      = EdgeToBondMap.WithSpaceFor(query);
     this.g1          = GraphUtil.ToAdjList(query, bonds1);
     this.subgraph    = substructure;
     DetermineFilters(query);
 }
Пример #20
0
        /// <summary>
        /// Determine the set of atoms that are available to have a double-bond.
        /// </summary>
        /// <param name="graph">adjacent list representation</param>
        /// <param name="atoms">array of atoms</param>
        /// <param name="bonds">map of atom indices to bonds</param>
        /// <returns>atoms that can require a double-bond</returns>
        private static BitArray IsAvailable(int[][] graph, IAtom[] atoms, EdgeToBondMap bonds)
        {
            var available = new BitArray(atoms.Length);

            // for all atoms, select those that require a double-bond
            for (int i = 0; i < atoms.Length; i++)
            {
                var atom = atoms[i];

                // preconditions
                if (atom.FormalCharge == null)
                {
                    throw new ArgumentException($"atom {i + 1} had unset formal charge");
                }
                if (atom.ImplicitHydrogenCount == null)
                {
                    throw new ArgumentException($"atom {i + 1} had unset implicit hydrogen count");
                }

                if (!atom.IsAromatic)
                {
                    continue;
                }

                // count preexisting pi-bonds, a higher bond order causes a skip
                int nPiBonds = 0;
                foreach (var w in graph[i])
                {
                    var order = bonds[i, w].Order;
                    if (order == BondOrder.Double)
                    {
                        nPiBonds++;
                    }
                    else if (order.Numeric() > 2)
                    {
                        goto continue_ATOMS;
                    }
                }

                // check if a pi bond can be assigned
                var element = atom.AtomicNumber;
                var charge  = atom.FormalCharge.Value;
                var valence = graph[i].Length + atom.ImplicitHydrogenCount.Value + nPiBonds;

                if (IsAvailable(element, charge, valence))
                {
                    available.Set(i, true);
                }

continue_ATOMS:
                ;
            }

            return(available);
        }
Пример #21
0
 /// <summary>
 /// Create a VF state for matching isomorphisms. The query is passed first
 /// and should read as, find container1 in container2.
 /// </summary>
 /// <param name="container1">the molecule to search for (query)</param>
 /// <param name="container2">the molecule to search in (target)</param>
 /// <param name="g1">adjacency list of the query</param>
 /// <param name="g2">adjacency list of the target</param>
 /// <param name="bonds1">bond lookup of the query</param>
 /// <param name="bonds2">bond lookup of the target</param>
 /// <param name="atomMatcher">what semantic attributes (symbol, charge, query) determines atoms to be compatible</param>
 /// <param name="bondMatcher">what semantic attributes (order/aromatic, query) determines bonds to be compatible</param>
 public VFState(IAtomContainer container1, IAtomContainer container2, int[][] g1, int[][] g2, EdgeToBondMap bonds1,
                EdgeToBondMap bonds2, AtomMatcher atomMatcher, BondMatcher bondMatcher)
     : base(g1, g2)
 {
     this.container1  = container1;
     this.container2  = container2;
     this.bonds1      = bonds1;
     this.bonds2      = bonds2;
     this.atomMatcher = atomMatcher;
     this.bondMatcher = bondMatcher;
 }
Пример #22
0
        /// <summary>
        /// Helper method to obtain the neighbouring bonds from an adjacency list
        /// graph and edge->bond map.
        /// </summary>
        /// <param name="v">vertex</param>
        /// <param name="g">graph (adj list)</param>
        /// <param name="bondMap">map of edges to bonds</param>
        /// <returns>neighboring bonds</returns>
        private static IBond[] Neighbors(int v, int[][] g, EdgeToBondMap bondMap)
        {
            var ws    = g[v];
            var bonds = new IBond[ws.Length];

            for (int i = 0; i < ws.Length; i++)
            {
                bonds[i] = bondMap[v, ws[i]];
            }
            return(bonds);
        }
Пример #23
0
        /// <summary>
        /// Create a state for matching benzene to naphthalene Benzene:
        /// InChI=1/C6H6/c1-2-4-6-5-3-1/h1-6H Naphthalene: InChI=1/C10H8/c1-2-6-10-8-4-3-7-9(10)5-1/h1-8H
        /// </summary>
        UllmannState CreateBenzeneToNaphthalene(AtomMatcher atomMatcher, BondMatcher bondMatcher)
        {
            IAtomContainer container1 = TestMoleculeFactory.MakeBenzene();
            IAtomContainer container2 = TestMoleculeFactory.MakeNaphthalene();
            EdgeToBondMap  bonds1     = EdgeToBondMap.WithSpaceFor(container1);
            EdgeToBondMap  bonds2     = EdgeToBondMap.WithSpaceFor(container2);

            int[][] g1 = GraphUtil.ToAdjList(container1, bonds1);
            int[][] g2 = GraphUtil.ToAdjList(container2, bonds2);
            return(new UllmannState(container1, container2, g1, g2, bonds1, bonds2, atomMatcher, bondMatcher));
        }
Пример #24
0
 /// <summary>
 /// Create a match for the following parameters.
 /// </summary>
 /// <param name="container1">query structure</param>
 /// <param name="container2">target structure</param>
 /// <param name="g1">query adjacency list</param>
 /// <param name="g2">target adjacency list</param>
 /// <param name="bonds1">query bond map</param>
 /// <param name="bonds2">target bond map</param>
 /// <param name="atomMatcher">how atoms are matched</param>
 /// <param name="bondMatcher">how bonds are matched</param>
 public UllmannIterable(IAtomContainer container1, IAtomContainer container2, int[][] g1, int[][] g2,
                        EdgeToBondMap bonds1, EdgeToBondMap bonds2, AtomMatcher atomMatcher, BondMatcher bondMatcher)
 {
     this.container1  = container1;
     this.container2  = container2;
     this.g1          = g1;
     this.g2          = g2;
     this.bonds1      = bonds1;
     this.bonds2      = bonds2;
     this.atomMatcher = atomMatcher;
     this.bondMatcher = bondMatcher;
 }
Пример #25
0
        private static bool IsAromPath(int[] path, EdgeToBondMap bmap)
        {
            int end = path.Length - 1;

            for (int i = 0; i < end; i++)
            {
                if (!bmap[path[i], path[i + 1]].IsAromatic)
                {
                    return(false);
                }
            }
            return(true);
        }
Пример #26
0
 /// <summary>
 /// Create a match for the following parameters.
 /// </summary>
 /// <param name="container1">query structure</param>
 /// <param name="container2">target structure</param>
 /// <param name="g1">query adjacency list</param>
 /// <param name="g2">target adjacency list</param>
 /// <param name="bonds1">query bond map</param>
 /// <param name="bonds2">target bond map</param>
 /// <param name="atomMatcher">how atoms are matched</param>
 /// <param name="bondMatcher">how bonds are matched</param>
 /// <param name="subgraph">perform subgraph search</param>
 public VFIterable(IAtomContainer container1, IAtomContainer container2, int[][] g1, int[][] g2,
                   EdgeToBondMap bonds1, EdgeToBondMap bonds2, AtomMatcher atomMatcher, BondMatcher bondMatcher,
                   bool subgraph)
 {
     this.container1  = container1;
     this.container2  = container2;
     this.g1          = g1;
     this.g2          = g2;
     this.bonds1      = bonds1;
     this.bonds2      = bonds2;
     this.atomMatcher = atomMatcher;
     this.bondMatcher = bondMatcher;
     this.subgraph    = subgraph;
 }
Пример #27
0
        /// <summary>
        /// Convert a cycle in <see cref="int"/>[] representation to an <see cref="IRing"/>
        /// but first map back using the given <paramref name="mapping"/>.
        /// </summary>
        /// <param name="container">atom container</param>
        /// <param name="edges">edge map</param>
        /// <param name="cycle">vertex walk forming the cycle, first and last vertex the same</param>
        /// <returns>a new ring</returns>
        private static IRing ToRing(IAtomContainer container, EdgeToBondMap edges, int[] cycle, int[] mapping)
        {
            var len   = cycle.Length - 1;
            var atoms = new IAtom[len];
            var bonds = new IBond[len];

            for (int i = 0; i < len; i++)
            {
                atoms[i]          = container.Atoms[mapping[cycle[i]]];
                bonds[i]          = edges[mapping[cycle[i]], mapping[cycle[i + 1]]];
                atoms[i].IsInRing = true;
            }
            var ring = container.Builder.NewRing(atoms, bonds);

            return(ring);
        }
Пример #28
0
        /// <summary>
        /// Create a new layout refiner for the provided molecule.
        /// </summary>
        /// <param name="mol">molecule to refine</param>
        internal LayoutRefiner(IAtomContainer mol, ISet <IAtom> afix, ISet <IBond> bfix)
        {
            this.mol     = mol;
            this.afix    = afix;
            this.bfix    = bfix;
            this.bondMap = EdgeToBondMap.WithSpaceFor(mol);
            this.adjList = GraphUtil.ToAdjList(mol, bondMap);
            this.idxs    = new Dictionary <IAtom, int>();
            foreach (var atom in mol.Atoms)
            {
                idxs[atom] = idxs.Count;
            }
            this.atoms = mol.Atoms.ToArray();

            // buffers for storing coordinates
            this.buffer1 = new Vector2[atoms.Length];
            this.buffer2 = new Vector2[atoms.Length];
            this.backup  = new Vector2[atoms.Length];
            for (int i = 0; i < buffer1.Length; i++)
            {
                buffer1[i] = new Vector2();
                buffer2[i] = new Vector2();
                backup[i]  = new Vector2();
            }
            this.stackBackup = new IntStack(atoms.Length);
            this.visited     = new bool[atoms.Length];

            this.congestion = new Congestion(mol, adjList);

            // note, this is lazy so only does the shortest path when needed
            // and does |V| search at maximum
            this.apsp = new AllPairsShortestPaths(mol);

            // index ring systems, idx -> ring system number (rnum)
            int rnum = 1;

            this.ringsystems = new int[atoms.Length];
            for (int i = 0; i < atoms.Length; i++)
            {
                if (atoms[i].IsInRing && ringsystems[i] == 0)
                {
                    TraverseRing(ringsystems, i, rnum++);
                }
            }
        }
Пример #29
0
        /// <summary>
        /// Assign a Kekulé representation to the aromatic systems of a compound.
        /// </summary>
        /// <param name="ac">structural representation</param>
        /// <exception cref="CDKException">a Kekulé form could not be assigned</exception>
        public static void Kekulize(IAtomContainer ac)
        {
            // storage of pairs of atoms that have pi-bonded
            var matching = Matching.WithCapacity(ac.Atoms.Count);

            // exract data structures for efficient access
            var atoms = ac.Atoms.ToArray();
            var bonds = EdgeToBondMap.WithSpaceFor(ac);
            var graph = GraphUtil.ToAdjList(ac, bonds);

            // determine which atoms are available to have a pi bond placed
            var available = IsAvailable(graph, atoms, bonds);

            // attempt to find a perfect matching such that a pi bond is placed
            // next to each available atom. if not found the solution is ambiguous
            if (!matching.Perfect(graph, available))
            {
                throw new CDKException("Cannot assign Kekulé structure without randomly creating radicals.");
            }

            // propagate bond order information from the matching
            foreach (var bond in ac.Bonds)
            {
                if (bond.Order == BondOrder.Unset && bond.IsAromatic)
                {
                    bond.Order = BondOrder.Single;
                }
            }
            for (int v = BitArrays.NextSetBit(available, 0); v >= 0; v = BitArrays.NextSetBit(available, v + 1))
            {
                var w    = matching.Other(v);
                var bond = bonds[v, w];

                // sanity check, something wrong if this happens
                if (bond.Order.Numeric() > 1)
                {
                    throw new CDKException("Cannot assign Kekulé structure, non-sigma bond order has already been assigned?");
                }

                bond.Order = BondOrder.Double;
                available.Set(w, false);
            }
        }
Пример #30
0
        /// <summary>
        /// Compute all rings up to an including the <paramref name="maxRingSize"/>. No
        /// pre-processing is done on the container.
        /// </summary>
        /// <param name="atomContainer">the molecule to be searched for rings</param>
        /// <param name="maxRingSize">Maximum ring size to consider. Provides a possible
        ///                      breakout from recursion for complex compounds.</param>
        /// <returns>a RingSet containing the rings in molecule</returns>
        /// <exception cref="CDKException">An exception thrown if the threshold was exceeded</exception>
        public IRingSet FindAllRingsInIsolatedRingSystem(IAtomContainer atomContainer, int maxRingSize)
        {
            var edges = EdgeToBondMap.WithSpaceFor(atomContainer);
            var graph = GraphUtil.ToAdjList(atomContainer, edges);

            var ac = new AllCycles(graph, maxRingSize, threshold.Value);

            if (!ac.Completed)
            {
                throw new CDKException("Threshold exceeded for AllRingsFinder");
            }

            var ringSet = atomContainer.Builder.NewRingSet();

            foreach (var path in ac.GetPaths())
            {
                ringSet.Add(ToRing(atomContainer, edges, path));
            }

            return(ringSet);
        }