B
    dBB                @   s:  d dl mZmZmZmZmZ ddlZddlmZm	Z	 ddl
mZ ddlZddlmZ ddlZddlZddlZddlZddlmZ ddlmZ dd	lmZmZ dd
lmZmZ ddlmZ ddlm Z  ddl!m"Z"m#Z# ddl$m%Z%m&Z&m'Z' ddl(m)Z) ddl*m+Z+ d dl,m-Z- d dl.m/Z/ d dl0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7 d dl8m9Z9 d dl:m;Z; d dl<m=Z= d dl m>Z>m?Z?m@Z@ d dlAmBZBmCZC d dlDmEZE d dl,mFZF dZGddddd gZHd!d"giZId#ZJd$ZKG d%d& d&eLZMd'd( ZNd)d* ZOd+d, ZPG d-d. d.eZQG d/d0 d0e#ZRG d1d2 d2eRZSG d3d4 d4ZTG d5d6 d6eTZUdS )7   )SlicedIndexTableIndicesTableLoc	TableILocTableLocIndices    N)OrderedDictdefaultdict)Mapping)deepcopy)ma)log)QuantityQuantityInfo)
isiterableShapedLikeNDArray)color_print)AstropyUserWarning)MetaDataMetaAttribute)BaseColumnInfo	MixinInfoDataInfo)
format_doc)UnifiedReadWriteMethod)groups)TableFormatter)
BaseColumnColumnMaskedColumn_auto_names
FalseArraycol_copy_convert_sequence_data_to_array)Row)fix_column_name)	TableInfo)Index_IndexModeContext	get_index)	TableRead
TableWrite)NdarrayMixin)confa.  
This string has informal notes concerning Table implementation for developers.

Things to remember:

- Table has customizable attributes ColumnClass, Column, MaskedColumn.
  Table.Column is normally just column.Column (same w/ MaskedColumn)
  but in theory they can be different.  Table.ColumnClass is the default
  class used to create new non-mixin columns, and this is a function of
  the Table.masked attribute.  Column creation / manipulation in a Table
  needs to respect these.

- Column objects that get inserted into the Table.columns attribute must
  have the info.parent_table attribute set correctly.  Beware just dropping
  an object into the columns dict since an existing column may
  be part of another Table and have parent_table set to point at that
  table.  Dropping that column into `columns` of this Table will cause
  a problem for the old one so the column object needs to be copied (but
  not necessarily the data).

  Currently replace_column is always making a copy of both object and
  data if parent_table is set.  This could be improved but requires a
  generic way to copy a mixin object but not the data.

- Be aware of column objects that have indices set.

- `cls.ColumnClass` is a property that effectively uses the `masked` attribute
  to choose either `cls.Column` or `cls.MaskedColumn`.
z
Table.readzTable.writezTable._readz#Table.convert_bytestring_to_unicodez#Table.convert_unicode_to_bytestringz*pandaszpandas>=1.1ay  
    {__doc__}

    Parameters
    ----------
    max_lines : int or None
        Maximum number of lines in table output.

    max_width : int or None
        Maximum character width of output.

    show_name : bool
        Include a header row for column names. Default is True.

    show_unit : bool
        Include a header row for unit.  Default is to show a row
        for units only if one or more columns has a defined value
        for the unit.

    show_dtype : bool
        Include a header row for column dtypes. Default is True.

    align : str or list or tuple or None
        Left/right alignment of columns. Default is right (None) for all
        columns. Other allowed values are '>', '<', '^', and '0=' for
        right, left, centered, and 0-padded, respectively. A list of
        strings can be provided for alignment of tables with multiple
        columns.
    aZ  
    {__doc__}

    Parameters
    ----------
    max_lines : int or None
        Maximum number of rows to output

    max_width : int or None
        Maximum character width of output

    show_name : bool
        Include a header row for column names. Default is True.

    show_unit : bool
        Include a header row for unit.  Default is to show a row
        for units only if one or more columns has a defined value
        for the unit.

    show_dtype : bool
        Include a header row for column dtypes. Default is True.

    html : bool
        Format the output as an HTML table. Default is False.

    tableid : str or None
        An ID tag for the table; only used if html is set.  Default is
        "table{id}", where id is the unique integer id of the table object,
        id(self)

    align : str or list or tuple or None
        Left/right alignment of columns. Default is right (None) for all
        columns. Other allowed values are '>', '<', '^', and '0=' for
        right, left, centered, and 0-padded, respectively. A list of
        strings can be provided for alignment of tables with multiple
        columns.

    tableclass : str or list of str or None
        CSS classes for the table; only used if html is set.  Default is
        None.

    Returns
    -------
    lines : list
        Formatted table as a list of strings.
    c               @   s   e Zd ZdZdS )TableReplaceWarninga	  
    Warning class for cases when a table column is replaced via the
    Table.__setitem__ syntax e.g. t['a'] = val.

    This does not inherit from AstropyWarning because we want to use
    stacklevel=3 to show the user where the issue occurred in their code.
    N)__name__
