
    HR-e!O                     2   d Z ddlZddlZ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mZ ddZdd	Zd
 ZddZddZd ZddZddZ G d dej                  Z G d dej                  Z G d dej                  Z G d dej                  ZdS )z
This package contains functions for reading and writing QDP tables that are
not meant to be used directly, but instead are available as readers/writers in
`astropy.table`. See :ref:`astropy:table_io` for more details.
    N)Iterable)Table)AstropyUserWarning   )basiccorec                    d}d}|}|d}d| d}d| d| d| d	}d
| d| d| d}t          j        |t           j                  }|                                 } | sdS |                    |           }	|	t          d|            |	                                                                D ]9\  }
}||
dk    r(dt          |	                    |                     c S |
c S dS )a   Interpret a QDP file line.

    Parameters
    ----------
    line : str
        a single line of the file

    Returns
    -------
    type : str
        Line type: "comment", "command", or "data"

    Examples
    --------
    >>> _line_type("READ SERR 3")
    'command'
    >>> _line_type(" \n    !some gibberish")
    'comment'
    >>> _line_type("   ")
    'comment'
    >>> _line_type(" 21345.45")
    'data,1'
    >>> _line_type(" 21345.45 1.53e-3 1e-3 .04 NO nan")
    'data,6'
    >>> _line_type(" 21345.45,1.53e-3,1e-3,.04,NO,nan", delimiter=',')
    'data,6'
    >>> _line_type(" 21345.45 ! a comment to disturb")
    'data,1'
    >>> _line_type("NO NO NO NO NO")
    'new'
    >>> _line_type("NO,NO,NO,NO,NO", delimiter=',')
    'new'
    >>> _line_type("N O N NOON OON O")
    Traceback (most recent call last):
        ...
    ValueError: Unrecognized QDP line...
    >>> _line_type(" some non-comment gibberish")
    Traceback (most recent call last):
        ...
    ValueError: Unrecognized QDP line...
    z'[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?zREAD [TS]ERR(\s+[0-9]+)+Nz\s+zNO(zNO)+(z|NO|[-+]?nan)(z|NO|[-+]?nan))*)z^\s*((?P<command>z
)|(?P<new>z)|(?P<data>z)?\s*(\!(?P<comment>.*))?\s*$commentzUnrecognized QDP line: datadata,)sep)
recompile
IGNORECASEstripmatch
ValueError	groupdictitemslensplit)line	delimiter_decimal_re_command_rer   _new_re_data_re_type_re_line_type_rer   type_vals               4lib/python3.11/site-packages/astropy/io/ascii/qdp.py
_line_typer$      sB   T =K-K
CSGRKRRsRR[RRRHvKvv7vvxvvvHJx77M::<<D y%%E}9499:::oo''--//  
s;F??:3syyYy7788:::::LLL     c                     fd| D             }d}|D ]H}|                     d          r1t          |dd                   }||}3||k    rt          d          I||fS )a;  Read through the list of QDP file lines and label each line by type.

    Parameters
    ----------
    lines : list
        List containing one file line in each entry

    Returns
    -------
    contents : list
        List containing the type for each line (see `line_type_and_data`)
    ncol : int
        The number of columns in the data lines. Must be the same throughout
        the file

    Examples
    --------
    >>> line0 = "! A comment"
    >>> line1 = "543 12 456.0"
    >>> lines = [line0, line1]
    >>> types, ncol = _get_type_from_list_of_lines(lines)
    >>> types[0]
    'comment'
    >>> types[1]
    'data,3'
    >>> ncol
    3
    >>> lines.append("23")
    >>> _get_type_from_list_of_lines(lines)
    Traceback (most recent call last):
        ...
    ValueError: Inconsistent number of columns
    c                 2    g | ]}t          |           S )r   )r$   ).0r   r   s     r#   
