B
    à‹då  ã               @   s\   d dl Z ddlmZ dZddlmZ ddlmZ dd„ Z	d	d
„ Z
dd„ Zdd„ Zdd„ ZdS )é    Né   )Úoffsetvectorz"Kipp Cannon <kipp.cannon@ligo.org>)Údate)Úversionc       
   	   C   sH  y|   d¡\}}W n  tk
r2   td|  ƒ‚Y nX tƒ }xüdd„ |  d¡D ƒD ]ä}ytt|  d¡ƒ\}}}W n$ tk
r’   td||f ƒ‚Y nX |dkr¾||kr°td	| ƒ‚| |¡ qPn&|dk rÐ||krän||k rätd
| ƒ‚xNt ¡ D ]B}|||  }	t||ƒ|	  kr"t	||ƒks&n P | |	¡ qîW qPW | 
¡ t|ƒfS )aq  
	Accepts a string in the format
	instrument=first:last:step[,first:last:step]...  and returns the
	tuple (instrument, [offset1, offset2, ....]) where the offsets are
	the sorted list of unique numbers described by the ranges.  A range
	with a positive step describes the offsets (first + n * step) where
	n is an integer such that first <= offset <= last.  A range with a
	negative step describes the offsets (first + n * step) where n is
	an integer such that last <= offset <= first.

	Example:

	>>> parse_slidespec("H1=-5:+5:0.5")
	('H1', [-5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0])
	>>> parse_slidespec("H1=+5:-5:-0.5")
	('H1', [-5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0])
	>>> parse_slidespec("H1=-5:+5:8")
	('H1', [-5.0, 3.0])
	ú=zcannot parse time slide '%s'c             S   s   g | ]}|  ¡ ‘qS © )Ústrip)Ú.0Úsr   r   ú`/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/lalburst/timeslides.pyú
<listcomp>H   s    z#parse_slidespec.<locals>.<listcomp>ú,ú:zmalformed range '%s' in '%s'r   zdivide by zero in range '%s'z!step has wrong sign in range '%s')ÚsplitÚ
ValueErrorÚsetÚmapÚfloatÚaddÚ	itertoolsÚcountÚminÚmaxr   Úsorted)
Ú	slidespecÚ
instrumentZ	rangespecÚoffsetsÚrngÚfirstÚlastÚstepÚiÚxr   r   r   Úparse_slidespec/   s.    
&r#   c          	   C   sn   i }xR| D ]J}t |ƒ\}}y||  t|ƒO  < W q
 tk
rR   t|ƒ||< Y q
X q
W tdd„ | ¡ D ƒƒS )a,  
	Accepts a list of strings of the format understood by
	parse_slidespec(), and returns a dictionary mapping instrument
	names to sorted lists of unique offsets.

	Example:

	>>> parse_slides(["H1=-1:+1:+1", "H2=-1:+1:+1", "L1=0:0:0"])
	{'H2': [-1.0, 0.0, 1.0], 'H1': [-1.0, 0.0, 1.0], 'L1': [0.0]}
	c             s   s   | ]\}}|t |ƒfV  qd S )N)r   )r	   r   r   r   r   r   ú	<genexpr>r   s    zparse_slides.<locals>.<genexpr>)r#   r   ÚKeyErrorÚdictÚitems)ÚslidesÚdr   r   r   r   r   r   Úparse_slides]   s    
r*   c             C   sF   |   ¡  d¡\}}t dd„ dd„ |  ¡  d¡D ƒD ƒ¡}t|ƒ|fS )a  
	Accepts a string in the format
	count:instrument=offset[,instrument=offset...] and returns the
	tuple (count, {instrument: offset, ...})

	Example:

	>>> parse_inspiral_num_slides_slidespec("3:H1=0,H2=5,L1=10")
	(3, offsetvector({'H2': 5.0, 'H1': 0.0, 'L1': 10.0}))
	r   c             s   s"   | ]\}}|  ¡ t|ƒfV  qd S )N)r   r   )r	   r   Úoffsetr   r   r   r$      s    z6parse_inspiral_num_slides_slidespec.<locals>.<genexpr>c             s   s   | ]}|  ¡  d ¡V  qdS )r   N)r   r   )r	   Útokenr   r   r   r$      s    r   )r   r   r   Úint)r   r   r   Z
offsetvectr   r   r   Ú#parse_inspiral_num_slides_slidespecu   s    (r.   c             c   s>   | sdS |   ¡ }x(tj|  ¡ Ž D ]}t t||ƒ¡V  q W dS )aä  
	Accepts a dictionary mapping instrument --> list-of-offsets (for
	example, as returned by parse_slides()), and iterates over the
	cartesian (outer) product of the offset lists, yielding all
	possible N-way instrument --> offset mappings.

	Example:

	>>> slides = {"H1": [-1, 0, 1], "H2": [-1, 0, 1], "L1": [0]}
	>>> list(SlidesIter(slides))
	[offsetvector({'H2': -1, 'H1': -1, 'L1': 0}), offsetvector({'H2': -1, 'H1': 0, 'L1': 0}), offsetvector({'H2': -1, 'H1': 1, 'L1': 0}), offsetvector({'H2': 0, 'H1': -1, 'L1': 0}), offsetvector({'H2': 0, 'H1': 0, 'L1': 0}), offsetvector({'H2': 0, 'H1': 1, 'L1': 0}), offsetvector({'H2': 1, 'H1': -1, 'L1': 0}), offsetvector({'H2': 1, 'H1': 0, 'L1': 0}), offsetvector({'H2': 1, 'H1': 1, 'L1': 0})]
	N)Úkeysr   ÚproductÚvaluesr   Úzip)r(   ZinstrumentsZslider   r   r   Ú
SlidesIterŽ   s
    	r3   c             #   sB   |  ¡ }x4t|  | 
 d ƒD ]‰ t ‡ fdd„|D ƒ¡V  qW dS )a×  
	This generator yields a sequence of time slide dictionaries in the
	style of lalapps_thinca's time slides.  Each resulting dictionary
	maps instrument to offset.  The input is a count of time slides (an
	integer), and a dictionary mapping instrument to offset.  The
	output dictionaries describe time slides that are integer multiples
	of the input time shifts.

	Example:

	>>> list(Inspiral_Num_Slides_Iter(3, {"H1": 0.0, "H2": 5.0,"L1": 10.0}))
	[offsetvector({'H2': -15.0, 'H1': -0.0, 'L1': -30.0}), offsetvector({'H2': -10.0, 'H1': -0.0, 'L1': -20.0}), offsetvector({'H2': -5.0, 'H1': -0.0, 'L1': -10.0}), offsetvector({'H2': 0.0, 'H1': 0.0, 'L1': 0.0}), offsetvector({'H2': 5.0, 'H1': 0.0, 'L1': 10.0}), offsetvector({'H2': 10.0, 'H1': 0.0, 'L1': 20.0}), offsetvector({'H2': 15.0, 'H1': 0.0, 'L1': 30.0})]

	The output time slides are all integer multiples of the input time
	shift vector in the range [-count, +count], and are returned in
	increasing order of mupltiplier.
	r   c             3   s   | ]\}}||ˆ  fV  qd S )Nr   )r	   r   r+   )Únr   r   r$   ¾   s    z+Inspiral_Num_Slides_Iter.<locals>.<genexpr>N)r'   Úranger   )r   r   r   )r4   r   ÚInspiral_Num_Slides_Iterª   s    r6   )r   Ú r   Ú
__author__Zgit_versionr   Ú__date__r   Ú__version__r#   r*   r.   r3   r6   r   r   r   r   Ú<module>   s   .