28 responsiblePerson = 
"youzhou@email.arizona.edu" 
   29 maillist = responsiblePerson
 
   31 CoolMergeByDefault = 
False 
   37   print (
'updating file list')
 
   39   outFile = 
open(oldListPath, 
'w')
 
   40   outFile.write(newList)
 
   46 def runCalib(calType, runNumber,workDir,castorCopyCmd):
 
   49   scriptDir = 
'${HOME}/CSC/run/' 
   50   if calType == 
'pulser':
 
   51     calibScript =  scriptDir + 
'CscCalcSlopeMon.py' 
   52     dbScript = scriptDir + 
'cscWritePSlopeCool.py' 
   53     webDir = 
'${HOME}/www/csc/pulser' 
   54     runListFile = 
"pulserRunList.pickle" 
   56   elif( calType == 
'ped'):
 
   57     calibScript = scriptDir + 
'CscCalcPedMon.py' 
   58     dbScript = scriptDir + 
'cscWritePedRefCool.py' 
   59     onlDbFile = scriptDir + 
'online.cal' 
   60     webDir = 
'${HOME}/www/csc/ped' 
   61     webPageUrl = 
'https://atlas-csc-calib.web.cern.ch/atlas-csc-calib/ped/pedRun_' +runNumber
 
   62     runListFile = 
"pedRunList.pickle" 
   65   outputDir = workDir +
"/CalibResults" 
   66   bsDir = workDir +
"/Bytestream" 
   68   print (
'outputDir = ' + outputDir)
 
   72   emailMessage = 
'Finished ' + calType + 
' calibration on run number ' + runNumber
 
   73   emailMessage += 
'. Output in ' + outputDir + 
'.' 
   74   emailMessage += 
'\\nAnd website at:\\n' 
   75   emailMessage += webPageUrl
 
   78   goodEmailSubject = 
'[CSC CALIB PROC]: SUCCESS with ' + calType + 
'calib run' + runNumber
 
   79   badEmailSubject = 
'[CSC CALIB PROC]: PROBLEMS with ' + calType + 
'calib run' + runNumber
 
   82   bashFilePath = workDir+
'/CscCalib_' + calType + 
'_' + runNumber + 
'.sh' 
   84   bsubCmd =
'cd ' + outputDir + 
';bsub -q 2nd -R "type==SLC5_64&&mem>420" ' + bashFilePath
 
   86   bashFileContents = 
"#!/bin/bash\n" 
   87   bashFileContents += 
"#To resubmit this job, submit it to the atlasmuonqueu like so:\n#" 
   88   bashFileContents += bsubCmd +
"\n" 
   89   bashFileContents += 
"source ~/CSC/CscSetup.sh\n" 
   90   bashFileContents += 
"\n" 
   91   bashFileContents += 
"resultDir=\"" + outputDir + 
"\"\n" 
   92   bashFileContents += 
'bytestreamDir="' + bsDir + 
'"\n' 
   93   bashFileContents += 
'maillist="' + maillist + 
'"\n' 
   94   bashFileContents += 
'webSiteDir="' + webDir + 
'"\n' 
   96   calFilePrefix= 
"${resultDir}/" + runNumber
 
   97   inputPattern = 
"${bytestreamDir}/*.data" 
   99   calibCommand = 
'echo "Running calibration"\n' \
 
  100       + 
'mkdir ${resultDir}\n' \
 
  101       + 
'athena.py -c "outputPre=\'' + calFilePrefix \
 
  102       + 
'\';inputOnlCalibFile=\'' +onlDbFile \
 
  103       + 
'\';inputPat=\'' + inputPattern \
 
  104       + 
'\';reportPrefix=\'' + emailMessage \
 
  109   goodEmailCommand = 
' mail -s "' + goodEmailSubject + 
'" $maillist < ' + calFilePrefix + 
"CalibReport.txt" 
  110   badEmailCommand = 
' mail -s "' + badEmailSubject + 
'" $maillist < ' + calFilePrefix + 
"CalibReport.txt" 
  114   infile = 
open(runListFile,
"rb")
 
  115   runList = pickle.load(infile)
 
  122   if(runNumber 
in runList):
 
  123     print (
"Mailing message")
 
  124     message =[
"mail",
"-s",\
 
  125         '"New castor run directory found for previously processed run ' + 
str(runNumber) + 
'"',\
 
  128         "runAlreadyProcessed.mail"]
 
  130     subprocess.call(message)
 
  134   highestRun = runList[-1]
 
  136   isRunNumberConflict = 
