B
    dG                 @   sD  d Z ddlmZ yddlmZ W n  ek
r@   ddlmZ Y nX ddl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ZddlZye W n ek
r   eZY nX ddlmZ ddlmZ dZd	ej ZejZeG d
d deZy ddlZG dd dej j!Z!W n& ek
r.   G dd deZ!Y nX G dd de"Z#dS )zs
This module contains bits and pieces of use when interacting with LAL and
LAL-derived code (eg. LALApps programs)
    )absolute_import)total_orderingN)urllib)segments)git_versionz"Kipp Cannon <kipp.cannon@ligo.org>z	git id %sc               @   s   e Zd ZdZd1ddZedd  ZZedd  ZZ	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d Zdd ZeZdd ZeZdd Zd d! Zd"d# ZeZd$d% ZeZd&d' Zd(d) Zd*d+ Zd,d- Z d.d/ Z!d0S )2LIGOTimeGPSa7  
	An object for storing times with nanosecond resolution.  LAL defines an
	equivalent object which is used through-out the search algorithms to
	represent times.  Many LALApps routines input and output times in a
	manner that meshes well with this object.

	Internally the time is represented as a signed integer "seconds" part
	and an unsigned integer "nanoseconds" part.  The actual time is always
	constructed by adding the nanoseconds to the seconds.  So -0.5 s is
	represented by setting seconds = -1, and nanoseconds to 500000000.
	That's the way LAL does it.
	r   c             C   sz  t |tttfs2yt|}W n   t|Y nX t |tr`t|\}}t|}||d 7 }nt |tjsVt |tj	tj
fr| drdnd}y@d|kr|d\}}t|td|  d }nd}t|}W n   td| Y nX ||7 }n\t|dr$t|d	r$||j7 }|j}n2t|d
rNt|drN||j7 }|j}nt||t|d  | _t|d | _dS )al  
		Create a LIGOTimeGPS instance.  The first parameter is the
		count of seconds, and the second (optional) parameter is the
		count of nanoseconds.  If the nanoseconds parameter is not
		supplied, it is assumed to be 0.  Either parameter can be
		a numeric type or an ASCII string.

		Example:

		>>> LIGOTimeGPS(100.5)
		LIGOTimeGPS(100, 500000000)
		>>> LIGOTimeGPS("100.5")
		LIGOTimeGPS(100, 500000000)
		>>> LIGOTimeGPS(100, 500000000)
		LIGOTimeGPS(100, 500000000)
		>>> LIGOTimeGPS(0, 100500000000)
		LIGOTimeGPS(100, 500000000)
		>>> LIGOTimeGPS(100.2, 300000000)
		LIGOTimeGPS(100, 500000000)
		>>> LIGOTimeGPS("0.000000001")
		LIGOTimeGPS(0, 1)
		>>> LIGOTimeGPS("0.0000000012")
		LIGOTimeGPS(0, 1)
		>>> LIGOTimeGPS("0.0000000018")
		LIGOTimeGPS(0, 2)
		>>> LIGOTimeGPS("-0.8")
		LIGOTimeGPS(-1, 200000000)
		>>> LIGOTimeGPS("-1.2")
		LIGOTimeGPS(-2, 800000000)
		g    eA-   .r   z%invalid literal for LIGOTimeGPS(): %s
gpsSecondsgpsNanoSecondssecondsnanosecondsi ʚ;N)
isinstancefloatintlong	TypeErrormathmodfsixinteger_typesbinary_type	text_typelstrip
startswithsplitroundhasattrr   r   r   r   _LIGOTimeGPS__seconds_LIGOTimeGPS__nanoseconds)selfr   r   nssign r%   U/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/glue/lal.py__init__\   s<    



zLIGOTimeGPS.__init__c             C   s   | j S )N)r    )r"   r%   r%   r&   <lambda>       zLIGOTimeGPS.<lambda>c             C   s   | j S )N)r!   )r"   r%   r%   r&   r(      r)   c             C   s   d| j | jf S )NzLIGOTimeGPS(%d, %u))r    r!   )r"   r%   r%   r&   __repr__   s    zLIGOTimeGPS.__repr__c             C   sh   | j dks| jdkr&d| j | jf }n2| j dk rJd| j d d| j f }ndd| j  }|ddS )	z=
		Return an ASCII string representation of a LIGOTimeGPS.
		r   z%d.%09ur	   r
   i ʚ;z-0.%09u0r   )r    r!   rstrip)r"   sr%   r%   r&   __str__   s    
zLIGOTimeGPS.__str__c             C   s   | j | jd  S )zg
		Convert a LIGOTimeGPS to seconds as a float.

		Example:

		>>> float(LIGOTimeGPS(100.5))
		100.5
		g&.>)r    r!   )r"   r%   r%   r&   	__float__   s    	zLIGOTimeGPS.__float__c             C   s   | j S )zt
		Return the integer part (seconds) of a LIGOTimeGPS as an int.

		Example:

		>>> int(LIGOTimeGPS(100.5))
		100
		)r    )r"   r%   r%   r&   __int__   s    	zLIGOTimeGPS.__int__c             C   s
   t | jS )z
		Return the integer part (seconds) of a LIGOTimeGPS as a long.

		Example:

		>>> repr(long(LIGOTimeGPS(100.5))) == '100L' if sys.version_info.major < 3 else True
		True
		)r   r    )r"   r%   r%   r&   __long__   s    	zLIGOTimeGPS.__long__c             C   s   | j d | j S )zz
		Convert a LIGOTimeGPS to a count of nanoseconds as a long.

		Example:

		>>> LIGOTimeGPS(100.5).ns()
		100500000000
		i ʚ;)r    r!   )r"   r%   r%   r&   r#      s    	zLIGOTimeGPS.nsc             C   s   | j | jA S )N)r    r!   )r"   r%   r%   r&   __hash__   s    zLIGOTimeGPS.__hash__c             C   s<   t |ts,yt|}W n tk
r*   tS X |  | kS )N)r   r   r   NotImplementedr#   )r"   otherr%   r%   r&   __eq__   s    
zLIGOTimeGPS.__eq__c             C   s<   t |ts,yt|}W n tk
r*   tS X |  | k S )a<  
		Compare a value to a LIGOTimeGPS.  If the value being compared
		to the LIGOTimeGPS is not also a LIGOTimeGPS, then an attempt
		is made to convert it to a LIGOTimeGPS.

		Example:

		>>> LIGOTimeGPS(100.5) < LIGOTimeGPS(200)
		True
		>>> LIGOTimeGPS(100.5) < 200
		True
		>>> LIGOTimeGPS(100.5) < "200"
		True
		)r   r   r   r3   r#   )r"   r4   r%   r%   r&   __lt__   s    
zLIGOTimeGPS.__lt__c             C   s   t | jpt | jS )zc
		Return True if the LIGOTimeGPS is nonzero.

		Example:

		>>> bool(LIGOTimeGPS(100.5))
		True
		)boolr    r!   )r"   r%   r%   r&   __bool__  s    	zLIGOTimeGPS.__bool__c             C   s,   t |tst|}t| j|j | j|j S )at  
		Add a value to a LIGOTimeGPS.  If the value being added to the
		LIGOTimeGPS is not also a LIGOTimeGPS, then an attempt is made
		to convert it to a LIGOTimeGPS.

		Example:

		>>> LIGOTimeGPS(100.5) + LIGOTimeGPS(3)
		LIGOTimeGPS(103, 500000000)
		>>> LIGOTimeGPS(100.5) + 3
		LIGOTimeGPS(103, 500000000)
		>>> LIGOTimeGPS(100.5) + "3"
		LIGOTimeGPS(103, 500000000)
		)r   r   r    r   r!   r   )r"   r4   r%   r%   r&   __add__  s    
zLIGOTimeGPS.__add__c             C   s,   t |tst|}t| j|j | j|j S )a  
		Subtract a value from a LIGOTimeGPS.  If the value being
		subtracted from the LIGOTimeGPS is not also a LIGOTimeGPS, then
		an attempt is made to convert it to a LIGOTimeGPS.

		Example:

		>>> LIGOTimeGPS(100.5) - LIGOTimeGPS(3)
		LIGOTimeGPS(97, 500000000)
		>>> LIGOTimeGPS(100.5) - 3
		LIGOTimeGPS(97, 500000000)
		>>> LIGOTimeGPS(100.5) - "3"
		LIGOTimeGPS(97, 500000000)
		)r   r   r    r   r!   r   )r"   r4   r%   r%   r&   __sub__+  s    
zLIGOTimeGPS.__sub__c             C   s,   t |tst|}t|j| j |j| j S )z*
		Subtract a LIGOTimeGPS from a value.
		)r   r   r   r    r   r!   )r"   r4   r%   r%   r&   __rsub__>  s    
zLIGOTimeGPS.__rsub__c             C   s   | j }| j}|dk r.|dkr.|d7 }|d8 }n |dkrN|dk rN|d8 }|d7 }|d }|| }|r~|dtt|dd   nd}|| }|t|9 }d}xF|| || || || fD ]&}t|\}	}
||
7 }||	d 7 }qW t|t|S )	zi
		Multiply a LIGOTimeGPS by a number.

		Example:

		>>> LIGOTimeGPS(100.5) * 2
		LIGOTimeGPS(201, 0)
		r   r
   i ʚ;i         g        g    eA)	r    r!   r   r   logr   r   r   r   )r"   r4   r   r   ZsloZshiZoloZohiaddendnr-   r%   r%   r&   __mul__F  s&    	
$"zLIGOTimeGPS.__mul__c             C   sX   t t| t| }x>tdD ]2}t| ||  t| }||7 }t|dkrP qW |S )zn
		Divide a LIGOTimeGPS by a number.

		Example:

		>>> LIGOTimeGPS(100.5) / 2
		LIGOTimeGPS(50, 250000000)
		d   g&.>)r   r   rangeabs)r"   r4   quotientr@   Zresidualr%   r%   r&   __truediv__j  s    	zLIGOTimeGPS.__truediv__c             C   s   t S )z#Integer division (not implemented).)r3   )r"   r4   r%   r%   r&   __floordiv__~  s    zLIGOTimeGPS.__floordiv__c             C   s   t | | }| ||  S )z
		Compute the remainder when a LIGOTimeGPS is divided by a number.

		Example:

		>>> LIGOTimeGPS(100.5) % 3
		LIGOTimeGPS(1, 500000000)
		)r   )r"   r4   rE   r%   r%   r&   __mod__  s    	zLIGOTimeGPS.__mod__c             C   s   | S )Nr%   )r"   r%   r%   r&   __pos__  s    zLIGOTimeGPS.__pos__c             C   s   t d|   S )Nr   )r   r#   )r"   r%   r%   r&   __neg__  s    zLIGOTimeGPS.__neg__c             C   s   | j dkr| S |  S )Nr   )r    )r"   r%   r%   r&   __abs__  s    
zLIGOTimeGPS.__abs__N)r   )"__name__
__module____qualname____doc__r'   propertyr   r   r   r   r*   r.   r/   r0   r1   r#   r2   r5   r6   r8   __nonzero__r9   __radd__r:   r;   rA   __rmul__rF   Z__div__rG   rH   rI   rJ   rK   r%   r%   r%   r&   r   K   s8   
F"r   c                   s   e Zd Z fddZ  ZS )
CacheEntryc                s   t dt tt| j||S )NzCglue.lal.CacheEntry is deprecated, use lal.utils.CacheEntry instead)warningswarnDeprecationWarningsuperrT   r'   )r"   argskwargs)	__class__r%   r&   r'     s    zCacheEntry.__init__)rL   rM   rN   r'   __classcell__r%   r%   )r[   r&   rT     s   rT   c               @   s   e Zd Zdd ZdS )rT   c             O   s   t dd S )Nz]glue.lal.CacheEntry is deprecated and lal is not available. Use lal.utils.CacheEntry instead.)
ValueError)r"   rY   rZ   r%   r%   r&   r'     s    zCacheEntry.__init__N)rL   rM   rN   r'   r%   r%   r%   r&   rT     s   c                   s   e Zd ZdZeZefddZeeZefddZ	ee	Z	efddZ
ee
Z
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d Zdd Zd'ddZd d! Zd(d#d$Z fd%d&Z  ZS ))Cachez
	An object representing a LAL cache file. Currently it is possible to
	add anything to a Cache. This method should check that the thing you
	are adding is a CacheEntry and throw and error if it is not.
	c                s    fdd|D } |S )zE
		Return a Cache object whose entries are read from an open file.
		c                s   g | ]} j |d qS ))coltype)entry_class).0line)clsr_   r%   r&   
<listcomp>  s    z"Cache.fromfile.<locals>.<listcomp>r%   )rc   fileobjr_   cr%   )rc   r_   r&   fromfile  s    zCache.fromfilec             C   s0   |  }x$|D ]}| | jt||d qW |S )z`
		Read Cache objects from the files named and concatenate the results into a
		single Cache.
		)r_   )extendrg   open)rc   	filenamesr_   cachefilenamer%   r%   r&   fromfilenames  s    
