B
    d"                 @   s@   d dl Z dZddlmZ ddlmZ G dd deZdd	 Z	dS )
    Nz"Kipp Cannon <kipp.cannon@ligo.org>   )date)versionc               @   s^   e Zd ZdZedd Zedd ZdddZd	d
 Zdd Z	dd Z
dd Zedd ZdS )offsetvectorz
	Subclass of the dict built-in type for storing mappings of
	instrument to time offset.

	Examples:

	>>> x = offsetvector({"H1": 0, "L1": 10, "V1": 20})
	>>> x["H1"]
	0
	>>> not any(x.values())	# check for "zero-lag"
	False
	c             C   s   | st dt| S )zD
		= min(self)

		Raises ValueError if the offsetvector is empty.
		zoffsetvector is empty)
ValueErrormin)self r	   b/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/lalburst/offsetvector.pyrefkey9   s    zoffsetvector.refkeyc                s(   j    t fddD S )aT  
		Dictionary of relative offsets.  The keys in the result are
		pairs of keys from the offset vector, (a, b), and the
		values are the relative offsets, (offset[b] - offset[a]).
		Raises ValueError if the offsetvector is empty (WARNING:
		this behaviour might change in the future).

		Example:

		>>> x = offsetvector({"H1": 0, "L1": 10, "V1": 20})
		>>> assert x.deltas == {('H1', 'L1'): 10, ('H1', 'V1'): 20, ('H1', 'H1'): 0}
		>>> y = offsetvector({'H1': 100, 'L1': 110, 'V1': 120})
		>>> y.deltas == x.deltas
		True

		Note that the result always includes a "dummy" entry,
		giving the relative offset of self.refkey with respect to
		itself, which is always 0.

		See also .fromdeltas().

		BUGS:  I think the keys in each tuple should be reversed.
		I can't remember why I put them in the way they are.
		Expect them to change in the future.
		c             3   s"   | ]} |f|  fV  qd S )Nr	   ).0key)r   	refoffsetr   r	   r
   	<genexpr>n   s    z&offsetvector.deltas.<locals>.<genexpr>)r   dict)r   r	   )r   r   r   r
   deltasH   s    $zoffsetvector.deltasFc             C   s<   |r d dd t|  D S d dd t|  D S )z
		Return a human-readable string representation of an offset
		vector.

		Example:

		>>> a = offsetvector({"H1": -10.1234567, "L1": 0.125})
		>>> str(a)
		'H1 = -10.1234567 s, L1 = +0.125 s'
		>>> a.__str__(compact = True)
		'H1=-10.123,L1=0.125'
		,c             s   s   | ]}d | V  qdS )z%s=%.5gNr	   )r   xr	   r	   r
   r   ~   s    z'offsetvector.__str__.<locals>.<genexpr>z, c             s   s   | ]}d | V  qdS )z%s = %+.16g sNr	   )r   r   r	   r	   r
   r      s    )joinsorteditems)r   compactr	   r	   r
   __str__p   s    zoffsetvector.__str__c             C   s   d| j jt| f S )a]  
		Return a string representation of the offset vector.
		Running eval() on the result reconstructs the offsetvector.

		Example:

		>>> a = offsetvector({"H1": -10.1234567, "L1": 0.1})
		>>> b = eval(repr(a))
		>>> b == a
		True
		>>> b is a
		False
		>>> c = offsetvector({"H1": -10.1234567})
		>>> repr(c)
		"offsetvector({'H1': -10.1234567})"
		z%s(%s))	__class____name__r   __repr__)r   r	   r	   r
   r      s    zoffsetvector.__repr__c             C   s   t |  t|   S )z
		Returns max(offset) - min(offset).

		Example:

		>>> abs(offsetvector({"H1": 0.0, "H2": 0.0, "L1": 0.0}))
		0.0
		>>> abs(offsetvector({"H1": 10.0, "H2": 10.0, "L1": 10.0}))
		0.0
		>>> abs(offsetvector({'H1': 10.0, 'L1': 0.0, 'V1': -10.0}))
		20.0
		)maxvaluesr   )r   r	   r	   r
   __abs__   s    zoffsetvector.__abs__c                s"   t  fdd|  D j jkS )a  
		Returns True if offset vector other can be found in self,
		False otherwise.  An offset vector is "found in" another
		offset vector if the latter contains all of the former's
		instruments and the relative offsets among those
		instruments are equal (the absolute offsets need not be).

		Example:

		>>> a = offsetvector({"H1": 10, "L1": 20, "V1": 30})
		>>> b = offsetvector({"H1": 20, "V1": 40})
		>>> a.contains(b)
		True

		Note the distinction between this and the "in" operator:

		>>> "H1" in a
		True
		c             3   s"   | ]\}}| kr||fV  qd S )Nr	   )r   r   offset)otherr	   r
   r      s    z(offsetvector.contains.<locals>.<genexpr>)r   r   r   )r   r    r	   )r    r
   contains   s    zoffsetvector.containsc             K   sV   xPt | D ]@\}}|| kr|| |  }x |  D ]}| |  |7  < q4W P qW | S )a  
		Adjust the offsetvector so that a particular instrument has
		the desired offset.  All other instruments have their
		offsets adjusted so that the relative offsets are
		preserved.  The instrument to noramlize, and the offset one
		wishes it to have, are provided as a key-word argument.
		The return value is the time slide dictionary, which is
		modified in place.

		If more than one key-word argument is provided the keys are
		sorted and considered in order until a key is found that is
		in the offset vector.  The offset vector is normalized to
		that value.  This function is a no-op if no key-word
		argument is found that applies.

		Example:

		>>> a = offsetvector({"H1": -10, "H2": -10, "L1": -10})
		>>> assert a.normalize(L1 = 0) == offsetvector({'H2': 0, 'H1': 0, 'L1': 0})
		>>> a = offsetvector({"H1": -10, "H2": -10})
		>>> assert a.normalize(L1 = 0, H2 = 5) == offsetvector({'H2': 5, 'H1': 5})
		)r   r   keys)r   kwargsr   r   deltar	   r	   r
   	normalize   s    zoffsetvector.normalizec             C   s   | dd |  D S )a  
		Construct an offsetvector from a dictionary of offset
		deltas as returned by the .deltas attribute.

		Example:

		>>> x = offsetvector({"H1": 0, "L1": 10, "V1": 20})
		>>> y = offsetvector.fromdeltas(x.deltas)
		>>> y == x
		True

		See also .deltas, .fromkeys()
		c             s   s   | ]\\}}}||fV  qd S )Nr	   )r   r   r   valuer	   r	   r
   r      s    z*offsetvector.fromdeltas.<locals>.<genexpr>)r   )clsr   r	   r	   r
   
