B
    d0             ,   @   s<  d Z ddlZddlZddlZddlZddlZ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ZddlmZ ddlmZmZmZ ddlmZ dd	lmZ dd
lmZ dddZdd ZG dd deZG dd deZG dd deZG dd deZej !dZ"G dd dej#Z$G dd dej#j%Z&e&e$_%G dd dej#Z'G dd dej#j%Z(e(e'_%G d d! d!ej#Z)G d"d# d#ej#j%Z*e*e)_%ej !d$Z+G d%d& d&ej#Z,G d'd( d(ej#j%Z-e-e,_%ej !d)Z.G d*d+ d+ej#Z/G d,d- d-ej#j%Z0e0e/_%ej !d)Z1G d.d/ d/ej#Z2G d0d1 d1ej#j%Z3e3e2_%G d2d3 d3ej#Z4G d4d5 d5ej#j%Z5e5e4_%ej !d)Z6G d6d7 d7ej#Z7G d8d9 d9ej#j%Z8e8e7_%G d:d; d;ej#Z9G d<d= d=ej#j%Z:e:e9_%ej !d>Z;G d?d@ d@ej#Z<G dAdB dBej#j%Z=e=e<_%ej !d>Z>G dCdD dDej#Z?G dEdF dFej#j%Z@e@e?_%ej !d>ZAG dGdH dHej#ZBG dIdJ dJej#j%ZCeCeB_%ej !dKZDG dLdM dMej#ZEG dNdO dOej#j%ZFeFeE_%ej !dPZGG dQdR dRej#ZHejIG dSdT dTej#j%ZJeJeH_%ej !dUZKG dVdW dWej#ZLG dXdY dYej#j%ZMeMeL_%ej !dZZNG d[d\ d\ej#ZOG d]d^ d^eJZPePeO_%ej !d_ZQG d`da daej#ZRG dbdc dcej#j%ZSeSeR_%ej !ddZTG dedf dfej#ZUG dgdh dhej#j%ZVeVeU_%ej !diZWG djdk dkej#ZXG dldm dmej#j%ZYeYeX_%G dndo doej#ZZG dpdq dqej#j%Z[e[eZ_%ej !drZ\ej !dsZ]G dtdu duej#Z^G dvdw dwej#j%Z_e_e^_%G dxdy dyej#Z`G dzd{ d{ej#j%Zaeae`_%eUjbeUe4jbe4eZjbeZe9jbe9eXjbeXe^jbe^e'jbe'e$jbe$e)jbe)e,jbe,eLjbeLeOjbeOeHjbeHe?jbe?e<jbe<eBjbeBe/jbe/e2jbe2e7jbe7eEjbeEeRjbeRe`jbe`iZcd|d} Zdd~d ZedS )aU  
LSC Table definitions.

See the LDAS CVS repository at
http://www.ldas-sw.ligo.caltech.edu/cgi-bin/cvsweb.cgi/ldas/dbms/db2/sql
for more information.


Customization
-------------

In some cases, applications will need to define sub-classes of the table
and row classes found here or will need to define their own custom tables
altogether.  Once the custom classes are defined, the following steps are
required to incorporate them into this module's document handling
machinery.

Firstly, if a new Table class is defined, the TableByName mapping defined
in this module should be updated.  The TableByName mapping is used to map
table names to corresponding Python classes.  This mapping is used when
parsing XML documents, when extracting the contents of SQL databases and
any other place the conversion from a name to a class definition is
required.  Once the mapping is updated, XML documents containing Table
elements whose names match the custom definition will be converted to
instances of that class (Tables whose names are not recognized are loaded
as instances of the generic ligo.lw.Table class).

Example:

>>> class MyCustomTable(table.Table):
...	tableName = "custom"
...
>>> TableByName[MyCustomTable.tableName] = MyCustomTable

The row type to be used with a table is selected using the .RowType
attribute of the corresponding Table class.  When parsing an XML document
the text is converted into row objects, each of which is created by calling
the .RowType attribute with no arguments.

Example:

>>> class MyCustomTableRow(table.Table.RowType):
...	pass
...
>>> MyCustomTable.RowType = MyCustomTableRow
    N)sax)segments)LIGOTimeGPS   )
__author____date____version__)ligolw)table)typesc          
   K   s   | t jd| j| jif|}x(|dk	r0|nt|jD ]}|| q:W |	  |
tt j|dtjjjtjjjd |S )a  
	Construct a pre-defined LSC table.  The optional columns argument
	is a sequence of the names of the columns the table is to be
	constructed with.  If columns = None, then the table is constructed
	with all valid columns (use columns = [] to create a table with no
	columns).

	Example:

	>>> import sys
	>>> tbl = New(ProcessTable, [u"process_id", u"start_time", u"end_time", u"comment"])
	>>> tbl.write(sys.stdout)	# doctest: +NORMALIZE_WHITESPACE
	<Table Name="process:table">
		<Column Name="process_id" Type="int_8s"/>
		<Column Name="start_time" Type="int_4s"/>
		<Column Name="end_time" Type="int_4s"/>
		<Column Name="comment" Type="lstring"/>
		<Stream Name="process:table" Delimiter="," Type="Local">
		</Stream>
	</Table>
	NameN)r   	DelimiterType)r   Z	xmlreaderZAttributesImpl	TableNameenc	tableNamesortedvalidcolumnsZappendColumnZ_end_of_columnsZappendChildr
   ZTableStreamZgetAttributer   defaultr   )clscolumnskwargsnewname r   ^/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/ligo/lw/lsctables.pyNew   s    "2r   c             C   s   t dd | tjjD S )za
	Return True if the document tree below elem contains non-LSC
	tables, otherwise return False.
	c             s   s   | ]}|j tkV  qd S )N)r   TableByName).0tr   r   r   	<genexpr>   s    z"HasNonLSCTables.<locals>.<genexpr>)anyZgetElementsByTagNamer	   TableZtagName)elemr   r   r   HasNonLSCTables   s    r$   c               @   s>   e Zd Zdd Zedd Zedd Zddd	Zd
d ZdS )instrumentspropertyc             C   s
   || _ d S )N)r   )selfr   r   r   r   __init__   s    zinstrumentsproperty.__init__c                s    dkrdS d kr:t dd  dD }|d |S d krht dd  dD }|d |S    t dkrt d st  fd	dtd
t dD S  rt  gS t  S )a  
		Parse the values stored in the "ifos" and "instruments"
		columns found in many tables.  This function is mostly for
		internal use by the .instruments properties of the
		corresponding row classes.  The mapping from input to
		output is as follows (rules are applied in order):

		input is None --> output is None

		input contains "," --> output is set of strings split on
		"," with leading and trailing whitespace stripped from each
		piece and empty strings removed from the set

		input contains "+" --> output is set of strings split on
		"+" with leading and trailing whitespace stripped from each
		piece and empty strings removed from the set

		else, after stripping input of leading and trailing
		whitespace,

		input has an even length greater than two --> output is set
		of two-character pieces

		input is a non-empty string --> output is a set containing
		input as single value

		else output is an empty set.

		NOTE:  the complexity of this algorithm is a consequence of
		there being several conventions in use for encoding a set
		of instruments into one of these columns;  it has been
		proposed that L.L.W.  documents standardize on the
		comma-delimited variant of the encodings recognized by this
		function, and for this reason the inverse function,
		instrumentsproperty.set(), implements that encoding only.

		NOTE:  to force a string containing an even number of
		characters to be interpreted as a single instrument name
		and not to be be split into two-character pieces, add a ","
		character to the end to force the comma-delimited decoding
		to be used.  instrumentsproperty.set() does this for you.

		Example:

		>>> print(instrumentsproperty.get(None))
		None
		>>> assert instrumentsproperty.get(u"") == set([])
		>>> assert instrumentsproperty.get(u"  ,  ,,") == set([])
		>>> assert instrumentsproperty.get(u"H1") == set([u'H1'])
		>>> assert instrumentsproperty.get(u"SWIFT") == set([u'SWIFT'])
		>>> assert instrumentsproperty.get(u"H1L1") == set([u'H1', u'L1'])
		>>> assert instrumentsproperty.get(u"H1L1,") == set([u'H1L1'])
		>>> assert instrumentsproperty.get(u"H1,L1") == set([u'H1', u'L1'])
		>>> assert instrumentsproperty.get(u"H1+L1") == set([u'H1', u'L1'])
		N,c             s   s   | ]}|  V  qd S )N)strip)r   ifor   r   r   r       s    z*instrumentsproperty.get.<locals>.<genexpr> +c             s   s   | ]}|  V  qd S )N)r)   )r   r*   r   r   r   r       s       c             3   s   | ]} ||d   V  qdS )r-   Nr   )r   n)ifosr   r   r       s    r   )setsplitdiscardr)   lenrange)r/   resultr   )r/   r   get   s     9

