"""
Classes that deal with computing intervals from arrays of values based on
various criteria.
"""

import abc

import numpy as np

from astropy.extern import six

__all__ = ['ManualInterval', 'MinMaxInterval', 'PercentileInterval']


@six.add_metaclass(abc.ABCMeta)
class BaseInterval(object):
    pass


class ManualInterval(BaseInterval):
    """
    Interval based on user-specified values.

    Parameters
    ----------
    vmin : float
        The minimum value in the scaling
    vmax : float
        The maximum value in the scaling
    """

    def __init__(self, vmin, vmax):
        self.vmin = vmin
        self.vmax = vmax

    def get_limits(self, values):
        return self.vmin, self.vmax


class MinMaxInterval(BaseInterval):
    """
    Interval based on the minimum and maximum values in the data.
    """

    def get_limits(self, values):
        return np.min(values), np.max(values)


class PercentileInterval(BaseInterval):
    """
    Interval based on a keeping a specified fraction of pixels

    Parameters
    ----------
    percentile : float
        The fraction of pixels to keep. The same fraction of pixels is
        eliminated from both ends.
    """

    def __init__(self, percentile):
        self.percentile = percentile

    def get_limits(self, values):

        pmin = (100. - self.percentile) * 0.5
        pmax = 100. - pmin

        # Filter out invalid values (inf, nan)
        values = values[np.isfinite(values)]

        # Determine values at percentiles
        vmin = np.percentile(values, pmin)
        vmax = np.percentile(values, pmax)

        return vmin, vmax

@@ -1176,16 +1176,242 @@
 h ends.%0A
+    n_samples : int, optional%0A        Maximum number of values to use. If this is specified, and there are%0A        more values in the dataset as this, then values are randomly sampled%0A        from the array (with replacement)%0A
     %22%22%22%0A
@@ -1444,16 +1444,32 @@
 rcentile
+, n_samples=None
 ):%0A     
@@ -1504,42 +1504,327 @@
 ile%0A
-%0A    def get_limits(self, values):
+        self.n_samples = n_samples%0A%0A    def get_limits(self, values):%0A%0A        # If needed, limmit the number of samples. We sample with replacement%0A        # since this is much faster.%0A        if self.n_samples is not None and values.size %3E self.n_samples:%0A            values = np.random.choice(values, self.n_samples)
 %0A%0A  

Add the option to sub-sample the data for the PercentileInterval