B
    dO                 @   s  yd dl mZ W n ek
r,   ed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
mZ d dl
mZ d dl
mZ d dl
mZ d d	lm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ZddlmZ  ddlm!Z" dd Z#G dd dej$Z%ej&j'(e%j)e%e%e%j)i G dd dej*Z*G dd dej+Z,d&ddZ-d'ddZ.d(ddZ/d d! Z0d"d# Z1d$d% Z2dS ))    )NegInfz-infN)ligolw)array)param)	lsctables)utils)process)rate   )offsetvector)	snglcoincz"Kipp Cannon <kipp.cannon@ligo.org>)date)versionc                sn   t   }i }xXtdt|d D ]B}x<t||D ],}tdd |D  fdd|D ||< q6W q$W |S )a8  
	Return a dictionary of snglcoinc.TOATriangulator objects
	initialized for a variety of instrument combinations.
	timing_uncertainties is a dictionary of instrument->$\Delta t$
	pairs.  The return value is a dictionary of (instrument
	tuple)->TOATrangulator mappings.  The instrument names in each
	tuple are sorted in alphabetical order, and the triangulators are
	constructed with the instruments in that order (the the
	documentation for snglcoinc.TOATriangulator for more information).

	Example:

	>>> x = triangulators({"H1": 0.005, "L1": 0.005, "V1": 0.005})

	constructs a dictionary of triangulators for every combination of
	two or more instruments that can be constructed from those three.

	The program lalapps_string_plot_binj can be used to measure the
	timing uncertainties for the instruments in a search.
	   r
   c             S   s   g | ]}t j| jqS  )lalZcached_detector_by_prefixlocation).0
instrumentr   r   a/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/lalburst/stringutils.py
<listcomp>`   s    z!triangulators.<locals>.<listcomp>c                s   g | ]} | qS r   r   )r   r   )timing_uncertaintiesr   r   r   `   s    )sortedkeysrangelen	itertoolscombinationsr   ZTOATriangulator)r   Zallinstrumentstriangulatorsninstrumentsr   )r   r   r   F   s    0r   c                   s8   e Zd ZdZdZ fddZdd Zdd Zd	Z  Z	S )
InstrumentBinszy
	Example:

	>>> x = InstrumentBins()
	>>> x[frozenset(("H1", "L1"))]
	55
	>>> x.centres()[55]
	frozenset(['H1', 'L1'])
	)ZE0ZE1ZE2ZE3ZG1H1H2zH1H2+zH1H2-ZL1ZV1c                s.   t t|  fddtt d D  d S )Nc             3   s(   | ] }t  |D ]}t|V  qqd S )N)r   r   	frozenset)r   r   Zcombo)namesr   r   	<genexpr>   s    z*InstrumentBins.__init__.<locals>.<genexpr>r
   )superr!   __init__r   r   )selfr%   )	__class__)r%   r   r(      s    zInstrumentBins.__init__c             C   s   t jdt| ddS )Nr   double)dtype)numpyaranger   )r)   r   r   r   lower   s    zInstrumentBins.lowerc             C   s   t jdt| d ddS )Nr
   r+   )r,   )r-   r.   r   )r)   r   r   r   upper   s    zInstrumentBins.upperZinstrumentbins)
__name__
__module____qualname____doc__r%   r(   r/   r0   xml_bins_name__classcell__r   r   )r*   r   r!   v   s   	r!   c                   sb   e Zd Zdd Zdd Zdd Zddd	Zd
d Zdd Zdd Z	 fddZ
edd Z  ZS )LnLRDensityc             C   s  i | _ x>|D ]6}tttdddtdddf| j d| < qW xtt|dD ]}dtj	|  }ttt
| |
 df| j d	| < ttt
