U
    e»{jCË  ã                   @   s  d Z ddlZddlZddlZddlmZ ddlmZmZm	Z	m
Z
mZ ddlZddlmZ ddlmZ ddgZed	d
ƒZG dd„ deƒZe ej ejf¡Zedœdd„Zedœdd„ZG dd„ dejƒZG dd„ deƒZeddƒZG dd„ deƒZG dd„ de ƒZ!G dd„ deƒZ"dS )z4
This module is to contain an improved bounding box
é    N)Ú
namedtuple)ÚAnyÚCallableÚDictÚListÚTuple©ÚQuantity)Ú
isiterableÚModelBoundingBoxÚCompoundBoundingBoxÚ_BaseIntervalzlower upperc                   @   s\   e Zd ZdZdd„ Zdd„ Zedd„ ƒZedd	„ ƒZ	ed
d„ ƒZ
ejdœdd„Zdd„ ZdS )Ú	_Intervala½  
    A single input's bounding box interval.

    Parameters
    ----------
    lower : float
        The lower bound of the interval

    upper : float
        The upper bound of the interval

    Methods
    -------
    validate :
        Contructs a valid interval

    outside :
        Determine which parts of an input array are outside the interval.

    domain :
        Contructs a discretization of the points inside the interval.
    c                 C   s   d| j › d| j› d�S )NzInterval(lower=z, upper=ú))ÚlowerÚupper©Úself© r   ú\/var/www/html/bwave/python/venv/lib/python3.8/site-packages/astropy/modeling/bounding_box.pyÚ__repr__1   s    z_Interval.__repr__c                 C   s
   t  | ¡S ©N)ÚcopyÚdeepcopyr   r   r   r   r   4   s    z_Interval.copyc                 C   sÆ   d}zt  | ¡}W nd tk
rv   z,t| ƒdkr8| d } t  dd„ | D ƒ¡}W n" tttfk
rp   t|ƒ‚Y nX Y nX |dk}|s®t|ƒdko¬|d dko¬tdd	„ | D ƒƒ}t| ƒrº|sÂt|ƒ‚d
S )z0Validate the shape of an interval representationz5An interval must be some sort of sequence of length 2é   r   c                 S   s   g | ]}|  ¡ ‘qS r   )Zto_value©Ú.0Úbr   r   r   Ú
<listcomp>C   s     z-_Interval._validate_shape.<locals>.<listcomp>))é   )r   r   )r   r   r   c                 s   s   | ]}t |tjƒV  qd S r   )Ú
isinstanceÚnpÚndarrayr   r   r   r   Ú	<genexpr>L   s     z,_Interval._validate_shape.<locals>.<genexpr>N)r!   ÚshapeÚ	TypeErrorÚlenÚ
ValueErrorÚAttributeErrorÚallr
   )ÚintervalZMESSAGEr$   Zvalid_shaper   r   r   Ú_validate_shape7   s&    
ÿýz_Interval._validate_shapec                 C   s<   t  |¡t  |¡k ¡ r2t d|› d|› d�t¡ | ||ƒS )zGValidate the bounds are reasonable and construct an interval from them.zInvalid interval: upper bound z# is strictly less than lower bound Ú.)r!   Ú
asanyarrayr)   ÚwarningsÚwarnÚRuntimeWarning)Úclsr   r   r   r   r   Ú_validate_boundsR   s    ýz_Interval._validate_boundsc                 C   s@   |   |¡ t|ƒdkr$t|d ƒ}nt|ƒ}|  |d |d ¡S )zä
        Construct and validate an interval

        Parameters
        ----------
        interval : iterable
            A representation of the interval.

        Returns
        -------
        A validated interval.
        r   r   )r+   r&   Útupler2   )r1   r*   r   r   r   Úvalidate^   s
    
z_Interval.validate)Ú_inputc                 C   s   t  || jk || jk¡S )aU  
        Parameters
        ----------
        _input : np.ndarray
            The evaluation input in the form of an array.

        Returns
        -------
        Boolean array indicating which parts of _input are outside the interval:
            True  -> position outside interval
            False -> position inside  interval
        )r!   Ú
logical_orr   r   )r   r5   r   r   r   Úoutsideu   s    z_Interval.outsidec                 C   s   t  | j| j| |¡S r   )r!   Zaranger   r   )r   Ú
resolutionr   r   r   Údomain„   s    z_Interval.domainN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   Ústaticmethodr+   Úclassmethodr2   r4   r!   r"   r7   r9   r   r   r   r   r      s   


r   ©Úreturnc                 C   s¤   t |tƒr<|| jkr"| j |¡}q td|› d| j› d�ƒ‚ndt t|ƒtj¡r�d|  krht	| jƒk rrn n|}q t
d|› dt	| jƒ› d�ƒ‚ntd|› d�ƒ‚|S )	z©
    Get the input index corresponding to the given key.
        Can pass in either:
            the string name of the input or
            the input index itself.
    ú'z' is not one of the inputs: r,   r   zInteger key: z must be non-negative and < zKey value: z must be string or integer.)r    ÚstrÚinputsÚindexr'   r!   Z
issubdtypeÚtypeÚintegerr&   Ú
IndexError)ÚmodelÚkeyrE   r   r   r   Ú	get_indexŒ   s    

ÿrK   ©rE   c                 C   s
   | j | S ©z3Get the input name corresponding to the input index©rD   )rI   rE   r   r   r   Úget_name¥   s    rO   c                   @   sd  e Zd ZdZd9ee edœdd„Zedd„ ƒZ	eed	œd
d„ƒZ
eee d	œdd„ƒZd:eedœdd„Zed	œdd„Zedœdd„Zeee d	œdd„ƒZeee dœdd„Zdd„ Zejedœdd„ƒZejeeeef d	œd d!„ƒZed"d#„ ƒZd$d%„ Zd&d'„ Zd(d)„ Zd*d+„ Zee d,œd-d.„ƒZ!e"e d/œd0d1„Z#e"e d/œd2d3„Z$ed4d5„ ƒZ%e"d6œd7d8„Z&dS );Ú_BoundingDomaina‡  
    Base class for ModelBoundingBox and CompoundBoundingBox.
        This is where all the `~astropy.modeling.core.Model` evaluation
        code for evaluating with a bounding box is because it is common
        to both types of bounding box.

    Parameters
    ----------
    model : `~astropy.modeling.Model`
        The Model this bounding domain is for.

    prepare_inputs :
        Generates the necessary input information so that model can
        be evaluated only for input points entirely inside bounding_box.
        This needs to be implemented by a subclass. Note that most of
        the implementation is in ModelBoundingBox.

    prepare_outputs :
        Fills the output values in for any input points outside the
        bounding_box.

    evaluate :
        Performs a complete model evaluation while enforcing the bounds
        on the inputs and returns a complete output.
    NÚC©ÚignoredÚorderc                 C   s"   || _ |  |¡| _|  |¡| _d S r   )Ú_modelÚ_validate_ignoredÚ_ignoredÚ
