B
    {dc              	   @   s8  d Z ddlmZ ddlZddlZedZddlZddlm	  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
lmZ ddlmZ dddgdddgddddddgdZeejfZeddG dd deZdd Zd/ddZd0d!d"Z ed#ddd1d$d%Z!d2d'd(Z"d3d)d*Z#d4d+d,Z$d-d. Z%dS )5zCProvides input and output functions for Healpix maps, alm, and cl.
    )divisionNhealpy)deprecated_renamed_argument   )	pixelfunc)Alm)UNSEEN)cookbook)
deprecatedTEMPERATUREZQ_POLARISATIONZU_POLARISATIONZIIZIQZIUZQQZQUZUU)r            z1.15.0)Zsincec               @   s   e Zd ZdS )HealpixFitsWarningN)__name__
__module____qualname__ r   r   \/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/healpy/fitsfunc.pyr   2   s   r   c                sr   d}t | trt| } d}t| dd t fddtt j	D }|rV| 
  t|dkrj|d S |S dS )	zReads Cl from a healpix file, as IDL fits2cl.

    Parameters
    ----------
    filename : str or HDUList or HDU or pathlib.Path instance
      the fits file name

    Returns
    -------
    cl : array
      the cl array
    FTr   )hduc                s   g | ]} j |qS r   )datafield).0n)fits_hdur   r   
<listcomp>I   s    zread_cl.<locals>.<listcomp>r   N)
isinstanceallowed_pathspfopen_get_hdunparrayrangelencolumnsclose)filenameopened_fileclr   )r   r   read_cl7   s    

"r*   Fc                s   |dkr$t |tjr|jn|d j}t| ddddddg}tt|d	krt fd
dt|dt| |D }n2tt|dkrtj	dd  |dg}nt
dtj|}d|jd< |jt| |d dS )aE  Writes Cl into a healpix file, as IDL cl2fits.

    Parameters
    ----------
    filename : str
      the fits file name
    cl : array
      the cl array to write to file
    dtype : np.dtype (optional)
      The datatype in which the columns will be stored. If not supplied,
      the dtype of the input cl will be used. This changed in `healpy` 1.15.0,
      in previous versions, cl by default were saved in `float64`.
    overwrite : bool, optional
      If True, existing file is silently overwritten. Otherwise trying to write
      an existing file raises an OSError.
    Nr   r   ZGRADIENTZCURLzG-TzC-TzC-Gr   c                s$   g | ]\}}t j|d   |dqS )z%s)nameformatr"   )r   Column)r   Zcolumn_nameZ	column_cl)
fitsformatr   r   r   k   s   zwrite_cl.<locals>.<listcomp>r   z%s)r+   r,   r"   z6write_cl: Expected one or more vectors of equal lengthr   ZCREATOR)	overwrite)r   r!   Zndarraydtype	getformatr$   shapezipr   r-   RuntimeErrorBinTableHDUfrom_columnsheaderwritetostr)r'   r)   r0   r/   column_namescolstbhdur   )r.   r   write_clR   s    

r=   Tr   c          
      s^  t |dstdt|}t|dkr0|g}|dkrXdd |D }tdt|  y$g }x|D ]}|t	| qdW W n& tk
