B
    d_                 @   s   d Z ddlZddlZddlZddlZddlmZ ddlm	Z	 ddl
mZ ddl
mZ dd	d
gZG dd
 d
eZG dd	 d	eeZG dd deZdd ZdddZdd Zdd ZG dd dZdd ZdS )z
This module defines classes that deal with parameters.

It is unlikely users will need to work with these classes directly,
unless they define their own models.
    N)Quantity)
isiterable   )array_repr_oneline)get_inputs_and_params	ParameterInputParameterErrorParameterErrorc               @   s   e Zd ZdZdS )r	   zDGeneric exception class for all exceptions pertaining to Parameters.N)__name__
__module____qualname____doc__ r   r   h/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/astropy/modeling/parameters.pyr	      s   c               @   s   e Zd ZdZdS )r   z:Used for incorrect input parameter values and definitions.N)r
   r   r   r   r   r   r   r   r      s   c               @   s   e Zd ZdZdS )ParameterDefinitionErrorz3Exception in declaration of class-level Parameters.N)r
   r   r   r   r   r   r   r   r   #   s   r   c          	   C   s   t | rJytj| td} W q ttfk
rF   tdt|  dY qX njt| t	rVn^t| tj
rpt|  } nDt| tjtjfrt| } n(t| trtdntdt|  d| S )z+Convert a parameter to float or float array)dtypezParameter of z  could not be converted to floatz7Expected parameter to be of numerical type, not booleanz'Don't know how to convert parameter of z	 to float)r   npZ
asanyarrayfloat	TypeError
ValueErrorr   type
isinstancer   ZndarrayitemnumbersNumbernumberbool)valuer   r   r   _tofloat'   s$    


r   Fc                s   t   fdd}|S )Nc                s<   | j d k	rt| j| j }n| j}r. ||S  ||S d S )N)unitr   r   )selfval
self_value)op	reflectedr   r   wrapperF   s    

z-_binary_arithmetic_operation.<locals>.wrapper)	functoolswraps)r#   r$   r%   r   )r#   r$   r   _binary_arithmetic_operationE   s    r(   c                s   t   fdd}|S )Nc                s*   | j d k	rt| j| j }n| j} ||S )N)r   r   r   )r    r!   r"   )r#   r   r   r%   W   s    
z-_binary_comparison_operation.<locals>.wrapper)r&   r'   )r#   r%   r   )r#   r   _binary_comparison_operationV   s    
r)   c                s   t   fdd}|S )Nc                s(   | j d k	rt| j| j }n| j} |S )N)r   r   r   )r    r"   )r#   r   r   r%   e   s    
z,_unary_arithmetic_operation.<locals>.wrapper)r&   r'   )r#   r%   r   )r#   r   _unary_arithmetic_operationd   s    
r*   c                   s  e Zd ZdZdZdT fdd	Zdd	 Zd
d Zdd Zdd Z	dd Z
edd Zedd Zedd Zejdd Zedd Zejdd ZdUddZedd Zejd d Zed!d" Zejd#d" Zed$d% Zejd&d% Zed'd( Zed)d* Zejd+d* Zed,d- Zejd.d- Zed/d0 Zejd1d0 Zed2d3 Zejd4d3 Zed5d6 Zejd7d6 Zed8d9 Zejd:d9 Zed;d< Zejd=d< Zed>d? Zejd@d? ZedAdB ZdCdD ZdVdEdFZ edGdH Z!e!jdIdH Z!edJdK Z"dLdM Z#dWdNdOZ$dPdQ Z%e&e'j(Z)e&e'j(dRdSZ*e&e'j+Z,e&e'j+dRdSZ-e&e'j.Z/e&e'j.dRdSZ0e&e'j1Z2e&e'j1dRdSZ3e&e'j4Z5e&e'j4dRdSZ6e&e'j4Z7e&e'j4dRdSZ8e9e'j:Z;e9e'j<Z=e9e'j>Z?e9e'j@ZAe9e'jBZCe9e'jDZEeFe'jGZHeFe'jIZJ  ZKS )Xr   a  
    Wraps individual parameters.

    Since 4.0 Parameters are no longer descriptors and are based on a new
    implementation of the Parameter class. Parameters now  (as of 4.0) store
    values locally (as instead previously in the associated model)

    This class represents a model's parameter (in a somewhat broad sense). It
    serves a number of purposes:

    1) A type to be recognized by models and treated specially at class
    initialization (i.e., if it is found that there is a class definition
    of a Parameter, the model initializer makes a copy at the instance level).

    2) Managing the handling of allowable parameter values and once defined,
    ensuring updates are consistent with the Parameter definition. This
    includes the optional use of units and quantities as well as tranforming
    values to an internally consistent representation (e.g., from degrees to
    radians through the use of getters and setters).

    3) Holding attributes of parameters relevant to fitting, such as whether
    the parameter may be varied in fitting, or whether there are constraints
    that must be satisfied.



    See :ref:`modeling-parameters` for more details.

    Parameters
    ----------
    name : str
        parameter name

        .. warning::

            The fact that `Parameter` accepts ``name`` as an argument is an
            implementation detail, and should not be used directly.  When
            defining a new `Model` class, parameter names are always
            automatically defined by the class attribute they're assigned to.
    description : str
        parameter description
    default : float or array
        default value to use for this parameter
    unit : `~astropy.units.Unit`
        if specified, the parameter will be in these units, and when the
        parameter is updated in future, it should be set to a
        :class:`~astropy.units.Quantity` that has equivalent units.
    getter : callable
        a function that wraps the raw (internal) value of the parameter
        when returning the value through the parameter proxy (eg. a
        parameter may be stored internally as radians but returned to the
        user as degrees)
    setter : callable
        a function that wraps any values assigned to this parameter; should
        be the inverse of getter
    fixed : bool
        if True the parameter is not varied during fitting
    tied : callable or False
        if callable is supplied it provides a way to link the value of this
        parameter to another parameter (or some other arbitrary function)
    min : float
        the lower bound of a parameter
    max : float
        the upper bound of a parameter
    bounds : tuple
        specify min and max as a single tuple--bounds may not be specified
        simultaneously with min or max
    )fixedtiedbounds NFc                s  t    d | _d| _| |d | _| |d | _|| _|  | _	| _
