
    IR-e                        d dl Z d dlmZmZ d dlmZ d dlZd dlm	Z	 d dl
mZmZmZ g dZej        ej        ej        ej        iZd Zd Zd	 Zej        d
 ej        eej        diZ G d de          Z G d de          Z G d de          Z G d de          Z G d d          Z G d dee          Z G d dee          Zd Z  G d dee          Z!dS )    N)ABCMetaabstractmethod)deepcopy)log)QuantityUnitUnitConversionError)MissingDataAssociationException"IncompatibleUncertaintiesExceptionNDUncertaintyStdDevUncertaintyUnknownUncertaintyVarianceUncertaintyInverseVariancec                 P   t          j        t          j        | j                  t	                                       }fdt          | j                  D             }|                     |gt          j        | j                  |                                         z             S )Nc                     g | ]}|v|	S  r   ).0ipreserve_axess     <lib/python3.11/site-packages/astropy/nddata/nduncertainty.py
<listcomp>z._move_preserved_axes_first.<locals>.<listcomp>&   s#    JJJ11M3I3IQ3I3I3I    )	npprodarrayshapelistrangendimreshapetolist)arrr   zeroth_axis_after_reshapecollapse_axess    `  r   _move_preserved_axes_firstr&      s     !#(;(;D<O<O(P Q QJJJJchJJJM;;	"#bhsy&9&9-&H&O&O&Q&QQ  r   c                     |j         t          |          k    rFt          j        | j                  }|                    |t          j        |                             S |S N)r    lenr   r   r   r!   asarray)r#   collapsed_arrr   	arr_shapes       r   _unravel_preserved_axesr-   ,   sT     S////HSY''	$$Yrz-/H/H%IJJJr   c                     | t           j                            |           }n t           j                            | |          }t          j        t           j                            | |                    |z  S r(   )r   macountsqrtsum)xaxisdenoms      r   from_variance_for_meanr6   :   sT    |AAt$$72599Q%%&&..r   c                 f    t          j        t           j                            | |                    S r(   )r   r1   r/   r2   )r3   r4   s     r   <lambda>r8   E   s     BGBEIIa$6$677 r   c                       e Zd ZdZdS )r   zThis exception should be used to indicate cases in which uncertainties
    with two different classes can not be propagated.
    N__name__
__module____qualname____doc__r   r   r   r   r   K              r   r   c                       e Zd ZdZdS )r
   zThis exception should be used to indicate that an uncertainty instance
    has not been associated with a parent `~astropy.nddata.NDData` object.
    Nr:   r   r   r   r
   r
   Q   r?   r   r
   c                      e Zd ZdZddZeed                         Zed             Zed             Z	e	j
        d             Z	ed	             Zej
        d
             Zed             Zed             Zej
        d             Zed             Zd Zd Zd Zd ZddZd Zed             Zed             Zed             Zed             Zd ZdS )r   a}  This is the metaclass for uncertainty classes used with `NDData`.

    Parameters
    ----------
    array : any type, optional
        The array or value (the parameter name is due to historical reasons) of
        the uncertainty. `numpy.ndarray`, `~astropy.units.Quantity` or
        `NDUncertainty` subclasses are recommended.
        If the `array` is `list`-like or `numpy.ndarray`-like it will be cast
        to a plain `numpy.ndarray`.
        Default is ``None``.

    unit : unit-like, optional
        Unit for the uncertainty ``array``. Strings that can be converted to a
        `~astropy.units.Unit` are allowed.
        Default is ``None``.

    copy : `bool`, optional
        Indicates whether to save the `array` as a copy. ``True`` copies it
        before saving, while ``False`` tries to save every parameter as
        reference. Note however that it is not always possible to save the
        input as reference.
        Default is ``True``.

    Raises
    ------
    IncompatibleUncertaintiesException
        If given another `NDUncertainty`-like class as ``array`` if their
        ``uncertainty_type`` is different.
    NTc                    t          |t                    rO|j        | j        k    rt          | ||j        k    rt          j        d           n|j        |j        }|j        }nSt          |t                    r>|'|j         ||j        k    rt          j        d           n|j        |j        }|j
        }|d | _        nt          |          | _        |rt          |          }t          |          }|| _        d | _        d S )Nz;overwriting Uncertainty's current unit with specified unit.z8overwriting Quantity's current unit with specified unit.)