_get_orderÚ_order)r   rI   rS   rT   r   r   r   Ú__init__Å   s    z_BoundingDomain.__init__c                 C   s   | j S r   )rU   r   r   r   r   rI   Ê   s    z_BoundingDomain.modelr@   c                 C   s   | j S r   )rY   r   r   r   r   rT   Î   s    z_BoundingDomain.orderc                 C   s   | j S r   ©rW   r   r   r   r   rS   Ò   s    z_BoundingDomain.ignored)rT   rA   c                 C   s*   |dkr| j }|dkr&td|› d�ƒ‚|S )zc
        Get if bounding_box is C/python ordered or Fortran/mathematically
        ordered
        N)rQ   ÚFzTorder must be either 'C' (C/python order) or 'F' (Fortran/mathematical order), got: r,   )rY   r'   )r   rT   r   r   r   rX   Ö   s    
ÿz_BoundingDomain._get_orderc                 C   s   t | j|ƒS )z½
        Get the input index corresponding to the given key.
            Can pass in either:
                the string name of the input or
                the input index itself.
        )rK   rU   ©r   rJ   r   r   r   Ú
_get_indexæ   s    z_BoundingDomain._get_indexrL   c                 C   s   t | j|ƒS rM   )rO   rU   )r   rE   r   r   r   Ú	_get_nameð   s    z_BoundingDomain._get_namec                    s   ‡ fdd„ˆ j D ƒS )Nc                    s   g | ]}ˆ   |¡‘qS r   ©r_   )r   rE   r   r   r   r   ö   s     z2_BoundingDomain.ignored_inputs.<locals>.<listcomp>r[   r   r   r   r   Úignored_inputsô   s    z_BoundingDomain.ignored_inputs)rS   rA   c                    s"   |d krg S ‡ fdd„|D ƒS d S )Nc                    s   g | ]}ˆ   |¡‘qS r   ©r^   )r   rJ   r   r   r   r   ü   s     z5_BoundingDomain._validate_ignored.<locals>.<listcomp>r   )r   rS   r   r   r   rV   ø   s    z!_BoundingDomain._validate_ignoredc                 O   s   t dƒ‚d S )NzPThis bounding box is fixed by the model and does not have adjustable parameters.©ÚNotImplementedError)r   ÚargsÚkwargsr   r   r   Ú__call__þ   s    ÿz_BoundingDomain.__call__©Úfixed_inputsc                 C   s   t dƒ‚dS )áC  
        Fix the bounding_box for a `fix_inputs` compound model.

        Parameters
        ----------
        model : `~astropy.modeling.Model`
            The new model for which this will be a bounding_box
        fixed_inputs : dict
            Dictionary of inputs which have been fixed by this bounding box.
        z,This should be implemented by a child class.Nrc   )r   rI   ri   r   r   r   Ú
fix_inputs  s    z_BoundingDomain.fix_inputsc                 C   s   t dƒ‚dS )á|  
        Get prepare the inputs with respect to the bounding box.

        Parameters
        ----------
        input_shape : tuple
            The shape that all inputs have be reshaped/broadcasted into
        inputs : list
            List of all the model inputs

        Returns
        -------
        valid_inputs : list
            The inputs reduced to just those inputs which are all inside
            their respective bounding box intervals
        valid_index : array_like
            array of all indices inside the bounding box
        all_out: bool
            if all of the inputs are outside the bounding_box
        z1This has not been implemented for BoundingDomain.Nrc   )r   Úinput_shaperD   r   r   r   Úprepare_inputs  s    z_BoundingDomain.prepare_inputsc                 C   s   t  | ¡| S )aÛ  
        Create a baseline output, assuming that the entire input is outside
        the bounding box

        Parameters
        ----------
        input_shape : tuple
            The shape that all inputs have be reshaped/broadcasted into
        fill_value : float
            The value which will be assigned to inputs which are outside
            the bounding box

        Returns
        -------
        An array of the correct shape containing all fill_value
        )r!   Úzeros)rm   Ú
fill_valuer   r   r   Ú_base_output+  s    z_BoundingDomain._base_outputc                    s"   ‡ ‡‡fdd„t ˆjjƒD ƒdfS )a¼  
        Create output if all inputs are outside the domain

        Parameters
        ----------
        input_shape : tuple
            The shape that all inputs have be reshaped/broadcasted into
        fill_value : float
            The value which will be assigned to inputs which are outside
            the bounding box

        Returns
        -------
        A full set of outputs for case that all inputs are outside domain.
        c                    s   g | ]}ˆ  ˆˆ ¡‘qS r   )rq   )r   Ú_©rp   rm   r   r   r   r   P  s   ÿz3_BoundingDomain._all_out_output.<locals>.<listcomp>N)ÚrangerU   Ú	n_outputs)r   rm   rp   r   rs   r   Ú_all_out_output?  s
    
þýz_BoundingDomain._all_out_outputc                 C   s>   |   ||¡}|jst |¡}n|||< t |¡r:| d¡}|S )a
  
        For a single output fill in all the parts corresponding to inputs
        outside the bounding box.

        Parameters
        ----------
        valid_output : numpy array
            The output from the model corresponding to inputs inside the
            bounding box
        valid_index : numpy array
            array of all indices of inputs inside the bounding box
        input_shape : tuple
            The shape that all inputs have be reshaped/broadcasted into
        fill_value : float
            The value which will be assigned to inputs which are outside
            the bounding box

        Returns
        -------
        An output array with all the indices corresponding to inputs
        outside the bounding box filled in by fill_value
        r   )rq   r$   r!   ÚarrayÚisscalarÚitem)r   Úvalid_outputÚvalid_indexrm   rp   Úoutputr   r   r   Ú_modify_outputU  s    

