a
    ߙfbR                     @   sF  d Z ddlZddlmZ ddlmZ g dZd,ddZd-d
dZG dd deZ	G dd de	Z
G dd de	ZG dd de	ZG dd de	ZG dd de	ZG dd deZG dd de	ZG dd de	ZG dd de	ZG d d! d!e	ZG d"d# d#e	ZG d$d% d%e	ZG d&d' d'e	ZG d(d) d)e	ZG d*d+ d+ee	ZdS ).z
Classes that deal with stretching, i.e. mapping a range of [0:1] values onto
another set of [0:1] values with a transformation
    N   )BaseTransform)CompositeTransform)BaseStretchLinearStretchSqrtStretchPowerStretchPowerDistStretchSquaredStretch
LogStretchAsinhStretchSinhStretchHistEqStretchContrastBiasStretchCompositeStretchc                 C   sH   |du rt |t |  S t j||d t j|t | |d |S dS )zCalculate the log base n of x.Nout)nplogtrue_divide)nxr    r   <lib/python3.9/site-packages/astropy/visualization/stretch.py_logn   s
    r   Tc                 C   sF   |rt j| dd|dS |du r,t j| ddS t | |dd< |S dS )z
    Prepare the data by optionally clipping and copying, and return the
    array that should be subsequently used for in-place calculations.
                  ?r   NT)copy)r   clipZarrayZasarray)valuesr   r   r   r   r   _prepare   s    r    c                   @   s:   e Zd ZdZedd Zdd Zddd	Zed
d ZdS )r   z
    Base class for the stretch classes, which, when called with an array
    of values in the range [0:1], return an transformed array of values,
    also in the range [0:1].
    c                 C   s   dS )NFr   selfr   r   r   _supports_invalid_kw6   s    z BaseStretch._supports_invalid_kwc                 C   s
   t || S N)r   )r"   otherr   r   r   __add__:   s    zBaseStretch.__add__TNc                 C   s   dS )ac  
        Transform values using this stretch.

        Parameters
        ----------
        values : array-like
            The input values, which should already be normalized to the
            [0:1] range.
        clip : bool, optional
            If `True` (default), values outside the [0:1] range are
            clipped to the [0:1] range.
        out : ndarray, optional
            If specified, the output values will be placed in this array
            (typically used for in-place calculations).

        Returns
        -------
        result : ndarray
            The transformed values.
        Nr   r"   r   r   r   r   r   r   __call__=   s    zBaseStretch.__call__c                 C   s   dS )5A stretch object that performs the inverse operation.Nr   r!   r   r   r   inverseS   s    zBaseStretch.inverse)TN)	__name__
__module____qualname____doc__propertyr#   r&   r(   r*   r   r   r   r   r   /   s   

r   c                       s8   e Zd ZdZd fdd	Zddd	Zed
d Z  ZS )r   as  
    A linear stretch with a slope and offset.

    The stretch is given by:

    .. math::
        y = slope x + intercept

    Parameters
    ----------
    slope : float, optional
        The ``slope`` parameter used in the above formula.  Default is 1.
    intercept : float, optional
        The ``intercept`` parameter used in the above formula.  Default is 0.
    r   r   c                    s   t    || _|| _d S r$   )super__init__slope	intercept)r"   r2   r3   	__class__r   r   r1   i   s    
zLinearStretch.__init__TNc                 C   sJ   t |||d}| jdkr*tj|| j|d | jdkrFtj|| j|d |S )Nr   r   r   r   r   )r    r2   r   multiplyr3   addr'   r   r   r   r(   n   s    

zLinearStretch.__call__c                 C   s   t d| j | j | j S r)   r   )r   r2   r3   r!   r   r   r   r*   v   s    zLinearStretch.inverse)r   r   )TN	r+   r,   r-   r.   r1   r(   r/   r*   __classcell__r   r   r4   r   r   X   s
   
r   c                   @   s2   e Zd ZdZedd Zd
ddZedd	 ZdS )r   zb
    A square root stretch.

    The stretch is given by:

    .. math::
        y = \sqrt{x}
    c                 C   s   dS NTr   r!   r   r   r   r#      s    z SqrtStretch._supports_invalid_kwTNc                 C   sr   t |||d}| o|du}tjdd* |r6|dk }tj||d W d   n1 sX0    Y  |rn|||< |S )Z  
        Transform values using this stretch.

        Parameters
        ----------
        values : array-like
            The input values, which should already be normalized to the
            [0:1] range.
        clip : bool, optional
            If `True` (default), values outside the [0:1] range are
            clipped to the [0:1] range.
        out : ndarray, optional
            If specified, the output values will be placed in this array
            (typically used for in-place calculations).
        invalid : None or float, optional
            Value to assign NaN values generated by this class.  NaNs in
            the input ``values`` array are not changed.  This option is
            generally used with matplotlib normalization classes, where
            the ``invalid`` value should map to the matplotlib colormap
            "under" value (i.e., any finite value < 0).  If `None`, then
            NaN values are not replaced.  This keyword has no effect if
            ``clip=True``.

        Returns
        -------
        result : ndarray
            The transformed values.
        r6   Nignoreinvalidr   r   )r    r   errstateZsqrtr"   r   r   r   r@   Zreplace_invalididxr   r   r   r(      s    ,zSqrtStretch.__call__c                 C   s   t dS )r)      )r   r!   r   r   r   r*      s    zSqrtStretch.inverse)TNN)r+   r,   r-   r.   r/   r#   r(   r*   r   r   r   r   r   |   s   	

