Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALInference 4.1.9.1-b246709
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
omegascans_dag.py
Go to the documentation of this file.
1"""
2Running the omega pipeline with condor for an arbitrary amount of sources
3"""
4
5__author__ = "Jeroen Meidam"
6__credits__ = ["Jeroen Meidam"]
7__maintainer__ = "Jeroen Meidam"
8__email__ = "jeroen.meidam@ligo.org"
9__status__ = ""
10
11usage=""" omegascans_dag.py config.ini [options]
12 This script creates a DAG to run the omega pipeline for multiple detectors
13 and multiple sources on a cluster.
14 Framefiles are automatically looked up with gw_data_find
15
16 It requires a config file and a sourcefile containing trigtimes
17 and detector timeslides.
18
19 Run with --example to create an example config and sourcefile.
20
21 It is possible to include auxiliary channels in the scans only for H1 and L1.
22 For Virgo this is only possible on one of the Virgo clusters
23"""
24
25###############################################################################
26#
27# LOAD LIBRARIES
28#
29###############################################################################
30
31from lal import pipeline
32from optparse import OptionParser
33import uuid
34import os
35import sys
36import ast
37from subprocess import Popen,PIPE
38
39from configparser import ConfigParser
40
41###############################################################################
42#
43# DEFINITIONS
44#
45###############################################################################
46
47DefaultFrameTypes = {'L1':'L1_RDS_R_L1',#Includes auxiliary channels
48 'H1':'H1_RDS_R_L1',#Includes auxiliary channels
49 'V1':'T1300121_V1_EARLY_RECOLORED_V2'}
50
51DefaultConfigFiles = {'L1':'/archive/home/omega/configurations/S6/S6b/L0L1-RDS_R_L1-selected.txt',
52 'H1':'/archive/home/omega/configurations/S6/S6b/H0H1-RDS_R_L1-selected.txt',
53 'V1':''}
54
55RecoloredFrameTypes = {'L1':'T1200307_V4_EARLY_RECOLORED_V2',
56 'H1':'T1200307_V4_EARLY_RECOLORED_V2',
57 'V1':'T1300121_V1_EARLY_RECOLORED_V2'}
58
59ConfigRecoloredV = \
60"""
61# QScan configuration file
62
63# Scans H1 and L1 gravitational-wave channel data
64# from the S5 version 1 calibrated data set
65
66# Shourov K. Chatterji
67# shourov@ligo.caltech.edu
68# 2006-02-11
69
70[Context,Context]
71
72[Parameters,Parameter Estimation]
73
74[Notes,Notes]
75
76[Gravitational,Gravitational wave data]
77
78{
79 channelName: 'V1:h_16384Hz'
80 frameType: 'T1300121_V1_EARLY_RECOLORED_V2'
81 sampleFrequency: 4096
82 searchTimeRange: 128
83 searchFrequencyRange: [32 Inf]
84 searchQRange: [3.32 141]
85 searchMaximumEnergyLoss: 0.2
86 whiteNoiseFalseRate: 1e-3
87 alwaysPlotFlag: 1
88 searchWindowDuration: 0.5
89 plotTimeRanges: [1 8 100]
90 plotFrequencyRange: []
91 plotNormalizedEnergyRange: [0 25.5]
92}
93"""
94
95ConfigRecoloredL = \
96"""
97# QScan configuration file
98
99# Scans H1 and L1 gravitational-wave channel data
100# from the S5 version 1 calibrated data set
101
102# Shourov K. Chatterji
103# shourov@ligo.caltech.edu
104# 2006-02-11
105
106[Context,Context]
107
108[Parameters,Parameter Estimation]
109
110[Notes,Notes]
111
112[Gravitational,Gravitational wave data]
113
114{
115 channelName: 'L1:LDAS-STRAIN'
116 frameType: 'T1200307_V4_EARLY_RECOLORED_V2'
117 sampleFrequency: 4096
118 searchTimeRange: 128
119 searchFrequencyRange: [32 Inf]
120 searchQRange: [3.32 141]
121 searchMaximumEnergyLoss: 0.2
122 whiteNoiseFalseRate: 1e-3
123 alwaysPlotFlag: 1
124 searchWindowDuration: 0.5
125 plotTimeRanges: [1 8 100]
126 plotFrequencyRange: []
127 plotNormalizedEnergyRange: [0 25.5]
128}
129"""
130
131ConfigRecoloredH = \
132"""
133# QScan configuration file
134
135# Scans H1 and L1 gravitational-wave channel data
136# from the S5 version 1 calibrated data set
137
138# Shourov K. Chatterji
139# shourov@ligo.caltech.edu
140# 2006-02-11
141
142[Context,Context]
143
144[Parameters,Parameter Estimation]
145
146[Notes,Notes]
147
148[Gravitational,Gravitational wave data]
149
150{
151 channelName: 'H1:LDAS-STRAIN'
152 frameType: 'T1200307_V4_EARLY_RECOLORED_V2'
153 sampleFrequency: 4096
154 searchTimeRange: 128
155 searchFrequencyRange: [32 Inf]
156 searchQRange: [3.32 141]
157 searchMaximumEnergyLoss: 0.2
158 whiteNoiseFalseRate: 1e-3
159 alwaysPlotFlag: 1
160 searchWindowDuration: 0.5
161 plotTimeRanges: [1 8 100]
162 plotFrequencyRange: []
163 plotNormalizedEnergyRange: [0 25.5]
164}
165"""
166
167ConfigsRecolored = {'L1':ConfigRecoloredL,
168 'H1':ConfigRecoloredH,
169 'V1':ConfigRecoloredV}
170
171ExampleConfig = \
172"""
173[paths]
174#The basedir is where the dag and sub files end up.
175basedir=/home/jmeidam/tiger_runs/omegascans/example
176
177#Within the outdir you will have one folder for each trigtime
178# and within that, a resultsfolder (the resultspage) for each ifo
179out=/home/jmeidam/public_html/omegascans/example
180
181#A file that contains a list of sources, each of which has at least
182# a trigtime, and timeslide for each detector (can be 0.0)
183sourcefile=/home/jmeidam/tiger_runs/omegascans/example/omegascanslist.txt
184
185
186
187[omegapipe]
188executable=/home/omega/opt/omega/bin/wpipeline
189
190
191
192[analysis]
193ifos=['L1','H1','V1']
194
195frametypes={'L1':'L1_RDS_R_L1','H1':'H1_RDS_R_L1','V1':'T1300121_V1_EARLY_RECOLORED_V2'}
196
197accounting_group=ligo.dev.o1.cbc.testgr.tiger
198
199#oddslimit can be empty if all sources in sourcefile are to be scanned
200# in this example, only odds > 20 are scanned
201oddslimit={'low':20.0}
202
203#comment out "basicscan" to include auxiliary channels as well
204basicscan=
205
206#leave out to use defaults, also ignored when basicscan is set
207#conigfiles={'L1':'conig_L1.txt','H1':'conig_H1.txt','V1':'conig_V1.txt'}
208
209
210
211[cbcwikitable]
212#A table will be written out to the output folder that can be pasted into
213#a CBC wiki page. The table includes links to all the scans.
214
215#When outlier is given a value, the CBCwiki_table will only include entries
216# where LogOdds > outlier. Not needed if already set with "oddslimit"
217outlier=20.0
218
219#the webdir is used to create links to the omega scan pages.
220# Make sure it corresponds to the "out" directory in the [paths] section
221webdir=https://ldas-jobs.ligo.caltech.edu/~jmeidam/omegascans/example
222"""
223
224ExampleSourceFile = \
225"""trigtime H1 L1 V1 logodds
226966944343 0 1869348 593939 107.23
227970687764 0 -1963504 -903565 156.14
228969100904 0 -109089 -2545560 96.04
229"""
230
231###############################################################################
232#
233# FUNCTIONS
234#
235###############################################################################
236
237def mkdirs(path):
238 """
239 Helper function. Make the given directory, creating intermediate
240 dirs if necessary, and don't complain about it already existing.
241 """
242 if os.access(path,os.W_OK) and os.path.isdir(path): return
243 else: os.makedirs(path)
244
245def system_call(command):
246 p = Popen([command], stdout=PIPE,stderr=PIPE, shell=True)
247 out, err = p.communicate()
248 return out, err#p.stdout.read(),p.stderr.read()
249
250def get_framedir(trigtime,timeslide,ifo,frametype):
251 """
252 Use gw_data_find to find the frame directory name which is used as
253 an argument to wpipeline.
254 """
255 scantime = trigtime+timeslide
256
257 #get framefile location with datafind:
258 command="/usr/bin/gw_data_find --observatory=%s --url-type=file --type=%s --gps-start-time=%.3f --gps-end-time=%.3f"%(ifo[0],frametype,scantime,scantime)
259 datafind_stdout,datafind_stderr = system_call(command)
260 if not datafind_stdout:
261 print(datafind_stderr)
262 exit("gw_data_find failed, exiting...")
263 gwf_file = datafind_stdout.replace("file://localhost","").strip()
264 gwf_dir = os.path.dirname(gwf_file).strip()
265
266 #An extra check to be sure the output was not gibberish
267 if not os.path.isfile(gwf_file):
268 exit("%s is not a file or does not exist, exiting..."%gwf_file)
269
270 return gwf_dir
271
272
273def fix_subfile(subfile):
274 """
275 The omega pipeline executable is followed by "scan", which
276 needs to be in front of all the other arguments and options.
277 This function corrects the final subfile to this end.
278 - It removes "scan" from the executable
279 - Places it as the first item in "arguments"
280 """
281 with open(subfile, 'r') as f:
282 lines = f.readlines()
283 i=0
284 i_exec = 0
285 i_args = 0
286 for l in lines:
287 if l.split()[0] == "executable":
288 i_exec=i
289 if l.split()[0] == "arguments":
290 i_args=i
291 i+=1
292
293 #remove last item of the executable line, which should be "scan".
294 if lines[i_exec].strip().split()[-1] == "scan":
295 execitem = lines[i_exec].strip().split()[:-1]
296 lines[i_exec] = ' '.join(execitem)
297 lines[i_exec] += '\n'
298
299 #add scan as the first argument
300 x = lines[i_args]
301 lines[i_args] = x.replace('"','" scan',1)
302
303 #rewrite subfile
304 with open(subfile, 'w') as f:
305 for line in lines:
306 f.write(line)
307
308
309def fix_scriptfile(dagpath,dagfilename,executable):
310 """
311 If the scan argument is not included in the executable,
312 it will not show up in the sh file.
313 This function corrects that.
314 """
315 scriptname = ".".join(dagfilename.split(".")[:-1]) + ".sh"
316 with open(os.path.join(dagpath,scriptname), 'r') as f:
317 lines = f.readlines()
318
319 if len(executable.split())>1:
320 if executable.split()[1] == 'scan':
321 print("scan found")
322 return
323
324 #do the following if scan is not present
325 i=0
326 for l in lines:
327 spl = l.strip().split()
328 if len(spl) > 1:
329 if len(spl[0].split('/')) > 1: #the line we need
330 x = spl[0]
331 x += " scan"
332 for item in spl[1:]:
333 x+=" %s"%item
334 x+='\n'
335 lines[i]=x
336 i+=1
337
338 #rewrite
339 with open(os.path.join(dagpath,scriptname), 'w') as f:
340 for line in lines:
341 f.write(line)
342
343###############################################################################
344#
345# CLASSES
346#
347###############################################################################
348
349class OmegaScansDAG(pipeline.CondorDAG):
350 def __init__(self,cp):
351 self.config=cp
352
353 ## Setup some paths and filenames
354 self.basepath = self.config.get('paths','basedir')
355 self.sourcefile = self.config.get('paths','sourcefile')
356 self.outpath = self.config.get('paths','out')
357 mkdirs(self.outpath)
358 self.daglogfile=os.path.join(self.basepath,'omegascans-'+str(uuid.uuid1())+'.log')
359 pipeline.CondorDAG.__init__(self,self.daglogfile)
360 if cp.has_option('paths','logdir'):
361 self.logpath=cp.get('paths','logdir')
362 else:
363 self.logpath=os.path.join(self.basepath,'log')
364 mkdirs(self.logpath)
365 self.dagfilename="omegascans"
366 self.submitFile = os.path.join(self.basepath,'omegascans.sub')
367
368 #get ifos
369 if cp.has_option('analysis','ifos'):
370 self.ifos=ast.literal_eval(cp.get('analysis','ifos'))
371 else:
372 self.ifos=['H1','L1','V1']
373
374 #Set the DAG's filename
375 self.set_dag_file(os.path.join(self.basepath,self.dagfilename))
376
377 #Set the config files and frametypes
378 self.frametypes=ast.literal_eval(cp.get('analysis','frametypes'))
379 if cp.has_option('analysis','configfiles'):
380 self.configfiles=ast.literal_eval(cp.get('analysis','configfiles'))
381 else:
382 if cp.has_option('analysis','basicscan'):
383 self.configfiles={}
384 self.frametypes=RecoloredFrameTypes
385 for ifo in self.ifos:
386 self.configfiles[ifo]=os.path.join(self.basepath,"basic_config_%s.txt"%ifo)
387 with open(os.path.join(self.basepath,self.configfiles[ifo]),'w') as f:
388 f.write(ConfigsRecolored[ifo])
389 else:
390 if 'V1' in self.ifos:
391 #For V1 there is no other file available on non-virgo clusters
392 DefaultConfigFiles['V1']=os.path.join(self.basepath,"basic_config_V1.txt")
393 with open(os.path.join(self.basepath,DefaultConfigFiles['V1']),'w') as f:
394 f.write(ConfigsRecolored['V1'])
395 self.configfiles=DefaultConfigFiles
396
397
398 #get info (e.g. trigtimes and timeslides) from data file
399 info = self.ReadInfoFromFile(self.ifos)
400 Nsources = len(info['trigtime'])
401
402 #create the job and add the nodes
403 job = OmegaScanJob(self.config,self.submitFile,self.logpath)
404
405 #set limits for analysis
406 self.oddslimit_set = False
407 if self.config.has_option('analysis','oddslimit'):
408 self.oddslimit=ast.literal_eval(self.config.get('analysis','oddslimit'))
409 if self.oddslimit.has_key('low') or self.oddslimit.has_key('high'):
410 self.oddslimit_set = True
411 if not self.oddslimit.has_key('low'):
412 self.oddslimit['low'] = float('-inf')
413 if not self.oddslimit.has_key('high'):
414 self.oddslimit['high'] = float('inf')
415 else:
416 self.oddslimit={'low':float('-inf'),'high':float('inf')}
417
418
419
420 #This is where we store data for a wiki table
422
423 print("calling gw_data_find for each node...")
424 for n in range(Nsources):
425 timeslides={}
426 if self.oddslimit_set:
427 if info['logodds'][n] > self.oddslimit['low'] and info['logodds'][n] < self.oddslimit['high']:
428 for ifo in self.ifos:
429 node = OmegaScanNode(info['trigtime'][n],info[ifo][n],ifo,self.frametypes[ifo],self.configfiles[ifo],self.outpath,job)
430 timeslides[ifo] = info[ifo][n]
431 self.add_node(node)
432 self.add_table_entry(info['trigtime'][n],timeslides,self.ifos,info['logodds'][n])
433 else:
434 for ifo in self.ifos:
435 node = OmegaScanNode(info['trigtime'][n],info[ifo][n],ifo,self.frametypes[ifo],self.configfiles[ifo],self.outpath,job)
436 timeslides[ifo] = info[ifo][n]
437 self.add_node(node)
438 self.add_table_entry(info['trigtime'][n],timeslides,self.ifos,0.0)
439 print("success!")
440
441 self.write_table()
442
443 def add_table_entry(self,trigtime,timeslides,ifos,logodds):
444 table_entry = {}
445 for ifo in ifos:
446 table_entry[ifo]=timeslides[ifo]
447 table_entry['trigtime']=trigtime
448 table_entry['logodds']=logodds
449
450 self.table_entries.append(table_entry)
451
452 def write_table(self):
453 """
454 writes a cbc wiki type table with some information and links
455 """
456
457 filename = os.path.join(self.outpath,"CBCwiki_table.txt")
458 print("writing CBC wiki table to \"%s\""%filename)
459
460 outlier=None
461 if self.config.has_option('cbcwikitable','outlier'):
462 outlier=float(self.config.get('cbcwikitable','outlier'))
463
464 fp = open(filename,'w')
465
466 webdir=None
467 if self.config.has_option('cbcwikitable','webdir'):
468 webdir=self.config.get('cbcwikitable','webdir')
469
470 header="||'''trigtime'''"
471 for ifo in self.ifos:
472 header+="||'''timeslide %s'''"%ifo
473 for ifo in self.ifos:
474 header+="||'''injtime %s'''"%ifo
475 header+="||'''log odds'''||"
476
477 fp.write(header+"\n")
478
479 entries_to_write=[]
480 if outlier:
481 for e in self.table_entries:
482 if float(e['logodds']) > outlier:
483 entries_to_write.append(e)
484 else:
485 entries_to_write = self.table_entries
486
487 for e in entries_to_write:
488 string="||%d"%e['trigtime']
489 #timeslide entries
490 for ifo in self.ifos:
491 string+="||%d"%e[ifo]
492 #injection time entries
493 for ifo in self.ifos:
494 time = float(e['trigtime'])+float(e[ifo])
495 if webdir:
496 link = os.path.join(webdir,"scan_%d"%e['trigtime'],"%s_%.2f"%(ifo,time))
497 string+="||[[%s|%d]]"%(link,time)
498 else:
499 string+="||%d"%time
500 string+="||%.3f||"%e['logodds']
501 fp.write(string+"\n")
502
503 fp.close()
504
505
506 def ReadInfoFromFile(self,ifos):
507 """
508 Reads in a file containing columns for at least trigtime, timeslide ifo1, timeslide ifo2 and timeslide ifo3 resp.
509 """
510 headerdict={}
511 info = {}
512
513 oddslimit_set = False
514 if self.config.has_option('analysis','oddslimit'):
515 oddstest = ast.literal_eval(self.config.get('analysis','oddslimit'))
516 if oddstest.has_key('low') or oddstest.has_key('high'):
517 oddslimit_set = True
518
519
520
521 with open(self.sourcefile,'r') as f:
522
523 data=f.readlines()
524
525 #Read the header to get the IFO names
526 header = data[0].strip().split()
527 Nsources = len(data)-1
528
529 #redefine data without the header
530 data = data[1:]
531
532 #which header label corresponds to which collum
533 for i in range(len(header)):
534 headerdict[header[i]] = i
535
536 for ifo in ifos:
537 if not headerdict.has_key("timeslide_"+ifo) and not headerdict.has_key(ifo):
538 sys.exit("ERROR: Not all ifos from config file are present in \""+self.sourcefile+"\"")
539
540 if not headerdict.has_key('trigtime') and not headerdict.has_key('injtime'):
541 sys.exit("ERROR: The \""+self.sourcefile+"\" does not contain \"trigtime\" column.")
542
543 if oddslimit_set:
544 #values for logodds are required if a limit was set
545 if not headerdict.has_key('logodds') and not headerdict.has_key('logO'):
546 sys.exit("ERROR: An odds limit was set, but \""+self.sourcefile+"\" does not contain \"logodds\" column.")
547
548 #change header dict to use preferred format
549 for ifo in ifos:
550 if headerdict.has_key("timeslide_"+ifo):
551 val = headerdict["timeslide_"+ifo]
552 headerdict[ifo]=val
553 if headerdict.has_key("injtime"):
554 val = headerdict["injtime"]
555 headerdict["trigtime"]=val
556 if oddslimit_set:
557 if headerdict.has_key("logO"):
558 val = headerdict["logO"]
559 headerdict["logodds"]=val
560
561 #read in the remaining lines
562 for ifo in ifos:
563 timeslist=[]
564 for n in range(Nsources):
565 linesplit = data[n].strip().split()
566 col = headerdict[ifo]
567 timeslist.append(float(linesplit[col]))
568 info[ifo]=timeslist
569
570 #read the trigtimes
571 trigtimeslist=[]
572 if oddslimit_set: logoddslist=[]
573 for n in range(Nsources):
574 linesplit = data[n].strip().split()
575 coltrig = headerdict['trigtime']
576 trigtimeslist.append(float(linesplit[coltrig]))
577 if oddslimit_set:
578 colodds = headerdict['logodds']
579 logoddslist.append(float(linesplit[colodds]))
580
581 info['trigtime'] = trigtimeslist
582 if oddslimit_set:
583 info['logodds'] = logoddslist
584
585 return info
586
587class OmegaScanJob(pipeline.CondorDAGJob):
588 def __init__(self,cp,submitFile,logdir):
589 self.basepath=cp.get('paths','basedir')
590
591 pipeline.CondorDAGJob.__init__(self,'vanilla',cp.get('omegapipe','executable'))
592
593 self.set_sub_file(os.path.abspath(submitFile))
595 self.machine_memory=str(1024) # default value
596 self.add_condor_cmd('accounting_group',cp.get('analysis','accounting_group'))
597 self.add_condor_cmd('RequestMemory',str(2000))
598 self.add_arg("--report")
599 self.set_stdout_file(os.path.join(logdir,'omegascans-$(cluster)-$(process)-$(node).out'))
600 self.set_stderr_file(os.path.join(logdir,'omegascans-$(cluster)-$(process)-$(node).err'))
601
602class OmegaScanNode(pipeline.CondorDAGNode):
603
604 def __init__(self,trigtime,timeslide,ifo,frametype,configfile,outdir,job,logodds=None):
605 self.framedir=get_framedir(trigtime,timeslide,ifo,frametype)
606 pipeline.CondorDAGNode.__init__(self,job)
607 self.__finalized=False
608 scantime = trigtime+timeslide
609
610 #sometimes there are unwanted lockfiles lying around.
611 #they will be removed, but the user is warned
612 lockfile = os.path.join(outdir,"scan_%.0f"%trigtime,"%s_%.2f"%(ifo,scantime),"lock.txt")
613 if os.path.isfile(lockfile):
614 print("WARNING: lock file found in output directory.\n Deleting it now, but check that you did not forget to stop some ongoing run.")
615 system_call('rm %s'%lockfile)
616
617 self.add_var_arg('%.3f'%scantime)
618 self.add_var_opt("outdir",os.path.join(outdir,"scan_%.0f"%trigtime,"%s_%.2f"%(ifo,scantime)))
619 self.add_var_opt("configuration",configfile)
620 self.add_var_opt("framecache",self.framedir)
621
622 def finalize(self):
623 if self.__finalized:
624 return
625 self.__finalized=True
626
627
628
629
630
631def main():
632
633 #############################################################################
634 #
635 # ARGUMENT PARSING
636 #
637 #############################################################################
638
639 parser=OptionParser(usage)
640 parser.add_option("-e","--example",default=False,dest="example",action="store_true",help="Create example config.ini and an example sourcefile")
641 (opts,args) = parser.parse_args()
642
643 if opts.example:
644 with open("omega_config.ini","w") as f:
645 f.write(ExampleConfig)
646 with open("omegascanslist.txt","w") as f:
647 f.write(ExampleSourceFile)
648
649 print("Example files \"omega_config.ini\" and \"omegascanslist.txt\" are created")
650 sys.exit(0)
651
652 if len(args) != 1:
653 parser.print_help()
654 sys.exit("ERROR: Must provide one config.ini")
655
656 cp=ConfigParser()
657 cp.optionxform = str
658 try:
659 cp.read_file(open(args[0]))
660 except AttributeError:
661 cp.readfp(open(args[0]))
662
663 dag=OmegaScansDAG(cp)
664
665 dag.write_sub_files()
666 dag.write_dag()
667 dag.write_script()
668
669 #fix the sub and sh files
670 #This is required because pipeline.py does not yet have the ability to add
671 #a specific argument before all other arguments and options ('scan' in this case)
672 fix_subfile(dag.submitFile)
673 fix_scriptfile(cp.get('paths','basedir'),dag.get_dag_file(),cp.get('omegapipe','executable'))
674
675 print('Successfully created DAG file.')
676 fulldagpath=os.path.join(cp.get('paths','basedir'),dag.get_dag_file())
677 print('Now run condor_submit_dag %s\n'%(fulldagpath))
678
679
680
681
682###############################################################################
683#
684# START THE MAIN FUNCTION
685#
686###############################################################################
687
688if __name__ == "__main__":
689 # START THE MAIN FUNCTION IF RUN AS A SCRIPT. OTHERWISE, JUST LOADS THE CLASS
690 # AND FUNCTION DEFINITIONS
691 exit(main())
def __init__(self, cp, submitFile, logdir)
def __init__(self, trigtime, timeslide, ifo, frametype, configfile, outdir, job, logodds=None)
def write_table(self)
writes a cbc wiki type table with some information and links
def add_table_entry(self, trigtime, timeslides, ifos, logodds)
def ReadInfoFromFile(self, ifos)
Reads in a file containing columns for at least trigtime, timeslide ifo1, timeslide ifo2 and timeslid...
def fix_scriptfile(dagpath, dagfilename, executable)
If the scan argument is not included in the executable, it will not show up in the sh file.
def get_framedir(trigtime, timeslide, ifo, frametype)
Use gw_data_find to find the frame directory name which is used as an argument to wpipeline.
def fix_subfile(subfile)
The omega pipeline executable is followed by "scan", which needs to be in front of all the other argu...