z_BoundingDomain._modify_outputc              	   C   s(   g }|D ]}|  |  ||||¡¡ q|S )aÂ  
        Fill in all the outputs of the model corresponding to inputs
        outside the bounding_box.

        Parameters
        ----------
        valid_outputs : list of numpy array
            The list of outputs from the model corresponding to inputs
            inside the bounding box
        valid_index : numpy array
            array of all indices of inputs inside the bounding box
        input_shape : tuple
            The shape that all inputs have be reshaped/broadcasted into
        fill_value : float
            The value which will be assigned to inputs which are outside
            the bounding box

        Returns
        -------
        List of filled in output arrays.
        )Úappendr}   )r   Úvalid_outputsr{   rm   rp   Úoutputsrz   r   r   r   Ú_prepare_outputsw  s    ÿz _BoundingDomain._prepare_outputsc                 C   s"   | j jdkr|g}|  ||||¡S )aÏ  
        Fill in all the outputs of the model corresponding to inputs
        outside the bounding_box, adjusting any single output model so that
        its output becomes a list of containing that output.

        Parameters
        ----------
        valid_outputs : list
            The list of outputs from the model corresponding to inputs
            inside the bounding box
        valid_index : array_like
            array of all indices of inputs inside the bounding box
        input_shape : tuple
            The shape that all inputs have be reshaped/broadcasted into
        fill_value : float
            The value which will be assigned to inputs which are outside
            the bounding box
        r   )rU   ru   r�   )r   r   r{   rm   rp   r   r   r   Úprepare_outputs•  s       ÿz_BoundingDomain.prepare_outputs)Ú
with_unitsc                 C   s   |rt | ddƒS dS )aD  
        Get the unit for outputs if one is required.

        Parameters
        ----------
        valid_outputs : list of numpy array
            The list of outputs from the model corresponding to inputs
            inside the bounding box
        with_units : bool
            whether or not a unit is required
        ÚunitN)Úgetattr)r   rƒ   r   r   r   Ú_get_valid_outputs_unit¯  s    z'_BoundingDomain._get_valid_outputs_unit)Úevaluaterƒ   c           	      C   s(   ||ƒ}|   ||¡}|  ||||¡|fS )a¾  
        Evaluate the model using the given evaluate routine

        Parameters
        ----------
        evaluate : Callable
            callable which takes in the valid inputs to evaluate model
        valid_inputs : list of numpy arrays
            The inputs reduced to just those inputs which are all inside
            their respective bounding box intervals
        valid_index : numpy array
            array of all indices inside the bounding box
        input_shape : tuple
            The shape that all inputs have be reshaped/broadcasted into
        fill_value : float
            The value which will be assigned to inputs which are outside
            the bounding box
        with_units : bool
            whether or not a unit is required

        Returns
        -------
        outputs :
            list containing filled in output values
        valid_outputs_unit :
            the unit that will be attached to the outputs
        )r†   r‚   )	r   r‡   Úvalid_inputsr{   rm   rp   rƒ   r   Úvalid_outputs_unitr   r   r   Ú_evaluate_modelÀ  s
    $þz_BoundingDomain._evaluate_modelc           	      C   s:   |   ||¡\}}}|r"|  ||¡S |  ||||||¡S dS )aä  
        Perform model evaluation steps:
            prepare_inputs -> evaluate -> prepare_outputs

        Parameters
        ----------
        evaluate : Callable
            callable which takes in the valid inputs to evaluate model
        valid_inputs : list of numpy arrays
            The inputs reduced to just those inputs which are all inside
            their respective bounding box intervals
        valid_index : numpy array
            array of all indices inside the bounding box
        input_shape : tuple
            The shape that all inputs have be reshaped/broadcasted into
        fill_value : float
            The value which will be assigned to inputs which are outside
            the bounding box
        with_units : bool
            whether or not a unit is required

        Returns
        -------
        outputs :
            list containing filled in output values
        valid_outputs_unit :
            the unit that will be attached to the outputs
        N)rn   rv   rŠ   )	r   r‡   rD   rm   rp   rƒ   rˆ   r{   Úall_outr   r   r   Ú	_evaluateì  s         ÿz_BoundingDomain._evaluatec                 C   s   |dk	rt | |ddd�S | S )a›  
        Set the units on the outputs
            prepare_inputs -> evaluate -> prepare_outputs -> set output units

        Parameters
        ----------
        outputs :
            list containing filled in output values
        valid_outputs_unit :
            the unit that will be attached to the outputs

        Returns
        -------
        List containing filled in output values and units
        NFT)r   Zsubokr   )r€   r‰   r   r   r   Ú_set_outputs_unit  s    z!_BoundingDomain._set_outputs_unit)r‡   c                 C   s6   | j  |¡}|  ||||| j j¡\}}t|  ||¡ƒS )a‚  
        Perform full model evaluation steps:
            prepare_inputs -> evaluate -> prepare_outputs -> set output units

        Parameters
        ----------
        evaluate : callable
            callable which takes in the valid inputs to evaluate model
        valid_inputs : list
            The inputs reduced to just those inputs which are all inside
            their respective bounding box intervals
        valid_index : array_like
            array of all indices inside the bounding box
        fill_value : float
            The value which will be assigned to inputs which are outside
            the bounding box
        )rU   rm   rŒ   Zbbox_with_unitsr3   r�   )r   r‡   rD   rp   rm   r€   r‰   r   r   r   r‡   +  s        ÿz_BoundingDomain.evaluate)NrQ   )N)'r:   r;   r<   r=   r   ÚintrC   rZ   ÚpropertyrI   rT   rS   rX   r^   r_   ra   ÚlistrV   rg   ÚabcÚabstractmethodÚdictrk   r   r   rn   r>   rq   rv   r}   r�   r‚   Úboolr†   r   rŠ   rŒ   r�   r‡   r   r   r   r   rP   ª   sH   


"ù- ÿ(
rP   c                       sŽ  e Zd ZdZd?eeef ee edœ‡ fdd„Z	d@dd„Z
eeeef d	œd
d„ƒZeeeef d	œdd„ƒZdd„ Zdd„ Zdd„ Zdd„ Zdd„ ZdAedœdd„Zdd„ Zdd„ Zdd „ Zed!œd"d#„Zed$d%„ ƒZdBedœd&d'„Zeed	œd(d)„ƒZdCedœd*d+„ZdDedœd,d-„ZedEeee d/œd0d1„ƒZ!dFed2œd3d4„Z"ed5d6„ ƒZ#dGedœd7d8„Z$d9d:„ Z%d;d<„ Z&e'e(e(e(f d	œd=d>„Z)‡  Z*S )Hr   aÔ  
    A model's bounding box

    Parameters
    ----------
    intervals : dict
        A dictionary containing all the intervals for each model input
            keys   -> input index
            values -> interval for that index

    model : `~astropy.modeling.Model`
        The Model this bounding_box is for.

    ignored : list
        A list containing all the inputs (index) which will not be
        checked for whether or not their elements are in/out of an interval.

    order : optional, str
        The ordering that is assumed for the tuple representation of this
        bounding_box. Options: 'C': C/Python order, e.g. z, y, x.
        (default), 'F': Fortran/mathematical notation order, e.g. x, y, z.
    NrQ   )Ú	intervalsrS   rT   c                    s8   t ƒ  |||¡ i | _|dkr4|i kr4| j||d� d S )Nr   ©rT   )ÚsuperrZ   Ú