r   t	|gt
| }Y nX |dkrtt
|dd td	t
|d	 D }nt
|t
|kstd
|dkst|tr|gt
| }t
ttt
|d	ks2tdtt
|d }|dk rVtdg }|rd}t|d  t d }t
|dkrtd fdd|D }t	t|  }|dkrd}|tjd||dd xt||||D ]t\}}}}t
|dkrH|rHt|}|tj|d| ||jd d|d n|tj|d| ||d qW tj |}d|j!d< |rd}nd}|df|j!d< |r|df|j!d< d|j!d< |d f|j!d!< |sd"|j!d#< t"|d	 d$f|j!d%< |rd&nd'd(f|j!d)< |rd*nd+d,f|j!d-< x$|	D ]}|d	d |j!|d < q(W |j#t| |
d. dS )/a	  Writes a healpix map into a healpix FITS file.

    .. warning::
    Starting from healpy 1.15.0, if you do not specify `dtype`,
    the map will be written to disk with the same precision it is stored in memory.
    Previously, by default `healpy` wrote maps in `float32`.
    To reproduce the same behaviour of `healpy` 1.14.0 and below, set `dtype=np.float32`.

    Parameters
    ----------
    filename : str
      the fits file name
    m : array or sequence of 3 arrays
      the map to write. Possibly a sequence of 3 maps of same size.
      They will be considered as I, Q, U maps.
      Supports masked maps, see the `ma` function.
    nest : bool, optional
      If True, ordering scheme is assumed to be NESTED, otherwise, RING. Default: RING.
      The map ordering is not modified by this function, the input map array
      should already be in the desired ordering (run `ud_grade` beforehand).
    fits_IDL : bool, optional
      If True, reshapes columns in rows of 1024, otherwise all the data will
      go in one column. Default: True
    coord : str
      The coordinate system, typically 'E' for Ecliptic, 'G' for Galactic or 'C' for
      Celestial (equatorial)
    partial : bool, optional
      If True, fits file is written as a partial-sky file with explicit indexing.
      Otherwise, implicit indexing is used.  Default: False.
    column_names : str or list
      Column name or list of column names, if None here the default column names based on
      the number of columns:
      1 : "TEMPERATURE",
      2 : ["Q_POLARISATION", "U_POLARISATION"],
      3 : ["TEMPERATURE", "Q_POLARISATION", "U_POLARISATION"],
      6 : ["II", "IQ", "IU", "QQ", "QU", "UU"]
      COLUMN_1, COLUMN_2... otherwise (FITS is 1-based)
    column_units : str or list
      Units for each column, or same units for all columns.
    extra_header : list
      Extra records to add to FITS header.
    dtype: np.dtype or list of np.dtypes, optional
      The datatype in which the columns will be stored. Will be converted
      internally from the numpy datatype to the fits convention. If a list,
      the length must correspond to the number of map arrays.
      Default: use the data type of the input array(s)
      .. note::
      this changed in 1.15.0, previous versions saved in float32
      by default
    overwrite : bool, optional
      If True, existing file is silently overwritten. Otherwise trying to write
      an existing file raises an OSError (IOError for Python 2).
    __len__zThe map must be a sequencer   Nc             S   s   g | ]
}|j qS r   )r0   )r   xr   r   r   r      s    zwrite_map.<locals>.<listcomp>z"setting the output map dtype to %sc             S   s   g | ]}d | qS )z	COLUMN_%dr   )r   r   r   r   r   r      s    r   z%Length column_names != number of mapszMaps must have same lengthz+Invalid healpix map : wrong number of pixelFz'Invalid healpix map : empty partial mapc                s   g | ]}|  qS r   r   )r   mm)maskr   r   r      s    IZPIXEL)r+   r,   r"   uniti   z1024%sz%s)ZHEALPIXzHEALPIX pixelisationZPIXTYPENESTEDRINGz,Pixel ordering scheme, either RING or NESTEDORDERINGz,Ecliptic, Galactic or Celestial (equatorial)ZCOORDSYS)Zxtensionz#name of this binary table extensionZEXTNAMEzResolution parameter of HEALPIXNSIDE)r   zFirst pixel # (0 based)ZFIRSTPIXzLast pixel # (0 based)ZLASTPIXEXPLICITIMPLICITzIndexing: IMPLICIT or EXPLICITINDXSCHMPARTIALFULLSKYz'Sky coverage, either FULLSKY or PARTIALOBJECT)r/   )$hasattr	TypeErrorr   Zma_to_arrayZmaptypelogwarningr9   appendr1   r$   standard_column_namesgetr#   AssertionErrorr   setmap
npix2nside
ValueErrorZ	mask_goodr!   whereZmin_scalar_typemaxr   r-   r3   ZasarrayZreshapesizer5   r6   r7   
nside2npixr8   )r'   mnestr0   Zfits_IDLZcoordpartialr:   Zcolumn_unitsZextra_headerr/   r.   
curr_dtypensider;   pixffZcncur@   Zcurr_fitsformatZmm2r<   orderingargsr   )rA   r   	write_map|   s    B