__module____qualname____doc__ r3   r3   `/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/astropy/table/table.pyr.      s   r.   c             C   sB   | j jdkrdn| j j}t| dr0| jdd nd}| j j||fS )zArray-interface compliant full description of a column.

    This returns a 3-tuple (name, type, shape) that can always be
    used in a structured array dtype definition.
    NOshaper   r3   )infodtypehasattrr6   name)colZ	col_dtypeZ	col_shaper3   r3   r4   descr   s    r<   c             C   s   t t| jdd|S )z1Check if the object's info is an instance of cls.r7   N)
isinstancegetattr	__class__)objclsr3   r3   r4   has_info_class   s    rB   c             C   s@   | dkrdS t  }x$| D ]}t|ts*dS || qW t|S )zReturn list of column names if ``rows`` is a list of dict that
    defines table data.

    If rows is not a list of dict then return None.
    N)setr=   dictupdatelist)rowsnamesrowr3   r3   r4   _get_names_from_list_of_dict   s    

rJ   c                   sf   e Zd ZdZi f fdd	Zdd Zd fdd	Zd	d
 Zdd Z fddZ	dd Z
dd Z  ZS )TableColumnsaB  OrderedDict subclass for a set of columns.

    This class enhances item access to provide convenient access to columns
    by name or index, including slice access.  It also handles renaming
    of columns.

    The initialization argument ``cols`` can be a list of ``Column`` objects
    or any structure that is valid for initializing a Python dict.  This
    includes a dict, list of (key, val) tuples or [key, val] lists, etc.

    Parameters
    ----------
    cols : dict, list, tuple; optional
        Column objects as data structure that can init dict (see above)
    c                s\   t |ttfrLg }x4|D ],}t|tr:||jj|f q|| qW |}t 	| d S )N)
r=   rF   tuplerB   r   appendr7   r:   super__init__)selfcolsnewcolsr;   )r?   r3   r4   rO      s    

zTableColumns.__init__c                s   t |trt |S t |ttjfr6t  | S t |tj	rl|j
dkrl|jjdkrlt  |  S t |tr  fdd|D S t |tr  fddt | D S td jjdS )a?  Get items from a TableColumns object.
        ::

          tc = TableColumns(cols=[Column(name='a'), Column(name='b'), Column(name='c')])
          tc['a']  # Column('a')
          tc[1] # Column('b')
          tc['a', 'b'] # <TableColumns names=('a', 'b')>
          tc[1:3] # <TableColumns names=('b', 'c')>
        r3   ic                s   g | ]} | qS r3   r3   ).0x)rP   r3   r4   
<listcomp>   s    z,TableColumns.__getitem__.<locals>.<listcomp>c                s   g | ]} | qS r3   r3   )rT   rU   )rP   r3   r4   rV      s    z(Illegal key or index value for {} objectN)r=   strr   __getitem__intnpintegerrF   valuesndarrayr6   r8   kinditemrL   r?   slice
IndexErrorformatr/   )rP   r_   r3   )rP   r4   rX      s    

"

 zTableColumns.__getitem__Fc                s,   || kr|st d|t || dS )a}  
        Set item in this dict instance, but do not allow directly replacing an
        existing column unless it is already validated (and thus is certain to
        not corrupt the table).

        NOTE: it is easily possible to corrupt a table by directly *adding* a new
        key to the TableColumns attribute of a Table, e.g.
        ``t.columns['jane'] = 'doe'``.

        z@Cannot replace column '{}'.  Use Table.replace_column() instead.N)
ValueErrorrb   rN   __setitem__)rP   r_   value	validated)r?   r3   r4   rd     s    zTableColumns.__setitem__c             C   s.   dd |   D }d| jj dd| dS )Nc             s   s   | ]}d | d V  qdS )'Nr3   )rT   rU   r3   r3   r4   	<genexpr>  s    z(TableColumns.__repr__.<locals>.<genexpr><z names=(,z)>)keysr?   r/   join)rP   rH   r3   r3   r4   __repr__  s    zTableColumns.__repr__c                s   ||krd S || kr$t d| d| | jj}|d k	rT|j|| |j|| ||i  fdd| D }t|  }|   | 	tt
|| d S )NzColumn z already existsc                s   g | ]}  ||qS r3   )get)rT   r:   )mapperr3   r4   rV   %  s    z/TableColumns._rename_column.<locals>.<listcomp>)KeyErrorr7   parent_tablepprint_exclude_names_renamepprint_include_namesrF   r\   clearrE   zip)rP   r:   new_namerq   	new_namesrQ   r3   )ro   r4   _rename_column  s    zTableColumns._rename_columnc                s8   | | j j}|d k	r,|j| |j| t |S )N)r7   rq   rr   _removert   rN   __delitem__)rP   r:   rq   )r?   r3   r4   r{   *  s
    zTableColumns.__delitem__c                s    fdd|   D }|S )ay  
        Return a list of columns which are instances of the specified classes.

        Parameters
        ----------
        cls : class or tuple thereof
            Column class (including mixin) or tuple of Column classes.

        Returns
        -------
        col_list : list of `Column`
            List of Column objects which are instances of given classes.
        c                s   g | ]}t | r|qS r3   )r=   )rT   r;   )rA   r3   r4   rV   B  s    z+TableColumns.isinstance.<locals>.<listcomp>)r\   )rP   rA   rQ   r3   )rA   r4   r=   4  s    zTableColumns.isinstancec                s    fdd|   D }|S )a  
        Return a list of columns which are not instances of the specified classes.

        Parameters
        ----------
        cls : class or tuple thereof
            Column class (including mixin) or tuple of Column classes.

        Returns
        -------
        col_list : list of `Column`
            List of Column objects which are not instances of given classes.
        c                s   g | ]}t | s|qS r3   )r=   )rT   r;   )rA   r3   r4   rV   S  s    z/TableColumns.not_isinstance.<locals>.<listcomp>)r\   )rP   rA   rQ   r3   )rA   r4   not_isinstanceE  s    zTableColumns.not_isinstance)F)r/   r0   r1   r2   rO   rX   rd   rm   ry   r{   r=   r|   __classcell__r3   r3   )r?   r4   rK      s   
rK   c               @   s   e Zd ZdZdS )TableAttributea  
    Descriptor to define a custom attribute for a Table subclass.

    The value of the ``TableAttribute`` will be stored in a dict named
    ``__attributes__`` that is stored in the table ``meta``.  The attribute
    can be accessed and set in the usual way, and it can be provided when
    creating the object.

    Defining an attribute by this mechanism ensures that it will persist if
    the table is sliced or serialized, for example as a pickle or ECSV file.

    See the `~astropy.utils.metadata.MetaAttribute` documentation for additional
    details.

    Parameters
    ----------
    default : object
        Default value for attribute

    Examples
    --------
      >>> from astropy.table import Table, TableAttribute
      >>> class MyTable(Table):
      ...     identifier = TableAttribute(default=1)
      >>> t = MyTable(identifier=10)
      >>> t.identifier
      10
      >>> t.meta
      OrderedDict([('__attributes__', {'identifier': 10})])
    N)r/   r0   r1   r2   r3   r3   r3   r4   r~   W  s   r~   c                   sz   e Zd ZdZdd Z fddZ fddZ fdd	Z fd
dZ fddZ	dd Z
dddZdd Zdd Z  ZS )PprintIncludeExcludea=  Maintain tuple that controls table column visibility for print output.

    This is a descriptor that inherits from MetaAttribute so that the attribute
    value is stored in the table meta['__attributes__'].

    This gets used for the ``pprint_include_names`` and ``pprint_exclude_names`` Table
    attributes.
    c             C   sF   |dkr| S |j | j}|dkr6t| }||j | j< t||_|S )zGet the attribute.

        This normally returns an instance of this class which is stored on the
        owner object.
        N)__dict__rn   r:   r   weakrefref_instance_ref)rP   instanceZ	owner_clsre   r3   r3   r4   __get__  s    zPprintIncludeExclude.__get__c                s<   t |tr|g}|dkr&t|| j nt |t|S dS )a  Set value of ``instance`` attribute to ``names``.

        Parameters
        ----------
        instance : object
            Instance that owns the attribute
        names : None, str, list, tuple
            Column name(s) to store, or None to clear
        N)r=   rW   delattrr:   rN   __set__rL   )rP   r   rH   )r?   r3   r4   r     s
    

zPprintIncludeExclude.__set__c                s   |   }t ||jS )zGet the value of the attribute.

        Returns
        -------
        names : None, tuple
            Include/exclude names
        )r   rN   r   r?   )rP   r   )r?   r3   r4   __call__  s    	zPprintIncludeExclude.__call__c                s:   t | dr,d| jj d| j d|   d}n
t  }|S )Nr   ri   z name=z value=>)r9   r?   r/   r:   rN   rm   )rP   out)r?   r3   r4   rm     s    
"
zPprintIncludeExclude.__repr__c                sN   t |tr|gnt|}|  }t ||j}|dkr<g nt|}|||fS )zCommon setup for add and remove.

        - Coerce attribute value to a list
        - Coerce names into a list
        - Get the parent table instance
        N)r=   rW   rF   r   rN   r   r?   )rP   rH   r   re   )r?   r3   r4   _add_remove_setup  s
    z&PprintIncludeExclude._add_remove_setupc                s>   |  |\}}   fdd|D  t |t  dS )zAdd ``names`` to the include/exclude attribute.

        Parameters
        ----------
        names : str, list, tuple
            Column name(s) to add
        c             3   s   | ]}| kr|V  qd S )Nr3   )rT   r:   )re   r3   r4   rh     s    z+PprintIncludeExclude.add.<locals>.<genexpr>N)r   extendrN   r   rL   )rP   rH   r   )r?   )re   r4   add  s    zPprintIncludeExclude.addc             C   s   | j |dd dS )zRemove ``names`` from the include/exclude attribute.

        Parameters
        ----------
        names : str, list, tuple
            Column name(s) to remove
        T)	raise_excN)rz   )rP   rH   r3   r3   r4   remove  s    zPprintIncludeExclude.removeFc             C   s   |  |\}}}|s"d|jkr"dS x8|D ]0}||kr@|| q(|r(t| d| j q(W |g krhdnt|}| || dS )z5Remove ``names`` with optional checking if they existZ__attributes__Nz not in )r   metar   rc   r:   rL   r   )rP   rH   r   r   re   r:   r3   r3   r4   rz     s    
zPprintIncludeExclude._removec             C   s6   |  pd}||kr2t |}||||< | | dS )z:Rename ``name`` to ``new_name`` if ``name`` is in the listr3   N)rF   indexrC   )rP   r:   rw   rH   rx   r3   r3   r4   rs     s
    
zPprintIncludeExclude._renamec             C   s0   G dd d}|| d}|   }| || |S )zSet value of include/exclude attribute to ``names``.

        Parameters
        ----------
        names : None, str, list, tuple
            Column name(s) to store, or None to clear
        c               @   s,   e Zd Zdd Zdd Zdd Zdd Zd	S )
z*PprintIncludeExclude.set.<locals>._Contextc             S   s   || _ | | _d S )N)descriptor_self
names_orig)rP   r   r3   r3   r4   rO     s    z3PprintIncludeExclude.set.<locals>._Context.__init__c             S   s   d S )Nr3   )rP   r3   r3   r4   	__enter__  s    z4PprintIncludeExclude.set.<locals>._Context.__enter__c             S   s    | j }| }||| j d S )N)r   r   r   r   )rP   typere   tbr   r   r3   r3   r4   __exit__  s    z3PprintIncludeExclude.set.<locals>._Context.__exit__c             S   s
   t | jS )N)reprr   )rP   r3   r3   r4   rm     s    z3PprintIncludeExclude.set.<locals>._Context.__repr__N)r/   r0   r1   rO   r   r   rm   r3   r3   r3   r4   _Context  s   r   )r   )r   r   )rP   rH   r   ctxr   r3   r3   r4   rC     s
    
zPprintIncludeExclude.set)F)r/   r0   r1   r2   r   r   r   rm   r   r   r   rz   rs   rC   r}   r3   r3   )r?   r4   r   x  s   

r   c            
       sV  e Zd ZdZeddZeZeZeZe	Z	e
Z
eeZeeZe Ze ZdddZddd	Zd
d Zdd Zdd Zedd Zejdd Zedd ZdddZedd Zedd Zedd Zedd Z ddd Z!d!d" Z"d#d$ Z#dd%d&Z$d'd( Z%d)d* Z&d+d, Z'dd-d.Z(d/d0 Z)d1d2 Z*d3d4 Z+d5d6 Z,d7d8 Z-d9d: Z.e/dd;d<Z0d=d> Z1d?d@ Z2ddAdBZ3dCdD Z4dEdF Z5dGdH Z6dIdJ Z7edKdL Z8edMdN Z9edOdP Z:dQdR Z;e<e=ddSdTZ>e<e=ddVdWZ?dXdY Z@dd]d^ZAd_dd`dadiddbdd\fdcddZBe<eCdedfddgdhZDe<eCdedfddidjZEddkdlZFdmdn ZGdodp ZHdqdr ZIdsdt ZJdudv ZKedwdx ZLeLjdydx ZLdzd{ ZMed|d} ZNed~d ZOedd ZPe/dd ZQdd ZRdd ZSdd ZTdd ZUdd ZVdddZWdddZXdd ZYdddZZdd Z[dd Z\dd Z]dd Z^dd Z_dd Z`dd Zadd Zbdd Zcdd Zddd Zedd ZfdddZgdddZhdd ZidddZjdddZkdd ZldddZmdddZndddZodd Zp fddĄZq fddƄZr fddȄZs fddʄZtdd̄ Zudd΄ ZvddЄ Zwdd҄ ZxeddԄ Zyddք Zzddd؄Z{e|dddڄZ}e~ Z  ZS )Tablea$  A class to represent tables of heterogeneous data.

    `~astropy.table.Table` provides a class for heterogeneous tabular data.
    A key enhancement provided by the `~astropy.table.Table` class over
    e.g. a `numpy` structured array is the ability to easily modify the
    structure of the table by adding or removing columns, or adding new
    rows of data.  In addition table and column metadata are fully supported.

    `~astropy.table.Table` differs from `~astropy.nddata.NDData` by the
    assumption that the input data consists of columns of homogeneous data,
    where each column has a unique identifier and may contain additional
    metadata such as the data unit, format, and description.

    See also: https://docs.astropy.org/en/stable/table/

    Parameters
    ----------
    data : numpy ndarray, dict, list, table-like object, optional
        Data to initialize table.
    masked : bool, optional
        Specify whether the table is masked.
    names : list, optional
        Specify column names.
    dtype : list, optional
        Specify column data types.
    meta : dict, optional
        Metadata associated with the table.
    copy : bool, optional
        Copy the input data. If the input is a Table the ``meta`` is always
        copied regardless of the ``copy`` parameter.
        Default is True.
    rows : numpy ndarray, list of list, optional
        Row-oriented data for table instead of ``data`` argument.
    copy_indices : bool, optional
        Copy any indices in the input data. Default is True.
    units : list, dict, optional
        List or dict of units to apply to columns.
    descriptions : list, dict, optional
        List or dict of descriptions to apply to columns.
    **kwargs : dict, optional
        Additional keyword args when converting table-like object.
    F)copyNc                s  | j p| jp| j}|rtjntj}t| jdkr<|dddS g }| j } dk	rd fdd|D }xR|D ]J}t	|}|j
jjs|st|d d}	|d |	|d f}|| qjW |t| |d}
x@|D ]8}||
|j
j< |rt|trt|d	r|j|
|j
j _qW |
S )
a%  
        Return a new copy of the table in the form of a structured np.ndarray or
        np.ma.MaskedArray object (as appropriate).

        Parameters
        ----------
        keep_byteorder : bool, optional
            By default the returned array has all columns in native byte
            order.  However, if this option is `True` this preserves the
            byte order of all columns (if any are non-native).

        names : list, optional:
            List of column names to include for returned structured array.
            Default is to include all table columns.

        Returns
        -------
        table_array : array or `~numpy.ma.MaskedArray`
            Copy of table as a numpy structured array.
            ndarray for unmasked or `~numpy.ma.MaskedArray` for masked.
        r   N)r8   c                s   g | ]}|j j kr|qS r3   )r7   r:   )rT   r;   )rH   r3   r4   rV   {  s    z"Table.as_array.<locals>.<listcomp>r   =   mask)maskedhas_masked_columnshas_masked_valuesr   emptyrZ   lencolumnsr\   r<   r7   r8   isnativenewbyteorderrM   r:   rB   r   r9   r   )rP   Zkeep_byteorderrH   r   Z
empty_initr8   rQ   r;   Z	col_descrZnew_dtdatar3   )rH   r4   as_array[  s(    


zTable.as_arrayTc                sr  |  | |  | _|  | _d| _|| _d | _|sD d k	rDtdd }|d k	r|d k	r`tdt	|t
jrtt|}t|}|r|}nt	|| jr|}ntt| }d }i }|rx6t|D ]*}t| j|d }t	|tr||||< qW t|dr|j| j|f|}d}n |r,tdt| d t	|tjrT|jdkrT|jjsTd }t	|| jrx|j|j|jd	  }t	|tt fr|pt|}|r| j!}t"|}n| j#}t"|}nt	|tjr>|jjr| j$}t"|jj}|jj}nH| j$}|jd
krtdn"t"|jd	kr0|tj%d d f }|jd	 }n.t	|t&rd| j'}t|}t"|}nt	|t(r|d kr|j)r|r|j)n|j)* }|j| _| jo|j| _|j+}t"|}t|j, }| j#}n|d krX|d kr> d krg }nFy&t   j} fdd|D  W n t-k
r<   tdY nX | j#}t"|}g g| }ntdt.| d d krd g|  n2t	 tjr|d kr j} fdd jD  |d kr|pd g| }dd |D }| /| | ||| || |d k	r|rt0|n|| _)|rBx"|1 D ]\}}t2| || q(W | j3dkrVtd| 4d|	 | 4d|
 d S )NTz$Cannot specify dtype when copy=Falsez+Cannot supply both `data` and `rows` values__astropy_table__Fz/__init__() got unexpected keyword argument {!r}r   )r   r   r3   z(Can not initialize a Table with a scalarc                s   g | ]} | qS r3   r3   )rT   r:   )r8   r3   r4   rV   "  s    z"Table.__init__.<locals>.<listcomp>z<dtype was specified but could not be parsed for column namesz
Data type z not allowed to init Tablec                s   g | ]} | qS r3   r3   )rT   r:   )r8   r3   r4   rV   9  s    c             S   s   g | ]}t |qS r3   )r%   )rT   r:   r3   r3   r4   rV   @  s    )NTFz+masked property must be None, True or Falseunitdescription)5_set_maskedrK   r   r   	formatter_copy_indices_init_indicesprimary_keyrc   r=   typesGeneratorTyperF   rJ   r$   rv   r>   r?   r~   popr9   r   	TypeErrorrb   rk   rZ   r]   r6   r8   rH   _table_indexrL   _init_from_list_of_dictsr   _init_from_list_init_from_ndarrayZnewaxisr
   _init_from_dictr   r   r   colnamesr\   	Exceptionr   _check_names_dtyper   itemssetattrr   _set_column_attribute)rP   r   r   rH   r8   r   r   rG   copy_indicesunitsZdescriptionskwargsZnames_from_list_of_dictdefault_namesZmeta_table_attrsattrr<   Z	init_funcn_colsre   r3   )r8   r4   rO     s    
















zTable.__init__c                s    sdS t  tr& fdd jD  t  tsbt t| jkrRtd| dtt| j  xx  D ]l\}}|| jkrtd| d| d|d	krt |t	r|
 d
krd}|tjjdfkrlt| | j|| qlW dS )zSet ``attr`` for columns to ``values``, which can be either a dict (keyed by column
        name) or a dict of name: value pairs.  This is used for handling the ``units`` and
        ``descriptions`` kwargs to ``__init__``.
        Nc                s   i | ]} | |qS r3   r3   )rT   r:   )r\   r3   r4   
<dictcomp>c  s    z/Table._set_column_attribute.<locals>.<dictcomp>zsequence of z$ values must match number of columnszinvalid column name z for setting z
 attributer    )r=   r$   r   rD   r   r   rc   rv   r   rW   striprZ   r   r   r   r7   )rP   r   r\   r:   re   r3   )r\   r4   r   Y  s     


zTable._set_column_attributec             C   s"   t dd | j D }|| jfS )Nc             s   s,   | ]$\}}|t |tr|nt|fV  qd S )N)r=   r   r"   )rT   keyr;   r3   r3   r4   rh   x  s   z%Table.__getstate__.<locals>.<genexpr>)r   r   r   r   )rP   r   r3   r3   r4   __getstate__w  s    zTable.__getstate__c             C   s   |\}}| j ||d d S )N)r   )rO   )rP   stater   r   r3   r3   r4   __setstate__|  s    zTable.__setstate__c             C   s@   | j s| js| jr8tdd |  D | jdd}d|_nd }|S )Nc             S   s   g | ]}t |d t|jqS )r   )r>   r!   r6   )rT   r;   r3   r3   r4   rV     s   zTable.mask.<locals>.<listcomp>F)rH   r   T)r   r   r   r   itercolsr   _setitem_inplace)rP   Z
mask_tabler3   r3   r4   r     s    
z
Table.maskc             C   s   || j d d < d S )N)r   )rP   valr3   r3   r4   r     s    c             C   s
   |   jS )zThis is needed so that comparison of a masked Table and a
        MaskedArray works.  The requirement comes from numpy.ma.core
        so don't remove this property.)r   r   )rP   r3   r3   r4   _mask  s    zTable._maskc                sJ   | j s| js| jr> fdd|  D }| j|t| jddS |  S dS )a+  Return copy of self, with masked values filled.

        If input ``fill_value`` supplied then that value is used for all
        masked entries in the table.  Otherwise the individual
        ``fill_value`` defined for each table column is used.

        Parameters
        ----------
        fill_value : str
            If supplied, this ``fill_value`` is used for all masked entries
            in the entire table.

        Returns
        -------
        filled_table : `~astropy.table.Table`
            New table with masked values filled
        c                s$   g | ]}t |d r| n|qS )filled)r9   r   )rT   r;   )
