1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 """
20 Tomoki Isogai (isogait@carleton.edu)
21
22 Utility functions for KW_veto codes
23
24 """
25
26 from __future__ import division
27
28 import os
29 import sys
30 from math import floor, ceil
31 import cPickle
32 import glob
33 import shutil
34 import tempfile
35
36 import sqlite3
37
38 from glue.segments import segment, segmentlist
39 from glue import segmentsUtils
40
41
42
43
44
45
46
47
49 """
50 copied from glue.ligolw.dbtables by Kipp Cannon
51 I can't directly import from glue because dbtables collides with other tables
52
53 Utility code for moving database files to a (presumably local)
54 working location for improved performance and reduced fileserver
55 load.
56 """
57 def mktmp(path, verbose = False):
58 if not os.path.isdir(path):
59 os.makedirs(path)
60 fd, filename = tempfile.mkstemp(suffix = ".sqlite", dir = path)
61 os.close(fd)
62 if verbose:
63 print >>sys.stderr, "using '%s' as workspace" % filename
64 return filename
65
66 def truncate(filename, verbose = False):
67 if verbose:
68 print >>sys.stderr, "'%s' exists, truncating ..." % filename
69 try:
70 fd = os.open(filename, os.O_WRONLY | os.O_TRUNC)
71 except:
72 if verbose:
73 print >>sys.stderr, "cannot truncate '%s': %s" % (filename, str(e))
74 return
75 os.close(fd)
76 if verbose:
77 print >>sys.stderr, "done."
78
79 def cpy(srcname, dstname, verbose = False):
80 if verbose:
81 print >>sys.stderr, "copying '%s' to '%s' ..." % (srcname, dstname)
82 shutil.copy(srcname, dstname)
83
84 database_exists = os.access(filename, os.F_OK)
85
86 if tmp_path is not None:
87 target = mktmp(tmp_path, verbose)
88 if database_exists:
89 if replace_file:
90
91
92
93 truncate(filename, verbose = verbose)
94 else:
95
96
97 i = 1
98 while True:
99 try:
100 cpy(filename, target, verbose)
101 except IOError, e:
102 import errno
103 import time
104 if e.errno == errno.ENOSPC:
105 if i < 5:
106 if verbose:
107 print >>sys.stderr, "Warning: attempt %d: no space left on device, sleeping and trying again ..." % i
108 time.sleep(10)
109 i += 1
110 continue
111 else:
112 if verbose:
113 print >>sys.stderr, "Warning: attempt %d: no space left on device: working with original file" % i
114 os.remove(target)
115 target = filename
116 else:
117 raise e
118 break
119 else:
120 target = filename
121 if database_exists and replace_file:
122 truncate(target, verbose = verbose)
123
124 del mktmp
125 del truncate
126 del cpy
127
128 return target
129
130
131
132
133
134
135
136 -def save_db(cursor, table_name, filename, working_filename, order_by = None, verbose=True):
137 """
138 Originally written by Nickolas Fotopoulos, modified.
139 Convert a dictionary to SQLite database for later use and also save to
140 specified format file.
141 Supported file extensions are:
142 * .pickle - Python pickle file (dictionary serialized unchanged)
143 * .pickle.gz - gzipped pickle (dictionary serialized unchanged)
144 * .mat - Matlab v4 file (dictionary keys become variable names; requires
145 Scipy)
146 * .txt - ASCII text
147 * .txt.gz - gzipped ASCII text
148 * .bd - sqlite database
149
150 FIXME: add xml
151 """
152 if verbose:
153 print >> sys.stderr, "saving data in %s..." % filename
154
155 if filename == '':
156 raise ValueError, "Empty filename"
157
158 ext = os.path.splitext(filename)[-1]
159
160
161 if ext == '.db':
162 shutil.copy(working_filename,filename)
163 return
164
165
166 cmd = "select * from %s"%table_name
167 if order_by is not None:
168 cmd += " order by %s"%order_by
169 table = cursor.execute(cmd)
170
171
172 if ext == '.stdout':
173 print "\n".join(["# column %d: "%(i+1)+c[0] for i, c in enumerate(cursor.description)])
174 for row in table:
175 print "\t".join(map(str,row))
176 return
177
178
179 file_handle = file(filename, 'wb')
180
181
182 if ext == '.gz':
183 import gzip
184 file_handle = gzip.GzipFile(fileobj=file_handle, mode='wb')
185 ext = os.path.splitext(filename[:-len(ext)])[-1]
186
187 if ext == '.txt':
188 lines = []
189 lines.append("\n".join(["# column %d: "%(i+1)+c[0] for i, c in enumerate(cursor.description)])+"\n")
190 for row in table:
191 lines.append("\t".join(map(str,row)))
192 file_handle.write("\n".join(lines))
193 return
194
195 if ext == '.pickle' or '.mat':
196
197 columns = [c[0] for c in cursor.description]
198
199 data_dict = {}
200 for c in columns:
201 data_dict[c] = []
202
203 for row in table:
204 for c, r in zip(columns,row):
205 data_dict[c].append(r)
206
207 if ext == '.mat':
208 import scipy.io
209 scipy.io.savemat(filename, data_dict)
210 return
211
212 if ext == '.pickle':
213 import cPickle
214 output = cPickle.dumps(data_dict, protocol = 2)
215 file_handle.write(output)
216 return
217
218 else:
219 raise ValueError, "Unrecognized file extension"
220
221 -def load_db(dbFile, tmp_path, verbose):
222 """
223 Connect to database.
224 Also, return a dictionary having variables from KW_veto_calc in a form:
225 {variable name: variable value}
226 """
227 if verbose:
228 print >> sys.stderr, "connecting to database %s..."%dbFile
229 working_filename = get_connection_filename(\
230 dbFile, tmp_path=tmp_path, verbose=verbose)
231 connection = sqlite3.connect(working_filename)
232 cursor = connection.cursor()
233 params = {}
234 for v in cursor.execute("select var_name, value from params").fetchall():
235 params[v[0]] = v[1]
236
237 return cursor, connection, working_filename, params
238
240 """
241 This function returns a tuple:
242 (threshold, used percentage, # of coincident KW triggers above the threshold, # of total KW triggers above the threshold, # of vetoed GW triggers, veto efficiency, dead time, dead time percentage, (used percentage) / (random used percentage), (veto efficiency) / (dead time percentage)) that corresponds to threshold to be used for veto.
243 This returns just None for non candidate channel.
244 """
245 return cursor.execute("select * from result where usedPercentage > ? order by threshold asc",(critical_usedPer,)).fetchone()
246
247
249 """
250 If src alaready exists, this function rename it so that new file/directory
251 won't overwite
252 """
253 index = 0; dst = os.path.normpath(src)
254 while os.path.exists(dst):
255 index += 1
256 dst = "%s.%d"%(os.path.normpath(src),index)
257 if index > 0:
258 print >> sys.stderr, "Warning: %s already exists, renaming the existing one to %s and continuing..."%(src,dst)
259 os.renames(src,dst)
260
262 """
263 Load segments in glue.segments.segmentlist format
264 FIXME: possibly SQL Injection attack
265 """
266 seg_list = segmentlist([segment(s[0], s[1]) for s in\
267 cur.execute("select start_time, end_time from %s"%tableName)])
268
269 return seg_list.coalesce()
270
272 """
273 Write glue.segments.segmentlist format segments into database.
274 FIXME: possibly SQL Injection attack
275 """
276 seg_list.coalesce()
277 cur.execute("create table %s (start_time int, end_time int)"%tableName)
278 cur.executemany("insert into %s values (?,?)"%tableName,seg_list)
279
280 return cur
281
283 """
284 Take glue.segments.segmentlist and write in a ascii file in a form compatible
285 to the segment database.
286 """
287 open(file_name,'w').write("\n".join(["%d %d"%(s[0],s[1]) for s in segs]))
288
289
291 """
292 Read segments in segwizard form with sanity check and return
293 glue.segments.segmentlist
294 """
295 try:
296 seg_list =\
297 segmentsUtils.fromsegwizard(open(segfile),coltype=float,strict=False)
298 except(IOError):
299 print >> sys.stderr, """
300 Error: file contains no segments or glue.segmentsUtils.fromsegwizard is
301 not reading segments correctly. Please check the seg file.
302 (possibly comments in the file is causing this)
303 %s
304 """%segfile
305 raise
306
307 seg_list.coalesce()
308 if seg_list == [] or abs(seg_list) == 0:
309 print >> sys.stderr, """
310 Warning: File contains no segments or glue.segmentsUtils.fromsegwizard is
311 not reading segments correctly. Please check the seg file.
312 (Possibly comments in the file is causing this.)
313 Attempting to ignore.
314 """
315 return seg_list
316
318 """
319 Read segment file in ligolw xml type and return in glue.segments.segmentlist
320 format.
321 """
322 from glue.ligolw import ligolw
323 from glue.ligolw import table
324 from glue.ligolw import utils
325
326 def ContentHandler(xmldoc):
327 return ligolw.PartialLIGOLWContentHandler(xmldoc, lambda name, attrs:\
328 (name == ligolw.Table.tagName) and\
329 (table.Table.TableName(attrs["Name"]) in ["segment"]))
330 try:
331 table.use_in(ligolw.PartialLIGOLWContentHandler)
332 except AttributeError:
333
334
335 pass
336
337 xmldoc = utils.load_url(segfile, verbose = verbose,gz = segfile.endswith(".gz"), contenthandler = ContentHandler)
338 seg_list = segmentlist()
339 for table_elem in xmldoc.getElements(lambda e:\
340 (e.tagName == ligolw.Table.tagName)):
341 for row in table_elem:
342 seg_list.append(segment(row.start_time, row.end_time))
343 xmldoc.unlink()
344 return seg_list
345
347 """
348 Find out the version of the flag for the given seg.
349 """
350 from glue.ligolw import ligolw
351 from glue.ligolw import table
352 from glue.ligolw import utils
353
354 def ContentHandler(xmldoc):
355 return ligolw.PartialLIGOLWContentHandler(xmldoc, lambda name, attrs:\
356 (name == ligolw.Table.tagName) and\
357 (table.Table.TableName(attrs["Name"]) in ["segment_definer","segment_summary"]))
358 try:
359 table.use_in(ligolw.PartialLIGOLWContentHandler)
360 except AttributeError:
361
362
363 pass
364
365 xmldoc = utils.load_url(segfile, verbose = verbose,gz = segfile.endswith(".gz"), contenthandler = ContentHandler)
366 for n, table_elem in enumerate(xmldoc.getElements(lambda e:\
367 (e.tagName == ligolw.Table.tagName))):
368 if n == 0:
369 definer = {}
370 for row in table_elem:
371 if row.name != "RESULT":
372 definer[str(row.segment_def_id).split(":")[-1]] = row.version
373
374 if n == 1:
375 for row in table_elem:
376 if seg[0] >= row.start_time and seg[1] <= row.end_time:
377 if str(row.segment_def_id).split(":")[-1] in definer.keys():
378 xmldoc.unlink()
379 return definer[str(row.segment_def_id).split(":")[-1]]
380
381
383 """
384 Given the time of trigger, this aplies +/- window and round to integers
385 in a way it broadens the window
386 """
387 return segment(floor(eventTime - neg_window), ceil(eventTime + pos_window))
388
390 """
391 Make a list of the result files from KW_veto_calc and check sanity.
392 """
393 files_list = [os.path.join(result_dir,f) for f in os.listdir(result_dir) if f.endswith("-data.db")]
394 if verbose:
395 print >> sys.stderr, "result files:", files_list
396 if files_list==[]:
397 print >> sys.stderr, "Error: no result files found in %s"%result_dir
398 sys.exit(1)
399
400
401 if os.path.commonprefix(files_list)=="":
402 print >> sys.stderr, """
403 Error: Possibly files from different runs are coexisting.
404 Please check the result_dir.
405 """
406 sys.exit(1)
407
408 return files_list
409
411 """
412 Get individual file names from names with globs.
413 Input could be a mixture of glob and ',' seperated file list, something like
414 '../segs/*,H1_segs.txt'
415 also there might be white space between file names
416 """
417 file_globs = [f.strip() for f in globs.split(",") if f.strip()!=""]
418 all_files = []
419 for f in file_globs:
420 files = glob.glob(f)
421 if files == []:
422 print >> sys.stderr, "Error: %s not found"%f
423 sys.exit(1)
424 else:
425 all_files.extend(files)
426
427 return all_files
428