runNovaSAM.py
Go to the documentation of this file.
1 #!/bin/env python
2 
3 from __future__ import print_function
4 from __future__ import division
5 from builtins import str
6 from builtins import range
7 from past.utils import old_div
8 import os, sys
9 import shutil
10 import samweb_client, ifdh
11 import pprint
12 import argparse
13 import subprocess
14 import re
15 import hashlib
16 import json
17 import resource
18 import string
19 import datetime
20 from samweb_client.utility import fileEnstoreChecksum
21 from samweb_client.exceptions import *
22 
23 import MetadataUtils
24 import NovaGridUtils as NGU
25 
26 ## Do a little bit of trickery with sys.argv to stop ROOT from gobbling it up and killing --help
27 argvCopy = sys.argv[:] # Make a copy
28 sys.argv = sys.argv[:1] # Replace it with just the first argument, i.e. script name
29 import ROOT
30 # The weird thing is that you have to do something with ROOT in order to make it parse args. Ok, we would have done this anyway.
31 ROOT.gErrorIgnoreLevel=3000 # Stop ROOT from complaining about not having dictionaries, 3000 is below kError but above kWarning.
32 sys.argv = argvCopy # Restore sys.argv. Thanks Wim, that's a real "solution"!
33 
34 #files
35 _skip_pattern = re.compile(r"^.*(RootOutput).*\.root", re.IGNORECASE)
36 
37 def make_temp_fcl(fclFile, inFileBase):
38  # make a temporary copy of the fcl file
39  fclPath = resolveFclPath(fclFile)
40  print("Found fcl file here: ", fclPath)
41  tmpFclName = os.path.basename(fclPath).replace(".fcl", "_" + os.path.splitext(inFileBase)[0] + ".fcl")
42  print("Creating local copy : ", tmpFclName)
43  shutil.copy(fclPath, tmpFclName)
44 
45  # determine if we're using the metadata module
46  # add parameters that describe this job
47  # NOTE:
48  # fhicl-expand (and other FCL tools) don't allow you
49  # to give the absolute path to a FCL. Instead FCLs have to
50  # live in $FHICL_FILE_PATH. $FHICL_FILE_PATH always begins
51  # with './:', i.e., search current dir first.
52  # so just make sure you don't cd() away from this dir
53  # between when the FCL is copied to this dir above and the check below.
54  isRunningMetadataModule=True
55  try:
56  subprocess.check_call("fhicl-expand %s | grep -q ^physics.analyzers.metadata.params." % tmpFclName, shell=True)
57  except subprocess.CalledProcessError:
58  isRunningMetadataModule=False
59 
60  if isRunningMetadataModule:
61  with open(tmpFclName, 'a') as fclFileObj:
62  if not fileMetaDataMgr.isSam4Users():
63  if args.npass != None:
64  MetadataUtils.addMetadataToFCL(fclFileObj, "NOVA.subversion", '"' + fileMetaDataMgr.subversion + '"')
65 
66  if fileMetaDataMgr.dataFlag == "sim" and fileMetaDataMgr.generator in MetadataUtils.neutrinoGenerators:
67  MetadataUtils.addMetadataToFCL(fclFileObj, "NOVA.flux_version", '"' + fileMetaDataMgr.fluxVersion + '"')
68 
69  MetadataUtils.addMetadataToFCL(fclFileObj, "NOVA.skim", '"' + fileMetaDataMgr.skim + '"')
70  MetadataUtils.addMetadataToFCL(fclFileObj, "NOVA.systematic", '"' + fileMetaDataMgr.systematic + '"')
71  MetadataUtils.addMetadataToFCL(fclFileObj, "NOVA.Special", '"' + fileMetaDataMgr.special + '"')
72 
73  return tmpFclName
74 
76  #memLimit = 3.9*1024**3
77  memLimit = 3.9*1000**3
78  print("Old virtual memory limit:", resource.getrlimit(resource.RLIMIT_AS))
79  print("Limiting the virtual memory of the nova job to 3.9 GB")
80  resource.setrlimit(resource.RLIMIT_AS, (memLimit, memLimit))
81  print("New virtual memory limit:", resource.getrlimit(resource.RLIMIT_AS))
82 
83 def makeDirSafely(dir):
84  if "/pnfs" != dir[0:5]:
85  makeDirIfNeeded(dir)
86  return
87 
88  print("runNovaSAM is making a directory with IFDH")
89  dh = ifdh.ifdh("http://samweb.fnal.gov:8480/sam/nova/api")
90  try:
91  print("Checking if directory ", dir, "exists")
92  dh.ls(dir, 1, "")
93  dh.chmod(774,dir,"")
94 
95  except (RuntimeError, IOError) as e:
96  try:
97  print("It doesn't - make directory", dir)
98  dh.mkdir(dir)
99  except:
100  print("Tried to make directory and couldn't. Perhaps it already exists?")
101 
102 
104  os.umask(0o02) # (rw-rw-r--) for files and (rwxrwxr-x) for directories.
105  if not os.path.isdir(dir):
106  print("runNovaSAM is making a directory: ", dir)
107  try:
108  os.mkdir(dir)
109  except:
110  print("Couldn't make the directory... some other job perhaps did, or permissions did not allow ")
111  if not os.path.isdir(dir):
112  raise Exception("Failed to make directory + " + dir )
113 
114 
115 def getOutDir(pathname, dest, hashDirs=False, runDirs=False, runNum=0):
116  dirs = [dest]
117  if hashDirs:
118  head, tail = os.path.split(pathname)
119  hash = hashlib.md5(tail.encode())
120  dirs += list(hash.hexdigest()[:3])
121  if runDirs:
122  head, tail = os.path.split(pathname)
123  runStr = str(runNum)
124  multiRunDir = runStr[:3].zfill(6)
125  makeDirSafely(os.path.join(dest, multiRunDir))
126  makeDirSafely(os.path.join(dest, multiRunDir, runStr))
127  dirs += [multiRunDir, runStr]
128  return os.path.join(*dirs)
129 
130 def checkAndMoveFiles(inFile, outputs, noCleanup=False, copyOnly=False):
131  makeDirIfNeeded('./copyback')
132  """Checks all root files in the current directories for zombie or recovered status. Bad files are deleted while good files are moved to the copyback subdirectory for copy out ease"""
133  inFileBase = os.path.basename(inFile)
134  baseDir = "."
135 
136  print('Looking for requested outputs: ')
137  for o in outputs: print(o)
138 
139  # If declaring files have to do non-decafs first, since they're the parents
140  # of the decafs. If not, it doesn't hurt to do it in that order anyway.
141  for secondPass in [False, True]:
142  for root, dirs, filenames in os.walk(baseDir):
143  if root == baseDir:
144  for file in filenames:
145  if file.endswith('decaf.root') != secondPass: continue
146  # If file not in outputs, then delete.
147  if (file.endswith (".root") or file.endswith(".h5")) and file != inFileBase:
148  fileWPath = os.path.join(root, file)
149  # If the file isn't in my outputs then delete it.
150  if file not in outputs:
151  if not noCleanup:
152  # Do not copy over, just delete
153  print("File", fileWPath, " is not among requested outputs, removing")
154  os.remove(fileWPath)
155  continue
156  # Now that I know that this file is in my output list, lets check it is valid...
157  # First, if it is a root file.
158  if file.endswith (".root"):
159  print("In checkAndMoveFiles, fileWPath is %s" %fileWPath)
160  rootFile = ROOT.TFile(fileWPath)
161  if rootFile.IsZombie() or rootFile.TestBit(ROOT.TFile.kRecovered):
162  #do not copy over, just delete
163  print("File", fileWPath, "is Zombie - remove it")
164  os.remove(fileWPath)
165  else:
166  newFilePath = os.path.join(root, "copyback", file)
167  print("New file name is %s" %newFilePath)
168  if copyOnly:
169  shutil.copyfile(fileWPath, newFilePath)
170  else:
171  shutil.move(fileWPath, newFilePath)
172  rootFile.Close()
173  # Next, if it is a h5 file.
174  elif file.endswith(".h5"):
175  # Only import h5py if have h5 files.
176  import h5py
177  print("In checkAndMoveFiles, fileWPath is %s" %fileWPath)
178  # If a valid HDF5 files.
179  if h5py.is_hdf5(fileWPath):
180  newFilePath = os.path.join(root, "copyback", file)
181  print("New file name is %s" %newFilePath)
182  if copyOnly:
183  shutil.copyfile(fileWPath, newFilePath)
184  else:
185  shutil.move(fileWPath, newFilePath)
186 
187  # If not a valid HDF5 file.
188  else:
189  print("File", fileWPath, "is Zombie - remove it")
190  os.remove(fileWPath)
191  return
192 
193 def ModifyParentMetadata(inParentFile, inFile):
194  print("Using parent metadata and modifying, using", inParentFile, "for", inFile)
195  samweb = samweb_client.SAMWebClient(experiment='nova')
196  md = MetadataUtils.createMetadata(inParentFile)
197  md['file_name'] = inFile
198  md['data_tier'] = args.histTier
199  md['file_format'] = "root"
200  parent_list=[]
201  for filename in os.listdir('.'):
202  print("found parent file",filename)
203  parent_dict = {'file_name': filename}
204  parent_list.append(parent_dict)
205 
206  print("parent list:")
207  print(parent_list)
208  parent_dumps = json.dumps(parent_list, separators = (', ', ': '))
209  print(parent_dumps)
210  md['parents'] = parent_list
211  print(md)
212  return md
213 
214 #def h5MetaHack(inFile):
215 # print "Doing a hack to get HDF5 metadata...Will take CAF metadata and change subtly."
216 # ### Make my client and get my CAF metadata
217 # samweb = samweb_client.SAMWebClient(experiment='nova')
218 # md = MetadataUtils.createMetadata( inFile.replace('.h5caf.h5', '.caf.root') )
219 # ### Change some parameters.
220 # md['file_name'] = inFile
221 # md['data_tier'] = unicode('h5')
222 # md['file_size'] = os.path.getsize( inFile )
223 # return md
224 
225 def declareFile(fileWPath):
226  """Checks file for a TKey of RootFileDB. If it exists, run sam_metadata_dumper and construct appropriate metadata for the file. Use that metadata to declare the file to SAM"""
227  samweb = samweb_client.SAMWebClient(experiment='nova')
228 
229  filename = os.path.basename(fileWPath)
230  print(filename)
231 
232  rootFileDB = False
233  if filename.endswith(".root"):
234  rootFile = ROOT.TFile(fileWPath)
235  rootFileDB = rootFile.FindKey("RootFileDB")
236  else:
237  rootFile = None
238 
239  olddir = os.getcwd()
240  os.chdir(os.path.dirname(fileWPath))
241  if rootFileDB or filename.endswith("caf.root") or filename.endswith(".h5"):
242  md = MetadataUtils.createMetadata(filename)
243  # Check that md exists, and then declare!
244  if md == None:
245  print("No metadata found!")
246  else:
247  # If I have a transpose file want to add plane (and cell) number.
248  if "cell" in filename:
249  try:
250  plane = re.search('^.*outplane(\d*).', filename).group(1)
251  cell = re.search('^.*cell(\d*).', filename).group(1)
252  print("Plane number:", plane, "Cell number:", cell, ". Is a transpose file")
253  md['Calibration.PlaneNumber'] = plane
254  md['Calibration.CellNumber'] = cell
255  except:
256  print("No cell number found - could be a plane mode transpose file")
257 
258  elif "outplane" in filename:
259  print(filename)
260  try:
261  plane = re.search('^.*outplane(\d*).', filename).group(1)
262  print("Plane number:", plane, ". Is a transpose file")
263  md['Calibration.PlaneNumber'] = plane
264  except:
265  print("No plane number found - not a transpose file")
266  ### Make sure that the txtfile is in the parent list.
267  if args.txtfiledef:
268  md['parents'].append({u'file_name':str(inFile)})
269 
270  # Print out the metadata before trying to declare
271  pprint.pprint(md)
272  print('')
273  print("Declaring", fileWPath, "to SAM")
274  try:
275  samweb.declareFile(md)
276  #samweb.validateFileMetadata(md=md)
277  except Exception as inst:
278  #print fileWPath, "already exists in SAM"
279  print(inst)
280  else:
281  print(fileWPath, "does not contain RootFileDB, do not try to declare")
282 
283  if rootFile:
284  rootFile.Close()
285  os.chdir(olddir)
286  return
287 
288 
289 def declareLogFile(logName, logFile, rootName):
290  # This is what NovaFTS/plugins/nova_log_metadata.py does
291  md = {
292  'file_name': os.path.basename(logName),
293  'file_size': os.path.getsize(logFile),
294  'data_tier': 'log',
295  'file_format': 'log',
296  'file_type': 'unknown', # maybe 'nonPhysicsGeneric'?
297  'parents': [{'file_name': os.path.basename(rootName)}]
298  }
299  print("16) declareLogFile(logName, logFile, rootName):")
300  print("Declaring", logName, "to SAM")
301  try:
302  samweb = samweb_client.SAMWebClient(experiment='nova')
303  samweb.declareFile(md)
304  except Exception as inst:
305  print(inst)
306 
307 
308 def fileExists(outPath, dh):
309  try:
310  # Check to see if you can ls the file.
311  # This works in ifdh 1_7_0 and newer
312  # If it exists, dh.ls() returns a tuple with one entry, converts to True
313  # If it doesn't, dh.ls() returns an empty tuple, converts to False
314  return bool(dh.ls(outPath, 1, ""))
315  except (RuntimeError, IOError) as e:
316  # Some versions of ifdh throw an exception when the file was not found
317  # But that means it is not there.
318  return False
319 
320 def listFiles(outPath, dh):
321  try:
322  return dh.ls(outPath, 1, "")
323  except:
324  return "Exception while trying to ls, OutPath =",outPath
325 
326 
328  """For every ROOT file, try to extract its metadata into a matching .json
329  file in the same directory"""
330  baseDir = "./copyback"
331  # If using --txtfiledef, want to pass multiple files at a time to sam_meta_dumper.
332  # This is because it simply takes too long to call it for each indiv file
333  # when there are 800+ outputs. 5 s each -> ~1 hour!
334  TransposeList = ""
335  # Declare the samweb client within this function
336  samweb = samweb_client.SAMWebClient(experiment='nova')
337  # Loop through directories to search for files to make json files for.
338  for root, dirs, filenames in os.walk(baseDir):
339  if root == baseDir:
340  # Push the h5 files to the front of the list so that the CAF files remain
341  # available to hack in the metadata.
342  for ifile in range(len(filenames)):
343  if("h5" in filenames[ifile]):
344  filenames = [filenames[ifile]] + filenames[:ifile] + filenames[ifile+1:]
345  for file in filenames:
346  if (file.endswith (".root") or file.endswith(".h5") ) and file != inFileBase:
347  skip_match = _skip_pattern.match(file)
348  if skip_match == None:
349  # Set some quick and useful variables.
350  olddir = os.getcwd()
351  fileWPath = os.path.join(root, file)
352  # If a transpose file want to make the json subtly differently.
353  if args.txtfiledef and "outplane" in file:
354  # This works for the cellmode of the transposer as well, due to the filename including outplane and cell.
355  print("Adding %s to TransposeList" %file)
356  TransposeList += "%s " %file
357  continue
358  # Which extractor am I using?
359  extractor = 'sam_metadata_dumper'
360  if file.endswith('caf.root'):
361  extractor = 'extractCAFMetadata'
362  elif file.endswith('.h5'):
363  extractor = 'extractHDF5Metadata'
364  try:
365  # if we're running an analyzer, then there's no outTier, no cafTier,
366  # and we just make the metadata from the parent file
367  meta=''
368  if args.useParentMetadata:
369  # ensure we're in the directory where the parent file lives
370  os.chdir(os.path.dirname(inFile))
371  md = ModifyParentMetadata(os.path.basename(inFile),file)
372  # and now switch back to copyback dir to make sure we can copy back json
373  os.chdir(olddir)
374  os.chdir(os.path.dirname(fileWPath))
375  md['file_size'] = os.path.getsize(file)
376  # meta is currently a list, convert to json format
377  meta = json.dumps(md, separators = (', ', ': '))
378  else:
379  # sam_metadata_dumper doesn't apply basename() to filename. https://cdcvs.fnal.gov/redmine/issues/8987
380  os.chdir(os.path.dirname(fileWPath))
381  meta = subprocess.check_output([extractor, os.path.basename(fileWPath)])
382  if file.endswith (".root"):
383  jsonf = open(file.replace('.root', '.json'), 'wb')
384  jsonf.write(meta)
385  jsonf.close()
386  print("Made metadata for %s" %file)
387  elif file.endswith(".h5"):
388  print("\nNow to make my json file for my h5...\n")
389  jsonf = open(file.replace('.h5caf.h5', '.h5caf.json'), 'wb')
390  jsonf.write(meta)
391  jsonf.close()
392  print("Made metadata for %s" %file)
393  else:
394  print("I'm not sure what file extension you have...")
395  except:
396  print("Error extracting metadata from file.")
397  finally:
398  os.chdir(olddir)
399  # Make the Transpose json files.
400  # Again same argument, outplane is already in the filenames for cell mode
401  if args.txtfiledef and "outplane" in file:
402  olddir = os.getcwd()
403  os.chdir(baseDir)
404  MakeTransposeJson( TransposeList )
405  os.chdir(olddir)
406 
407 def MakeTransposeJson( TransposeList ):
408  """Transpose files need some extra tweaking when making .json files, largely because there are so many of them.
409  This takes in a list of files, and makes appropriate .json files in the same directory"""
410  # If using --txtfiledef, I can now pass my file list to sam_meta_dumper.
411  print("Is MakeTransposeJson called without a txt def, if you see this then yes.")
412  MetaListFile="AllMetaJson.txt"
413  meta_cmd="sam_metadata_dumper -s " + TransposeList + " > " + MetaListFile
414  os.system(meta_cmd)
415  # Now want to open the file and split by "}," character.
416  MetaFile = open( MetaListFile )
417  MetaLines = MetaFile.read().split(" },")
418  # Loop through lines, and appropriately separate out json files.
419  for i in range(0,len( MetaLines ) ):
420  meta=MetaLines[i]
421  # Figure out file name...this is assuming that file name is always the first entry...
422  StName=re.search('"(.+?).root"', meta ).group(1)
423  filename=StName+".json" # Effecitvely replacing .root with .json
424  # If transpose file add PlaneNumber and CellNumber if run in cell mode
425  if "cell" in filename:
426  try:
427  plane = re.search('^.*outplane(\d*).', filename).group(1)
428  cell = re.search('^.*cell(\d*).', filename).group(1)
429  print("Plane number:", plane, "Cell number:", cell, ". Is a transpose file")
430  meta = meta.replace('"calibration.base_release"', '"calibration.PlaneNumber": "%s",\n "calibration.CellNumber": "%s",\n "calibration.base_release"')%(plane, cell)
431  except:
432  print("No cell number found - could be a plane mode transpose file")
433 
434  elif "outplane" in filename:
435  try:
436  plane = re.search('^.*outplane(\d*).', filename).group(1)
437  print("Plane number:", plane, ". Is a transpose file")
438  meta = meta.replace('"calibration.base_release"', '"calibration.PlaneNumber": "%s",\n "calibration.base_release"') %plane
439  except:
440  print("Error extracting plane number from transpose file.")
441 
442  ### Make sure that the txtfile is in the parent list.
443  meta['parents'].append({u'file_name':str(inFile)})
444 
445  # Now open the json file
446  fout=open(filename,'w')
447  # Want to make sure that the json starts with '{'
448  if meta[0] not in "{":
449  meta = meta[:0] + '{\n' + meta[1:]
450  # Want to make sure that the json ends with a double '}'
451  if i < len(MetaLines)-1:
452  meta += "}\n}\n"
453  # Write and close the json file
454  fout.write(meta)
455  fout.close()
456 
457 def copyOutFiles(dest, hashDirs=False, runDirs=False, runNum=0, noCleanup=False, declareLocation=False, declareLogs=False):
458  """Builtin facility to copy out art files. This adds in a subdirectories with a single hex digit each corresponding to the first three digits in the hash of the output file name. This splits up files into 4096 separate subdirectories, preventing overfull directories. Copy out does not happen if the file already exists in the output"""
459  dh = ifdh.ifdh("http://samweb.fnal.gov:8480/sam/nova/api")
460  baseDir = "./copyback"
461  declareFiles = declareLogs
462  for root, dirs, filenames in os.walk(baseDir):
463  if root == baseDir:
464 
465  # copy out root files before h5 files
466  ordered_files = [s for s in filenames if ".root" in s]
467  for s in filenames:
468  if ".h5" in s:
469  ordered_files.append(s)
470 
471  for file in ordered_files:
472  if (file.endswith (".root") or file.endswith(".h5") ) and file != inFileBase:
473  fileWPath = os.path.join(root, file)
474  outDir = getOutDir(file, dest, hashDirs, runDirs, runNum)
475 
476  skip_match = _skip_pattern.match(file)
477  if skip_match == None:
478  outPath = os.path.join(outDir, file)
479 
480  if fileExists(outPath, dh):
481  print('copyOutFiles: ', outPath, 'already moved. Skipping')
482  else:
483  # note: this will fail if the file already exists
484  returnValue = dh.cp(["-D", fileWPath, outDir])
485  if returnValue != 0:
486  print("Copy out failed for file:", fileWPath, file=sys.stderr)
487  print("Skipping it.", file=sys.stderr)
488  else:
489  if declareFiles:
490  declareFile(fileWPath)
491  ###################
492  # Declare the file's location to SAM if we have the declareLocation option on
493  if declareLocation==True :
494  loc = string.replace(outDir, 's3://','s3:/')
495  print("Declaring location %s for file %s\n" % (loc,file))
496  sam = samweb_client.SAMWebClient('nova')
497  ret=sam.addFileLocation(file, loc)
498  if ret.status_code != 200 :
499  print(" SAMWEB Unable to declare file location (%s, %s) status code %s" %(file, loc, ret.status_code))
500  if fileWPath.endswith (".root"):
501  jsonPath = fileWPath.replace('.root', '.json')
502  elif fileWPath.endswith (".h5"):
503  jsonPath = fileWPath[:-3] + '.json'
504  if os.path.isfile(jsonPath):
505  if fileExists(os.path.join(outDir, os.path.basename(jsonPath)), dh):
506  print('copyOutFiles: ', os.path.join(outDir, os.path.basename(jsonPath)), 'already moved. Skipping')
507  else:
508  returnValue = dh.cp(['-D', jsonPath, outDir])
509  if returnValue != 0:
510  print("Copy out failed for file: " + jsonPath, file=sys.stderr)
511  print("Skipping it.", file=sys.stderr)
512  else:
513  print('JSON not found %s' % jsonPath)
514 
515  for ext in ['.bz2', '']:
516  if os.path.isfile('log.txt'+ext):
517  if file.endswith (".root"):
518  logName = file.replace('.root', '.log'+ext)
519  elif file.endswith (".h5"):
520  logName = file + '.log'+ext
521  if fileExists(os.path.join(outDir,logName), dh):
522  print('copyOutFiles: ', os.path.join(outDir, logName), 'already moved. Skipping')
523  else:
524  returnValue = dh.cp(['log.txt'+ext, os.path.join(outDir, logName)])
525 
526  if returnValue != 0:
527  print("Copy out failed for file: " + logName, file=sys.stderr)
528  print("Skipping it.", file=sys.stderr)
529 
530  if declareLogs:
531  declareLogFile(logName, 'log.txt'+ext, file)
532 
533  # Remove the copied-out log so it's not in
534  # the way for new log creation.
535  os.remove('log.txt'+ext)
536 
537  break
538 
539  else:
540  print("It does exist, not copying.")
541  if not noCleanup:
542  print("Removing", fileWPath)
543  os.remove(fileWPath)
544 
545  if fileWPath.endswith(".root"):
546  jsonPath = fileWPath.replace('.root', '.json')
547  elif fileWPath.endswith(".h5"):
548  jsonPath = fileWPath + ".json"
549  if os.path.isfile(jsonPath):
550  print('Removing', jsonPath)
551  os.remove(jsonPath)
552  return
553 
554 def makeDeCAF(script, fname, special):
555  trimname = fname[:-5] # cut off .root from end
556  trimidx = trimname.rindex('.')+1 # find last period before .root
557  decaf_tier = trimname[trimidx:-3]+'de'+trimname[-3:] # properly insert 'de'
558  oname = '{0}_{1}.{2}.root'.format(trimname, special, decaf_tier)
559  novaSource = os.getenv("SRT_PUBLIC_CONTEXT", "undefined")
560  if(novaSource == "undefined"):
561  novaSource = os.getenv("NOVASOFT_DIR", "undefined")
562  if(novaSource == "undefined"):
563  NGU.fail("Unable to locate NOvA source code")
564  else:
565  novaSource = os.getenv("NOVASOFT_DIR") + "/source"
566 
567  os.system('cafe -bq '+novaSource+'/CAFAna/'+script+' '+fname+' '+oname+' 2>&1')
568  return oname
569 
570 def resolveFclPath(fcl):
571  # Check if we have an absolute path name, return it if so
572  if fcl[0] == "/":
573  return fcl
574 
575  # Otherwise, we need to do some searching
576  fclPaths = os.environ["FHICL_FILE_PATH"].split(":")
577  for path in fclPaths:
578  # ensure there is always a trailing "/" on the path
579  path += "/"
580  if os.path.isfile(path + fcl):
581  return path + fcl
582 
583  # If we haven't found it, we have a problem.
584  raise IOError(sys.argv[0] + ": config file "+ fcl+" not found in FHICL_FILE_PATH")
585 
586 
587 if __name__=='__main__':
588 
589  parser = argparse.ArgumentParser(description='Run the nova command using SAM metadata')
590  parser.add_argument('inFile', help='The input file to run over', type=str)
591  parser.add_argument('--config', '-c', help='FHiCL file to use as configuration for nova executable', type=str)
592  parser.add_argument('--outTier', help="""
593  Data tier of the output file, multiple allowed, formatted as
594  <name_in_fcl_outputs>:<data_tier>.' Optionally, if a second colon is
595  included, the third argument will be treated as an additional naming string,
596  allowing multiple outputs with the same data_tier but unique file names.
597  Example: out1:reco:shifted leads to <file_id>_shifted.reco.root
598  """, type=str, action='append')
599  parser.add_argument('--cafTier', help="""Module label for CAF output,
600  multiple allowed. Format as <cafmaker_module_label>:<data_tier>.
601  Optionally, if a second colon is
602  included, the third argument will be treated as an additional naming string,
603  allowing multiple outputs with the same data_tier but unique file names.
604  Example: cafmaker:caf:shifted leads to <file_id>_shifted.caf.root
605  """, type=str, action='append')
606  parser.add_argument('--flatTier', help="""Module label for FlatCAF output,
607  multiple allowed. Format as <flatmaker_module_label>:<data_tier>.
608  Optionally, if a second colon is
609  included, the third argument will be treated as an additional naming string,
610  allowing multiple outputs with the same data_tier but unique file names.
611  Example: flatmaker:flatcaf:shifted leads to <file_id>_shifted.flatcaf.root
612  """, type=str, action='append')
613  parser.add_argument('--histTier', help='File identifier string for TFileService output, only one allowed. Supply as --histTier <id> for output_name.<id>.root, where output_name is assembled based on the input file.', type=str)
614  parser.add_argument('--h5Tier', help="""Module label for H5 output,
615  multiple allowed. Format as <h5maker_module_label>:<data_tier>.
616  Optionally, if a second colon is
617  included, the third argument will be treated as an additional naming string,
618  allowing multiple outputs with the same data_tier but unique file names.
619  Example: h5maker:h5:shifted leads to <file_id>_shifted.h5
620  """, type=str, action='append')
621  parser.add_argument('--outputNumuDeCAF', help='Make standard numu decafs for all CAF files produced', action='store_true')
622  parser.add_argument('--outputNueDeCAF', help='Make standard nue decafs for all CAF files produced', action='store_true')
623  parser.add_argument('--outputNumuOrNueDeCAF', help='Make standard numu or nue decafs for all CAF files produced', action='store_true')
624  parser.add_argument('--outputNusDeCAF', help='Make standard nus decafs for all CAF files produced', action='store_true')
625  parser.add_argument('--outputValidationDeCAF', help='Make validation (nue_or_numu_or_nus) decafs for all CAF files produced during the job', action='store_true')
626  parser.add_argument('--cosmicsPolarity', help='.', type=str)
627  parser.add_argument('--npass', help='.', type=str)
628  parser.add_argument('--skim', help='Specify skimming name.', type=str)
629  parser.add_argument('--systematic', help='Flag as systematic variation (append to file name and metadata parameters).', type=str)
630  parser.add_argument('--specialName', help='Additional name to add before data tier in output.', type=str)
631  parser.add_argument('--genietune', help='Specify the GENIE tune (append to file name and metadata parameters).', type=str)
632  parser.add_argument('--NPPFX', help='Number of PPFX universes.', type=str)
633  parser.add_argument('-n', help='Number of events to run over', type=int)
634  parser.add_argument('--copyOut', help='Use the built in copy out mechanism', action='store_true')
635  parser.add_argument('--dest', '-d', help='Output file destination for --copyOut functionality.', type=str)
636  parser.add_argument('--hashDirs', help='Use hash directory structure in destination directory.', action='store_true')
637  parser.add_argument('--runDirs', help='Use run directory structure in destination directory, 000XYZ/XYZUW for run number XYZUW.', action='store_true')
638  parser.add_argument('--autoDropbox', help='Use automatic dropox location', default=False, action='store_true')
639  parser.add_argument('--jsonMetadata', help='Create JSON files with metadata corresponding to each output file, and copy them to the same destinations', action='store_true')
640  parser.add_argument('--declareFiles', help='Declare files with metadata on worker node', action='store_true')
641  parser.add_argument('--declareLocations', help='Declare the file output locations to SAM during the copy back of the files', action='store_true')
642  parser.add_argument('--logs', help='Return .log files corresponding to every output', action='store_true')
643  parser.add_argument('--zipLogs', help='Format logs as .bz2 files. Implies --logs', action='store_true')
644  parser.add_argument('--noCleanup', help='Skip working directory cleanup step, good for interactive debugging or custom copy-out.', action='store_true')
645  parser.add_argument('--gdb', help='Run nova executable under gdb, print full stack trace, then quit gdb.', action='store_true')
646  parser.add_argument('--lemBalance', help='Choose lem server based on (CLUSTER+PROCESS)%%2 to balance load', action='store_true')
647  parser.add_argument('--lemServer', help='Specify lem server', type=str)
648  parser.add_argument('--txtfiledef', help='Use if the input definition is made up of text files, each containing a list of file names',default=False, action='store_true')
649  parser.add_argument('--precopyscript', help='Execute script PRECOPYSCRIPT within runNovaSAM.py, after running the nova -c command.', type=str, action='append')
650  parser.add_argument('--useParentMetadata', help="Use metadata of parent file to generate metadata for child file (for running analyzer modules)", action='store_true', default=False)
651  parser.add_argument('--second_config', help="""Second configuration fcl executed after main process.
652  nova is executed with art file that is output from the main process.
653  Files that get produced by this process that are named identically
654  to files produced by the main process and are among the requested outputs
655  are ignored and the file produced by the first process is returned""", type=str)
656 
657  args = parser.parse_args()
658 
659  # Sanity check for output
660  if args.copyOut:
661  if not (args.outTier or args.cafTier or args.flatTier or args.histTier or args.h5Tier):
662  raise Exception("Copy-out requested with --copyOut, but no outputs specified. Nothing will happen with output, aborting.")
663  if not (args.dest or "DEST" in os.environ):
664  raise Exception("Copy-out requested with --copyOut, but no output directory specified. Use --dest or $DEST.")
665 
666  # No longer set VMem limit -- causes problems on some OSG sites
667  #setVMemLimit()
668 
669  samweb = samweb_client.SAMWebClient(experiment='nova')
670 
671  if "SRT_BASE_RELEASE" in os.environ:
672  release = os.environ["SRT_BASE_RELEASE"]
673  elif "NOVASOFT_VERSION" in os.environ:
674  release = os.environ["NOVASOFT_VERSION"]
675  else:
676  print("No release set!")
677  exit(1)
678 
679 
680  inFile = args.inFile
681  inFileBase = os.path.basename(inFile)
682 
683  # Which file do I want to use to get the metadata?
684  if not args.txtfiledef:
685  # Normally my infile.
686  metadata = samweb.getMetadata(inFileBase)
687  fileMetaDataMgr = MetadataUtils.metaDataMgr(inFile, metadata, release, args.systematic, args.skim, args.cosmicsPolarity, args.npass, args.specialName)
688  else:
689  # However, if using a txtfile def, want to use the first file in the txt file.
690  with open( inFile ) as f:
691  PassFile = f.readline().strip()
692  print("Looking at ", PassFile)
693  #metadata_cmd = "ifdh_fetch %s" %PassFile
694  #os.system(metadata_cmd)
695  metadata = samweb.getMetadata(PassFile)
696  fileMetaDataMgr = MetadataUtils.metaDataMgr(PassFile, metadata, release, args.systematic, args.skim, args.cosmicsPolarity, args.npass, args.specialName)
697 
698 
699 
700  tmpFclName = make_temp_fcl(args.config, inFileBase)
701 
702  # Open the fcl file so that we can append output filenames to it
703  fclFileObj = open(tmpFclName, 'a')
704 
705  print(" Open the fcl file so that we can append output filenames to it ::::::::::::::::::::::::::: fclFileObj=", fclFileObj)
706  doMeta = True
707  if not (args.outTier or args.cafTier or args.flatTier or args.h5Tier):
708  doMeta = False
709 
710  # Start setting up the nova command, add SAM parameters
711  cmdList = []
712  cmdList.append('nova')
713  cmdList.append('-c')
714  cmdList.append(tmpFclName)
715  if doMeta:
716  cmdList.append('--sam-application-family=nova')
717  cmdList.append('--sam-application-version=' + release)
718  if not fileMetaDataMgr.isSam4Users():
719  cmdList.append('--sam-file-type=' + fileMetaDataMgr.fileType)
720 
721  if not args.outTier:
722  args.outTier = []
723  if not args.cafTier:
724  args.cafTier = []
725  if not args.flatTier:
726  args.flatTier = []
727  if not args.h5Tier:
728  args.h5Tier = []
729 
730  if not args.precopyscript:
731  args.precopyscript = []
732 
733  outList = [] # list of files to be supplied with -o
734  outputs = [] # list of files that will be moved to copyback directory, includes CAFs
735  # Loop over output tiers
736  for outTier in args.outTier:
737 
738  try:
739  output = outTier.split(":")[0]
740 
741  tier = outTier.split(":")[1]
742 
743  except:
744  raise ValueError("Output data tier: " + outTier + "not formatted corectly, should be <output_name>:<data_tier>")
745 
746  if "," in output:
747  if(re.search('cell',output)):
748  outP, outC = re.findall(',(.+?),', output)
749  outXp, outXc = [re.findall('(.+)-', outP)[0], re.findall('(.+)-', outC)[0]] # p stands for plane, c stands for cell
750  outYp, outYc = [re.findall('-(.+)', outP)[0], re.findall('-(.+)', outC)[0]]
751  for i in range( int(outXp), int(outYp)+1 ):
752  for j in range( int(outXc), int(outYc)+1):
753  NewOMod = re.search('^(.+?),', output).group(1) + repr(i) + re.search('cell',output).group() + repr(j)
754  cmdList.append('--sam-data-tier=' + ":".join([NewOMod, tier]))
755  if not fileMetaDataMgr.isSam4Users():
756  if fileMetaDataMgr.dataFlag == "data":
757  cmdList.append('--sam-stream-name=' + NewOMod + ':' + str(fileMetaDataMgr.stream))
758  else:
759  outX = re.search(',(.+?)-', output).group(1)
760  outY = re.search('-(.+?),', output).group(1)
761  for i in range( int(outX), int(outY)+1 ):
762  NewOMod = re.search('^(.+?),', output).group(1)+repr(i)
763  cmdList.append('--sam-data-tier=' + ":".join([NewOMod, tier]))
764  if not fileMetaDataMgr.isSam4Users():
765  if fileMetaDataMgr.dataFlag == "data":
766  cmdList.append('--sam-stream-name=' + NewOMod + ':' + str(fileMetaDataMgr.stream))
767  else:
768  cmdList.append('--sam-data-tier=' + ":".join([output, tier]))
769  if not fileMetaDataMgr.isSam4Users():
770  if fileMetaDataMgr.dataFlag == "data":
771  cmdList.append('--sam-stream-name=' +output + ':' + str(fileMetaDataMgr.stream))
772 
773  outNameTemp = fileMetaDataMgr.getOutputFileName(tier)
774  if args.txtfiledef:
775  FirstRun = re.search('FirstRun-(.+?)_LastRun', os.path.basename(inFile)).group(1).zfill(8)
776  LastRun = re.search('LastRun-(.+?)_TotFiles', os.path.basename(inFile)).group(1).zfill(8)
777  Index=outNameTemp.find("_r0")
778  outNameTemp=outNameTemp[:Index]+"_r"+FirstRun+"_r"+LastRun+outNameTemp[Index+14:]
779  outName = os.path.basename(outNameTemp)
780 
781  if "," in output:
782  if(re.search('cell',output)):
783  outP, outC = re.findall(',(.+?),', output)
784  outXp, outXc = [re.findall('(.+)-', outP)[0], re.findall('(.+)-', outC)[0]] # p stands for plane, c stands for cell
785  outYp, outYc = [re.findall('-(.+)', outP)[0], re.findall('-(.+)', outC)[0]]
786  for i in range( int(outXp), int(outYp)+1 ):
787  for j in range( int(outXc), int(outYc)+1):
788  NewOMod = re.search('^(.+?),', output).group(1)+repr(i) + re.search('cell',output).group() + repr(j)
789  tier = outTier.split(":")[1]
790  NewOName = outName.replace(str("."+tier), str("-"+NewOMod+"."+tier))
791  fclFileObj.write("\noutputs." + NewOMod + '.fileName: "'+ NewOName + '"\n')
792  outList.append(NewOName)
793  outputs.append(NewOName)
794  else:
795  print("Running in Plane Mode")
796  outX = re.search(',(.+?)-', output).group(1)
797  outY = re.search('-(.+?),', output).group(1)
798  for i in range( int(outX), int(outY)+1 ):
799  NewOMod = re.search('^(.+?),', output).group(1)+repr(i)
800  tier = outTier.split(":")[1]
801  NewOName = outName.replace(str("."+tier), str("-"+NewOMod+"."+tier))
802  fclFileObj.write("\noutputs." + NewOMod + '.fileName: "'+ NewOName + '"\n')
803  outList.append(NewOName)
804  outputs.append(NewOName)
805  else:
806  print("Output file name: ", outName, " for tier ", tier, " and output ", output)
807  fclFileObj.write("\noutputs." + output + '.fileName: "'+ outName + '"\n')
808  outList.append(outName)
809  outputs.append(outName)
810 
811  for cafTier in args.cafTier:
812  try:
813  cafLabel = cafTier.split(":")[0]
814  tier = cafTier.split(":")[1]
815  except:
816  raise ValueError("Output data tier: " + cafTier + "not formatted corectly, should be <output_name>:<data_tier>")
817 
818  cafName = fileMetaDataMgr.getOutputFileName(tier)
819  print("Adding CAF: ", cafLabel, tier, cafName)
820 
821  fclFileObj.write("\nphysics.producers." + cafLabel + '.CAFFilename: "' + cafName + '" \n')
822  fclFileObj.write("physics.producers." + cafLabel + '.DataTier: "' + tier + '" \n')
823  outputs.append(cafName)
824 
825 
826  for flatTier in args.flatTier:
827  try:
828  flatLabel = flatTier.split(":")[0]
829  tier = flatTier.split(":")[1]
830  except:
831  raise ValueError("Output data tier: " + flatTier + "not formatted corectly, should be <output_name>:<data_tier>")
832 
833  flatName = fileMetaDataMgr.getOutputFileName(tier)
834  print("Adding FlatCAF: ", flatLabel, tier, flatName)
835 
836  #fclFileObj.write("\nphysics.producers." + flatLabel + '.OutputName: "' + flatName + '" \n')
837  #fclFileObj.write("physics.producers." + flatLabel + '.DataTier: "' + tier + '" \n')
838  outputs.append(flatName)
839 
840 
841  for h5Tier in args.h5Tier:
842  try:
843  h5Label = h5Tier.split(":")[0]
844  tier = h5Tier.split(":")[1]
845  except:
846  raise ValueError("Output data tier: " + h5Tier + "not formatted corectly, should be <output_name>:<data_tier>")
847 
848  h5Name = fileMetaDataMgr.getOutputFileName(tier)
849  print("Adding H5: ", h5Label, tier, h5Name)
850 
851  outputs.append(h5Name+".h5")
852 
853  if args.lemBalance and (int(os.environ["PROCESS"])+int(os.environ["CLUSTER"]))%2==0:
854  fclFileObj.write("physics.producers.lem.WebSettings.Host: \"lem2.hep.caltech.edu\"\n")
855  elif args.lemServer:
856  fclFileObj.write("physics.producers.lem.WebSettings.Host: \"%s\"\n" % args.lemServer)
857 
858 
859  if args.histTier:
860  try:
861  tier = str(args.histTier)
862  except:
863  raise Exception("Histogram identifier supplied by --histTier could not be converted to a string.")
864 
865  histName = fileMetaDataMgr.getOutputFileName(tier)
866 
867  outputs.append(histName)
868  fclFileObj.write("\nservices.TFileService.fileName: " + '"' + histName + '"\n')
869 
870  fclFileObj.close()
871 
872 
873 
874  print("Config: ")
875  for line in open(tmpFclName):
876  print(line.strip())
877 
878  if args.n != None:
879  cmdList.append('-n')
880  cmdList.append(str(args.n))
881 
882  if args.txtfiledef:
883  print("\nI have a text file definition, InFile is {}".format(inFile))
884  ### Are we streaming the files via xrootd?
885  #txtcmd="cat %s | xargs -n1 samweb2xrootd > xrootd_inFile.txt"%inFile
886  #os.system(txtcmd)
887  #with open("xrootd_inFile.txt") as f:
888  # for line in f:
889  # print line.strip()
890  # cmdList.append( line.strip() )
891  #print ""
892  ### Are we going to copy the files?
893  olddir = os.getcwd()
894  os.system("mkdir InFiles")
895  allFiles = 0.
896  failFiles = 0.
897  with open(inFile) as f:
898  os.chdir("InFiles")
899  for line in f:
900  allFiles += 1
901  copyfile = "InFiles/%s" %line.strip()
902  print("Now copying",line.strip(),"to ",copyfile)
903  ifdhcmd = "ifdh cp -D `samweb2xrootd %s` ." %line.strip()
904  print(datetime.datetime.now())
905  ret = os.system( ifdhcmd )
906  if ret == 0:
907  cmdList.append( copyfile )
908  else:
909  failFiles += 1
910  print("Copy in success ratio: " + str(old_div((allFiles-failFiles),allFiles)))
911  os.chdir(olddir)
912  else:
913  cmdList.append(inFile)
914 
915  if args.gdb:
916  gdbArgs = ["gdb", "-return-child-result", "--ex", "run", "--ex", "bt", "full", "--ex", "q", "--args"]
917  cmdList = gdbArgs + cmdList
918 
919  cmd = ' '.join(cmdList)
920 
921  print('Running:', cmd)
922  sys.stdout.flush() # flush the stdout buffer before running the nova executable, cleans up output.
923 
924  if args.logs or args.zipLogs:
925  with open('log.txt', 'w') as logfile:
926  sys.stderr.write('\nnova command runs here. stderr redirected to stdout\n\n')
927  retCode = subprocess.call(cmdList, stdout=logfile, stderr=subprocess.STDOUT)
928  # Print all the output to the screen as well so that regular condor
929  # logs include it too.
930  with open('log.txt', 'r') as logfile:
931  for line in logfile:
932  print(line, end=' ')
933  if args.zipLogs:
934  os.system('bzip2 -f log.txt')
935  else:
936  retCode = subprocess.call(cmdList)
937 
938  ### If using a txtfiledef make sure to clean up the InputFile List....
939  if args.txtfiledef:
940  os.system("rm -rf InFiles")
941 
942  if retCode != 0:
943  print("Want to copy back the logs for this job somehwere....")
944  else:
945 
946  # determine output destination
947  if args.copyOut:
948  if args.dest:
949  dest = args.dest
950  elif "DEST" in os.environ:
951  dest = os.environ["DEST"]
952  else:
953  raise Exception("Copy out requested with --copyOut, but no destination supplied. Use --dest or $DEST")
954 
955  if args.autoDropbox:
956  dest=NGU.get_prod_dropbox()
957  print(("Getting automatic dropbox location", dest))
958  # If the initial job finished successfully, we may want to run another config over the output
959  # copy logic above for executing nova with the second_config instead.
960  if args.second_config:
961  # stage files from first config to be declared
962  # before the second config is run
963  if args.copyOut:
964  # move what we have there
965  checkAndMoveFiles(inFile, outputs, noCleanup=True, copyOnly=True)
966  if args.jsonMetadata:
968  copyOutFiles(dest, args.hashDirs, args.runDirs, fileMetaDataMgr.runNum, args.noCleanup, args.declareLocations, args.declareFiles)
969 
970 
971  # create a temporary work space so we're careful about overwriting files
972  # from the main step
973  import random
974  import string
975 
976  lastdir = os.getcwd()
977  tmpdir = os.path.abspath(os.path.join('./', 'tmp' + ''.join(random.choice(string.ascii_letters) for i in range(8))))
978  os.mkdir(tmpdir)
979  os.chdir(tmpdir)
980  print('Changing to %s' % os.getcwd())
981  tmpSecondFclName = make_temp_fcl(args.second_config, inFileBase)
982  cmdList = []
983  cmdList.append('nova')
984  cmdList.append('-c')
985  cmdList.append(tmpSecondFclName)
986  if doMeta:
987  cmdList.append('--sam-application-family=nova')
988  cmdList.append('--sam-application-version=' + release)
989  if not fileMetaDataMgr.isSam4Users():
990  cmdList.append('--sam-file-type=' + fileMetaDataMgr.fileType)
991 
992  if args.gdb:
993  gdbArgs = ["gdb", "-return-child-result", "--ex", "run", "--ex", "bt", "full", "--ex", "q", "--args"]
994  cmdList = gdbArgs + cmdList
995 
996 
997  # run second nova executable
998  inPID= fileMetaDataMgr.getOutputFileName('pid')
999  if not os.path.isfile(os.path.abspath(os.path.join(lastdir, os.path.basename(inPID)))):
1000  print('WARNING: Could not find PID file for second configuration fcl. Skipping', inPID)
1001  else:
1002 
1003  cmdList.append(os.path.abspath(os.path.join(lastdir, os.path.basename(inPID))))
1004  cmd = ' '.join(cmdList)
1005 
1006  print('Running:', cmd)
1007  sys.stdout.flush() # flush the stdout buffer before running the nova executable, cleans up output.
1008  if args.logs or args.zipLogs:
1009  with open(os.path.join(lastdir,'log.txt'), 'w') as logfile:
1010  sys.stderr.write('\nsecond nova command runs here. stderr redirected to stdout\n\n')
1011  retCode = subprocess.call(cmdList, stdout=logfile, stderr=subprocess.STDOUT)
1012 
1013  # Print all the output to the screen as well so that regular condor
1014  # logs include it too.
1015  with open(os.path.join(lastdir, 'log.txt'), 'r') as logfile:
1016  for line in logfile:
1017  print(line, end=' ')
1018 
1019  if args.zipLogs:
1020  os.system('bzip2 -f log.txt')
1021 
1022  else:
1023  retCode = subprocess.call(cmdList)
1024 
1025  if retCode == 0:
1026  # handle output of second nova executable
1027  # don't copy back files that belong to both the 'outputs' list and
1028  # the files that were created by the first executable.
1029  # Warn the user if this happens
1030  _first = set(os.listdir(lastdir))
1031  _second = set(os.listdir(tmpdir))
1032  _outputs = set(outputs)
1033  _bad = (_first & _second) & _outputs
1034  _good = _second - _bad
1035  if len(_bad) > 0:
1036  print('runNovaSAM.py: [WARNING] First and second processes produced identically named files that among requested outputs. Ignoring file produced by the second and copying out only the first')
1037  for b in _bad: print(b)
1038  for g in _good:
1039  print('Change ', os.path.join(tmpdir, os.path.basename(g)), ' to ', os.path.join(lastdir, os.path.basename(g)))
1040  os.rename(os.path.join(tmpdir, os.path.basename(g)), os.path.join(lastdir, os.path.basename(g)))
1041  else:
1042  sys.stderr.write('\nSecond nova command failed with exit code %d' % retCode)
1043  # remove temp directory
1044  if not args.noCleanup:
1045  # we've moved all of the files we care about at this point.
1046  # remove all contents of tmpdir so we can remove the directory
1047  # itself too
1048  for f in os.listdir(tmpdir):
1049  os.remove(os.path.join(tmpdir, f))
1050  os.rmdir(tmpdir)
1051 
1052  # go back to previous working directory
1053  os.chdir(lastdir)
1054 
1055  # wait until after we possibly run a second config to zip the output up
1056  if args.zipLogs:
1057  os.system('bzip2 -f log.txt')
1058 
1059 
1060  if args.outputNumuDeCAF or args.outputNueDeCAF or args.outputNumuOrNueDeCAF or args.outputNusDeCAF or args.outputValidationDeCAF:
1061  decafdir = os.listdir(".")
1062  for fname in decafdir:
1063  if fname.endswith("caf.root"):
1064  if args.outputNumuDeCAF:
1065  outputs.append(makeDeCAF('numu/FirstAnalysis/reduce_numu_fa.C',fname,'numu_contain'))
1066  if args.outputNueDeCAF:
1067  outputs.append(makeDeCAF('nue/reduce_nue_sa.C',fname,'nue_contain'))
1068  if args.outputNumuOrNueDeCAF:
1069  outputs.append(makeDeCAF('nue/reduce_nue_or_numu_sa.C',fname,'nue_or_numu_contain'))
1070  if args.outputNusDeCAF:
1071  outputs.append(makeDeCAF('nus/reduce_nus.C',fname,'nus_contain'))
1072  if args.outputValidationDeCAF:
1073  outputs.append(makeDeCAF('nus/reduce_nue_or_numu_or_nus.C',fname,'nue_or_numu_or_nus_contain'))
1074  print("\nAt the start of check and move.")
1075  checkAndMoveFiles(inFile, outputs, args.noCleanup)
1076 
1077  if args.copyOut:
1078  if args.jsonMetadata:
1079  print("\nMake JSONs")
1081  print("\nMade JSONs, now to copy files.")
1082 
1083  copyOutFiles(dest, args.hashDirs, args.runDirs, fileMetaDataMgr.runNum, args.noCleanup, args.declareLocations, args.declareFiles)
1084  print("Copied files.")
1085  else:
1086  #job didn't succeed, remove output files if they exist
1087  for file in outList:
1088  try:
1089  os.remove("./" + file)
1090  except OSError:
1091  pass
1092 
1093  #clean up section
1094  if not args.noCleanup:
1095  os.remove(tmpFclName)
1096  os.remove(inFile)
1097  dirList = os.listdir(".")
1098  for file in dirList:
1099  skip_match = _skip_pattern.match(file)
1100  if skip_match != None:
1101  print(file, "contains RootOutput*.root: clean up")
1102  os.remove("./" + file)
1103 
1104  dh = ifdh.ifdh("http://samweb.fnal.gov:8480/sam/nova/api")
1105  dh.cleanup()
1106 
1107  exit(retCode)
def makeMetadataJSONs()
Definition: runNovaSAM.py:327
void split(double tt, double *fr)
def copyOutFiles(hashDirs=False)
Definition: runNovaSAM.py:149
def makeDirSafely(dir)
Definition: runNovaSAM.py:83
def checkAndMoveFiles(inFile, declareFiles)
Definition: runNovaSAM.py:105
def resolveFclPath(fcl)
Definition: runNovaSAM.py:188
void append()
Definition: append.C:24
def getOutDir(pathname, hashDirs=False)
Definition: runNovaSAM.py:92
if(dump)
bool print
def MakeTransposeJson(TransposeList)
Definition: runNovaSAM.py:407
std::string format(const int32_t &value, const int &ndigits=8)
Definition: HexUtils.cpp:14
procfile open("FD_BRL_v0.txt")
def createMetadata(inFile)
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
def addMetadataToFCL(fclFile, parName, parValue)
exit(0)
def listFiles(outPath, dh)
Definition: runNovaSAM.py:320
def make_temp_fcl(fclFile, inFileBase)
Definition: runNovaSAM.py:37
def setVMemLimit()
Definition: runNovaSAM.py:75
def fileExists(outPath, dh)
Definition: runNovaSAM.py:308
def makeDirIfNeeded(dir)
Definition: runNovaSAM.py:103
def declareFile(fileWPath)
Definition: runNovaSAM.py:127
def declareLogFile(logName, logFile, rootName)
Definition: runNovaSAM.py:289
def makeDeCAF(script, fname, special)
Definition: runNovaSAM.py:554
def ModifyParentMetadata(inParentFile, inFile)
Definition: runNovaSAM.py:193