_intervalsÚ	_validate)r   r•   rI   rS   rT   ©Ú	__class__r   r   rZ   `  s    zModelBoundingBox.__init__c                 C   s:   dd„ | j  ¡ D ƒ}|d kr&| j ¡ }t|| j|| jd�S )Nc                 S   s   i | ]\}}||  ¡ “qS r   )r   )r   rE   r*   r   r   r   Ú
<dictcomp>n  s     z)ModelBoundingBox.copy.<locals>.<dictcomp>rR   )r˜   ÚitemsrW   r   r   rU   rY   )r   rS   r•   r   r   r   r   m  s    ÿ
   ÿzModelBoundingBox.copyr@   c                 C   s   | j S )z1Return bounding_box labeled using input positions)r˜   r   r   r   r   r•   y  s    zModelBoundingBox.intervalsc                    s   ‡ fdd„ˆ j  ¡ D ƒS )z-Return bounding_box labeled using input namesc                    s   i | ]\}}ˆ   |¡|“qS r   r`   )r   rE   Úbboxr   r   r   rœ   �  s      z4ModelBoundingBox.named_intervals.<locals>.<dictcomp>)r˜   r�   r   r   r   r   Únamed_intervals~  s    z ModelBoundingBox.named_intervalsc                 C   s¦   ddg}| j  ¡ D ]\}}| d|› d|› �¡ q| d¡ t| jƒdkr\| d| j› �¡ | d| jjj› d	| jj	› d
�¡ | d| j
› d�¡ | d
¡ d |¡S )NzModelBoundingBox(z    intervals={ú        z: ú    }r   z    ignored=z
    model=z(inputs=r   z    order='rB   Ú
)rŸ   r�   r~   r&   rW   ra   rU   r›   r:   rD   rY   Újoin)r   ÚpartsÚnamer*   r   r   r   r   ƒ  s    
ÿ
zModelBoundingBox.__repr__c                 C   s
   t | jƒS r   )r&   r˜   r   r   r   r   Ú__len__•  s    zModelBoundingBox.__len__c              	   C   s8   z|   |¡| jkp| jW S  ttfk
r2   Y dS X d S ©NF)r^   r˜   rW   rH   r'   r]   r   r   r   Ú__contains__˜  s    zModelBoundingBox.__contains__c                 C   s   |   |¡| jkS r   )r^   r˜   r]   r   r   r   Úhas_intervalž  s    zModelBoundingBox.has_intervalc                 C   s,   |   |¡}|| jkrtS | j|   |¡ S dS )z<Get bounding_box entries by either input name or input indexN)r^   rW   Ú_ignored_intervalr˜   ©r   rJ   rE   r   r   r   Ú__getitem__¡  s    

zModelBoundingBox.__getitem__r–   c                    s~   t ˆ jƒdkr$ttˆ j ¡ ƒd ƒS ˆ  |¡}ˆ jj}|dkrL|ddd… }t‡ fdd„|D ƒƒ}t |ƒdkrv|d }|S dS )zÛ
        Return the old tuple of tuples representation of the bounding_box
            order='C' corresponds to the old bounding_box ordering
            order='F' corresponds to the gwcs bounding_box ordering.
        r   r   rQ   Néÿÿÿÿc                 3   s   | ]}t ˆ | ƒV  qd S r   ©r3   ©r   Z
input_namer   r   r   r#   ·  s     z0ModelBoundingBox.bounding_box.<locals>.<genexpr>)r&   r˜   r3   r�   ÚvaluesrX   rU   rD   )r   rT   rD   rž   r   r   r   Úbounding_box©  s    
zModelBoundingBox.bounding_boxc                 C   s@   t |tƒr|  ¡ |kS t |tƒr8| j|jko6| j|jkS dS dS )z?Note equality can be either with old representation or new one.FN)r    r3   r±   r   r•   rS   ©r   Úvaluer   r   r   Ú__eq__½  s    


ÿzModelBoundingBox.__eq__c                 C   s4   |   |¡}|| jkr | j |¡ t |¡| j|< dS )zBValidate and store interval under key (input index or input name).N)r^   rW   Úremover   r4   r˜   )r   rJ   r³   rE   r   r   r   Ú__setitem__È  s    

zModelBoundingBox.__setitem__c                 C   s<   |   |¡}|| jkr$td|› d�ƒ‚| j|= | j |¡ dS )zDelete stored intervalzCannot delete ignored input: ú!N)r^   rW   ÚRuntimeErrorr˜   r~   r«   r   r   r   Ú__delitem__Ð  s
    

zModelBoundingBox.__delitem__)r±   c                 C   s   |  ¡ D ]\}}|| |< qdS )z:Validate passing dictionary of intervals and setting them.N©r�   )r   r±   rJ   r³   r   r   r   Ú_validate_dictØ  s    zModelBoundingBox._validate_dictc                    s(   ‡ fdd„ˆ j jD ƒ}‡ fdd„|D ƒS )Nc                    s   g | ]}ˆ   |¡‘qS r   rb   ©r   r5   r   r   r   r   ß  s     z;ModelBoundingBox._available_input_index.<locals>.<listcomp>c                    s   g | ]}|ˆ j kr|‘qS r   r[   r¼   r   r   r   r   á  s     
 )rU   rD   )r   Zmodel_input_indexr   r   r   Ú_available_input_indexÝ  s    z'ModelBoundingBox._available_input_indexc                 C   sD   |   |¡}|dkr |ddd… }t|ƒD ]\}}|| | j| < q(dS )z`
        Validate passing tuple of tuples representation (or related) and setting them.
        rQ   Nr­   )rX   Ú	enumerater½   )r   r±   rT   rE   r³   r   r   r   Ú_validate_sequenceã  s
    
