ATLAS Offline Software
calibdata.py
Go to the documentation of this file.
1 #!/bin/env python
2 
3 from __future__ import print_function
4 
5 from CalibDataClass import *
6 import readline
7 import sys
8 import traceback
9 import os
10 import fnmatch
11 import getopt
12 import re
13 import fileinput
14 import time
15 
16 # initializing some things, do not edit
17 usedb = CalibDbInfo.calibdb
18 noask = False
19 force = False
20 debug = False
21 quiet = False
22 nobatch = False
23 upload = False
24 createid = False
25 showlist = False
26 modifyhead = False
27 copy = False
28 copydata = []
29 head_id = None
30 tube_id = None
31 tube = None
32 chamber = None
33 lowrun = None
34 uprun = None
35 lowtime = None
36 uptime = None
37 copysrc = None
38 syncdb = False
39 constant_type = None
40 constant_arg = None
41 insert_time = None
42 sitename = None
43 implementation = None
44 status_flag = "NULL"
45 valid = []
46 delete = []
47 upload_args = []
48 rootfile = None
49 luminosity = None
50 newidfile = None
51 cd = None
52 autoimpl = False
53 synclimit = 1
54 
55 datatypes = ['t0','rt','adc','id']
56 
57 def usage():
58  print("\n --yes to avoid being asked for confirmation (-y)")
59  print("\n --quiet (-q) to run with no output. Will return 0 if no errors, 1 if any problem.")
60  print("\n --force (-F) to force delete of existing data attached to head id before upload or copy")
61  print("\n --list to list head id information from database (-l)")
62  print("\n --listdb to list available databases.")
63  print("\n--db=DATABASE to specify database to operate on (or to be used as destination in case of copy commands)")
64  print("\t If --db not specified actions will apply to default set by calibdb variable in CalibDbInfo.py")
65  print("\n --id=head id to apply actions to (-i headid). Not required by actions that \n\tmay create new head id (upload,copy,newid). If specified for upload or copy \n\tthen inserted data will be associated with that id. \n\t--force may be required to delete existing data for id")
66  print("\n --upload (-u) --path=/path/to/files [--path=/path/to/files] (-p)")
67  print("\tPath to 1 or more dir of files to upload named with chamber in filenames.\n\tIf directory is named YYYYMMDD will automatically use for lowtime/uptime. \n\tAssume 24HR period with end at midnight UTC of day in dir name.")
68  print("\tUpload can be a single filename. Filename doesn't have to contain chamber name if --chamber is specified.\n\tAny number of path arguments can be used though generally 2 would be used to upload RT and T0 together.\n")
69  print(" --implementation='implementation string'\n")
70  print("\tImplementation is ignored for RT as it is derived from type and path")
71  print("\n --type=[GTPM][T0BS][T0MT] (-t)")
72  print("\tArgument required if files do not have header. Ignored on per-file basis if standard header is provided in any file. Only one type can be specified (if uploading RT and T0 together at least one set must specify correct type in file headers). For RT upload type arguments are:")
73  print(" \tG = Gasmon RT")
74  print(" \tT = temperature-corrected")
75  print(" \tP = pressure-corrected")
76  print(" \tM = magnetic-field corrected")
77  print("\tFor T0 or ADC spectra types are:")
78  print(" \tT0BS = T0 Beam Splash")
79  print(" \tT0MT = T0 Mag,Temp corrected (also will accept T0CalibrationMT)")
80  print("\n --sync --from=database [--synclimit=<integer> (0 for no limit)] [--db=database]\n\tCompares head ids in source(--from) and destination db (--db), and synchronizes ids/data from\n\tsource if not found in destination (must be configured as 'replica').\n\tIf synclimit is not specified, will only sync highest head id. Otherwise sync until synclimit ids have been copied.\n\tIf both source and destination already contain same head ids then program will exit with no action.")
81  print("\n --copy=[t0,adc,rt] --from=ID[@DATABASE] (copy single id) or --from=database (for syncing to replicas) [--force] \n\tIf you do not provide existing --id to copy into then you may provide\n\timplementation, lowrun, uprun, lowtime, uptime to create new id with those parameters.\n\tTo modify some destination fields add --modifyhead and provide new values. \n\tFor convenience --implementation will be accepted without --modifyhead.\n\tIf target is specified as a replica in CalibDbInfo.py then you\n\tdo not need to specify destination ID or new id information - source meta information will be copied exactly.")
82  print("\tMultiple types may be copied at once, separate them with commas. t0 and adc are synonynms that copy the same tables (MDT_TUBE*)\n")
83  print("\tIn any case where a database is not provided for source (@DATABASE) or destination (--db)\n\tlocal database specified in config variable 'calibdb' is used")
84  print("\n --tube=tubeid (-b tubeid) \n\tNumeric ID (321937408) or tube name string (BIL1C01) to apply operations to")
85  print(" --chamber=chamberid (-c chamberid) \n\tChamber id or string to apply operations to.")
86  print("\n\tTube and chamber arguments can be applied to limit scope of any relevant operation.");
87  print("\tIf no tube or chamber is provided, operations effect all data for head id.")
88  print("\tMust provide --id with --tube or --chamber \n\tThey cannot be used to create new id with info for only one tube or chamber.")
89  print("\n --modifyhead --implementation='string' (only implementation,rootfile,statusflag supported). \n\tUse alone or in conjunction with 'copy' commands to modify existing head ids")
90  print("\n --newid to create a new headid from command line arguments (-n)")
91  print("\n --newidfile[=filename] -f [filename] \n\tUse to create a new headid from rows in file if provided \n\tor from info provided in command line args if no filename provided")
92  print("\tFile format is 5 columns ordered: \n\tIMPLEMENTATION LOWRUN UPRUN LOWTIME UPTIME\n\tFile can contain any number of rows to insert")
93  print("\n--lowrun (-L)")
94  print(" --uprun (-U)")
95  print("\tlowrun/uprun are required for new head ids")
96  print("\n --lowtime (-W) format: '20101231 23:59:00'")
97  print(" --uptime (-P) format '20101231 23:59:00'")
98  print("\tNote: lowtime/uptime are required for new head ids. \n\tIf first --path argument contains date in YYYYMMDD format then lowtime/uptime will be start and end of that day unless specified. ")
99  print("\n --luminosity (optional, defaults to 1.0)")
100  print("\n --rootfile (optional, defaults to 'none')")
101  print("\n --statusflag (optional, defaults to NULL")
102  print("\n --implementation (required for new head id)")
103  print("\tNOTE: Modifying other values is implemented internally but there is no option available to specify them - if needed please request.")
104  print("\n --delete [rt,t0,adc,id] (-e) to delete values for head id given by --id.\n\tIf id is in list, deletes that head id.\n\tDeleting id implies deleting values associated regardless of specification of adc,t0,rt in command.")
105  print("\n --setvalid [rt,t0,adc] (-z) sets data as valid for chamber or head id, requires --id and optionally --chamber args.\n")
106 
108  if noask == False and quiet == False:
109  confirm = raw_input("Enter 'y' or 'yes' if you wish to continue with operation: ")
110  else:
111  confirm = "y"
112  if confirm not in ("y","yes","Y","YES"):
113  return False
114  else:
115  return True
116 
117 def perr(error,exc=None,exit=False,):
118  if quiet == False:
119  output = error
120  if isinstance(exc,KeyboardInterrupt):
121  output += ": User Interrupt"
122  elif isinstance(exc,Exception):
123  if not isinstance(exc,SystemExit):
124  output += ": " + exc.__str__()
125  output += "\n"
126  print (output, file=sys.stderr)
127  if exit == True:
128  sys.exit(1)
129 
130 def pout(output,newline=True):
131  if newline:
132  output += "\n"
133  if quiet == False:
134  print (output)
135 
136 def check_path(path):
137  if os.path.isdir(path) or os.path.isfile(path):
138  return True
139  else:
140  perr("File/path argument to upload option does not exist", exit=True)
141  #sys.exit(1)
142 
143 # check --type argument
144 def check_algo_type(type):
145  if re.match(r'[GTPM]', type):
146  return True
147 
148  if type == 'T0CalibrationMT' or type == 'T0BS' or type == 'T0MT':
149  return True
150 
151  return False
152 
153 # check input data type in t0,adc,rt,id
154 def checktypes(arg):
155  if len(list(set(arg) & set(datatypes))) == 0:
156  return False
157  else:
158  return True
159 
160 def parse_date_dir(upload_arg):
161  global lowtime
162  global uptime
163  # try to parse a date from dirname and figure out IOV
164  check = re.compile('.*2[0-9][0-9][0-9][0-1][0-9][0-3][0-9]\/*')
165  find = re.compile('2[0-9][0-9][0-9][0-1][0-9][0-3][0-9]')
166  check_date = check.match(upload_arg)
167  if check_date != None and (lowtime == None and uptime == None):
168  upload_date = find.findall(upload_arg)
169  # calculate times for IOV from date found in upload_arg
170  lowtime = upload_date[0] + " 00:00:00"
171  uptime = upload_date[0] + " 23:59:59"
172  elif (lowtime != None and uptime != None):
173  upload_date = find.findall(uptime)
174  else:
175  pout("Upload directory name does not contain date in format: 20091021 and you did not specify lowtime/uptime in arguments. Today's date will be used.")
176  today = time.strftime('%Y%m%d')
177  lowtime = today + " 00:00:00"
178  uptime = today + " 23:59:59"
179  return [today]
180  return upload_date
181 
182 def summary(cd):
183  pout("Committed %s database operations this session in %s separate transactions. \nRolled back or failed %s write operations.\nTotal walltime %s and total CPU time %s seconds." % (cd.optotal, cd.transtotal, cd.opcount,cd.dbtime['wtime'],cd.dbtime['ptime']))
184 
185 # TODO: Rewrite all this to use argparse and
186 # consolidate some options into argument-optional
187 # versions (like --db to list db, --db= to set db, and then can remove --listdb)
188 # (getopt cannot handle optional arguments)
189 
190 # options
191 try:
192  opts, args = getopt.getopt(sys.argv[1:], "hup:d:t:b:c:m:i:nf:r:ylqDFL:U:W:P:", ["help", "upload","path=","delete=","type=","tube=","chamber=","implementation=","id=","newid","newidfile=","setvalid=","yes","list","quiet","debug","force","lowrun=","uprun=","lowtime=","uptime=","from=","copy=","modifyhead","luminosity=","rootfile=","statusflag=","listdb","db=","sync","synclimit=" ])
193 except getopt.GetoptError as err:
194  print ("A bad option was passed:", file=sys.stderr)
195  print (str(err), file=sys.stderr)
196  print ("Use option -h or --help for usage instructions", file=sys.stderr)
197  sys.exit(2)
198 
199 if len(opts) == 0:
200  print("This program requires an option: \n")
201  usage()
202  sys.exit(1)
203 
204 # option handling could probably be done better
205 # action prerequisite args here
206 for opt,arg in opts:
207  if opt in ["-y","--yes"]:
208  noask = True
209 
210  if opt in ["-h","--help"]:
211  usage()
212  sys.exit()
213 
214  if opt in ["--listdb"]:
215  print (CalibData.format_dblist())
216  sys.exit(0)
217 
218  if opt in ["--list", "-l"]:
219  showlist = True
220 
221  if opt in ["--db"]:
222  if arg in CalibDbInfo.databases:
223  usedb = arg
224  else:
225  perr("An unknown database was specified, valid databases are:");
226  print (CalibData.format_dblist())
227  sys.exit(1)
228 
229  if opt in ['--sync']:
230  syncdb = True
231 
232  if opt in ['--synclimit']:
233  if re.match("^\d+$", arg, flags=0):
234  synclimit = int(arg)
235  else:
236  perr("--synclimit must be integer",exit=True)
237 
238  if opt in ["-L","--lowrun"]:
239  lowrun = arg
240 
241  if opt in ["-U","--uprun"]:
242  uprun = arg
243 
244  if opt in ["-W","--lowtime"]:
245  lowtime = arg
246 
247  if opt in ["-P","--uptime"]:
248  uptime = arg
249 
250  if opt in ["--luminosity"]:
251  luminosity = arg
252 
253  if opt in ["--rootfile"]:
254  rootfile = arg
255 
256  if opt in ["--statusflag"]:
257  status_flag = arg
258 
259  if opt in ["-q", "--quiet"]:
260  quiet = True
261 
262  if opt in ["-D","--debug"]:
263  debug = True
264 
265  if opt in ["-i","--id"]:
266  head_id = arg
267 
268  if opt in ["-b","--tube"]:
269  tube = arg
270  nobatch = True
271 
272  if opt in ["-c","--chamber"]:
273  chamber = arg
274  nobatch = True
275 
276  if opt in ["-m","--implementation"]:
277  implementation = arg
278 
279  if opt in ["--copy"]:
280  copydata = arg.split(',')
281  copy = True
282  if not checktypes(copydata):
283  perr("Invalid copy types: %s" % arg)
284  upload_args.append('copyarg')
285 
286  if opt in ["--from"]:
287  copysrc = arg
288 
289  if opt in ["-z", "--setvalid"]:
290  valid = arg.split(',')
291  if not checktypes(valid):
292  perr("Invalid types for setting valid: %s" % arg)
293 
294  if opt in ["-e", "--delete"]:
295  delete = arg.split(',')
296  if not checktypes(delete):
297  perr("Invalid types for deletion: %s" % arg)
298 
299  if opt in ["--upload", "-u"]:
300  upload = True
301 
302  if opt in ["--modifyhead"]:
303  modifyhead = True
304 
305  if opt in ["-F","--force"]:
306  force = True
307 
308  if opt in ["-n", "--newid"]:
309  newidfile = None
310  createid = True
311  if upload == False:
312  upload_args = ['createid']
313 
314  if opt in ["-f","--newidfile"]:
315  implementation = 'fromfile'
316  newidfile = arg
317  createid = True
318  if upload == False:
319  upload_args = ['createid']
320 
321  if opt in ["-t","--type"]:
322  if check_algo_type(arg):
323  constant_arg = arg
324  else:
325  perr("Unknown algorithm type, not one of T0CalibrationMT, T0BS, T0MT or containing one of 'GTPM' for RT")
326  sys.exit(1)
327 
328  if opt in ["-p", "--path"]:
329  if check_path(arg):
330  upload_args.append(arg)
331 
332 try:
333 
334  if syncdb == True:
335  if copysrc not in CalibDbInfo.databases:
336  perr("\nMust specify a valid database key to --from argument",exit=True)
337  if usedb not in CalibDbInfo.databases:
338  perr("\nMust specify a valid destination database key to --db argument or in 'calibdb' setting in CalibDbInfo",exit=True)
339 
340  syncsrc = CalibData()
341  syncsrc.debug = debug
342  syncsrc.setdb(copysrc)
343  cd = CalibData()
344  cd.debug = debug
345  cd.setdb(usedb)
346 
347  srcdata = syncsrc.fetch_head_data()
348  dstdata = cd.fetch_head_data()
349  dst_ids = []
350  sync_ids = []
351 
352  for dst_head in dstdata:
353  dst_ids.append(dst_head[0])
354 
355  scount = 0
356  for src_head in srcdata:
357  if scount >= synclimit and synclimit != 0:
358  break
359  if src_head[0] not in dst_ids:
360  sync_ids.append(src_head[0])
361  scount += 1
362 
363  for copy_id in sync_ids:
364  print ("\nSyncing head id %s" % copy_id)
365  syncsrc = CalibData(copy_id)
366  syncsrc.setdb(copysrc)
367  syncsrc.debug = debug
368  syncsrc.get_head_info()
369  cd.copy_head(syncsrc)
370  cd.copy_tzero(syncsrc,ignore_missing=True)
371  cd.copy_rt(syncsrc,ignore_missing=True)
372 
373 
374  if upload == True or copy == True or createid == True:
375  # open file of head ids or set to 1 just to trigger 1 loop of head_id inserting from params
376  if newidfile != None and createid == True:
377  try:
378  idfile = open(newidfile, 'r')
379  except:
380  perr("Unable to open file of new head IDs: %s" % newidfile)
381  sys.exit(1)
382  else:
383  idfile = "1"
384 
385  # tally of how many files we read in the upcoming loop
386  count_files = 0
387  if upload == True:
388  pout("\nUploading from : %s" % (' '.join(upload_args)))
389  for upload_arg in upload_args:
390  if copy == True:
391  files = ["copyloop"]
392  elif upload_arg == 'createid':
393  files = ["idloop"]
394  else:
395  if os.path.isfile(upload_arg):
396  files = [upload_arg]
397  dirprep = ''
398  else:
399  files = os.listdir(upload_arg)
400  dirprep = upload_arg + "/"
401 
402  if head_id == None:
403  upload_date = parse_date_dir(upload_arg)
404 
405  for filename in files:
406  if not fnmatch.fnmatch(filename, '*.dat'):
407  continue
408  constant_type = constant_arg
409  # upload is initially false, becomes set to a string
410  if filename != 'copyloop' and filename != 'idloop':
411  f = open(dirprep + filename, 'r')
412  # read first line, determine what kind of upload this is. If RT with no header, we'll need to seek back to the first line.
413  f_start = f.tell()
414  rts = f.readline().split()
415  # T0 header is len 6, T0 is 19, ADC fit is 17.
416  if len(rts) == 6 or len(rts) == 19 or len(rts) == 17:
417  if len(rts) == 6:
418  ct = rts[3]
419  if constant_arg != None:
420  perr("Header found in input file, ignoring --type")
421  else:
422  ct = constant_type
423  f.seek(f_start)
424  if ct == "T0MT" or ct == "T0CalibrationMT":
425  upload = 't0'
426  constant_type = "T0MT"
427  fieldcount = 19
428  elif ct == "T0BS":
429  upload = 't0'
430  constant_type = ct
431  fieldcount = 19
432  elif ct == "ADCfit":
433  upload = 'adc'
434  constant_type = ct
435  fieldcount = 17
436  else:
437  raise Exception("Unrecognized algorithm type '%s' in T0 or ADC header in file %s" % (rts[3], filename))
438 
439  # if len == 3 it is RT with no header. If len == 12 it is RT with standard header
440  elif len(rts) == 3 or len(rts) == 12:
441  upload = 'rt'
442  fieldcount = 3
443  if len(rts) == 12:
444  # pull constant_type/algorithm from header. There isn't really a known standard for this so I'll use the one I invented for gas monitor RT uploads.
445  match_type = re.findall(r'[GPTM]+',rts[2])
446  if match_type:
447  constant_type = ''.join(match_type)
448  if constant_arg != None:
449  perr("Header found in input file, ignoring --type")
450  else:
451  raise Exception("Unable to find algorithm type from RT header field '%s' in file %s" % (rts[2],filename))
452  else:
453  f.seek(f_start)
454  if constant_type == None:
455  raise Exception("Unable to determine upload type from file contents: %s\nSpecifying a constant type with --type (aka ALGO_FLAG) is required for uploads if any files do not have a header." % filename)
456 
457  # only if no implementation argument on command line, set implementation from date defined by directory name of upload path
458  if implementation == None and head_id == None:
459  if upload == 'rt':
460  implementation = "RT_"
461  elif upload == 'adc' or upload == 't0':
462  implementation = "CALIB_"
463  implementation += constant_type + '_' + upload_date[0]
464  pout("No implementation specified, generating automatically: %s " % implementation)
465 
466  # end of specific to upload stuff......
467 
468  if cd == None:
469  for line in idfile:
470  if newidfile != None and createid == True:
471  idlines = line.split()
472  implementation = idlines[0]
473  lowrun = idlines[1]
474  uprun = idlines[2]
475  lowtime = idlines[3] + " " + idlines[4]
476  uptime = idlines[5] + " " + idlines[6]
477  try:
478  cd = CalibData(head_id,implementation,lowrun,uprun,lowtime,uptime,luminosity,rootfile,status_flag)
479  cd.debug = debug
480  cd.setdb(usedb)
481  if head_id != None:
482  cd.get_head_info()
483  if copy == True:
484  cdsource = CalibData(copysrc)
485  cdsource.debug = debug
486  cdsource.get_head_info()
487  pout("Source head id %s from database has information:" % cdsource.head_id)
488  pout(cdsource.format_headinfo())
489 
490  except QueryError as exc:
491  output = "\nCould not retrieve head id(s) from database: "
492  if "cdsource" not in locals() and head_id != None:
493  output += "ID %s" % head_id
494  if "cdsource" in locals():
495  output += " ID " + copysrc
496  perr(error=output,exception=exc)
497  sys.exit(1)
498 
499  if cd.head_id != None:
500  pout("Destination head id %s from database has information:" % cd.head_id)
501  pout(cd.format_headinfo())
502 
503  if implementation != None and copy == True:
504  pout("Setting/modifying destination implementation to '%s'" % implementation)
505  cdsource.implementation = implementation
506 
507  if (copy == True) and tube == None and chamber == None:
508  pout("If --id specified, copy will overwrite destination id with source values.\nIf implementation provided on command line it will be used for destination.\nIf no id is specified, a new one will be created with source data.\nIf destination is replica db an exact copy of source, including head id, will be created.")
509 
510  if cd.head_id == None:
511  try:
512  if copy == True:
513  cd.copy_head(cdsource)
514  else:
515  cd.write_headid()
516  pout("Successful commit will create new head ID: %s" % cd.head_id)
517  pout(cd.format_headinfo())
518  except HeadInsertError:
519  perr("Sorry, failed to setup head_id, quitting now")
520  raise
521 
522  if ask_confirm() == False:
523  sys.exit(0)
524 
525  if upload != False:
526  pout("\nFilename: %s" % filename, newline=False)
527  count_files += 1
528 
529  # this might seem redundant but we don't know what format we got from extract_tubestring
530  # the two methods below take whatever as an input and return a known format even if they might just return the input
531 
532  chamber_string = CalibData.extract_tubestring(filename)
533 
534  if (chamber_string):
535  chamber = CalibData.get_tube_string(chamber_string)
536  chamber_id = CalibData.get_tube_id(chamber_string)
537  elif (chamber):
538  chamber_id = CalibData.get_tube_id(chamber)
539  chamber = CalibData.get_tube_string(chamber)
540  else:
541  if filename != 'copyloop' and filename != 'idloop':
542  pout("Skipping %s, could not determine chamber from filename and none given on command line (may be fake bookkeeping chamber)" % filename)
543  continue
544 
545  pout("Chamber is: %s" % chamber, 0)
546  pout("Chamber id is: %s" % chamber_id, 0)
547 
548  if tube != None:
549  tube_id = CalibData.get_tube_id(tube)
550  tube = CalibData.get_tube_string(tube)
551  pout("Tube is: %s" % chamber, 0)
552  pout("Tube id is: %s" % chamber_id, 0)
553 
554  if upload != False:
555  cd.type = constant_type
556  if upload == 'rt':
557  try:
558  # insert RT into mdt_rt table, chamber_id was determined from file or arguments by this point
559  if force:
560  cd.delete_rt(chamber_id)
561  cd.insert_rt(chamber_id)
562 
563  except DataUniqueError:
564  perr("\nRT value exists for chamber.\nAdd --force to command to force delete before insert or delete rt with --delete='rt' option")
565  raise
566  except RTInsertError:
567  perr("Problem inserting RT for chamber: %s id: %s" % (chamber,chamber_id))
568  perr("Not deleting head id, reuse with --id flag or delete with --delete=id")
569  raise
570  except Exception:
571  perr("Error with RT insert operation")
572  raise
573 
574  # point_nr is just an informational count of datapoints in file (number of lines, start at 0 for first point)
575  point_nr = 0
576 
577  for line in f:
578  try:
579  rts = line.split()
580  if len(rts) != fieldcount:
581  perr("Invalid line in %s file %s, too many or too few fields" % (upload, filename))
582  if upload == 'rt':
583  cd.insert_rt_map(point_nr,rts[0],rts[1],rts[2])
584  elif upload == 't0' or upload == 'adc':
585  tube_id_string = rts[0] + "_" + rts[1] + "_" + rts[2] + "-" + rts[4] + "-" + rts[5] + "-" + rts[6]
586  tube_id = cd.get_tube_id(tube_id_string)
587  pout("Tube ID string: %s" % tube_id_string,0)
588  pout("Tube ID: %s" % tube_id)
589 
590  cd.t0_tube_grouping = "CHAMBER"
591  # hmm...not efficient if inserting a batch of them, but allows for not necessarily inserting/overwriting every t0.
592  # educate users to use --deletet0 for faster overwrites of existing t0 in batch uploads
593  if force == True:
594  cd.delete_tube(tube_id,chamber_id)
595  if upload == 't0':
596  cd.insert_t0(tube_id,chamber_id,rts[7],rts[8],rts[9],rts[10],rts[11],rts[12],rts[13],rts[14],rts[15],rts[16],rts[17],rts[18])
597  elif upload == 'adc':
598  cd.insert_adc(tube_id,chamber_id,rts[7],rts[8],rts[9],rts[10],rts[11],rts[12],rts[13],rts[14],rts[15],rts[16])
599  except (RTInsertError, T0InsertError, ADCInsertError):
600  perr("Error inserting values read at line %s in file %s" % (point_nr + 1, filename))
601  perr("Not deleting head id, reuse with --id flag or delete with --delete=id")
602  raise
603  except DataUniqueError:
604  perr("Values already exist for chamber %s (%s) tube %s (%s) at line %s in file %s. Use --force to delete existing t0 one-by-one before each insert. Use --delete=[t0,rt,adc] to delete values. \n" % (chamber, chamber_id, tube_id_string, tube_id, point_nr + 1, filename))
605  raise
606  except Exception:
607  perr("An error has occurred at line %s in file %s." % (point_nr + 1,filename))
608  raise
609  point_nr += 1
610 
611  if upload == 'rt' and point_nr != 100 and point_nr != 200:
612  raise Exception("Found %s data points in file %s. RT must have either 100 or 200 data points." % (point_nr,filename))
613  # reset all values or might validate values from this iteration on next one
614  chamber = None
615  chamber_id = None
616  tube = None
617  tube_id = None
618 
619  if count_files > 0:
620  pout("\nFound %d files in dir %s" % (count_files,upload_arg))
621  pout("\nInserting to head_id %s" % cd.head_id)
622 
623  if 't0' in copydata or 'adc' in copydata:
624  try:
625  if force == True:
626  cd.delete_tube(tube,chamber)
627  cd.copy_tzero(cdsource,chamber,tube)
628  #if implementation != None and head_id != None:
629  # cd.implementation = implementation
630  # cd.write_headid()
631  pout("T0/ADC copy complete")
632  except DataCopyError:
633  perr("Problem copying values from %s to %s@%s" % (copysrc, cd.head_id, cd.database))
634  raise
635  except DataUniqueError:
636  perr("Data for tube(s) or chamber(s) already exists. Use --force to overwrite.")
637  raise
638  except HeadInsertError:
639  perr("Error modifying head id %s" % cd.head_id)
640  raise
641  except Exception:
642  perr("Error copying T0/ADC")
643  raise
644 
645  if 'rt' in copydata:
646  try:
647  if force == True:
648  cd.delete_rt(chamber)
649  # should just require adding --modifyhead but for convenience in this one case...
650  cd.copy_rt(cdsource,chamber)
651  if implementation != None and head_id != None:
652  cd.implementation = implementation
653  cd.write_headid
654  pout("RT Copy complete")
655  except DataCopyError:
656  perr("Problem copying RT values from %s to %s@%s" % (copysrc, cd.head_id, cd.database))
657  raise
658  except DataUniqueError:
659  perr("Data for chamber(s) already exists. Use --force to overwrite.")
660  raise
661  except HeadInsertError:
662  perr("Error modifying head id %s" % cd.head_id)
663  raise
664  except Exception:
665  perr("Error copying RT")
666  raise
667  if (modifyhead):
668  if cd.head_id == None:
669  perr("Must provide --id with --modifyhead")
670  sys.exit(1)
671 
672  fields = { 'implementation':implementation, 'lowrun':lowrun, 'uprun':uprun, 'lowtime':lowtime, 'uptime':uptime,'luminosity':luminosity, 'rootfile':rootfile, 'sitename':sitename,'insert_time':insert_time, 'status_flag':status_flag }
673  modified = False
674  try:
675  for field,val in fields.items():
676  if val != None:
677  setattr(cd, field, val)
678  modified = True
679  if modified == False:
680  perr("No modification specified")
681  sys.exit(1)
682  cd.write_headid()
683  except HeadInsertError as exc:
684  perr("Error modifying head id" + cd.head_id, exc)
685  raise
686 
687  if showlist:
688  noask = True
689  try:
690  cd = CalibData()
691  cd.debug = debug
692  cd.setdb(usedb)
693  print (cd.format_head_data(cd.fetch_head_data()))
694  sys.exit(0)
695  except QueryError as exc:
696  perr("Error querying for head ids", exc)
697  sys.exit(1)
698 
699  if delete or valid:
700  if head_id == None:
701  perr("You did not give head id (--id=)")
702  sys.exit(1)
703 
704  if not isinstance(cd,CalibData):
705  cd = CalibData(head_id)
706  cd.setdb(usedb)
707  cd.debug = debug
708  try:
709  cd.get_head_info()
710  except QueryError as exc:
711  perr("Could not retrieve information for head id: %s" % head_id, exc)
712  sys.exit(1)
713 
714  if tube != None:
715  try:
716  tube_id = cd.get_tube_id(tube)
717  tube = cd.get_tube_string(tube)
718  except TubeIdError:
719  perr("Invalid tube string or numeric ID was input")
720  raise
721  except Exception:
722  perr("Unable to convert tube string or ID")
723  raise
724  else:
725  tube_id = None
726 
727  if chamber != None:
728  try:
729  chamber_id = cd.get_tube_id(chamber)
730  chamber = cd.get_tube_string(chamber)
731  except TubeIdError:
732  perr("Invalid tube string or numeric ID was input")
733  sys.exit(1)
734  except Exception:
735  perr("Invalid chamber string or ID was put in")
736  sys.exit(1)
737  else:
738  chamber_id = None
739 
740  if 'rt' in delete:
741  pout("Deleting RT for head id: %s, implementation name: %s " % (head_id,cd.implementation))
742  if chamber_id != None:
743  pout("Chamber: %s, chamber id: %s" % (chamber, chamber_id))
744  if ask_confirm() == False:
745  sys.exit(0)
746  try:
747  cd.delete_rt(chamber_id)
748  except DeleteError:
749  perr("Error deleting rt for head id %s \n" % head_id)
750  raise
751  except Exception:
752  raise
753 
754  if 't0' in delete:
755  pout("Deleting T0 for head id: %s, implementation name: %s " % (head_id,cd.implementation))
756  if chamber != None:
757  pout("Deleting t0 for chamber: %s, tube id: %s" % (chamber, chamber_id))
758  if tube_id != None:
759  pout("Deleting t0 for tube: %s, tube id: %s" % (tube, tube_id))
760  if ask_confirm() == False:
761  sys.exit(0)
762  try:
763  cd.delete_tube(tube_id,chamber_id)
764  except DeleteError:
765  perr("Error deleting t0 for head id %s" % head_id)
766  raise
767  except Exception:
768  raise
769 
770  # modify all this so any number of items can be set valid at once....
771  if 't0' in valid or 'adc' in valid:
772  try:
773  cd.set_t0_valid(tube_id)
774  except UpdateError:
775  print("Error setting t0 valid flag for head id %s \n" % head_id)
776  except Exception:
777  raise
778 
779  pout("Committing update of t0 valid flag for head id: %s, implementation name: %s " % (head_id,cd.implementation))
780  if tube_id != None:
781  pout("Tube: %s, tube id: %s" % (tube, tube_id))
782 
783  if 'rt' in valid:
784  try:
785  cd.set_rt_valid(tube_id)
786  except UpdateError:
787  perr("Error setting RT valid flag for head id %s \n" % head_id)
788  except Exception:
789  raise
790  pout("Committing update of rt valid flag for head id: %s, implementation name: %s " % (head_id,cd.implementation))
791  if tube_id != None:
792  pout("Tube: %s, tube id: %s" % (tube, tube_id))
793 
794  if 'id' in delete:
795  pout("*** Will delete associated RT ***")
796  pout("*** Will delete associated T0 ***")
797  pout("*** Will delete associated ADC ***")
798  pout ("*** Will delete all head id information ***")
799  pout(cd.format_headinfo())
800  if ask_confirm() == False:
801  sys.exit(0)
802  try:
803  cd.delete_head_id()
804  cd.delete_rt()
805  cd.delete_tube()
806  except DeleteError:
807  perr("Error deleting head id: %s" % head_id)
808  raise
809  except Exception:
810  raise
811 
812 # catch unhandled exceptions
813 except (Exception,KeyboardInterrupt) as exc:
814  # catch when we exit(0) by intent
815  if isinstance(exc,SystemExit):
816  if exc.code == 0:
817  sys.exit(0)
818  if debug == True:
819  traceback.print_exc()
820  perr("Error performing operation", exc)
821  if isinstance(cd,CalibData):
822  cd.rollback()
823  summary(cd)
824 
825  sys.exit(1)
826 
827 # safe and sound with no exceptions and time to commit whatever we did up there
828 # ...that is, time to commit anything that didn't get committed automatically when we exceeded 10000 operations for CalibData.opcount internally
829 
830 try:
831  pout("Committing data to database.")
832  commit = True
833  if debug:
834  commit = ask_confirm()
835  if commit == False:
836  cd.rollback()
837  if commit == True:
838  cd.commit(force=True)
839  summary(cd)
840 except Exception as exc:
841  perr("There was an error committing data", exc)
842  if cd:
843  cd.rollback()
844  summary(cd)
845  sys.exit(1)
846 
847 
848 
849 
calibdata.pout
def pout(output, newline=True)
Definition: calibdata.py:130
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
calibdata.perr
def perr(error, exc=None, exit=False)
Definition: calibdata.py:117
calibdata.check_algo_type
def check_algo_type(type)
Definition: calibdata.py:144
calibdata.parse_date_dir
def parse_date_dir(upload_arg)
Definition: calibdata.py:160
calibdata.check_path
def check_path(path)
Definition: calibdata.py:136
calibdata.summary
def summary(cd)
Definition: calibdata.py:182
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
calibdata.checktypes
def checktypes(arg)
Definition: calibdata.py:154
CxxUtils::set
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition: bitmask.h:232
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
Trk::open
@ open
Definition: BinningType.h:40
calibdata.usage
def usage()
Definition: calibdata.py:57
str
Definition: BTagTrackIpAccessor.cxx:11
dbg::print
void print(std::FILE *stream, std::format_string< Args... > fmt, Args &&... args)
Definition: SGImplSvc.cxx:70
CalibDataClass.CalibData
Definition: CalibDataClass.py:53
Trk::split
@ split
Definition: LayerMaterialProperties.h:38
calibdata.ask_confirm
def ask_confirm()
Definition: calibdata.py:107