"
zinstrumentsproperty.getc             C   s   | dkrdS t tdd | D }t|r<tdd |D rDt| t|dkr|t|d dkr|t|d d s|d|d  S d	|S )
a  
		Convert an iterable of instrument names into a value
		suitable for storage in the "ifos" column found in many
		tables.  This function is mostly for internal use by the
		.instruments properties of the corresponding row classes.
		The input can be None or an iterable of zero or more
		instrument names, none of which may be zero-length, consist
		exclusively of spaces, or contain "," or "+" characters.
		The output is a single string containing the unique
		instrument names concatenated using "," as a delimiter.
		instruments will only be iterated over once and so can be a
		generator expression.  Whitespace is allowed in instrument
		names but might not be preserved.  Repeated names will not
		be preserved.

		NOTE:  in the special case that there is 1 instrument name
		in the iterable and it has an even number of characters > 2
		in it, the output will have a "," appended in order to
		force instrumentsproperty.get() to parse the string back
		into a single instrument name.  This is a special case
		included temporarily to disambiguate the encoding until all
		codes have been ported to the comma-delimited encoding.
		This behaviour will be discontinued at that time.  DO NOT
		WRITE CODE THAT RELIES ON THIS!  You have been warned.

		Example:

		>>> print(instrumentsproperty.set(None))
		None
		>>> assert instrumentsproperty.set(()) == u''
		>>> assert instrumentsproperty.set((u"H1",)) == u'H1'
		>>> assert instrumentsproperty.set((u"H1",u"H1",u"H1")) == u'H1'
		>>> assert instrumentsproperty.set((u"H1",u"L1")) == u'H1,L1'
		>>> assert instrumentsproperty.set((u"SWIFT",)) == u'SWIFT'
		>>> assert instrumentsproperty.set((u"H1L1",)) == u'H1L1,'
		Nc             s   s   | ]}|  V  qd S )N)r)   )r   
instrumentr   r   r   r    "  s    z*instrumentsproperty.set.<locals>.<genexpr>c             s   s   | ]}d |kpd|kV  qdS )r(   r,   Nr   )r   r7   r   r   r   r    &  s    r   r   r-   z%s,r(   )r   r0   allr!   
ValueErrorr3   join)instrumentsZ_instrumentsr   r   r   r0      s    &,zinstrumentsproperty.setNc             C   s   |  t|| jS )N)r6   getattrr   )r&   objr   r   r   r   __get__.  s    zinstrumentsproperty.__get__c             C   s   t || j| | d S )N)setattrr   r0   )r&   r=   r;   r   r   r   __set__1  s    zinstrumentsproperty.__set__)N)	__name__
__module____qualname__r'   staticmethodr6   r0   r>   r@   r   r   r   r   r%      s
   O4
r%   c               @   s:   e Zd ZdZdd ZdZdZeefZdddZd	d
 Z	dS )gpspropertya  
	Descriptor used internally to implement LIGOTimeGPS-valued
	properties using pairs of integer attributes on row objects, one
	for the integer seconds part of the GPS time and one for the
	integer nanoseconds part.

	Non-LIGOTimeGPS values are converted to LIGOTimeGPS before encoding
	them into the integer attributes.  None is allowed as a special
	case, which is encoded by setting both column attributes to None.

	For the purpose of representing the boundaries of unbounded
	segments (open-ended time intervals), +inf and -inf are also
	allowed, and will be encoded into and decoded out of the integer
	attributes.  To do so, a non-standard encoding is used that makes
	use of denormalized GPS times, that is times whose nanosecond
	component has a magnitude greater than 999999999.  Two such values
	are reserved for +/- infinity.  To guard against the need for
	additional special encodings in the future, this descriptor
	reserves all denormalized values and will not allow calling code to
	set GPS times to those values.  Calling code must provide
	normalized GPS times, times with nanosecond components whose
	magnitudes are not greater than 999999999.  When decoded, the
	values reported are segments.PosInfinity or segments.NegInfinity.
	c             C   s(   || _ t|| _|| _t|| _d S )N)s_nameoperator
attrgetterget_sns_nameget_ns)r&   rF   rJ   r   r   r   r'   N  s    zgpsproperty.__init__)il    )l    l    Nc             C   sr   |  |}| |}|d kr(|d kr(d S |dkrh||f| jkrDtjS ||f| jkrXtjS td||f t||S )Nl    z3unrecognized denormalized number LIGOTimeGPS(%d,%d))	rI   rK   posinfr   ZPosInfinityneginfZNegInfinityr9   r   )r&   r=   r   snsr   r   r   r>   X  s    

zgpsproperty.__get__c             C   s   |d krd  }}nt |tjs(t|rZ|dkr<| j\}}q|dk rP| j\}}qt|nNy|j}|j	}W n  t
k
r   | |t|S X t|dkrtd||f t|| j| t|| j| d S )Nr   iɚ;z9denormalized LIGOTimeGPS not allowed: LIGOTimeGPS(%d, %d))
isinstancer   infinitymathisinfrL   rM   r9   Z
gpsSecondsZgpsNanoSecondsAttributeErrorr@   r   absr?   rF   rJ   )r&   r=   gpsrN   rO   r   r   r   r@   e  s"    


zgpsproperty.__set__)N)
rA   rB   rC   __doc__r'   rL   rM   Zinfsr>   r@   r   r   r   r   rE   5  s   
rE   c                   s,   e Zd ZdZ fddZ fddZ  ZS )gpsproperty_with_gmsta  
	Variant of the gpsproperty descriptor, adding support for a third
	"GMST" column.  When assigning a time to the GPS-valued descriptor,
	after the pair of integer attributes are set to the encoded form of
	the GPS time, the value is retrieved and the GMST column is set to
	the Greenwhich mean sidereal time corresponding to that GPS time.
	Note that the conversion to sidereal time is performed after
	encoding the GPS time into the integer seconds and nanoseconds
	attributes, so the sidereal time will reflect any rounding that has
	occured as a result of that encoding.  If the GPS time is set to
	None or +inf or -inf, the sidereal time is set to that value as
	well.
	c                s   t t| || || _d S )N)superrX   r'   	gmst_name)r&   rF   rJ   rZ   )	__class__r   r   r'     s    zgpsproperty_with_gmst.__init__c                s   t t| || |d kr*t|| jd  nl| |}t|tjsVt|| jt	
| n@|dkrrt|| jtd n$|dk rt|| jtd nt|d S )Nr   z+infz-inf)rY   rX   r@   r?   rZ   r>   rP   r   rQ   lalGreenwichMeanSiderealTimefloatr9   )r&   r=   rV   )r[   r   r   r@     s    
zgpsproperty_with_gmst.__set__)rA   rB   rC   rW   r'   r@   __classcell__r   r   )r[   r   rX   |  s   rX   c               @   s*   e Zd ZdZdd Zd	ddZdd ZdS )
segmentpropertya  
	Descriptor used internally to expose pairs of GPS-valued properties
	as segment-valued properties.  A segment may be set to None, which
	is encoded by setting both GPS-valued properties to None.  Likewise
	if both GPS-valued properties are set to None then the value
	reported by this descriptor is None, not (None, None).

	See the documentation for gpsproperty for more information on the
	encodings it uses for special values and the limitations they
	create.
	c             C   s   || _ || _d S )N)startstop)r&   Z
start_nameZ	stop_namer   r   r   r'     s    zsegmentproperty.__init__Nc             C   s8   t || j}t || j}|d kr,|d kr,d S t||S )N)r<   ra   rb   r   segment)r&   r=   r   ra   rb   r   r   r   r>     s
    zsegmentproperty.__get__c             C   s:   |d krd  }}n|\}}t || j| t || j| d S )N)r?   ra   rb   )r&   r=   segra   rb   r   r   r   r@     s
    