d
ddf| j d| < ttt
dddf| j d| < qXW ttt|t
dddf| j d< d S )N
   g    cAi!  g?g     @z%s_snr2_chi2r   g{Gzt?z%s_%s_dtg      g      ?z%s_%s_dAgɿg?i  z%s_%s_dfg{Gzg{Gz?i  z#instrumentgroup,rss_timing_residual)	densitiesr	   BinnedLnPDFNDBinsZATanLogarithmicBinsr   r   r   r   Zlight_travel_timeZATanBinsr!   )r)   r    r   pairdtr   r   r   r(      s    
6*&*zLnLRDensity.__init__c                sP   y
| j  W n" tk
r,   |   | j  Y nX |rLt fdd| D S tS )Nc             3   s   | ]\}} | | V  qd S )Nr   )r   r   value)interpsr   r   r&      s    z'LnLRDensity.__call__.<locals>.<genexpr>)r?   AttributeError	mkinterpssumitemsr   )r)   paramsr   )r?   r   __call__   s    
zLnLRDensity.__call__c             C   s   t | t |ks$t| jt|jkr<tdt | t |f x$| j D ]\}}||j| 7 }qHW y| `W n tk
r~   Y nX | S )Nzcannot add %s and %s)typesetr9   	TypeErrorrC   r?   r@   )r)   otherkeypdfr   r   r   __iadd__   s    $zLnLRDensity.__iadd__      ?c             K   s2   x,|  D ] \}}| j| j|  |7  < q
W d S )N)rC   r9   count)r)   weightrD   r   r>   r   r   r   	increment   s    zLnLRDensity.incrementc             C   s6   t | g }x$| j D ]\}}| |j|< qW |S )N)rF   r9   rC   copy)r)   newrJ   rK   r   r   r   rQ      s    zLnLRDensity.copyc             C   s   t dd | j D | _d S )Nc             s   s&   | ]\}}d |kr||  fV  qdS )rss_timing_residualN)Zmkinterp)r   rJ   rK   r   r   r   r&      s    z(LnLRDensity.mkinterps.<locals>.<genexpr>)dictr9   rC   r?   )r)   r   r   r   rA      s    zLnLRDensity.mkinterpsc          	   C   s   x| j  D ]~\}}|dr:t|jtjdddd nH|dsX|dsX|drrt|jtjddd n|dr~nt|	  qW | 
  d S )	N
_snr2_chi2      )sigmaZ_dtZ_dAZ_dfZinstrumentgroup)r9   rC   endswithr	   Zfilter_arrayr   Zgaussian_window
startswith	Exception	normalizerA   )r)   rJ   rK   r   r   r   finish   s    

zLnLRDensity.finishc                sl   t t| |}tdd | jD }|tjdt	j
| x&| j D ]\}}||| qLW |S )Nc             s   s(   | ] }| d r|ddd V  qdS )rU   _r
   r   N)rY   split)r   rJ   r   r   r   r&      s    z%LnLRDensity.to_xml.<locals>.<genexpr>r    )r'   r7   to_xmlrG   r9   appendChildligolw_paramParamZfrom_pyvaluer   instrumentspropertyrC   )r)   namexmlr    rJ   rK   )r*   r   r   r`      s    zLnLRDensity.to_xmlc             C   sL   |  ||}| tjt|d}x"|jD ]}tj	|||j|< q,W |S )Nr    )