isinstancer   uncertainty_typer   _unitr   infounitr   r   valuer   r   parent_nddata)selfr   copyrG   s       r   __init__zNDUncertainty.__init__w   s   e]++ 	  %)>>>88DEK$7$7VWWWW(zKEEx(( 	 EJ$:tuz?Q?QSTTTT'zKE<DJJdDJ 	"UOOED>>D
!r   c                     dS )z`str` : Short description of the type of uncertainty.

        Defined as abstract property so subclasses *have* to override this.
        Nr   rJ   s    r   rD   zNDUncertainty.uncertainty_type   	     tr   c                     dS )zp`bool` : Supports uncertainty propagation with correlated uncertainties?

        .. versionadded:: 1.2
        Fr   rN   s    r   supports_correlatedz!NDUncertainty.supports_correlated   s	     ur   c                     | j         S )z*`numpy.ndarray` : the uncertainty's value.)_arrayrN   s    r   r   zNDUncertainty.array   s     {r   c                     t          |t          t          j        f          rt          j        |dd          }|| _        d S )NF)subokrK   )rC   r   r   ndarrayr   rS   rJ   rH   s     r   r   zNDUncertainty.array   s<    edBJ/00 	=HU%e<<<Er   c                     | j         S )z<`~astropy.units.Unit` : The unit of the uncertainty, if any.)rE   rN   s    r   rG   zNDUncertainty.unit   s     zr   c                     || j         g| j        j        }	 |                     |                              |           n1# t
          $ r$ t          d                    ||                    w xY wt          |          | _        dS || _        dS )z|
        The unit should be set to a value consistent with the parent NDData
        unit and the uncertainty type.
        Nz5Unit {} is incompatible with unit {} of parent nddata)	_parent_nddatarI   rG   _data_unit_to_uncertainty_unittor	   formatr   rE   )rJ   rH   parent_units      r   rG   zNDUncertainty.unit   s      "."0577DDGGNNNN*   -OVV!;    eDJJJDJJJs   (A   .A.c                 P    t          | j        | j        d| j        j                  S )zJ
        This uncertainty as an `~astropy.units.Quantity` object.
        F)rK   dtype)r   r   rG   r`   rN   s    r   quantityzNDUncertainty.quantity   s$    
 
DIEAQRRRRr   c                 B   d}d}	 | j         }|t          |          t          | j         t          j                  r,|                                  }|t          j        |           |S t          j        d           | j         S # t          $ r t          |          w xY w)z`NDData` : reference to `NDData` instance with this uncertainty.

        In case the reference is not set uncertainty propagation will not be
        possible since propagation might need the uncertain data besides the
        uncertainty.
        z3uncertainty is not associated with an NDData objectzthe associated NDData object was deleted and cannot be accessed anymore. You can prevent the NDData object from being deleted by assigning it to a variable. If this happened after unpickling make sure you pickle the parent not the uncertainty directly.Nz6parent_nddata should be a weakref to an NDData object.)rZ   r
   rC   weakrefrefr   rF   AttributeError)rJ   no_parent_messageparent_lost_messageparentresolved_parents        r   rI   zNDUncertainty.parent_nddata   s     RL 		/(F ~56GHHH d17;?? /&*&9&9&;&;O&.!4555**HUVVV..#  	E 	E 	E12CDDD	Es   B Bc                 6   |.t          |t          j                  st          j        |          }|| _        || j        j        }t          | j        j        dd           }||	d | _        d S | j        ||                     |          | _        d S ||                     |          | _        d S |                     |          }	 |	                    | j                   d S # t          $ r) t          d                    | j        |                    w xY wd S )NrG   z8Unit {} of uncertainty incompatible with unit {} of data)rC   rc   rd   rZ   rI   rG   getattrdatar[   r\   r	   r]   )rJ   rH   r^   parent_data_unitunit_from_datas        r   rI   zNDUncertainty.parent_nddata   s=   Zw{%C%C K&&E $ ,1K&t'9'>MM"'7'? 			"{'> ??LL			!- ??@PQQ			
 "&!D!D[!Q!Q"%%di00000*   -%vdi==  ' s   C# #3Dc                     dS )z
        Subclasses must override this property. It should take in a data unit
        and return the correct unit for the uncertainty given the uncertainty
        type.
        Nr   rW   s     r   r[   z,NDUncertainty._data_unit_to_uncertainty_unit$  rO   r   c                     | j         j        dz   }	 t          j        | j        d|          }n$# t
          $ r t          | j                  }Y nw xY wd                    ||dg          S )N(z, )	separatorprefix ))	__class__r;   r   array2stringr   re   strjoin)rJ   rs   bodys      r   __repr__zNDUncertainty.__repr__-  sw    (3.	#?4:fMMMDD 	# 	# 	#tz??DDD	# wwc*+++s   . AAc                 j    	 | j         | j        | j        fS # t          $ r | j         | j        d fcY S w xY wr(   )rS   rE   rI   r
   rN   s    r   __getstate__zNDUncertainty.__getstate__6  sM    	1;
D,>>>. 	1 	1 	1;
D0000	1s    22c                     t          |          dk    rt          d          |d         | _        |d         | _        |d         }|t	          j        |          }|| _        d S )N   z!The state should contain 3 items.r         )r)   	TypeErrorrS   rE   rc   rd   rZ   )rJ   staterh   s      r   __setstate__zNDUncertainty.__setstate__>  sb    u::???@@@Ah1X
q[((F$r   c                 R    |                      | j        |         | j        d          S )zBNormal slicing on the array, keep the unit and return a reference.F)rG   rK   )rv   r   rG   )rJ   items     r   __getitem__zNDUncertainty.__getitem__I  s#    ~~dj.TYU~KKKr   c                 |   | j         sLt          |t          j                  s|dk    r,t	          d                    | j        j                            ||                     |j	                  }|j        dk    r| 
                    |||          }n|j        dk    r|                     |||          }nq|j        dk    r|                     |||          }nN|j        dv r|                     |||          }n-t	          d|j                   |                     ||          }|                     |d	
          S )a  Calculate the resulting uncertainty given an operation on the data.

        .. versionadded:: 1.2

        Parameters
        ----------
        operation : callable
            The operation that is performed on the `NDData`. Supported are
            `numpy.add`, `numpy.subtract`, `numpy.multiply` and
            `numpy.true_divide` (or `numpy.divide`).

        other_nddata : `NDData` instance
            The second operand in the arithmetic operation.

        result_data : `~astropy.units.Quantity` or ndarray
            The result of the arithmetic operations on the data.

        correlation : `numpy.ndarray` or number
            The correlation (rho) is defined between the uncertainties in
            sigma_AB = sigma_A * sigma_B * rho. A value of ``0`` means
            uncorrelated operands.

        axis : int or tuple of ints, optional
            Axis over which to perform a collapsing operation.

        Returns
        -------
        resulting_uncertainty : `NDUncertainty` instance
            Another instance of the same `NDUncertainty` subclass containing
            the uncertainty of the result.

        Raises
        ------
        ValueError
            If the ``operation`` is not supported or if correlation is not zero
            but the subclass does not support correlated uncertainties.

        Notes
        -----
        First this method checks if a correlation is given and the subclass
        implements propagation with correlated uncertainties.
        Then the second uncertainty is converted (or an Exception is raised)
        to the same class in order to do the propagation.
        Then the appropriate propagation method is invoked and the result is
        returned.
        r   z={} does not support uncertainty propagation with correlation.Naddsubtractmultiply)true_dividedividezunsupported operation: F)rK   )rQ   rC   r   rV   
ValueErrorr]   rv   r;   _convert_uncertaintyuncertainty_propagate_add_propagate_subtract_propagate_multiply_propagate_divide_propagate_collapse)rJ   	operationother_nddataresult_datacorrelationr4   other_uncertresults           r   	propagatezNDUncertainty.propagateM  sg   ` ' 	+rz22 kQ6F6F vdn566   #44\5MNNL!U**,,\;TT#z1111 +{  #z1111 +{  #'@@@//k;WW !O9;M!O!OPPP --i>>F~~f5~111r   c                     t          |t                    r'| j        |j        k    r|S |                     |          S t          )a  Checks if the uncertainties are compatible for propagation.

        Checks if the other uncertainty is `NDUncertainty`-like and if so
        verify that the uncertainty_type is equal. If the latter is not the
        case try returning ``self.__class__(other_uncert)``.

        Parameters
        ----------
        other_uncert : `NDUncertainty` subclass
            The other uncertainty.

        Returns
        -------
        other_uncert : `NDUncertainty` subclass
            but converted to a compatible `NDUncertainty` subclass if
            possible and necessary.

        Raises
        ------
        IncompatibleUncertaintiesException:
            If the other uncertainty cannot be converted to a compatible
            `NDUncertainty` subclass.
        )rC   r   rD   rv   r   rJ   r   s     r   r   z"NDUncertainty._convert_uncertainty  sE    0 lM22 	5$(EEE##~~l33344r   c                     d S r(   r   rJ   r   r   r   s       r   r   zNDUncertainty._propagate_add      tr   c                     d S r(   r   r   s       r   r   z!NDUncertainty._propagate_subtract  r   r   c                     d S r(   r   r   s       r   r   z!NDUncertainty._propagate_multiply  r   r   c                     d S r(   r   r   s       r   r   zNDUncertainty._propagate_divide  r   r   c                     t          | dd          }|t          t          |            d          t          |dd          }|t          |j         d           | |                      S )aU  Convert this uncertainty to a different uncertainty type.

        Parameters
        ----------
        other_uncert : `NDUncertainty` subclass
            The `NDUncertainty` subclass to convert to.

        Returns
        -------
        resulting_uncertainty : `NDUncertainty` instance
            An instance of ``other_uncert`` subclass containing the uncertainty
            converted to the new uncertainty type.

        Raises
        ------
        TypeError
            If either the initial or final subclasses do not support
            conversion, a `TypeError` is raised.
        _convert_to_varianceNz9 does not support conversion to another uncertainty type._convert_from_variancez; does not support conversion from another uncertainty type.)rk   r   typer;   )rJ   r   as_variancefrom_variances       r   represent_aszNDUncertainty.represent_as  s    ( d$:DAA::XXX    .FMM ( , , ,   }[[]]+++r   )NTNr(   )r;   r<   r=   r>   rL   propertyr   rD   rQ   r   setterrG   ra   rI   r[   r{   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r   W   s;        > "  "  "  "D   ^ X   X   X \  \
   X 
[  [0 S S XS !/ !/ X!/F # # #J   ^, , ,1 1 1	% 	% 	%L L LN2 N2 N2 N2`5 5 5@   ^   ^   ^   ^, , , , ,r   r   )	metaclassc                   b    e Zd ZdZed             Zed             Zd Zd Zd Z	d Z
d Zd	 Zd
S )r   zThis class implements any unknown uncertainty type.

    The main purpose of having an unknown uncertainty class is to prevent
    uncertainty propagation.

    Parameters
    ----------
    args, kwargs :
        see `NDUncertainty`
    c                     dS )zC`False` : Uncertainty propagation is *not* possible for this class.Fr   rN   s    r   rQ   z&UnknownUncertainty.supports_correlated  	     ur   c                     dS )zq``"unknown"`` : `UnknownUncertainty` implements any unknown                            uncertainty type.
        unknownr   rN   s    r   rD   z#UnknownUncertainty.uncertainty_type   s	    
 yr   c                     dS )z>
        No way to convert if uncertainty is unknown.
        Nr   rW   s     r   r[   z1UnknownUncertainty._data_unit_to_uncertainty_unit  s	     tr   c                 $    d}t          |          )zcRaise an Exception because unknown uncertainty types cannot
        implement propagation.
        z3Uncertainties of unknown type cannot be propagated.)r   )rJ   r   msgs      r   r   z'UnknownUncertainty._convert_uncertainty  s     D0555r   c                     dS )z+Not possible for unknown uncertainty types.Nr   r   s       r   r   z!UnknownUncertainty._propagate_add  r   r   c                     d S r(   r   r   s       r   r   z&UnknownUncertainty._propagate_subtract      tr   c                     d S r(   r   r   s       r   r   z&UnknownUncertainty._propagate_multiply  r   r   c                     d S r(   r   r   s       r   r   z$UnknownUncertainty._propagate_divide  r   r   N)r;   r<   r=   r>   r   rQ   rD   r[   r   r   r   r   r   r   r   r   r   r     s        	 	   X   X  6 6 6          r   r   c                   D    e Zd ZdZddZd Zdd d fdZdd	 d
 fdZdS )_VariancePropagationMixinz
    Propagation of uncertainties for variances, also used to perform error
    propagation for variance-like uncertainties (standard deviation and inverse
    variance).
    Nc                 4   	 | j         j        dz  }n# t          t          f$ r d}Y nw xY w| j        |t
          j        t
          j        fv r|                     ||          S t          |         }t          |         }t
          j                            | j        | j         j                  }| j        M || j                  | j         j        dz  k    r, ||| j        z                                |          j        }n ||          } |||          S dS )ah  
        Error propagation for collapse operations on variance or
        variance-like uncertainties. Uncertainties are calculated using the
        formulae for variance but can be used for uncertainty convertible to
        a variance.

        Parameters
        ----------
        numpy_op : function
            Numpy operation like `np.sum` or `np.max` to use in the collapse

        subtract : bool, optional
            If ``True``, propagate for subtraction, otherwise propagate for
            addition.

        axis : tuple, optional
            Axis on which to compute collapsing operations.
        r   Nr4   )rI   rG   re   r   r   r   minmax_get_err_at_extremumcollapse_to_variance_mappingcollapse_from_variance_mappingr/   masked_arraymaskr\   rH   )rJ   numpy_opr4   result_unit_sqto_variancer   masked_uncertaintythiss           r   r   z-_VariancePropagationMixin._propagate_collapse)  sB   &	"!/4a7NN	* 	" 	" 	"!NNN	" :! BFBF+++ 000EEE ;8D >x H%'U%7%7J 2 7& &" I)#DI..$2D2I12LLL
 $$6$)$CDDN++ D ';'9::D$}T5555A "!s    ((c                   	 t          d          sg|t          j        u rt          j        j        	n|t          j        u rt          j        j        	t          j        | j        j	                  }S 	t          j
        | j                                                            }| j                                        |         S fd|D             }t          j                            t          | j        j        |          t          | j        j        |                    }t          | j        |          }t          j        	fdt#          ||          D                       }t%          | j        j        ||          S )a  
        Return the value of the ``uncertainty`` array at the indices
        which satisfy the ``extremum`` function applied to the ``measurement`` array,
        where we expect ``extremum`` to be np.argmax or np.argmin, and
        we expect a two-dimensional output.

        Assumes the ``measurement`` and ``uncertainty`` array dimensions
        are ordered such that the zeroth dimension is the one to preserve.
        For example, if you start with array with shape (a, b, c), this
        function applies the ``extremum`` function to the last two dimensions,
        with shapes b and c.

        This operation is difficult to cast in a vectorized way. Here
        we implement it with a list comprehension, which is likely not the
        most performant solution.
        N__len__c                     g | ]}|v|	S r   r   )r   axr4   s     r   r   zB_VariancePropagationMixin._get_err_at_extremum.<locals>.<listcomp>  s    AAA"D.....r   c                 h    g | ].\  }}|t          j         |          |j                           /S r   )r   unravel_indexr   )r   mearg_extremums      r   r   zB_VariancePropagationMixin._get_err_at_extremum.<locals>.<listcomp>  s9    VVVtq!QrQ99:VVVr   )hasattrr   r   r/   argminr   argmaxaranger   r    