zsegmentproperty.__set__)N)rA   rB   rC   rW   r'   r>   r@   r   r   r   r   r`     s   
r`   
process_idc               @   sT   e Zd ZdZddddddddddddddddZdZedZdd	 Ze	d
d Z
dS )ProcessTableprocesslstringint_4sint_8s)programversioncvs_repositorycvs_entry_timecomment	is_onlinenodeusernameunix_procid
start_timeend_timejobiddomainr/   re   zPRIMARY KEY (process_id)r   c                s   t  fdd| D S )zh
		Return a set containing the process IDs from rows whose
		program string equals the given program.
		c             3   s   | ]}|j  kr|jV  qd S )N)rk   re   )r   row)rk   r   r   r      s    z2ProcessTable.get_ids_by_program.<locals>.<genexpr>)r0   )r&   rk   r   )rk   r   get_ids_by_program  s    zProcessTable.get_ids_by_programc           	   C   s|   y
t jd S  tk
r   Y nX y
t jd S  tk
r>   Y nX yddl} | t  d S  ttfk
rv   tY nX dS )af  
		Utility to help retrieve a sensible value for the current
		username.  First the environment variable LOGNAME is tried,
		if that is not set the environment variable USERNAME is
		tried, if that is not set the password database is
		consulted (only on Unix systems, if the import of the pwd
		module succeeds), finally if that fails KeyError is raised.
		LOGNAMEUSERNAMEr   N)osenvironKeyErrorpwdgetpwuidgetuidImportError)r   r   r   r   get_username  s    


zProcessTable.get_usernameN)rA   rB   rC   r   r   constraints	ProcessIDnext_idry   rD   r   r   r   r   r   rf     s(   rf   c               @   s   e Zd ZdZeeejje	j
Zedd Zejdd Zedd Zejdd ZedZed	d
ZeddZeddZedddZdd ZdS )ProcessaW  
	Example:

	>>> x = Process()
	>>> x.instruments = (u"H1", u"L1")
	>>> assert x.ifos == u'H1,L1'
	>>> assert x.instruments == set([u'H1', u'L1'])
	>>> # truncates to integers
	>>> x.start = 10.5
	>>> x.start
	LIGOTimeGPS(10, 0)
	>>> x.end = 20.5
	>>> x.end
	LIGOTimeGPS(20, 0)
	>>> x.segment
	segment(LIGOTimeGPS(10, 0), LIGOTimeGPS(20, 0))
	c             C   s   dS )Nr   r   )eslfr   r   r   start_time_ns  s    zProcess.start_time_nsc             C   s   d S )Nr   )r&   valr   r   r   r     s    c             C   s   dS )Nr   r   )r   r   r   r   end_time_ns  s    zProcess.end_time_nsc             C   s   d S )Nr   )r&   r   r   r   r   r   !  s    r/   rt   r   ru   r   ra   endNFr   c             C   s   | ||||dk	r"t t|dnd|t|t t t t	 d|||	d}yt
 |_W n tk
rz   d|_Y nX |
dk	r|
|_|S )a  
		Create a new Process object and initialize its attributes
		to sensible defaults.  If not None, program, version,
		cvs_repository, comment, and domain should all be strings
		or unicodes.  If cvs_entry_time is not None, it must be a
		string or unicode in the format "YYYY-MM-DD HH:MM:SS".
		is_online should be boolean, jobid an integer.  If not
		None, instruments must be an iterable (set, tuple, etc.) of
		instrument names (strings or unicodes).

		In addition, .node is set to the current hostname,
		.unix_procid is set to the current process ID, .username is
		set to the current user's name, .start_time is set to the
		current GPS time.

		Note:  if the process_id keyword argument is None (the
		default), then the process_id attribute is not set, it is
		left uninitialized rather than setting it to None.  It must
		be initialized before the row object can be written to a
		file, and so in this way the calling code is required to
		provide a proper value for it.

		Example:

		>>> process = Process.initialized()
		Nz%Y-%m-%d %H:%M:%S +0000)rk   rl   rm   rn   ro   rp   rq   rs   rt   ru   rv   rw   r;   )r\   UTCToGPStimestrptimeintsocketgethostnamer|   getpidgmtimerf   r   rr   r~   re   )r   rk   rl   rm   rn   ro   rp   rv   rw   r;   re   r&   r   r   r   initialized*  s*    zProcess.initializedc             C   s   t t | _dS )z,
		Set .end_time to the current GPS time.
		N)r\   r   r   r   ru   )r&   r   r   r   set_end_time_now]  s    zProcess.set_end_time_now)
NNNNNFr   NNN)rA   rB   rC   rW   tuplemapr
   Column
ColumnNamerf   r   	__slots__propertyr   setterr   r%   r;   rE   ra   r   r`   rc   classmethodr   r   r   r   r   r   r     s   


2r   c                   s8   e Zd ZdZddddddZddiZ fddZ  ZS )	ProcessParamsTableZprocess_paramsrh   rj   )rk   zprocess:process_idparamtypevalueZpp_pip_index)re   r   c                sD   |j d k	r0|j tjkr0td|j |j|jf tt| 	| d S )Nz0unrecognized type '%s' for process %d param '%s')
r   ligolwtypesZTypesr	   ZElementErrorre   r   rY   r   append)r&   rx   )r[   r   r   r     s    zProcessParamsTable.append)rA   rB   rC   r   r   how_to_indexr   r_   r   r   )r[   r   r   p  s   r   c               @   s>   e Zd ZdZeeejje	j
Zedd Zejdd ZdS )ProcessParamsa  
	Example:

	>>> x = ProcessParams()
	>>> x.pyvalue = u"test"
	>>> print(x.type)
	lstring
	>>> print(x.value)
	test
	>>> print(x.pyvalue)
	test
	>>> x.pyvalue = 6.
	>>> print(x.type)
	real_8
	>>> assert x.value == u'6'
	>>> print(x.pyvalue)
	6.0
	>>> x.pyvalue = None
	>>> print(x.type)
	None
	>>> print(x.value)
	None
	>>> print(x.pyvalue)
	None
	>>> x.pyvalue = True
	>>> print(x.type)
	int_4s
	>>> assert x.value == u'1'
	>>> x.pyvalue
	1
	c             C   sL   | j d krd S ytj| j }W n" tk
r@   td| j Y nX || j S )Nzinvalid type '%s')r   r   ZToPyTyper   r~   r9   )r&   Z	parsefuncr   r   r   pyvalue  s    
zProcessParams.pyvaluec             C   sz   |d krd  | _ | _n`ytjt | | _ W n( tk
rR   tdtt | Y nX | j tjkrd|ntj| j  || _d S )Nztype not supported: %s)	r   r   r   Z
FromPyTyper~   r9   reprZStringTypesZ
FormatFunc)r&   r   r   r   r   r     s    N)rA   rB   rC   rW   r   r   r
   r   r   r   r   r   r   r   r   r   r   r   r   r     s   
r   c               @   sR   e Zd ZdZdddddddddddddddddZddiZdd	d
ZdddZdS )SearchSummaryTableZsearch_summaryrj   rh   ri   )zprocess:process_idshared_objectlalwrapper_cvs_taglal_cvs_tagro   r/   in_start_timein_start_time_nsin_end_timein_end_time_nsout_start_timeout_start_time_nsout_end_timeout_end_time_nsneventsnnodesZss_pi_index)re   Nc                sR   t  }xD| D ]<  jpd}|dks. j|kr|t fdd|D  qW |S )aT  
		Return a segmentlistdict mapping instrument to in segment
		list.  If process_ids is a sequence of process IDs, then
		only rows with matching IDs are included otherwise all rows
		are included.

		Note:  the result is not coalesced, each segmentlist
		contains the segments listed for that instrument as they
		appeared in the table.
		)NNc             3   s    | ]}|t  jgfV  qd S )N)r   segmentlist
in_segment)r   r*   )rx   r   r   r      s    z<SearchSummaryTable.get_in_segmentlistdict.<locals>.<genexpr>)r   segmentlistdictr;   re   extenddict)r&   process_idsseglistsr/   r   )rx   r   get_in_segmentlistdict  s    

 z)SearchSummaryTable.get_in_segmentlistdictc                sR   t  }xD| D ]<  jpd}|dks. j|kr|t fdd|D  qW |S )aU  
		Return a segmentlistdict mapping instrument to out segment
		list.  If process_ids is a sequence of process IDs, then
		only rows with matching IDs are included otherwise all rows
		are included.

		Note:  the result is not coalesced, each segmentlist
		contains the segments listed for that instrument as they
		appeared in the table.
		)NNc             3   s    | ]}|t  jgfV  qd S )N)r   r   out_segment)r   r*   )rx   r   r   r      s    z=SearchSummaryTable.get_out_segmentlistdict.<locals>.<genexpr>)r   r   r;   re   r   r   )r&   r   r   r/   r   )rx   r   get_out_segmentlistdict  s    

 z*SearchSummaryTable.get_out_segmentlistdict)N)N)rA   rB   rC   r   r   r   r   r   r   r   r   r   r     s(   
r   c            
   @   sv   e Zd ZdZeeejje	j
ZedZeddZeddZeddZed	d
ZeddZeddZedddZdS )SearchSummarya  
	Example:

	>>> x = SearchSummary()
	>>> x.instruments = (u"H1", u"L1")
	>>> print(x.ifos)
	H1,L1
	>>> assert x.instruments == set([u'H1', u'L1'])
	>>> x.in_start = x.out_start = LIGOTimeGPS(0)
	>>> x.in_end = x.out_end = LIGOTimeGPS(10)
	>>> x.in_segment
	segment(LIGOTimeGPS(0, 0), LIGOTimeGPS(10, 0))
	>>> x.out_segment
	segment(LIGOTimeGPS(0, 0), LIGOTimeGPS(10, 0))
	>>> x.in_segment = x.out_segment = None
	>>> print(x.in_segment)
	None
	>>> print(x.out_segment)
	None
	r/   r   r   r   r   r   r   r   r   in_startin_end	out_startout_end
standaloner+   Nr   r   c             C   s2   | |j ||||p|j|dk	r |n|j|||	|
d
S )z
		Create and return a sensibly initialized row for the
		search_summary table.  process is an initialized row for
		the process table.
		N)
re   r   r   r   ro   r;   r   r   r   r   )re   ro   r;   )r   rg   r   r   r   ro   r/   ZinsegZoutsegr   r   r   r   r   r   '  s    zSearchSummary.initialized)	r   r+   r+   NNNNr   r   )rA   rB   rC   rW   r   r   r
   r   r   r   r   r   r%   r;   rE   r   r   r   r   r`   r   r   r   r   r   r   r   r   r     s   





