B
    ~df                 @   s   d Z ddlZddlmZ ddlmZ ddlmZ ddlZddl	m
Z ddlmZmZ ddlmZ d	d
lmZ d	dlmZ ddlmZmZ dZdddgZdd Zdd ZeG dd deZdS )z2Extend :mod:`astropy.table` with the `EventTable`
    N)wraps)
attrgetter)ceil)DEFAULT_URL)Tablevstack)registry   )
read_multi)	gps_types   )filter_tableparse_operatorz(Duncan Macleod <duncan.macleod@ligo.org>timeZgpsZpeakGPSc             C   s   | j d }xtj|dD ]}|d }|d  dkrNtj|| t||dd |d  dkrxtj|| t||dd |d	  dkrtj|| tj	||f dd qW | S )
Nr   )Z
data_classZFormatZReadyesF)forceZWritezAuto-identify)
__mro__r   Zget_formatslowerZregister_readerZ
get_readerZregister_writerZ
get_writerZregister_identifierZ_identifiers)clsparentrowname r   ]/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/gwpy/table/table.pyinherit_io_registrations2   s,    


r   c                s   t   fdd}|S )Nc          
      s   | d}| d}| d}|d kr6|d ks<|d ks<| jsy|  |d< W n8 tk
r } zd|jd f|_ W d d }~X Y nX |d| jd  | |d  }|d kr| |d< |d kr| |d<  | f||S )N
timecolumnstartendz%{0}, please give `timecolumn` keywordr   )	getZcolnames_get_time_column
ValueErrorformatargs
setdefaultminmax)selfr"   kwargsr   r   r   exctimes)funcr   r   wrapped_funcR   s$    


z'_rates_preprocess.<locals>.wrapped_func)r   )r*   r+   r   )r*   r   _rates_preprocessQ   s    r,   c               @   s   e Zd ZdZdd Zdd Zedd Zdd	 Zed
d Z	edde
fddZdd Zed$ddZed%ddZdd Zdd Zdd Zdd Zdd Zd d! Zd"d# ZdS )&
EventTableaK  A container for a table of events.

    This object expands the default :class:`~astropy.table.Table`
    with extra read/write formats, and methods to perform filtering,
    rate calculations, and visualisation.

    See also
    --------
    astropy.table.Table
        for details on parameters for creating an `EventTable`
    c             C   sN   |  tkrdS | | jtkr"dS yt| | d tS  tk
rH   dS X dS )aK  Return `True` if a column in this table represents 'time'

        This method checks the name of the column against a hardcoded list
        of time-like names, then checks the `dtype` of the column (or the
        first element in the column) against a hardcoded list of time-like
        dtypes (`gwpy.time.gps_types`).
        Tr   FN)r   TIME_LIKE_COLUMN_NAMESdtyper   
isinstance
IndexError)r&   r   r   r   r   _is_time_column   s    	zEventTable._is_time_columnc          
   C   s~   t t| j| j}y
|\}W n\ tk
rx   ddttt	dd}d
|}t|dkrl|dd}t|Y nX |S )a^  Return the name of the 'time' column in this table.

        This method tries the following:

        - look for a single column named 'time', 'gps', or 'peakGPS'
        - look for a single column with a GPS type (e.g. `LIGOTimeGPS`)

        So, its not foolproof.

        Raises a `ValueError` if either 0 or multiple matches are found.
        z, or z, r   zOcannot identify time column for table, no columns named {}, or with a GPS dtypez