t|tr|d k	rv||jsvtd|||j}|j}|| _|| _d | _| js| jd k	r| j| _nd | _|d k	r|	d k	s|
d k	rtd|n|	|
f}|| _|| _|| _d | _d | _d | _d | _d | _d S )NFzMparameter default {0} does not have units equivalent to the required unit {1}z]bounds may not be specified simultaneously with min or or max when instantiating Parameter {})super__init___model_model_required_create_value_wrapper_setter_getter_namestripr   Z_descriptionr   r   Zis_equivalentr   r   formatr   _default_unit_internal_unit_valuer   _fixed_tied_bounds_order
_validator_prior
_posterior_std)r    namedescriptiondefaultr   gettersetterr+   r,   minmaxr-   )	__class__r   r   r0      sF    





zParameter.__init__c             C   s
   || _ d S )N)r6   )r    ownerrE   r   r   r   __set_name__   s    zParameter.__set_name__c             C   s"   | j }|jdkrdS |jd S d S )Nr   r   r   )r   shape)r    r!   r   r   r   __len__   s    
zParameter.__len__c             C   s"   | j }t|jdkr|g}|| S )Nr   )r   lenrO   )r    keyr   r   r   r   __getitem__  s    zParameter.__getitem__c          
   C   s   | j }t|trdt|| dkr0td| jxntt|	t|  |D ]\}}| 
|| qJW n<y|||< W n. tk
r   td|| j|jd Y nX d S )Nr   z:Slice assignment outside the parameter dimensions for '{}'z?Input dimension {} invalid for {!r} parameter with dimension {})r   r   slicerQ   r   r8   rE   ziprangeindices__setitem__
IndexErrorrO   )r    rR   r   Zoldvalueidxr!   r   r   r   rX     s    

"zParameter.__setitem__c             C   s   d| j  d}|d| j 7 }| jd k	r8|d| j 7 }x4| jD ]*}t| |}|dkr@|d| d| 7 }q@W | jj d| dS )	N'z, value=z, unit=)NF)NNz, =())r6   r   r   constraintsgetattrrL   r
   )r    argsZconsr!   r   r   r   __repr__  s    

zParameter.__repr__c             C   s   | j S )zParameter name)r6   )r    r   r   r   rE   .  s    zParameter.namec             C   s   | j S )zParameter default value)r9   )r    r   r   r   rG   4  s    zParameter.defaultc             C   sp   | j dkr | jdkr t| jS | jrBt|  | j| j| jjS | j rZt|  | jS | jrlt| jS dS )z.The unadorned value proxied by this parameter.N)	r5   r4   r   float64r<   internal_unit_internal_valuer   r   )r    r   r   r   r   9  s    zParameter.valuec             C   sL   t |trtd| jd kr0tj|tjd| _ntj| |tjd| _d S )NzThe .value property on parameters should be set to unitless values, not Quantity objects. To seta parameter to a quantity simply set the parameter directly without using .value)r   )	r   r   r   r4   r   arrayrc   r<   re   )r    r   r   r   r   r   M  s    