r   search_summvar_idc               @   s,   e Zd ZdZddddddZdZedZdS )	SearchSummVarsTableZsearch_summvarsrj   rh   real_8)zprocess:process_idr   r   stringr   zPRIMARY KEY (search_summvar_id)r   N)rA   rB   rC   r   r   r   SearchSummVarsIDr   r   r   r   r   r   K  s   r   c               @   s    e Zd Zeeejjej	Z
dS )SearchSummVarsN)rA   rB   rC   r   r   r
   r   r   r   r   r   r   r   r   r   r   X  s   r   event_idc            1   @   s   e Zd ZdZddddddddddddddddddddddddddddddddddddddddddddddddd0ZdZed	Zd
S )SnglBurstTableZ
sngl_burstri   rj   rh   real_4r   )0
creator_dbzprocess:process_idzfilter:filter_idr*   searchchannelrt   r   	stop_timestop_time_nsdurationflowfhighcentral_freq	bandwidth	amplitudesnr
confidencechisq	chisq_dofZtfvolumehrssZtime_lag	peak_timepeak_time_nsZpeak_frequencyZpeak_strainZpeak_time_errorZpeak_frequency_errorZpeak_strain_errorms_start_timems_start_time_nsms_stop_timems_stop_time_nsms_durationms_flowms_fhighms_bandwidthZms_hrssZms_snrZms_confidenceZparam_one_nameZparam_one_valueZparam_two_nameZparam_two_valueZparam_three_nameZparam_three_valuer   zPRIMARY KEY (event_id)r   N)rA   rB   rC   r   r   r   SnglBurstIDr   r   r   r   r   r   k  sf   r   c               @   s   e Zd Zeeejjej	Z
eddZeddZeddZedd Zejd	d Zed
d Zejdd ZeddZeddZeddZedd Zejdd Zedd Zejdd ZdS )	SnglBurstrt   r   r   r   r   r   c             C   sn   | j }y
| j}W n tk
r(   d }Y nX |d k	rN|d krN| jd k	rN|| j }|d krb|d krbd S t||S )N)ra   rb   rT   r   r   rc   )r&   ra   rb   r   r   r   period  s    


zSnglBurst.periodc             C   s:   |d krd  | _  | _| _n|\| _ | _tt|| _d S )N)ra   rb   r   r^   rU   )r&   rd   r   r   r   r     s    c             C   s<   | j d kr| jd krd S t| j | jd  | j | jd  S )Ng       @)r   r   r   rc   )r&   r   r   r   band  s    zSnglBurst.bandc             C   s~   |d kr<yd  | _ | _W n tk
r,   Y nX d  | _| _n>y|\| _ | _W n tk
r`   Y nX t|d | _t|| _d S )Ng       @)r   r   rT   r   r   sumrU   )r&   rd   r   r   r   r     s    r   r   r   r   Zms_peak_timeZms_peak_time_nsc             C   sT   | j }| j}|d k	r4|d kr4| jt d k	r4|| j }|d krH|d krHd S t||S )N)ms_startms_stopmsr   r   r   rc   )r&   ra   rb   r   r   r   	ms_period  s    
zSnglBurst.ms_periodc             C   s:   |d krd  | _  | _| _n|\| _ | _tt|| _d S )N)r   r   r   r^   rU   )r&   rd   r   r   r   r     s    c             C   s.   | j d kr| jd krd S t| j | j | j S )N)r   r   r   rc   )r&   r   r   r   ms_band  s    zSnglBurst.ms_bandc             C   s6   |d krd  | _  | _| _n|\| _| _t|| _ d S )N)r   r   r   rU   )r&   rd   r   r   r   r     s    N)rA   rB   rC   r   r   r
   r   r   r   r   r   rE   ra   rb   Zpeakr   r   r   r   r   r   Zms_peakr   r   r   r   r   r   r     s   





r   c            A   @   s   e Zd ZdZddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd@ZdZed	Zd
S )SnglInspiralTableZsngl_inspiralrj   rh   ri   r   r   )@zprocess:process_idr*   r   r   ru   r   end_time_gmstZimpulse_timeZimpulse_time_nsZtemplate_durationZevent_durationr   Zeff_distance	coa_phasemass1mass2mchirpZmtotaletakappachiZtau0Ztau2Ztau3Ztau4Ztau5Zttotalpsi0psi3alphaalpha1alpha2alpha3alpha4alpha5alpha6betaf_finalr   r   r   Z
bank_chisqZbank_chisq_dofZ
cont_chisqZcont_chisq_dofZsigmasqZrsqveto_durationGamma0ZGamma1ZGamma2ZGamma3ZGamma4ZGamma5ZGamma6ZGamma7ZGamma8ZGamma9spin1xspin1yspin1zspin2xspin2yspin2zr   zPRIMARY KEY (event_id)r   N)rA   rB   rC   r   r   r   SnglInspiralIDr   r   r   r   r   r     s   r   c               @   s   e Zd Zeeejjej	Z
edddZedddZedd Zejd	d Zed
d Zejdd Zedd Zejdd Zdd ZdS )SnglInspiralffffff?c             C   s   | d| | d  S )Ng ڌ?g?r   )distr   Zref_massr   r   r   chirp_distance`  s    zSnglInspiral.chirp_distanceru   r   r   c             C   s<   | j d kr"| jd kr"| jd kr"d S tj| j | j| jfddS )Ndouble)dtype)r	  r
  r  numpyarray)r&   r   r   r   spin1j  s    zSnglInspiral.spin1c             C   s0   |d krd  | _  | _| _n|\| _ | _| _d S )N)r	  r
  r  )r&   spinr   r   r   r  p  s    c             C   s<   | j d kr"| jd kr"| jd kr"d S tj| j | j| jfddS )Nr  )r  )r  r  r  r  r  )r&   r   r   r   spin2w  s    zSnglInspiral.spin2c             C   s0   |d krd  | _  | _| _n|\| _ | _| _d S )N)r  r  r  )r&   r  r   r   r   r  }  s    c             C   s
   t | jS )N)r   r  )r&   r   r   r   template_id  s    zSnglInspiral.template_idc             C   s   t || _d S )N)r^   r  )r&   r  r   r   r   r    s    c             C   sT   | j |j koR| j|jkoR| j|jkoR| j|jkoR| j|jkoR| j|jkoR| j|jkS )N)r*   r   r   r   r  r  r   )r&   otherr   r   r   __eq__  s    zSnglInspiral.__eq__N)r  )rA   rB   rC   r   r   r
   r   r   r   r   r   rD   r  rX   r   r   r  r   r  r  r  r   r   r   r   r  ]  s   	r  c               @   s2   e Zd ZdZddddddddddd
ZddiZd	S )
CoincInspiralTableZcoinc_inspiralrj   rh   ri   r   )
zcoinc_event:coinc_event_idr/   ru   r   massr   Zminimum_durationr   false_alarm_ratecombined_farZci_cei_index)coinc_event_idN)rA   rB   rC   r   r   r   r   r   r   r   r    s   r  c               @   s6   e Zd ZdZeeejje	j
ZedZeddZdS )CoincInspiralz
	Example:

	>>> x = CoincInspiral()
	>>> x.instruments = (u"H1", u"L1")
	>>> print(x.ifos)
	H1,L1
	>>> assert x.instruments == set([u'H1', u'L1'])
	>>> x.end = LIGOTimeGPS(10)
	>>> x.end
	LIGOTimeGPS(10, 0)
	>>> x.end = None
	>>> print(x.end)
	None
	r/   ru   r   N)rA   rB   rC   rW   r   r   r
   r   r   r  r   r   r%   r;   rE   r   r   r   r   r   r#    s   r#  c               @   sR   e Zd ZdZdddddddddddddddddddddddddZdZed	Zd
