a
    ߙfb,                     @   sx   d dl Z d dlm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
gZdd	 Zdd ZG dd
 d
eZdS )    N)defaultdict
isiterable)lazyproperty   )BaseLowLevelWCS   )BaseWCSWrappersanitize_slicesSlicedLowLevelWCSc                 C   s4  t | ttfs| f} t| |kr6td|  d| dtdd | D rPtdt| } t| v r| tdkrvtd| 	t}| 
t |t|  }t|D ]}|| }| |td	 qt|D ]j}|t| k r | | }t |tr|jr|jdkrtd
nt |tjs.tdq| td	 q| S )z
    Given a slice as input sanitise it to an easier to parse format.format

    This function returns a list ``ndim`` long containing slice objects (or ints).
    z*The dimensionality of the specified slice z- can not be greater than the dimensionality (z) of the wcs.c                 s   s   | ]}t |V  qd S Nr   ).0s r   Elib/python3.9/site-packages/astropy/wcs/wcsapi/wrappers/sliced_wcs.py	<genexpr>       z"sanitize_slices.<locals>.<genexpr>zBThis slice is invalid, only integer or range slices are supported.r   z0an index can only have a single ellipsis ('...')Nz)Slicing WCS with a step is not supported.z*Only integer or range slices are accepted.)
isinstancetuplelistlen
ValueErrorany
IndexErrorEllipsiscountindexremoverangeinsertslicestepnumbersIntegralappend)slicesndimZe_indZn_eiZindZslcr   r   r   r
      s<    



c                 C   s  t | tr| jdurtdt |tr8|jdur8tdt |tjr\| jdu rR|S || j S | jdu r| jdu rt|S |jdu rt|j| jS t|jt| j|jS nf|jdu r| j}n| j|j }|jdu r| j}n6| jdu r|j}n|j| j }| jdur
t| j|}t||S )z
    Given two slices that can be applied to a 1-d array, find the resulting
    slice that corresponds to the combination of both slices. We assume that
    slice2 can be an integer, but slice1 cannot.
    Nz)Only slices with steps of 1 are supported)	r   r    r!   r   r"   r#   startstopmin)Zslice1Zslice2r(   r)   r   r   r   combine_slices=   s2    







r+   c                   @   s   e Zd ZdZdd Zedd Zedd Zedd	 Z	ed
d Z
edd Zedd Ze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dd Zed d! Zed"d# Zd$S )%r   a&  
    A Low Level WCS wrapper which applies an array slice to a WCS.

    This class does not modify the underlying WCS object and can therefore drop
    coupled dimensions as it stores which pixel and world dimensions have been
    sliced out (or modified) in the underlying WCS and returns the modified
    results on all the Low Level WCS methods.

    Parameters
    ----------
    wcs : `~astropy.wcs.wcsapi.BaseLowLevelWCS`
        The WCS to slice.
    slices : `slice` or `tuple` or `int`
        A valid array slice to apply to the WCS.

    c                    s  t ||j}t|trz|j _|j }t|jD ]>}|jjd |j|  }|jd | }t	|| || ||< q2| _n| _| _ jd d d  _
t fddt jjD d  _t jjd d  jf jddd  _t jdkst jdkrtdd S )Nr   c                    s    g | ]}t  j| tj qS r   )r   _slices_pixelr"   r#   r   Zipselfr   r   
<listcomp>   s   z.SlicedLowLevelWCS.__init__.<locals>.<listcomp>r   )Zaxisz[Cannot slice WCS: the resulting WCS should have at least one pixel and one world dimension.)r
   pixel_n_dimr   r   _wcs_slices_arraycopyr   _pixel_keepr+   r-   npZnonzeroaxis_correlation_matrixr   _world_keepr   r   )r0   Zwcsr%   Zslices_originalipixelZipixel_origZ
ipixel_newr   r/   r   __init__z   s4    



 zSlicedLowLevelWCS.__init__c                    s   | j dgt| j  }tt}t| jjD ]ȉ  | jv r:q*d|vrLt	 |d< | jj
}| jj|d |   |d | jj   |d | jj   |d | jj   |d    |d t	t fdd	|  | j|d
< q*t	|S )zF
        Information describing the dropped world dimensions.
        r   world_axis_object_classesvalueworld_axis_namesworld_axis_physical_typesworld_axis_unitsworld_axis_object_componentsc                    s   | d   d kS Nr   r   )xr'   Zwao_componentsr   r   <lambda>   r   z<SlicedLowLevelWCS.dropped_world_dimensions.<locals>.<lambda>serialized_classes)_pixel_to_world_values_allr   r6   r   r   r   r3   world_n_dimr9   dictr<   rA   r$   r>   r?   r@   updatefilteritemsrF   )r0   Zworld_coordsZdropped_infoZwao_classesr   rD   r   dropped_world_dimensions   s*    