fill_valuer3   r4   rV     s   z Table.filled.<locals>.<listcomp>F)r   r   N)r   r   r   r   r?   r   r   r   )rP   r   r   r3   )r   r4   r     s
    
zTable.filledc                sV   g }xH| j  D ]:}x4|jjD ]( t fdd|D dkr|  qW qW t|S )zk
        Return the indices associated with columns of the table
        as a TableIndices object.
        c                s   g | ]} |kqS r3   r3   )rT   rU   )r   r3   r4   rV     s    z!Table.indices.<locals>.<listcomp>r   )r   r\   r7   indicessumrM   r   )rP   lstcolumnr3   )r   r4   r     s    zTable.indicesc             C   s   t | S )z
        Return a TableLoc object that can be used for retrieving
        rows by index in a given data range. Note that both loc
        and iloc work only with single-column indices.
        )r   )rP   r3   r3   r4   loc  s    z	Table.locc             C   s   t | S )z
        Return a TableLocIndices object that can be used for retrieving
        the row indices corresponding to given table index key value or values.
        )r   )rP   r3   r3   r4   loc_indices  s    zTable.loc_indicesc             C   s   t | S )z
        Return a TableILoc object that can be used for retrieving
        indexed rows in the order they appear in the index.
        )r   )rP   r3   r3   r4   iloc  s    z
Table.ilocc       	      C   s   t |tr|f}| jt|  }x2|D ]*}t|jdds(td|jj	t
|q(W | j }t|||d}t|tddddd}|r|| _x|D ]}|jj| qW dS )	aJ  
        Insert a new index among one or more columns.
        If there are no indices, make this index the
        primary table index.

        Parameters
        ----------
        colnames : str or list
            List of column names (or a single column name) to index
        engine : type or None
            Indexing engine class to use, from among SortedArray, BST,
            and SCEngine. If the supplied argument is None
            (by default), use SortedArray.
        unique : bool
            Whether the values of the index must be unique. Default is False.
        Z_supports_indexingFz3Cannot create an index on column "{}", of type "{}")engineuniquer   NT)original)r=   rW   r   rL   r\   r>   r7   rc   rb   r:   r   r   r'   r   r`   r   rM   )	rP   r   r   r   r   r;   Z
is_primaryr   Zsliced_indexr3   r3   r4   	add_index  s    


zTable.add_indexc          	   C   sd   | j | }xT| jD ]J}y||jj W n tk
r<   Y qX x|j D ]}|jj| qFW qW dS )a  
        Remove all indices involving the given column.
        If the primary index is removed, the new primary
        index will be the most recently added remaining
        index.

        Parameters
        ----------
        colname : str
            Name of column
        N)r   r   col_positionr7   r:   rc   r   )rP   colnamer;   r   cr3   r3   r4   remove_indices  s    
zTable.remove_indicesc             C   s
   t | |S )a'  
        Return a context manager for an indexing mode.

        Parameters
        ----------
        mode : str
            Either 'freeze', 'copy_on_getitem', or 'discard_on_copy'.
            In 'discard_on_copy' mode,
            indices are not copied whenever columns or tables are copied.
            In 'freeze' mode, indices are not modified whenever columns are
            modified; at the exit of the context, indices refresh themselves
            based on column values. This mode is intended for scenarios in
            which one intends to make many additions or modifications in an
            indexed column.
            In 'copy_on_getitem' mode, indices are copied when taking column
            slices as well as table slices, so col[i0:i1] will preserve
            indices.
        )r(   )rP   moder3   r3   r4   
index_mode  s    zTable.index_modec             C   s0   |dk	rt d|  }t|tjjr,|jS |S )zSupport converting Table to np.array via np.array(table).

        Coercion to a different dtype via np.array(table, dtype) is not
        supported and will raise a ValueError.
        Nz Datatype coercion is not allowed)rc   r   r=   rZ   r   MaskedArrayr   )rP   r8   r   r3   r3   r4   	__array__,  s    
zTable.__array__c             C   sX   x2|df|dffD ]\}}t |st| dqW t||ksLt||krTtddS )zcMake sure that names and dtype are both iterable and have
        the same length as data.
        r8   rH   z must be a list or Nonez:Arguments "names" and "dtype" must match number of columnsN)r   rc   r   )rP   rH   r8   r   Zinp_listZinp_strr3   r3   r4   r   @  s    zTable._check_names_dtypec          
      s  t   t }x|D ]}|| qW t|d  |krJt|d  }nt|}i }tt}	xl|D ]d}
g ||
< xVt|D ]J\}}y||
 }W n& tk
r   |	|
 	|  }Y nX ||
 	| qzW qdW |	rxJ|	
 D ]>\}
}||
 }t fdd|D }x|D ]}|||< qW qW tdd |D r6|}| ||||| |	rxX|	
 D ]L\}
}| |
 }t|trt|ts| j|dd| |
< tjj| |
 |< qXW dS )z?Initialize table from a list of dictionaries representing rows.r   c             3   s   | ]}| k	r|V  qd S )Nr3   )rT   r   )MISSINGr3   r4   rh   q  s    z1Table._init_from_list_of_dicts.<locals>.<genexpr>c             s   s   | ]}|d kV  qd S )Nr3   )rT   r:   r3   r3   r4   rh   v  s    F)r   N)objectrC   rE   rk   rF   sortedr	   	enumeraterp   rM   r   nextallr   r=   r   r   rZ   r   r   )rP   r   rH   r8   r   r   Znames_from_datarI   rQ   Zmissing_indexesr:   iir   indexesr;   Z	first_valr   r3   )r   r4   r   L  sD    



zTable._init_from_list_of_dictsc             C   sb   |dkrdS g }t |}x:t||||D ](\}}	}
}| |||
||	}|| q(W | | dS )zInitialize table from a list of column data.  A column can be a
        Column object, np.ndarray, mixin, or any other iterable object.
        r   N)r    rv   _convert_data_to_colrM   _init_from_cols)rP   r   rH   r8   r   r   rQ   r   r;   r:   default_namer3   r3   r4   r     s    zTable._init_from_listc             C   s  |  |}t| j| jr| jn| j}y|  |d }W n tk
rN   d}Y nX t|ts|st|tjrt	|j
dkr|t}d}|st|tr|jp|}n"dt|ddkr|jjp|}n|}t|tr| |}	n|r |rt|| jdn|}
||
j_|
S |rNy|d |}
||
j_|
S  tk
rJ   tj|td	}| j}	Y nX nnt|tjjrd|}	nX|d
krtd
}| j}	n<t|dst||}d}t|tjjr|n| j}	n| j}	y|	||||| jd}
W n tk
r   tdY nX | |
}
|
S )a  
        Convert any allowed sequence data ``col`` to a column object that can be used
        directly in the self.columns dict.  This could be a Column, MaskedColumn,
        or mixin column.

        The final column name is determined by::

            name or data.info.name or def_name

        If ``data`` has no ``info`` then ``name = name or def_name``.

        The behavior of ``copy`` for Column objects is:
        - copy=True: new class instance with a copy of data and deep copy of meta
        - copy=False: new class instance with same data and a key-only copy of meta

        For mixin columns:
        - copy=True: new class instance with copy of data and deep copy of meta
        - copy=False: original instance (no copy at all)

        Parameters
        ----------
        data : object (column-like sequence)
            Input column data
        copy : bool
            Make a copy
        default_name : str
            Default name
        dtype : np.dtype or None
            Data dtype
        name : str or None
            Column name

        Returns
        -------
        col : Column, MaskedColumn, mixin-column type
            Object that can be used as a column in self
        r   Fr   Tr7   r   r3   )r   )r8   Nr8   )r:   r   r8   r   r   z*unable to convert data to Column for Table)_is_mixin_for_table
issubclassColumnClassr   r   r=   r   rZ   r]   r   r8   viewr,   r:   r>   r7   _get_col_cls_for_tabler"   r   r?   arrayr   r   r   r9   r#   rc   _convert_col_for_table)rP   r   r   r   r8   r:   Zdata_is_mixinZmasked_col_clsZdata0_is_mixincol_clsr;   r3   r3   r4   r     s`    &








zTable._convert_data_to_colc                st    j jpt| j jdk	}fddt|D }|rH fddD n fddt|D }| ||||| dS )z1Initialize table from an ndarray structured arrayNc                s   g | ]\}}|p | qS r3   r3   )rT   rS   r:   )
data_namesr3   r4   rV   '  s    z,Table._init_from_ndarray.<locals>.<listcomp>c                s   g | ]} | qS r3   r3   )rT   r:   )r   r3   r4   rV   )  s    c                s   g | ]} d d |f qS )Nr3   )rT   rS   )r   r3   r4   rV   *  s    )r8   rH   r    r   ranger   )rP   r   rH   r8   r   r   structrQ   r3   )r   r   r4   r   "  s    zTable._init_from_ndarrayc                s(    fdd|D }|  ||||| dS )z-Initialize table from a dictionary of columnsc                s   g | ]} | qS r3   r3   )rT   r:   )r   r3   r4   rV   1  s    z)Table._init_from_dict.<locals>.<listcomp>N)r   )rP   r   rH   r8   r   r   Z	data_listr3   )r   r4   r   .  s    zTable._init_from_dictc             C   sh   |j }| jr*t|trdt|| jsd| j}n:t|trHt|| jsd| j}nt|trdt|| jsd| j}|S )a  Get the correct column class to use for upgrading any Column-like object.

        For a masked table, ensure any Column-like object is a subclass
        of the table MaskedColumn.

        For unmasked table, ensure any MaskedColumn-like object is a subclass
        of the table MaskedColumn.  If not a MaskedColumn, then ensure that any
        Column-like object is a subclass of the table Column.
        )r?   r   r=   r   r   )rP   r;   r   r3   r3   r4   r   4  s    
zTable._get_col_cls_for_tablec             C   s:   t |tr6t || js6| |}||jk	r6||dd}|S )a
  
        Make sure that all Column objects have correct base class for this type of
        Table.  For a base Table this most commonly means setting to
        MaskedColumn if the table is masked.  Table subclasses like QTable
        override this method.
        F)r   )r=   r   r   r   r?   )rP   r;   r   r3   r3   r4   r   M  s
    