zCache.fromfilenamesc                s"   dd   fdd|D S )a0  
		Return a Cache whose entries are inferred from the URLs
		in urllist, if possible.  PFN lists will also work; for PFNs, the path
		will be absolutized and "file://" and "localhost" will be assumed
		for the schemes and hosts.

		The filenames must be in the format set forth by DASWG in T050017-00.
		c             S   sH   t j| \}}}}}|dkr*tj|}t j|p6d|p<d|ddfS )N file	localhost)r   parseurlsplitospathabspath
urlunsplit)urlschemehostrt   dummyr%   r%   r&   
pfn_to_url  s
     z#Cache.from_urls.<locals>.pfn_to_urlc                s    g | ]} j j|d qS ))r_   )r`   Zfrom_T050017)ra   f)rc   r_   r{   r%   r&   rd     s   z#Cache.from_urls.<locals>.<listcomp>r%   )rc   Zurllistr_   r%   )rc   r_   r{   r&   	from_urls  s    	zCache.from_urlsc             C   sB   t | d }x0t| ddd D ]\}}||kr | || = q W | S )z2
		Remove elements from self that are in other.
		r
   Nr	   )len	enumerate)r"   r4   endielemr%   r%   r&   __isub__  s
    zCache.__isub__c                s   |   fdd| D S )zJ
		Return a Cache containing the entries of self that are not in other.
		c                s   g | ]}| kr|qS r%   r%   )ra   r   )r4   r%   r&   rd     s    z!Cache.__sub__.<locals>.<listcomp>)r[   )r"   r4   r%   )r4   r&   r:     s    zCache.__sub__c             C   s   |  ||   | S )zO
		Append entries from other onto self without introducing (new) duplicates.
		)rh   )r"   r4   r%   r%   r&   __ior__  s    zCache.__ior__c             C   s   |  | dd |S )z>
		Return a Cache containing all entries of self and other.
		N)r[   r   )r"   r4   r%   r%   r&   __or__  s    zCache.__or__c             C   sB   t | d }x0t| ddd D ]\}}||kr | || = q W | S )z4
		Remove elements in self that are not in other.
		r
   Nr	   )r~   r   )r"   r4   r   r   r   r%   r%   r&   __iand__  s
    zCache.__iand__c                s   |   fdd| D S )zK
		Return a Cache containing the entries of self that are also in other.
		c                s   g | ]}| kr|qS r%   r%   )ra   r   )r4   r%   r&   rd     s    z!Cache.__and__.<locals>.<listcomp>)r[   )r"   r4   r%   )r4   r&   __and__  s    zCache.__and__c                s   t   |  fdd| D S )z
		Return a Cache which has every element of self, but without
		duplication.  Preserve order.  Does not hash, so a bit slow.
		c                s"   g | ]}| kr  |s|qS r%   )add)ra   x)seenr%   r&   rd     s    z Cache.unique.<locals>.<listcomp>)setr[   )r"   r%   )r   r&   unique  s    zCache.uniquec             C   s,   x| D ]}| dt|  qW |  dS )z=
		write a cache object to the fileobj as a lal cache file
		z%s