z#ModelBoundingBox._validate_sequencec                 C   s&   | j jt| jƒ }|dkr|S dS d S )Nr   )rU   Ún_inputsr&   rW   )r   rÀ   r   r   r   Ú	_n_inputsð  s    zModelBoundingBox._n_inputsc                 C   sP   t |ƒ| jkr*tdt |ƒ› d| j› d�ƒ‚t|tƒr@|  |¡ n|  ||¡ dS )z,Validate and set any iterable representationzFound z" intervals, but must have exactly r,   N)r&   rÁ   r'   r    r“   r»   r¿   ©r   r±   rT   r   r   r   Ú_validate_iterableø  s    ÿ
z#ModelBoundingBox._validate_iterablec                 C   s4   | j dkr$t|tƒs$|| | jd < n|  ||¡ dS )z#Validate and set any representationr   r   N)rÁ   r    r“   r½   rÃ   rÂ   r   r   r   r™     s    zModelBoundingBox._validateF)rS   rT   Ú_preserve_ignorec                 K   s>   t |tƒr |j}|r|j}|j}| i |||d�}| |¡ |S )aª  
        Construct a valid bounding box for a model.

        Parameters
        ----------
        model : `~astropy.modeling.Model`
            The model for which this will be a bounding_box
        bounding_box : dict, tuple
            A possible representation of the bounding box
        order : optional, str
            The order that a tuple representation will be assumed to be
                Default: 'C'
        rR   )r    r   rT   rS   rŸ   r™   )r1   rI   r±   rS   rT   rÄ   rf   Únewr   r   r   r4     s    

zModelBoundingBox.validaterh   c                 C   sB   |   ¡ }| ¡ D ]
}||= q|r(|j}nd}tj||j||jd�S )a°  
        Fix the bounding_box for a `fix_inputs` compound model.

        Parameters
        ----------
        model : `~astropy.modeling.Model`
            The new model for which this will be a bounding_box
        fixed_inputs : dict
            Dictionary of inputs which have been fixed by this bounding box.
        keep_ignored : bool
            Keep the ignored inputs of the bounding box (internal argument only)
        NrR   )r   ÚkeysrS   r   r4   rŸ   rY   )r   rI   ri   Ú_keep_ignoredrÅ   r5   rS   r   r   r   rk   .  s       ÿzModelBoundingBox.fix_inputsc                 C   s   t | ƒS r   )r&   r   r   r   r   Ú	dimensionJ  s    zModelBoundingBox.dimensionc                    s<   ˆj j}ˆ |¡}|dkr(|d d d… }‡ ‡fdd„|D ƒS )NrQ   r­   c                    s   g | ]}ˆ|   ˆ ¡‘qS r   )r9   r¯   ©r8   r   r   r   r   T  s     z+ModelBoundingBox.domain.<locals>.<listcomp>)rU   rD   rX   )r   r8   rT   rD   r   rÉ   r   r9   N  s
    
zModelBoundingBox.domainc                 C   sd   d}t j|td�}t|ƒD ]@\}}t  |¡}t  | |  |¡|¡}d||< | ¡ rd} q\q||fS )aƒ  
        Get all the input positions which are outside the bounding_box,
        so that the corresponding outputs can be filled with the fill
        value (default NaN).

        Parameters
        ----------
        input_shape : tuple
            The shape that all inputs have be reshaped/broadcasted into
        inputs : list
            List of all the model inputs

        Returns
        -------
        outside_index : bool-numpy array
            True  -> position outside bounding_box
            False -> position inside  bounding_box
        all_out : bool
            if all of the inputs are outside the bounding_box
        F)ZdtypeT)r!   ro   r”   r¾   r-   Úbroadcast_tor7   r)   )r   rm   rD   r‹   Úoutside_indexrE   r5   r7   r   r   r   Ú_outsideV  s    
zModelBoundingBox._outsidec                 C   s@   |   ||¡\}}t t |¡¡ ¡ }t|d ƒdkr8d}||fS )aç  
        Get the indices of all the inputs inside the bounding_box.

        Parameters
        ----------
        input_shape : tuple
            The shape that all inputs have be reshaped/broadcasted into
        inputs : list
            List of all the model inputs

        Returns
        -------
        valid_index : numpy array
            array of all indices inside the bounding box
        all_out : bool
            if all of the inputs are outside the bounding_box
        r   T)rÌ   r!   Ú
atleast_1dZlogical_notZnonzeror&   )r   rm   rD   rË   r‹   r{   r   r   r   Ú_valid_indexz  s
    zModelBoundingBox._valid_indexc                 C   st   |   ||¡\}}g }|sf|D ]H}|rZt t |¡|¡| }t |¡rN| d¡}| |¡ q| |¡ qt|ƒ||fS )rl   r   )rÎ   r!   rÊ   rÍ   rx   ry   r~   r3   )r   rm   rD   r{   r‹   rˆ   r5   Zvalid_inputr   r   r   rn   ”  s    ÿ

zModelBoundingBox.prepare_inputs)NrQ   )N)N)N)N)N)NrQ   F)F)N)+r:   r;   r<   r=   r   rŽ   r   r   rC   rZ   r   r�   r•   rŸ   r   r¦   r¨   r©   r¬   r±   r´   r¶   r¹   r“   r»   r½   r¿   rÁ   rÃ   r™   r?   r�   r”   r4   rk   rÈ   r9   rÌ   rÎ   r   r   rn   Ú__classcell__r   r   rš   r   r   H  s\     û
û

   úú!
$Ú_BaseSelectorArgumentzindex ignorec                       sv   e Zd ZdZ‡ fdd„Zededœdd„ƒZdd	„ Ze	d
œdd„Z
dd„ Zedœdd„Zed
œdd„Zdd„ Z‡  ZS )Ú_SelectorArgumenta#  
    Contains a single CompoundBoundingBox slicing input.

    Parameters
    ----------
    index : int
        The index of the input in the input list

    ignore : bool
        Whether or not this input will be ignored by the bounding box.

    Methods
    -------
    validate :
        Returns a valid SelectorArgument for a given model.

    get_selector :
        Returns the value of the input for use in finding the correct
        bounding_box.

    get_fixed_value :
        Gets the slicing value from a fix_inputs set of values.
    c                    s   t ƒ  | ||¡}|S r   )r—   Ú__new__)r1   rE   Úignorer   rš   r   r   rÒ   ×  s    z_SelectorArgument.__new__T)rS   c                 C   s   | t ||ƒ|ƒS )aí  
        Construct a valid selector argument for a CompoundBoundingBox.

        Parameters
        ----------
        model : `~astropy.modeling.Model`
            The model for which this will be an argument for.
        argument : int or str
            A representation of which evaluation input to use
        ignored : optional, bool
            Whether or not to ignore this argument in the ModelBoundingBox.

        Returns
        -------
        Validated selector_argument
        )rK   )r1   rI   ÚargumentrS   r   r   r   r4   Ü  s    z_SelectorArgument.validatec                 G   s2   || j  }t|ƒr.t|ƒdkr&|d S t|ƒS |S )z·
        Get the selector value corresponding to this argument

        Parameters
        ----------
        *inputs :
            All the processed model evaluation inputs.
        r   r   )rE   r
   r&   r3   ©r   rD   Ú	_selectorr   r   r   Úget_selectorð  s    	
