B
    d7M                 @   s   d dl m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mZ d dl	m
Z
 d dl	mZ ddlmZ d	Zdd
lmZ ddlmZ G dd dejZejdd ddZdd ZG dd dejZG dd dejZdddeddfddZG dd deZdS )    )print_functionN)ligolw)	lsctables)offsetvector)	snglcoinc   )_thincaz"Kipp Cannon <kipp.cannon@ligo.org>)date)versionc               @   sd   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	e
dd Ze
dd Ze
dd ZdS )SnglInspiral c             C   s
   | j |k S )N)end)selfotherr   r   _/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/lalinspiral/thinca.py__lt__F   s    zSnglInspiral.__lt__c             C   s
   | j |kS )N)r   )r   r   r   r   r   __le__I   s    zSnglInspiral.__le__c             C   s
   | j |kS )N)r   )r   r   r   r   r   __eq__L   s    zSnglInspiral.__eq__c             C   s
   | j |kS )N)r   )r   r   r   r   r   __ne__O   s    zSnglInspiral.__ne__c             C   s
   | j |kS )N)r   )r   r   r   r   r   __ge__R   s    zSnglInspiral.__ge__c             C   s
   | j |kS )N)r   )r   r   r   r   r   __gt__U   s    zSnglInspiral.__gt__c             C   s   | j | j S )N)mass1mass2)r   r   r   r   mtotal_   s    zSnglInspiral.mtotalc             C   s   | j | j | jd  S )Ng       @)r   r   r   )r   r   r   r   etac   s    zSnglInspiral.etac             C   s   | j | jd  S )Ng333333?)r   r   )r   r   r   r   mchirpg   s    zSnglInspiral.mchirpN)__name__
__module____qualname__	__slots__r   r   r   r   r   r   propertyr   r   r   r   r   r   r   r   =   s   
r   Zinspiralz+sngl_inspiral<-->sngl_inspiral coincidences)searchsearch_coinc_typedescriptionc             C   s    t | dd d}|j||j  S )a  
	Compute the end time of an inspiral coincidence.  events is an
	iterable of sngl_inspiral triggers, offset_vector is a dictionary
	mapping instrument to offset.

	This function returns the time shifted end time of the trigger with
	the highest SNR.  The end time reported by this function gets used
	for things like plot titles, alert messages, and so on.  It is not
	meant to be an accurate estimate of the time at which the
	gravitational wave passed through the geocentre, or any other such
	thing.

	This end time is also used to parallelize thinca by allowing a
	single lock stretch to be split across several jobs without missing
	or double counting any coincs.  This is achieved by using a
	definition that is guaranteed to return a bit-identical "end time"
	for a given set of triggers.  Guaranteeing that allows thinca to
	clip coincs to a sequence of contiguous segments and know that no
	coinc will missed or double counted.
	c             S   s   | j S )N)snr)eventr   r   r   <lambda>       z)coinc_inspiral_end_time.<locals>.<lambda>)key)maxr   ifo)eventsoffset_vectorr%   r   r   r   coinc_inspiral_end_time   s    r-   c                   s4   e Zd Z fddZ fddZ fddZ  ZS )InspiralCoincTablesc                s^   t t| || ytj|| _W n4 tk
rX   ttj| _|j	d 
| j Y nX d S )Nr   )superr.   __init__r   CoincInspiralTable	get_tablecoinc_inspiral_table
ValueErrorNewZ
childNodesappendChild)r   xmldoccoinc_definer_row)	__class__r   r   r0      s    zInspiralCoincTables.__init__c       
         s   t t| |||d\}}| j| t|dd d}|j|j   tdd |D }| jj	|j
