Exemplo n.º 1
0
        /// <summary>
        /// Create a stereo encoder for all potential 2D and 3D double bond stereo
        /// configurations.
        /// </summary>
        /// <param name="container">an atom container</param>
        /// <param name="graph">adjacency list representation of the container</param>
        /// <returns>a new encoder for tetrahedral elements</returns>
        public IStereoEncoder Create(IAtomContainer container, int[][] graph)
        {
            var encoders = new List <IStereoEncoder>(5);

            foreach (var bond in container.Bonds)
            {
                // if double bond and not E or Z query bond
                if (BondOrder.Double.Equals(bond.Order) && !BondStereo.EOrZ.Equals(bond.Stereo))
                {
                    IAtom left  = bond.Begin;
                    IAtom right = bond.End;

                    // skip -N=N- double bonds which exhibit inversion
                    if (7.Equals(left.AtomicNumber) &&
                        7.Equals(right.AtomicNumber))
                    {
                        continue;
                    }

                    IStereoEncoder encoder = NewEncoder(container, left, right, right, left, graph);

                    if (encoder != null)
                    {
                        encoders.Add(encoder);
                    }
                }
            }

            return(encoders.Count == 0 ? StereoEncoder.Empty : new MultiStereoEncoder(encoders));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Package-private method for generating the hash for the given molecule.
        /// The initial invariants are passed as to the method along with an
        /// adjacency list representation of the graph.
        /// </summary>
        /// <param name="current">initial invariants</param>
        /// <param name="encoder"></param>
        /// <param name="graph">adjacency list representation</param>
        /// <param name="suppressed"></param>
        /// <returns>hash codes for atoms</returns>
        public override long[] Generate(long[] current, IStereoEncoder encoder, int[][] graph, Suppressed suppressed)
        {
            int n    = graph.Length;
            var next = Copy(current);

            // buffers for including adjacent invariants
            var unique   = new long[n];
            var included = new long[n];

            while (encoder.Encode(current, next))
            {
                Copy(next, current);
            }

            for (int d = 0; d < depth; d++)
            {
                for (int v = 0; v < n; v++)
                {
                    next[v] = Next(graph, v, current, unique, included);
                }

                Copy(next, current);

                while (encoder.Encode(current, next))
                {
                    Copy(next, current);
                }
            }

            return(current);
        }
Exemplo n.º 3
0
        private long[] Generate(IAtomContainer container, long[] seeds, IStereoEncoder encoder, int[][] graph)
        {
            Suppressed suppressed = suppression.Suppress(container);

            // compute original values then find indices equivalent values
            long[] original      = simple.Generate(seeds, encoder, graph, suppressed);
            var    equivalentSet = finder.Find(original, container, graph);
            var    equivalents   = equivalentSet.ToArray();

            // size of the matrix we need to make
            int n = original.Length;
            int m = equivalents.Length;

            // skip when there are no equivalent atoms
            if (m < 2)
            {
                return(original);
            }

            // matrix of perturbed values and identity values
            long[][] perturbed = Arrays.CreateJagged <long>(n, m + 1);

            // set the original values in the first column
            for (int i = 0; i < n; i++)
            {
                perturbed[i][0] = original[i];
            }

            // systematically perturb equivalent vertex
            for (int i = 0; i < m; i++)
            {
                int equivalentIndex = equivalents[i];

                // perturb the value and reset stereo configuration
                original[equivalentIndex] = Rotate(original[equivalentIndex]);
                encoder.Reset();

                // compute new hash codes and copy the values a column in the matrix
                long[] tmp = simple.Generate(Copy(original), encoder, graph, suppressed);
                for (int j = 0; j < n; j++)
                {
                    perturbed[j][i + 1] = tmp[j];
                }

                // reset value
                original[equivalentIndex] = perturbed[equivalentIndex][0];
            }

            return(Combine(perturbed));
        }
 private static IList <IStereoEncoder> ExtractEncoders(IStereoEncoder encoder)
 {
     if (encoder is MultiStereoEncoder)
     {
         FieldInfo field = null;
         field = encoder.GetType().GetField("encoders", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
         if (field == null)
         {
             Console.Error.WriteLine("Error on accessing encoders field.");
             return(null);
         }
         return((IList <IStereoEncoder>)field.GetValue(encoder));
     }
     return(new IStereoEncoder[0]);
 }
 private static GeometricParity GetGeometricParity(IStereoEncoder encoder)
 {
     if (encoder is GeometryEncoder)
     {
         FieldInfo field = null;
         field = encoder.GetType().GetField("geometric", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
         if (field == null)
         {
             Console.Error.WriteLine("Error on accessing geometric field.");
             return(null);
         }
         return((GeometricParity)field.GetValue(encoder));
     }
     return(null);
 }
Exemplo n.º 6
0
        /// <summary>
        /// Package-private method for generating the hash for the given molecule.
        /// The initial invariants are passed as to the method along with an
        /// adjacency list representation of the graph.
        /// </summary>
        /// <param name="current">initial invariants</param>
        /// <param name="encoder"></param>
        /// <param name="graph">adjacency list representation</param>
        /// <param name="suppressed"></param>
        /// <returns>hash codes for atoms</returns>
        public override long[] Generate(long[] current, IStereoEncoder encoder, int[][] graph, Suppressed suppressed)
        {
            // for the stereo perception depending on how the
            // (BasicPermutationParity) is done we need to set the value to be as
            // high (or low) as possible
            foreach (var i in suppressed.ToArray())
            {
                current[i] = long.MaxValue;
            }

            int n = graph.Length;

            long[] next = Copy(current);

            // buffers for including adjacent invariants
            long[] unique   = new long[n];
            long[] included = new long[n];

            while (encoder.Encode(current, next))
            {
                Copy(next, current);
            }

            for (int d = 0; d < depth; d++)
            {
                for (int v = 0; v < n; v++)
                {
                    next[v] = Next(graph, v, current, unique, included, suppressed);
                }

                Copy(next, current);

                while (encoder.Encode(current, next))
                {
                    Copy(next, current);
                }
            }

            // zero all suppressed values so they are not combined in any molecule
            // hash
            foreach (var i in suppressed.ToArray())
            {
                current[i] = 0L;
            }

            return(current);
        }
 private static GeometricParity GetGeometricParity(IStereoEncoder encoder)
 {
     if (encoder is MultiStereoEncoder)
     {
         return(GetGeometricParity(ExtractEncoders(encoder)[0]));
     }
     else if (encoder is GeometryEncoder)
     {
         FieldInfo field = null;
         field = encoder.GetType().GetField("geometric", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
         if (field == null)
         {
             Console.Error.WriteLine("No geometric field found.");
             return(null);
         }
         return((GeometricParity)field.GetValue(encoder));
     }
     return(null);
 }
Exemplo n.º 8
0
        public void TestCreate()
        {
            var m = new AtomContainer();

            m.Atoms.Add(CarbonAt(-0.2994, 3.2084));
            m.Atoms.Add(CarbonAt(-1.1244, 3.2084));
            m.Atoms.Add(CarbonAt(-1.9494, 3.2084));
            m.Atoms.Add(CarbonAt(-2.3619, 2.4939));
            m.Atoms.Add(CarbonAt(0.1131, 3.9228));
            m.Bonds.Add(new Bond(m.Atoms[0], m.Atoms[1], BondOrder.Double));
            m.Bonds.Add(new Bond(m.Atoms[1], m.Atoms[2], BondOrder.Double));
            m.Bonds.Add(new Bond(m.Atoms[2], m.Atoms[3]));
            m.Bonds.Add(new Bond(m.Atoms[0], m.Atoms[4]));

            IStereoEncoderFactory factory = new GeometricCumulativeDoubleBondFactory();
            // graph not used
            IStereoEncoder encoder = factory.Create(m, null);

            Assert.IsInstanceOfType(encoder, typeof(MultiStereoEncoder));
        }
Exemplo n.º 9
0
 /// <summary>
 /// Create a new conjugated encoder from a left and right encoder.
 /// </summary>
 /// <param name="left">encoder</param>
 /// <param name="right">encoder</param>
 public ConjugatedEncoder(IStereoEncoder left, IStereoEncoder right)
 {
     this.left  = left;
     this.right = right;
 }
Exemplo n.º 10
0
 /// <summary>
 /// Internal method invoked by 'molecule' hash generators.
 /// </summary>
 /// <param name="current">the current invariants</param>
 /// <param name="encoder">encoder used for encoding stereo-chemistry</param>
 /// <param name="graph">adjacency list representation of the molecule</param>
 /// <param name="suppressed">bit set marks vertices which are 'suppressed' (may be ignored)</param>
 /// <returns>the atom hash values</returns>
 public abstract long[] Generate(long[] current, IStereoEncoder encoder, int[][] graph, Suppressed suppressed);
        /// <summary>
        /// Create a stereo encoder for cumulative double bonds.
        /// </summary>
        /// <param name="container">the container</param>
        /// <param name="graph">adjacency list representation of the container</param>
        /// <returns>a stereo encoder</returns>
        public IStereoEncoder Create(IAtomContainer container, int[][] graph)
        {
            int     n   = container.Atoms.Count;
            BondMap map = new BondMap(n);

            var encoders = new List <IStereoEncoder>(1);

            // index double bonds by their atoms
            foreach (var bond in container.Bonds)
            {
                if (IsDoubleBond(bond))
                {
                    map.Add(bond);
                }
            }

            var visited = new HashSet <IAtom>();

            // find atoms which are connected between two double bonds
            foreach (var a in map.Atoms)
            {
                var bonds = map.bonds[a];
                if (bonds.Count == 2)
                {
                    // (s)tart/(e)nd of cumulated system: -s=a=e-
                    IAtom s = bonds[0].GetOther(a);
                    IAtom e = bonds[1].GetOther(a);
                    // need the parents to re-use the double bond encoder
                    IAtom sParent = a;
                    IAtom eParent = a;

                    visited.Add(a);
                    visited.Add(s);
                    visited.Add(e);

                    int size = 2;

                    // expand out from 'l'
                    while (s != null && map.Cumulated(s))
                    {
                        IAtom p = map.bonds[s][0].GetOther(s);
                        IAtom q = map.bonds[s][1].GetOther(s);
                        sParent = s;
                        s       = visited.Add(p) ? p : visited.Add(q) ? q : null;
                        size++;
                    }

                    // expand from 'r'
                    while (e != null && map.Cumulated(e))
                    {
                        IAtom p = map.bonds[e][0].GetOther(e);
                        IAtom q = map.bonds[e][1].GetOther(e);
                        eParent = e;
                        e       = visited.Add(p) ? p : visited.Add(q) ? q : null;
                        size++;
                    }

                    // s and e are null if we had a cumulative cycle...
                    if (s != null && e != null)
                    {
                        // system has now be expanded, size is the number of double
                        // bonds. For odd numbers we use E/Z whilst for even are
                        // axial M/P.
                        //  \           /
                        //   s = = = = e
                        //  /           \
                        if (IsOdd(size))
                        {
                            IStereoEncoder encoder = GeometricDoubleBondEncoderFactory.NewEncoder(container, s, sParent, e,
                                                                                                  eParent, graph);
                            if (encoder != null)
                            {
                                encoders.Add(encoder);
                            }
                        }
                        else
                        {
                            IStereoEncoder encoder = AxialEncoder(container, s, e);
                            if (encoder != null)
                            {
                                encoders.Add(encoder);
                            }
                        }
                    }
                }
            }

            return(encoders.Count == 0 ? StereoEncoder.Empty : new MultiStereoEncoder(encoders));
        }