get_xml_rootr   rd   getrb   Zget_pyvaluer9   r	   r:   from_xml)clsrf   re   r)   rJ   r   r   r   ri      s
    zLnLRDensity.from_xml)rM   )r1   r2   r3   r(   rE   rL   rP   rQ   rA   r]   r`   classmethodri   r6   r   r   )r*   r   r7      s   
r7   c                   s   e Zd ZdZejejejG dd dej	Z	dd Z
dd Z fdd	Zd
d Zdd Zdd Zdd Zedd Zedd Zdd Z  ZS )StringCoincParamsDistributionsZ#stringcusp_coincparamsdistributionsc               @   s   e Zd ZdS )z3StringCoincParamsDistributions.LIGOLWContentHandlerN)r1   r2   r3   r   r   r   r   LIGOLWContentHandler   s   rm   c             C   s4   t t|d| _ t|| _t|| _t|| _d S )Ngh㈵?)r   rT   fromkeysr7   	numeratordenominator
candidates)r)   r    r   r   r   r(      s    

z'StringCoincParamsDistributions.__init__c             C   sp   t | t |krt|t| j t|j kr<td|  j|j7  _|  j|j7  _|  j|j7  _| S )Nzincompatible instruments)	rF   rH   rG   r   r   
ValueErrorro   rp   rq   )r)   rI   r   r   r   rL     s    z'StringCoincParamsDistributions.__iadd__c                s4   t dd |D }|t dkr"tS tt| jf |S )Nc             s   s$   | ]}| d r|dd V  qdS )rU   Nr   )rY   )r   r   r   r   r   r&     s    z:StringCoincParamsDistributions.__call__.<locals>.<genexpr>)r"   r#   )rG   r   r'   rl   rE   )r)   kwargsr    )r*   r   r   rE     s    z'StringCoincParamsDistributions.__call__c             C   s<   t | g }| j|_| j |_| j |_| j |_|S )N)rF   r   ro   rQ   rp   rq   )r)   rR   r   r   r   rQ     s    z#StringCoincParamsDistributions.copyc                s  i }t |dk r|S tt|dd d}tdd |D }| j| t fdd|D \}}}}d}x,|D ]$}|jd	 |j|j f|d
|j < qlW xt	|dD ]\}}	|j|	jkst
d|j|	jf }
t|j |j  |	j |	j   }|f|d|
 < tt|j|	j }|f|d|
 < |j|jd  }|	j|	jd  }tt|t| t|t|  }|f|d|
 < qW |S )Nr   c             S   s   | j S )N)ifo)eventr   r   r   <lambda>1      z=StringCoincParamsDistributions.coinc_params.<locals>.<lambda>)rJ   c             s   s   | ]}|j V  qd S )N)rt   )r   ru   r   r   r   r&   2  s    z>StringCoincParamsDistributions.coinc_params.<locals>.<genexpr>c             3   s   | ]}|j  |j  V  qd S )N)peakrt   )r   ru   )r   r   r   r&   8  s    g        g       @z%s_snr2_chi2z%s_%s_z%sdtz%sdAz%sdf)r   tupler   r   ZsnrZchisqZ	chisq_dofrt   r   r   AssertionErrorfloatrx   mathlog10absZ	amplitudeZcentral_freq	bandwidth)r)   eventsr   rD   r    ZignoredrS   ru   Zevent1Zevent2prefixr=   ZdAZf_cut1Zf_cut2dfr   )r   r   coinc_params  s*    
(

$$,z+StringCoincParamsDistributions.coinc_paramsc             C   s   | f |  ||S )N)r   )r)   r   r   r   r   r   ln_lr_from_triggersi  s    z2StringCoincParamsDistributions.ln_lr_from_triggersc             C   s"   | j   | j  | j  | S )N)ro   r]   rp   rq   )r)   r   r   r   r]   l  s    


z%StringCoincParamsDistributions.finishc                sR   d | j f   fdd|tjjD }t|dkrJtdtjj f |d S )Nz%s:%sc                s$   g | ]}| d r|j kr|qS )Name)ZhasAttributer   )r   elem)re   r   r   r   u  s    z?StringCoincParamsDistributions.get_xml_root.<locals>.<listcomp>r
   z5XML tree must contain exactly one %s element named %sr   )ligo_lw_name_suffixZgetElementsByTagNamer   LIGO_LWZtagNamer   rr   )rj   rf   re   r   )re   r   rg   r  s
    z+StringCoincParamsDistributions.get_xml_rootc             C   sj   |  ||}| g }t|d|_t|d|_t|d|_dd |jj D }tt	
|d|_|S )Nro   rp   rq   c             S   s    g | ]}d |kr| d dqS )rU    )replace)r   rJ   r   r   r   r     s    z;StringCoincParamsDistributions.from_xml.<locals>.<listcomp>gh㈵?)rg   r7   ri   ro   rp   rq   r9   r   r   rT   rn   )rj   rf   re   r)   r    r   r   r   ri   z  s    z'StringCoincParamsDistributions.from_xmlc             C   sR   t dd|| jf i}|| jd || jd || jd |S )Nr   z%s:%sro   rp   rq   )r   r   r   ra   ro   r`   rp   rq   )r)   re   rf   r   r   r   r`     s
    z%StringCoincParamsDistributions.to_xml)r1   r2   r3   r   ligolw_arrayZuse_inrb   r   r   rm   r(   rL   rE   rQ   r   r   r]   rk   rg   ri   r`   r6   r   r   )r*   r   rl      s   