zTable._convert_col_for_tablec       	         s   t dd |D }t|dkr,td|  fdd|D }  | i }xd  D ]X}xRt|jjpjg D ]>\}}tdd |j	D }||kr|| |jj|< qn|||< qnW qXW dS )	z7Initialize table from a list of Column or mixin objectsc             s   s   | ]}t |V  qd S )N)r   )rT   r;   r3   r3   r4   rh   ^  s    z(Table._init_from_cols.<locals>.<genexpr>r   z"Inconsistent data column lengths: c                s   g | ]}  |qS r3   )r   )rT   r;   )rP   r3   r4   rV   e  s    z)Table._init_from_cols.<locals>.<listcomp>c             s   s   | ]}|j jV  qd S )N)r7   r:   )rT   Zind_colr3   r3   r4   rh   o  s    N)
rC   r   rc   _make_table_from_colsr   r   r7   r   rL   r   )	rP   rQ   lengthsrR   Z
index_dictr;   rS   r   rH   r3   )rP   r4   r   [  s    zTable._init_from_colsc             C   s   | j | jd}| jr | j |_| j|_g }x`| j D ]R}|| }t|trR|n|j	j
r| j|j	_|j	||t|}d|j	_|| q8W | j||d| j d |S )z3Create a new table as a referenced slice from self.)r   TF)verifyrH   )r?   r   r   r   r   r   r\   r=   r   r7   r   r   Zslice_indicesr   rM   r   rk   )rP   Zslice_tablerR   r;   newcolr3   r3   r4   _new_from_sliceu  s    
zTable._new_from_slicec             C   s~   |dkrdd |D }|rFd|kr*t dtt|t|krFtd| dd t||D | _x|D ]}| | qhW dS )z[
        Make ``table`` in-place so that it represents the given list of ``cols``.
        Nc             S   s   g | ]}|j jqS r3   )r7   r:   )rT   r;   r3   r3   r4   rV     s    z/Table._make_table_from_cols.<locals>.<listcomp>z Cannot have None for column namezDuplicate column namesc             s   s   | ]\}}||fV  qd S )Nr3   )rT   r:   r;   r3   r3   r4   rh     s    z.Table._make_table_from_cols.<locals>.<genexpr>)r   r   rC   rc   rK   rv   r   _set_col_parent_table_and_mask)r  rQ   r   rH   r;   r3   r3   r4   r     s    
zTable._make_table_from_colsc             C   s:   t |tr|n|j}| |_| jr6t|ds6t|j|_dS )z
        Set ``col.parent_table = self`` and force ``col`` to have ``mask``
        attribute if the table is masked and ``col.mask`` does not exist.
        r   N)	r=   r   r7   rq   r   r9   r!   r6   r   )rP   r;   Zcol_infor3   r3   r4   r    s    z$Table._set_col_parent_table_and_maskc             c   s   x| j D ]}| | V  qW dS )a  
        Iterate over the columns of this table.

        Examples
        --------

        To iterate over the columns of a table::

            >>> t = Table([[1], [2]])
            >>> for col in t.itercols():
            ...     print(col)
            col0
            ----
               1
            col1
            ----
               2

        Using ``itercols()`` is similar to  ``for col in t.columns.values()``
        but is syntactically preferred.
        N)r   )rP   r   r3   r3   r4   r     s    zTable.itercolsc             C   s   |d kr6| j jg}| jr"|d |dt|   d|}|rbddlm}	 d|	| d}nd| d	}|d krd
t|  }| j	j
| |||dd |||d	\}
}|d|
 }|S )Nzmasked=Truezlength= r   )
xml_escapez<i>z</i>
ri   z>
r  T)tableidhtml	max_width	show_name	show_unit
show_dtype	max_lines
tableclass
)r?   r/   r   rM   r   rl   Zastropy.utils.xml.writerr  idr   _pformat_table)rP   r  Z
descr_valsr	  r  r  r  r  r<   r  Z
data_linesoutsr   r3   r3   r4   _base_repr_  s$    


zTable._base_repr_c             C   s"   | j ddtjd}d| d}|S )NT)r  r	  r  z<div>z</div>)r  r-   default_notebook_table_class)rP   r   r3   r3   r4   _repr_html_  s    
zTable._repr_html_c             C   s   | j dd dS )NF)r  r	  )r  )rP   r3   r3   r4   rm     s    zTable.__repr__c             C   s   d |  S )Nr  )rl   pformat)rP   r3   r3   r4   __str__  s    zTable.__str__c             C   s   t | dS )Nzutf-8)rW   encode)rP   r3   r3   r4   	__bytes__  s    zTable.__bytes__c             C   s   t dd | j D S )zr
        True if table has any mixin columns (defined as columns that are not Column
        subclasses).
        c             s   s   | ]}t |tV  qd S )N)rB   r   )rT   r;   r3   r3   r4   rh     s    z*Table.has_mixin_columns.<locals>.<genexpr>)anyr   r\   )rP   r3   r3   r4   has_mixin_columns  s    zTable.has_mixin_columnsc             C   s   t dd |  D S )zTrue if table has any ``MaskedColumn`` columns.

        This does not check for mixin columns that may have masked values, use the
        ``has_masked_values`` property in that case.

        c             s   s   | ]}t |tV  qd S )N)r=   r   )rT   r;   r3   r3   r4   rh     s    z+Table.has_masked_columns.<locals>.<genexpr>)r  r   )rP   r3   r3   r4   r   	  s    zTable.has_masked_columnsc             C   s4   x.|   D ]}t|dr
t|jr
dS q
W dS dS )zTrue if column in the table has values which are masked.

        This may be relatively slow for large tables as it requires checking the mask
        values of each column.
        r   TFN)r   r9   rZ   r  r   )rP   r;   r3   r3   r4   r     s    zTable.has_masked_valuesc             C   s$   t |trdS t|to"t|t S )zg
        Determine if ``col`` should be added to the table directly as
        a mixin column.
        F)r=   r   rB   r   r   )rP   r;   r3   r3   r4   r      s    
zTable._is_mixin_for_tablec          	   C   sz   | j j| ||||||d\}}|d r<|dt|  d |d }	x0t|D ]$\}
}|
|	k rjt|d qNt| qNW dS )a!  Print a formatted string representation of the table.

        If no value of ``max_lines`` is supplied then the height of the
        screen terminal is used to set ``max_lines``.  If the terminal
        height cannot be determined then the default is taken from the
        configuration item ``astropy.conf.max_lines``.  If a negative
        value of ``max_lines`` is supplied then there is no line limit
        applied.

        The same applies for max_width except the configuration item is
        ``astropy.conf.max_width``.

        )r
  r  r  alignshow_lengthz	Length = z rowsn_headerredN)r   r  rM   r   r   r   print)rP   r  r	  r
  r  r  r  linesr  r  rS   liner3   r3   r4   pprint,  s    zTable.pprintr  c             C   s   |  ||||||S )aM  Print a formatted string representation of the entire table.

        This method is the same as `astropy.table.Table.pprint` except that
        the default ``max_lines`` and ``max_width`` are both -1 so that by
        default the entire table is printed instead of restricting to the size
        of the screen terminal.

        )r$  )rP   r  r	  r
  r  r  r  r3   r3   r4   
pprint_allJ  s    
zTable.pprint_allc             C   sH   || j kr@| j|tt| d}| j|gt| j   ddS | S d S )N)r:   r   F)r   )r   r   rZ   Zaranger   r?   rF   r\   )rP   Zindex_row_nameZidx_colr3   r3   r4   _make_index_row_display_tableX  s
    
z#Table._make_index_row_display_table2   astropy-defaultidxc             C   s   ddl m} ddlm} |dkr>dt|  dtjdd }||d	}|rX| |}	n| }	|d
krjt	j
}|	jdd|dd|d}
|	j }dd t|D }|
|j|||d7 }
||
S )a  Render the table in HTML and show it in the IPython notebook.

        Parameters
        ----------
        tableid : str or None
            An html ID tag for the table.  Default is ``table{id}-XXX``, where
            id is the unique integer id of the table object, id(self), and XXX
            is a random number to avoid conflicts when printing the same table
            multiple times.
        table_class : str or None
            A string with a list of HTML classes used to style the table.
            The special default string ('astropy-default') means that the string
            will be retrieved from the configuration item
            ``astropy.table.default_notebook_table_class``. Note that these
            table classes may make use of bootstrap, as this is loaded with the
            notebook.  See `this page <https://getbootstrap.com/css/#tables>`_
            for the list of classes.
        css : str
            A valid CSS string declaring the formatting for the table. Defaults
            to ``astropy.table.jsviewer.DEFAULT_CSS_NB``.
        display_length : int, optional
            Number or rows to show. Defaults to 50.
        show_row_index : str or False
            If this does not evaluate to False, a column with the given name
            will be added to the version of the table that gets displayed.
            This new column shows the index of the row in the table itself,
            even when the displayed table is re-sorted by another column. Note
            that if a column with this name already exists, this option will be
            ignored. Defaults to "idx".

        Notes
        -----
        Currently, unlike `show_in_browser` (with ``jsviewer=True``), this
        method needs to access online javascript code repositories.  This is due
        to modern browsers' limitations on accessing local files.  Hence, if you
        call this method while offline (and don't have a cached version of
        jquery and jquery.dataTables), you will not get the jsviewer features.
        r   )JSViewerr   )HTMLNr  -g    .A)display_lengthzastropy-defaultTr  F)r  r	  r  r  r  r  c             S   s"   g | ]\}}|j jjd kr|qS )Ziufc)r7   r8   r^   )rT   rS   r;   r3   r3   r4   rV     s    z*Table.show_in_notebook.<locals>.<listcomp>)cssZsort_columns)jsviewerr*  IPython.displayr+  r  rZ   randomrandintr&  r-   r  r  r   r\   r   Zipynb)rP   r  r.  r-  table_classshow_row_indexr*  r+  Zjsvdisplay_tabler  r   Zsortable_columnsr3   r3   r4   show_in_notebook`  s"    )


zTable.show_in_notebooki  defaultZuse_local_fileszdisplay compactc	          
   C   s  ddl }	ddl}
ddl}ddlm} ddlm} ddlm} |dkrH|}|	 }|	j
|d}t|dF}|r|r~| |}n| }|j|d	|||||d
 n| j|dd W dQ R X y|
|dkrdn|}W n( |
jk
r   td| d Y nX ||d|| dS )a  Render the table in HTML and show it in a web browser.

        Parameters
        ----------
        max_lines : int
            Maximum number of rows to export to the table (set low by default
            to avoid memory issues, since the browser view requires duplicating
            the table in memory).  A negative value of ``max_lines`` indicates
            no row limit.
        jsviewer : bool
            If `True`, prepends some javascript headers so that the table is
            rendered as a `DataTables <https://datatables.net>`_ data table.
            This allows in-browser searching & sorting.
        browser : str
            Any legal browser name, e.g. ``'firefox'``, ``'chrome'``,
            ``'safari'`` (for mac, you may need to use ``'open -a
            "/Applications/Google Chrome.app" {}'`` for Chrome).  If
            ``'default'``, will use the system default browser.
        jskwargs : dict
            Passed to the `astropy.table.JSViewer` init. Defaults to
            ``{'use_local_files': True}`` which means that the JavaScript
            libraries will be served from local copies.
        tableid : str or None
            An html ID tag for the table.  Default is ``table{id}``, where id
            is the unique integer id of the table object, id(self).
        table_class : str or None
            A string with a list of HTML classes used to style the table.
            Default is "display compact", and other possible values can be
            found in https://www.datatables.net/manual/styling/classes
        css : str
            A valid CSS string declaring the formatting for the table. Defaults
            to ``astropy.table.jsviewer.DEFAULT_CSS``.
        show_row_index : str or False
            If this does not evaluate to False, a column with the given name
            will be added to the version of the table that gets displayed.
            This new column shows the index of the row in the table itself,
            even when the displayed table is re-sorted by another column. Note
            that if a column with this name already exists, this option will be
            ignored. Defaults to "idx".
        r   Nr   )DEFAULT_CSS)urljoin)pathname2urlz
table.htmlwr/  )rb   r.  r  jskwargsZtable_idr3  r  )rb   r7  z	Browser 'z' not found.zfile:)os
webbrowsertempfiler/  r8  urllib.parser9  urllib.requestr:  mkdtemppathrl   openr&  writern   Errorr   error)rP   r  r/  Zbrowserr<  r  r3  r.  r4  r=  r>  r?  r8  r9  r:  ZtmpdirrC  tmpr5  brr3   r3   r4   show_in_browser  s0    -
zTable.show_in_browserz{id})r  c
             C   sF   | j j| ||||||||	|d
\}
}|d rB|
dt|  d |
S )aE  Return a list of lines for the formatted string representation of
        the table.

        If no value of ``max_lines`` is supplied then the height of the
        screen terminal is used to set ``max_lines``.  If the terminal
        height cannot be determined then the default is taken from the
        configuration item ``astropy.conf.max_lines``.  If a negative
        value of ``max_lines`` is supplied then there is no line limit
        applied.

        The same applies for ``max_width`` except the configuration item  is
        ``astropy.conf.max_width``.

        )r
  r  r  r  r  r  r  r  z	Length = z rows)r   r  rM   r   )rP   r  r	  r
  r  r  r  r  r  r  r"  r  r3   r3   r4   r    s    zTable.pformatc
       
      C   s   |  |||||||||		S )aL  Return a list of lines for the formatted string representation of
        the entire table.

        If no value of ``max_lines`` is supplied then the height of the
        screen terminal is used to set ``max_lines``.  If the terminal
        height cannot be determined then the default is taken from the
        configuration item ``astropy.conf.max_lines``.  If a negative
        value of ``max_lines`` is supplied then there is no line limit
        applied.

        The same applies for ``max_width`` except the configuration item  is
        ``astropy.conf.max_width``.

        )r  )
rP   r  r	  r
  r  r  r  r  r  r  r3   r3   r4   pformat_all  s    
zTable.pformat_allc             C   s   | j j| |||||d dS )a  Interactively browse table with a paging interface.

        Supported keys::

          f, <space> : forward one page
          b : back one page
          r : refresh same page
          n : next row
          p : previous row
          < : go to beginning
          > : go to end
          q : quit browsing
          h : print this help

        Parameters
        ----------
        max_lines : int
            Maximum number of lines in table output

        max_width : int or None
            Maximum character width of output

        show_name : bool
            Include a header row for column names. Default is True.

        show_unit : bool
            Include a header row for unit.  Default is to show a row
            for units only if one or more columns has a defined value
            for the unit.

        show_dtype : bool
            Include a header row for column dtypes. Default is True.
        )r
  r  r  N)r   Z_more_tabcol)rP   r  r	  r
  r  r  r3   r3   r4   more#  s    #z
Table.morec                sN  t |tr j| S t |ttjfr0  |S t |tjrb|jdkrb|j	j
dkrb  | S  |r j fdd|D  jd}tj| jj jjd|_ j |_|S t |tjr|jdkst |ttfr|s g S t |ts,t |tjs,t |ts,t |tr6tdd	 |D r6 |S td
t| dd S )Nr3   rS   c                s   g | ]} | qS r3   r3   )rT   rU   )rP   r3   r4   rV   Q  s    z%Table.__getitem__.<locals>.<listcomp>)r   )r   rk   r   c             s   s   | ]}t |tjV  qd S )N)r=   rZ   r]   )rT   rU   r3   r3   r4   rh   ^  s   z$Table.__getitem__.<locals>.<genexpr>zIllegal type z for table item access)r=   rW   r   rY   rZ   r[   r$   r]   r6   r8   r^   r_   _is_list_or_tuple_of_strr?   r   r   TableGroups_indices_keys_groupsr   r   sizerL   rF   r  r`   r   rc   r   )rP   r_   r   r3   )rP   r4   rX   I  s.    

"



zTable.__getitem__c                s  t |tr(|| jkr(| j |dd nt| j}t |trt| ddsttjsty| 	|  d S  t
k
rr   Y nX  | j| d d < n0t |ttjfr| j|| j d n
t |tst |tjst |tst |trtdd |D rt  trdd  j D }njt  tjrB jjrB fd	d jjD }n:t r\t |}n t |krxtd
| }x<t| j |D ]\}}|||< qW ntdt| dd S )NT)r:   r   r   F)r)  r   valsc             s   s   | ]}t |tjV  qd S )N)r=   rZ   r]   )rT   rU   r3   r3   r4   rh     s    z$Table.__setitem__.<locals>.<genexpr>c             s   s   | ]
}|V  qd S )Nr3   )rT   r;   r3   r3   r4   rh     s    c             3   s   | ]} | V  qd S )Nr3   )rT   r:   )re   r3   r4   rh     s    z8Right side value needs {} elements (one for each column)zIllegal type z for table item access)r=   rW   r   
add_columnr   r   r>   r-   Zreplace_inplace_replace_column_warningsr   rY   rZ   r[   _set_rowr`   r]   rF   rL   r   r   r\   r8   rH   Zisscalar	itertoolsrepeatrc   rb   rv   r   )rP   r_   re   r   rS  r;   r   r3   )re   r4   rd   g  s@    



