B
    }dF9              	   @   s  d Z ddlZddlZddlmZmZ ddlmZ ddlm	Z	m
Z
mZ yddlmZ W n ek
rl   d	ZY nX d
ZyddlmZ W n ek
r   d	ZY nX d
ZdZdd Zdd ZefddZdd ZefddZG dd dedddddgZefddZeeddd	fdd Zefd!d"Zd#d$ Zed%dd&d=d'd(Zd)d* Zd+d, Z d-d. Z!d/d0 Z"d1d2 Z#d3d4 Z$d5d6 Z%d>d7d8Z&d9d: Z'd;d< Z(dS )?zInput/Output utilities for GW Cache files.

A cache file is a specially-formatted ASCII file that contains file paths
and associated metadata for those files, designed to make identifying
relevant data, and sieving large file lists, easier for the user.
    N)
namedtupleOrderedDict   )LIGOTimeGPS   )	FILE_LIKE	file_path	with_open)
CacheEntryFT)Cachez(Duncan Macleod <duncan.macleod@ligo.org>c             C   sT   t | }t|\}}}|\}}| r.t|}| r>t|}|||t|||fS )N)r   filename_metadata
is_integerinttype)entrypathobstagsegstartend r   Z/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/gwpy/io/cache.py_preformat_entry6   s    r   c          	   C   s8   t | \}}}}| d| d|d  dt| d| 	S )N r   )r   abs)r   r   r   r   r   r   r   r   _format_entry_lalA   s    r   c       	      C   sB   ddl m} | \}}}}}||}|t| }t||||||S )Nr   )Segment)segmentsr   float_CacheEntry)	linegpstyper   r   descr   durr   r   r   r   r   _parse_entry_lalF   s
    r%   c             C   s.   t | \}}}}| d|d  dt| dS )Nr   r   z 0 0)r   r   )r   r   r   r   r   r   r   r   _format_entry_fflN   s    r&   c       
   	   C   s   ddl m} | \}}}}}||}|t| }y$tj|ddd d \}}	W n$ tk
rv   td d ||||S X t||	||||S )Nr   )r   -)	r   r   r   osr   basenamesplit
ValueErrorr    )
r!   r"   r   r   r   r$   _r   observatorydescriptionr   r   r   _parse_entry_fflS   s    $r/   c               @   s(   e Zd ZdZdd ZeefddZdS )r    zQuick version of lal.utils.CacheEntry for internal purposes only

    Just to allow metadata handling for files that don't follow LIGO-T050017.
    c             C   s   | j S )N)r   )selfr   r   r   __str__e   s    z_CacheEntry.__str__c             C   s   t |tr|d}|  }t|dkrF|d }| t||f  S yt||dS  tt	t
fk
r } z:yt||dS  t
k
r   Y nX d| f|_ W d d }~X Y nX d S )Nzutf-8r   r   )r"   z'Cannot identify format for cache entry )
isinstancebytesdecodestripr*   lenr   r/   RuntimeError	TypeErrorr+   r%   args)clsr!   r"   partsr   excr   r   r   parseh   s    

z_CacheEntry.parseN)__name__
__module____qualname____doc__r1   classmethodr   r=   r   r   r   r   r    _   s   r    r-   r.   segmentr   c             c   s   yt j| j}W n tk
r*   d}Y nX x| D ]}ytj||dV  W q2 tk
r   | }t	|dkrt j|d |krt
|d d"}xt||dD ]
}|V  qW W dQ R X n Y q2X q2W dS )zInternal method that yields a `_CacheEntry` for each line in the file

    This method supports reading LAL- and (nested) FFL-format cache files.
    N)r"      r   r)r(   r   abspathnameAttributeErrorr    r=   r+   r*   r6   open_iter_cache)	cachefiler"   r   r!   r;   Zcache2r   r   r   r   rJ      s    

 rJ   c             C   s<   dd t | |dD }|r(t|||d}|r8|j|d |S )aB  Read a LAL- or FFL-format cache file as a list of file paths

    Parameters
    ----------
    cachefile : `str`, `pathlib.Path`, `file`
        Input file or file path to read.

    coltype : `LIGOTimeGPS`, `int`, optional
        Type for GPS times.

    sort : `callable`, optional
        A callable key function by which to sort the output list of file paths

    segment : `gwpy.segments.Segment`, optional
        A GPS `[start, stop)` interval, if given only files overlapping this
        interval will be returned.

    strict : `bool`, optional
        If `False` warn about entries that don't follow the LIGO-T050017
        standard, then skip them; if `True` all errors are raised as
        exceptions.

    Returns
    -------
    paths : `list` of `str`
        A list of file paths as read from the cache file.
    c             S   s   g | ]
}|j qS r   )r   ).0xr   r   r   
<listcomp>   s    zread_cache.<locals>.<listcomp>)r"   )rC   strict)key)rJ   sievesort)rK   coltyperR   rC   rO   cacher   r   r   
read_cache   s    $rU   c             C   s   t j| |djS )ak  Read a file path from a line in a cache file.

    Parameters
    ----------
    line : `str`, `bytes`
        Line of text to parse

    gpstype : `LIGOTimeGPS`, `int`, optional
        Type for GPS times.

    Returns
    -------
    path : `str`
       The file path.

    Raises
    ------
    ValueError
        if the line cannot be parsed successfully
    )r"   )r    r=   r   )r!   r"   r   r   r   read_cache_entry   s    rV   c              O   s   t dt t| |S )Nz/gwpy.io.cache.open_cache was renamed read_cache)warningswarnDeprecationWarningrU   )r9   kwargsr   r   r   