asanyarrayrI   ravelr   r&   rl   r   zipr-   )
rJ   extremumr4   all_axesindr   measerrr   r   s
     `      @r   r   z._VariancePropagationMixin._get_err_at_extremumc  si   " GD)$<$<6Drv5<LL5<L9TZ_--<,r}T-?@@FFHHIIC:##%%c** BAAAhAAAu!!&t'9'>NN&t'9'>NN
 
 )]CCVVVVs4QT~~VVV
 
 '#
 
 	
r   Fc                     | S r(   r   r3   s    r   r8   z"_VariancePropagationMixin.<lambda>      a r   c                     | S r(   r   r   s    r   r8   z"_VariancePropagationMixin.<lambda>       r   c                    |rd}nd}	 |j         dz  }n# t          $ r d}Y nw xY w|j        ]|j         E| ||j                   k    r1 ||j        |j         z                                |          j        }	n ||j                  }	nd}	| j        j| j         R || j                   | j        j         dz  k    r1 || j        | j         z                                |          j        }
n || j                  }
nd}
t          |t          j                  s|dk    r)d|z  t          j	        |
|	z            z  }|
|	z   ||z  z   }n|
|	z   } ||          S )a_  
        Error propagation for addition or subtraction of variance or
        variance-like uncertainties. Uncertainties are calculated using the
        formulae for variance but can be used for uncertainty convertible to
        a variance.

        Parameters
        ----------
        other_uncert : `~astropy.nddata.NDUncertainty` instance
            The uncertainty, if any, of the other operand.

        result_data : `~astropy.nddata.NDData` instance
            The results of the operation on the data.

        correlation : float or array-like
            Correlation of the uncertainties.

        subtract : bool, optional
            If ``True``, propagate for subtraction, otherwise propagate for
            addition.

        to_variance : function, optional
            Function that will transform the input uncertainties to variance.
            The default assumes the uncertainty is the variance.

        from_variance : function, optional
            Function that will convert from variance to the input uncertainty.
            The default assumes the uncertainty is the variance.
        r   r   Nr   )
rG   re   r   r\   rH   rI   rC   r   rV   r1   )rJ   r   r   r   r   r   r   correlation_signr   otherr   corrr   s                r   _propagate_add_subz,_VariancePropagationMixin._propagate_add_sub  s   L  	!! 	"(-q0NN 	" 	" 	"!NNN	" ) ,;;!D D 2 2  K 2l6G GHHR''  $L$677E:! 	%K	**d.@.Eq.HHH #{4:#:;;>>~NNT"{4:..D k2:.. 	"+2B2B{?RWTE\%:%::DE\$4t$;;FFE\F}V$$$s   
 ##c                     | S r(   r   r   s    r   r8   z"_VariancePropagationMixin.<lambda>  r   r   c                     | S r(   r   r   s    r   r8   z"_VariancePropagationMixin.<lambda>  r   r   c                 8   t          |t                    r|j        }|rd}nd}|j        |j        rm |d|j        z            d|j        j        z  dz  j        k    rA ||j        |j        z                                d|j        j        z  dz            j        }n ||j                  }t          j        | j        j	        dz  |z            }	nd}	| j        | j        rm |d| j        z            d| j        j        z  dz  j        k    rA || j        | j        z                                d| j        j        z  dz            j        }
n || j                  }
t          j        |j        j	        dz  |
z            }nd}t          |t          j
                  s|dk    r8d|z  t          j        |
|z            z  | j        j	        z  |j        j	        z  }nd}|r$ |||	z   ||z  z   |j        j	        dz  z            S  |||	z   ||z  z             S )ac  
        Error propagation for multiplication or division of variance or
        variance-like uncertainties. Uncertainties are calculated using the
        formulae for variance but can be used for uncertainty convertible to
        a variance.

        Parameters
        ----------
        other_uncert : `~astropy.nddata.NDUncertainty` instance
            The uncertainty, if any, of the other operand.

        result_data : `~astropy.nddata.NDData` instance
            The results of the operation on the data.

        correlation : float or array-like
            Correlation of the uncertainties.

        divide : bool, optional
            If ``True``, propagate for division, otherwise propagate for
            multiplication.

        to_variance : function, optional
            Function that will transform the input uncertainties to variance.
            The default assumes the uncertainty is the variance.

        from_variance : function, optional
            Function that will convert from variance to the input uncertainty.
            The default assumes the uncertainty is the variance.
        r   r   Nr   r      )rC   r   rH   r   rG   rI   r\   r   absrl   rV   r1   )rJ   r   r   r   r   r   r   r   d_brightd_aleftr   s                r   _propagate_multiply_dividez4_VariancePropagationMixin._propagate_multiply_divide  s   N k8,, 	,%+K 	!! )
 !6KL$5 566388Q>DE E  K 2l6G GHHR\7<<BCC  "k,"455F4-2A5;<<EEE:! 	.KDI..+00Q6<= =  K
di 788RT/44:;;  "k$*--6,491<sBCCDDD< k2:.. 		+2B2B'#)$$% $)* ,1	2 D D 	I = 04 77,1145  
 !=0@40G!GHHHr   r(   )r;   r<   r=   r>   r   r   r   r   r   r   r   r   r   "  s         86 86 86 86t1
 1
 1
p K!k[% [% [% [%D K!kDI DI DI DI DI DIr   r   c                        e Zd ZdZed             Zed             Zd Z fdZ fdZ	 fdZ
 fdZ fd	Zd
 Zd Zed             Z xZS )r   a  Standard deviation uncertainty assuming first order gaussian error
    propagation.

    This class implements uncertainty propagation for ``addition``,
    ``subtraction``, ``multiplication`` and ``division`` with other instances
    of `StdDevUncertainty`. The class can handle if the uncertainty has a
    unit that differs from (but is convertible to) the parents `NDData` unit.
    The unit of the resulting uncertainty will have the same unit as the
    resulting data. Also support for correlation is possible but requires the
    correlation as input. It cannot handle correlation determination itself.

    Parameters
    ----------
    args, kwargs :
        see `NDUncertainty`

    Examples
    --------
    `StdDevUncertainty` should always be associated with an `NDData`-like
    instance, either by creating it during initialization::

        >>> from astropy.nddata import NDData, StdDevUncertainty
        >>> ndd = NDData([1,2,3], unit='m',
        ...              uncertainty=StdDevUncertainty([0.1, 0.1, 0.1]))
        >>> ndd.uncertainty  # doctest: +FLOAT_CMP
        StdDevUncertainty([0.1, 0.1, 0.1])

    or by setting it manually on the `NDData` instance::

        >>> ndd.uncertainty = StdDevUncertainty([0.2], unit='m', copy=True)
        >>> ndd.uncertainty  # doctest: +FLOAT_CMP
        StdDevUncertainty([0.2])

    the uncertainty ``array`` can also be set directly::

        >>> ndd.uncertainty.array = 2
        >>> ndd.uncertainty
        StdDevUncertainty(2)

    .. note::
        The unit will not be displayed.
    c                     dS )z`True` : `StdDevUncertainty` allows to propagate correlated                     uncertainties.

        ``correlation`` must be given, this class does not implement computing
        it by itself.
        Tr   rN   s    r   rQ   z%StdDevUncertainty.supports_correlated  	     tr   c                     dS )z>``"std"`` : `StdDevUncertainty` implements standard deviation.stdr   rN   s    r   rD   z"StdDevUncertainty.uncertainty_type  r   r   c                 >    t          |t                    r|S t          r(   )rC   r   r   r   s     r   r   z&StdDevUncertainty._convert_uncertainty  s!    l$566 	544r   c                 z    t                                          |||dt          j        t          j                  S NFr   r   r   superr   r   squarer1   rJ   r   r   r   rv   s       r   r   z StdDevUncertainty._propagate_add  s:    ww))	' * 
 
 	
r   c                 z    t                                          |||dt          j        t          j                  S NTr   r   r  s       r   r   z%StdDevUncertainty._propagate_subtract  s:    ww))	' * 
 
 	
r   c                 z    t                                          |||dt          j        t          j                  S NFr   r   r   r   r   r   r  r1   r  s       r   r   z%StdDevUncertainty._propagate_multiply  s:    ww11	' 2 
 
 	
r   c                 z    t                                          |||dt          j        t          j                  S NTr  r  r  s       r   r   z#StdDevUncertainty._propagate_divide  s:    ww11	' 2 
 
 	
r   c                 J    t                                          ||          S )Nr   )r   r   )rJ   numpy_operationr4   rv   s      r   r   z%StdDevUncertainty._propagate_collapse  s     ww**?*FFFr   c                     |S r(   r   rW   s     r   r[   z0StdDevUncertainty._data_unit_to_uncertainty_unit  s    r   c                 p    | j         d n	| j         dz  }| j        d n	| j        dz  }t          ||          S )Nr   rG   r   rG   r   rJ   	new_arraynew_units      r   r   z&StdDevUncertainty._convert_to_variance  sA     J.DDDJM	9,44$)Q,"98<<<<r   c                 h    |j         d n	|j         dz  }|j        d n	|j        dz  } | ||          S )Ng      ?r  r   rG   cls
var_uncertr  r  s       r   r   z(StdDevUncertainty._convert_from_variance  sG    &,4DD*:Ju:U	%?244
E8Rs98,,,,r   )r;   r<   r=   r>   r   rQ   rD   r   r   r   r   r   r   r[   r   classmethodr   __classcell__rv   s   @r   r   r   z  s*       ) )V   X   X5 5 5
 
 
 
 

 
 
 
 

 
 
 
 

 
 
 
 
G G G G G  = = =
 - - [- - - - -r   r   c                        e Zd ZdZed             Zed             Z fdZ fdZ fdZ	 fdZ
d Zd	 Zed
             Z xZS )r   a  
    Variance uncertainty assuming first order Gaussian error
    propagation.

    This class implements uncertainty propagation for ``addition``,
    ``subtraction``, ``multiplication`` and ``division`` with other instances
    of `VarianceUncertainty`. The class can handle if the uncertainty has a
    unit that differs from (but is convertible to) the parents `NDData` unit.
    The unit of the resulting uncertainty will be the square of the unit of the
    resulting data. Also support for correlation is possible but requires the
    correlation as input. It cannot handle correlation determination itself.

    Parameters
    ----------
    args, kwargs :
        see `NDUncertainty`

    Examples
    --------
    Compare this example to that in `StdDevUncertainty`; the uncertainties
    in the examples below are equivalent to the uncertainties in
    `StdDevUncertainty`.

    `VarianceUncertainty` should always be associated with an `NDData`-like
    instance, either by creating it during initialization::

        >>> from astropy.nddata import NDData, VarianceUncertainty
        >>> ndd = NDData([1,2,3], unit='m',
        ...              uncertainty=VarianceUncertainty([0.01, 0.01, 0.01]))
        >>> ndd.uncertainty  # doctest: +FLOAT_CMP
        VarianceUncertainty([0.01, 0.01, 0.01])

    or by setting it manually on the `NDData` instance::

        >>> ndd.uncertainty = VarianceUncertainty([0.04], unit='m^2', copy=True)
        >>> ndd.uncertainty  # doctest: +FLOAT_CMP
        VarianceUncertainty([0.04])

    the uncertainty ``array`` can also be set directly::

        >>> ndd.uncertainty.array = 4
        >>> ndd.uncertainty
        VarianceUncertainty(4)

    .. note::
        The unit will not be displayed.
    c                     dS )z6``"var"`` : `VarianceUncertainty` implements variance.varr   rN   s    r   rD   z$VarianceUncertainty.uncertainty_type'  r   r   c                     dS )z`True` : `VarianceUncertainty` allows to propagate correlated                     uncertainties.

        ``correlation`` must be given, this class does not implement computing
        it by itself.
        Tr   rN   s    r   rQ   z'VarianceUncertainty.supports_correlated,  r   r   c                 N    t                                          |||d          S )NFr   r   r   r  s       r   r   z"VarianceUncertainty._propagate_add6  s-    ww))+{U * 
 
 	
r   c                 N    t                                          |||d          S )NTr!  r"  r  s       r   r   z'VarianceUncertainty._propagate_subtract;  s-    ww))+{T * 
 
 	
r   c                 N    t                                          |||d          S )NFr   r   r   r  s       r   r   z'VarianceUncertainty._propagate_multiply@  s-    ww11+{5 2 
 
 	
r   c                 N    t                                          |||d          S )NTr%  r&  r  s       r   r   z%VarianceUncertainty._propagate_divideE  s-    ww11+{4 2 
 
 	
r   c                     |dz  S )Nr   r   rW   s     r   r[   z2VarianceUncertainty._data_unit_to_uncertainty_unitJ  s    axr   c                     | S r(   r   rN   s    r   r   z(VarianceUncertainty._convert_to_varianceM  s    r   c                     |S r(   r   )r  r  s     r   r   z*VarianceUncertainty._convert_from_varianceP  s    r   r;   r<   r=   r>   r   rD   rQ   r   r   r   r   r[   r   r  r   r  r  s   @r   r   r     s        . .`   X   X
 
 
 
 


 
 
 
 


 
 
 
 


 
 
 
 

       [    r   r   c                     d| z  S )z5Just a simple inverse for use in the InverseVariance.r   r   r   s    r   _inverser-  U  s    q5Lr   c                        e Zd ZdZed             Zed             Z fdZ fdZ fdZ	 fdZ