z_SelectorArgument.get_selectorr@   c                 C   s   t || jƒS )zÕ
        Get the name of the input described by this selector argument

        Parameters
        ----------
        model : `~astropy.modeling.Model`
            The Model this selector argument is for.
        )rO   rE   ©r   rI   r   r   r   r¥     s    	z_SelectorArgument.namec                 C   s   d|   |¡› d| j› d�S )zÈ
        Get a pretty-print representation of this object

        Parameters
        ----------
        model : `~astropy.modeling.Model`
            The Model this selector argument is for.
        zArgument(name='z
', ignore=r   ©r¥   rÓ   rØ   r   r   r   Úpretty_repr  s    	z_SelectorArgument.pretty_repr©r°   c                 C   sL   | j |kr|| j  S |  |¡|kr0||  |¡ S t|  |¡› d|› �ƒ‚dS )a  
        Gets the value fixed input corresponding to this argument

        Parameters
        ----------
        model : `~astropy.modeling.Model`
            The Model this selector argument is for.

        values : dict
            Dictionary of fixed inputs.
        z was not found in N)rE   r¥   r¸   rÚ   ©r   rI   r°   r   r   r   Úget_fixed_value  s    

ÿz!_SelectorArgument.get_fixed_valuec                 C   s   | j t||ƒkS )a?  
        Determine if passed argument is described by this selector argument

        Parameters
        ----------
        model : `~astropy.modeling.Model`
            The Model this selector argument is for.

        argument : int or str
            A representation of which evaluation input is being used
        )rE   rK   )r   rI   rÔ   r   r   r   Úis_argument-  s    z_SelectorArgument.is_argumentc                 C   s   |   |¡| jfS )zð
        Get a tuple representation of this argument using the input
        name from the model.

        Parameters
        ----------
        model : `~astropy.modeling.Model`
            The Model this selector argument is for.
        rÙ   rØ   r   r   r   Únamed_tuple<  s    
z_SelectorArgument.named_tuple)T)r:   r;   r<   r=   rÒ   r?   r”   r4   r×   rC   r¥   rÚ   r“   rÝ   rÞ   rß   rÏ   r   r   rš   r   rÑ   ¾  s   rÑ   c                       s²   e Zd ZdZdZd!ee edœ‡ fdd„Zdd„ Z	e
dd	„ ƒZe
d
d„ ƒZed"edœdd„ƒZdd„ Zdd„ Zedœdd„Zedœdd„Zdd„ Zdd„ Zdd„ Zdd „ Z‡  ZS )#Ú_SelectorArgumentsaû  
    Contains the CompoundBoundingBox slicing description

    Parameters
    ----------
    input_ :
        The SelectorArgument values

    Methods
    -------
    validate :
        Returns a valid SelectorArguments for its model.

    get_selector :
        Returns the selector a set of inputs corresponds to.

    is_selector :
        Determines if a selector is correctly formatted for this CompoundBoundingBox.

    get_fixed_value :
        Gets the selector from a fix_inputs set of values.
    N)Úinput_Úkept_ignorec                    s(   t ƒ  | |¡}|d krg |_n||_|S r   )r—   rÒ   Ú_kept_ignore)r1   rá   râ   r   rš   r   r   rÒ   c  s
    z_SelectorArguments.__new__c                 C   s:   dg}| D ]}|  d| |¡› �¡ q
|  d¡ d |¡S )zË
        Get a pretty-print representation of this object

        Parameters
        ----------
        model : `~astropy.modeling.Model`
            The Model these selector arguments are for.
        zSelectorArguments(z    r   r¢   )r~   rÚ   r£   )r   rI   r¤   rÔ   r   r   r   rÚ   m  s
    	
z_SelectorArguments.pretty_reprc                 C   s   dd„ | D ƒ}|  | j¡ |S )zGet the list of ignored inputsc                 S   s   g | ]}|j r|j‘qS r   )rÓ   rE   ©r   rÔ   r   r   r   r   €  s      z-_SelectorArguments.ignore.<locals>.<listcomp>)Úextendrã   )r   rÓ   r   r   r   rÓ   }  s    z_SelectorArguments.ignorec                 C   s   | j S )z$The arguments to persist in ignoring)rã   r   r   r   r   râ   …  s    z_SelectorArguments.kept_ignore)râ   c                 C   s˜   g }|D ]J}t j|f|žŽ }|jdd„ |D ƒkrHtdt||jƒ› d�ƒ‚| |¡ qt|ƒdkrhtdƒ‚t|tƒrŠ|dkr~g }| 	|j
¡ | t|ƒ|ƒS )ae  
        Construct a valid Selector description for a CompoundBoundingBox.

        Parameters
        ----------
        model : `~astropy.modeling.Model`
            The Model these selector arguments are for.

        arguments :
            The individual argument informations

        kept_ignore :
            Arguments to persist as ignored
        c                 S   s   g | ]
}|j ‘qS r   rL   )r   Úthisr   r   r   r   �  s     z/_SelectorArguments.validate.<locals>.<listcomp>zInput: 'z' has been repeated.r   z-There must be at least one selector argument.N)rÑ   r4   rE   r'   rO   r~   r&   r    rà   rå   râ   r3   )r1   rI   Ú	argumentsrâ   rD   rÔ   r5   r   r   r   r4   Š  s    ÿ
z_SelectorArguments.validatec                    s   t ‡ fdd„| D ƒƒS )z°
        Get the selector corresponding to these inputs

        Parameters
        ----------
        *inputs :
            All the processed model evaluation inputs.
        c                 3   s   | ]}|j ˆ Ž V  qd S r   )r×   rä   rN   r   r   r#   ·  s     z2_SelectorArguments.get_selector.<locals>.<genexpr>r®   )r   rD   r   rN   r   r×   ®  s    	z_SelectorArguments.get_selectorc                 C   s   t |tƒot|ƒt| ƒkS )zŸ
        Determine if this is a reasonable selector

        Parameters
        ----------
        _selector : tuple
            The selector to check
        )r    r3   r&   ©r   rÖ   r   r   r   Úis_selector¹  s    	z_SelectorArguments.is_selectorrÛ   c                    s   t ‡ ‡fdd„| D ƒƒS )a  
        Gets the value fixed input corresponding to this argument

        Parameters
        ----------
        model : `~astropy.modeling.Model`
            The Model these selector arguments are for.

        values : dict
            Dictionary of fixed inputs.
        c                 3   s   | ]}|  ˆ ˆ¡V  qd S r   )rÝ   rä   ©rI   r°   r   r   r#   Ð  s     z6_SelectorArguments.get_fixed_values.<locals>.<genexpr>r®   rÜ   r   rê   r   Úget_fixed_valuesÄ  s    z#_SelectorArguments.get_fixed_valuesr@   c                 C   s    | D ]}|  ||¡r dS qdS )a<  
        Determine if passed argument is one of the selector arguments

        Parameters
        ----------
        model : `~astropy.modeling.Model`
            The Model these selector arguments are for.

        argument : int or str
            A representation of which evaluation input is being used
        TFN)rÞ   )r   rI   rÔ   Úselector_argr   r   r   rÞ   Ò  s    z_SelectorArguments.is_argumentc                 C   s8   t | ƒD ]\}}| ||¡r|  S qt|› d�ƒ‚dS )a2  
        Get the index of the argument passed in the selector tuples

        Parameters
        ----------
        model : `~astropy.modeling.Model`
            The Model these selector arguments are for.

        argument : int or str
            A representation of which argument is being used
        z. does not correspond to any selector argument.N)r¾   rÞ   r'   )r   rI   rÔ   rE   rì   r   r   r   Úselector_indexå  s    