zTable.__setitem__c             C   s   t |tr| | nt |ttjfr2| | n|t |tttj	frbt
dd |D rb| | nLt |ttj	frt|jjdkr| | nt |tr| | ntdd S )Nc             s   s   | ]}t |tV  qd S )N)r=   rW   )rT   rU   r3   r3   r4   rh     s    z$Table.__delitem__.<locals>.<genexpr>rS   zillegal key or index value)r=   rW   remove_columnrY   rZ   r[   
remove_rowrF   rL   r]   r   remove_columnsasarrayr8   r^   remove_rowsr`   ra   )rP   r_   r3   r3   r4   r{     s    

zTable.__delitem__c             C   s   | j S )N)r   )rP   r3   r3   r4   _ipython_key_completions_  s    zTable._ipython_key_completions_c             C   s
   | j | S )z/Return column[item] for recarray compatibility.)r   )rP   r_   r3   r3   r4   field  s    zTable.fieldc             C   s   | j S )N)_masked)rP   r3   r3   r4   r     s    zTable.maskedc             C   s   t dd S )NzZMasked attribute is read-only (use t = Table(t, masked=True) to convert to a masked table))r   )rP   r   r3   r3   r4   r     s    c             C   s0   |dkr|| _ ntd| j r$| jn| j| _dS )z
        Set the table masked property.

        Parameters
        ----------
        masked : bool
            State of table masking (`True` or `False`)
        )TFNz)masked should be one of True, False, NoneN)r`  rc   r   r   _column_class)rP   r   r3   r3   r4   r     s    	zTable._set_maskedc             C   s   | j d kr| jS | j S d S )N)ra  r   )rP   r3   r3   r4   r     s    
zTable.ColumnClassc             C   s   t dd | j D S )Nc             S   s   g | ]}t |qS r3   )r<   )rT   r;   r3   r3   r4   rV     s    zTable.dtype.<locals>.<listcomp>)rZ   r8   r   r\   )rP   r3   r3   r4   r8     s    zTable.dtypec             C   s   t | j S )N)rF   r   rk   )rP   r3   r3   r4   r     s    zTable.colnamesc             C   s$   t | ttfo"| o"tdd | D S )z2Check that ``names`` is a tuple or list of stringsc             s   s   | ]}t |tV  qd S )N)r=   rW   )rT   rU   r3   r3   r4   rh     s    z1Table._is_list_or_tuple_of_str.<locals>.<genexpr>)r=   rL   rF   r   )rH   r3   r3   r4   rM    s    zTable._is_list_or_tuple_of_strc             C   s   t | j S )N)rF   r   rk   )rP   r3   r3   r4   rk     s    z
Table.keysc             C   s
   | j  S )N)r   r\   )rP   r3   r3   r4   r\     s    zTable.valuesc             C   s
   | j  S )N)r   r   )rP   r3   r3   r4   r     s    zTable.itemsc          	   C   s`   yt t| j| jS  ttfk
rZ   t | jdkr:dS tt| j| _t | j| j S X d S )Nr   )	r   r   rX   r   Z_first_colnameAttributeErrorrp   r   iter)rP   r3   r3   r4   __len__  s    zTable.__len__c             C   s6   y| j |S  tk
r0   td| dY nX dS )a  
        Return the positional index of column ``name``.

        Parameters
        ----------
        name : str
            column name

        Returns
        -------
        index : int
            Positional index of column ``name``.

        Examples
        --------
        Create a table with three columns 'a', 'b' and 'c'::

            >>> t = Table([[1, 2, 3], [0.1, 0.2, 0.3], ['x', 'y', 'z']],
            ...           names=('a', 'b', 'c'))
            >>> print(t)
             a   b   c
            --- --- ---
              1 0.1   x
              2 0.2   y
              3 0.3   z

        Get index of column 'b' of the table::

            >>> t.index_column('b')
            1
        zColumn z does not existN)r   r   rc   )rP   r:   r3   r3   r4   index_column  s     zTable.index_columnc             C   s  |dkrdt | j }| j||||d}|jdkrJt | dkrJtdn|jdksb|jd dkrt | dkrt | ft|dddd  }t|tjrtj	||d	d
}nt|t
r|jtj	|d	d
}t|}|jj}t | jdkrt |t | krtd|r>|}d}	x*|| jkr4|d t|	 }|	d7 }	qW ||j_| | || j|< |dk	r| j|d }
x|
D ]}| jj|d	d qpW dS )a  
        Add a new column to the table using ``col`` as input.  If ``index``
        is supplied then insert column before ``index`` position
        in the list of columns, otherwise append column to the end
        of the list.

        The ``col`` input can be any data object which is acceptable as a
        `~astropy.table.Table` column object or can be converted.  This includes
        mixin columns and scalar or length=1 objects which get broadcast to match
        the table length.

        To add several columns at once use ``add_columns()`` or simply call
        ``add_column()`` for each one.  There is very little performance difference
        in the two approaches.

        Parameters
        ----------
        col : object
            Data object for the new column
        index : int or None
            Insert column before this position or at end (default).
        name : str
            Column name
        rename_duplicate : bool
            Uniquify column name if it already exist. Default is False.
        copy : bool
            Make a copy of the new column. Default is True.
        default_name : str or None
            Name to use if both ``name`` and ``col.info.name`` are not available.
            Defaults to ``col{number_of_columns}``.

        Examples
        --------
        Create a table with two columns 'a' and 'b', then create a third column 'c'
        and append it to the end of the table::

            >>> t = Table([[1, 2], [0.1, 0.2]], names=('a', 'b'))
            >>> col_c = Column(name='c', data=['x', 'y'])
            >>> t.add_column(col_c)
            >>> print(t)
             a   b   c
            --- --- ---
              1 0.1   x
              2 0.2   y

        Add column 'd' at position 1. Note that the column is inserted
        before the given index::

            >>> t.add_column(['a', 'b'], name='d', index=1)
            >>> print(t)
             a   d   b   c
            --- --- --- ---
              1   a 0.1   x
              2   b 0.2   y

        Add second column named 'b' with rename_duplicate::

            >>> t = Table([[1, 2], [0.1, 0.2]], names=('a', 'b'))
            >>> t.add_column(1.1, name='b', rename_duplicate=True)
            >>> print(t)
             a   b  b_1
            --- --- ---
              1 0.1 1.1
              2 0.2 1.1

        Add an unnamed column or mixin object in the table using a default name
        or by specifying an explicit name with ``name``. Name can also be overridden::

            >>> t = Table([[1, 2], [0.1, 0.2]], names=('a', 'b'))
            >>> t.add_column(['a', 'b'])
            >>> t.add_column(col_c, name='d')
            >>> print(t)
             a   b  col2  d
            --- --- ---- ---
              1 0.1    a   x
              2 0.2    b   y
        Nr;   )r:   r   r   r3   r   z2Empty table cannot have column set to scalar valuer   r6   T)r6   Zsubokz Inconsistent data column lengths_r  )last)r   r   r   r6   r   r>   r=   rZ   r]   Zbroadcast_tor   _applyr"   r7   r:   rc   rW   r  r   move_to_end)rP   r;   r   r:   rename_duplicater   r   Z	new_shape	orig_namerS   Z
move_namesZ	move_namer3   r3   r4   rT    s>    O

$






zTable.add_columnc          	      s   |dkrt  jgt | }nt |t |kr6td|dkrLdt | }nt |t |krdtd fddtt |D }x<tt|D ]*} j|| || || || ||d qW dS )aY  
        Add a list of new columns the table using ``cols`` data objects.  If a
        corresponding list of ``indexes`` is supplied then insert column
        before each ``index`` position in the *original* list of columns,
        otherwise append columns to the end of the list.

        The ``cols`` input can include any data objects which are acceptable as
        `~astropy.table.Table` column objects or can be converted.  This includes
        mixin columns and scalar or length=1 objects which get broadcast to match
        the table length.

        From a performance perspective there is little difference between calling
        this method once or looping over the new columns and calling ``add_column()``
        for each column.

        Parameters
        ----------
        cols : list of object
            List of data objects for the new columns
        indexes : list of int or None
            Insert column before this position or at end (default).
        names : list of str
            Column names
        copy : bool
            Make a copy of the new columns. Default is True.
        rename_duplicate : bool
            Uniquify new column names if they duplicate the existing ones.
            Default is False.


        Examples
        --------
        Create a table with two columns 'a' and 'b', then create columns 'c' and 'd'
        and append them to the end of the table::

            >>> t = Table([[1, 2], [0.1, 0.2]], names=('a', 'b'))
            >>> col_c = Column(name='c', data=['x', 'y'])
            >>> col_d = Column(name='d', data=['u', 'v'])
            >>> t.add_columns([col_c, col_d])
            >>> print(t)
             a   b   c   d
            --- --- --- ---
              1 0.1   x   u
              2 0.2   y   v

        Add column 'c' at position 0 and column 'd' at position 1. Note that
        the columns are inserted before the given position::

            >>> t = Table([[1, 2], [0.1, 0.2]], names=('a', 'b'))
            >>> t.add_columns([['x', 'y'], ['u', 'v']], names=['c', 'd'],
            ...               indexes=[0, 1])
            >>> print(t)
             c   a   d   b
            --- --- --- ---
              x   1   u 0.1
              y   2   v 0.2

        Add second column 'b' and column 'c' with ``rename_duplicate``::

            >>> t = Table([[1, 2], [0.1, 0.2]], names=('a', 'b'))
            >>> t.add_columns([[1.1, 1.2], ['x', 'y']], names=('b', 'c'),
            ...               rename_duplicate=True)
            >>> print(t)
             a   b  b_1  c
            --- --- --- ---
              1 0.1 1.1  x
              2 0.2 1.2  y

        Add unnamed columns or mixin objects in the table using default names
        or by specifying explicit names with ``names``. Names can also be overridden::

            >>> t = Table()
            >>> col_b = Column(name='b', data=['u', 'v'])
            >>> t.add_columns([[1, 2], col_b])
            >>> t.add_columns([[3, 4], col_b], names=['c', 'd'])
            >>> print(t)
            col0  b   c   d
            ---- --- --- ---
               1   u   3   u
               2   v   4   v
        Nz+Number of indexes must match number of cols)Nz)Number of names must match number of colsc                s    g | ]}d |t  j  qS )r;   )r   r   )rT   r   )rP   r3   r4   rV     s   z%Table.add_columns.<locals>.<listcomp>)r   r:   r   rj  r   )r   r   rc   r   reversedrZ   argsortrT  )rP   rQ   r   rH   r   rj  r   r   r3   )rP   r4   add_columns  s    R
zTable.add_columnsc             C   sX  t j}d|kr&|| jkr&t| | }|| jkr8| | }| || d|krdtjd| dtdd d|kry,t	|j
|jrd|}tj|tdd W n tk
r   Y nX d|krt| | }||krd	|}tj|tdd d
|krTg }| | }	x4tjD ]*}
t|j|
t|	j|
kr||
 qW |rTd||}tj|tdd dS )zY
        Same as replace_column but issues warnings under various circumstances.
        refcountalwayszreplaced column 'rg      )
stacklevelr`   zureplaced column '{}' which looks like an array slice. The new column no longer shares memory with the original array.zHreplaced column '{}' and the number of references to the column changed.
attributesz6replaced column '{}' and column attributes {} changed.N)r-   Zreplace_warningsr   sysgetrefcountreplace_columnwarningswarnr.   r=   baser?   rb   rb  r   
attr_namesr>   r7   rM   )rP   r:   r;   warnsro  Zold_colmsgZnew_refcountZchanged_attrsnew_colr   r3   r3   r4   rU  	  sB    


zTable._replace_column_warningsc             C   s   || j krtd| d| | jjr.td| j|||d}| | t| jdkrrt|t| | krrtd| jj||dd d	S )
a  
        Replace column ``name`` with the new ``col`` object.

        The behavior of ``copy`` for Column objects is:
        - copy=True: new class instance with a copy of data and deep copy of meta
        - copy=False: new class instance with same data and a key-only copy of meta

        For mixin columns:
        - copy=True: new class instance with copy of data and deep copy of meta
        - copy=False: original instance (no copy at all)

        Parameters
        ----------
        name : str
            Name of column to replace
        col : `~astropy.table.Column` or `~numpy.ndarray` or sequence
            New column object to replace the existing column.
        copy : bool
            Make copy of the input ``col``, default=True

        Examples
        --------
        Replace column 'a' with a float version of itself::

            >>> t = Table([[1, 2, 3], [0.1, 0.2, 0.3]], names=('a', 'b'))
            >>> float_a = t['a'].astype(float)
            >>> t.replace_column('a', float_a)
        zcolumn name z is not in the tablez#cannot replace a table index column)r:   r   r   z,length of new column must match table lengthT)rf   N)	r   rc   r7   r   r   r  r   r   rd   )rP   r:   r;   r   r3   r3   r4   rv  >	  s    