S )SnglRingdownTableZsngl_ringdownrj   rh   ri   r   r   )zprocess:process_idr*   r   rt   r   start_time_gmst	frequencyqualityphaser  r  epsilonZnum_clust_trigsZds2_H1H2Zds2_H1L1Zds2_H1V1Zds2_H2L1Zds2_H2V1Zds2_L1V1r   r   Zeff_distZsigma_sqr   zPRIMARY KEY (event_id)r   N)rA   rB   rC   r   r   r   SnglRingdownIDr   r   r   r   r   r$    s6   r$  c               @   s,   e Zd Zeeejjej	Z
edddZdS )SnglRingdownrt   r   r%  N)rA   rB   rC   r   r   r
   r   r   r$  r   r   rX   ra   r   r   r   r   r+    s   r+  c               @   s@   e Zd ZdZddddddddddddddddddZddiZd	S )
CoincRingdownTableZcoinc_ringdownrj   rh   ri   r   )zcoinc_event:coinc_event_idr/   rt   r   r&  r'  r  r  r   Zchoppedl_snrZsnr_sqZeff_coh_snrZ	null_statr   Z	snr_ratior   r!  Zcr_cei_index)r"  N)rA   rB   rC   r   r   r   r   r   r   r   r,    s&   r,  c               @   s2   e Zd Zeeejjej	Z
edZeddZdS )CoincRingdownr/   rt   r   N)rA   rB   rC   r   r   r
   r   r   r,  r   r   r%   r;   rE   ra   r   r   r   r   r-  /  s   r-  simulation_idc            ;   @   s   e Zd ZdZddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd:ZdZed	Zd
S )SimInspiralTableZsim_inspiralrj   rh   ri   r   r   ):zprocess:process_idwaveformgeocent_end_timegeocent_end_time_nsZ
h_end_timeZh_end_time_nsZ
l_end_timeZl_end_time_nsZ
g_end_timeZg_end_time_nsZ
t_end_timeZt_end_time_nsZ
v_end_timeZv_end_time_nsr   sourcer   r   r   r   distance	longitudelatitudeinclinationr   polarizationr   r   r   r   r  r  r  r  r  r  r	  r
  r  r  r  r  Ztheta0Zphi0Zf_lowerr  
eff_dist_h
eff_dist_lZ
eff_dist_gZ
eff_dist_t
eff_dist_vZnumrel_mode_minZnumrel_mode_maxZnumrel_dataZ	amp_orderZtaperZbandpassr.  zPRIMARY KEY (simulation_id)r   N)rA   rB   rC   r   r   r   SimInspiralIDr   r   r   r   r   r/  F  sz   r/  c               @   s   e Zd ZdZeeejje	j
ZedddZedd Zejdd Zedd	 Zejd
d	 Zedd Zejdd Zdd Zdd Zdd Zdd ZdS )SimInspirala  
	Example:

	>>> x = SimInspiral()
	>>> x.ra_dec = 0., 0.
	>>> x.ra_dec
	(0.0, 0.0)
	>>> x.ra_dec = None
	>>> print(x.ra_dec)
	None
	>>> x.time_geocent = None
	>>> print(x.time_geocent)
	None
	>>> print(x.end_time_gmst)
	None
	>>> x.time_geocent = LIGOTimeGPS(6e8)
	>>> print(x.time_geocent)
	600000000
	>>> print(round(x.end_time_gmst, 8))
	-2238.39417156
	>>> x.distance = 100e6
	>>> x.ra_dec = 0., 0.
	>>> x.inclination = 0.
	>>> x.coa_phase = 0.
	>>> x.polarization = 0.
	>>> x.snr_geometry_factors(("H1",))
	{'H1': (0.490467233277456-0.4671010853697789j)}
	>>> # NOTE:  complex, abs() is traditional value
	>>> x.effective_distances(("H1",))
	{'H1': (106915812.12292896+101822279.85362741j)}
	>>> x.expected_snrs({"H1": 150e6})
	{'H1': (5.885606799329472-5.605213024437346j)}
	r1  r2  r   c             C   s$   | j d kr| jd krd S | j | jfS )N)r5  r6  )r&   r   r   r   ra_dec  s    zSimInspiral.ra_decc             C   s&   |d krd  | _ | _n|\| _ | _d S )N)r5  r6  )r&   radecr   r   r   r>    s    c             C   s<   | j d kr"| jd kr"| jd kr"d S tj| j | j| jfddS )Nr  )r  )r	  r
  r  r  r  )r&   r   r   r   r    s    zSimInspiral.spin1c             C   s.   |d krd\| _ | _| _n|\| _ | _| _d S )N)NNN)r	  r
  r  )r&   r  r   r   r   r    s    c             C   s<   | j d kr"| jd kr"| jd kr"d S tj| j | j| jfddS )Nr  )r  )r  r  r  r  r  )r&   r   r   r   r    s    zSimInspiral.spin2c             C   s.   |d krd\| _ | _| _n|\| _ | _| _d S )N)NNN)r  r  r  )r&   r  r   r   r   r    s    c             C   s4   | j ||  }| j\}}|ttj| j||| S )a  
		Return the "time" of the injection, delay corrected for the
		displacement from the geocentre to the given instrument.

		NOTE:  this method does not account for the rotation of the
		Earth that occurs during the transit of the plane wave from
		the detector to the geocentre.  That is, it is assumed the
		Earth is in the same orientation with respect to the
		celestial sphere when the wave passes through the detector
		as when it passes through the geocentre.  The Earth rotates
		by about 1.5 urad during the 21 ms it takes light to travel
		the radius of the Earth, which corresponds to 10 m of
		displacement at the equator, or 33 light-ns.  Therefore,
		the failure to do a proper retarded time calculation here
		results in errors as large as 33 ns.  This is insignificant
		in present applications, but be aware that this
		approximation is being made if the return value is used in
		other contexts.
		)time_geocentr>  r\   TimeDelayFromEarthCentercached_detector_by_prefixlocation)r&   r7   offsetvector	t_geocentradecr   r   r   time_at_instrument  s    