False 
  139   if(highestRun > runNumber):
 
  143     subprocess.call([
"mail",
"-s",\
 
  144         "[CSC CALIB PROC] Wrong run number ordering on run " + 
str(runNumber) \
 
  145         + 
"! Human intervension required!",\
 
  148         "runNumberConflict.mail"]\
 
  150     isRunNumberConflict = 
True 
  153     runList += [runNumber]
 
  154     outfile = 
open(runListFile,
"wb")
 
  155     pickle.dump(runList,outfile)
 
  160   subprocess.call([
'touch',
'/afs/cern.ch/user/m/muoncali/CSC/run/runningCalibration' + runNumber])
 
  163   DbCommand = 
'athena.py -c "input=\'' + calFilePrefix+
'.cal\';output=\'' \
 
  164       + calFilePrefix + 
'.db\';IOVRunStart=int(\'' + highestRun + 
'\')" ' + dbScript
 
  180   UploadCommand += 
'/afs/cern.ch/user/a/atlcond/utils/AtlCoolMerge.py ' \
 
  182   if(
not CoolMergeByDefault 
or isRunNumberConflict):
 
  183     UploadCommand += 
" --noexec " 
  185   UploadCommand += 
"--comment=\'Automated reference update from " + calType  \
 
  186     + 
' run ' + runNumber + 
' to IOV starting at ' + highestRun + 
"' " \
 
  187     + calFilePrefix + 
'.db'   \
 
  188     + 
' COMP200 ATLAS_COOLWRITE ATLAS_COOLOFL_CSC_W WCOOLOFL4CSC17 ' 
  190   WebSiteCommand = 
'\nfs sa ${resultDir} webserver:afs read\n' 
  191   WebSiteCommand += 
'cd $resultDir\n' 
  192   WebSiteCommand += 
'ln -s ${resultDir} ${webSiteDir}/pedRun_' + runNumber + 
'\n' 
  193   WebSiteCommand += 
'MakeCscPedSite.exe ' + runNumber + 
'.root ' + runNumber + 
'.cal_online\n' 
  198   bashFileContents += 
'\ncd ' + workDir + 
'\n' \
 
  199       + 
"#Copying files from castor#\n" \
 
  202       + 
"#Running calibration (and calib monitoring)\n"\
 
  203       + 
"#, resulting in .cal file and status report\n"\
 
  204       + calibCommand +
'\n' \
 
  206       +  
"#Athena job to transform *.cal file to *.db file.\n"\
 
  208       +  
"#Python utility to upload *.db file to database. When entering by\n"\
 
  209       +  
"#hand, I recomend removing '--batch' flag so you can check puposed\n"\
 
  210       +  
"#operations before submision to database\n"\
 
  211       +  UploadCommand + 
'\n' \
 
  212       + 
'#Check if AllCalibMonGood file was created, which means that\n'\
 
  213       + 
'#this run passed acceptable criteria in the calibration monitoring\n'\
 
  214       + 
'if [ -a AllCalibMonGood ]; then\n' \
 
  215       + t1 + 
"#Email list that the calibration looks good\n"\
 
  216       + t1 + goodEmailCommand +
'\n' \
 
  217       + t1 + 
"################################################################\n"\
 
  218       + t1 + 
"#Execute next two commands if you want to submit database entry#\n"\
 
  219       + t1 + 
"#Useful if these steps were skipped due to suspicious behaviour#\n"\
 
  220       + t1 + 
"#during calibration.                                           #\n"\
 
  221       + t1 + 
"###############################################################\n"\
 
  225       + t1 + 
"#Suspicious behaviour in calibration. Notify mail list of this fact\n"\
 
  226       + t1 + badEmailCommand + 
'\n' \
 
  229       + 
'#Always create website'\
 
  230       + WebSiteCommand + 
'\n' \
 
  231       + 
'rm -rf $bytestreamDir\n' \
 
  232       + 
'rm -rf ' + scriptDir +
"runningCalibration" + runNumber +
'\n' 
  235   print (
"Printing bash file to: " +bashFilePath)
 
  236   bashFile = 
open(bashFilePath, 
'w')
 
  237   bashFile.write(bashFileContents)
 
  241   os.system(
'chmod +x ' + bashFilePath)
 
  242   bsubsMessage = os.popen(bsubCmd).
read()
 
  245   emailMessage = 
'Starting ' + calType + 
' calibration on run number ' + runNumber
 
  246   emailSubject = 
'[CSC CALIB PROC]: ' +  emailMessage
 
  247   emailMessage += 
'\nbsubs output:\n' + bsubsMessage
 
  248   os.system(
'echo "' + emailMessage + 
'" | mail -s "' + emailSubject + 
'" ' + maillist)
 
  256 calType = sys.argv[1]
 
  257 if calType == 
'pulser':
 
  258   calibFileDir = 
'/castor/cern.ch/user/l/lampen/CalibRunTest/slope/' 
  259   oldListFilePath = 
'/afs/cern.ch/user/m/muoncali/CSC/run/pulserList.txt' 
  260   outputDir = 
'/afs/cern.ch/user/m/muoncali/w0/CSC/runs/pulser/pulser' 
  261 elif calType == 
'ped':
 
  262   calibFileDir = 
'/castor/cern.ch/grid/atlas/DAQ/muon/csc/' 
  263   oldListFilePath = 
'/afs/cern.ch/user/m/muoncali/CSC/run/pedDirList.txt' 
  264   outputDir = 
'/afs/cern.ch/user/m/muoncali/w0/CSC/runs/ped/ped' 
  265   calibRe = re.compile(
'data1.*_calib.*calibration_pedCSC\\.daq\\.RAW.*\\.data')
 
  267   print (
'Need to specify pulser or ped')
 
  273 testFile = glob.glob(
"/afs/cern.ch/user/m/muoncali/CSC/run/runningCalibration*")
 
  275   print (
'already running: ' + 
str(testFile))
 
  280 print (
'rfdir ' + calibFileDir)
 
  281 currentLs = os.popen(
'rfdir ' + calibFileDir).
read()
 
  283 os.popen(
'touch testing')
 
  286 inFile = 
open(oldListFilePath, 
'r')
 
  287 oldLs = inFile.read()
 
  291 print (
'checking for changes')
 
  294 now = datetime.datetime.now()
 
  298 if(oldLs != currentLs):
 
  299   print (
'There has been a change')
 
  300   currentDirList = currentLs.split(
'\n')
 
  301   oldDirList = oldLs.split(
'\n')
 
  306   for Dir 
in currentDirList:
 
  308     if Dir 
not in oldDirList:
 
  309       print (
"**********************************************************")
 
  310       splitDir = Dir.split()
 
  312       DirName =splitDir[-1]   
 
  315       timediff = today - day
 
  316       if(timediff > 7 
or timediff < -23):
 
  319         print (
"Found old dir " + DirName + 
", but its over at least a week old, so we're skipping it")
 
  325       print (
"day is " + 
str(day))
 
  328       cmd = 
'rfdir ' + calibFileDir + DirName
 
  331       nFiles = len(fileList) -1
 
  332       print (
"found " + 
str(nFiles) + 
" files")
 
  337       outputDirFull = outputDir + 
'Run_' + runNumber
 
  338       print (
'outputDirFull is ' + outputDirFull)
 
  345       castorCopyCmd = 
"mkdir ${bytestreamDir}" 
  346       for file 
in fileList:
 
  347         fileName = (file.split(
' '))[-1]  
 
  349           print (
"fileName: " +fileName)
 
  350           ThisCalibDir = re.match(calibRe,fileName)
 
  351           if(nFiles < numFilesToRun):
 
  352             print (
"only " +
str(nFiles) + 
" files. Breaking.")
 
  354               print (
"There is a calib dir, but it only has " + 
str(nFiles)
 
  355                      + 
" file. Will not process.")
 
  356               updateRunList = 
False 
  359             fullPath = calibFileDir + DirName + 
'/' + fileName 
 
  360             castorCopyCmd += 
"\nxrdcp root://castoratlas/" + fullPath + 
" ${bytestreamDir}" 
  365       print (
"found " + 
str(nFiles) + 
" files")
 
  368       if(nFiles >= numFilesToRun):
 
  371           updateRunList = 
False 
  372           print (
"Found new calibration directory to run on (" +DirName + 
"), but already running on " + runningDir)
 
  374         print (
'running on ' + DirName)
 
  376         if(nFiles > numFilesToRun):
 
  377           print (
'WARNING! Found ' + 
str(nFiles) + 
' calib files, when only ' + 
str(numFilesToRun) + 
' were expected!')
 
  380         if( os.path.exists(outputDirFull)):
 
  381           print (
"There is already a directory for run number " + runNumber)
 
  382           print (
"Will not run on this pedestal run")
 
  387           print (castorCopyCmd)
 
  390           os.makedirs(outputDirFull+
"/CalibResults")
 
  392           runCalib(calType, runNumber, outputDirFull, castorCopyCmd)
 
  394           print(
'Launched job, but will continue to check if we have more runs to run on later')
 
  396           updateRunList = 
False 
  403     print (
"No unprocessed or currently being processed calibration runs. Will update run list.")
 
  406     print (
"NOT updating run list")
 
  409   print (
'No changes between old and new runs')