3 from __future__
import print_function
5 from CalibDataClass
import *
17 usedb = CalibDbInfo.calibdb
55 datatypes = [
't0',
'rt',
'adc',
'id']
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")
108 if noask ==
False and quiet ==
False:
109 confirm = raw_input(
"Enter 'y' or 'yes' if you wish to continue with operation: ")
112 if confirm
not in (
"y",
"yes",
"Y",
"YES"):
117 def perr(error,exc=None,exit=False,):
120 if isinstance(exc,KeyboardInterrupt):
121 output +=
": User Interrupt"
122 elif isinstance(exc,Exception):
123 if not isinstance(exc,SystemExit):
124 output +=
": " + exc.__str__()
126 print (output, file=sys.stderr)
137 if os.path.isdir(path)
or os.path.isfile(path):
140 perr(
"File/path argument to upload option does not exist", exit=
True)
145 if re.match(
r'[GTPM]', type):
148 if type ==
'T0CalibrationMT' or type ==
'T0BS' or type ==
'T0MT':
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)
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)
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"
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']))
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)
200 print(
"This program requires an option: \n")
207 if opt
in [
"-y",
"--yes"]:
210 if opt
in [
"-h",
"--help"]:
214 if opt
in [
"--listdb"]:
215 print (CalibData.format_dblist())
218 if opt
in [
"--list",
"-l"]:
222 if arg
in CalibDbInfo.databases:
225 perr(
"An unknown database was specified, valid databases are:");
226 print (CalibData.format_dblist())
229 if opt
in [
'--sync']:
232 if opt
in [
'--synclimit']:
233 if re.match(
"^\d+$", arg, flags=0):
236 perr(
"--synclimit must be integer",exit=
True)
238 if opt
in [
"-L",
"--lowrun"]:
241 if opt
in [
"-U",
"--uprun"]:
244 if opt
in [
"-W",
"--lowtime"]:
247 if opt
in [
"-P",
"--uptime"]:
250 if opt
in [
"--luminosity"]:
253 if opt
in [
"--rootfile"]:
256 if opt
in [
"--statusflag"]:
259 if opt
in [
"-q",
"--quiet"]:
262 if opt
in [
"-D",
"--debug"]:
265 if opt
in [
"-i",
"--id"]:
268 if opt
in [
"-b",
"--tube"]:
272 if opt
in [
"-c",
"--chamber"]:
276 if opt
in [
"-m",
"--implementation"]:
279 if opt
in [
"--copy"]:
280 copydata = arg.split(
',')
283 perr(
"Invalid copy types: %s" % arg)
284 upload_args.append(
'copyarg')
286 if opt
in [
"--from"]:
289 if opt
in [
"-z",
"--setvalid"]:
290 valid = arg.split(
',')
292 perr(
"Invalid types for setting valid: %s" % arg)
294 if opt
in [
"-e",
"--delete"]:
295 delete = arg.split(
',')
297 perr(
"Invalid types for deletion: %s" % arg)
299 if opt
in [
"--upload",
"-u"]:
302 if opt
in [
"--modifyhead"]:
305 if opt
in [
"-F",
"--force"]:
308 if opt
in [
"-n",
"--newid"]:
312 upload_args = [
'createid']
314 if opt
in [
"-f",
"--newidfile"]:
315 implementation =
'fromfile'
319 upload_args = [
'createid']
321 if opt
in [
"-t",
"--type"]:
325 perr(
"Unknown algorithm type, not one of T0CalibrationMT, T0BS, T0MT or containing one of 'GTPM' for RT")
328 if opt
in [
"-p",
"--path"]:
330 upload_args.append(arg)
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)
341 syncsrc.debug = debug
342 syncsrc.setdb(copysrc)
347 srcdata = syncsrc.fetch_head_data()
348 dstdata = cd.fetch_head_data()
352 for dst_head
in dstdata:
353 dst_ids.append(dst_head[0])
356 for src_head
in srcdata:
357 if scount >= synclimit
and synclimit != 0:
359 if src_head[0]
not in dst_ids:
360 sync_ids.append(src_head[0])
363 for copy_id
in sync_ids:
364 print (
"\nSyncing head id %s" % 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)
374 if upload ==
True or copy ==
True or createid ==
True:
376 if newidfile !=
None and createid ==
True:
380 perr(
"Unable to open file of new head IDs: %s" % newidfile)
388 pout(
"\nUploading from : %s" % (
' '.
join(upload_args)))
389 for upload_arg
in upload_args:
392 elif upload_arg ==
'createid':
395 if os.path.isfile(upload_arg):
399 files = os.listdir(upload_arg)
400 dirprep = upload_arg +
"/"
405 for filename
in files:
406 if not fnmatch.fnmatch(filename,
'*.dat'):
408 constant_type = constant_arg
410 if filename !=
'copyloop' and filename !=
'idloop':
411 f =
open(dirprep + filename,
'r')
416 if len(rts) == 6
or len(rts) == 19
or len(rts) == 17:
419 if constant_arg !=
None:
420 perr(
"Header found in input file, ignoring --type")
424 if ct ==
"T0MT" or ct ==
"T0CalibrationMT":
426 constant_type =
"T0MT"
437 raise Exception(
"Unrecognized algorithm type '%s' in T0 or ADC header in file %s" % (rts[3], filename))
440 elif len(rts) == 3
or len(rts) == 12:
445 match_type = re.findall(
r'[GPTM]+',rts[2])
447 constant_type =
''.
join(match_type)
448 if constant_arg !=
None:
449 perr(
"Header found in input file, ignoring --type")
451 raise Exception(
"Unable to find algorithm type from RT header field '%s' in file %s" % (rts[2],filename))
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)
458 if implementation ==
None and head_id ==
None:
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)
470 if newidfile !=
None and createid ==
True:
471 idlines = line.split()
472 implementation = idlines[0]
475 lowtime = idlines[3] +
" " + idlines[4]
476 uptime = idlines[5] +
" " + idlines[6]
478 cd =
CalibData(head_id,implementation,lowrun,uprun,lowtime,uptime,luminosity,rootfile,status_flag)
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())
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)
499 if cd.head_id !=
None:
500 pout(
"Destination head id %s from database has information:" % cd.head_id)
501 pout(cd.format_headinfo())
503 if implementation !=
None and copy ==
True:
504 pout(
"Setting/modifying destination implementation to '%s'" % implementation)
505 cdsource.implementation = implementation
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.")
510 if cd.head_id ==
None:
513 cd.copy_head(cdsource)
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")
526 pout(
"\nFilename: %s" % filename, newline=
False)
532 chamber_string = CalibData.extract_tubestring(filename)
535 chamber = CalibData.get_tube_string(chamber_string)
536 chamber_id = CalibData.get_tube_id(chamber_string)
538 chamber_id = CalibData.get_tube_id(chamber)
539 chamber = CalibData.get_tube_string(chamber)
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)
545 pout(
"Chamber is: %s" % chamber, 0)
546 pout(
"Chamber id is: %s" % chamber_id, 0)
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)
555 cd.type = constant_type
560 cd.delete_rt(chamber_id)
561 cd.insert_rt(chamber_id)
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")
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")
571 perr(
"Error with RT insert operation")
580 if len(rts) != fieldcount:
581 perr(
"Invalid line in %s file %s, too many or too few fields" % (upload, filename))
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)
590 cd.t0_tube_grouping =
"CHAMBER"
594 cd.delete_tube(tube_id,chamber_id)
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")
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))
607 perr(
"An error has occurred at line %s in file %s." % (point_nr + 1,filename))
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))
620 pout(
"\nFound %d files in dir %s" % (count_files,upload_arg))
621 pout(
"\nInserting to head_id %s" % cd.head_id)
623 if 't0' in copydata
or 'adc' in copydata:
626 cd.delete_tube(tube,chamber)
627 cd.copy_tzero(cdsource,chamber,tube)
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))
635 except DataUniqueError:
636 perr(
"Data for tube(s) or chamber(s) already exists. Use --force to overwrite.")
638 except HeadInsertError:
639 perr(
"Error modifying head id %s" % cd.head_id)
642 perr(
"Error copying T0/ADC")
648 cd.delete_rt(chamber)
650 cd.copy_rt(cdsource,chamber)
651 if implementation !=
None and head_id !=
None:
652 cd.implementation = implementation
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))
658 except DataUniqueError:
659 perr(
"Data for chamber(s) already exists. Use --force to overwrite.")
661 except HeadInsertError:
662 perr(
"Error modifying head id %s" % cd.head_id)
665 perr(
"Error copying RT")
668 if cd.head_id ==
None:
669 perr(
"Must provide --id with --modifyhead")
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 }
675 for field,val
in fields.items():
677 setattr(cd, field, val)
679 if modified ==
False:
680 perr(
"No modification specified")
683 except HeadInsertError
as exc:
684 perr(
"Error modifying head id" + cd.head_id, exc)
693 print (cd.format_head_data(cd.fetch_head_data()))
695 except QueryError
as exc:
696 perr(
"Error querying for head ids", exc)
701 perr(
"You did not give head id (--id=)")
704 if not isinstance(cd,CalibData):
710 except QueryError
as exc:
711 perr(
"Could not retrieve information for head id: %s" % head_id, exc)
716 tube_id = cd.get_tube_id(tube)
717 tube = cd.get_tube_string(tube)
719 perr(
"Invalid tube string or numeric ID was input")
722 perr(
"Unable to convert tube string or ID")
729 chamber_id = cd.get_tube_id(chamber)
730 chamber = cd.get_tube_string(chamber)
732 perr(
"Invalid tube string or numeric ID was input")
735 perr(
"Invalid chamber string or ID was put in")
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))
747 cd.delete_rt(chamber_id)
749 perr(
"Error deleting rt for head id %s \n" % head_id)
755 pout(
"Deleting T0 for head id: %s, implementation name: %s " % (head_id,cd.implementation))
757 pout(
"Deleting t0 for chamber: %s, tube id: %s" % (chamber, chamber_id))
759 pout(
"Deleting t0 for tube: %s, tube id: %s" % (tube, tube_id))
763 cd.delete_tube(tube_id,chamber_id)
765 perr(
"Error deleting t0 for head id %s" % head_id)
771 if 't0' in valid
or 'adc' in valid:
773 cd.set_t0_valid(tube_id)
775 print(
"Error setting t0 valid flag for head id %s \n" % head_id)
779 pout(
"Committing update of t0 valid flag for head id: %s, implementation name: %s " % (head_id,cd.implementation))
781 pout(
"Tube: %s, tube id: %s" % (tube, tube_id))
785 cd.set_rt_valid(tube_id)
787 perr(
"Error setting RT valid flag for head id %s \n" % head_id)
790 pout(
"Committing update of rt valid flag for head id: %s, implementation name: %s " % (head_id,cd.implementation))
792 pout(
"Tube: %s, tube id: %s" % (tube, tube_id))
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())
807 perr(
"Error deleting head id: %s" % head_id)
813 except (Exception,KeyboardInterrupt)
as exc:
815 if isinstance(exc,SystemExit):
819 traceback.print_exc()
820 perr(
"Error performing operation", exc)
821 if isinstance(cd,CalibData):
831 pout(
"Committing data to database.")
838 cd.commit(force=
True)
840 except Exception
as exc:
841 perr(
"There was an error committing data", exc)