& 






rh   verbosec	                sV  d}	t | tr tj| |d} d}	t| ||d}
|
jd}|dkrftd |
j	
d}t|j}nt|}td	| t|std
|
jdd }|dkr|rdpd}td| td| t|}g }t|
jdd }|dkr|dkrd}n|dkrd}|
jdd }|dkrt|dkrT|dkrNtdd}n |dkrt|dkrptdd}|dkr|rdpd}td| td| |dkrtt|
j	jd|  }t|dst |ts|f}|r|tdd |D }y|
j	
djtdd }W n^ tjk
rz } z<t| td |
d  |
j	
djtdd }W dd}~X Y nX yt t|kstd!W n$ tk
r    gt|  Y nX xt | D ]\}}y:|dkr|
j	
| }n|
j	
|j|dd }W nz tjk
r } zXt| td |
d }|dkrb|
j	
| }n|
j	
|j|dd }W dd}~X Y nX |rt!t"j#||j$d" }|||< |}t%|jr|dkr||jkrtd#&|||j td
|dk	rz|r>|dkr>t'|t"j(|jt"j)d"}|| }td$ n<|sz|dkrzt*|t"j(|jt"j)d"}|| }td% yt!|t+|< W n t,k
r   Y nX |-| qW |rg }x&|
j. D ]\}}|-||f qW |	r| /  t|dkr|r|d |fS |d S n4t0 fd&d D r@t"1|}|rN||fS |S dS )'a
  Read a healpix map from a fits file.  Partial-sky files,
    if properly identified, are expanded to full size and filled with UNSEEN.

    .. warning::
    Starting from healpy 1.15.0, if you do not specify `dtype`,
    the map will be read in memory with the same precision it is stored on disk.
    Previously, by default `healpy` wrote maps in `float32` and then upcast to
    `float64` when reading to memory. To reproduce the same behaviour of `healpy`
    1.14.0 and below, set `dtype=np.float64` in `read_map`.

    Parameters
    ----------
    filename : str or HDU or HDUList or pathlib.Path instance
      the fits file name
    field : int or tuple of int, or None, optional
      The column to read. Default: 0.
      By convention 0 is temperature, 1 is Q, 2 is U.
      Field can be a tuple to read multiple columns (0,1,2)
      If the fits file is a partial-sky file, field=0 corresponds to the
      first column after the pixel index column.
      If None, all columns are read in.
    dtype : data type or list of data types, optional
      Force the conversion to some type. Passing a list allows different
      types for each field. In that case, the length of the list must
      correspond to the length of the field parameter.
      If None, keep the dtype of the input FITS file
      Default: Preserve the data types in the file
    nest : bool, optional
      If True return the map in NEST ordering, otherwise in RING ordering;
      use fits keyword ORDERING to decide whether conversion is needed or not
      If None, no conversion is performed.
    partial : bool, optional
      If True, fits file is assumed to be a partial-sky file with explicit indexing,
      if the indexing scheme cannot be determined from the header.
      If False, implicit indexing is assumed.  Default: False.
      A partial sky file is one in which OBJECT=PARTIAL and INDXSCHM=EXPLICIT,
      and the first column is then assumed to contain pixel indices.
      A full sky file is one in which OBJECT=FULLSKY and INDXSCHM=IMPLICIT.
      At least one of these keywords must be set for the indexing
      scheme to be properly identified.
    hdu : int, optional
      the header number to look at (start at 0)
    h : bool, optional
      If True, return also the header. Default: False.
    verbose : bool, deprecated
      It has no effect
    memmap : bool, optional
      Argument passed to astropy.io.fits.open, if True, the map is not read into memory,
      but only the required pixels are read when needed. Default: False.

    Returns
    -------
    m | (m0, m1, ...) [, header] : array or a tuple of arrays, optionally with header appended
      The map(s) read from the file, and the header if *h* is True.
    F)memmapT)r   rj   rG   Nz6No NSIDE in the header file : will use length of arrayr   z