open_cache   s    r[   w)modeposc          	   C   s   |dkrt }n2| dkr t}n | dkr2t}ntd|xNt|| D ]@}yt||d W qL tk
r   || d	d Y qLX qLW dS )a  Write a `list` of cache entries to a file

    Parameters
    ----------
    cache : `list` of `str`
        The list of file paths to write

    fobj : `file`, `str`, `pathlib.Path`
        The open file object, or file path to write to.

    format : `str`, optional
        The format to write to, one of

        - `None` : format each entry using `str`
        - ``'lal'`` : write a LAL-format cache
        - ``'ffl'`` : write an FFL-format cache
    NZlalfflzUnrecognised cache format )file
zutf-8)
strlowerr   r&   r+   mapprintr8   writeencode)rT   Zfobjformat	formatterr!   r   r   r   write_cache   s    rj   c             C   st   t | ttjft r>yttt| tdS  t	k
r<   dS X t
rPt | trPdS tt | ttfop| opttt| S )a<  Returns `True` if ``cache`` is a readable cache file or object

    Parameters
    ----------
    cache : `str`, `file`, `list`
        Object to detect as cache

    Returns
    -------
    iscache : `bool`
        `True` if the input object is a cache, or a file in LAL cache format,
        otherwise `False`
    )rS   FT)r2   rb   r(   PathLiker   boolr6   rU   r   	Exception	HAS_CACHEr   listtupleallrd   is_cache_entry)rT   r   r   r   is_cache  s    rs   c          
   C   s>   t rt| trdS yt|  W n tttfk
r8   dS X dS )a  Returns `True` if ``path`` can be represented as a cache entry

    In practice this just tests whether the input is |LIGO-T050017|_ compliant.

    Parameters
    ----------
    path : `str`, :class:`lal.utils.CacheEntry`
        The input to test

    Returns
    -------
    isentry : `bool`
        `True` if ``path`` is an instance of `CacheEntry`, or can be parsed
        using |LIGO-T050017|_.
    TF)HAS_CACHEENTRYr2   r
   file_segmentr+   r8   rH   )r   r   r   r   rr   ,  s    rr   c          
   C   s   ddl m} tj| }y|d\}}}}W n4 tk
rb } zd|df|_ W dd}~X Y nX t|}|	ddd	 }xByt|}W n. tk
r   d|kr |	ddd	 }Y q~X P q~W |||||| fS )
a  Return metadata parsed from a filename following LIGO-T050017

    This method is lenient with regards to integers in the GPS start time of
    the file, as opposed to `gwdatafind.utils.filename_metadata`, which is
    strict.

    Parameters
    ----------
    filename : `str`
        the path name of a file

    Returns
    -------
    obs : `str`
        the observatory metadata

    tag : `str`
        the file tag

    segment : `gwpy.segments.Segment`
        the GPS ``[float, float)`` interval for this file

    Notes
    -----
    `LIGO-T050017 <https://dcc.ligo.org/LIGO-T050017>`__ declares a
    file naming convention that includes documenting the GPS start integer
    and integer duration of a file, see that document for more details.

    Examples
    --------
    >>> from gwpy.io.cache import filename_metadata
    >>> filename_metadata("A-B-0-1.txt")
    ('A', 'B', Segment(0, 1))
    >>> filename_metadata("A-B-0.456-1.345.txt")
    ("A", "B", Segment(0.456, 1.801))
    r   )r   r'   zFailed to parse z& as a LIGO-T050017-compatible filenameN.r   r   )