N)writestrclose)r"   re   entryr%   r%   r&   tofile   s    
zCache.tofilec             C   s*   x| D ]}| d|j  qW |  dS )z?
		write a cache object to filename as a plain text pfn file
		z%s
N)r   rt   r   )r"   re   r   r%   r%   r&   	topfnfile(  s    
zCache.topfnfilec             C   s$   t  }x| D ]}||jO }qW |S )z
		Return a segmentlistdict object describing the instruments
		and times spanned by the entries in this Cache.  The return
		value is coalesced.
		)r   Zsegmentlistdict)r"   dr   r%   r%   r&   to_segmentlistdict0  s    
zCache.to_segmentlistdictNFc                s   |rfddfddn@|dk	r2d| d }|dk	rFd| d }fddfdd| }|dk	rt t|fdd	|D }|dk	rt t|  fd
d	|D }dk	rЇfdd	|D }dk	r  fdd	|D }| |S )a  
		Return a Cache object with those CacheEntries that
		contain the given patterns (or overlap, in the case of
		segment or segmentlist).  If exact_match is True, then
		non-None ifos, description, and segment patterns must
		match exactly, and a non-None segmentlist must contain
		a segment which matches exactly).

		It makes little sense to specify both segment and
		segmentlist arguments, but it is not prohibited.

		Bash-style wildcards (*?) are allowed for ifos and description.
		c                s
   | j  kS )N)segment)e)r   r%   r&   r(   K  r)   zCache.sieve.<locals>.<lambda>c                s
   | j  kS )N)r   )r   )segmentlistr%   r&   r(   L  r)   N*c                s     | jS )N)Z