|j|j |jttdd |D d d d  |d	}	t fd	d| D |B |_|||	fS )
NZsngl_inspiralc             S   s   | j S )N)r$   )r%   r   r   r   r&      r'   z0InspiralCoincTables.coinc_rows.<locals>.<lambda>)r(   c             s   s   | ]}|j V  qd S )N)r*   ).0r%   r   r   r   	<genexpr>   s    z1InspiralCoincTables.coinc_rows.<locals>.<genexpr>c             s   s   | ]}|j d  V  qdS )g       @N)r$   )r:   r%   r   r   r   r;      s    )	coinc_event_idZmassr   r$   Zfalse_alarm_rateZcombined_farZminimum_durationr   Zinstrumentsc             3   s*   | ]"\}}t  |  |kr|V  qd S )N)float)r:   
instrumentZsegs)r   r   r   r   r;      s    )r/   r.   
coinc_rowstime_slide_indexr)   r   r*   	frozensetr3   ZRowTyper<   r   r   r   mathsqrtsumsetitemsZinsts)
r   
process_idtime_slide_idr+   seglistsZcoincZ	coincmapsZrefeventZparticipating_instrumentscoinc_inspiral)r9   )r   r   r   r?      s"    
	
"zInspiralCoincTables.coinc_rowsc                s*   t t| ||}|j|_| j| |S )N)r/   r.   append_coincr<   r3   append)r   coinc_eventZcoinc_event_mapsrJ   )r9   r   r   rK      s    z InspiralCoincTables.append_coinc)r   r   r   r0   r?   rK   __classcell__r   r   )r9   r   r.      s   7r.   c               @   s&   e Zd ZG dd dejjZejZdS )coincgen_doublesc               @   s   e Zd ZedZdS )zcoincgen_doubles.singlesqueuer   N)r   r   r   operator
attrgetterZ
event_timer   r   r   r   singlesqueue   s   rR   N)r   r   r   r   rO   rR   r   Z
get_coincsr   r   r   r   rO      s   rO      TFc
          	      s`  |	rt dtjd t| |}
tjt|
j|||	d}tj	
| } d k	r` fdd|D }|  }|sxtt|dd dd	d D ]\}}||t|t qW nxtt|d
d ddd D ]`\}}t|}|||tdd |D rx2|j|dD ]"\}}|
j|
j||j||d  qW qW x6|j|ddD ]$\}}|
j|
j||j||d  q4W | S )Nzindexing ...)file)min_instrumentsverbosec             3   s,   | ]$}|j  ks |j |j  kr|V  qd S )N)r*   r   )r:   r%   )veto_segmentsr   r   r;   (  s    z ligolw_thinca.<locals>.<genexpr>c             S   s   | j S )N)r*   )rowr   r   r   r&   4  r'   zligolw_thinca.<locals>.<lambda>)r(   c             S   s   | j S )N)r*   )r%   r   r   r   r&   4  r'   c             S   s   | j | jfS )N)r   r*   )rX   r   r   r   r&   ;  r'   c             S   s   | j S )N)r*   )r%   r   r   r   r&   ;  r'   c             s   s   | ]}|j V  qd S )N)r   )r:   r%   r   r   r   r;   =  s    )coinc_sieve)rI   T)rY   flush)printsysstderrr.   r   ZTimeSlideGraphrO   r@   r   SnglInspiralTabler2   	itertoolsgroupbysortedpushtupleZPosInfinityr)   pullrK   r?   rH   )r7   rG   Zdelta_trI   Zntuple_comparefuncrW   rU   r8   incrementalrV   Zcoinc_tablesZtime_slide_graphsngl_inspiral_tabler>   r+   noder   )rW   r   ligolw_thinca  s&    
&&" rh   c               @   sh   e Zd ZdZdd Ze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S )sngl_inspiral_coincsa5  
	Dictionary-like device to extract XML document trees containing
	individual sngl_inspiral coincs from a source XML document tree
	containing several.

	An instance of the class is initialized with an XML document tree.
	The coinc event ID of a sngl_inspiral<-->sngl_inspiral coinc in
	the document can then be used like a dictionary key to retrieve a
	newly-constructed XML document containing that coinc by itself.
	The output document trees are complete, self-describing, documents
	with all metadata about the event from the source document
	preserved.

	Example:

	>>> coincs = sngl_inspiral_coincs(xmldoc)
	>>> print(coincs.coinc_def_id)
	0
	>>> coincs.keys()
	[0]
	>>> coinc_id = coincs.keys()[0]
	>>> print(coinc_id)
	83763
	>>> coincs[coinc_id].write()
	<?xml version='1.0' encoding='utf-8'?>
	<!DOCTYPE LIGO_LW SYSTEM "http://ldas-sw.ligo.caltech.edu/doc/ligolwAPI/html/ligolw_dtd.txt">
	<LIGO_LW>
		<Table Name="process:table">
			<Column Type="lstring" Name="process:comment"/>
			<Column Type="lstring" Name="process:node"/>
	...

	The XML documents returned from this class share references to the
	row objects in the original document.  Modifications to the row
	objects in the tables returned by this class will affect both the
	original document and all other documents returned by this class.
	However, each retrieval constructs a new document from scratch,
	they are not cached nor re-used, therefore this operation can be
	time consuming if it needs to be performed repeatedly but the table
	objects and document trees can be edited without affecting each
	other.

	If the source document is modified after this class has been
	instantiated, the behaviour is undefined.

	To assist with memory clean-up, it is helpful to invoke the
	.unlink() method on the XML trees returned by this class when they
	are no longer needed.
	c          	      s  t j|_t j|_t j|_t j|_	t j
|_t j|_t j|_t j|_tdd jD _i _x$jD ]}j|jg | qW tdd jD _i _x$jD ]}j|jg | qW tdd j  D _dd j	D \_tdd jD  t fddjD _ t fddjD _!tj tj!kst"td	d j D _#xBjD ]8}yj#|j$ | W n t%k
r   wY nX qW d
S )z
		Initialize an instance of the class.  xmldoc is the source
		XML document tree from which the
		sngl_inspiral<-->sngl_inspiral coincs will be extracted.
		c             s   s   | ]}|j |fV  qd S )N)rG   )r:   rX   r   r   r   r;     s    z0sngl_inspiral_coincs.__init__.<locals>.<genexpr>c             s   s   | ]}|j |fV  qd S )N)event_id)r:   rX   r   r   r   r;     s    c             s   s"   | ]\}}t | s|V  qd S )N)anyvalues)r:   rH   r,   r   r   r   r;     s    c             s   s*   | ]"}|j tj kr|jtjkr|V  qd S )N)r!   InspiralCoincDefr"   )r:   rX   r   r   r   r;     s    c             s   s   | ]}|j V  qd S )N)r<   )r:   rX   r   r   r   r;     s    c             3   s0   | ](}|j jj kr|j kr|j|fV  qd S )N)coinc_def_id	coinc_defr<   )r:   rX   )coinc_event_map_idsr   r   r   r;     s    c             3   s"   | ]}|j  kr|j |fV  qd S )N)r<   )r:   rX   )rp   r   r   r;     s    c             s   s   | ]}|g fV  qd S )Nr   )r:   r<   r   r   r   r;     s    N)&r   ProcessTabler2   process_tableProcessParamsTableprocess_params_tabler^   rf   CoincDefTablecoinc_def_table
CoincTablecoinc_event_tabler1   r3   CoincMapTablecoinc_event_map_tableTimeSlideTabletime_slide_tabledictprocess_indexprocess_params_index
setdefaultrG   rL   sngl_inspiral_indexr@   rH   rA   as_dictrF   zero_lag_time_slide_idsro   coinc_event_indexcoinc_inspiral_indexAssertionErrorcoinc_event_map_indexr<   KeyError)r   r7   rX   r   )rp   r   r   r0     s8    
zsngl_inspiral_coincs.__init__c             C   s   | j jS )za
		The coinc_def_id of the sngl_inspiral<-->sngl_inspiral
		coincs in the source XML document.
		)ro   rn   )r   r   r   r   rn     s    z!sngl_inspiral_coincs.coinc_def_idc                s    fdd j | D S )zm
		Return a list of the sngl_inspiral rows that participated
		in the coincidence given by coinc_event_id.
		c                s   g | ]} j |j qS r   )r   rj   )r:   rX   )r   r   r   
<listcomp>  s    z7sngl_inspiral_coincs.sngl_inspirals.<locals>.<listcomp>)r   )r   r<   r   )r   r   sngl_inspirals  s    z#sngl_inspiral_coincs.sngl_inspiralsc             c   sL   xF| j  D ]8\}}|j| jkr|jdk r| j| \}| j|j V  qW dS )a  
		Generator returns a sequence of the sngl_inspiral table
		rows that formed zero-lag single-instrument "coincs".

		This is only meaningful if the coincidence engine was run
		with min_instruments = 1, otherwise this sequence will be
		empty by construction.  Also, if there was no zero-lag time
		slide included in the time slide graph then this sequence
		will be empty.

		This method is used by codes that want lists of
		non-coincident triggers for background models even if
		min_instruments has been set below 2.

		The constraint that they be "zero-lag" singles might at
		first seem nonsensical but is included to exclude triggers
		that form genuine coincidences at zero-lag but are present
		only as single-detector candidates in one or more time
		slides.
		rS   N)r   rF   rH   r   Zneventsr   r   rj   )r   r<   rM   rX   r   r   r   single_sngl_inspirals  s    z*sngl_inspiral_coincs.single_sngl_inspiralsc             C   s   t  dd | j| D S )z5
		Return the offsetvector given by time_slide_id.
		c             s   s   | ]}|j |jfV  qd S )N)r>   offset)r:   rX   r   r   r   r;     s    z5sngl_inspiral_coincs.offset_vector.<locals>.<genexpr>)r   r@   )r   rH   r   r   r   r,     s    z"sngl_inspiral_coincs.offset_vectorc          	   C   s  t  }|t  }|ttj| jj}|ttj	| j
j}|ttj| jj}|ttj| jj}|ttj| jj}|ttj| jj}	|ttj| jj}
|ttj| jj}|| j | j| }|| |	| j|  t|
j| j|  t|j| j|j  x |
D ]}|| j|j   q2W xrt!|"dt!|"dB t!|"dB D ]D}|| j#|  yt|j| j$|  W n t%k
r   Y nX qzW |S )z
		Construct and return an XML document containing the
		sngl_inspiral<-->sngl_inspiral coinc carrying the given
		coinc_event_id.
		rG   )&r   ZDocumentr6   ZLIGO_LWr   r5   rq   rr   Zcolumnnamesrs   rt   r^   rf   ru   rv   rw   rx   r1   r3   ry   rz   r{   r|   rL   ro   r   r   mapr   r@   rH   r   rj   rE   ZgetColumnByNamer~   r   r   )r   r<   Z	newxmldocZligolw_elemZnew_process_tableZnew_process_params_tableZnew_sngl_inspiral_tableZnew_coinc_def_tableZnew_coinc_event_tableZnew_coinc_inspiral_tableZnew_coinc_event_map_tableZnew_time_slide_tablerM   rX   rG   r   r   r   __getitem__  s2    


0z sngl_inspiral_coincs.__getitem__c             C   s
   t | jS )z?
		Iterate over the coinc_event_id's in the source document.
		)iterr   )r   r   r   r   __iter__  s    zsngl_inspiral_coincs.__iter__c             C   s
   t | jS )N)boolr   )r   r   r   r   __nonzero__  s    z sngl_inspiral_coincs.__nonzero__c             C   s
   | j  S )z{
		A list of the coinc_event_id's of the
		sngl_inspiral<-->sngl_inspiral coincs available in the
		source XML document.
		)r   keys)r   r   r   r   r   "  s    zsngl_inspiral_coincs.keysc             c   s    x| D ]}|| | fV  qW dS )aG  
		Yield a sequence of (coinc_event_id, XML tree) tuples, one
		for each sngl_inspiral<-->sngl_inspiral coinc in the source
		document.

		NOTE:  to allow this to work more easily with very large
		documents, instead of returning the complete sequence as a
		pre-constructed list this method is implemented as a
		generator.
		Nr   )r   r<   r   r   r   rF   *  s    
zsngl_inspiral_coincs.itemsN)r   r   r   __doc__r0   r    rn   r   r   r,   r   r   r   r   rF   	iteritemsr   r   r   r   ri   ]  s   12)ri   )
__future__r   r_   rB   rP   r\   Zligo.lwr   r   Zlalburstr   r    r   
__author__Zgit_versionr	   __date__r
   __version__r   ZCoincDefrm   r-   ZCoincTablesr.   rO   rh   objectri   r   r   r   r   <module>   s0   =VL