zSimInspiral.time_at_instrumentc       	      C   s   t | j}|d }t| j}i }x`|D ]X}ttj| j| j	| j
| j|\}}t| | |d|  d td| j  ||< q*W |S )a  
		Compute and return a dictionary of the ratios of the
		source's physical distance to its effective distance for
		each of the given instruments.  NOTE that the quantity
		returned is complex, where the magnitude of the value is
		that ratio and the phase is such that the expected complex
		SNR in a detector is given by

		rho_{0} = 8 * (D_horizon / D) * snr_geometry_factor,

		where D_horizon is the detector's horizon distance for this
		waveform (computed from the detector's noise spectral
		density), and D is the source's physical distance.  The
		geometry factor (what this method computes) depends on the
		direction to the source with respect to the antenna beam,
		the inclination of the source's orbital plane, the wave
		frame's polarization, and the phase of the waveform at the
		time of coalescence.  The combination

		D / geometry factor

		is called the effective distance.  See Equation (4.3) of
		arXiv:0705.1514.

		See also .effective_distances(), .expected_snrs().
		g       @g      ?y              )rR   cosr7  r\   r]   r@  ZComputeDetAMResponserB  responser5  r6  r8  complexcmathexpr   )	r&   r;   ZcosiZcos2iZgmstsnr_geometry_factorsr7   fpfcr   r   r   rN    s    


z SimInspiral.snr_geometry_factorsc                s    fdd  | D S )a  
		Compute and return a dictionary of the effective distances
		for this injection for the given instruments.  The
		effective distance is the distance at which an optimally
		oriented and positioned source would be seen with the same
		SNR as that with which this source will be seen in the
		given instrument.  Effective distance is related to the
		physical distance, D, by the geometry factor

		D_effective = D / (geometry factor).

		NOTE that in this implementation the quantity returned is
		complex such that the expected complex SNR in a detector is

		rho_{0} = 8 * D_horizon / D_effective

		Traditionally the effective distance is a scalar and does
		not convey information about the phase of the
		signal-to-noise ratio.  That quantity is the absolute value
		of the quantity computed by this method.  The extension to
		complex values is done here to facilitate the use of this
		code in applications where the expected complex SNR is
		required.

		See also .snr_geometry_factors(), .expected_snrs().
		c                s   i | ]\}} j | |qS r   )r4  )r   r7   Zsnr_geometry_factor)r&   r   r   
<dictcomp>8  s    z3SimInspiral.effective_distances.<locals>.<dictcomp>)rN  items)r&   r;   r   )r&   r   effective_distances  s    zSimInspiral.effective_distancesc                s    fdd|    D S )am  
		Compute and return a dictionary of the expected complex
		SNRs for this injection in the given instruments.
		horizon_distances is a dictionary giving the horizon
		distance for each of the detectors for which an expected
		SNR is to be computed.  The expected SNR in a detector is

		rho_{0} = 8 * D_horizon / D_effective.

		See also .effective_distances().
		c                s"   i | ]\}}d  |  | |qS )g       @r   )r   r7   Zeffective_distance)horizon_distancesr   r   rQ  F  s    z-SimInspiral.expected_snrs.<locals>.<dictcomp>)rS  rR  )r&   rT  r   )rT  r   expected_snrs:  s    zSimInspiral.expected_snrsN)rA   rB   rC   rW   r   r   r
   r   r   r/  r   r   rX   r@  r   r>  r   r  r  rH  rN  rS  rU  r   r   r   r   r=    s   !,r=  c               @   sJ   e Zd ZdZdddddddddddddddddddddZdZed	Zd
S )SimBurstTableZ	sim_burstrj   rh   r   ri   Zint_8u)zprocess:process_idr0  rF  rG  psitime_geocent_gpstime_geocent_gps_nstime_geocent_gmstr   r&  r   qZpol_ellipse_angleZpol_ellipse_er   r   Zegw_over_rsquaredZwaveform_numberztime_slide:time_slide_idr.  zPRIMARY KEY (simulation_id)r   N)rA   rB   rC   r   r   r   
SimBurstIDr   r   r   r   r   rV  X  s.   rV  c               @   sR   e Zd ZdZeeejje	j
ZedddZedd Zejdd Zdd	 Zd
S )SimBurstak  
	Example:

	>>> x = SimBurst()
	>>> x.ra_dec = 0., 0.
	>>> x.ra_dec
	(0.0, 0.0)
	>>> x.ra_dec = None
	>>> print(x.ra_dec)
	None
	>>> x.time_geocent = None
	>>> print(x.time_geocent)
	None
	>>> print(x.time_geocent_gmst)
	None
	>>> x.time_geocent = LIGOTimeGPS(6e8)
	>>> print(x.time_geocent)
	600000000
	>>> print(round(x.time_geocent_gmst, 8))
	-2238.39417156
	rX  rY  rZ  c             C   s$   | j d kr| jd krd S | j | jfS )N)rF  rG  )r&   r   r   r   r>    s    zSimBurst.ra_decc             C   s&   |d krd  | _ | _n|\| _ | _d S )N)rF  rG  )r&   r?  r   r   r   r>    s    c             C   s4   | j ||  }| j\}}|ttj| j||| S )a  
		Return the "time" of the injection, delay corrected for the
		displacement from the geocentre to the given instrument.

		NOTE:  this method does not account for the rotation of the
		Earth that occurs during the transit of the plane wave from
		the detector to the geocentre.  That is, it is assumed the
		Earth is in the same orientation with respect to the
		celestial sphere when the wave passes through the detector
		as when it passes through the geocentre.  The Earth rotates
		by about 1.5 urad during the 21 ms it takes light to travel
		the radius of the Earth, which corresponds to 10 m of
		displacement at the equator, or 33 light-ns.  Therefore,
		the failure to do a proper retarded time calculation here
		results in errors as large as 33 ns.  This is insignificant
		for burst searches, but be aware that this approximation is
		being made if the return value is used in other contexts.
		)r@  r>  r\   rA  rB  rC  )r&   r7   rD  rE  rF  rG  r   r   r   rH    s    
zSimBurst.time_at_instrumentN)rA   rB   rC   rW   r   r   r
   r   r   rV  r   r   rX   r@  r   r>  r   rH  r   r   r   r   r]  t  s   r]  c            !   @   sb   e Zd ZdZddddddddddddddddddddddddddddddddd ZdZed	Zd
S )SimRingdownTableZsim_ringdownrj   rh   ri   r   r   ) zprocess:process_idr0  Zcoordinatesgeocent_start_timegeocent_start_time_nsZh_start_timeZh_start_time_nsZl_start_timeZl_start_time_nsZv_start_timeZv_start_time_nsr%  r5  r6  r4  r7  r8  r&  r'  r(  r  r  r)  r   r9  r:  r;  r   Zhrss_hZhrss_lZhrss_vr.  zPRIMARY KEY (simulation_id)r   N)rA   rB   rC   r   r   r   SimRingdownIDr   r   r   r   r   r^    sF   r^  c               @   sN   e Zd Zeeejjej	Z
edddZedd Zejdd Zdd Zd	S )
SimRingdownr_  r`  r%  c             C   s$   | j d kr| jd krd S | j | jfS )N)r5  r6  )r&   r   r   r   r>    s    zSimRingdown.ra_decc             C   s&   |d krd  | _ | _n|\| _ | _d S )N)r5  r6  )r&   r?  r   r   r   r>    s    c             C   s4   | j ||  }| j\}}|ttj| j||| S )a  
		Return the start time of the injection, delay corrected for
		the displacement from the geocentre to the given
		instrument.

		NOTE:  this method does not account for the rotation of the
		Earth that occurs during the transit of the plane wave from
		the detector to the geocentre.  That is, it is assumed the
		Earth is in the same orientation with respect to the
		celestial sphere when the wave passes through the detector
		as when it passes through the geocentre.  The Earth rotates
		by about 1.5 urad during the 21 ms it takes light to travel
		the radius of the Earth, which corresponds to 10 m of
		displacement at the equator, or 33 light-ns.  Therefore,
		the failure to do a proper retarded time calculation here
		results in errors as large as 33 ns.  This is insignificant
		for ring-down searches, but be aware that this
		approximation is being made if the return value is used in
		other contexts.
		)geocent_startr>  r\   rA  rB  rC  )r&   r7   rD  rE  rF  rG  r   r   r   rH     s    
zSimRingdown.time_at_instrumentN)rA   rB   rC   r   r   r
   r   r   r^  r   r   rX   rc  r   r>  r   rH  r   r   r   r   rb    s
   rb  summ_value_idc               @   s@   e Zd ZdZddddddddddddddddZdZedZd	S )
SummValueTableZ
summ_valuerj   rh   ri   r   )rd  rk   zprocess:process_idZframeset_groupzsegment_definer:segment_def_idrt   r   ru   r   r*   r   r   errorZintvaluero   zPRIMARY KEY (summ_value_id)r   N)rA   rB   rC   r   r   r   SummValueIDr   r   r   r   r   re  -  s$   re  c               @   sJ   e Zd ZdZeeejje	j
ZedZeddZeddZeddZd	S )
	SummValuea<  
	Example:

	>>> x = SummValue()
	>>> x.instruments = (u"H1", u"L1")
	>>> print(x.ifo)
	H1,L1
	>>> assert x.instruments == set([u'H1', u'L1'])
	>>> x.start = LIGOTimeGPS(0)
	>>> x.end = LIGOTimeGPS(10)
	>>> x.segment
	segment(LIGOTimeGPS(0, 0), LIGOTimeGPS(10, 0))
	>>> x.segment = None
	>>> print(x.segment)
	None
	r*   rt   r   ru   r   ra   r   N)rA   rB   rC   rW   r   r   r
   r   r   re  r   r   r%   r;   rE   ra   r   r`   rc   r   r   r   r   rh  D  s   

rh  
segment_idc            
   @   s4   e Zd ZdZdddddddddd	ZdZedZdS )SegmentTablerc   ri   rj   )	r   zprocess:process_idri  rt   r   ru   r   zsegment_definer:segment_def_idsegment_def_cdbzPRIMARY KEY (segment_id)r   N)rA   rB   rC   r   r   r   	SegmentIDr   r   r   r   r   rj  m  s   rj  c               @   s   e Zd ZdZeeejje	j
ZeddZe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dS )Segmenta  
	Example:

	>>> x = Segment()
	>>> x.start = LIGOTimeGPS(0)
	>>> x.end = LIGOTimeGPS(10)
	>>> x.segment
	segment(LIGOTimeGPS(0, 0), LIGOTimeGPS(10, 0))
	>>> x.segment = None
	>>> print(x.segment)
	None
	>>> print(x.start)
	None
	>>> # non-LIGOTimeGPS times are converted to LIGOTimeGPS
	>>> x.segment = (20, 30.125)
	>>> x.end
	LIGOTimeGPS(30, 125000000)
	>>> # initialization from a tuple or with arguments
	>>> Segment((20, 30)).segment
	segment(LIGOTimeGPS(20, 0), LIGOTimeGPS(30, 0))
	>>> Segment(20, 30).segment
	segment(LIGOTimeGPS(20, 0), LIGOTimeGPS(30, 0))
	>>> # use as a segment object in segmentlist operations
	>>> from ligo import segments
	>>> x = segments.segmentlist([Segment(0, 10), Segment(20, 30)])
	>>> abs(x)
	LIGOTimeGPS(20, 0)
	>>> y = segments.segmentlist([Segment(5, 15), Segment(25, 35)])
	>>> abs(x & y)
	LIGOTimeGPS(10, 0)
	>>> abs(x | y)
	LIGOTimeGPS(30, 0)
	>>> 8.0 in x
	True
	>>> 12 in x
	False
	>>> Segment(2, 3) in x
	True
	>>> Segment(2, 12) in x
	False
	>>> segments.segment(2, 3) in x
	True
	>>> segments.segment(2, 12) in x
	False
	>>> # make sure results are segment table row objects
	>>> segments.segmentlist(map(Segment, x & y))	# doctest: +ELLIPSIS
	[<ligo.lw.lsctables.Segment object at 0x...>, <ligo.lw.lsctables.Segment object at 0x...>]

	Unbounded intervals are permitted.  See gpsproperty for information
	on the encoding scheme used internally, and its limitations.

	Example:

	>>> x = Segment()
	>>> # OK
	>>> x.start = -segments.infinity()
	>>> # also OK
	>>> x.start = float("-inf")
	>>> # infinite boundaries always returned as segments.infinity
	>>> # instances
	>>> x.start
	-infinity
	>>> x.end = float("+inf")
	>>> x.segment
	segment(-infinity, infinity)
	rt   r   ru   r   ra   r   c             C   s
   t | jS )N)rU   rc   )r&   r   r   r   __abs__  s    zSegment.__abs__c             C   s
   | j |k S )N)rc   )r&   r  r   r   r   __lt__  s    zSegment.__lt__c             C   s
   | j |kS )N)rc   )r&   r  r   r   r   r    s    zSegment.__eq__c             C   s
   || j kS )N)rc   )r&   r  r   r   r   __contains__  s    zSegment.__contains__c             C   s
   | j | S )N)rc   )r&   ir   r   r   __getitem__  s    zSegment.__getitem__c             O   sR   |r,y
|| _ W n tk
r*   |\| _ Y nX x | D ]\}}t| || q6W d S )N)rc   r9   rR  r?   )r&   argsr   keyr   r   r   r   r'     s    
zSegment.__init__c             C   s
   t | jS )N)r3   rc   )r&   r   r   r   __len__  s    zSegment.__len__c             C   s
   t | jS )N)boolrc   )r&   r   r   r   __nonzero__  s    zSegment.__nonzero__N)rA   rB   rC   rW   r   r   r
   r   r   rj  r   r   rE   ra   r   r`   rc   rn  ro  r  rp  rr  r'   ru  rw  r   r   r   r   rm  ~  s   C