ÿz!_SelectorArguments.selector_indexc                 C   s<   t | ƒ}| |  ||¡¡jg}| | j¡ t |t|ƒ|¡S )a*  
        Reduce the selector arguments by the argument given

        Parameters
        ----------
        model : `~astropy.modeling.Model`
            The Model these selector arguments are for.

        argument : int or str
            A representation of which argument is being used
        )	r�   Úpoprí   rE   rå   rã   rà   r4   r3   )r   rI   rÔ   rç   râ   r   r   r   Úreduceú  s    z_SelectorArguments.reducec                 C   s4   |   ||¡rt|› d�ƒ‚t||ƒg}t || |¡S )a  
        Add argument to the kept_ignore list

        Parameters
        ----------
        model : `~astropy.modeling.Model`
            The Model these selector arguments are for.

        argument : int or str
            A representation of which argument is being used
        z/: is a selector argument and cannot be ignored.)rÞ   r'   rK   rà   r4   )r   rI   rÔ   râ   r   r   r   Ú
add_ignore  s    ÿz_SelectorArguments.add_ignorec                    s   t ‡ fdd„| D ƒƒS )zÔ
        Get a tuple of selector argument tuples using input names

        Parameters
        ----------
        model : `~astropy.modeling.Model`
            The Model these selector arguments are for.
        c                 3   s   | ]}|  ˆ ¡V  qd S r   )rß   )r   rì   ©rI   r   r   r#   ,  s     z1_SelectorArguments.named_tuple.<locals>.<genexpr>r®   rØ   r   rñ   r   rß   #  s    	z_SelectorArguments.named_tuple)N)N)r:   r;   r<   r=   rã   r   rÑ   r   rÒ   rÚ   r�   rÓ   râ   r?   r4   r×   ré   r“   rë   r”   rÞ   rí   rï   rð   rß   rÏ   r   r   rš   r   rà   I  s$   


#rà   c                       sZ  e Zd ZdZd5eeef eee	e
 edœ‡ fdd„Zdd„ Zd	d
„ Zeeeef dœdd„ƒZeedœdd„ƒZejdd„ ƒZeedœdd„ƒZedd„ ƒZedd„ ƒZdd„ Zedœdd„Zdd„ Zed6eeeedœd d!„ƒZd"d#„ Z d$d%„ Z!d&d'„ Z"edœd(d)„Z#e$eeef dœd*d+„Z%eeef dœd,d-„Z&d.d/„ Z'd0d1„ Z(ed2œd3d4„Z)‡  Z*S )7r   a”  
    A model's compound bounding box

    Parameters
    ----------
    bounding_boxes : dict
        A dictionary containing all the ModelBoundingBoxes that are possible
            keys   -> _selector (extracted from model inputs)
            values -> ModelBoundingBox

    model : `~astropy.modeling.Model`
        The Model this compound bounding_box is for.

    selector_args : _SelectorArguments
        A description of how to extract the selectors from model inputs.

    create_selector : optional
        A method which takes in the selector and the model to return a
        valid bounding corresponding to that selector. This can be used
        to construct new bounding_boxes for previously undefined selectors.
        These new boxes are then stored for future lookups.

    order : optional, str
        The ordering that is assumed for the tuple representation of the
        bounding_boxes.
    NrQ   )Úbounding_boxesÚselector_argsÚcreate_selectorrS   rT   c                    s8   t ƒ  |||¡ || _t ||¡| _i | _|  |¡ d S r   )r—   rZ   Ú_create_selectorrà   r4   Ú_selector_argsÚ_bounding_boxesr™   )r   rò   rI   ró   rô   rS   rT   rš   r   r   rZ   K  s
    	zCompoundBoundingBox.__init__c                    s8   ‡ fdd„ˆ j  ¡ D ƒ}t|ˆ jˆ jt ˆ j¡ˆ jd�S )Nc                    s    i | ]\}}||  ˆ jj¡“qS r   )r   ró   rÓ   )r   Úselectorrž   r   r   r   rœ   ]  s   ÿ z,CompoundBoundingBox.copy.<locals>.<dictcomp>)ró   rô   rT   )	r÷   r�   r   rU   rö   r   r   rõ   rY   )r   rò   r   r   r   r   \  s    
þ
ûzCompoundBoundingBox.copyc              	   C   sÂ   ddg}| j  ¡ D ]L\}}| ¡  d¡}| d|› d| d¡› �¡ |D ]}| d|› �¡ qHq| d¡ | j | j¡ d¡}| d	| d¡› �¡ |D ]}| d|› �¡ q˜| d
¡ d 	|¡S )NzCompoundBoundingBox(z    bounding_boxes={r¢   r    z = r   z            r¡   z    selector_args = r   )
r÷   r�   r   Úsplitr~   rî   ró   rÚ   rU   r£   )r   r¤   rÖ   rž   Z	bbox_reprÚpartZselector_args_reprr   r   r   r   j  s    