no columnszmultiple columns)listfilterr2   columnsr    joinmapreprr.   rsplitr!   lenreplace)r&   matchesr   Z	tcolnamesmsgr   r   r   r      s    
zEventTable._get_time_columnc             O   s   t t| |f||S )a  Read data into an `EventTable`

        Parameters
        ----------
        source : `str`, `list`
            Source of data, any of the following:

            - `str` path of single data file,
            - `str` path of LAL-format cache file,
            - `list` of paths.

        *args
            other positional arguments will be passed directly to the
            underlying reader method for the given format

        format : `str`, optional
            the format of the given source files; if not given, an attempt
            will be made to automatically identify the format

        columns : `list` of `str`, optional
            the list of column names to read

        selection : `str`, or `list` of `str`, optional
            one or more column filters with which to downselect the
            returned table rows as they as read, e.g. ``'snr > 5'``;
            multiple selections should be connected by ' && ', or given as
            a `list`, e.g. ``'snr > 5 && frequency < 1000'`` or
            ``['snr > 5', 'frequency < 1000']``

        nproc : `int`, optional, default: 1
            number of CPUs to use for parallel reading of multiple files

        verbose : `bool`, optional
            print a progress bar showing read status, default: `False`

        .. note::

           Keyword arguments other than those listed here may be required
           depending on the `format`

        Returns
        -------
        table : `EventTable`

        Raises
        ------
        astropy.io.registry.IORegistryError
            if the `format` cannot be automatically identified
        IndexError
            if ``source`` is an empty list

        Notes
        -----)io_read_multir   )r   sourcer"   r'   r   r   r   read   s    7zEventTable.readc             O   s   t j| |f||S )a  Write this table to a file

        Parameters
        ----------
        target: `str`
            filename for output data file

        *args
            other positional arguments will be passed directly to the
            underlying writer method for the given format

        format : `str`, optional
            format for output data; if not given, an attempt will be made
            to automatically identify the format based on the `target`
            filename

        **kwargs
            other keyword arguments will be passed directly to the
            underlying writer method for the given format

        Raises
        ------
        astropy.io.registry.IORegistryError
            if the `format` cannot be automatically identified

        Notes
        -----)r   write)r&   targetr"   r'   r   r   r   rA      s    zEventTable.writec       
   
   O   s   yddl m} W n tk
r$   Y n,X t||rPddlm} | ||f||S ddlm} ||| }|||}t|| st| t	|ry| |S  t
k
r }	 zd| jt|	f|	_ W dd}	~	X Y nX td| j|S )	a  Fetch a table of events from a database

        Parameters
        ----------
        format : `str`, `~sqlalchemy.engine.Engine`
            the format of the remote data, see _Notes_ for a list of
            registered formats, OR an SQL database `Engine` object

        *args
            all other positional arguments are specific to the
            data format, see below for basic usage

        columns : `list` of `str`, optional
            the columns to fetch from the database table, defaults to all

        selection : `str`, or `list` of `str`, optional
            one or more column filters with which to downselect the
            returned table rows as they as read, e.g. ``'snr > 5'``;
            multiple selections should be connected by ' && ', or given as
            a `list`, e.g. ``'snr > 5 && frequency < 1000'`` or
            ``['snr > 5', 'frequency < 1000']``

        **kwargs
            all other positional arguments are specific to the
            data format, see the online documentation for more details


        Returns
        -------
        table : `EventTable`
            a table of events recovered from the remote database

        Examples
        --------
        >>> from gwpy.table import EventTable

        To download a table of all blip glitches from the Gravity Spy database:

        >>> EventTable.fetch(
        ...     'gravityspy',
        ...     'glitches',
        ...     selection=['ml_label=Blip', 'ml_confidence>0.9'],
        ... )

        To download a table from any SQL-type server

        >>> from sqlalchemy.engine import create_engine
        >>> engine = create_engine(...)
        >>> EventTable.fetch(engine, 'mytable')

        Notes
        -----r   )Enginer   )fetch)get_fetcherz,could not convert fetch() output to {0}: {1}Nz$fetch() should return a {0} instance)Zsqlalchemy.enginerC   ImportErrorr0   Zio.sqlrD   Zio.fetchrE   
issubclasstype	Exceptionr!   __name__strr"   	TypeError)
r   Zformat_r"   r'   rC   rD   rE   Zfetcheroutr(   r   r   r   rD     s*    7