"zTable.replace_columnc             C   s&   t |ttjfstd| | dS )a  
        Remove a row from the table.

        Parameters
        ----------
        index : int
            Index of row to remove

        Examples
        --------
        Create a table with three columns 'a', 'b' and 'c'::

            >>> t = Table([[1, 2, 3], [0.1, 0.2, 0.3], ['x', 'y', 'z']],
            ...           names=('a', 'b', 'c'))
            >>> print(t)
             a   b   c
            --- --- ---
              1 0.1   x
              2 0.2   y
              3 0.3   z

        Remove row 1 from the table::

            >>> t.remove_row(1)
            >>> print(t)
             a   b   c
            --- --- ---
              1 0.1   x
              3 0.3   z

        To remove several rows at the same time use remove_rows.
        zRow index must be an integerN)r=   rY   rZ   r[   r   r]  )rP   r   r3   r3   r4   rZ  k	  s    "zTable.remove_rowc             C   s   x| j D ]}|| qW tjt| td}d||< |  }x.| j D ] \}}|| }| |j	_
|||< qHW | | t| dr| `dS )at  
        Remove rows from the table.

        Parameters
        ----------
        row_specifier : slice or int or array of int
            Specification for rows to remove

        Examples
        --------
        Create a table with three columns 'a', 'b' and 'c'::

            >>> t = Table([[1, 2, 3], [0.1, 0.2, 0.3], ['x', 'y', 'z']],
            ...           names=('a', 'b', 'c'))
            >>> print(t)
             a   b   c
            --- --- ---
              1 0.1   x
              2 0.2   y
              3 0.3   z

        Remove rows 0 and 2 from the table::

            >>> t.remove_rows([0, 2])
            >>> print(t)
             a   b   c
            --- --- ---
              2 0.2   y


        Note that there are no warnings if the slice operator extends
        outside the data::

            >>> t = Table([[1, 2, 3], [0.1, 0.2, 0.3], ['x', 'y', 'z']],
            ...           names=('a', 'b', 'c'))
            >>> t.remove_rows(slice(10, 20, 1))
            >>> print(t)
             a   b   c
            --- --- ---
              1 0.1   x
              2 0.2   y
              3 0.3   z
        )r8   FrQ  N)r   r]  rZ   Zonesr   boolrK   r   r   r7   rq   _replace_colsr9   rQ  )rP   Zrow_specifierr   Z	keep_maskr   r:   r;   r  r3   r3   r4   r]  	  s    -

zTable.remove_rowsc                sX   t |dkr j}n&x$|D ]}| jkrt| dqW  fdd|D }t| }|S )a}  
        Iterate over rows of table returning a tuple of values for each row.

        This method is especially useful when only a subset of columns are needed.

        The ``iterrows`` method can be substantially faster than using the standard
        Table row iteration (e.g. ``for row in tbl:``), since that returns a new
        ``~astropy.table.Row`` object for each row and accessing a column in that
        row (e.g. ``row['col0']``) is slower than tuple access.

        Parameters
        ----------
        names : list
            List of column names (default to all columns if no names provided)

        Returns
        -------
        rows : iterable
            Iterator returns tuples of row values

        Examples
        --------
        Create a table with three columns 'a', 'b' and 'c'::

            >>> t = Table({'a': [1, 2, 3],
            ...            'b': [1.0, 2.5, 3.0],
            ...            'c': ['x', 'y', 'z']})

        To iterate row-wise using column names::

            >>> for a, c in t.iterrows('a', 'c'):
            ...     print(a, c)
            1 x
            2 y
            3 z

        r   z is not a valid column namec             3   s   | ]} | V  qd S )Nr3   )rT   r:   )rP   r3   r4   rh   	  s    z!Table.iterrows.<locals>.<genexpr>)r   r   rc   rv   )rP   rH   r:   rQ   r   r3   )rP   r4   iterrows	  s    &

zTable.iterrowsc             C   s   |  |g dS )aR  
        Remove a column from the table.

        This can also be done with::

          del table[name]

        Parameters
        ----------
        name : str
            Name of column to remove

        Examples
        --------
        Create a table with three columns 'a', 'b' and 'c'::

            >>> t = Table([[1, 2, 3], [0.1, 0.2, 0.3], ['x', 'y', 'z']],
            ...           names=('a', 'b', 'c'))
            >>> print(t)
             a   b   c
            --- --- ---
              1 0.1   x
              2 0.2   y
              3 0.3   z

        Remove column 'b' from the table::

            >>> t.remove_column('b')
            >>> print(t)
             a   c
            --- ---
              1   x
              2   y
              3   z

        To remove several columns at the same time use remove_columns.
        N)r[  )rP   r:   r3   r3   r4   rY  
  s    'zTable.remove_columnc             C   sV   t |tr|g}x&|D ]}|| jkrtd| dqW x|D ]}| j| q>W dS )a  
        Remove several columns from the table.

        Parameters
        ----------
        names : list
            A list containing the names of the columns to remove

        Examples
        --------
        Create a table with three columns 'a', 'b' and 'c'::

            >>> t = Table([[1, 2, 3], [0.1, 0.2, 0.3], ['x', 'y', 'z']],
            ...     names=('a', 'b', 'c'))
            >>> print(t)
             a   b   c
            --- --- ---
              1 0.1   x
              2 0.2   y
              3 0.3   z

        Remove columns 'b' and 'c' from the table::

            >>> t.remove_columns(['b', 'c'])
            >>> print(t)
             a
            ---
              1
              2
              3

        Specifying only a single column also works. Remove column 'b' from the table::

            >>> t = Table([[1, 2, 3], [0.1, 0.2, 0.3], ['x', 'y', 'z']],
            ...     names=('a', 'b', 'c'))
            >>> t.remove_columns('b')
            >>> print(t)
             a   c
            --- ---
              1   x
              2   y
              3   z

        This gives the same as using remove_column.
        zColumn z does not existN)r=   rW   r   rp   r   )rP   rH   r:   r3   r3   r4   r[  *
  s    .



zTable.remove_columnsc          
   C   s   x|   D ]}|jj|kr
y|j||d}W nj ttfk
r   |||d}x@|jj|jj t	dg D ]"}t
t|j|}t|j|| qlW Y nX || |j< q
W dS )z
        Convert string-like columns to/from bytestring and unicode (internal only).

        Parameters
        ----------
        in_kind : str
            Input dtype.kind
        out_kind : str
            Output dtype.kind
        )r8   zutf-8r8   N)r   r8   r^   r?   UnicodeEncodeErrorUnicodeDecodeErrorr7   rz  Z_attrs_no_copyrC   r   r>   r   r:   )rP   Zin_kindZout_kindZencode_decode_funcr;   r  r   re   r3   r3   r4   _convert_string_dtypeb
  s     zTable._convert_string_dtypec             C   s   |  ddtjj dS )am  
        Convert bytestring columns (dtype.kind='S') to unicode (dtype.kind='U')
        using UTF-8 encoding.

        Internally this changes string columns to represent each character
        in the string with a 4-byte UCS-4 equivalent, so it is inefficient
        for memory but allows scripts to manipulate string arrays with
        natural syntax.
        SUN)r  rZ   chardecode)rP   r3   r3   r4   convert_bytestring_to_unicode
  s    
z#Table.convert_bytestring_to_unicodec             C   s   |  ddtjj dS )z
        Convert unicode columns (dtype.kind='U') to bytestring (dtype.kind='S')
        using UTF-8 encoding.

        When exporting a unicode string array to a file, it may be desirable
        to encode unicode columns as bytestrings.
        r  r  N)r  rZ   r  r  )rP   r3   r3   r4   convert_unicode_to_bytestring
  s    z#Table.convert_unicode_to_bytestringc             C   s^   t |tr|g}x&|D ]}|| jkrtd| dqW tt|  t| }| | dS )a  
        Keep only the columns specified (remove the others).

        Parameters
        ----------
        names : list
            A list containing the names of the columns to keep. All other
            columns will be removed.

        Examples
        --------
        Create a table with three columns 'a', 'b' and 'c'::

            >>> t = Table([[1, 2, 3],[0.1, 0.2, 0.3],['x', 'y', 'z']],
            ...           names=('a', 'b', 'c'))
            >>> print(t)
             a   b   c
            --- --- ---
              1 0.1   x
              2 0.2   y
              3 0.3   z

        Specifying only a single column name keeps only this column.
        Keep only column 'a' of the table::

            >>> t.keep_columns('a')
            >>> print(t)
             a
            ---
              1
              2
              3

        Specifying a list of column names is keeps is also possible.
        Keep columns 'a' and 'c' of the table::

            >>> t = Table([[1, 2, 3],[0.1, 0.2, 0.3],['x', 'y', 'z']],
            ...           names=('a', 'b', 'c'))
            >>> t.keep_columns(['a', 'c'])
            >>> print(t)
             a   c
            --- ---
              1   x
              2   y
              3   z
        zColumn z does not existN)r=   rW   r   rp   rF   rC   rk   r[  )rP   rH   r:   r   r3   r3   r4   keep_columns
  s    0


zTable.keep_columnsc             C   s.   ||   krtd| d|| j| j_dS )ag  
        Rename a column.

        This can also be done directly with by setting the ``name`` attribute
        for a column::

          table[name].name = new_name

        TODO: this won't work for mixins

        Parameters
        ----------
        name : str
            The current name of the column.
        new_name : str
            The new name for the column

        Examples
        --------
        Create a table with three columns 'a', 'b' and 'c'::

            >>> t = Table([[1,2],[3,4],[5,6]], names=('a','b','c'))
            >>> print(t)
             a   b   c
            --- --- ---
              1   3   5
              2   4   6

        Renaming column 'a' to 'aa'::

            >>> t.rename_column('a' , 'aa')
            >>> print(t)
             aa  b   c
            --- --- ---
              1   3   5
              2   4   6
        zColumn z does not existN)rk   rp   r   r7   r:   )rP   r:   rw   r3   r3   r4   rename_column
  s    'zTable.rename_columnc             C   sd   |  |std|  |s$tdt|t|kr<tdx"t||D ]\}}| || qHW dS )a?  
        Rename multiple columns.

        Parameters
        ----------
        names : list, tuple
            A list or tuple of existing column names.
        new_names : list, tuple
            A list or tuple of new column names.

        Examples
        --------
        Create a table with three columns 'a', 'b', 'c'::

            >>> t = Table([[1,2],[3,4],[5,6]], names=('a','b','c'))
            >>> print(t)
              a   b   c
             --- --- ---
              1   3   5
              2   4   6

        Renaming columns 'a' to 'aa' and 'b' to 'bb'::

            >>> names = ('a','b')
            >>> new_names = ('aa','bb')
            >>> t.rename_columns(names, new_names)
            >>> print(t)
             aa  bb   c
            --- --- ---
              1   3   5
              2   4   6
        z7input 'names' must be a tuple or a list of column namesz;input 'new_names' must be a tuple or a list of column nameszDinput 'names' and 'new_names' list arguments must be the same lengthN)rM  r   r   rc   rv   r  )rP   rH   rx   r:   rw   r3   r3   r4   rename_columns
  s    "

zTable.rename_columnsc             C   s   yt |t |kstW n tk
r4   tdY nX g }| j}y:x4t||D ]&\}}||| |  ||| |< qNW W nB tk
r   x*t||d d D ]\}}||| |< qW  Y nX d S )Nzcright hand side must be a sequence of values with the same length as the number of selected columnsr  )r   AssertionErrorr   rc   r   rv   rM   )rP   r)  r   rS  Z	orig_valsrQ   r:   r   r3   r3   r4   rV  +  s    zTable._set_rowc             C   s   |  t| || dS )a  Add a new row to the end of the table.

        The ``vals`` argument can be:

        sequence (e.g. tuple or list)
            Column values in the same order as table columns.
        mapping (e.g. dict)
            Keys corresponding to column names.  Missing values will be
            filled with np.zeros for the column dtype.
        `None`
            All values filled with np.zeros for the column dtype.

        This method requires that the Table object "owns" the underlying array
        data.  In particular one cannot add a row to a Table that was
        initialized with copy=False from an existing array.

        The ``mask`` attribute should give (if desired) the mask for the
        values. The type of the mask should match that of the values, i.e. if
        ``vals`` is an iterable, then ``mask`` should also be an iterable
        with the same length, and if ``vals`` is a mapping, then ``mask``
        should be a dictionary.

        Parameters
        ----------
        vals : tuple, list, dict or None
            Use the specified values in the new row
        mask : tuple, list, dict or None
            Use the specified mask values in the new row

        Examples
        --------
        Create a table with three columns 'a', 'b' and 'c'::

           >>> t = Table([[1,2],[4,5],[7,8]], names=('a','b','c'))
           >>> print(t)
            a   b   c
           --- --- ---
             1   4   7
             2   5   8

        Adding a new row with entries '3' in 'a', '6' in 'b' and '9' in 'c'::

           >>> t.add_row([3,6,9])
           >>> print(t)
             a   b   c
             --- --- ---
             1   4   7
             2   5   8
             3   6   9
        N)
insert_rowr   )rP   rS  r   r3   r3   r4   add_row@  s    3zTable.add_rowc          
      sj  | j  t| }|| k s ||kr0td|||dk r@||7 }dd }||sZ|dkrf|dk	rr||srtd|dk	rt| t| krtd|rt fdd	|D rtd
g }g }x D ]}|r||kr|	||  |	|dkrdn||  q| | }	t
|	drJ|	tjd|	jd |	| joD|dk	 qtd| dqW |}|}t|r|dk	rt|r||rtdt| jt|krtd|dk	rt| jt|krtdndgt| j }ntd|  }
yxt | j ||D ]\}}	}}|rht|	trht|	tsht| j| jrV| jn| j}||	dd}	|	j||dd}t||d krtd||t||d | |j_|rt
|drtjj||< ntd|	jj||
|< qW x$| jD ]}|||| j  qW W n4 t k
rJ } ztd||W dd}~X Y nX | !|
 t
| drf| `"dS )a  Add a new row before the given ``index`` position in the table.

        The ``vals`` argument can be:

        sequence (e.g. tuple or list)
            Column values in the same order as table columns.
        mapping (e.g. dict)
            Keys corresponding to column names.  Missing values will be
            filled with np.zeros for the column dtype.
        `None`
            All values filled with np.zeros for the column dtype.

        The ``mask`` attribute should give (if desired) the mask for the
        values. The type of the mask should match that of the values, i.e. if
        ``vals`` is an iterable, then ``mask`` should also be an iterable
        with the same length, and if ``vals`` is a mapping, then ``mask``
        should be a dictionary.

        Parameters
        ----------
        vals : tuple, list, dict or None
            Use the specified values in the new row
        mask : tuple, list, dict or None
            Use the specified mask values in the new row
        z2Index {} is out of bounds for table with length {}r   c                s   d}t  fdd|D S )z9Minimal checker for mapping (dict-like) interface for obj)rX   rd  __iter__rk   r\   r   c             3   s   | ]}t  |V  qd S )N)r9   )rT   r   )r@   r3   r4   rh     s    z8Table.insert_row.<locals>._is_mapping.<locals>.<genexpr>)r   )r@   attrsr3   )r@   r4   _is_mapping  s    z%Table.insert_row.<locals>._is_mappingNz&Mismatch between type of vals and maskz&keys in mask should match keys in valsc             3   s   | ]}| kV  qd S )Nr3   )rT   r:   )r   r3   r4   rh     s    z#Table.insert_row.<locals>.<genexpr>z+Keys in vals must all be valid column namesFr8   r3   )r6   r8   z#Value must be supplied for column 'rg   z+Mismatch between number of vals and columnsz,Mismatch between number of masks and columnsz+Vals must be an iterable or mapping or None)r   )axisr   zGIncorrect length for column {} after inserting {} (expected {}, got {})r   zGmask was supplied for column '{}' but it does not support masked valuesz<Unable to insert row because of exception in column '{}':
{}rQ  )#r   r   ra   rb   r   rC   rk   rc   r  rM   r9   rZ   zerosr8   r   r   r   rK   rv   r\   r=   r   r   r   r   insertr7   rq   r   r:   r   r  r   r  rQ  )rP   r   rS  r   Nr  Z	vals_listZ	mask_listr:   r;   r   r   Zmask_r   r  Ztable_indexerrr3   )r   r4   r  u  s    
 