rm  segment_def_idc            	   @   s2   e Zd ZdZdddddddddZdZedZdS )	SegmentDefTableZsegment_definerri   rj   rh   )r   zprocess:process_idrx  r/   r   rl   ro   Zinsertion_timezPRIMARY KEY (segment_def_id)r   N)rA   rB   rC   r   r   r   SegmentDefIDr   r   r   r   r   ry    s   ry  c               @   s,   e Zd ZdZeeejje	j
ZedZdS )
SegmentDefz
	Example:

	>>> x = SegmentDef()
	>>> x.instruments = (u"H1", u"L1")
	>>> print(x.ifos)
	H1,L1
	>>> assert x.instruments == set([u'H1', u'L1'])
	r/   N)rA   rB   rC   rW   r   r   r
   r   r   ry  r   r   r%   r;   r   r   r   r   r{  
  s   	r{  segment_sum_idc               @   s@   e Zd ZdZddddddddddd
ZdZedZdd	d
ZdS )SegmentSumTableZsegment_summaryri   rj   rh   )
r   zprocess:process_idr|  rt   r   ru   r   ro   zsegment_definer:segment_def_idrk  zPRIMARY KEY (segment_sum_id)r   Nc                s4    dkrt dd | D S t  fdd| D S )a  
		Return a segmentlist object describing the times spanned by
		the segments carrying the given segment_def_id.  If
		segment_def_id is None then all segments are returned.

		Note:  the result is not coalesced, the segmentlist
		contains the segments as they appear in the table.
		Nc             s   s   | ]}|j V  qd S )N)rc   )r   rx   r   r   r   r    C  s    z&SegmentSumTable.get.<locals>.<genexpr>c             3   s   | ]}|j  kr|jV  qd S )N)rx  rc   )r   rx   )rx  r   r   r    D  s    )r   r   )r&   rx  r   )rx  r   r6   9  s    	zSegmentSumTable.get)N)	rA   rB   rC   r   r   r   SegmentSumIDr   r6   r   r   r   r   r}  (  s   r}  c               @   s>   e Zd Zeeejjej	Z