r   r   r(   r   r)   r*   r+   r9   r   rsplit)filenamer   rG   r   r#   r   r$   r<   r   r   r   r   G  s$    %r   c             C   s8   ddl m} y
|| jS  tk
r2   t| d S X dS )a  Return the data segment for a filename following T050017

    Parameters
    ---------
    filename : `str`, :class:`~lal.utils.CacheEntry`
        the path name of a file

    Returns
    -------
    segment : `~gwpy.segments.Segment`
        the ``[start, stop)`` GPS segment covered by the given file

    Notes
    -----
    |LIGO-T050017|_ declares a filenaming convention that includes
    documenting the GPS start integer and integer duration of a file,
    see that document for more details.
    r   )r   N)r   r   rC   rH   r   )rx   r   r   r   r   ru     s
    
ru   c              G   s<   ddl m} | }x | D ]}|dd |D  qW | S )aV  Returns the segments of data covered by entries in the cache(s).

    Parameters
    ----------
    *caches : `list`
        One or more lists of file paths
        (`str` or :class:`~lal.utils.CacheEntry`).

    Returns
    -------
    segments : `~gwpy.segments.SegmentList`
        A list of segments for when data should be available
    r   )SegmentListc             s   s   | ]}t |V  qd S )N)ru   )rL   er   r   r   	<genexpr>  s    z!cache_segments.<locals>.<genexpr>)r   ry   extendZcoalesce)cachesry   outrT   r   r   r   cache_segments  s
    
r   c              G   s   t tdd | D S )a;  Flatten a nested list of cache entries

    Parameters
    ----------
    *caches : `list`
        One or more lists of file paths
        (`str` or :class:`~lal.utils.CacheEntry`).

    Returns
    -------
    flat : `list`
        A flat `list` containing the unique set of entries across
        each input.
    c             s   s   | ]}|D ]
}|V  q
qd S )Nr   )rL   crz   r   r   r   r{     s    zflatten.<locals>.<genexpr>)ro   r   fromkeys)r}   r   r   r   flatten  s    r   c              g   s,   t |  }xt|D ]}t||dV  qW dS )aD  Separate one or more cache entry lists into time-contiguous sub-lists

    Parameters
    ----------
    *caches : `list`
        One or more lists of file paths
        (`str` or :class:`~lal.utils.CacheEntry`).

    Returns
    -------
    caches : `iter` of `list`
        an interable yielding each contiguous cache
    )rC   N)r   r   rQ   )r}   ZflatrC   r   r   r   find_contiguous  s    r   c             C   sv   t |  }xf| D ]^}yt|}W n8 tk
rX } z|r8 tt| wW dd}~X Y nX ||r|| qW |S )aV  Filter the cache to find those entries that overlap ``segment``

    Parameters
    ----------
    cache : `list`
        Input list of file paths

    segment : `~gwpy.segments.Segment`
        The ``[start, stop)`` interval to match against.

    strict : `bool`, optional
        If `True` raise all exceptions, if `False` emit warnings when
        the file segment cannot be determined.

    Warns
    -----
    UserWarning
        For any files for which the file segment cannot be determined,
        if ``strict=False`` is given; these files are excluded from the
        sieved cache.
    N)r   ru   r+   rW   rX   rb   Z
intersectsappend)rT   rC   rO   r~   rz   r   r<   r   r   r   rQ     s    


rQ   c              O   s"   ddl m} tdt || |S )Nr   )r   z7this function has been moved to gwpy.io.utils.file_path)utilsr   rW   rX   rY   )r9   rZ   r   r   r   r   	file_name  s    r   c              O   s"   ddl m} tdt || |S )Nr   )	file_listz7this function has been moved to gwpy.io.utils.file_list)r   r   rW   rX   rY   )r9   rZ   r   r   r   r   r     s    r   )N)NT))rA   r(   rW   collectionsr   r   timer   r   r   r   r	   Z	lal.utilsr
   ImportErrorrt   Zglue.lalr   rn   
__author__r   r   r%   r&   r/   r    rJ   rU   rV   r[   rj   rs   rr   r   ru   r   r   r   rQ   r   r   r   r   r   r   <module>   sV   

$*
#<
(