z*SlicedLowLevelWCS.dropped_world_dimensionsc                 C   s
   t | jS r   )r   r6   r/   r   r   r   r2      s    zSlicedLowLevelWCS.pixel_n_dimc                 C   s
   t | jS r   )r   r9   r/   r   r   r   rH      s    zSlicedLowLevelWCS.world_n_dimc                    s    fdd j D S )Nc                    s   g | ]} j j| qS r   )r3   r?   r   r'   r/   r   r   r1      r   z?SlicedLowLevelWCS.world_axis_physical_types.<locals>.<listcomp>r9   r/   r   r/   r   r?      s    z+SlicedLowLevelWCS.world_axis_physical_typesc                    s    fdd j D S )Nc                    s   g | ]} j j| qS r   )r3   r@   rN   r/   r   r   r1      r   z6SlicedLowLevelWCS.world_axis_units.<locals>.<listcomp>rO   r/   r   r/   r   r@      s    z"SlicedLowLevelWCS.world_axis_unitsc                    s    fdd j D S )Nc                    s   g | ]} j j| qS r   )r3   pixel_axis_namesrN   r/   r   r   r1      r   z6SlicedLowLevelWCS.pixel_axis_names.<locals>.<listcomp>)r6   r/   r   r/   r   rP      s    z"SlicedLowLevelWCS.pixel_axis_namesc                    s    fdd j D S )Nc                    s   g | ]} j j| qS r   )r3   r>   rN   r/   r   r   r1      r   z6SlicedLowLevelWCS.world_axis_names.<locals>.<listcomp>rO   r/   r   r/   r   r>      s    z"SlicedLowLevelWCS.world_axis_namesc                 G   s   t ttj|}g }d}t| jjD ]j}t| j| t	j
rL|| j|  q$|d7 }| j| jd ur||| | j| j  q$|||  q$tj| }| jj| S )Nr,   r   )r   mapr7   
asanyarrayr   r3   r2   r   r-   r"   r#   r$   r(   broadcast_arrayspixel_to_world_values)r0   pixel_arraysZpixel_arrays_newZ	ipix_currZipixr   r   r   rG      s    
z,SlicedLowLevelWCS._pixel_to_world_values_allc                    sV   | j |  t tjr  js  S | jjdkrR fdd| jD  | jdkrR d   S )Nr   c                    s   g | ]} | qS r   r   )r   Ziwworld_arraysr   r   r1      r   z;SlicedLowLevelWCS.pixel_to_world_values.<locals>.<listcomp>r   )rG   r   r7   ndarrayshaper3   rH   r9   )r0   rU   r   rV   r   rT      s    

z'SlicedLowLevelWCS.pixel_to_world_valuesc                    s  t ttj|}g }d}t| jjD ]0}|| jv rJ|d7 }|||  q$|d q$tj	| }t
| jj|  t| jjD ]<}t| j| tr|| j| jd ur| |  | j| j8  < q|t tjrЈ jsЈ S t  fdd| jD }| jdkr
| jjdkr
|d }|S )Nr,   r   g      ?c                 3   s   | ]} | V  qd S r   r   r.   rU   r   r   r   
  r   z:SlicedLowLevelWCS.world_to_pixel_values.<locals>.<genexpr>r   )r   rQ   r7   rR   r   r3   rH   r9   r$   rS   r   world_to_pixel_valuesr2   r   r-   r    r(   rX   rY   r6   )r0   rW   Zworld_arrays_newZiworld_currZiworldr:   Zpixelr   rZ   r   r[      s&    

 z'SlicedLowLevelWCS.world_to_pixel_valuesc                    s    fdd j D S )Nc                    s   g | ]} j j| qS r   )r3   rA   )r   idxr/   r   r   r1     r   zBSlicedLowLevelWCS.world_axis_object_components.<locals>.<listcomp>rO   r/   r   r/   r   rA     s    z.SlicedLowLevelWCS.world_axis_object_componentsc                    s.   dd | j D  t fdd| jj D S )Nc                 S   s   g | ]}|d  qS r   r   r   itemr   r   r   r1     r   z?SlicedLowLevelWCS.world_axis_object_classes.<locals>.<listcomp>c                    s   g | ]}|d   v r|qS r]   r   r^   Z	keys_keepr   r   r1     r   )rA   rI   r3   r<   rL   r/   r   r`   r   r<     s    z+SlicedLowLevelWCS.world_axis_object_classesc                 C   s(   | j jr$td| j jt| j jS d S rB   )r3   array_shaper7   Zbroadcast_tor   r4   rY   r/   r   r   r   ra     s    zSlicedLowLevelWCS.array_shapec                 C   s   | j rt| j d d d S d S )Nr,   )ra   r   r/   r   r   r   pixel_shape  s    zSlicedLowLevelWCS.pixel_shapec                 C   s~   | j jd u rd S g }| jD ]Z}| j| jd u rB|| j j|  q| j j| \}}| j| j}||| || f qt|S r   )r3   pixel_boundsr6   r-   r(   r$   r   )r0   Zboundsr\   ZiminZimaxr(   r   r   r   rc   "  s    
zSlicedLowLevelWCS.pixel_boundsc                 C   s   | j j| j d d | jf S r   )r3   r8   r9   r6   r/   r   r   r   r8   2  s    z)SlicedLowLevelWCS.axis_correlation_matrixN)__name__
__module____qualname____doc__r;   r   rM   propertyr2   rH   r?   r@   rP   r>   rG   rT   r[   rA   r<   ra   rb   rc   r8   r   r   r   r   r   i   s>   "











)r"   collectionsr   Znumpyr7   Zastropy.utilsr   Zastropy.utils.decoratorsr   Zlow_level_apir   baser	   __all__r
   r+   r   r   r   r   r   <module>   s   .,