intersectsr   )r   )r   r%   r&   r(   P  r)   c                s     | jS )N)Zintersects_segmentr   )r   )r   r%   r&   r(   Q  r)   c                s    g | ]}  |jd k	r|qS )N)matchZobservatory)ra   r   )ifos_regexpr%   r&   rd   W  s    zCache.sieve.<locals>.<listcomp>c                s    g | ]}  |jd k	r|qS )N)r   description)ra   r   )descr_regexpr%   r&   rd   [  s    c                s   g | ]} |r|qS r%   r%   )ra   r   )segment_funcr%   r&   rd   ^  s    c                s   g | ]} |r|qS r%   r%   )ra   r   )segmentlist_funcr%   r&   rd   c  s    )recompilefnmatch	translateZcoalescer[   )r"   Zifosr   r   r   Zexact_matchrf   r%   )r   r   r   r   r   r   r&   sieve;  s,      zCache.sievec             C   s   dd | D S )z+
		Return a list of physical file names.
		c             S   s   g | ]
}|j qS r%   )rt   )ra   r   r%   r%   r&   rd   k  s    z!Cache.pfnlist.<locals>.<listcomp>r%   )r"   r%   r%   r&   pfnlistg  s    zCache.pfnlistrV   c             C   s   |dkrt dg }g }x0| D ](}tj|jr<|| q|| qW t|dkrdt|t| f }|dkrtjd|  n$|dkrt |n|dkrnt d	| 	|| 	|fS )
an  
		Runs through the entries of the Cache() object and checks each entry
		if the file which it points to exists or not. If the file does exist then
		it adds the entry to the Cache() object containing found files, otherwise it
		adds the entry to the Cache() object containing all entries that are missing.
		It returns both in the follwing order: Cache_Found, Cache_Missed.

		Pass on_missing to control how missing files are handled:
		  "warn": print a warning message saying how many files
		          are missing out of the total checked.
		  "error": raise an exception if any are missing
		  "ignore": do nothing
		)rV   errorignorez0on_missing must be "warn", "error", or "ignore".r   z2%d of %d files in the cache were not found on diskrV   zwarning: %s
r   r   z(Why am I here? Please file a bug report!)
r]   rs   rt   isfileappendr~   sysstderrr   r[   )r"   Z
on_missingZc_foundZc_missedr   msgr%   r%   r&   checkfilesexistm  s&    

zCache.checkfilesexistc                s   |  tt| ||S )N)r[   rX   r^   __getslice__)r"   r   j)r[   r%   r&   r     s    zCache.__getslice__)NNNNF)rV   )rL   rM   rN   rO   rT   r`   r   rg   classmethodrm   r}   r   r:   r   r   r   r   r   r   r   r   r   r   r   r   r\   r%   r%   )r[   r&   r^     s.   	

 
+
'r^   )$rO   
__future__r   	functoolsr   ImportErrorZfunctools32r   r   rs   r   r   Z	six.movesr   rU   r   r   	NameErrorr   Zligor   Zgluer   
__author__id__version__date__date__objectr   Z	lal.utilsZlalutilsrT   listr^   r%   r%   r%   r&   <module>   s@   

  Z