zEventTable.fetchNc             K   s<   ddl m} ||f|||d|}t|| kr4|S | |S )a  Fetch events from an open-data catalogue hosted by GWOSC.

        Parameters
        ----------
        catalog : `str`
            the name of the catalog to fetch, e.g. ``'GWTC-1-confident'``

        columns : `list` of `str`, optional
            the list of column names to read

        selection : `str`, or `list` of `str`, optional
            one or more column filters with which to downselect the
            returned events as they as read, e.g. ``'mass1 < 30'``;
            multiple selections should be connected by ' && ', or given as
            a `list`, e.g. ``'mchirp < 3 && distance < 500'`` or
            ``['mchirp < 3', 'distance < 500']``

        host : `str`, optional
            the open-data host to use
        r   )fetch_catalog)r5   	selectionhost)Zio.loscrN   rH   )r   catalogr5   rO   rP   r'   rN   tabr   r   r   fetch_open_data_  s    
zEventTable.fetch_open_datac             C   s   | | S )a  Return the `Column` with the given name

        This method is provided only for compatibility with the
        :class:`ligo.lw.table.Table`.

        Parameters
        ----------
        name : `str`
            the name of the column to return

        Returns
        -------
        column : `astropy.table.Column`

        Raises
        ------
        KeyError
            if no column is found with the given name
        r   )r&   r   r   r   r   
get_column  s    zEventTable.get_columnc       	      C   s   ddl m} | | }|jjdkr.|jddd}tt|| | }t|d | | }|tj	||dd t
| ||d	d
dS )a  Calculate the rate `~gwpy.timeseries.TimeSeries` for this `Table`.

        Parameters
        ----------
        stride : `float`
            size (seconds) of each time bin

        start : `float`, `~gwpy.time.LIGOTimeGPS`, optional
            GPS start epoch of rate `~gwpy.timeseries.TimeSeries`

        end : `float`, `~gwpy.time.LIGOTimeGPS`, optional
            GPS end time of rate `~gwpy.timeseries.TimeSeries`.
            This value will be rounded up to the nearest sample if needed.

        timecolumn : `str`, optional
            name of time-column to use when binning events, attempts
            are made to guess this

        Returns
        -------
        rate : `~gwpy.timeseries.TimeSeries`
            a `TimeSeries` of events per second (Hz)

        Raises
        ------
        ValueError
            if the ``timecolumn`` cannot be guessed from the table contents
        r   )
TimeSeriesobjectZ
longdoubleF)copyr   )binsZHzz
Event rate)t0dtunitr   )gwpy.timeseriesrU   r/   r   Zastypeintr   numpyZarangeZ	histogramfloat)	r&   strider   r   r   rU   r)   ZnsampZtimebinsr   r   r   
event_rate  s    zEventTable.event_rate>=c                s   ddl m}  s tj tjfg |dkrVt d tsV fddt dd D  nt|trjt|}	n|}	| | }
| }xr D ]j}t|tr|
|d k|
|d k @ }n
|	|
|}| | j	||||d	||< d

|t|t|f|| _qW |S )a  Calculate an event rate `~gwpy.timeseries.TimeSeriesDict` over
        a number of bins.

        Parameters
        ----------
        stride : `float`
            size (seconds) of each time bin

        column : `str`
            name of column by which to bin.

        bins : `list`
            a list of `tuples <tuple>` marking containing bins, or a list of
            `floats <float>` defining bin edges against which an math operation
            is performed for each event.

        operator : `str`, `callable`
            one of:

            - ``'<'``, ``'<='``, ``'>'``, ``'>='``, ``'=='``, ``'!='``,
              for a standard mathematical operation,
            - ``'in'`` to use the list of bins as containing bin edges, or
            - a callable function that takes compares an event value
              against the bin value and returns a boolean.

            .. note::

               If ``bins`` is given as a list of tuples, this argument
               is ignored.

        start : `float`, `~gwpy.time.LIGOTimeGPS`, optional
            GPS start epoch of rate `~gwpy.timeseries.TimeSeries`.

        end : `float`, `~gwpy.time.LIGOTimeGPS`, optional
            GPS end time of rate `~gwpy.timeseries.TimeSeries`.
            This value will be rounded up to the nearest sample if needed.

        timecolumn : `str`, optional, default: ``time``
            name of time-column to use when binning events

        Returns
        -------
        rates : ~gwpy.timeseries.TimeSeriesDict`
            a dict of (bin, `~gwpy.timeseries.TimeSeries`) pairs describing a
            rate of events per second (Hz) for each of the bins.
        r   )TimeSeriesDictinc                s    g | ]\}}| |d   fqS )r   r   ).0ibin_)rX   r   r   
<listcomp>  s    z1EventTable.binned_event_rates.<locals>.<listcomp>Nr   )r   r   r    )r\   rc   r^   infr0   tuple	enumeraterK   r   ra   r6   r   )r&   r`   columnrX   operatorr   r   r   rc   Zop_funcZcoldatarM   rg   Zkeepr   )rX   r   binned_event_rates  s$    3 




