def __init__(self, features, mask=None, specs=['kl'], Ks=[3],
                 cores=None, algorithm=None, min_dist=None,
                 status_fn=True, progressbar=None, **flann_args):
        if progressbar is None:
            progressbar = status_fn is True
        self.status_fn = status_fn = get_status_fn(status_fn)
        self.progressbar = progressbar

        if not isinstance(features, Features):
            raise TypeError("features should be a Features instance")
        n_bags = len(features)
        dim = features.dim
        self.features = features

        if mask is None:
            mask = np.ones((n_bags, n_bags), dtype=bool)
        else:
            mask = np.asarray(mask)
            if mask.shape != (n_bags, n_bags):
                msg = "mask should be n x n, not {}"
                raise TypeError(msg.format(mask.shape))
            elif mask.dtype.kind != 'b':
                msg = "mask should be a boolean array, not {}"
                raise TypeError(msg.format(mask.dtype))
        self.mask = mask

        self.Ks = Ks = np.array(np.squeeze(Ks), ndmin=1, dtype=np.int32)
        if Ks.ndim != 1:
            msg = "Ks should be 1-dim, got shape {}"
            raise TypeError(msg.format(Ks.shape))
        if Ks.min() < 1:
            raise ValueError("Ks should be positive; got {}".format(Ks.min()))
        if Ks.max() >= features._n_pts.min():
            msg = "asked for K = {}, but there's a bag with only {} points"
            raise ValueError(msg.format(Ks.max(), features._n_pts.min()))
        self.max_K = Ks.max()

        self.funcs, self.metas, self.n_meta_only = \
                _parse_specs(specs, Ks, dim, features._n_pts)
        self.specs = specs

        self.save_all_Ks = False
        for func in self.funcs:
            if hasattr(func, 'k_needed'):
                self.max_K = max(self.max_K, func.k_needed)
                self.save_all_Ks = True
                # TODO: could be more efficient about this
                # eg if we need [1, 2, ..., 5] and 20, no need to save 6 to 19
                # (but that won't happen with the current estimators)

        if cores is None:
            from multiprocessing import cpu_count
            cores = cpu_count()
        flann_args['cores'] = cores

        if algorithm is None:
            algorithm = pick_flann_algorithm(dim)
        flann_args['algorithm'] = algorithm

        try:
            FLANNParameters(**flann_args)
        except __HOLE__ as e:
            msg = "_DivEstimator got an unexpected keyword argument:\n  {}"
            raise TypeError(msg.format(e))
        self.flann_args = flann_args

        if min_dist is None:
            min_dist = default_min_dist(dim)
        self.min_dist = min_dist

        status_fn('kNN processing: K = {} on {!r}'.format(self.max_K, features))
dataset/ETHPy150Open dougalsutherland/py-sdm/sdm/np_divs.py/_DivEstimator.__init__