Commit fe92b000 authored by Jay's avatar Jay Committed by Jason R Laura
Browse files

Refinement added back in.

parent 08c77fac
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -78,5 +78,15 @@ class TestFundamentalMatrix(unittest.TestCase):
        self.assertEqual(self.F.rank, 3)

    def test_f_refine(self):
        r = self.F.refine()
        self.assertIsNone(r)
        # This should raise an error.
        self.F.refine()
        self.assertEqual(len(self.F._action_stack), 1)

        # Previous error should preclude do/undo
        self.F.rollback()
        self.assertEqual(self.F._current_action_stack, 0)
        self.F.rollforward()
        self.assertEqual(self.F._current_action_stack, 0)

        self.F._clean_attrs()
        self.assertNotIn('_error', self.F.__dict__)
 No newline at end of file
+56 −2
Original line number Diff line number Diff line
@@ -186,8 +186,62 @@ class FundamentalMatrix(TransformationMatrix):
            warnings.warn('F rank not equal to 2.  This indicates a poor F matrix.')
        return rank

    def refine(self):
        pass
    def refine(self, method=ps.esda.mapclassify.Fisher_Jenks, values=None, bin_id=0, **kwargs):
        """
        Refine the fundamental matrix by accepting some data classification
        method that accepts an ndarray and returns an object with a bins
        attribute, where bins are data breaks.  Using the bin_id, mask
        all values greater than the selected bin.  Then compute a
        new fundamental matrix.
        The matrix is "refined" based on the reprojection errors for
        each point.
        Parameters
        ----------
        method : object
                 A function that accepts and ndarray and returns an object
                 with a bins attribute
        values      : ndarray
                      (n,1) of values to use used for classification
        bin_id : int
                 The index into the bins object.  Data classified > this
                 id is masked
        kwargs : dict
                 Keyword args supported by the data classifier
        Returns
        -------
        FundamentalMatrix : object
                            A fundamental matrix class object
        mask : series
               A bool mask with index attribute identifying the valid
               data in the new fundamental matrix.
        """
        # Perform the data classification
        if values is None:
            values = self.error
        fj = method(values.ravel(), **kwargs)
        # Mask the data that falls outside the provided bins
        mask = values <= fj.yb[bin_id]
        new_x1 = self.x1.iloc[mask[mask == True].index]
        new_x2 = self.x2.iloc[mask[mask == True].index]
        fmatrix, new_mask = compute_fundamental_matrix(new_x1.values, new_x2.values)
        mask[mask == True] = new_mask

        # Update the current state
        self[:] = fmatrix
        self.mask = mask

        # Update the action stack
        try:
            state_package = {'arr': fmatrix.copy(),
                             'mask': self.mask.copy()}

            self._action_stack.append(state_package)
            self._current_action_stack = len(self._action_stack) - 1  # 0 based vs. 1 based
            self._clean_attrs()
            self._notify_subscribers(self)
        except:
            warnings.warn('Refinement outlier detection removed all observations.',
                          UserWarning)

    def _clean_attrs(self):
        for a in ['_error', '_determinant', '_condition']: