Fit model parameters to data using the RANSAC algorithm

    This implementation is written from pseudo-code found at
    http://en.wikipedia.org/w/index.php?title=RANSAC&oldid=116358182

    :param npts: A set of observed data points
    :param model: A model that can be fitted to data points
    :param n: The minimum number of data values required to fit the model
    :param k: The maximum number of iterations allowed in the algorithm
    :param t: A threshold value for determining when a data point fits a model
    :param d: The number of close data values required to assert that a model fits well to data
    :return: Model parameters which best fit the data (or None if no good model is found)

def ransac(npts, model, n, k, t, d):
    """ Fit model parameters to data using the RANSAC algorithm

    This implementation is written from pseudo-code found at
    http://en.wikipedia.org/w/index.php?title=RANSAC&oldid=116358182

    :param npts: A set of observed data points
    :param model: A model that can be fitted to data points
    :param n: The minimum number of data values required to fit the model
    :param k: The maximum number of iterations allowed in the algorithm
    :param t: A threshold value for determining when a data point fits a model
    :param d: The number of close data values required to assert that a model fits well to data
    :return: Model parameters which best fit the data (or None if no good model is found)
    """
    iterations = 0
    bestfit = None
    besterr = np.inf
    # best_inlier_idxs = None
    while iterations < k:
        maybe_idxs, test_idxs = random_partition(n, npts)
        maybemodel = model.fit(maybe_idxs)
        test_err = model.score(test_idxs, maybemodel)
        also_idxs = test_idxs[test_err < t]  # select indices of rows with accepted points

        LOGGER.debug('test_err.min() %f', test_err.min() if test_err.size else None)
        LOGGER.debug('test_err.max() %f', test_err.max() if test_err.size else None)
        LOGGER.debug('numpy.mean(test_err) %f', np.mean(test_err) if test_err.size else None)
        LOGGER.debug('iteration %d, len(alsoinliers) = %d', iterations, len(also_idxs))

        if len(also_idxs) > d:
            betteridxs = np.concatenate((maybe_idxs, also_idxs))
            bettermodel = model.fit(betteridxs)
            better_errs = model.score(betteridxs, bettermodel)
            thiserr = np.mean(better_errs)
            if thiserr < besterr:
                bestfit = bettermodel
                besterr = thiserr
                # best_inlier_idxs = np.concatenate((maybe_idxs, also_idxs))
        iterations += 1
    return bestfit