Jrl   Fc       	      C   s   d }d }xt | dD ]\}}|r<td|t| f dtjd tj||tjd}t	|d}t
j|t
j|d }|  |d kr|}n||7 }|d kr|}q||O }qW ||fS )Nr
   z%d/%d: )endfile)verboseZcontenthandlerZstring_cusp_likelihoodZlalapps_string_meas_likelihood)	enumerateprintr   sysstderrligolw_utilsZload_filenamerl   rm   ri   r   ZSearchSummaryTableZ	get_tableZget_out_segmentlistdictZProcessTableZget_ids_by_programZcoalesceunlink)		filenamesr   r   seglistsr   filenameZxmldocZthis_coinc_paramsZthis_seglistsr   r   r   load_likelihood_data  s     $r   c       	      C   s   d}|   } t|}|r*td| tjd xt|D ]z\}}|r\tdd| |  dtjd | j| |dkr|tt	t
|  |7 }q4|tt	t
| |@  |7 }q4W |rtd	tjd |S )
a  
	seglists is a segmentlistdict of times when each of a set of
	instruments were on, time_slides is a sequence of
	instrument-->offset dictionaries, each vector of offsets in the
	sequence is applied to the segmentlists and the total time during
	which at least min_instruments were on is summed and returned.  If
	clip is not None, after each offset vector is applied to seglists
	the result is intersected with clip before computing the livetime.
	If verbose is True then progress reports are printed to stderr.
	g        z+computing the live time for %d time slides:)r   z	%.1f%%g      Y@r   )r   r   Nz	100.0%)rQ   r   r   r   r   r   offsetsupdater{   r~   segmentsUtilsZvotevalues)	r   time_slidesZmin_instrumentsr   cliplivetimeNr   
time_slider   r   r   time_slides_livetime  s    $r   c          	   C   s  d}| j |d}| j t| t| d}t|}|rPtdd||f tjd xt|D ]\}	}
|rtdd|	 |  dtjd	 |j	|
 |j	|
 |d
kr|t
t|| ||  7 }qZ|t
t||@ | ||  7 }qZW |rtdtjd |S )z
	like time_slides_livetime() except computes the time for which
	exactly the instruments given by the sequence instruments were on
	(and nothing else).
	g        )r   z1computing the live time for %s in %d time slides:z, )r   z	%.1f%%g      Y@r   )r   r   Nz	100.0%)rQ   rG   r   r   joinr   r   r   r   r   r{   r~   intersectionr   union)r   r   r    r   r   r   Z
onseglistsZoffseglistsr   r   r   r   r   r   )time_slides_livetime_for_instrument_combo  s"    *0r   c             C   s,   |   }|d |d|f |  dS )a  
	Create a temporary table named "recovered_ln_likelihood_ratio"
	containing two columns:  "simulation_id", the simulation_id of an
	injection, and "ln_likelihood_ratio", the highest log likelihood
	ratio at which that injection was recovered by a coincidence of
	type coinc_def_id.
	zr
CREATE TEMPORARY TABLE recovered_ln_likelihood_ratio (simulation_id TEXT PRIMARY KEY, ln_likelihood_ratio REAL)
	a  