NSIDE = %dzWrong nside parameter.rF   ZUNDEFrD   rE   z.No ORDERING keyword in header file : assume %szORDERING = %s in fits filerM   rK   rL   rJ   rH   zIncompatible INDXSCHM keywordrI   z-No INDXSCHM keyword in header file: assume %szINDXSCHM = %sr   r>   c             s   s$   | ]}t |tr|n|d  V  qdS )r   N)r   r9   )r   fr   r   r   	<genexpr>  s    zread_map.<locals>.<genexpr>)copyz&Trying to fix a badly formatted headerZfixz:The number of dtypes are not equal to the number of fields)r0   z#nside={0:d}, sz={1:d}, m.size={2:d}zOrdering converted to NESTzOrdering converted to RINGc             3   s   | ]}| d  kV  qdS )r   Nr   )r   dt)r0   r   r   rl     s    )2r   r   r   r   r    r7   rT   rP   infor   r   r   rX   r\   intZ	isnsideokrY   stripr]   r9   r#   r$   r%   rN   tupleastypeZravelZVerifyErrorrQ   verifyrU   rO   r3   r   r!   Zonesr0   Zisnpixokr,   Z	nest2ringZarangeint32Z	ring2nestZmask_badOverflowErrorrR   itemsr&   allr"   )r'   r   r0   r_   r`   r   hri   rj   r(   r   rb   rc   rf   szretobjZschmerd   ra   r^   Zmnewidxr7   keyvaluer   )r0   r   read_map,  s    D
















,





,$



r   c             C   s  t |s|g}tjt|d |d}|dkr@||kr@tdn|dkrL|}|dkrX|}|dkrd|}||krp|}|dkr|d jj}t|\}}	t	
||k|	|k }
||
 }|	|
 }	tj|||	d}|d | |	 d }t }x|D ]}t	jt|d	d
|fd|fgd}||d< |j| |d
< |j| |d< tjdtt	jd|d d}tjd
t|d|d
 d}tjdt|d|d d}tj|||g}|| qW |jt| |d dS )a  Write alms to a fits file.

    In the fits file the alms are written
    with explicit index scheme, index = l*l + l + m +1, possibly out of order.
    By default write_alm makes a table with the same precision as the alms.
    If specified, the lmax and mmax parameters truncate the input data to
    include only alms for which l <= lmax and m <= mmax.

    Parameters
    ----------
    filename : str
      The filename of the output fits file
    alms : array, complex or list of arrays
      A complex ndarray holding the alms, index = m*(2*lmax+1-m)/2+l, see Alm.getidx
    lmax : int, optional
      The maximum l in the output file
    mmax : int, optional
      The maximum m in the output file
    out_dtype : data type, optional
      data type in the output file (must be a numpy dtype). Default: *alms*.real.dtype
    mmax_in : int, optional
      maximum m in the input array
    r   )mmaxr   zToo big lmax in parameterN)lr^   r   r   )indexirealimag)r0   r   z	l*l+l+m+1)r+   r,   rC   r"   unknown)r/   )cbZis_seq_of_seqr   Zgetlmaxr$   rY   r   r0   Zgetlmr!   rZ   getidxr   HDUListemptyr   r-   r1   ru   r5   r6   rR   r8   r9   )r'   almsZ	out_dtypelmaxr   Zmmax_inr/   Zl2maxr   r^   r~   Zidx_in_originalr   hdulistalmZout_dataZcindexZcrealZcimagr<   r   r   r   	write_alm  s\    


r   c                sZ  g }d}d}d}t  tr(t  d}xt|D ]܉ fddtdD \}}}	tt|d 	t
}
||
d  |
 d }|d	k  rtd
|
 }| }|dkr|}|}n"||ks||krtd ||d }t||