"zEventTable.binned_event_ratesc             O   s$   t dt| jt | j||S )z-DEPRECATED, use `EventTable.scatter`
        zK{0}.plot was renamed {0}.scatter and will be removed in an upcoming release)warningswarnr!   rH   rJ   DeprecationWarningscatter)r&   r"   r'   r   r   r   plot  s    
zEventTable.plotc             K   s:   | dd}|dk	r | | |d< | jd| | | | f|S )a  Make a scatter plot of column ``x`` vs column ``y``.

        Parameters
        ----------
        x : `str`
            name of column defining centre point on the X-axis

        y : `str`
            name of column defining centre point on the Y-axis

        color : `str`, optional, default:`None`
            name of column by which to color markers

        **kwargs
            any other keyword arguments, see below

        Returns
        -------
        plot : `~gwpy.plot.Plot`
            the newly created figure

        See also
        --------
        matplotlib.pyplot.figure
            for documentation of keyword arguments used to create the
            figure
        matplotlib.figure.Figure.add_subplot
            for documentation of keyword arguments used to create the
            axes
        gwpy.plot.Axes.scatter
            for documentation of keyword arguments used to display the table
        colorNcrt   )pop_plot)r&   xyr'   rv   r   r   r   rt     s    !zEventTable.scatterc             K   sF   | dd}|dk	r | | |d< | jd| | | | | | | | f|S )a7  Make a tile plot of this table.

        Parameters
        ----------
        x : `str`
            name of column defining anchor point on the X-axis

        y : `str`
            name of column defining anchor point on the Y-axis

        w : `str`
            name of column defining extent on the X-axis (width)

        h : `str`
            name of column defining extent on the Y-axis (height)

        color : `str`, optional, default:`None`
            name of column by which to color markers

        **kwargs
            any other keyword arguments, see below

        Returns
        -------
        plot : `~gwpy.plot.Plot`
            the newly created figure

        See also
        --------
        matplotlib.pyplot.figure
            for documentation of keyword arguments used to create the
            figure
        matplotlib.figure.Figure.add_subplot
            for documentation of keyword arguments used to create the
            axes
        gwpy.plot.Axes.tile
            for documentation of keyword arguments used to display the table
        rv   Ntile)rx   ry   )r&   rz   r{   whr'   rv   r   r   r   r|   =  s    'zEventTable.tilec             O   s   ddl m} ddlm} ddlm} | |d jrL|dd |dd	 ||d
< |||}|	 }x~t
ttd|j|jf|d d D ]V\}	}
|
j}|d rd||
j}|
jd k	r|d|
jd7 }|	| d|	_qW |S )Nr   )rcParamsr	   )Plot)label_to_latexZfigsize)      Zxscalezauto-gpsmethodisDefault_labelztext.usetexz\texttt{{{0}}}z [{0}]Zlatex_inlineT)Z
matplotlibr   ru   r   Zplot.texr   r2   r   r#   Zgcazipr4   r   ZxaxisZyaxisr!   r[   Z	to_stringZset_label_textr   )r&   r   r"   r'   r   r   r   ru   ZaxZaxiscolr   r   r   r   ry   i  s(    



zEventTable._plotc             K   s$   ddl m} || | fddi|S )a  Generate a `HistogramPlot` of this `Table`.

        Parameters
        ----------
        column : `str`
            Name of the column over which to histogram data

        method : `str`, optional
            Name of `~matplotlib.axes.Axes` method to use to plot the
            histogram, default: ``'hist'``.

        **kwargs
            Any other keyword arguments, see below.

        Returns
        -------
        plot : `~gwpy.plot.Plot`
            The newly created figure.

        See also
        --------
        matplotlib.pyplot.figure
            for documentation of keyword arguments used to create the
            figure.
        matplotlib.figure.Figure.add_subplot
            for documentation of keyword arguments used to create the
            axes.
        gwpy.plot.Axes.hist
            for documentation of keyword arguments used to display the
            histogram, if the ``method`` keyword is given, this method
            might not actually be the one used.
        r	   )r   r   hist)ru   r   )r&   rn   r'   r   r   r   r   r     s    !zEventTable.histc             G   s   t | f| S )a  Apply one or more column slice filters to this `EventTable`

        Multiple column filters can be given, and will be applied
        concurrently

        Parameters
        ----------
        column_filter : `str`, `tuple`
            a column slice filter definition, e.g. ``'snr > 10``, or
            a filter tuple definition, e.g. ``('snr', <my_func>, <arg>)``

        Notes
        -----
        See :ref:`gwpy-table-filter` for more details on using filter tuples

        Returns
        -------
        table : `EventTable`
            a new table with only those rows matching the filters

        Examples
        --------
        To filter an existing `EventTable` (``table``) to include only
        rows with ``snr`` greater than `10`, and ``frequency`` less than
        `1000`:

        >>> table.filter('snr>10', 'frequency<1000')

        Custom operations can be defined using filter tuple definitions:

        >>> from gwpy.table.filters import in_segmentlist
        >>> table.filter(('time', in_segmentlist, segs))
        )r   )r&   Zcolumn_filtersr   r   r   r4     s    "zEventTable.filterc                s   |dkrt dt| dkr$|  S t| | }| | | }| | |  tt||kd }t|dkrv|  S t|tt|dkd d }dd |D } fdd|D }	tj|t	d}
d	|
t
|< d
|
|	< | ||
  S )a~  Cluster this `EventTable` over a given column, `index`, maximizing
        over a specified column in the table, `rank`.

        The clustering algorithm uses a pooling method to identify groups
        of points that are all separated in `index` by less than `window`.

        Each cluster of nearby points is replaced by the point in that cluster
        with the maximum value of `rank`.

        Parameters
        ----------
        index : `str`
            name of the column which is used to search for clusters

        rank : `str`
            name of the column to maximize over in each cluster

        window : `float`
            window to use when clustering data points, will raise
            ValueError if `window > 0` is not satisfied

        Returns
        -------
        table : `EventTable`
            a new table that has had the clustering algorithm applied via
            slicing of the original

        Examples
        --------
        To cluster an `EventTable` (``table``) whose `index` is
        `end_time`, `window` is `0.1`, and maximize over `snr`:

        >>> table.cluster('end_time', 'snr', 0.1)
        g        zWindow must be a positive valuer   r   c          	   S   s(   g | ] }t |t |d  d gqS )ri   r   )r^   appendarray)re   sr   r   r   rh   
  s   z&EventTable.cluster.<locals>.<listcomp>c                s   g | ]}|t  |  qS r   )r^   Zargmax)re   r   )paramr   r   rh     s    )r/   FT)r    r:   rW   r^   ZargsortwherediffsplitZ	ones_likeboolZconcatenate)r&   indexZrankZwindowZorderidxr   ZclusterpointsZsublistsZpadded_sublistsZmaxidxmaskr   )r   r   cluster  s&    #zEventTable.cluster)NNN)rb   NNN)rJ   
__module____qualname____doc__r2   r   classmethodr@   rA   rD   DEFAULT_GWOSC_URLrS   rT   r,   ra   rp   ru   rt   r|   ry   r   r4   r   r   r   r   r   r-   s   s,   9T) L&,$$r-   )r   rq   	functoolsr   ro   r   mathr   r^   Z	gwosc.apir   r   Zastropy.tabler   r   Z
astropy.ior   Zio.mpr
   r>   r   r   r4   r   r   
__author__r.   r   r,   r-   r   r   r   r   <module>   s&   "