<listcomp>z0_get_type_from_list_of_lines.<locals>.<listcomp>z   s&    EEEtZ	222EEEr%   Nr      zInconsistent number of columns)
startswithintr   )linesr   typescurrent_ncolr!   ncols    `    r#   _get_type_from_list_of_linesr2   X   s    D FEEEuEEEEL C CG$$ 	CuQRRy>>D##%% !ABBB,r%   c                 >   d| v r|                      d          }nt          | t                    rFt          |           5 }d |                                D             }d d d            n# 1 swxY w Y   n't          | t
                    r| }nt          d          |S )N
c                 6    g | ]}|                                 S  )r   )r)   r   s     r#   r*   z(_get_lines_from_file.<locals>.<listcomp>   s     ???dTZZ\\???r%   zinvalid value of qdb_file)r   
isinstancestropen	readlinesr   r   )qdp_filer.   fobjs      r#   _get_lines_from_filer=      s    xt$$	Hc	"	" 6(^^ 	@t??dnn.>.>???E	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@	Hh	'	' 64555Ls   A**A.1A.c                    d t          |          D             }| g x}}n@t          j        |           } |                     dg           }|                     dg           }|Gt	          |          t	          |          dz  z   }|t	          |          z   |k    rt          d          d}t          |          D ]d}|dz   |z
  }	||         d	k    rd
|	 }
|||	dz
           }
|
 ||<   |	|v r|
 d||dz   <   |dz  }D|	|v r|
 d||dz   <   |
 d||dz   <   |dz  }det          j        d |D                       rJ |S )a  Give list of column names from the READ SERR and TERR commands.

    Parameters
    ----------
    err_specs : dict
        ``{'serr': [n0, n1, ...], 'terr': [n2, n3, ...]}``
        Error specifications for symmetric and two-sided errors
    ncols : int
        Number of data columns

    Other Parameters
    ----------------
    names : list of str
        Name of data columns (defaults to ['col1', 'col2', ...]), _not_
        including error columns.

    Returns
    -------
    colnames : list
        List containing the column names. Error columns will have the name
        of the main column plus ``_err`` for symmetric errors, and ``_perr``
        and ``_nerr`` for positive and negative errors respectively

    Examples
    --------
    >>> col_in = ['MJD', 'Rate']
    >>> cols = _interpret_err_lines(None, 2, names=col_in)
    >>> cols[0]
    'MJD'
    >>> err_specs = {'terr': [1], 'serr': [2]}
    >>> ncols = 5
    >>> cols = _interpret_err_lines(err_specs, ncols, names=col_in)
    >>> cols[0]
    'MJD'
    >>> cols[2]
    'MJD_nerr'
    >>> cols[4]
    'Rate_err'
    >>> _interpret_err_lines(err_specs, 6, names=col_in)
    Traceback (most recent call last):
        ...
    ValueError: Inconsistent number of input colnames
    c                     g | ]}d S  r6   )r)   is     r#   r*   z(_interpret_err_lines.<locals>.<listcomp>   s    )))q)))r%   Nserrterr   z%Inconsistent number of input colnamesr   r   rA   col_err_perr_nerrc                     g | ]}|d k    	S r@   r6   r)   cs     r#   r*   z(_interpret_err_lines.<locals>.<listcomp>   s    1111qBw111r%   )rangecopydeepcopypopr   r   npany)	err_specsncolsnamescolnames	serr_cols	terr_colsall_error_colsshiftrB   col_numcolname_roots              r#   _interpret_err_linesr]      s   X *)E%LL)))H ""	II M),,	MM&"--	MM&"--	Y#i..1*<<CJJ&%//DEEEE5\\  a%%-A;"&W 1-L%'i!-333HQUOQJEi!-444HQUO!-444HQUOQJE	   v1111122222Or%   c                    t          |           }t          ||          \  }}g }i }d}d}	d}
d}d}t          ||          D ]\  }}|                                                    d          }|dk    r	|	|dz   z  }	<|dk    r3|dk    r|	}
d}	|i k    rt          j        dt                     ||dz   z  }u|                    d	          rz|i k    r|dk    r|                                	                    d          D ]k}|                                	                                }t          |          d
k     r<d |dd         D             ||d                                         <   l|t          |||          }|g }g }|	                    |          D ]}|                                dk    r%|                    t          j        j                   ?	 |                    t%          |                     c# t&          $ r% |                    t)          |                     Y w xY w|                    |           |dk    r|t+          ||          }|
                                	                    d          |j        d<   |	                                	                    d          |j        d<   d}	|                    |           d}|t+          ||          }|
                                	                    d          |j        d<   |	                                	                    d          |j        d<   |                    |           |S )a  Get all tables from a QDP file.

    Parameters
    ----------
    qdp_file : str
        Input QDP file name

    Other Parameters
    ----------------
    input_colnames : list of str
        Name of data columns (defaults to ['col1', 'col2', ...]), _not_
        including error columns.
    delimiter : str
        Delimiter for the values in the table.

    Returns
    -------
    list of `~astropy.table.Table`
        List containing all the tables present inside the QDP file
    r(   NrA   !r   r4   commandz9This file contains multiple command blocks. Please verifyr      c                 ,    g | ]}t          |          S r6   )r-   rK   s     r#   r*   z-_get_tables_from_qdp_file.<locals>.<listcomp>,  s    4Q4Q4QSVV4Q4Q4Qr%   rE   r   )rU   NOnew)rU   rowsinitial_commentscomments)r=   r2   zipr   lstripwarningswarnr   r,   r   r   lowerr]   upperappendrQ   mamaskedr-   r   floatr   meta)r;   input_colnamesr   r.   contentsr1   
table_listrS   rV   comment_textrf   command_linescurrent_rowsr   datatypecliner`   valuesv	new_tables                       r#   _get_tables_from_qdp_filer~      s   * !**E1%9MMMNHdJIHLMLeX.. > >hzz||""3''y  D4K'Ly   ""#/ !BO&   TD[(Mv&& 	B=B#6#6*002288>> R RE#kkmm1133G7||a'' 4Q4QWQRR[4Q4Q4QIgaj..0011/	4~VVV#!FZZ	** 0 07799$$MM"%,////0c!ff----% 0 0 0eAhh/////0'''u'!|DDD	5E5K5K5M5M5S5S6 6	12 .:-?-?-A-A-G-G-M-M	z*!!!),,,#   |<<<	-=-C-C-E-E-K-KD-Q-Q	)*%1%7%7%9%9%?%?%E%E	z")$$$s   "G>>,H-,H-c                    d}g }g }t          |           D ]\  }}|                    d          r|                    ||z
             |dz  }8|                    d          ra|                    ||z
             t          |           |dz   k    s| |dz                                d          st	          d          |dz  }|                    d          r-| |dz
                               d          st	          d          ||fS )	a-  Get which column names are error columns.

    Examples
    --------
    >>> colnames = ['a', 'a_err', 'b', 'b_perr', 'b_nerr']
    >>> serr, terr = _understand_err_col(colnames)
    >>> np.allclose(serr, [1])
    True
    >>> np.allclose(terr, [2])
    True
    >>> serr, terr = _understand_err_col(['a', 'a_nerr'])
    Traceback (most recent call last):
    ...
    ValueError: Missing positive error...
    >>> serr, terr = _understand_err_col(['a', 'a_perr'])
    Traceback (most recent call last):
    ...
    ValueError: Missing negative error...
    r   rG   r   rH   rI   zMissing negative errorrE   zMissing positive error)	enumerateendswithrn   r   r   )rV   rZ   rC   rD   rB   rF   s         r#   _understand_err_colr   Y  s$   ( EDDH%% 7 73<< 	7 KKE	"""QJEE\\'"" 	7KKE	"""8}}A%%Xa!e_-E-Eg-N-N% !9:::QJEE\\'"" 	78AE?+C+CG+L+L 	75666:r%   c                 r    |t          j        dt                     d}t          | ||          }||         S )a  Read a table from a QDP file.

    Parameters
    ----------
    qdp_file : str
        Input QDP file name

    Other Parameters
    ----------------
    names : list of str
        Name of data columns (defaults to ['col1', 'col2', ...]), _not_
        including error columns.

    table_id : int, default 0
        Number of the table to be read from the QDP file. This is useful
        when multiple tables present in the file. By default, the first is read.

    delimiter : str
        Any delimiter accepted by the `sep` argument of str.split()

    Returns
    -------
    tables : list of `~astropy.table.Table`
        List containing all the tables present inside the QDP file
    Nz9table_id not specified. Reading the first available tabler   )rs   r   )rj   rk   r   r~   )r;   rU   table_idr   tabless        r#   _read_table_qdpr     sS    4 G	
 	
 	
 &)  F (r%   c                 ~   ddl }|                                }d| j        v r`| j        d         g k    rO| j        d         D ]A}|                                }|                    d          sd|z   }t          ||           B|t          | j                  \  }}n,|                    dg           }|                    dg           }|g k    r3d	                    d	 |D                       }t          d
| |           |g k    r3d	                    d |D                       }t          d| |           d| j        v r`| j        d         g k    rO| j        d         D ]A}|                                }|                    d          sd|z   }t          ||           B| j        }	t          dd	                    |	          z   |           | D ]s}
g }|
D ]H}t          j                            |          st          |          }nd}|                    |           It          d	                    |          |           t|                                }|                                 |9t#          |d          5 }t          ||           ddd           n# 1 swxY w Y   |                    d          S )a  Write a table to a QDP file.

    Parameters
    ----------
    table : :class:`~astropy.table.Table`
        Input table to be written
    filename : str
        Output QDP file name

    Other Parameters
    ----------------
    err_specs : dict
        Dictionary of the format {'serr': [1], 'terr': [2, 3]}, specifying
        which columns have symmetric and two-sided errors (see QDP format
        specification)
    r   Nrf   r_   )filerC   rD    c                 ,    g | ]}t          |          S r6   r8   r)   r"   s     r#   r*   z$_write_table_qdp.<locals>.<listcomp>      ===Cs3xx===r%   z