d Zd	 Zed
             Z xZS )r   a  
    Inverse variance uncertainty assuming first order Gaussian error
    propagation.

    This class implements uncertainty propagation for ``addition``,
    ``subtraction``, ``multiplication`` and ``division`` with other instances
    of `InverseVariance`. The class can handle if the uncertainty has a unit
    that differs from (but is convertible to) the parents `NDData` unit. The
    unit of the resulting uncertainty will the inverse square of the unit of
    the resulting data. Also support for correlation is possible but requires
    the correlation as input. It cannot handle correlation determination
    itself.

    Parameters
    ----------
    args, kwargs :
        see `NDUncertainty`

    Examples
    --------
    Compare this example to that in `StdDevUncertainty`; the uncertainties
    in the examples below are equivalent to the uncertainties in
    `StdDevUncertainty`.

    `InverseVariance` should always be associated with an `NDData`-like
    instance, either by creating it during initialization::

        >>> from astropy.nddata import NDData, InverseVariance
        >>> ndd = NDData([1,2,3], unit='m',
        ...              uncertainty=InverseVariance([100, 100, 100]))
        >>> ndd.uncertainty  # doctest: +FLOAT_CMP
        InverseVariance([100, 100, 100])

    or by setting it manually on the `NDData` instance::

        >>> ndd.uncertainty = InverseVariance([25], unit='1/m^2', copy=True)
        >>> ndd.uncertainty  # doctest: +FLOAT_CMP
        InverseVariance([25])

    the uncertainty ``array`` can also be set directly::

        >>> ndd.uncertainty.array = 0.25
        >>> ndd.uncertainty
        InverseVariance(0.25)

    .. note::
        The unit will not be displayed.
    c                     dS )z;``"ivar"`` : `InverseVariance` implements inverse variance.ivarr   rN   s    r   rD   z InverseVariance.uncertainty_type  s	     vr   c                     dS )z`True` : `InverseVariance` allows to propagate correlated                     uncertainties.

        ``correlation`` must be given, this class does not implement computing
        it by itself.
        Tr   rN   s    r   rQ   z#InverseVariance.supports_correlated  r   r   c                 f    t                                          |||dt          t                    S r   r   r   r-  r  s       r   r   zInverseVariance._propagate_add  s6    ww)) " * 
 
 	