fromdeltas   s    zoffsetvector.fromdeltasN)F)r   
__module____qualname____doc__propertyr   r   r   r   r   r!   r%   classmethodr(   r	   r	   r	   r
   r   ,   s   (
!r   c                sf   i }xN| D ]Fx@t t|D ], | t t fdd D  q W q
W dd | D S )a  
	Given an iterable of offset vectors, return the shortest list of
	the unique n-instrument offset vectors from which all the vectors
	in the input iterable can be constructed.  This can be used to
	determine the minimal set of n-instrument coincs required to
	construct all of the coincs for all of the requested instrument and
	offset combinations in a set of offset vectors.

	It is assumed that the coincs for the vector {"H1": 0, "H2": 10,
	"L1": 20} can be constructed from the coincs for the vectors {"H1":
	0, "H2": 10} and {"H2": 0, "L1": 10}, that is only the relative
	offsets are significant in determining if two events are
	coincident, not the absolute offsets.
	c             3   s"   | ]}|  d    V  qdS )r   Nr	   )r   Z
instrument)instrumentsvectr	   r
   r     s    z*component_offsetvectors.<locals>.<genexpr>c             S   s(   g | ] \}}|D ]}t t||qqS r	   )r   zip)r   r.   Z	delta_setr   r	   r	   r
   
<listcomp>  s    z+component_offsetvectors.<locals>.<listcomp>)	itertoolscombinationsr   
setdefaultsetaddtupler   )ZoffsetvectorsnZ
delta_setsr	   )r.   r/   r
   component_offsetvectors   s
    
0r9   )
r2   
__author__Zgit_versionr   __date__r   __version__r   r   r9   r	   r	   r	   r
   <module>   s    J