예제 #1
0
        /// <summary>
        /// Calculates 11 directional and 6 non-directional WHIM descriptors for.
        /// the specified weighting scheme
        /// </summary>
        /// <returns>An ArrayList containing the descriptors in the order described above.</returns>
        public Result Calculate(IAtomContainer container, AtomWeightingType type = AtomWeightingType.Unity)
        {
            if (!GeometryUtil.Has3DCoordinates(container))
            {
                throw new ThreeDRequiredException("Molecule must have 3D coordinates");
            }

            double sum = 0.0;
            var    ac  = (IAtomContainer)container.Clone();

            // do aromaticity detecttion for calculating polarizability later on
            //HueckelAromaticityDetector had = new HueckelAromaticityDetector();
            //had.DetectAromaticity(ac);

            // get the coordinate matrix
            var cmat = Arrays.CreateJagged <double>(ac.Atoms.Count, 3);

            for (int i = 0; i < ac.Atoms.Count; i++)
            {
                var coords = ac.Atoms[i].Point3D.Value;
                cmat[i][0] = coords.X;
                cmat[i][1] = coords.Y;
                cmat[i][2] = coords.Z;
            }

            // set up the weight vector
            var wt = new double[ac.Atoms.Count];
            IReadOnlyDictionary <int, double> hash = null;

            switch (type)
            {
            case AtomWeightingType.Mass:
                hash = hashatwt;
                break;

            case AtomWeightingType.Volume:
                hash = hashvdw;
                break;

            case AtomWeightingType.Electronegativity:
                hash = hasheneg;
                break;

            case AtomWeightingType.Polarizability:
                hash = hashpol;
                break;

            default:
                break;
            }
            switch (type)
            {
            case AtomWeightingType.Unity:
                for (int i = 0; i < ac.Atoms.Count; i++)
                {
                    wt[i] = 1.0;
                }
                break;

            default:
                for (int i = 0; i < ac.Atoms.Count; i++)
                {
                    wt[i] = hash[ac.Atoms[i].AtomicNumber];
                }
                break;
            }

            PCA pcaobject = null;

            try
            {
                pcaobject = new PCA(cmat, wt);
            }
            catch (CDKException cdke)
            {
                Debug.WriteLine(cdke);
            }

            // directional WHIM's
            var lambda = pcaobject.GetEigenvalues();
            var gamma  = new double[3];
            var nu     = new double[3];
            var eta    = new double[3];

            for (int i = 0; i < 3; i++)
            {
                sum += lambda[i];
            }
            for (int i = 0; i < 3; i++)
            {
                nu[i] = lambda[i] / sum;
            }

            var scores = pcaobject.GetScores();

            for (int i = 0; i < 3; i++)
            {
                sum = 0.0;
                for (int j = 0; j < ac.Atoms.Count; j++)
                {
                    sum += scores[j][i] * scores[j][i] * scores[j][i] * scores[j][i];
                }
                sum    = sum / (lambda[i] * lambda[i] * ac.Atoms.Count);
                eta[i] = 1.0 / sum;
            }

            // look for symmetric & asymmetric atoms for the gamma descriptor
            for (int i = 0; i < 3; i++)
            {
                double ns = 0.0;
                double na = 0.0;
                for (int j = 0; j < ac.Atoms.Count; j++)
                {
                    bool foundmatch = false;
                    for (int k = 0; k < ac.Atoms.Count; k++)
                    {
                        if (k == j)
                        {
                            continue;
                        }
                        if (scores[j][i] == -1 * scores[k][i])
                        {
                            ns++;
                            foundmatch = true;
                            break;
                        }
                    }
                    if (!foundmatch)
                    {
                        na++;
                    }
                }
                var n = (double)ac.Atoms.Count;
                gamma[i] = -1.0 * ((ns / n) * Math.Log(ns / n) / Math.Log(2.0) + (na / n) * Math.Log(1.0 / n) / Math.Log(2.0));
                gamma[i] = 1.0 / (1.0 + gamma[i]);
            }
            {
                // non directional WHIMS's
                var t = lambda[0] + lambda[1] + lambda[2];
                var a = lambda[0] * lambda[1] + lambda[0] * lambda[2] + lambda[1] * lambda[2];
                var v = t + a + lambda[0] * lambda[1] * lambda[2];

                double k = 0.0;
                sum = 0.0;
                for (int i = 0; i < 3; i++)
                {
                    sum += lambda[i];
                }
                for (int i = 0; i < 3; i++)
                {
                    k = (lambda[i] / sum) - (1.0 / 3.0);
                }
                k = k / (4.0 / 3.0);

                var g = Math.Pow(gamma[0] * gamma[1] * gamma[2], 1.0 / 3.0);
                var d = eta[0] + eta[1] + eta[2];

                // return all the stuff we calculated
                return(new Result(
                           lambda[0],
                           lambda[1],
                           lambda[2],

                           nu[0],
                           nu[1],

                           gamma[0],
                           gamma[1],
                           gamma[2],

                           eta[0],
                           eta[1],
                           eta[2],

                           t,
                           a,
                           v,
                           k,
                           g,
                           d));
            }
        }