"
zTable.insert_rowc             C   sh   x\t | j | D ]D\}}g |j_x2|jjD ]&}||j||jj< |jj| q0W qW || _d S )N)rv   r   r\   r7   r   r   r:   rM   )rP   r   r;   r}  r   r3   r3   r4   r    s    zTable._replace_colsc             C   s   t |tr|g}|dk	rPt| |d}|dk	rPt| }|rL|ddd S |S i }|rt|dkrz||d< | j|d}q| |d  }n|  }|r||d< tj|f|}|r|ddd S |S )a  
        Return the indices which would sort the table according to one or
        more key columns.  This simply calls the `numpy.argsort` function on
        the table with the ``order`` parameter set to ``keys``.

        Parameters
        ----------
        keys : str or list of str
            The column name(s) to order the table by
        kind : {'quicksort', 'mergesort', 'heapsort'}, optional
            Sorting algorithm.
        reverse : bool
            Sort in reverse order (default=False)

        Returns
        -------
        index_array : ndarray, int
            Array of indices that sorts the table by the specified key
            column(s).
        N)rH   r  r   orderr   r^   )	r=   rW   r)   rZ   r\  Zsorted_datar   r   rm  )rP   rk   r^   reverser   r)  r   r   r3   r3   r4   rm    s$    
zTable.argsortc          
   C   s   |dkr,| j stddd | j d jD }t|tr<|g}| |}|rX|ddd }| d^ xV| j D ]H\}}|j|dd}y||dd< W qp t	k
r   || |j
j< Y qpX qpW W dQ R X dS )	a  
        Sort the table according to one or more keys. This operates
        on the existing table and does not return a new table.

        Parameters
        ----------
        keys : str or list of str
            The key(s) to order the table by. If None, use the
            primary index of the Table.

        reverse : bool
            Sort in reverse order (default=False)

        Examples
        --------
        Create a table with 3 columns::

            >>> t = Table([['Max', 'Jo', 'John'], ['Miller', 'Miller', 'Jackson'],
            ...            [12, 15, 18]], names=('firstname', 'name', 'tel'))
            >>> print(t)
            firstname   name  tel
            --------- ------- ---
                  Max  Miller  12
                   Jo  Miller  15
                 John Jackson  18

        Sorting according to standard sorting rules, first 'name' then 'firstname'::

            >>> t.sort(['name', 'firstname'])
            >>> print(t)
            firstname   name  tel
            --------- ------- ---
                 John Jackson  18
                   Jo  Miller  15
                  Max  Miller  12

        Sorting according to standard sorting rules, first 'firstname' then 'tel',
        in reverse order::

            >>> t.sort(['firstname', 'tel'], reverse=True)
            >>> print(t)
            firstname   name  tel
            --------- ------- ---
                  Max  Miller  12
                 John Jackson  18
                   Jo  Miller  15
        Nz/Table sort requires input keys or a table indexc             S   s   g | ]}|j jqS r3   )r7   r:   )rT   rU   r3   r3   r4   rV   t  s    zTable.sort.<locals>.<listcomp>r   r  freeze)r  )r   rc   r   r=   rW   rm  r   r   Ztaker   r7   r:   )rP   rk   r  r   r:   r;   r}  r3   r3   r4   sortA  s     0