INSERT OR REPLACE INTO
	recovered_ln_likelihood_ratio
SELECT
	sim_burst.simulation_id AS simulation_id,
	MAX(coinc_event.likelihood) AS ln_likelihood_ratio
FROM
	sim_burst
	JOIN coinc_event_map AS a ON (
		a.table_name == "sim_burst"
		AND a.event_id == sim_burst.simulation_id
	)
	JOIN coinc_event_map AS b ON (
		b.coinc_event_id == a.coinc_event_id
	)
	JOIN coinc_event ON (
		b.table_name == "coinc_event"
		AND b.event_id == coinc_event.coinc_event_id
	)
WHERE
	coinc_event.coinc_def_id == ?
GROUP BY
	sim_burst.simulation_id
	N)cursorexecuteclose)
connectioncoinc_def_idr   r   r   r   *create_recovered_ln_likelihood_ratio_table  s    
r   c             C   s   |   d|f dS )z@
	Construct a sim_burst --> best matching coinc_event mapping.
	a  
CREATE TEMPORARY TABLE
	sim_burst_best_string_sngl_map
AS
	SELECT
		sim_burst.simulation_id AS simulation_id,
		(
			SELECT
				sngl_burst.event_id
			FROM
				coinc_event_map AS a
				JOIN coinc_event_map AS b ON (
					b.coinc_event_id == a.coinc_event_id
				)
				JOIN coinc_event ON (
					coinc_event.coinc_event_id == a.coinc_event_id
				)
				JOIN sngl_burst ON (
					b.table_name == 'sngl_burst'
					AND b.event_id == sngl_burst.event_id
				)
			WHERE
				a.table_name == 'sim_burst'
				AND a.event_id == sim_burst.simulation_id
				AND coinc_event.coinc_def_id == ?
			ORDER BY
				(sngl_burst.chisq / sngl_burst.chisq_dof) / (sngl_burst.snr * sngl_burst.snr)
			LIMIT 1
		) AS event_id
	FROM
		sim_burst
	WHERE
		event_id IS NOT NULL
	N)r   r   )r   r   r   r   r   %create_sim_burst_best_string_sngl_map  s    !r   c             C   s   |   d|f dS )zg
	Construct a sim_burst --> best matching coinc_event mapping for
	string cusp injections and coincs.
	a  
CREATE TEMPORARY TABLE
	sim_burst_best_string_coinc_map
AS
	SELECT
		sim_burst.simulation_id AS simulation_id,
		(
			SELECT
				coinc_inspiral.coinc_event_id
			FROM
				coinc_event_map AS a
				JOIN coinc_event_map AS b ON (
					b.coinc_event_id == a.coinc_event_id
				)
				JOIN coinc_inspiral ON (
					b.table_name == 'coinc_event'
					AND b.event_id == coinc_inspiral.coinc_event_id
				)
			WHERE
				a.table_name == 'sim_burst'
				AND a.event_id == sim_burst.simulation_id
				AND coinc_event.coinc_def_id == ?
			ORDER BY
				(sngl_burst.chisq / sngl_burst.chisq_dof) / (sngl_burst.snr * sngl_burst.snr)
			LIMIT 1
		) AS coinc_event_id
	FROM
		sim_burst
	WHERE
		coinc_event_id IS NOT NULL
	N)r   r   )r   r   r   r   r   &create_sim_burst_best_string_coinc_mapC  s    r   )F)FN)FN)3Zfpconstr   ImportErrorr{   r   r|   r-   Zscipy.statsZscipyr   Zligo.lwr   r   r   r   rb   r   r   r   Zligo.lw.utilsr   Zligolw_processr   r	   Zligo.segmentsr   r   r   r   
__author__Zgit_versionr   __date__r   __version__r   ZHashableBinsr!   r;   Zxml_bins_name_mappingr   r5   r7   ZLnLikelihoodRatioMixinrl   r   r   r   r   r   r   r   r   r   r   <module>   sH   0	T #


%'(