c             C   s   | j S )z
        The unit attached to this parameter, if any.

        On unbound parameters (i.e. parameters accessed through the
        model class, rather than a model instance) this is the required/
        default unit for the parameter.
        )r:   )r    r   r   r   r   Z  s    
zParameter.unitc             C   s    | j d krtdntdd S )NzNCannot attach units to parameters that were not initially specified with unitszYCannot change the unit attribute directly, instead change the parameter to a new quantity)r   r   )r    r   r   r   r   r   f  s    

c             C   s*   |r|| _ n|d krtdntdd S )NzNCannot attach units to parameters that were not initially specified with unitszYCannot change the unit attribute directly, instead change the parameter to a new quantity)r:   r   )r    r   forcer   r   r   	_set_unito  s
    
zParameter._set_unitc             C   s   | j S )z[
        Return the internal unit the parameter uses for the internal value stored
        )r;   )r    r   r   r   rd   z  s    zParameter.internal_unitc             C   s
   || _ dS )z{
        Set the unit the parameter will convert the supplied value to the
        representation used internally.
        N)r;   )r    rd   r   r   r   rd     s    c             C   s   | j dkrdS | j| j  S )zQ
        This parameter, as a :class:`~astropy.units.Quantity` instance.
        N)r   r   )r    r   r   r   quantity  s    
zParameter.quantityc             C   s&   t |tstd|j| _|j| _d S )Nz:The .quantity attribute should be set to a Quantity object)r   r   r   r   r   r:   )r    ri   r   r   r   ri     s    
c             C   s   | j dkr| jjS | jjS )z*The shape of this parameter's value array.N)r4   r<   rO   re   )r    r   r   r   rO     s    
zParameter.shapec             C   s,   t | jtjr |dkr(tdn|| j_d S )N)r   )r   z-Cannot assign this shape to a scalar quantity)r   r   r   Zgenericr   rO   )r    r   r   r   r   rO     s    
c             C   s   t | jS )z)The size of this parameter's value array.)r   sizer   )r    r   r   r   rj     s    zParameter.sizec             C   s   | j S )z*Standard deviation, if available from fit.)rD   )r    r   r   r   std  s    zParameter.stdc             C   s
   || _ d S )N)rD   )r    r   r   r   r   rk     s    c             C   s   | j S )N)rB   )r    r   r   r   prior  s    zParameter.priorc             C   s
   || _ d S )N)rB   )r    r!   r   r   r   rl     s    c             C   s   | j S )N)rC   )r    r   r   r   	posterior  s    zParameter.posteriorc             C   s
   || _ d S )N)rC   )r    r!   r   r   r   rm     s    c             C   s   | j S )zS
        Boolean indicating if the parameter is kept fixed during fitting.
        )r=   )r    r   r   r   r+     s    zParameter.fixedc             C   s   t |tstd|| _dS )z Fix a parameter. zValue must be booleanN)r   r   r   r=   )r    r   r   r   r   r+     s    
c             C   s   | j S )z
        Indicates that this parameter is linked to another one.

        A callable which provides the relationship of the two parameters.
        )r>   )r    r   r   r   r,     s    zParameter.tiedc             C   s"   t |s|dkrtd|| _dS )zTie a parameter)FNz/Tied must be a callable or set to False or NoneN)callabler   r>   )r    r   r   r   r   r,     s    c             C   s   | j S )z8The minimum and maximum values of a parameter as a tuple)r?   )r    r   r   r   r-     s    zParameter.boundsc             C   s   |\}}|dk	rFt |tjtfs(tdt |tr>t|j}nt|}|dk	rt |tjtfsftdt |tr|t|j}nt|}||f| _dS )z>Set the minimum and maximum values of a parameter from a tupleNz(Min value must be a number or a QuantityzMax value must be a number)r   r   r   r   r   r   r   r?   )r    r   _min_maxr   r   r   r-     s    

c             C   s
   | j d S )z6A value used as a lower bound when fitting a parameterr   )r-   )r    r   r   r   rJ     s    zParameter.minc             C   s   || j f| _dS )z"Set a minimum value of a parameterN)rK   r-   )r    r   r   r   r   rJ     s    c             C   s
   | j d S )z7A value used as an upper bound when fitting a parameterr   )r-   )r    r   r   r   rK     s    zParameter.maxc             C   s   | j |f| _dS )z#Set a maximum value of a parameter.N)rJ   r-   )r    r   r   r   r   rK     s    c             C   s   | fdd}|S )aS  
        Used as a decorator to set the validator method for a `Parameter`.
        The validator method validates any value set for that parameter.
        It takes two arguments--``self``, which refers to the `Model`
        instance (remember, this is a method defined on a `Model`), and
        the value being set for this parameter.  The validator method's
        return value is ignored, but it may raise an exception if the value
        set on the parameter is invalid (typically an `InputParameterError`
        should be raised, though this is not currently a requirement).

        c             S   s   t | r| |_|S tdd S )NzThis decorator method expects a callable.