r   c                 f    t                                          |||dt          t                    S r  r3  r  s       r   r   z#InverseVariance._propagate_subtract  s6    ww)) " * 
 
 	
r   c                 f    t                                          |||dt          t                    S r  r   r   r-  r  s       r   r   z#InverseVariance._propagate_multiply  s6    ww11 " 2 
 
 	
r   c                 f    t                                          |||dt          t                    S r
  r6  r  s       r   r   z!InverseVariance._propagate_divide  s6    ww11 " 2 
 
 	
r   c                     d|dz  z  S )Nr   r   r   rW   s     r   r[   z.InverseVariance._data_unit_to_uncertainty_unit  s    5!8|r   c                 p    | j         d n	d| j         z  }| j        d n	d| j        z  }t          ||          S Nr   r  r  r  s      r   r   z$InverseVariance._convert_to_variance  sA     J.DDA
N	9,44!di-"98<<<<r   c                 h    |j         d n	d|j         z  }|j        d n	d|j        z  } | ||          S r:  r  r  s       r   r   z&InverseVariance._convert_from_variance  sG    &,4DD!j>N:N	%?244JO8Ks98,,,,r   r+  r  s   @r   r   r   Z  s        / /b   X   X
 
 
 
 

 
 
 
 

 
 
 
 

 
 
 
 
  = = =
 - - [- - - - -r   r   )"rc   abcr   r   rK   r   numpyr   astropyr   astropy.unitsr   r   r	   __all__r2   r  meanr   r&   r-   r6   medianr   	Exceptionr   r
   r   r   r   r   r   r-  r   r   r   r   <module>rD     s    ' ' ' ' ' ' ' '                 = = = = = = = = = =   FBIGRY      / / / F77G#It"            i   U, U, U, U, U,g U, U, U, U,p0 0 0 0 0 0 0 0fUI UI UI UI UI UI UI UIp
y- y- y- y- y-1= y- y- y-x\ \ \ \ \3] \ \ \~  
u- u- u- u- u-/ u- u- u- u- u-r   