[Scipy-svn] r5182 - in trunk/scipy/cluster: . src tests

scipy-svn@scip... scipy-svn@scip...
Mon Nov 24 16:09:46 CST 2008


Author: damian.eads
Date: 2008-11-24 16:09:34 -0600 (Mon, 24 Nov 2008)
New Revision: 5182

Modified:
   trunk/scipy/cluster/hierarchy.py
   trunk/scipy/cluster/src/hierarchy.c
   trunk/scipy/cluster/tests/test_hierarchy.py
Log:
Added regression tests for scipy.cluster.hierarchy.maxdists.

Modified: trunk/scipy/cluster/hierarchy.py
===================================================================
--- trunk/scipy/cluster/hierarchy.py	2008-11-24 09:54:25 UTC (rev 5181)
+++ trunk/scipy/cluster/hierarchy.py	2008-11-24 22:09:34 UTC (rev 5182)
@@ -1212,7 +1212,7 @@
             else:
                 raise ValueError('Linkage matrix must have 4 columns.')
         if Z.shape[0] == 0:
-            raise ValueError('Linkage must be over at least one observation.')
+            raise ValueError('Linkage must be computed on at least two observations.')
         n = Z.shape[0]
         if n > 1:
             if ((Z[:,0] < 0).any() or
@@ -2376,13 +2376,13 @@
           specifically, ``MD[i] = Z[Q(i)-n, 2].max()`` where ``Q(i)`` is the
           set of all node indices below and including node i.
     """
-    Z = np.asarray(Z, order='c')
+    Z = np.asarray(Z, order='c', dtype=np.double)
     is_valid_linkage(Z, throw=True, name='Z')
 
     n = Z.shape[0] + 1
     MD = np.zeros((n-1,))
     [Z] = _copy_arrays_if_base_present([Z])
-    _hierarchy_wrap.get_max_dist_for_each_hierarchy_wrap(Z, MD, int(n))
+    _hierarchy_wrap.get_max_dist_for_each_cluster_wrap(Z, MD, int(n))
     return MD
 
 def maxinconsts(Z, R):

Modified: trunk/scipy/cluster/src/hierarchy.c
===================================================================
--- trunk/scipy/cluster/src/hierarchy.c	2008-11-24 09:54:25 UTC (rev 5181)
+++ trunk/scipy/cluster/src/hierarchy.c	2008-11-24 22:09:34 UTC (rev 5182)
@@ -841,7 +841,6 @@
 
     /** Rows i+1 to j-1 lose one unit of space, so we move them up. */
     /** Rows j to np-1 lose no space. We do nothing to them. */
-
     /**    memcpy(rows[0], buf, sizeof(double) * rowsize[0] - k);*/
 
     for (i = 0; i < mini; i++) {
@@ -1418,7 +1417,8 @@
       max_dist = CPY_MAX(max_dist, max_dists[rid-n]);
     }
     max_dists[ndid-n] = max_dist;
-    CPY_DEBUG_MSG("i=%d maxdist[i]=%5.5f verif=%5.5f\n", ndid-n, max_dist, max_dists[ndid-n]);
+    CPY_DEBUG_MSG("i=%d maxdist[i]=%5.5f verif=%5.5f\n",
+		  ndid-n, max_dist, max_dists[ndid-n]);
     k--;
   }
   free(curNode);

Modified: trunk/scipy/cluster/tests/test_hierarchy.py
===================================================================
--- trunk/scipy/cluster/tests/test_hierarchy.py	2008-11-24 09:54:25 UTC (rev 5181)
+++ trunk/scipy/cluster/tests/test_hierarchy.py	2008-11-24 22:09:34 UTC (rev 5182)
@@ -38,7 +38,7 @@
 import numpy as np
 from numpy.testing import *
 
-from scipy.cluster.hierarchy import linkage, from_mlab_linkage, to_mlab_linkage, num_obs_linkage, inconsistent, cophenet, from_mlab_linkage, fclusterdata, fcluster, is_isomorphic, single, complete, average, weighted, centroid, median, ward, leaders, correspond, is_monotonic
+from scipy.cluster.hierarchy import linkage, from_mlab_linkage, to_mlab_linkage, num_obs_linkage, inconsistent, cophenet, from_mlab_linkage, fclusterdata, fcluster, is_isomorphic, single, complete, average, weighted, centroid, median, ward, leaders, correspond, is_monotonic, maxdists
 from scipy.spatial.distance import squareform, pdist
 
 _tdist = np.array([[0,    662,  877,  255,  412,  996],
@@ -685,15 +685,109 @@
         Z = linkage(X, 'single')
         self.failUnless(is_monotonic(Z) == True)
 
-def help_single_inconsistent_depth(self, i):
-    Y = squareform(_tdist)
-    Z = linkage(Y, 'single')
-    R = inconsistent(Z, i)
-    Rright = eo['inconsistent-single-tdist-depth-' + str(i)]
-    eps = 1e-05
-    print np.abs(R - Rright).max()
-    self.failUnless(within_tol(R, Rright, eps))
+class TestMaxDists(TestCase):
 
+    def test_maxdists_empty_linkage(self):
+        "Tests maxdists(Z) on empty linkage. Expecting exception."
+        Z = np.zeros((0, 4), dtype=np.double)
+        self.failUnlessRaises(ValueError, maxdists, Z)
+
+    def test_maxdists_one_cluster_linkage(self):
+        "Tests maxdists(Z) on linkage with one cluster."
+        Z = np.asarray([[0, 1, 0.3, 4]], dtype=np.double)
+        MD = maxdists(Z)
+        eps = 1e-15
+        expectedMD = calculate_maximum_distances(Z)
+        self.failUnless(within_tol(MD, expectedMD, eps))
+
+    def test_maxdists_Q_linkage_single(self):
+        "Tests maxdists(Z) on the Q data set using single linkage."
+        X = eo['Q-X']
+        Y = pdist(X)
+        Z = linkage(X, 'single')
+        MD = maxdists(Z)
+        eps = 1e-15
+        expectedMD = calculate_maximum_distances(Z)
+        self.failUnless(within_tol(MD, expectedMD, eps))
+
+    def test_maxdists_Q_linkage_complete(self):
+        "Tests maxdists(Z) on the Q data set using complete linkage."
+        X = eo['Q-X']
+        Y = pdist(X)
+        Z = linkage(X, 'complete')
+        MD = maxdists(Z)
+        eps = 1e-15
+        expectedMD = calculate_maximum_distances(Z)
+        self.failUnless(within_tol(MD, expectedMD, eps))
+
+    def test_maxdists_Q_linkage_ward(self):
+        "Tests maxdists(Z) on the Q data set using Ward linkage."
+        X = eo['Q-X']
+        Y = pdist(X)
+        Z = linkage(X, 'ward')
+        MD = maxdists(Z)
+        eps = 1e-15
+        expectedMD = calculate_maximum_distances(Z)
+        self.failUnless(within_tol(MD, expectedMD, eps))
+
+    def test_maxdists_Q_linkage_centroid(self):
+        "Tests maxdists(Z) on the Q data set using centroid linkage."
+        X = eo['Q-X']
+        Y = pdist(X)
+        Z = linkage(X, 'centroid')
+        MD = maxdists(Z)
+        eps = 1e-15
+        expectedMD = calculate_maximum_distances(Z)
+        print np.abs(expectedMD - MD)
+        print is_monotonic(Z)
+        self.failUnless(within_tol(MD, expectedMD, eps))
+
+    def test_maxdists_Q_linkage_median(self):
+        "Tests maxdists(Z) on the Q data set using median linkage."
+        X = eo['Q-X']
+        Y = pdist(X)
+        Z = linkage(X, 'median')
+        MD = maxdists(Z)
+        eps = 1e-15
+        expectedMD = calculate_maximum_distances(Z)
+        print np.abs(expectedMD - MD).max()
+        print is_monotonic(Z)
+        self.failUnless(within_tol(MD, expectedMD, eps))
+
+def calculate_maximum_distances(Z):
+    "Used for testing correctness of maxdists. Very slow."
+    n = Z.shape[0] + 1
+    B = np.zeros((n-1,))
+    q = np.zeros((3,))
+    for i in xrange(0, n - 1):
+        q[:] = 0.0
+        L = Z[i, 0]
+        R = Z[i, 1]
+        if L >= n:
+            q[0] = B[L - n]
+        if R >= n:
+            q[1] = B[R - n]
+        q[2] = Z[i, 2]
+        B[i] = q.max()
+    return B
+
+def calculate_maximum_inconsistent(Z, R):
+    "Used for testing correctness of maxinconsts. Very slow."
+    n = Z.shape[0] + 1
+    B = np.zeros((n-1,))
+    q = np.zeros((3,))
+    for i in xrange(0, n - 1):
+        q[:] = 0.0
+        L = Z[i, 0]
+        R = Z[i, 1]
+        if L >= n:
+            q[0] = B[L - n]
+        if R >= n:
+            q[1] = B[R - n]
+        q[2] = R[i, 2]
+        B[i] = q.max()
+    return B
+
 def within_tol(a, b, tol):
     return np.abs(a - b).max() < tol
 



More information about the Scipy-svn mailing list