3 Michalis Agathos (2014)
5 This script provides a set of good gps times for injecting a GW signal
6 into real multiple detector data.
7 The input consists of a set of science segment and veto segment ASCII files
8 having the 4-column format:
10 segid gpsstart gpsend duration
12 The output consists of an ASCII file containing a list of gps injection times.
13 If the timeslides functionality is activated, an additional ASCII file is
14 output, containing timeslide information (in seconds) for each IFO, with
15 respect to the nominal times provided in the first file.
18 __author__ =
"Michalis Agathos"
19 __maintainer__ =
"Michalis Agathos"
20 __email__ =
"michalis.agathos@ligo.org"
22 __status__ =
"Production"
24 import matplotlib
as mpl
31 py_version = sys.version_info[:2]
32 np_version = np.__version__
34 colordict={
'H1':
'r',
'L1':
'g',
'V1':
'b',
'H1L1':
'c',
'L1H1':
'c',
'H1V1':
'm',
'V1H1':
'm',
'L1V1':
'y',
'V1L1':
'y',
'H1L1V1':
'k'}
36 '''Exclude segments that contain the following gpstimes'''
37 excludetimes = [966951349, 967054240, 968021010]
47 '''An interferometer. Can also refer to multiple interferometers to host doubles, triples etc.'''
48 def __init__(self, name, segments, vetoes, minlen=1):
49 self.
_name_name = name
52 if type(segments)
is str:
53 print(
"Reading segments for " + self.
_name_name +
"")
55 elif type(segments)
is ndarray:
57 elif isinstance(segments, segmentData):
60 print(
"Cannot recognize segments!")
64 if type(vetoes)
is str:
65 print(
"Reading veto segments for " + self.
_name_name +
"")
67 elif type(vetoes)
is ndarray:
69 elif isinstance(vetoes, segmentData):
72 print(
"Cannot recognize veto segments!")
76 print(
"Number of unvetoed segments that fit " +
str(self.
_minlen_minlen) +
": " +
str(self.
_unvetoed_unvetoed.length()))
79 '''This is getting a list of unvetoed segments that fit the minimum length'''
84 print(
"Reading " + segfname)
85 segdata = genfromtxt(segfname, dtype=int)
89 self.
_unvetoed_unvetoed.printToFile(outname)
91 def getTrigTimes(self, whereInj='middle', interval=None, rmargin=2, lmargin=2, n=None, outfile=None):
92 '''Returns a list of gps times on which injections can be made'''
98 for seg
in self.
_unvetoed_unvetoed._seglist:
100 if whereInj ==
'often':
101 '''Inject every l seconds until you reach rmargin seconds from end of segment.'''
103 while t + rmargin <= seg[2]:
104 if t >= seg[1] + lmargin:
107 elif whereInj ==
'middle':
108 '''Inject in the middle of minlen-long intervals.'''
109 while t + self.
_minlen_minlen <= seg[2]:
110 if (t + self.
_minlen_minlen//2 >= seg[1] + lmargin)
and (t + self.
_minlen_minlen//2 + rmargin <= seg[2]):
111 trigtimes.append(t + self.
_minlen_minlen//2)
114 print(
"Invalid whereInj argument. Output times will be empty.")
117 trigtimes = trigtimes[:n]
119 return array(trigtimes)
121 savetxt(outfile, array(trigtimes), fmt=
'%i')
124 print(
"Plotting segment lengths distribution to file " + outfile)
126 ax = fig.add_subplot(111)
127 ax.set_xlabel(
"segment length")
128 ax.set_ylabel(
"Cumulative # segments")
129 sdur = array(self.
_segments_segments._seglist)[:,-1]
130 udur = array(self.
_unvetoed_unvetoed._seglist)[:,-1]
131 if maxdur
is not None:
132 sdur = sdur[where(sdur <= maxdur)[0]]
133 udur = udur[where(udur <= maxdur)[0]]
134 ax.set_ylim((0,
max([len(udur),len(sdur)])))
135 ax.set_title(
"Segment length distribution for " + self.
_name_name)
136 ax.hist(sdur, bins=sort(sdur), cumulative=
True, histtype=
'stepfilled', alpha=0.3, label=
"All segments (" +
str(self.
_segments_segments.length()) +
")")
137 ax.hist(udur, bins=sort(udur), cumulative=
True, histtype=
'stepfilled', alpha=0.3, label=
"Unvetoed segments (" +
str(self.
_unvetoed_unvetoed.length()) +
")")
141 def plotSegments(self, outfile=None, lenperline=200000, segcolorlist=['b','r','g'], title=None):
142 '''Plot segments in rows of lenperline seconds'''
145 n = ceil((end-start)/lenperline)
146 plot_params = {
'figure.figsize': [fig_width,fig_height*2]}
147 rcParams.update(plot_params)
150 s = array(segs._seglist)
151 t = sort(hstack((s[:,1],s[:,1],s[:,2],s[:,2])))
152 y = array(len(s)*[0,1,1,0])
154 ax=fig.add_subplot(n,1,i+1)
155 ax.tick_params(axis=
'y', which=
'both', left=
'off', right=
'off', labelleft=
'off')
156 ax.tick_params(axis=
'x', which=
'both', top=
'on', bottom=
'off', labelbottom=
'off')
158 ax.xaxis.set_major_formatter(FormatStrFormatter(
'%0.0f'))
159 t0 = start + i*lenperline
161 ax.set_ylabel(
int(t0), verticalalignment=
'top', rotation=45)
163 ax.fill_between(t, 0*y + 2*(k//2), y + 2*(1-y)*(k//2), alpha=0.3, color=segcolorlist[k])
164 if title
is not None:
169 print(
'Plotting segments to ', outfile)
171 plot_params = {
'figure.figsize': [fig_width,fig_height]}
172 rcParams.update(plot_params)
180 '''A time segment in an IFO'''
182 def __init__(self, data, gpsstart=None, gpsend=None):
183 '''Creates a segment'''
184 if gpsstart
is not None and gpsend
is not None:
185 self.
_id_id = data[0]
186 self.
_start_start = gpsstart
187 self.
_end_end = gpsend
188 self.
_len_len =
max(gpsend-gpsstart, 0)
189 elif gpsstart
is None and gpsend
is None:
190 '''Overloading to generate segment from an array (id, start, end, length)'''
192 print(
"Segment data doesn't have the correct length!")
194 self.
_id_id = data[0]
195 self.
_start_start = data[1]
196 self.
_end_end = data[2]
197 self.
_len_len = data[3]
199 print(
"Wrong arguments to create segment!")
205 '''Intersect segment with list of (non-overlapping) segments'''
209 '''Cut list short from the left'''
210 for oseg
in other[startid:]:
211 if segment(oseg)._start > self.
_end_end
and sortedlist:
215 if newseg._start < newseg._end:
218 newlist.append(newseg.toArray())
222 return (newlist, minid)
225 '''Checks if time is in (open) segment'''
226 if (time < self.
_start_start
or time > self.
_end_end):
227 dist = min(self.
_start_start - time, time - self.
_end_end)
233 '''Intersects with another segment'''
234 newstart =
max(self.
_start_start, other._start)
235 newend = min(self.
_end_end, other._end)
236 newseg =
segment([self.
_id_id], newstart, newend)
244 '''Data that holds segments for one or more IFOs.'''
246 def __init__(self, seglist, gpsstart=None, gpsend=None):
248 gpsstart = seglist[0][1]
250 gpsend = seglist[-1][2]
251 sortedlist = list(array(seglist)[argsort(array(seglist)[:,1])])
253 self.
_start_start = gpsstart
254 self.
_end_end = gpsend
259 def fits(self, minlen):
260 '''Returns the list of segments that fit a minimum required length.'''
262 fitted = data[where(data[:,3] >= minlen)[0]]
263 fitted = vstack( (arange(len(fitted)),fitted[:, 1:].T) ).T
267 '''Returns the intersection with another list of segments.'''
274 for et
in excludetimes:
275 exclude = exclude
or (seg.hasTime(et) == 0)
277 id = id0 + len(newdata)
278 nd, minid= seg.intersectWithList(id, other._seglist, startid=startfrom)
285 '''Get the complement of the (non-overlapping) segments in this data'''
288 times = array(self.
_seglist_seglist)[:,[1,2]]
290 times = times[argsort(times[:,1])]
292 for i
in (arange(len(times))):
294 if t2 > t1
and t1 >= start
and t2 <= end:
295 newseg = array([c, t1, t2, t2-t1])
296 notlist.append(newseg)
300 newseg = array([c, t1, end, end-t1])
301 notlist.append(newseg)
305 '''Returns a segmentData object with unvetoed segments'''
306 noveto = vetodata.notSegments(self.
_start_start, self.
_end_end)
311 '''Take the union of segment lists. This is used for combining veto segments of different detectors.'''
312 '''Here I use AUB = not(notA^notB)'''
313 start = min(self.
_start_start, other._start)
314 end =
max(self.
_end_end, other._end)
319 '''Checks whether time is in the segments. Gives 0 if true and the distance of time to the segment list otherwise.'''
320 dist =
max(abs(self.
_start_start - time), abs(self.
_end_end - time))
322 dist = min(dist, s.hasTime(time))
326 '''If t is in a segment returns the distance to the edges, otherwise returns False'''
331 ids = where(sgn < 0)[0]
333 print(
"Time " + time +
" contained in more than one segment!")
335 return [ds[ids[0]], -de[ids[0]]]
341 print(
"Printing segment list to file " + outfile)
342 savetxt(outfile, array(self.
_seglist_seglist), fmt=
'%i')
344 def plotSegments(self, outfile=None, lenperline=200000, segcolor='b', title=None):
345 '''Plot segments in rows of lenperline seconds'''
347 t = sort(hstack((s[:,1],s[:,1],s[:,2],s[:,2])))
349 n = ceil((t[-1]-t[0])/lenperline)
352 ax=fig.add_subplot(n,1,i+1)
353 ax.tick_params(axis=
'y', which=
'both', left=
'off', right=
'off', labelleft=
'off')
354 ax.tick_params(axis=
'x', which=
'both', top=
'on', bottom=
'off', labelbottom=
'off')
356 ax.xaxis.set_major_formatter(FormatStrFormatter(
'%0.0f'))
357 t0 = t[0] + i*lenperline
359 ax.set_ylabel(
int(t0), verticalalignment=
'top', rotation=45)
361 ax.fill_between(t, 0*array(y), y, alpha=0.3, color=segcolor)
362 if title
is not None:
367 print(
'Plotting segments to ', outfile)
372 print(
"Plotting segment lengths distribution to file " + outfile)
374 ax = fig.add_subplot(111)
375 ax.set_xlabel(
"segment length")
376 ax.set_ylabel(
"# segments")
377 dur = array(self.
_seglist_seglist)[:,-1]
378 if maxdur
is not None:
379 dur = dur[where(dur <= maxdur)[0]]
380 ax.hist(dur, bins=sort(dur), cumulative=
True, histtype=
'stepfilled', alpha=0.3)
394 CREATE FOLDER IF IT DOES NOT EXIST
396 if not os.path.exists(f):
402 Combines 2 interferometer objects into a new one, taking intersection of segments and union of vetoes
403 Setting unvetoed=True will speed up the calculations by ignoring
404 small/vetoed segments. Use with caution! (not good for plotting seglen distr)
408 seg1 = ifo1._allsegments
409 seg2 = ifo2._allsegments
412 unv1 = ifo1._unvetoed
413 unv2 = ifo2._unvetoed
417 name12 = name1 + name2
418 print(
'Combining ' + name1 +
' and ' + name2 +
' into ' + name12)
420 seg12 = unv1.intersectSegments(unv2)
422 seg12 = seg1.intersectSegments(seg2)
423 vet12 = vet1.unionSegments(vet2)
424 minl12 =
max(minl1, minl2)
425 ifo12 =
IFO(name12, seg12, vet12, minl12)
430 def getTriples(ifo1, ifo2, ifo3, unvetoed=False):
431 '''Combines 3 IFO objects into one'''
439 Generate a list of injection times and timeslides,
440 given a dictionary of (single) injection times
449 for k
in tdict.keys():
454 injdict[ifo].append(rd.sample(tdict[ifo], 1)[0])
456 injtimes = injdict[ref]
458 slidedict[ifo] = array(injdict[ifo]) - array(injdict[ref])
460 if outfolder
is None:
461 return injtimes, slidedict
463 label=
''.join(ifos) +
'_' +
str(n)
464 injtimesfile = os.path.join(outfolder,
'injtimes_'+label+
'.dat')
465 slidefilename = os.path.join(outfolder,
'timeslides_'+label+
'.dat')
466 slidefile = open(slidefilename,
'w')
467 header =
" ".join(ifos)
468 slidefile.write(header+
'\n')
469 slidedata = array(slidedict.values()).T
473 savetxt(injtimesfile, array(injtimes), fmt=
'%i')
474 savetxt(slidefile, slidedata, delimiter=
' ', fmt=
'%i')
476 return (injtimesfile, slidefilename)
486 if __name__ ==
"__main__":
495 parser = argparse.ArgumentParser(description=
"Reads segment files and outputs injection times in veto-free segments.")
498 parser.add_argument(
'-i',
'--ifos', nargs=3, type=str, metavar=
'IFO', dest=
'ifos', help=
'List of IFOs to be considered (currently takes 3)')
499 parser.add_argument(
'-s',
'--segfiles', nargs=3, type=str, metavar=
'FILE', dest=
'segf', help=
'path to the segment files for IFOS in the order entered above')
500 parser.add_argument(
'-v',
'--vetofiles', nargs=3, type=str, metavar=
'FILE', dest=
'vetof', help=
'path to the veto files for IFOS in the order entered above')
501 parser.add_argument(
'-o',
'--outfolder', type=str, metavar=
'FILE', dest=
'outf', help=
'path to the output folder', default=
'.')
502 parser.add_argument(
'-l',
'--length', type=int, metavar=
'INT', dest=
'length', help=
'length of signal segments in seconds', default=45.0)
503 parser.add_argument(
'-P',
'--psdlength', type=int, metavar=
'INT', dest=
'psdlength', help=
'minimum length for calculating PSD in seconds', default=1024)
504 parser.add_argument(
'-N',
'--Ninj', type=int, dest=
"Ninj", help=
"# injections", default=1000)
505 parser.add_argument(
'-I',
'--interval', type=int, metavar=
'INT', dest=
'interval', help=
'minimum space between injections in seconds (defaults to injecting only in the middle of segments)', default=
None)
506 parser.add_argument(
'-S',
'--singles', action=
"store_true", dest=
"singles", help=
"process singles (default for timeslides)", default=
False)
507 parser.add_argument(
'-D',
'--doubles', action=
"store_true", dest=
"doubles", help=
"process doubles (N/A for timeslides)", default=
False)
508 parser.add_argument(
'-T',
'--triples', action=
"store_true", dest=
"triples", help=
"process triples (N/A for timeslides)", default=
False)
509 parser.add_argument(
'-t',
'--timeslides', action=
"store_true", dest=
"timeslides", help=
"Enable timeslides. This automatically deactivates --triples and --doubles.", default=
False)
510 parser.add_argument(
'-p',
'--plot', action=
"store_true", dest=
"plotsegdist", help=
"plot cumulative segment length distribution", default=
False)
511 parser.add_argument(
'-c',
'--checkslides', action=
"store_true", dest=
"check", help=
"verbose check that all timeslid times are in unvetoed segments", default=
False)
512 parser.add_argument(
'-u',
'--dumpunvetoed', action=
"store_true", dest=
"dumpunvetoed", help=
"dump list of unvetoed segments to file and plot segments", default=
False)
518 args = parser.parse_args()
520 outfolder =
str(args.outf)
522 vetofiles = args.vetof
527 psdlen = args.psdlength
528 plotsegdist = args.plotsegdist
529 dumpunvetoed = args.dumpunvetoed
530 interval = args.interval
531 singles = args.singles
532 doubles = args.doubles
533 triples = args.triples
534 timeslides = args.timeslides
541 ensure_dir(os.path.join(outfolder,
'segments'))
551 minlen =
max(psdlen, seglen)
555 for i
in arange(nifos):
556 IFOlist.append(
IFO(ifos[i], segfiles[i], vetofiles[i], minlen))
560 IFOlist[-1].plotCumulativeDurations(os.path.join(outfolder,
'singleseg_' + IFOlist[-1]._name +
'.png'), maxplot)
561 timesdict[ifos[i]] = IFOlist[-1].getTrigTimes(whereInj=whereInj, interval=interval, lmargin=seglen)
565 ensure_dir(os.path.join(outfolder,
'timeslides'))
572 for single
in IFOlist:
574 single.plotCumulativeDurations(os.path.join(outfolder,
'singleseg_' + single._name +
'.png'), maxplot)
576 single.getTrigTimes(whereInj=whereInj, n=Ninj, interval=interval, lmargin=seglen, outfile=os.path.join(outfolder,
'injtimes_' + single._name +
'_' +
str(single._minlen) +
'.dat'))
579 print(
'checking single ' + single._name)
580 for time
in single.getTrigTimes(whereInj=whereInj, n=Ninj, interval=interval, lmargin=seglen):
581 dist = single._unvetoed.timeIn(time)
582 print(dist, dist > 0)
585 single._unvetoed.printToFile(os.path.join(outfolder,
'segments', single._name +
'_unvetoed_segs.dat'))
586 figseg = single._unvetoed.plotSegments(os.path.join(outfolder,
'segments', single._name +
'_unvetoed_segs.pdf'), title=single._name +
' unvetoed segments', segcolor=colordict[single._name])
592 doubleIFOs.append(
getDoubles(IFOlist[0], IFOlist[1]) )
593 doubleIFOs.append(
getDoubles(IFOlist[1], IFOlist[2]) )
594 doubleIFOs.append(
getDoubles(IFOlist[0], IFOlist[2]) )
597 for double
in doubleIFOs:
598 double.getTrigTimes(whereInj=whereInj, n=Ninj, interval=interval, lmargin=seglen, outfile=os.path.join(outfolder,
'injtimes_' + double._name +
'_' +
str(double._minlen) +
'.dat'))
600 double.plotCumulativeDurations(os.path.join(outfolder,
'doubleseg_' + double._name +
'.png'), maxplot)
603 print(
'checking double ' + double._name)
604 for time
in double.getTrigTimes(whereInj=whereInj, n=Ninj, interval=interval, lmargin=seglen):
605 dist = double._unvetoed.timeIn(time)
606 print(dist, dist > 0)
609 double._unvetoed.printToFile(os.path.join(outfolder,
'segments', double._name +
'_unvetoed_segs.dat'))
610 figseg = double._unvetoed.plotSegments(os.path.join(outfolder,
'segments', double._name +
'_unvetoed_segs.pdf'), title=double._name +
' unvetoed segments')
619 tripleIFO =
getTriples(IFOlist[0], IFOlist[1], IFOlist[2])
622 tripleIFO.getTrigTimes(whereInj=whereInj, n=Ninj, interval=interval, lmargin=seglen, outfile=os.path.join(outfolder,
'injtimes_' + tripleIFO._name +
'_' +
str(tripleIFO._minlen) +
'.dat'))
624 tripleIFO.plotCumulativeDurations(os.path.join(outfolder,
'tripleseg_' + tripleIFO._name +
'.png'), maxplot)
627 print(
'checking triple ' + tripleIFO._name)
628 for time
in tripleIFO.getTrigTimes(whereInj=whereInj, n=Ninj, interval=interval, lmargin=seglen):
629 dist = tripleIFO._unvetoed.timeIn(time)
630 print(dist, dist > 0)
633 tripleIFO._unvetoed.printToFile(os.path.join(outfolder,
'segments', tripleIFO._name +
'_unvetoed_segs.dat'))
634 figseg = tripleIFO._unvetoed.plotSegments(os.path.join(outfolder,
'segments', tripleIFO._name +
'_unvetoed_segs.pdf'), title=tripleIFO._name +
' unvetoed segments')
def setUnvetoed(self)
This is getting a list of unvetoed segments that fit the minimum length.
def plotSegments(self, outfile=None, lenperline=200000, segcolorlist=['b', 'r', 'g'], title=None)
Plot segments in rows of lenperline seconds.
def getTrigTimes(self, whereInj='middle', interval=None, rmargin=2, lmargin=2, n=None, outfile=None)
Returns a list of gps times on which injections can be made.
def printUnvetoedToFile(self, outname)
def plotCumulativeDurations(self, outfile, maxdur=None)
def readSegments(self, segfname)
def __init__(self, name, segments, vetoes, minlen=1)
Data that holds segments for one or more IFOs.
def plotSegments(self, outfile=None, lenperline=200000, segcolor='b', title=None)
Plot segments in rows of lenperline seconds.
def getUnvetoed(self, vetodata)
Returns a segmentData object with unvetoed segments.
def timeIn(self, time)
If t is in a segment returns the distance to the edges, otherwise returns False.
def plotCumulativeDurations(self, outfile, maxdur=None)
def __init__(self, seglist, gpsstart=None, gpsend=None)
def notSegments(self, start, end)
Get the complement of the (non-overlapping) segments in this data.
def hasTime(self, time)
Checks whether time is in the segments.
def unionSegments(self, other)
Take the union of segment lists.
def fits(self, minlen)
Returns the list of segments that fit a minimum required length.
def printToFile(self, outfile)
def intersectSegments(self, other)
Returns the intersection with another list of segments.
A time segment in an IFO.
def intersectWith(self, other)
Intersects with another segment.
def __init__(self, data, gpsstart=None, gpsend=None)
Creates a segment.
def hasTime(self, time)
Checks if time is in (open) segment.
def intersectWithList(self, id0, other, sortedlist=True, startid=None)
Intersect segment with list of (non-overlapping) segments.
def getTriples(ifo1, ifo2, ifo3, unvetoed=False)
Combines 3 IFO objects into one.
def getDoubles(ifo1, ifo2, unvetoed=False)
Combines 2 interferometer objects into a new one, taking intersection of segments and union of vetoes...
def ensure_dir(f)
CREATE FOLDER IF IT DOES NOT EXIST.
def generateTimeslides(tdict, n, ref=None, outfolder=None, verbose=False)
Generate a list of injection times and timeslides, given a dictionary of (single) injection times.