,r   c                       sB   e Zd ZdZedd Z fddZddd	Zed
d Z  Z	S )r   z
    A power stretch.

    The stretch is given by:

    .. math::
        y = x^a

    Parameters
    ----------
    a : float
        The power index (see the above formula).  ``a`` must be greater
        than 0.
    c                 C   s   dS r<   r   r!   r   r   r   r#      s    z!PowerStretch._supports_invalid_kwc                    s$   t    |dkrtd|| _d S Nr   za must be > 0)r0   r1   
ValueErrorpowerr"   ar4   r   r   r1      s    
zPowerStretch.__init__TNc                 C   s   t |||d}| oN|duoNd| j  k o0dk n  pNd| j  k oJdk n  }tjdd. |rj|dk }tj|| j|d W d   n1 s0    Y  |r|||< |S )	r=   r6   Nr   r   r>   r?   r   )r    rG   r   rA   rB   r   r   r   r(      s    0zPowerStretch.__call__c                 C   s   t d| j S r9   )r   rG   r!   r   r   r   r*     s    zPowerStretch.inverse)TNN
r+   r,   r-   r.   r/   r#   r1   r(   r*   r;   r   r   r4   r   r      s   

.r   c                       s8   e Zd ZdZd fdd	ZdddZed	d
 Z  ZS )r	   aI  
    An alternative power stretch.

    The stretch is given by:

    .. math::
        y = \frac{a^x - 1}{a - 1}

    Parameters
    ----------
    a : float, optional
        The ``a`` parameter used in the above formula.  ``a`` must be
        greater than or equal to 0, but cannot be set to 1.  Default is
        1000.
         @@c                    s,   |dk s|dkrt dt   || _d S Nr   r   z&a must be >= 0, but cannot be set to 1rF   r0   r1   exprH   r4   r   r   r1     s    
zPowerDistStretch.__init__TNc                 C   sJ   t |||d}tj| j||d tj|d|d tj|| jd |d |S )Nr6   r   r   r   )r    r   rG   rO   subtractr   r'   r   r   r   r(   !  s
    zPowerDistStretch.__call__c                 C   s   t | jdS r)   rI   )InvertedPowerDistStretchrO   r!   r   r   r   r*   (  s    zPowerDistStretch.inverse)rL   )TNr:   r   r   r4   r   r	   
  s
   
r	   c                       s8   e Zd ZdZd fdd	ZdddZed	d
 Z  ZS )rS   a  
    Inverse transformation for
    `~astropy.image.scaling.PowerDistStretch`.

    The stretch is given by:

    .. math::
        y = \frac{\log(y (a-1) + 1)}{\log a}

    Parameters
    ----------
    a : float, optional
        The ``a`` parameter used in the above formula.  ``a`` must be
        greater than or equal to 0, but cannot be set to 1.  Default is
        1000.
    rL   c                    s,   |dk s|dkrt dt   || _d S rM   rN   rH   r4   r   r   r1   @  s    
z!InvertedPowerDistStretch.__init__TNc                 C   sH   t |||d}tj|| jd |d tj|d|d t| j||d |S )Nr6   r   r   r   )r    r   r7   rO   r8   r   r'   r   r   r   r(   F  s
    z!InvertedPowerDistStretch.__call__c                 C   s   t | jdS rQ   )r	   rO   r!   r   r   r   r*   M  s    z InvertedPowerDistStretch.inverse)rL   )TNr:   r   r   r4   r   rS   .  s
   