READ SERR c                 ,    g | ]}t          |          S r6   r   r   s     r#   r*   z$_write_table_qdp.<locals>.<listcomp>  r   r%   z
READ TERR rg   rc   wr4   )ioStringIOrr   r   r,   printr   rV   rP   joinrQ   ro   	is_maskedr8   rn   getvaluecloser9   r   )tablefilenamerS   r   r<   r   rW   rX   
col_stringrV   rowr{   r"   repfull_strings                  r#   _write_table_qdpr     s(   " III;;==DUZ''EJ7I,Jb,P,PJ12 	# 	#D::<<D??3'' "Tz$T"""""25>BB	99MM&"--	MM&"--	BXX==9===>>
':''d3333BXX==9===>>
':''d3333UZEJz$:b$@$@Jz* 	# 	#D::<<D??3'' "Tz$T"""""~H	#""
".... + + 	 	C5??3'' #hhMM#chhvT*****--//KJJLLL(C   	*D+D))))	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* T"""s   JJ#&J#c                       e Zd ZdZdZdS )QDPSplitterz(
    Split on space for QDP tables.
    r   N)__name__
__module____qualname____doc__r   r6   r%   r#   r   r     s          IIIr%   r   c                       e Zd ZdZeZdZdZdS )	QDPHeaderzK
    Header that uses the :class:`astropy.io.ascii.basic.QDPSplitter`.
    r_   N)r   r   r   r   r   splitter_classr   write_commentr6   r%   r#   r   r     s)          !NGMMMr%   r   c                   2    e Zd ZdZeZej        dfgZdZ	dZ