eddZeddZeddZdS )
SegmentSumrt   r   ru   r   ra   r   N)rA   rB   rC   r   r   r
   r   r   r}  r   r   rE   ra   r   r`   rc   r   r   r   r   r  G  s   

r  time_slide_idc               @   sD   e Zd ZdZdddddZdZedZdd	 Zd
d Z	dddZ
dS )TimeSlideTableZ
time_sliderj   rh   r   )zprocess:process_idr  r7   offsetz'PRIMARY KEY (time_slide_id, instrument)r   c                s:   ddl m  t fddtt| dd ddd D S )z
		Return a dictionary mapping time slide IDs to offset
		dictionaries.

		NOTE:  very little checking is done, e.g., for repeated
		instruments for a given ID (which could suggest an ID
		collision).
		r   )rD  c             3   s(   | ] \}}| d d |D fV  qdS )c             s   s   | ]}|j |jfV  qd S )N)r7   r  )r   rx   r   r   r   r    w  s    z3TimeSlideTable.as_dict.<locals>.<genexpr>.<genexpr>Nr   )r   r  rows)rD  r   r   r    w  s    z)TimeSlideTable.as_dict.<locals>.<genexpr>c             S   s   | j S )N)r  )rx   r   r   r   <lambda>w      z(TimeSlideTable.as_dict.<locals>.<lambda>)rt  )Zlalburst.offsetvectorrD  r   	itertoolsgroupbyr   )r&   r   )rD  r   as_dicti  s    zTimeSlideTable.as_dictc          	   C   s<   |   }x.| D ]"\}}| | j|j|||d qW |S )ad  
		Append rows describing an instrument --> offset mapping to
		this table.  offsetvect is a dictionary mapping instrument
		to offset.  process should be the row in the process table
		on which the new time_slide table rows will be blamed (or
		any object with a process_id attribute).  The return value
		is the time_slide_id assigned to the new rows.
		)re   r  r7   r  )get_next_idrR  r   RowTypere   )r&   Z
offsetvectrg   r  r7   r  r   r   r   append_offsetvectory  s    	z"TimeSlideTable.append_offsetvectorNFc                s   |r  fdd|    D }n fdd|    D }t|dkrb|rR|d S tdt  t|dkrv|d S |dkrtdt  |  |S )	af  
		Return the time_slide_id corresponding to the offset vector
		described by offsetdict, a dictionary of instrument/offset
		pairs.

		If the optional create_new argument is None (the default),
		then the table must contain a matching offset vector.  The
		return value is the ID of that vector.  If the table does
		not contain a matching offset vector then KeyError is
		raised.

		If the optional create_new argument is set to a Process
		object (or any other object with a process_id attribute),
		then if the table does not contain a matching offset vector
		a new one will be added to the table and marked as having
		been created by the given process.  The return value is the
		ID of the (possibly newly created) matching offset vector.

		If the optional superset_ok argument is False (the default)
		then an offset vector in the table is considered to "match"
		the requested offset vector only if they contain the exact
		same set of instruments.  If the superset_ok argument is
		True, then an offset vector in the table is considered to
		match the requested offset vector as long as it provides
		the same offsets for the same instruments as the requested
		vector, even if it provides offsets for other instruments
		as well.

		More than one offset vector in the table might match the
		requested vector.  If the optional nonunique_ok argument is
		False (the default), then KeyError will be raised if more
		than one offset vector in the table is found to match the
		requested vector.  If the optional nonunique_ok is True
		then the return value is the ID of one of the matching
		offset vectors selected at random.
		c                s2   g | ]*\}} t  fd d| D kr|qS )c             3   s"   | ]\}}| kr||fV  qd S )Nr   )r   r7   r  )
offsetdictr   r   r      s    z>TimeSlideTable.get_time_slide_id.<locals>.<listcomp>.<genexpr>)r   rR  )r   r  slide)r  r   r   
<listcomp>  s    z4TimeSlideTable.get_time_slide_id.<locals>.<listcomp>c                s   g | ]\}} |kr|qS r   r   )r   r  r  )r  r   r   r    s    r   r   z%s not uniqueNz%s not found)r  rR  r3   r~   r   r  )r&   r  
create_newZsuperset_okZnonunique_okZidsr   )r  r   get_time_slide_id  s    &z TimeSlideTable.get_time_slide_id)NFF)rA   rB   rC   r   r   r   TimeSlideIDr   r  r  r  r   r   r   r   r  ^  s   r  c               @   s    e Zd Zeeejjej	Z
dS )	TimeSlideN)rA   rB   rC   r   r   r
   r   r   r  r   r   r   r   r   r   r    s   r  coinc_def_idc               @   s<   e Zd ZdZdddddZdZedZdd	iZdddZ	dS )CoincDefTableZcoinc_definerrj   rh   int_4u)r  r   search_coinc_typedescriptionzPRIMARY KEY (coinc_def_id)r   Zcd_ssct_index)r   r  TNc                sz    fdd| D }t |dkr0td f t |dkrF|d jS |sVt f|  }| | j| |d |S )a  
		Return the coinc_def_id for the row in the table whose
		search string and search_coinc_type integer have the values
		given.  If a matching row is not found, the default
		behaviour is to create a new row and return the ID assigned
		to the new row.  If, instead, create_new is False then
		KeyError is raised when a matching row is not found.  The
		optional description parameter can be used to set the
		description string assigned to the new row if one is
		created, otherwise the new row is left with no description.
		c                s$   g | ]}|j |jf fkr|qS r   )r   r  )r   rx   )r   r  r   r   r    s    z2CoincDefTable.get_coinc_def_id.<locals>.<listcomp>r   z<(search, search coincidence type) = ('%s', %d) is not uniquer   )r  r   r  r  )r3   r9   r  r~   r  r   r  )r&   r   r  r  r  r  r  r   )r   r  r   get_coinc_def_id  s    

zCoincDefTable.get_coinc_def_id)TN)
rA   rB   rC   r   r   r   
CoincDefIDr   r   r  r   r   r   r   r    s   r  c               @   s    e Zd Zeeejjej	Z
dS )CoincDefN)rA   rB   rC   r   r   r
   r   r   r  r   r   r   r   r   r   r  	  s   r  r"  c               @   s:   e Zd ZdZddddddddZdZedZd	d
dZdS )
CoincTablecoinc_eventrj   rh   r  r   )zprocess:process_idzcoinc_definer:coinc_def_idr"  ztime_slide:time_slide_idr;   r   Z
likelihoodzPRIMARY KEY (coinc_event_id)r   )r  )r  )Zce_cdi_indexZce_tsi_indexN)	rA   rB   rC   r   r   r   CoincIDr   r   r   r   r   r   r  	  s   r  c               @   s(   e Zd Zeeejjej	Z
edZdS )Coincr;   N)rA   rB   rC   r   r   r
   r   r   r  r   r   r%   Zinstsr   r   r   r   r  1	  s   r  c               @   s.   e Zd ZdZddddZdddZdd	 Zd
S )CoincMapTableZcoinc_event_maprj   Zchar_v)zcoinc_event:coinc_event_id
table_namer   )r  r   )r"  )Zcem_tn_ei_indexZcem_cei_indexc       	   	   C   s   |  d}|  d}|  d}xvtt|||D ]b\}\}}}y|||f ||< W n tk
rf   Y nX y|d|f ||< W q0 tk
r   Y q0X q0W d S )Nr  r   r"  r  )ZgetColumnByName	enumeratezipr~   )	r&   mappingtable_columnZevent_id_columnZcoinc_event_id_columnrq  r  Zold_event_idZold_coinc_event_idr   r   r   applyKeyMappingO	  s    


 zCoincMapTable.applyKeyMappingN)rA   rB   rC   r   r   r   r  r   r   r   r   r  C	  s   r  c               @   s    e Zd Zeeejjej	Z
dS )CoincMapN)rA   rB   rC   r   r   r
   r   r   r  r   r   r   r   r   r   r  ^	  s   r  Z
dq_list_iddq_list_row_idc               @   s.   e Zd ZdZdddddddZdZedZdS )	DQSpecListTableZdq_listrj   rh   r   )zdq_list:dq_list_idr  r7   flag
low_windowhigh_windowz(PRIMARY KEY (dq_list_id, dq_list_row_id)r   N)rA   rB   rC   r   r   r   DQSpecListIDr   r   r   r   r   r  r	  s   r  c               @   s(   e Zd Zeeejjej	Z
dd ZdS )DQSpecc             C   s>   x8t |D ],\}}||d | j |d | j ||< q
W dS )zH
		Apply our low and high windows to the segments in a
		segmentlist.
		r   r   N)r  r[   r  r  )r&   seglistrq  rd   r   r   r   apply_to_segmentlist	  s    zDQSpec.apply_to_segmentlistN)rA   rB   rC   r   r   r
   r   r   r  r   r   r  r   r   r   r   r  	  s   r  c               @   s<   e Zd ZdZddddddddddd
Zdd Zdd
dZdS )VetoDefTableZveto_definerrj   rh   ri   )
zprocess:process_idr*   r   rl   categoryrt   ru   	start_padend_padro   c                s   t  fdd| D S )zD
		Report the versions available for the (name, category)
		pair.
		c             3   s(   | ] }|j kr|j kr|jV  qd S )N)r   r  rl   )r   rx   )r  r   r   r   r    	  s    z(VetoDefTable.versions.<locals>.<genexpr>)r0   )r&   r   r  r   )r  r   r   versions	  s    zVetoDefTable.versionsNFc          	   C   s   t  }|dkr$t| ||p d}xx| D ]p}|j|ks*|j|ks*|j|krNq*y||j }W n& tk
r   t 	  }||j< Y nX |
|r|jn|j q*W |S )a  
		Return a segments.segmentlistdict mapping instrument to the
		segments for the (name, category) pair.  If version is None
		(the default) then the newest version of the segments are
		reported, otherwise the segments for the requested version
		are reported.  If padded is boolean False (the default) the
		non-padded segments are reported, otherwise the padded
		segments are reported.
		N)N)r   r   maxr  r   r  rl   r*   r~   r   r   segment_paddedrc   )r&   r   r  rl   Zpaddedr   rx   r  r   r   r   r   	  s    

zVetoDefTable.segmentlistdict)NF)rA   rB   rC   r   r   r  r   r   r   r   r   r  	  s   r  c               @   s   e Zd Zeeejjej	Z
edd Zejdd Zedd Zejdd ZeddZed	d
ZeddZedd Zedd ZeddZdS )VetoDefc             C   s   dS )Nr   r   )r   r   r   r   r   	  s    zVetoDef.start_time_nsc             C   s   d S )Nr   )r&   r   r   r   r   r   	  s    c             C   s   dS )Nr   r   )r   r   r   r   r   	  s    zVetoDef.end_time_nsc             C   s   d S )Nr   )r&   r   r   r   r   r   	  s    rt   r   ru   r   ra   r   c             C   s   | j | j S )N)ra   r  )r&   r   r   r   start_padded	  s    zVetoDef.start_paddedc             C   s   | j | j S )N)r   r  )r&   r   r   r   
end_padded	  s    zVetoDef.end_paddedr  r  N)rA   rB   rC   r   r   r
   r   r   r  r   r   r   r   r   r   rE   ra   r   rc   r  r  r  r   r   r   r   r  	  s   	


r  c             C   s   x| D ]}|   qW dS )a  
	For each class in the list, if the .next_id attribute is not None
	(meaning the table has an ID generator associated with it), set
	.next_id to 0.  This has the effect of reseting the ID generators,
	and is useful in applications that process multiple documents and
	add new rows to tables in those documents.  Calling this function
	between documents prevents new row IDs from growing continuously
	from document to document.  There is no need to do this, it's
	purpose is merely aesthetic, but it can be confusing to open a
	document and find process ID 300 in the process table and wonder
	what happened to the other 299 processes.

	Example:

	>>> reset_next_ids(TableByName.values())
	N)Zreset_next_id)classesr   r   r   r   reset_next_ids
  s    
r  c             C   s"   t | } | jfdd}|| _| S )ai  
	Modify ContentHandler, a sub-class of
	ligo.lw.ligolw.LIGOLWContentHandler, to cause it to use the Table
	classes defined in this module when parsing XML documents.

	Example:

	>>> from ligo.lw import ligolw
	>>> class MyContentHandler(ligolw.LIGOLWContentHandler):
	...	pass
	...
	>>> use_in(MyContentHandler)
	<class 'ligo.lw.lsctables.MyContentHandler'>
	c             S   s0   t j|d }|tkr$t| |S || ||S )Nr   )r
   r"   r   r   )r&   parentattrsZ__orig_startTabler   r   r   r   
startTableO
  s    zuse_in.<locals>.startTable)r
   use_inr  )ZContentHandlerr  r   r   r   r  >
  s    
r  )N)frW   rL  	functoolsr  rR   r  rG   r|   r   r   warningsxmlr   Zligor   r\   r   r+   r   r   r   r	   r
   r   r   r   r$   objectr%   rE   rX   r`   r   r   r   r"   rf   r  r   r   r   r   r   r   r   r   r   r   r   r  r   r  r  r#  r*  r$  r+  r,  r-  r<  r/  r=  r\  rV  r]  ra  r^  rb  rg  re  rh  rl  rj  total_orderingrm  rz  ry  r{  r~  r}  r  r  r  r  r  r  r  r  r  r  r  r  r  ZDQSpecListRowIDr  r  r  r  r   r   r  r  r   r   r   r   <module>H   s  #
 G%)6a8=68cH= B BC(0lj00(
#