rS   c                       s,   e Zd ZdZ fddZedd Z  ZS )r
   zt
    A convenience class for a power stretch of 2.

    The stretch is given by:

    .. math::
        y = x^2
    c                    s   t  d d S )NrD   )r0   r1   r!   r4   r   r   r1   ]  s    zSquaredStretch.__init__c                 C   s   t  S r)   )r   r!   r   r   r   r*   `  s    zSquaredStretch.inverse)r+   r,   r-   r.   r1   r/   r*   r;   r   r   r4   r   r
   S  s   	r
   c                       sD   e Zd ZdZedd Zd fdd	Zdd	d
Zedd Z  Z	S )r   a  
    A log stretch.

    The stretch is given by:

    .. math::
        y = \frac{\log{(a x + 1)}}{\log{(a + 1)}}

    Parameters
    ----------
    a : float
        The ``a`` parameter used in the above formula.  ``a`` must be
        greater than 0.  Default is 1000.
    c                 C   s   dS r<   r   r!   r   r   r   r#   v  s    zLogStretch._supports_invalid_kwrL   c                    s$   t    |dkrtd|| _d S rE   r0   r1   rF   rO   rH   r4   r   r   r1   z  s    
zLogStretch.__init__TNc                 C   s   t |||d}| o|du}tjddh |r6|dk }tj|| j|d tj|d|d tj||d tj|t| jd |d W d   n1 s0    Y  |r|||< |S )r=   r6   Nr>   r?   r   r   r   )r    r   rA   r7   rO   r8   r   r   rB   r   r   r   r(     s    :zLogStretch.__call__c                 C   s
   t | jS rT   )InvertedLogStretchrO   r!   r   r   r   r*     s    zLogStretch.inverse)rL   )TNNrK   r   r   r4   r   r   f  s   

/r   c                       s6   e Zd ZdZ fddZd
ddZedd	 Z  ZS )rV   at  
    Inverse transformation for `~astropy.image.scaling.LogStretch`.

    The stretch is given by:

    .. math::
        y = \frac{e^{y \log{a + 1}} - 1}{a} \\
        y = \frac{e^{y} (a + 1) - 1}{a}

    Parameters
    ----------
    a : float, optional
        The ``a`` parameter used in the above formula.  ``a`` must be
        greater than 0.  Default is 1000.
    c                    s$   t    |dkrtd|| _d S rE   rU   rH   r4   r   r   r1     s    
zInvertedLogStretch.__init__TNc                 C   s^   t |||d}tj|t| jd |d tj||d tj|d|d tj|| j|d |S )Nr6   r   r   )r    r   r7   r   rO   rP   r   r'   r   r   r   r(     s    zInvertedLogStretch.__call__c                 C   s
   t | jS rT   )r   rO   r!   r   r   r   r*     s    zInvertedLogStretch.inverse)TNr:   r   r   r4   r   rV     s
   
rV   c                       s8   e Zd ZdZd fdd	ZdddZed	d
 Z  ZS )r   a  
    An asinh stretch.

    The stretch is given by:

    .. math::
        y = \frac{{\rm asinh}(x / a)}{{\rm asinh}(1 / a)}.

    Parameters
    ----------
    a : float, optional
        The ``a`` parameter used in the above formula.  The value of
        this parameter is where the asinh curve transitions from linear
        to logarithmic behavior, expressed as a fraction of the
        normalized image.  ``a`` must be greater than 0 and less than or
        equal to 1 (0 < a <= 1).  Default is 0.1.
    皙?c                    s,   t    |dks|dkr"td|| _d S Nr   r   za must be > 0 and <= 1r0   r1   rF   rI   rH   r4   r   r   r1     s    
zAsinhStretch.__init__TNc                 C   sN   t |||d}tj|| j|d tj||d tj|td| j |d |S Nr6   r   r   )r    r   r   rI   arcsinhr'   r   r   r   r(     s
    zAsinhStretch.__call__c                 C   s   t dtd| j  dS r)   r   rR   )r   r   r[   rI   r!   r   r   r   r*     s    zAsinhStretch.inverse)rW   )TNr:   r   r   r4   r   r     s
   
r   c                       s8   e Zd ZdZd fdd	ZdddZed	d
 Z  ZS )r   aT  
    A sinh stretch.

    The stretch is given by:

    .. math::
        y = \frac{{\rm sinh}(x / a)}{{\rm sinh}(1 / a)}

    Parameters
    ----------
    a : float, optional
        The ``a`` parameter used in the above formula.  ``a`` must be
        greater than 0 and less than or equal to 1 (0 < a <= 1).
        Default is 1/3.
    UUUUUU?c                    s,   t    |dks|dkr"td|| _d S rX   rY   rH   r4   r   r   r1     s    
zSinhStretch.__init__TNc                 C   sN   t |||d}tj|| j|d tj||d tj|td| j |d |S rZ   )r    r   r   rI   sinhr'   r   r   r   r(     s
    zSinhStretch.__call__c                 C   s   t dtd| j  dS r\   )r   r   r^   rI   r!   r   r   r   r*     s    zSinhStretch.inverse)r]   )TNr:   r   r   r4   r   r      s
   
r   c                   @   s0   e Zd ZdZd
ddZdddZedd	 ZdS )r   a  
    A histogram equalization stretch.

    Parameters
    ----------
    data : array-like
        The data defining the equalization.
    values : array-like, optional
        The input image values, which should already be normalized to
        the [0:1] range.
    Nc                 C   sv   t | | _| jt | j | _| j }| j }| j| ||  | _|d u rlt ddt| j| _	n|| _	d S Nr   r   )
r   sortZraveldataisfiniteminmaxlinspacelenr   )r"   ra   r   ZvminZvmaxr   r   r   r1   1  s    

zHistEqStretch.__init__Tc                 C   s,   t |||d}t|| j| j|d d < |S Nr6   )r    r   interpra   r   r'   r   r   r   r(   ?  s    zHistEqStretch.__call__c                 C   s   t | j| jdS r)   )r   )InvertedHistEqStretchra   r   r!   r   r   r   r*   D  s    zHistEqStretch.inverse)N)TNr+   r,   r-   r.   r1   r(   r/   r*   r   r   r   r   r   $  s
   

r   c                   @   s0   e Zd ZdZd
ddZdddZedd	 ZdS )rj   a.  
    Inverse transformation for `~astropy.image.scaling.HistEqStretch`.

    Parameters
    ----------
    data : array-like
        The data defining the equalization.
    values : array-like, optional
        The input image values, which should already be normalized to
        the [0:1] range.
    Nc                 C   s:   |t | | _|d u r0t ddt| j| _n|| _d S r_   )r   rb   ra   re   rf   r   )r"   ra   r   r   r   r   r1   W  s    zInvertedHistEqStretch.__init__Tc                 C   s,   t |||d}t|| j| j|d d < |S rg   )r    r   rh   r   ra   r'   r   r   r   r(   ^  s    zInvertedHistEqStretch.__call__c                 C   s   t | j| jdS ri   )r   ra   r   r!   r   r   r   r*   c  s    zInvertedHistEqStretch.inverse)N)TNrk   r   r   r   r   rj   J  s
   

rj   c                       s6   e Zd ZdZ fddZd
ddZedd	 Z  ZS )r   a  
    A stretch that takes into account contrast and bias.

    The stretch is given by:

    .. math::
        y = (x - {\rm bias}) * {\rm contrast} + 0.5

    and the output values are clipped to the [0:1] range.

    Parameters
    ----------
    contrast : float
        The contrast parameter (see the above formula).

    bias : float
        The bias parameter (see the above formula).
    c                    s   t    || _|| _d S r$   r0   r1   contrastbiasr"   rm   rn   r4   r   r   r1   }  s    
zContrastBiasStretch.__init__TNc                 C   s\   t |d|d}tj|| j|d tj|| j|d tj|d|d |rXtj|dd|d |S )NFr6   r         ?r   r   )r    r   rP   rn   r7   rm   r8   r   r'   r   r   r   r(     s    zContrastBiasStretch.__call__c                 C   s   t | j| jS rT   )InvertedContrastBiasStretchrm   rn   r!   r   r   r   r*     s    zContrastBiasStretch.inverse)TNr:   r   r   r4   r   r   i  s
   
r   c                       s6   e Zd ZdZ fddZd
ddZedd	 Z  ZS )rq   a1  
    Inverse transformation for ContrastBiasStretch.

    Parameters
    ----------
    contrast : float
        The contrast parameter (see
        `~astropy.visualization.ConstrastBiasStretch).

    bias : float
        The bias parameter (see
        `~astropy.visualization.ConstrastBiasStretch).
    c                    s   t    || _|| _d S r$   rl   ro   r4   r   r   r1     s    
z$InvertedContrastBiasStretch.__init__TNc                 C   s\   t |d|d}tj|d|d tj|| j|d tj|| j|d |rXtj|dd|d |S )NFr6   rp   r   r   r   )r    r   rP   r   rm   r8   rn   r   r'   r   r   r   r(     s    z$InvertedContrastBiasStretch.__call__c                 C   s   t | j| jS rT   )r   rm   rn   r!   r   r   r   r*     s    z#InvertedContrastBiasStretch.inverse)TNr:   r   r   r4   r   rq     s
   
rq   c                   @   s   e Zd ZdZdddZdS )r   a  
    A combination of two stretches.

    Parameters
    ----------
    stretch_1 : :class:`astropy.visualization.BaseStretch`
        The first stretch to apply.
    stretch_2 : :class:`astropy.visualization.BaseStretch`
        The second stretch to apply.
    TNc                 C   s   | j | j|||d||dS rg   )Ztransform_2Ztransform_1r'   r   r   r   r(     s    zCompositeStretch.__call__)TN)r+   r,   r-   r.   r(   r   r   r   r   r     s   r   )N)TN)r.   Znumpyr   Z	transformr   r   __all__r   r    r   r   r   r   r	   rS   r
   r   rV   r   r   r   rj   r   rq   r   r   r   r   r   <module>   s,   

)$@N$%O%&$&-'