4 from CalibDataClass
import *
16 usedb = CalibDbInfo.calibdb
54 datatypes = [
't0',
'rt',
'adc',
'id']
57 print(
"\n --yes to avoid being asked for confirmation (-y)")
58 print(
"\n --quiet (-q) to run with no output. Will return 0 if no errors, 1 if any problem.")
59 print(
"\n --force (-F) to force delete of existing data attached to head id before upload or copy")
60 print(
"\n --list to list head id information from database (-l)")
61 print(
"\n --listdb to list available databases.")
62 print(
"\n--db=DATABASE to specify database to operate on (or to be used as destination in case of copy commands)")
63 print(
"\t If --db not specified actions will apply to default set by calibdb variable in CalibDbInfo.py")
64 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")
65 print(
"\n --upload (-u) --path=/path/to/files [--path=/path/to/files] (-p)")
66 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.")
67 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")
68 print(
" --implementation='implementation string'\n")
69 print(
"\tImplementation is ignored for RT as it is derived from type and path")
70 print(
"\n --type=[GTPM][T0BS][T0MT] (-t)")
71 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:")
72 print(
" \tG = Gasmon RT")
73 print(
" \tT = temperature-corrected")
74 print(
" \tP = pressure-corrected")
75 print(
" \tM = magnetic-field corrected")
76 print(
"\tFor T0 or ADC spectra types are:")
77 print(
" \tT0BS = T0 Beam Splash")
78 print(
" \tT0MT = T0 Mag,Temp corrected (also will accept T0CalibrationMT)")
79 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.")
80 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.")
81 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")
82 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")
83 print(
"\n --tube=tubeid (-b tubeid) \n\tNumeric ID (321937408) or tube name string (BIL1C01) to apply operations to")
84 print(
" --chamber=chamberid (-c chamberid) \n\tChamber id or string to apply operations to.")
85 print(
"\n\tTube and chamber arguments can be applied to limit scope of any relevant operation.");
86 print(
"\tIf no tube or chamber is provided, operations effect all data for head id.")
87 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.")
88 print(
"\n --modifyhead --implementation='string' (only implementation,rootfile,statusflag supported). \n\tUse alone or in conjunction with 'copy' commands to modify existing head ids")
89 print(
"\n --newid to create a new headid from command line arguments (-n)")
90 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")
91 print(
"\tFile format is 5 columns ordered: \n\tIMPLEMENTATION LOWRUN UPRUN LOWTIME UPTIME\n\tFile can contain any number of rows to insert")
92 print(
"\n--lowrun (-L)")
93 print(
" --uprun (-U)")
94 print(
"\tlowrun/uprun are required for new head ids")
95 print(
"\n --lowtime (-W) format: '20101231 23:59:00'")
96 print(
" --uptime (-P) format '20101231 23:59:00'")
97 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. ")
98 print(
"\n --luminosity (optional, defaults to 1.0)")
99 print(
"\n --rootfile (optional, defaults to 'none')")
100 print(
"\n --statusflag (optional, defaults to NULL")
101 print(
"\n --implementation (required for new head id)")
102 print(
"\tNOTE: Modifying other values is implemented internally but there is no option available to specify them - if needed please request.")
103 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.")
104 print(
"\n --setvalid [rt,t0,adc] (-z) sets data as valid for chamber or head id, requires --id and optionally --chamber args.\n")
107 if noask ==
False and quiet ==
False:
108 confirm = raw_input(
"Enter 'y' or 'yes' if you wish to continue with operation: ")
111 if confirm
not in (
"y",
"yes",
"Y",
"YES"):
116 def perr(error,exc=None,exit=False,):
119 if isinstance(exc,KeyboardInterrupt):
120 output +=
": User Interrupt"
121 elif isinstance(exc,Exception):
122 if not isinstance(exc,SystemExit):
123 output +=
": " + exc.__str__()
125 print (output, file=sys.stderr)
136 if os.path.isdir(path)
or os.path.isfile(path):
139 perr(
"File/path argument to upload option does not exist", exit=
True)
144 if re.match(
r'[GTPM]', type):
147 if type ==
'T0CalibrationMT' or type ==
'T0BS' or type ==
'T0MT':
163 check = re.compile(
r'.*2[0-9][0-9][0-9][0-1][0-9][0-3][0-9]\/*')
164 find = re.compile(
r'2[0-9][0-9][0-9][0-1][0-9][0-3][0-9]')
165 check_date = check.match(upload_arg)
166 if check_date !=
None and (lowtime ==
None and uptime ==
None):
167 upload_date = find.findall(upload_arg)
169 lowtime = upload_date[0] +
" 00:00:00"
170 uptime = upload_date[0] +
" 23:59:59"
171 elif (lowtime !=
None and uptime !=
None):
172 upload_date = find.findall(uptime)
174 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.")
175 today = time.strftime(
'%Y%m%d')
176 lowtime = today +
" 00:00:00"
177 uptime = today +
" 23:59:59"
182 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']))
191 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=" ])
192 except getopt.GetoptError
as err:
193 print (
"A bad option was passed:", file=sys.stderr)
194 print (
str(err), file=sys.stderr)
195 print (
"Use option -h or --help for usage instructions", file=sys.stderr)
199 print(
"This program requires an option: \n")
206 if opt
in [
"-y",
"--yes"]:
209 if opt
in [
"-h",
"--help"]:
213 if opt
in [
"--listdb"]:
214 print (CalibData.format_dblist())
217 if opt
in [
"--list",
"-l"]:
221 if arg
in CalibDbInfo.databases:
224 perr(
"An unknown database was specified, valid databases are:");
225 print (CalibData.format_dblist())
228 if opt
in [
'--sync']:
231 if opt
in [
'--synclimit']:
232 if re.match(
r"^\d+$", arg, flags=0):
235 perr(
"--synclimit must be integer",exit=
True)
237 if opt
in [
"-L",
"--lowrun"]:
240 if opt
in [
"-U",
"--uprun"]:
243 if opt
in [
"-W",
"--lowtime"]:
246 if opt
in [
"-P",
"--uptime"]:
249 if opt
in [
"--luminosity"]:
252 if opt
in [
"--rootfile"]:
255 if opt
in [
"--statusflag"]:
258 if opt
in [
"-q",
"--quiet"]:
261 if opt
in [
"-D",
"--debug"]:
264 if opt
in [
"-i",
"--id"]:
267 if opt
in [
"-b",
"--tube"]:
271 if opt
in [
"-c",
"--chamber"]:
275 if opt
in [
"-m",
"--implementation"]:
278 if opt
in [
"--copy"]:
279 copydata = arg.split(
',')
282 perr(
"Invalid copy types: %s" % arg)
283 upload_args.append(
'copyarg')
285 if opt
in [
"--from"]:
288 if opt
in [
"-z",
"--setvalid"]:
289 valid = arg.split(
',')
291 perr(
"Invalid types for setting valid: %s" % arg)
293 if opt
in [
"-e",
"--delete"]:
294 delete = arg.split(
',')
296 perr(
"Invalid types for deletion: %s" % arg)
298 if opt
in [
"--upload",
"-u"]:
301 if opt
in [
"--modifyhead"]:
304 if opt
in [
"-F",
"--force"]:
307 if opt
in [
"-n",
"--newid"]:
311 upload_args = [
'createid']
313 if opt
in [
"-f",
"--newidfile"]:
314 implementation =
'fromfile'
318 upload_args = [
'createid']
320 if opt
in [
"-t",
"--type"]:
324 perr(
"Unknown algorithm type, not one of T0CalibrationMT, T0BS, T0MT or containing one of 'GTPM' for RT")
327 if opt
in [
"-p",
"--path"]:
329 upload_args.append(arg)
334 if copysrc
not in CalibDbInfo.databases:
335 perr(
"\nMust specify a valid database key to --from argument",exit=
True)
336 if usedb
not in CalibDbInfo.databases:
337 perr(
"\nMust specify a valid destination database key to --db argument or in 'calibdb' setting in CalibDbInfo",exit=
True)
340 syncsrc.debug = debug
341 syncsrc.setdb(copysrc)
346 srcdata = syncsrc.fetch_head_data()
347 dstdata = cd.fetch_head_data()
351 for dst_head
in dstdata:
352 dst_ids.append(dst_head[0])
355 for src_head
in srcdata:
356 if scount >= synclimit
and synclimit != 0:
358 if src_head[0]
not in dst_ids:
359 sync_ids.append(src_head[0])
362 for copy_id
in sync_ids:
363 print (
"\nSyncing head id %s" % copy_id)
365 syncsrc.setdb(copysrc)
366 syncsrc.debug = debug
367 syncsrc.get_head_info()
368 cd.copy_head(syncsrc)
369 cd.copy_tzero(syncsrc,ignore_missing=
True)
370 cd.copy_rt(syncsrc,ignore_missing=
True)
373 if upload ==
True or copy ==
True or createid ==
True:
375 if newidfile !=
None and createid ==
True:
379 perr(
"Unable to open file of new head IDs: %s" % newidfile)
387 pout(
"\nUploading from : %s" % (
' '.
join(upload_args)))
388 for upload_arg
in upload_args:
391 elif upload_arg ==
'createid':
394 if os.path.isfile(upload_arg):
398 files = os.listdir(upload_arg)
399 dirprep = upload_arg +
"/"
404 for filename
in files:
405 if not fnmatch.fnmatch(filename,
'*.dat'):
407 constant_type = constant_arg
409 if filename !=
'copyloop' and filename !=
'idloop':
410 f =
open(dirprep + filename,
'r')
415 if len(rts) == 6
or len(rts) == 19
or len(rts) == 17:
418 if constant_arg !=
None:
419 perr(
"Header found in input file, ignoring --type")
423 if ct ==
"T0MT" or ct ==
"T0CalibrationMT":
425 constant_type =
"T0MT"
436 raise Exception(
"Unrecognized algorithm type '%s' in T0 or ADC header in file %s" % (rts[3], filename))
439 elif len(rts) == 3
or len(rts) == 12:
444 match_type = re.findall(
r'[GPTM]+',rts[2])
446 constant_type =
''.
join(match_type)
447 if constant_arg !=
None:
448 perr(
"Header found in input file, ignoring --type")
450 raise Exception(
"Unable to find algorithm type from RT header field '%s' in file %s" % (rts[2],filename))
453 if constant_type ==
None:
454 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)
457 if implementation ==
None and head_id ==
None:
459 implementation =
"RT_"
460 elif upload ==
'adc' or upload ==
't0':
461 implementation =
"CALIB_"
462 implementation += constant_type +
'_' + upload_date[0]
463 pout(
"No implementation specified, generating automatically: %s " % implementation)
469 if newidfile !=
None and createid ==
True:
470 idlines = line.split()
471 implementation = idlines[0]
474 lowtime = idlines[3] +
" " + idlines[4]
475 uptime = idlines[5] +
" " + idlines[6]
477 cd =
CalibData(head_id,implementation,lowrun,uprun,lowtime,uptime,luminosity,rootfile,status_flag)
484 cdsource.debug = debug
485 cdsource.get_head_info()
486 pout(
"Source head id %s from database has information:" % cdsource.head_id)
487 pout(cdsource.format_headinfo())
489 except QueryError
as exc:
490 output =
"\nCould not retrieve head id(s) from database: "
491 if "cdsource" not in locals()
and head_id !=
None:
492 output +=
"ID %s" % head_id
493 if "cdsource" in locals():
494 output +=
" ID " + copysrc
495 perr(error=output,exception=exc)
498 if cd.head_id !=
None:
499 pout(
"Destination head id %s from database has information:" % cd.head_id)
500 pout(cd.format_headinfo())
502 if implementation !=
None and copy ==
True:
503 pout(
"Setting/modifying destination implementation to '%s'" % implementation)
504 cdsource.implementation = implementation
506 if (copy ==
True)
and tube ==
None and chamber ==
None:
507 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 if cd.head_id ==
None:
512 cd.copy_head(cdsource)
515 pout(
"Successful commit will create new head ID: %s" % cd.head_id)
516 pout(cd.format_headinfo())
517 except HeadInsertError:
518 perr(
"Sorry, failed to setup head_id, quitting now")
525 pout(
"\nFilename: %s" % filename, newline=
False)
531 chamber_string = CalibData.extract_tubestring(filename)
534 chamber = CalibData.get_tube_string(chamber_string)
535 chamber_id = CalibData.get_tube_id(chamber_string)
537 chamber_id = CalibData.get_tube_id(chamber)
538 chamber = CalibData.get_tube_string(chamber)
540 if filename !=
'copyloop' and filename !=
'idloop':
541 pout(
"Skipping %s, could not determine chamber from filename and none given on command line (may be fake bookkeeping chamber)" % filename)
544 pout(
"Chamber is: %s" % chamber, 0)
545 pout(
"Chamber id is: %s" % chamber_id, 0)
548 tube_id = CalibData.get_tube_id(tube)
549 tube = CalibData.get_tube_string(tube)
550 pout(
"Tube is: %s" % chamber, 0)
551 pout(
"Tube id is: %s" % chamber_id, 0)
554 cd.type = constant_type
559 cd.delete_rt(chamber_id)
560 cd.insert_rt(chamber_id)
562 except DataUniqueError:
563 perr(
"\nRT value exists for chamber.\nAdd --force to command to force delete before insert or delete rt with --delete='rt' option")
565 except RTInsertError:
566 perr(
"Problem inserting RT for chamber: %s id: %s" % (chamber,chamber_id))
567 perr(
"Not deleting head id, reuse with --id flag or delete with --delete=id")
570 perr(
"Error with RT insert operation")
579 if len(rts) != fieldcount:
580 perr(
"Invalid line in %s file %s, too many or too few fields" % (upload, filename))
582 cd.insert_rt_map(point_nr,rts[0],rts[1],rts[2])
583 elif upload ==
't0' or upload ==
'adc':
584 tube_id_string = rts[0] +
"_" + rts[1] +
"_" + rts[2] +
"-" + rts[4] +
"-" + rts[5] +
"-" + rts[6]
585 tube_id = cd.get_tube_id(tube_id_string)
586 pout(
"Tube ID string: %s" % tube_id_string,0)
587 pout(
"Tube ID: %s" % tube_id)
589 cd.t0_tube_grouping =
"CHAMBER"
593 cd.delete_tube(tube_id,chamber_id)
595 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])
596 elif upload ==
'adc':
597 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])
598 except (RTInsertError, T0InsertError, ADCInsertError):
599 perr(
"Error inserting values read at line %s in file %s" % (point_nr + 1, filename))
600 perr(
"Not deleting head id, reuse with --id flag or delete with --delete=id")
602 except DataUniqueError:
603 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))
606 perr(
"An error has occurred at line %s in file %s." % (point_nr + 1,filename))
610 if upload ==
'rt' and point_nr != 100
and point_nr != 200:
611 raise Exception(
"Found %s data points in file %s. RT must have either 100 or 200 data points." % (point_nr,filename))
619 pout(
"\nFound %d files in dir %s" % (count_files,upload_arg))
620 pout(
"\nInserting to head_id %s" % cd.head_id)
622 if 't0' in copydata
or 'adc' in copydata:
625 cd.delete_tube(tube,chamber)
626 cd.copy_tzero(cdsource,chamber,tube)
630 pout(
"T0/ADC copy complete")
631 except DataCopyError:
632 perr(
"Problem copying values from %s to %s@%s" % (copysrc, cd.head_id, cd.database))
634 except DataUniqueError:
635 perr(
"Data for tube(s) or chamber(s) already exists. Use --force to overwrite.")
637 except HeadInsertError:
638 perr(
"Error modifying head id %s" % cd.head_id)
641 perr(
"Error copying T0/ADC")
647 cd.delete_rt(chamber)
649 cd.copy_rt(cdsource,chamber)
650 if implementation !=
None and head_id !=
None:
651 cd.implementation = implementation
653 pout(
"RT Copy complete")
654 except DataCopyError:
655 perr(
"Problem copying RT values from %s to %s@%s" % (copysrc, cd.head_id, cd.database))
657 except DataUniqueError:
658 perr(
"Data for chamber(s) already exists. Use --force to overwrite.")
660 except HeadInsertError:
661 perr(
"Error modifying head id %s" % cd.head_id)
664 perr(
"Error copying RT")
667 if cd.head_id ==
None:
668 perr(
"Must provide --id with --modifyhead")
671 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 }
674 for field,val
in fields.items():
676 setattr(cd, field, val)
678 if modified ==
False:
679 perr(
"No modification specified")
682 except HeadInsertError
as exc:
683 perr(
"Error modifying head id" + cd.head_id, exc)
692 print (cd.format_head_data(cd.fetch_head_data()))
694 except QueryError
as exc:
695 perr(
"Error querying for head ids", exc)
700 perr(
"You did not give head id (--id=)")
703 if not isinstance(cd,CalibData):
709 except QueryError
as exc:
710 perr(
"Could not retrieve information for head id: %s" % head_id, exc)
715 tube_id = cd.get_tube_id(tube)
716 tube = cd.get_tube_string(tube)
718 perr(
"Invalid tube string or numeric ID was input")
721 perr(
"Unable to convert tube string or ID")
728 chamber_id = cd.get_tube_id(chamber)
729 chamber = cd.get_tube_string(chamber)
731 perr(
"Invalid tube string or numeric ID was input")
734 perr(
"Invalid chamber string or ID was put in")
740 pout(
"Deleting RT for head id: %s, implementation name: %s " % (head_id,cd.implementation))
741 if chamber_id !=
None:
742 pout(
"Chamber: %s, chamber id: %s" % (chamber, chamber_id))
746 cd.delete_rt(chamber_id)
748 perr(
"Error deleting rt for head id %s \n" % head_id)
754 pout(
"Deleting T0 for head id: %s, implementation name: %s " % (head_id,cd.implementation))
756 pout(
"Deleting t0 for chamber: %s, tube id: %s" % (chamber, chamber_id))
758 pout(
"Deleting t0 for tube: %s, tube id: %s" % (tube, tube_id))
762 cd.delete_tube(tube_id,chamber_id)
764 perr(
"Error deleting t0 for head id %s" % head_id)
770 if 't0' in valid
or 'adc' in valid:
772 cd.set_t0_valid(tube_id)
774 print(
"Error setting t0 valid flag for head id %s \n" % head_id)
778 pout(
"Committing update of t0 valid flag for head id: %s, implementation name: %s " % (head_id,cd.implementation))
780 pout(
"Tube: %s, tube id: %s" % (tube, tube_id))
784 cd.set_rt_valid(tube_id)
786 perr(
"Error setting RT valid flag for head id %s \n" % head_id)
789 pout(
"Committing update of rt valid flag for head id: %s, implementation name: %s " % (head_id,cd.implementation))
791 pout(
"Tube: %s, tube id: %s" % (tube, tube_id))
794 pout(
"*** Will delete associated RT ***")
795 pout(
"*** Will delete associated T0 ***")
796 pout(
"*** Will delete associated ADC ***")
797 pout (
"*** Will delete all head id information ***")
798 pout(cd.format_headinfo())
806 perr(
"Error deleting head id: %s" % head_id)
812 except (Exception,KeyboardInterrupt)
as exc:
814 if isinstance(exc,SystemExit):
818 traceback.print_exc()
819 perr(
"Error performing operation", exc)
820 if isinstance(cd,CalibData):
830 pout(
"Committing data to database.")
837 cd.commit(force=
True)
839 except Exception
as exc:
840 perr(
"There was an error committing data", exc)