The use of this method as a direct validator is
deprecated; use the new validate method instead
)rn   rA   r   )funcr    r   r   r   	validator-  s    z&Parameter.validator.<locals>.validatorr   )r    rr   r   r   r   rr     s    zParameter.validatorc             C   s&   | j dk	r"| jdk	r"|  | j| dS )z$ Run the validator on this parameterN)rA   r1   )r    r   r   r   r   validate7  s    zParameter.validatec             C   s   t   }|d= xb| D ]V\}}|dkr|dkr6qn2t| |rLt| |}nt| d| rht| d| }|||< qW | jf |S )a  
        Make a copy of this `Parameter`, overriding any of its core attributes
        in the process (or an exact copy).

        The arguments to this method are the same as those for the `Parameter`
        initializer.  This simply returns a new `Parameter` instance with any
        or all of the attributes overridden, and so returns the equivalent of:

        .. code:: python

            Parameter(self.name, self.description, ...)

        r    N)rJ   rK   _)localscopyitemshasattrr`   rL   )r    rE   rF   rG   r   rH   rI   r+   r,   rJ   rK   r-   rl   rm   kwargsrR   r   r   r   r   rv   <  s    

zParameter.copyc             C   s   | j S )z5 Return the model this  parameter is associated with.)r1   )r    r   r   r   model_  s    zParameter.modelc             C   sJ   || _ | | j|| _| | j|| _| jrF| jd k	r@| j| _nd | _d S )N)r1   r3   r4   r5   r2   r9   r   r<   )r    r   r   r   r   rz   d  s    

c             C   s   | j r| jS | jS )ac  
        Currently for internal use only.

        Like Parameter.value but does not pass the result through
        Parameter.getter.  By design this should only be used from bound
        parameters.

        This will probably be removed are retweaked at some point in the
        process of rethinking how parameter values are stored/updated.
        )r4   re   r   )r    r   r   r   
_raw_valueo  s    zParameter._raw_valuec             C   s   t |tjr |jdkrtdnf|dkr,dS t|\}}t|}|dkrJn<|dkr~d| _|dk	r|d j}t	j
|f||i}ntd|S )aL  Wraps a getter/setter function to support optionally passing in
        a reference to the model object as the second argument.
        If a model is tied to this parameter and its getter/setter supports
        a second argument then this creates a partial function using the model
        instance as the second argument.
        r   zOA numpy.ufunc used for Parameter getter/setter may only take one input argumentN   TzIParameter getter/setter must be a function of either one or two arguments)r   r   ZufuncZninr   r   rQ   r2   rE   r&   partial)r    r%   rz   inputsrt   nargsZ	model_argr   r   r   r3     s     


zParameter._create_value_wrapperc             C   s.   t j| j|d}| jd k	r*t|| jdd}|S )N)r   F)rv   )r   Zasarrayr   r   r   )r    r   Zarrr   r   r   	__array__  s    
zParameter.__array__c             C   s
   t | jS )N)r   r   )r    r   r   r   __bool__  s    zParameter.__bool__T)r$   )r.   r.   NNNNFFNNN)F)NNNNNNFFNNNNN)N)Lr
   r   r   r   r_   r0   rN   rP   rS   rX   rb   propertyrE   rG   r   rI   r   rh   rd   ri   rO   rj   rk   rl   rm   r+   r,   r-   rJ   rK   rr   rs   rv   rz   r{   r3   r   r   r(   operatoradd__add____radd__sub__sub____rsub__mul__mul____rmul__pow__pow____rpow__truedivZ__div__Z__rdiv____truediv____rtruediv__r)   eq__eq__ne__ne__lt__lt__gt__gt__le__le__ge__ge__r*   neg__neg__abs__abs____classcell__r   r   )rL   r   r   r   s   D	  6	
	
  
!#
	












c             C   s(   t | j}| jdk	r$| d| j}|S )z
    Like array_repr_oneline but works on `Parameter` objects and supports
    rendering parameters with units like quantities.
    N )r   r   r   )paramoutr   r   r   param_repr_oneline  s    

r   )F)r   r&   r   r   numpyr   Zastropy.unitsr   Zastropy.utilsr   utilsr   r   __all__	Exceptionr	   r   r   r   r   r(   r)   r*   r   r   r   r   r   r   <module>	   s,   

    W