dS )QDPDatazI
    Data that uses the :class:`astropy.io.ascii.basic.CsvSplitter`.
    rc   r_   N)r   r   r   r   r   r   r   rp   fill_valuesr   r   r6   r%   r#   r   r      s8          !NK&'KGMMMr%   r   c                   H     e Zd ZdZdZdZdZdZeZ	e
Zd
 fd	Zd Zd	 Z xZS )QDPa  Quick and Dandy Plot table.

    Example::

        ! Initial comment line 1
        ! Initial comment line 2
        READ TERR 1
        READ SERR 3
        ! Table 0 comment
        !a a(pos) a(neg) b be c d
        53000.5   0.25  -0.5   1  1.5  3.5 2
        54000.5   1.25  -1.5   2  2.5  4.5 3
        NO NO NO NO NO
        ! Table 1 comment
        !a a(pos) a(neg) b be c d
        54000.5   2.25  -2.5   NO  3.5  5.5 5
        55000.5   3.25  -3.5   4  4.5  6.5 nan

    The input table above contains some initial comments, the error commands,
    then two tables.
    This file format can contain multiple tables, separated by a line full
    of ``NO``s. Comments are exclamation marks, and missing values are single
    ``NO`` entries. The delimiter is usually whitespace, more rarely a comma.
    The QDP format differentiates between data and error columns. The table
    above has commands::

        READ TERR 1
        READ SERR 3

    which mean that after data column 1 there will be two error columns
    containing its positive and engative error bars, then data column 2 without
    error bars, then column 3, then a column with the symmetric error of column
    3, then the remaining data columns.

    As explained below, table headers are highly inconsistent. Possible
    comments containing column names will be ignored and columns will be called
    ``col1``, ``col2``, etc. unless the user specifies their names with the
    ``names=`` keyword argument,
    When passing column names, pass **only the names of the data columns, not
    the error columns.**
    Error information will be encoded in the names of the table columns.
    (e.g. ``a_perr`` and ``a_nerr`` for the positive and negative error of
    column ``a``, ``b_err`` the symmetric error of column ``b``.)

    When writing tables to this format, users can pass an ``err_specs`` keyword
    passing a dictionary ``{'serr': [3], 'terr': [1, 2]}``, meaning that data
    columns 1 and two will have two additional columns each with their positive
    and negative errors, and data column 3 will have an additional column with
    a symmetric error (just like the ``READ SERR`` and ``READ TERR`` commands
    above)

    Headers are just comments, and tables distributed by various missions
    can differ greatly in their use of conventions. For example, light curves
    distributed by the Swift-Gehrels mission have an extra space in one header
    entry that makes the number of labels inconsistent with the number of cols.
    For this reason, we ignore the comments that might encode the column names
    and leave the name specification to the user.

    Example::

        >               Extra space
        >                   |
        >                   v
        >!     MJD       Err (pos)       Err(neg)        Rate            Error
        >53000.123456   2.378e-05     -2.378472e-05     NO             0.212439

    These readers and writer classes will strive to understand which of the
    comments belong to all the tables, and which ones to each single table.
    General comments will be stored in the ``initial_comments`` meta of each
    table. The comments of each table will be stored in the ``comments`` meta.

    Example::

        t = Table.read(example_qdp, format='ascii.qdp', table_id=1, names=['a', 'b', 'c', 'd'])

    reads the second table (``table_id=1``) in file ``example.qdp`` containing
    the table above. There are four column names but seven data columns, why?
    Because the ``READ SERR`` and ``READ TERR`` commands say that there are
    three error columns.
    ``t.meta['initial_comments']`` will contain the initial two comment lines
    in the file, while ``t.meta['comments']`` will contain ``Table 1 comment``

    The table can be written to another file, preserving the same information,
    as::

        t.write(test_file, err_specs={'terr': [1], 'serr': [3]})

    Note how the ``terr`` and ``serr`` commands are passed to the writer.

    qdpTz.qdpzQuick and Dandy PlotterNc                     t                                                       || _        || _        || _        || _        d S N)super__init__r   rU   rS   r   )selfr   rU   rS   r   	__class__s        r#   r   zQDP.__init__o  s9     