|}||j|< |	|j|< || q4W |r"   t|dkr:|d	 }n
t|}|rR||fS |S dS )a  Read alm from a fits file.

    In the fits file, the alm are written
    with explicit index scheme, index = l**2+l+m+1, while healpix cxx
    uses index = m*(2*lmax+1-m)/2+l. The conversion is done in this
    function.

    Parameters
    ----------
    filename : str or HDUList or HDU or pathlib.Path instance
      The name of the fits file to read
    hdu : int, or tuple of int, optional
      The header to read. Start at 0. Default: hdu=1
    return_mmax : bool, optional
      If true, both the alms and mmax is returned in a tuple. Default: return_mmax=False

    Returns
    -------
    alms[, mmax] : complex array or tuple of a complex array and an int
      The alms read from the file and optionally mmax read from the file
    NFTc                s    g | ]}t  d j|qS ))r   )r    r   r   )r   r   )r'   rC   r   r   r   q  s    zread_alm.<locals>.<listcomp>r   r   r   r   zNegative m value encountered !z?read_alm: harmonic expansion order in {} HDUs {} does not matchy                )r   r   r   r   r!   Z
atleast_1dr#   floorsqrtrs   rp   anyrY   r[   r4   r,   r   r   r   r   rR   r&   r$   r"   )r'   r   Zreturn_mmaxr   ZlmaxtotZmmaxtotr(   r~   ZalmrZalmir   r^   r   r   r   r   r   )r'   rC   r   read_almQ  sF    





r   c             C   s   t | tr$tj| |d}t||dS t | tjrbt |trX|t| krXtdt|  q| | }n,t | tj	tj
tjtjtjfr| }ntd|S )a  
    Return an HDU from a FITS file

    Parameters
    ----------
    input_data : str or HDUList or HDU instance
        The input FITS file, either as a filename, HDU list, or HDU instance.

    Returns
    -------
    fits_hdu : HDU
        The extracted HDU
    )rj   )r   zAvailable hdu in [0-%d]z^First argument should be a input_data (str or pathlib.Path), HDUList instance, or HDU instance)r   r   r   r   r    r   rp   r$   rY   Z
PrimaryHDUZImageHDUr5   ZTableHDUZ	GroupsHDUrO   )Z
input_datar   rj   r   r   r   r   r   r      s    

r    c             C   sF  t t jdt t jdt t jdt t jdt t jdt t jdt t jdt t j	dt t j
d	i	}y| |kr||  S W n   Y nX y t | |kr|t |  S W n   Y nX y(t t| |kr|t t|  S W n   Y nX y2t t| d
 |kr&|t t| d
  S W n   Y nX y| tkrFdS W n   Y nX yt| tkrrdt|  S W n   Y nX y0t| d
 tkrtdd | D }d| S W n   Y nX y&t | j|kr|t | j S W n   Y nX y.t | d
 j|kr |t | d
 j S W n   Y nX tdt| dS )a'  Get the FITS convention format string of data type t.

    Parameters
    ----------
    t : data type
      The data type for which the FITS type is requested

    Returns
    -------
    fits_type : str or None
      The FITS string code describing the data type, or None if unknown type.
    LBrB   JKEDCMr   AzA%dc             s   s   | ]}t |V  qd S )N)r$   )r   sr   r   r   rl     s    zgetformat.<locals>.<genexpr>zthealpy could not understand the equivalent FITS datatype of {}, please open an issue on the healpy Github repositoryN)r!   r0   Zbool_Zuint8Zint16ru   Zint64Zfloat32Zfloat64Z	complex64Z
complex128typer9   r$   r[   rY   r,   )tconvr   r   r   r   r1     st    
r1   )NF)	FNTNFNNr   F)r   NFFr   FTF)Nr   r   r   F)r   F)NN)&__doc__
__future__r   syslogging	getLoggerrP   pathlibZastropy.io.fitsioZfitsr   numpyr!   Zastropy.utils.decoratorsr    r   Zsphtfuncr   r   r	   r   r
   rS   r9   Pathr   Warningr   r*   r=   rh   r   r   r   r    r1   r   r   r   r   <module>   s\   


-        
 &
        B
Z
D
$