z
Table.sortc          	   C   sp   xR| j  D ]D}|ddd }y||dd< W q tk
rN   || |jj< Y qX qW x| jD ]}|  q\W dS )a)  
        Reverse the row order of table rows.  The table is reversed
        in place and there are no function arguments.

        Examples
        --------
        Create a table with three columns::

            >>> t = Table([['Max', 'Jo', 'John'], ['Miller','Miller','Jackson'],
            ...         [12,15,18]], names=('firstname','name','tel'))
            >>> print(t)
            firstname   name  tel
            --------- ------- ---
                  Max  Miller  12
                   Jo  Miller  15
                 John Jackson  18

        Reversing order::

            >>> t.reverse()
            >>> print(t)
            firstname   name  tel
            --------- ------- ---
                 John Jackson  18
                   Jo  Miller  15
                  Max  Miller  12
        Nr  )r   r\   r   r7   r:   r   r  )rP   r;   r}  r   r3   r3   r4   r    s    zTable.reverser   c          	   C   s   t |tr| }| }n$t |tr8t|}| j}ntdxnt	||D ]`\}}| j
| }t|jjtjrLytj|||d W qL tk
r   tj||d|d< Y qLX qLW dS )a  
        Round numeric columns in-place to the specified number of decimals.
        Non-numeric columns will be ignored.

        Examples
        --------
        Create three columns with different types:

            >>> t = Table([[1, 4, 5], [-25.55, 12.123, 85],
            ...     ['a', 'b', 'c']], names=('a', 'b', 'c'))
            >>> print(t)
             a    b     c
            --- ------ ---
              1 -25.55   a
              4 12.123   b
              5   85.0   c

        Round them all to 0:

            >>> t.round(0)
            >>> print(t)
             a    b    c
            --- ----- ---
              1 -26.0   a
              4  12.0   b
              5  85.0   c

        Round column 'a' to -1 decimal:

            >>> t.round({'a':-1})
            >>> print(t)
             a    b    c
            --- ----- ---
              0 -26.0   a
              0  12.0   b
              0  85.0   c

        Parameters
        ----------
        decimals: int, dict
            Number of decimals to round the columns to. If a dict is given,
            the columns will be rounded to the number specified as the value.
            If a certain column is not in the dict given, it will remain the
            same.
        z,'decimals' argument must be an int or a dict)decimalsr   )r  r3   N)r=   rD   r\   rk   rY   rW  rX  r   rc   rv   r   rZ   Z
issubdtyper7   r8   numberZaroundr   )rP   r  Zdecimal_valuesZcolumn_namesr   decimalr;   r3   r3   r4   round  s    .




zTable.roundc             C   s6   | j | |d}t| dr2tj|| jj| jjd|_|S )a;  
        Return a copy of the table.

        Parameters
        ----------
        copy_data : bool
            If `True` (the default), copy the underlying data array.
            Otherwise, use the same data array. The ``meta`` is always
            deepcopied regardless of the value for ``copy_data``.
        )r   rQ  )r   rk   )r?   r9   r   rN  rQ  rO  rP  )rP   Z	copy_datar   r3   r3   r4   r     s
    
z
Table.copyc             C   s
   |  dS )NT)r   )rP   memor3   r3   r4   __deepcopy__  s    zTable.__deepcopy__c             C   s
   |  dS )NF)r   )rP   r3   r3   r4   __copy__  s    zTable.__copy__c                s   t  |S )N)rN   __lt__)rP   other)r?   r3   r4   r    s    zTable.__lt__c                s   t  |S )N)rN   __gt__)rP   r  )r?   r3   r4   r    s    zTable.__gt__c                s   t  |S )N)rN   __le__)rP   r  )r?   r3   r4   r    s    zTable.__le__c                s   t  |S )N)rN   __ge__)rP   r  )r?   r3   r4   r    s    zTable.__ge__c             C   s
   |  |S )N)_rows_equal)rP   r  r3   r3   r4   __eq__   s    zTable.__eq__c             C   s   |  | S )N)r  )rP   r  r3   r3   r4   __ne__#  s    zTable.__ne__c             C   s   t |tr| }| jrjt |tjjr4|  |k}qtjddd | jj	D d}|  j
|k| j|k@ }nPt |tjjrtjddd |jj	D d}|  |j
k|j|k@ }n|  |k}|S )a  
        Row-wise comparison of table with any other object.

        This is actual implementation for __eq__.

        Returns a 1-D boolean numpy array showing result of row-wise comparison.
        This is the same as the ``==`` comparison for tables.

        Parameters
        ----------
        other : Table or DataFrame or ndarray
             An object to compare with table

        Examples
        --------
        Comparing one Table with other::

            >>> t1 = Table([[1,2],[4,5],[7,8]], names=('a','b','c'))
            >>> t2 = Table([[1,2],[4,5],[7,8]], names=('a','b','c'))
            >>> t1._rows_equal(t2)
            array([ True,  True])

        r   c             S   s   g | ]}|t fqS r3   )r~  )rT   nr3   r3   r4   rV   H  s    z%Table._rows_equal.<locals>.<listcomp>)r8   c             S   s   g | ]}|t fqS r3   )r~  )rT   r  r3   r3   r4   rV   N  s    )r=   r   r   r   rZ   r   r   r  r8   rH   r   r   )rP   r  resultZ
false_maskr3   r3   r4   r  &  s    
zTable._rows_equalc       	         s  t  tr j}nDyt dd  j}W n, tk
rT   | j} fdd|D  Y nX t| jt|krptdg }x|D ]
}y~t| |  |  tj	ddT}t
d | |  | k}|rt|d	 jtrd
t|d	 jkrt|d	 jW dQ R X W n4 tk
r4 } ztd| |W dd}~X Y nX t |tjrh|jtdkrht|t| ks~td| d| d|| q|W t||d}|S )a  
        Element-wise comparison of table with another table, list, or scalar.

        Returns a ``Table`` with the same columns containing boolean values
        showing result of comparison.

        Parameters
        ----------
        other : table-like object or list or scalar
             Object to compare with table

        Examples
        --------
        Compare one Table with other::

          >>> t1 = Table([[1, 2], [4, 5], [-7, 8]], names=('a', 'b', 'c'))
          >>> t2 = Table([[1, 2], [-4, 5], [7, 8]], names=('a', 'b', 'c'))
          >>> t1.values_equal(t2)
          <Table length=2>
           a     b     c
          bool  bool  bool
          ---- ----- -----
          True False False
          True  True  True

        F)r   c                s   i | ]
} |qS r3   r3   )rT   r:   )r  r3   r4   r   {  s    z&Table.values_equal.<locals>.<dictcomp>z1cannot compare tables with different column namesT)recordrp  r  zelementwise comparison failedNzunable to compare column r~  zcomparison for column z
 returned z( instead of the expected boolean ndarray)rH   )r=   r   r   r   rC   rc   rZ   	broadcastrw  catch_warningssimplefilterr   categoryFutureWarningrW   messager]   r8   r   r   rM   )	rP   r  rH   Zeqsr:   r{  eqr  r   r3   )r  r4   values_equalU  s:    


"zTable.values_equalc             C   s   t | dst| | _| jS )NrQ  )r9   r   rN  rQ  )rP   r3   r3   r4   r     s    
zTable.groupsc             C   s   t | |S )ax  
        Group this table by the specified ``keys``

        This effectively splits the table into groups which correspond to unique
        values of the ``keys`` grouping object.  The output is a new
        `~astropy.table.TableGroups` which contains a copy of this table but
        sorted by row according to ``keys``.

        The ``keys`` input to `group_by` can be specified in different ways:

          - String or list of strings corresponding to table column name(s)
          - Numpy array (homogeneous or structured) with same length as this table
          - `~astropy.table.Table` with same length as this table

        Parameters
        ----------
        keys : str, list of str, numpy array, or `~astropy.table.Table`
            Key grouping object

        Returns
        -------
        out : `~astropy.table.Table`
            New table with groups set
        )r   Ztable_group_by)rP   rk   r3   r3   r4   group_by  s    zTable.group_byc          	   C   s  ddl m}m} |dk	rX|dkrF| jr@t| jdkr@| jd }qXd}n|| jkrXtddd }|| }d	d
 | j D }|rtd| dt	 }x |j D ]\}	}
t
|
jddr|
||	< n|
j d||	< t|
trt|
jr|
jjdkrt|
jj}|r|dddd}|||	 |d||	< |
jj||	 jjkrtjd|	 d|
j d||	 j tdd q|
jjdkr|
ttj||	< qW i }|r||}||d< x$| D ]}t||r||_ qW ||f|}|r|j!j|j _|S )a
  
        Return a :class:`pandas.DataFrame` instance

        The index of the created DataFrame is controlled by the ``index``
        argument.  For ``index=True`` or the default ``None``, an index will be
        specified for the DataFrame if there is a primary key index on the
        Table *and* if it corresponds to a single column.  If ``index=False``
        then no DataFrame index will be specified.  If ``index`` is the name of
        a column in the table then that will be the DataFrame index.

        In addition to vanilla columns or masked columns, this supports Table
        mixin columns like Quantity, Time, or SkyCoord.  In many cases these
        objects have no analog in pandas and will be converted to a "encoded"
        representation using only Column or MaskedColumn.  The exception is
        Time or TimeDelta columns, which will be converted to the corresponding
        representation in pandas using ``np.datetime64`` or ``np.timedelta64``.
        See the example below.

        Parameters
        ----------
        index : None, bool, str
            Specify DataFrame index mode
        use_nullable_int : bool, default=True
            Convert integer MaskedColumn to pandas nullable integer type.
            If ``use_nullable_int=False`` or the pandas version does not support
            nullable integer types (version < 0.24), then the column is converted
            to float with NaN for missing elements and a warning is issued.

        Returns
        -------
        dataframe : :class:`pandas.DataFrame`
            A pandas :class:`pandas.DataFrame` instance

        Raises
        ------
        ImportError
            If pandas is not installed
        ValueError
            If the Table has multi-dimensional columns

        Examples
        --------
        Here we convert a table with a few mixins to a
        :class:`pandas.DataFrame` instance.

          >>> import pandas as pd
          >>> from astropy.table import QTable
          >>> import astropy.units as u
          >>> from astropy.time import Time, TimeDelta
          >>> from astropy.coordinates import SkyCoord

          >>> q = [1, 2] * u.m
          >>> tm = Time([1998, 2002], format='jyear')
          >>> sc = SkyCoord([5, 6], [7, 8], unit='deg')
          >>> dt = TimeDelta([3, 200] * u.s)

          >>> t = QTable([q, tm, sc, dt], names=['q', 'tm', 'sc', 'dt'])

          >>> df = t.to_pandas(index='tm')
          >>> with pd.option_context('display.max_columns', 20):
          ...     print(df)
                        q  sc.ra  sc.dec              dt
          tm
          1998-01-01  1.0    5.0     7.0 0 days 00:00:03
          2002-01-01  2.0    6.0     8.0 0 days 00:03:20

        r   )	DataFrameSeriesF)NTr   z6index must be None, False, True or a table column namec       	         s  ddl m} ddlm m}  fdd|  D }|rg }x2|  D ]&}|jjr\t|ddn|}|	| qDW | j
|dd	} x|  D ]}|jj  qW xb|D ]Z}t||r|jd
 d}td}n|j }td}|jr|||j< || |jj< qW || }|S )zEncode a Table ``tbl`` that may have mixin columns to a Table with only
            astropy Columns + appropriate meta-data to allow subsequent decoding.
            r   )	serializer   )TimeBase	TimeDeltac                s   g | ]}t | r|qS r3   )r=   )rT   r;   )r  r3   r4   rV     s    z;Table.to_pandas.<locals>._encode_mixins.<locals>.<listcomp>F)r   )r   g    eAztimedelta64[ns]ZNaT)r   r  astropy.timer  r  r   r7   r   r"   rM   r?   ru   r=   secastyperZ   Ztimedelta64
datetime64r   r   r   r:   Zrepresent_mixins_as_columns)	tblr  r  Z	time_colsZnew_colsr;   r}  ZnatZ
encode_tblr3   )r  r4   _encode_mixins  s,    





z'Table.to_pandas.<locals>._encode_mixinsc             S   s"   g | ]\}}t |jd kr|qS )r   )r   r6   )rT   r:   r;   r3   r3   r4   rV   <  s    z#Table.to_pandas.<locals>.<listcomp>zcCannot convert a table with multidimensional columns to a pandas DataFrame. Offending columns are: z
One can filter out such columns using:
names = [name for name in tbl.colnames if len(tbl[name].shape) <= 1]
tbl[names].to_pandas(...)r   Tr   )rS   urS   Ir  r  )r8   zconverted column 'z' from z to rq  )rr  )fr   r   )"Zpandasr  r  r   r   r   rc   r   r   r   r>   r8   r   byteswapr   r=   r   rZ   r  r   r^   r:   replacerw  rx  r.   r  r   r   nanr   r\   r   r7   )rP   r   Zuse_nullable_intr  r  r  r  Zbadcolsr   r:   r   Zpd_dtyper   r)  vdfr3   r3   r4   	to_pandas  sT    D
'

zTable.to_pandasc                s  t  }t j} fdd|D }dd |D }dd |D }|r jjpLd}	x|	|krfd|	 d }	qPW |d|	 |d j |dt j |dtjt	 t
d d	krd	gt	| nNttstd
t t| }
|
rtd|
  fdd|D xt||||D ]\}}}}}|jjdkrt|rt|j }tj|j|d}||  || < t||||dd||< q*|jjdkrttftjtfdd|D rd||< tdd |D }|jjdkr@ddlm} ||dd||< t|r4tjj || |< d|| _!n|jjdkrddlm"} |#d#tj$d }||dd||< t|rtjj || |< n4t|rt||||d ||< nt%|||d!||< q*W | |S )"a  
        Create a `~astropy.table.Table` from a :class:`pandas.DataFrame` instance

        In addition to converting generic numeric or string columns, this supports
        conversion of pandas Date and Time delta columns to `~astropy.time.Time`
        and `~astropy.time.TimeDelta` columns, respectively.

        Parameters
        ----------
        dataframe : :class:`pandas.DataFrame`
            A pandas :class:`pandas.DataFrame` instance
        index : bool
            Include the index column in the returned table (default=False)
        units: dict
            A dict mapping column names to to a `~astropy.units.Unit`.
            The columns will have the specified unit in the Table.

        Returns
        -------
        table : `~astropy.table.Table`
            A `~astropy.table.Table` (or subclass) instance

        Raises
        ------
        ImportError
            If pandas is not installed

        Examples
        --------
        Here we convert a :class:`pandas.DataFrame` instance
        to a `~astropy.table.QTable`.

          >>> import numpy as np
          >>> import pandas as pd
          >>> from astropy.table import QTable

          >>> time = pd.Series(['1998-01-01', '2002-01-01'], dtype='datetime64[ns]')
          >>> dt = pd.Series(np.array([1, 300], dtype='timedelta64[s]'))
          >>> df = pd.DataFrame({'time': time})
          >>> df['dt'] = dt
          >>> df['x'] = [3., 4.]
          >>> with pd.option_context('display.max_columns', 20):
          ...     print(df)
                  time              dt    x
          0 1998-01-01 0 days 00:00:01  3.0
          1 2002-01-01 0 days 00:05:00  4.0

          >>> QTable.from_pandas(df)
          <QTable length=2>
                    time            dt      x
                   object         object float64
          ----------------------- ------ -------
          1998-01-01T00:00:00.000    1.0     3.0
          2002-01-01T00:00:00.000  300.0     4.0

        c                s   g | ]} | qS r3   r3   )rT   r:   )	dataframer3   r4   rV     s    z%Table.from_pandas.<locals>.<listcomp>c             S   s   g | ]}t |qS r3   )rZ   r   )rT   r   r3   r3   r4   rV     s    c             S   s   g | ]}t | qS r3   )rZ   r   Zisnull)rT   r   r3   r3   r4   rV     s    r   rf  r   )r8   Nz*Expected a Mapping "column-name" -> "unit"z%`units` contains additional columns: c                s   g | ]}  |qS r3   )rn   )rT   r:   )r   r3   r4   rV     s    )r  rS   )r6   r8   F)r   r:   r   r   r   r5   c             3   s    | ]}t |p| kV  qd S )N)r=   )rT   rU   )r  string_typesr3   r4   rh     s    z$Table.from_pandas.<locals>.<genexpr>    c             S   s   g | ]}|qS r3   r3   )rT   rU   r3   r3   r4   rV     s    M)Timer  )rb   Zisotm)r  ztimedelta64[ns]g    eAr  )r   r:   r   r   )r   r:   r   )&r   rF   r   r   r:   r  rZ   r   r  r   r~  r=   r
   r   rC   rk   rw  rx  rv   r8   r^   r  rW   lowerr6   r   bytesr  r   r  r  r   r   rb   r  r  Zfloat64r   )rA   r  r   r   r   rH   r   ZdatasmasksZ
index_name	not_foundr:   r   r   r   r   Znp_dtyper  r  Zdata_secr3   )r  r  r  r   r4   from_pandasr  sd    ;


$zTable.from_pandas)FN)
NFNNNTNTNN)N)NF)N)TNNN)TN)FNNNTNN)NNTNFN)r  r  TNFN)NNr'  r(  r)  )	NNTNFFNNN)	r  r  TNFFNNN)NNTNF)NNFTN)NNTF)T)NN)NN)NNF)NF)r   )T)N)NT)FN)r/   r0   r1   r2   r   r   r$   r   r   rK   r   r   r*   readr+   rE  r   rr   rt   r   rO   r   r   r   propertyr   setterr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  staticmethodr   r  r   r  r  rm   r  r  r  r   r   r   r   _pprint_docsr$  r%  r&  r6  rJ  _pformat_docsr  rK  rL  rX   rd   r{   r^  r_  r   r   r   r8   r   rM  rk   r\   r   rd  re  rT  rn  rU  rv  rZ  r]  r  rY  r[  r  r  r  r  r  r  rV  r  r  r  rm  r  r  r  r   r  r  r  r  r  r  r  r  r  r  r   r  r  classmethodr  r&   r7   r}   r3   r3   )r?   r4   r     s  *

8  
 E
	
#
>
 !  

   
?L
  
   
%4% 
 
d7
-&?1)8
;,.
5
 	
9
N,
@

/K
 2 r   c                   s(   e Zd ZdZdd Z fddZ  ZS )QTablea  A class to represent tables of heterogeneous data.

    `~astropy.table.QTable` provides a class for heterogeneous tabular data
    which can be easily modified, for instance adding columns or new rows.

    The `~astropy.table.QTable` class is identical to `~astropy.table.Table`
    except that columns with an associated ``unit`` attribute are converted to
    `~astropy.units.Quantity` objects.

    See also:

    - https://docs.astropy.org/en/stable/table/
    - https://docs.astropy.org/en/stable/table/mixin_columns.html

    Parameters
    ----------
    data : numpy ndarray, dict, list, table-like object, optional
        Data to initialize table.
    masked : bool, optional
        Specify whether the table is masked.
    names : list, optional
        Specify column names.
    dtype : list, optional
        Specify column data types.
    meta : dict, optional
        Metadata associated with the table.
    copy : bool, optional
        Copy the input data. Default is True.
    rows : numpy ndarray, list of list, optional
        Row-oriented data for table instead of ``data`` argument.
    copy_indices : bool, optional
        Copy any indices in the input data. Default is True.
    **kwargs : dict, optional
        Additional keyword args when converting table-like object.

    c             C   s
   t |tS )zg
        Determine if ``col`` should be added to the table directly as
        a mixin column.
        )rB   r   )rP   r;   r3   r3   r4   r   "  s    zQTable._is_mixin_for_tablec                s   t |trt|dd d k	rt|jdt}y||j|jdd}W nH tk
r } z*td|j	j
 d|jj d|t W d d }~X Y qX t |trt|jrtd|j	j
t |j	|_	|j	j|j	_|}nt |}|S )	Nr   Z_quantity_classF)r   zcolumn z has a unit but is kept as a z6 as an attempt to convert it to Quantity failed with:
zDdropping mask in Quantity column '{}': masked Quantity not supported)r=   r   r>   r   r   r   r   rw  rx  r7   r:   r?   r/   r   r   rZ   r  r   rb   r   rN   r   )rP   r;   Zq_clsZqcolexc)r?   r3   r4   r   )  s      zQTable._convert_col_for_table)r/   r0   r1   r2   r   r   r}   r3   r3   )r?   r4   r    s   $r  )Vr   r   r   r   r   r   rt  collectionsr   r	   collections.abcr
   rw  r   r   r   rW  r   numpyrZ   r   Zastropyr   Zastropy.unitsr   r   Zastropy.utilsr   r   Zastropy.utils.consoler   Zastropy.utils.exceptionsr   Zastropy.utils.metadatar   r   Zastropy.utils.data_infor   r   r   Zastropy.utils.decoratorsr   Zastropy.io.registryr   r   r   r$  r   r   r   r   r   r    r!   r"   r#   rI   r$   Znp_utilsr%   r7   r&   r'   r(   r)   connectr*   r+   Zndarray_mixinr,   r-   Z_implementation_notesZ__doctest_skip__Z__doctest_requires__r  r  UserWarningr.   r<   rB   rJ   rK   r~   r   r   r  r3   r3   r3   r4   <module>   s   $
/ ! '                         w