"r%   c                     | j                             |d          | _        t          | j        | j        | j        | j                  S )Nr4   )newline)r   rU   r   )inputter	get_linesr.   r   r   rU   r   )r   r   s     r#   readzQDP.readv  sI    ],,UD,AA
J]*n	
 
 
 	
r%   c                 \    |                      |           t          || j                  }|S )N)rS   )_check_multidim_tabler   rS   )r   r   r.   s      r#   writez	QDP.write  s/    ""5))) $.AAAr%   )NNNN)r   r   r   r   _format_name_io_registry_can_write_io_registry_suffix_descriptionr   header_classr   
data_classr   r   r   __classcell__)r   s   @r#   r   r     s        Y Yv L! ,LLJ     
 
 
      r%   r   r   )NN)NNN)r   rN   r   rj   collections.abcr   numpyrQ   astropy.tabler   astropy.utils.exceptionsr   rA   r   r   r$   r2   r=   r]   r~   r   r   r   DefaultSplitterr   CommentedHeaderHeaderr   	BasicDatar   Basicr   r6   r%   r#   <module>r      s   
  				  $ $ $ $ $ $           7 7 7 7 7 7        A A A AH, , , ,^  U U U Upi i i iX% % %P% % % %PB# B# B# B#J    $&       +       eo   w w w w w%+ w w w w wr%   