zCompoundBoundingBox.__repr__r@   c                 C   s   | j S r   ©r÷   r   r   r   r   rò   }  s    z"CompoundBoundingBox.bounding_boxesc                 C   s   | j S r   )rö   r   r   r   r   ró   �  s    z!CompoundBoundingBox.selector_argsc                 C   s    t  | j|¡| _t dt¡ d S )NzhOverriding selector_args may cause problems you should re-validate the compound bounding box before use!)rà   r4   rU   rö   r.   r/   r0   r²   r   r   r   ró   …  s
    ýc                 C   s   | j  | j¡S r   )rö   rß   rU   r   r   r   r   Únamed_selector_tuple�  s    z(CompoundBoundingBox.named_selector_tuplec                 C   s   | j S r   )rõ   r   r   r   r   rô   “  s    z#CompoundBoundingBox.create_selectorc                 C   s   t | ƒrt| ƒS | fS d S r   )r
   r3   )rJ   r   r   r   Ú_get_selector_key—  s    z%CompoundBoundingBox._get_selector_keyc                 C   sR   |   |¡}| j |¡s$t|› d�ƒ‚| jj| j }tj| j||| j	d�| j
|< d S )Nz is not a selector!r–   )rý   ró   ré   r'   rÓ   rS   r   r4   rU   rY   r÷   )r   rJ   r³   rÖ   rS   r   r   r   r¶   ž  s    
   ÿzCompoundBoundingBox.__setitem__)rò   c                 C   s   |  ¡ D ]\}}|| |< qd S r   rº   )r   rò   rÖ   r±   r   r   r   r™   ¨  s    zCompoundBoundingBox._validatec                 C   s6   t |tƒr.| j|jko,| j|jko,| j|jkS dS d S r§   )r    r   rò   ró   rô   r²   r   r   r   r´   ¬  s    

ÿ
ýzCompoundBoundingBox.__eq__F)r±   rS   rT   rÄ   c           	      K   s`   t |tƒr<|dkr|j}|dkr&|j}|j}|r6|j}|j}|dkrLtdƒ‚| ||||||d�S )ac  
        Construct a valid compound bounding box for a model.

        Parameters
        ----------
        model : `~astropy.modeling.Model`
            The model for which this will be a bounding_box
        bounding_box : dict
            Dictionary of possible bounding_box respresentations
        selector_args : optional
            Description of the selector arguments
        create_selector : optional, callable
            Method for generating new selectors
        order : optional, str
            The order that a tuple representation will be assumed to be
                Default: 'C'
        NzTSelector arguments must be provided (can be passed as part of bounding_box argument))rô   rS   rT   )r    r   ró   rô   rT   rS   rò   r'   )	r1   rI   r±   ró   rô   rS   rT   rÄ   Úkwargr   r   r   r4   ¶  s*    
ÿúzCompoundBoundingBox.validatec                 C   s
   || j kS r   rû   r]   r   r   r   r¨   ì  s    z CompoundBoundingBox.__contains__c                 C   s   | j || jd�| |< | | S )Nrñ   )rõ   rU   rè   r   r   r   Ú_create_bounding_boxï  s    z(CompoundBoundingBox._create_bounding_boxc                 C   sD   |   |¡}|| kr| j| S | jd k	r0|  |¡S td|› d�ƒ‚d S )Nz)No bounding box is defined for selector: r,   )rý   r÷   rõ   rÿ   r¸   )r   rJ   rÖ   r   r   r   r¬   ô  s    



zCompoundBoundingBox.__getitem__c                 C   s   | j j|Ž }| | S r   )ró   r×   rÕ   r   r   r   Ú_select_bounding_boxý  s    z(CompoundBoundingBox._select_bounding_boxc                 C   s   |   |¡}| ||¡S )rl   )r   rn   )r   rm   rD   r±   r   r   r   rn     s    
z"CompoundBoundingBox.prepare_inputsc           	      C   s¢   | j  | j|¡}i }| j ¡ D ]\\}}|| |krt|ƒ}| |¡ | |¡rf|j| j||idd�}n| 	¡ }||t
|ƒ< qt|ƒdkržtd|› d|› d�ƒ‚|S )NT©rÇ   r   zAttempting to fix input z5, but there are no bounding boxes for argument value r,   )ró   rí   rU   r÷   r�   r�   rî   r©   rk   r   r3   r&   r'   )	r   rÔ   r³   rí   ZmatchingÚselector_keyrž   Znew_selector_keyZnew_bboxr   r   r   Ú_matching_bounding_boxes  s&    

  ÿÿz,CompoundBoundingBox._matching_bounding_boxesc                 C   s@   |   ||¡}t| jƒdkr"|d S t|| j| j | j|¡ƒS d S )Nr   r   )r  r&   ró   r   rU   rï   )r   rÔ   r³   Zmatching_bounding_boxesr   r   r   Ú_fix_input_selector_arg3  s    ýz+CompoundBoundingBox._fix_input_selector_argc                 C   sL   i }| j  ¡ D ]"\}}|j| j||idd�||< qt|| j| j | j|¡ƒS )NTr  )r÷   r�   rk   rU   r   ró   rð   )r   rÔ   r³   rò   r  rž   r   r   r   Ú_fix_input_bbox_arg?  s      ÿýz'CompoundBoundingBox._fix_input_bbox_argrh   c           
      C   s¬   t | ¡ ƒ}| ¡ }|| }| j | j|¡r:|  ||¡}n|  ||¡}t|ƒdkrl| 	¡ }||= | 
||¡}t|tƒr‚|j}|}	nt|tƒr–d}|j}	|jj||	|j|d�S )rj   r   N)rT   ró   )r�   rÆ   rî   ró   rÞ   rU   r  r  r&   r   rk   r    r   rü   r   rŸ   r›   r4   rT   )
r   rI   ri   Zfixed_input_keysrÔ   r³   rž   Znew_fixed_inputsró   Z	bbox_dictr   r   r   rk   L  s,    

   ÿzCompoundBoundingBox.fix_inputs)NNrQ   )NNNrQ   F)+r:   r;   r<   r=   r   r   r   rà   r   r   rŽ   rC   rZ   r   r   r�   rò   ró   Úsetterr3   rü   rô   r>   rý   r¶   r“   r™   r´   r?   r�   r”   r4   r¨   rÿ   r¬   r   r   rn   r  r  r  rk   rÏ   r   r   rš   r   r   /  sb       ù
ù
	



     øø5	)#r=   r‘   r   r.   Úcollectionsr   Útypingr   r   r   r   r   Únumpyr!   Zastropy.unitsr	   Zastropy.utilsr
   Ú__all__r   r   r4   Úinfrª   rŽ   rK   rO   ÚABCrP   r   rÐ   rÑ   r3   rà   r   r   r   r   r   Ú<module>   s6   
p   !  u
  g