CMS 3D CMS Logo

submitDQMOfflineCAF.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 #
4 #
5 
6 ## CMSSW/DQM/SiStripMonitorClient/scripts/submitDQMOfflineCAF.py
7 #
8 # This script submits CRAB/LSF jobs to the CAF in order to process the full
9 # granularity SiStrip offline DQM.
10 # Questions and comments to: volker.adler@cern.ch
11 
12 
13 from __future__ import print_function
14 import sys
15 import os
16 import os.path
17 import commands
18 import shutil
19 import string
20 import math
21 import urllib
22 import time
23 import datetime
24 import smtplib
25 
26 # Constants
27 
28 # numbers
29 OCT_rwx_r_r = 0o744
30 LFLOAT_valueMagField = [0.0,2.0,3.0,3.5,3.8,4.0]
31 TD_shiftUTC = datetime.timedelta(hours = 2) # positive for timezones with later time than UTC
32 # strings
33 LSTR_true = ['1','TRUE' ,'True' ,'true' ]
34 LSTR_false = ['0','FALSE','False','false']
35 STR_default = 'DEFAULT'
36 STR_none = 'None'
37 LSTR_auto = ['AUTO','Auto','auto']
38 STR_nameCmsswPackage = 'DQM/SiStripMonitorClient'
39 STR_textUsage = """ CMSSW/DQM/SiStripMonitorClient/scripts/submitDQMOfflineCAF.py
40 
41  This script submits batch jobs to the CAF in order to process the full
42  granularity SiStrip offline DQM.
43  Questions and comments to: volker.adler@cern.ch
44 
45  Func_Usage(): submitDQMOfflineCAF.py (-s, --submit | -c, --create |
46  -h, --help)
47  [-r, --run]
48  [-C, --CRAB]
49  [-S, --server]
50  [-e, --email]
51  [-j, --jobs]
52  [-f, --filter]
53  [-d, --dataset]
54  [-o, --outpath]
55  [-m, --mergepath]
56 
57  Function letters: One of the following options m u s t be used.
58 
59  -s, --submit
60  create jobs and submit them to CAF;
61  requires option '-r'
62 
63  -c, --create
64  create jobs, but do not submit them;
65  requires option '-r'
66 
67  -h, --help
68  print this message
69 
70  Other options:
71 
72  -r, --run RUNNUMBER
73  number of run to process;
74  required by funtion letters '-s' and '-c'
75 
76  -d, --dataset PRIMARY_DATASET
77  specify dataset for DBS query;
78  required by funtion letters '-s' and '-c'
79 
80  -C, --CRAB TRUE/FALSE
81  submit or submit not using CRAB;
82  default: TRUE
83 
84  NOTE: This script runs only with CRAB 2.4.0 or higher.
85 
86  -S, --server CRAB_SERVER
87  CRAB server to use;
88  available: None (default)
89  caf (works, but slow)
90  bari (CRAB version >= 2.4.1,
91  s. https://twiki.cern.ch/twiki/bin/view/CMS/CrabServer#Server_available_for_users)
92 
93  NOTE: CRAB server submission is disabled at the moment.
94 
95  -e, --email EMAIL_ADDRESS
96  where the CRAB server should send its messages;
97  default: volker.adler@cern.ch
98 
99  -j, --jobs NUMBER
100  number of jobs to create;
101  default: 10
102 
103  -g, --global-tag GLOBAL_TAG
104  global tag to be used;
105  default: CRAFT_V4P::All
106 
107  -M, --magnetic-field FIELD
108  specification of field to be used;
109  can be:
110  - average field during run in Tesla, given as float (e.g.: 3.8),
111  - specification referring to existing configuration files (e.g.: 38T)
112  (s. Configuration/StandardSequences/python/MagneticField_[FIELD]_cff.py),
113  - usage of automatic average field determination from CMS WBM by using "auto"
114  default: 38T
115 
116  NOTE: "auto" is disabled for the moment due to unavailablity of CMS WBM outside '.cms' network.
117 
118  -f, --filter TRUE/FALSE
119  use or use not HLT filters to select events to process;
120  default: FALSE
121 
122  -o, --outpath PATH
123  path to copy job output *.root files to;
124  currently (almost) no check performed;
125  must be in AFS or CASTOR
126  default: /castor/cern.ch/user/c/cctrack/DQM
127 
128  -m, --mergepath PATH
129  path to merge the job output *.root files;
130  currently (almost) no check performed;
131  must be in AFS or on local computer (e.g. /tmp/[user])
132  default: /afs/cern.ch/cms/CAF/CMSCOMM/COMM_TRACKER/DQM/SiStrip/jobs/merged
133 """
134 LSTR_datatiers = ['RECO','RAW']
135 # argument vector
136 LSTR_wordArgument = sys.argv[1:]
137 # default arguments
138 BOOL_CRAB = True
139 LSTR_server = [STR_none,'caf','bari']
140 STR_server = LSTR_server[0]
141 STR_email = 'volker.adler@cern.ch'
142 INT_jobs = 10
143 STR_globalTag = 'CRAFT_V4P::All'
144 STR_magField = '38T'
145 BOOL_magFieldAuto = False
146 BOOL_filter = False
147 STR_outpath = '/castor/cern.ch/user/c/cctrack/DQM'
148 BOOL_useCastor = True
149 STR_mergepath = '/afs/cern.ch/cms/CAF/CMSCOMM/COMM_TRACKER/DQM/SiStrip/jobs/merged'
150 # option lists
151 LSTR_functionLetters = ['-s','-c','-h']
152 DICT_functionLetters = {'--submit':LSTR_functionLetters[0],
153  '--create':LSTR_functionLetters[1],
154  '--help' :LSTR_functionLetters[2]}
155 LSTR_optionLetters = ['-r','-C','-S','-e','-j','-M','-g','-f','-d','-o','-m']
156 DICT_optionLetters = {'--run' :LSTR_optionLetters[0],
157  '--CRAB' :LSTR_optionLetters[1],
158  '--server' :LSTR_optionLetters[2],
159  '--email' :LSTR_optionLetters[3],
160  '--jobs' :LSTR_optionLetters[4],
161  '--magnetic-field':LSTR_optionLetters[5],
162  '--global-tag' :LSTR_optionLetters[6],
163  '--filter' :LSTR_optionLetters[7],
164  '--dataset' :LSTR_optionLetters[8],
165  '--outpath' :LSTR_optionLetters[9],
166  '--mergepath' :LSTR_optionLetters[10]}
167 STR_mailSmtp = 'localhost'
168 STR_mailServer = '@mail.cern.ch'
169 STR_mailTextOpener = """Dear """ + os.getenv('USER').capitalize() + """,
170 
171 on """ + str(time.ctime()) + """, you have submitted run """
172 STR_mailText = """
173 for SiStrip offline DQM at the CAF.
174 Unfortunately, this needed to be done from your private account. So, only you
175 are able to finalize this submission -- even after the end of your shift.
176 To do so, please forward all emails from the LSF batch system referring to the
177 respective jobs to the list t h i s message was sent to.
178 -- and then your shift is r e a l l y done :-)
179 
180 We are very sorry for the inconvenience.
181 Thanks a lot!
182 
183 Best regards,
184 your SiStrip DQM team
185 
186 P.S.:
187 To reply to this email, simply use the "Reply to all" function of your email
188 client.
189 """
190 
191 # Globals
192 
193 # arguments
194 global Dict_arguments
195 global Str_run
196 global Bool_CRAB
197 global Str_server
198 global Str_email
199 global Int_jobs
200 global Str_globalTag
201 global Bool_filter
202 global Str_dataset
203 global Str_datatier
204 global Str_magField
205 global Float_magField
206 global Bool_magFieldAuto
207 global Str_outpath
208 global Bool_useCastor
209 global Str_mergepath
210 # others
211 global Str_pathCurrentDir
212 global Str_pathCmsswBase
213 global Str_nameCmsswRel
214 global Str_pathCmsswBasePackage
215 global Str_nameRun
216 global Str_pathRunIncludeDir
217 global Str_pathInputFilesCAFCff
218 global Int_jobsNew
219 global Str_magField
220 # initialize arguments
221 Dict_arguments = {}
222 Bool_CRAB = BOOL_CRAB
223 Str_server = STR_server
224 Str_email = STR_email
225 Int_jobs = INT_jobs
226 Str_globalTag = STR_globalTag
227 Bool_filter = BOOL_filter
228 Str_magField = STR_magField
229 Float_magField = float(Str_magField[:-1])/10.
230 Bool_magFieldAuto = BOOL_magFieldAuto
231 Str_outpath = STR_outpath
232 Bool_useCastor = BOOL_useCastor
233 Str_mergepath = STR_mergepath
234 
235 ## Function Func_Usage()
236 #
237 # Displays usage of the script
239  """ Function Func_Usage():
240  Displays usage of the script
241  """
242  print(STR_textUsage)
243 
244 ## Function Func_Exit()
245 #
246 # Exit after error
247 def Func_Exit():
248  """ Function Func_Exit():
249  Exit after error
250  """
251  print(' exit')
252  print()
253  sys.exit(1)
254 
255 ## Function Func_ExitUsage()
256 #
257 # Exit after wrong invocation of script
259  """ Function Func_ExitUsage():
260  Exit after wrong invocation of script
261  """
262  print(' exit')
263  print()
264  Func_Usage()
265  sys.exit(1)
266 
267 ## Function Func_ExitBool()
268 #
269 # Exit after wrong assignment of bool option
270 def Func_ExitBool(int_index):
271  """ Function Func_ExitBool():
272  Exit after wrong assignment of bool option
273  """
274  print('> submitDQMOfflineCAF.py > option %s expects 0/1, FALSE/TRUE, False/True or false/true' %(DICT_optionLetters.items()[int_index]))
275  Func_Exit()
276 
277 ## Function Func_MkDir()
278 #
279 # Create new directory
280 def Func_MkDir(str_path):
281  """ Function Func_MkDir():
282  Create new directory
283  """
284  shutil.rmtree(str_path, True)
285  os.mkdir(str_path)
286 
287 ## Function Func_MagConfig(float_magFieldMeasured)
288 #
289 # Determine configuration to be used for a given magnetic field
290 def Func_MagConfig(float_magFieldMeasured):
291  """ Func_MagConfig(float_magFieldMeasured):
292  Determine configuration to be used for a given magnetic field
293  """
294  float_magField = 0.0
295  for float_valueMagField in LFLOAT_valueMagField:
296  if math.fabs(float_valueMagField-float_magFieldMeasured) < math.fabs(float_magField-float_magFieldMeasured):
297  float_magField = float_valueMagField
298  return float_magField
299 
300 ## Main program
301 
302 print()
303 
304 # Current environment
305 
306 Str_pathCurrentDir = os.getcwd()
307 Str_pathCmsswBase = os.getenv('CMSSW_BASE')
308 if not Str_pathCmsswBase:
309  print('> submitDQMOfflineCAF.py > CMSSW environment not set properly;')
310  print(' first do')
311  print()
312  print(' $ cd [your/CMSSW/release/area]/src')
313  print(' $ cmsenv')
314  print()
315  Func_Exit()
316 Str_nameCmsswRel = os.getenv('CMSSW_VERSION')
317 Str_pathCmsswBasePackage = Str_pathCmsswBase + '/src/' + STR_nameCmsswPackage
318 str_suffixShell = 'csh'
319 if not os.getenv('SHELL')[-3:] == str_suffixShell:
320  str_suffixShell = 'sh'
321 
322 # Check function letters
323 
324 if len(LSTR_wordArgument) == 0:
326 int_nFunctionLetters = 0
327 for str_argument in LSTR_wordArgument:
328  if str_argument in LSTR_functionLetters or\
329  str_argument in DICT_functionLetters :
330  int_nFunctionLetters += 1
331 if int_nFunctionLetters == 0:
332  print('> submitDQMOfflineCAF.py > no or unknown function letter used')
334 elif int_nFunctionLetters > 1:
335  print('> submitDQMOfflineCAF.py > too many function letter used')
337 
338 # Check options
339 
340 str_argumentFormer = ''
341 bool_standBy = False
342 for str_argument in LSTR_wordArgument:
343  if not ( str_argument in LSTR_functionLetters or str_argument in DICT_functionLetters or\
344  str_argument in LSTR_optionLetters or str_argument in DICT_optionLetters ):
345  if str_argument[0] == '-':
346  print('> submitDQMOfflineCAF.py > unknown option used')
348  if not bool_standBy:
349  print('> submitDQMOfflineCAF.py > value without option used')
351  Dict_arguments[str_argumentFormer] = str_argument
352  bool_standBy = False
353  else:
354  if bool_standBy:
355  Dict_arguments[str_argumentFormer] = STR_default
356  if str_argumentFormer in LSTR_optionLetters or\
357  str_argumentFormer in DICT_optionLetters:
358  print('> submitDQMOfflineCAF.py > option "%s" w/o value' %(str_argumentFormer))
359  print(' default used')
360  print()
361  bool_standBy = not ( str_argument in LSTR_functionLetters or\
362  str_argument in DICT_functionLetters )
363  if not bool_standBy:
364  Dict_arguments[str_argument] = STR_default
365  str_argumentFormer = str_argument
366 if bool_standBy:
367  Dict_arguments[str_argumentFormer] = STR_default
368  if str_argumentFormer in LSTR_optionLetters or\
369  str_argumentFormer in DICT_optionLetters :
370  print('> submitDQMOfflineCAF.py > option "%s" w/o value' %(str_argumentFormer))
371  print(' default used')
372  print()
373 
374 # Correct arguments' dictionary
375 
376 dict_arguments = Dict_arguments
377 for str_key, str_value in dict_arguments.items():
378  if str_key in DICT_functionLetters.keys():
379  del Dict_arguments[str_key]
380  Dict_arguments[DICT_functionLetters[str_key]] = str_value
381  if str_key in DICT_optionLetters.keys():
382  del Dict_arguments[str_key]
383  Dict_arguments[DICT_optionLetters[str_key]] = str_value
384 
385 # Help (exit)
386 
387 if LSTR_functionLetters[2] in Dict_arguments:
388  Func_Usage()
389  sys.exit(0)
390 
391 # Check and assign arguments
392 
393 # run number
394 if LSTR_optionLetters[0] in Dict_arguments and\
395  Dict_arguments[LSTR_optionLetters[0]] != STR_default :
396  Str_run = Dict_arguments[LSTR_optionLetters[0]]
397 else:
398  print('> submitDQMOfflineCAF.py > no run number given')
399  Func_Exit()
400 # use CRAB
401 if LSTR_optionLetters[1] in Dict_arguments and\
402  Dict_arguments[LSTR_optionLetters[1]] != STR_default :
403  if Dict_arguments[LSTR_optionLetters[1]] in LSTR_true:
404  Bool_CRAB = True
405  elif Dict_arguments[LSTR_optionLetters[1]] in LSTR_false:
406  Bool_CRAB = False
407  else:
408  Func_ExitBool(1)
409 # name of CRAB server
410 if LSTR_optionLetters[2] in Dict_arguments and\
411  Dict_arguments[LSTR_optionLetters[2]] != STR_default :
412  Str_server = Dict_arguments[LSTR_optionLetters[2]]
413 # email address to be used by CRAB server
414 if LSTR_optionLetters[3] in Dict_arguments and\
415  Dict_arguments[LSTR_optionLetters[3]] != STR_default :
416  Str_email = Dict_arguments[LSTR_optionLetters[3]]
417 # number of jobs to create
418 if LSTR_optionLetters[4] in Dict_arguments and\
419  Dict_arguments[LSTR_optionLetters[4]] != STR_default :
420  Int_jobs = int(Dict_arguments[LSTR_optionLetters[4]])
421 # magnetic field
422 if LSTR_optionLetters[5] in Dict_arguments and\
423  Dict_arguments[LSTR_optionLetters[5]] != STR_default :
424  Str_magField = Dict_arguments[LSTR_optionLetters[5]]
425 if Str_magField in LSTR_auto:
426 # Bool_magFieldAuto = True
427  print('> submitDQMOfflineCAF.py > automatic determination of magnetic field disabled at the moment')
428  Func_Exit()
429 # global tag
430 if LSTR_optionLetters[6] in Dict_arguments and\
431  Dict_arguments[LSTR_optionLetters[6]] != STR_default :
432  Str_globalTag = Dict_arguments[LSTR_optionLetters[6]]
433 # use HLT to filter events
434 if LSTR_optionLetters[7] in Dict_arguments and\
435  Dict_arguments[LSTR_optionLetters[7]] != STR_default :
436  if Dict_arguments[LSTR_optionLetters[7]] in LSTR_true:
437  Bool_filter = True
438  elif Dict_arguments[LSTR_optionLetters[7]] in LSTR_false:
439  Bool_filter = False
440  else:
441  Func_ExitBool(7)
442 # primary dataset
443 if LSTR_optionLetters[8] in Dict_arguments and\
444  Dict_arguments[LSTR_optionLetters[8]] != STR_default :
445  Str_dataset = Dict_arguments[LSTR_optionLetters[8]]
446 else:
447  print('> submitDQMOfflineCAF.py > no primary dataset given')
448  Func_Exit()
449 # path for job output
450 if LSTR_optionLetters[9] in Dict_arguments and\
451  Dict_arguments[LSTR_optionLetters[9]] != STR_default :
452  Str_outpath = Dict_arguments[LSTR_optionLetters[9]]
453 # path for merged output
454 if LSTR_optionLetters[10] in Dict_arguments and\
455  Dict_arguments[LSTR_optionLetters[10]] != STR_default :
456  Str_mergepath = Dict_arguments[LSTR_optionLetters[10]]
457 
458 # React on arguments
459 
460 # on use CRAB
461 if Bool_CRAB:
462  str_buffer = commands.getoutput('which crab')
463  if str_buffer.find('which: no crab in') >= 0:
464  str_suffixShell = 'csh'
465  if not os.getenv('SHELL')[-3:] == str_suffixShell:
466  str_suffixShell = 'sh'
467  print('> submitDQMOfflineCAF.py > CRAB environment not set properly;')
468  print(' please use')
469  print()
470  print(' $ source /afs/cern.ch/cms/ccs/wm/scripts/Crab/crab.%s' %(str_suffixShell))
471  print()
472  Func_Exit()
473 # on name of CRAB server
474 if not Str_server in LSTR_server:
475  print('> submitDQMOfflineCAF.py > CRAB server "%s" not available' %(Str_server))
476  Func_Exit()
477 # on number of jobs
478 if Int_jobs == 0:
479  Int_jobs = 1
480  print('> submitDQMOfflineCAF.py > number of requested jobs was 0')
481  print(' set to 1')
482 # on magnetic field
483 if Str_magField in LSTR_auto:
484 # Bool_magFieldAuto = True
485  print('> submitDQMOfflineCAF.py > automatic determination of magnetic field disabled at the moment')
486  Func_Exit()
487 elif Str_magField[-1] == 'T':
488  bool_foundField = False
489  for float_valueMagField in LFLOAT_valueMagField:
490  if str(int(float_valueMagField*10)) == Str_magField[:-1]:
491  Float_magField = float_valueMagField
492  bool_foundField = True
493  break
494  if not bool_foundField:
495  print('> submitDQMOfflineCAF.py > no magnet configuration for \'%s\' available' %(Str_magField))
496  Func_Exit()
497 else:
498  Float_magField = float(Str_magField) # FIXME protect better from wrong user input
499 # on primary dataset
500 # data tier
501 str_datatier = Str_dataset.split('/')[-1]
502 if str_datatier == 'RAW-RECO':
503  Str_datatier = LSTR_datatiers[1] # FIXME: This should be an option
504 else:
505  Str_datatier = str_datatier
506 Str_datatier = Str_dataset.split('/')[-1]
507 if not Str_datatier in LSTR_datatiers:
508  print('> submitDQMOfflineCAF.py > datatier "%s" not processable' %(Str_datatier))
509  Func_Exit()
510 # on path for job output
511 # use CASTOR
512 if Str_outpath.split('/')[1] == 'afs':
513  Bool_useCastor = False
514 elif Str_outpath.split('/')[1] != 'castor':
515  print('> submitDQMOfflineCAF.py > output path not accepted')
517 str_castorCp = 'cp'
518 if Bool_useCastor:
519  str_castorCp = 'rfcp'
520 # on path for merged output
521 if Str_mergepath.split('/')[1] != 'afs':
522  print('> submitDQMOfflineCAF.py > merge path not accepted')
524 
525 # Prepare work area
526 
527 # string identifying run (run name)
528 Str_nameRun = 'R' + Str_run.zfill(9)
529 # directories
530 Func_MkDir(Str_nameRun)
531 Str_pathRunIncludeDir = Str_pathCmsswBasePackage + '/python/' + Str_nameRun
532 Func_MkDir(Str_pathRunIncludeDir)
533 str_nameInputFilesFile = Str_nameRun + '/' + Str_nameRun + '.txt'
534 str_nameRunIncludeDir = STR_nameCmsswPackage.replace('/','.') + '.' + Str_nameRun
535 
536 # Retrieving information from the web
537 
538 # input files
539 int_nInputFiles = 0
540 file_inputFilesCff = file(str_nameInputFilesFile, 'w')
541 # DBS query for list of input files
542 str_dbsParams = urllib.urlencode({'dbsInst':'cms_dbs_prod_global', 'blockName':'*', 'dataset':Str_dataset, 'userMode':'user', 'run':Str_run, 'what':'py'})
543 file_dbsOutput = urllib.urlopen("https://cmsweb.cern.ch/dbs_discovery/getLFN_txt", str_dbsParams)
544 for str_iLine in file_dbsOutput.readlines():
545  lstr_wordsLine = str_iLine.split("/")
546  if len(lstr_wordsLine) >= 5:
547  if lstr_wordsLine[1] == 'store' and\
548  lstr_wordsLine[2] == 'data' and\
549  Str_dataset.find(lstr_wordsLine[3]) >= 0 and\
550  Str_dataset.find(lstr_wordsLine[4]) >= 0 and\
551  lstr_wordsLine[5] == str_datatier :
552  int_nInputFiles += 1
553  file_inputFilesCff.write(str_iLine)
554 if int_nInputFiles == 0:
555  print('> submitDQMOfflineCAF.py > no input files found in DBS for run %s in dataset %s' %(Str_run,Str_dataset))
556  Func_Exit()
557 file_inputFilesCff.close()
558 print('> submitDQMOfflineCAF.py > input files for run %s: %i' %(Str_run,int_nInputFiles))
559 if int_nInputFiles < Int_jobs:
560  Int_jobs = int_nInputFiles
561  print(' number of requested jobs reduced accordingly')
562 Int_jobsNew = Int_jobs
563 print()
564 
565 # magnetic field
566 if Bool_magFieldAuto:
567  # extract time stamps of the run
568  str_cmsmonParams = urllib.urlencode({'RUN':Str_run})
569  file_cmsmonOutput = urllib.urlopen("http://cmsmon.cern.ch/cmsdb/servlet/RunSummary", str_cmsmonParams)
570  str_timeBegin = ''
571  str_timeEnd = ''
572  for str_cmsmonOutput in file_cmsmonOutput.readlines():
573  if str_cmsmonOutput.find('HREF=Component?RUN=' + Str_run + '&NAME=TRACKER') >= 0:
574  lstr_timeQuery = str_cmsmonOutput.split('HREF=Component?RUN=' + Str_run + '&NAME=TRACKER&')[1].split('>TRACKER')[0].split('&')
575  for str_timeQuery in lstr_timeQuery:
576  str_nameStamp = str_timeQuery.split('=')[0]
577  lstr_timeDate = str_timeQuery.split('=')[1].split('_')[0].split('.')
578  lstr_timeTime = str_timeQuery.split('=')[1].split('_')[1].split(':')
579  dt_stampOld = datetime.datetime(int(lstr_timeDate[0]),int(lstr_timeDate[1]),int(lstr_timeDate[2]),int(lstr_timeTime[0]),int(lstr_timeTime[1]),int(lstr_timeTime[2]))
580  dt_stampNew = dt_stampOld - TD_shiftUTC
581  str_timeStamp = str(dt_stampNew).replace('-','.')
582  if str_nameStamp == 'TIME_BEGIN':
583  str_timeBegin = str_timeStamp
584  elif str_nameStamp == 'TIME_END':
585  str_timeEnd = str_timeStamp
586  # get magnetic field itself
587  str_cmsmonParams = urllib.urlencode({'TIME_BEGIN':str_timeBegin, 'TIME_END':str_timeEnd})
588  file_cmsmonOutput = urllib.urlopen("http://cmsmon.cern.ch/cmsdb/servlet/MagnetHistory", str_cmsmonParams)
589  bool_foundField = False
590  for str_cmsmonOutput in file_cmsmonOutput.readlines():
591  if str_cmsmonOutput.find('BFIELD, Tesla') >= 0:
592  Float_magField = float(str_cmsmonOutput.split('</A>')[0].split('>')[-1])
593  bool_foundField = True
594  break
595  if not bool_foundField:
596  print('> submitDQMOfflineCAF.py > could not extract magnetic field')
597  print(' please provide value')
598  Func_Exit()
599 # determine corresponding configuration file to be included
600 float_magField = Func_MagConfig(Float_magField)
601 Str_magField = str(int(float_magField*10)) + 'T'
602 print('> submitDQMOfflineCAF.py > (average) magnetic field in run %s: %s T' %(Str_run,Float_magField))
603 print(' using %s T for configuration' %(float_magField))
604 print()
605 
606 # Create scripts
607 
608 int_nLinesRead = 0
609 file_inputFilesCff = file(str_nameInputFilesFile)
610 lstr_linesInput = file_inputFilesCff.readlines()
611 file_inputFilesCff.close()
612 
613 # create harvesting config file and job script
614 str_sedCommand = 'sed '
615 str_sedCommand += '-e \"s#xMAG_FIELDx#' + Str_magField + '#g\" '
616 str_sedCommand += '-e \"s#xGLOBAL_TAGx#' + Str_globalTag + '#g\" '
617 str_sedCommand += '-e \"s#xINCLUDE_DIRECTORYx#' + str_nameRunIncludeDir + '#g\" '
618 str_sedCommand += '-e \"s#xMERGE_PATHx#' + Str_mergepath + '#g\" '
619 str_sedCommand += Str_pathCmsswBasePackage + '/test/SiStripCAFHarvest_template_cfg.py > ' + Str_nameRun + '/SiStripCAFHarvest_cfg.py'
620 os.system(str_sedCommand)
621 str_sedCommand = 'sed '
622 str_sedCommand += '-e \"s#xCMSSW_BASEx#' + Str_pathCmsswBase + '#g\" '
623 str_sedCommand += '-e \"s#xRUN_NAMEx#' + Str_nameRun + '#g\" '
624 str_sedCommand += '-e \"s#xMERGE_PATHx#' + Str_mergepath + '#g\" '
625 str_sedCommand += '-e \"s#xCURRENT_DIRx#' + Str_pathCurrentDir + '#g\" '
626 str_sedCommand += '-e \"s#xDATA_TIERx#' + Str_datatier + '#g\" '
627 str_sedCommand += '-e \"s#xCMSSW_VERSIONx#' + Str_nameCmsswRel + '#g\" '
628 str_sedCommand += Str_pathCmsswBasePackage + '/scripts/SiStripDQMCAFHarvest_template.job > ' + Str_nameRun + '/SiStripCAFHarvest.job'
629 os.system(str_sedCommand)
630 # create included CAF input files list (mainly for compilation)
631 Str_pathInputFilesCAFCff = Str_pathRunIncludeDir + '/inputFilesCAF_cff.py'
632 file_inputFilesCAFCff = file(Str_pathInputFilesCAFCff, 'w')
633 file_inputFilesCAFCff.write('import FWCore.ParameterSet.Config as cms\n\nsource = cms.Source ("PoolSource",\n processingMode = cms.untracked.string( \'Runs\' ),\n fileNames = cms.untracked.vstring(\n')
634 for int_iJob in range(1,Int_jobs+1):
635  str_lineInput = Str_outpath + '/SiStripDQMOfflineGlobalRunCAF-' + Str_nameRun + '_' + str(int_iJob) + '.root'
636  if Bool_useCastor:
637  str_lineInput = 'rfio:' + str_lineInput
638  str_lineInput = ' \'' + str_lineInput + '\''
639  if int_iJob == Int_jobs:
640  str_lineInput += '\n'
641  file_inputFilesCAFCff.write(str_lineInput)
642  break
643  str_lineInput += ',\n'
644  file_inputFilesCAFCff.write(str_lineInput)
645 file_inputFilesCAFCff.write(' )\n)\n')
646 file_inputFilesCAFCff.close()
647 
648 str_sedCommandCommon = 'sed '
649 if Bool_filter:
650  str_sedCommandCommon += '-e \"s#xHLT_FILTERx# #g\" '
651 else:
652  str_sedCommandCommon += '-e \"s#xHLT_FILTERx#\# #g\" '
653 if Str_datatier == 'RECO':
654  str_sedCommandCommon += '-e \"s#xRECO_FROM_RAWx#\# #g\" '
655  str_sedCommandCommon += '-e \"s#xDQM_FROM_RAWx#\# #g\" '
656 else:
657  str_sedCommandCommon += '-e \"s#xRECO_FROM_RAWx# #g\" '
658  str_sedCommandCommon += '-e \"s#xDQM_FROM_RAWx# #g\" '
659 str_sedCommandCommon += '-e \"s#xMAG_FIELDx#' + Str_magField + '#g\" '
660 str_sedCommandCommon += '-e \"s#xGLOBAL_TAGx#' + Str_globalTag + '#g\" '
661 str_sedCommandCommon += '-e \"s#xRUN_NAMEx#' + Str_nameRun + '#g\" '
662 
663 if Bool_CRAB:
664  os.chdir(Str_nameRun)
665  str_outputDir = '.'
666  # create main configuration file
667  str_sedCommand = str_sedCommandCommon
668  str_sedCommand += '-e \"s#xINCLUDE_DIRECTORYx#' + str_nameRunIncludeDir + '#g\" '
669  str_sedCommand += '-e \"s#xOUTPUT_DIRECTORYx#' + str_outputDir + '#g\" '
670  str_sedCommand += Str_pathCmsswBasePackage + '/test/SiStripDQMOfflineGlobalRunCAF_template_cfg.py > SiStripDQMOfflineGlobalRunCAF_cfg.py'
671  os.system(str_sedCommand)
672  # create included input files list
673  str_pathInputFilesJobCff = Str_pathRunIncludeDir + '/inputFiles_cff.py'
674  file_inputFilesJobCff = file(str_pathInputFilesJobCff, 'w')
675  file_inputFilesJobCff.write('import FWCore.ParameterSet.Config as cms\n\nsource = cms.Source ("PoolSource",\n fileNames = cms.untracked.vstring (\n')
676  nLines = 0
677  for str_linesInput in lstr_linesInput:
678  nLines += 1
679  str_correctedLine1 = str_linesInput.replace(') );',',')
680  str_correctedLine = str_correctedLine1.replace(' ] );',',')
681  if nLines == len(lstr_linesInput):
682  str_actualLine = str_correctedLine.replace(',','\n )\n)\n')
683  elif nLines%255 == 0: # FIXME add this check also to LSF
684  str_actualLine = str_correctedLine.replace(',','\n )\n)\nsource.fileNames.extend(\n (')
685  else:
686  str_actualLine = str_correctedLine
687  file_inputFilesJobCff.write(str_actualLine)
688  file_inputFilesJobCff.close()
689  # create CRAB configuration file
690  lstr_outpath = Str_outpath.split('/', 3)
691  str_outpath = lstr_outpath[0] + '/' + lstr_outpath[1] + '/' + lstr_outpath[2]
692  str_sedCommand = 'sed '
693  str_sedCommand += '-e \"s#xSERVER_NAMEx#' + Str_server + '#g\" '
694  str_sedCommand += '-e \"s#xDATASETPATHx#' + Str_dataset + '#g\" '
695  str_sedCommand += '-e \"s#xRUNSELECTIONx#' + Str_run + '#g\" '
696  str_sedCommand += '-e \"s#xNUMBER_OF_JOBSx#' + str(Int_jobs) + '#g\" '
697  str_sedCommand += '-e \"s#xEMAILx#' + Str_email + '#g\" '
698  str_sedCommand += '-e \"s#xRUN_NAMEx#' + Str_nameRun + '#g\" '
699  str_sedCommand += '-e \"s#xSTORAGE_PATHx#' + str_outpath + '#g\" '
700  str_sedCommand += '-e \"s#xLFNx#' + lstr_outpath[3] + '#g\" '
701  str_sedCommand += '-e \"s#xCOPY_DATAx#' + str(int(Bool_useCastor)) + '#g\" '
702  str_sedCommand += Str_pathCmsswBasePackage + '/test/SiStripDQMOfflineCAF_template.crab > crab.cfg'
703  os.system(str_sedCommand)
704  os.chdir(Str_pathCurrentDir)
705 else:
706  # FIXME: following calculation has to be reviewed
707  int_nInputFilesJob = int(int_nInputFiles/Int_jobs) + 1
708  if int_nInputFiles%Int_jobs == 0:
709  int_nInputFilesJob -= 1
710  if int_nInputFiles == int_nInputFilesJob*(Int_jobs-1) and Int_jobs > 1:
711  Int_jobs -= 1
712  # loop over single jobs
713  for int_iJob in range(1,Int_jobs+1):
714  str_nameJob = Str_nameRun + '_' + str(int_iJob).zfill(4)
715  # prepare job dir
716  str_nameJobDir = Str_nameRun + "/" + str_nameJob
717  str_outputDir = '/tmp/' + os.getenv('USER') + '/' + str_nameJobDir
718  str_pathJobIncludeDir = Str_pathRunIncludeDir + '/' + str_nameJob
719  str_nameJobIncludeDir = STR_nameCmsswPackage.replace('/','.') + '.' + str_nameJobDir.replace('/','.')
720  os.mkdir(str_nameJobDir)
721  os.chdir(str_nameJobDir)
722  # create job script
723  str_sedCommand = 'sed '
724  str_sedCommand += '-e \"s#xCMSSW_BASEx#' + Str_pathCmsswBase + '#g\" '
725  str_sedCommand += '-e \"s#xRUN_NAMEx#' + Str_nameRun + '#g\" '
726  str_sedCommand += '-e \"s#xJOB_NAMEx#' + str_nameJob + '#g\" '
727  str_sedCommand += '-e \"s#xCURRENT_DIRx#' + Str_pathCurrentDir + '#g\" '
728  str_sedCommand += '-e \"s#xCOPYx#' + str_castorCp + '#g\" '
729  str_sedCommand += '-e \"s#xOUTPUT_DIRx#' + Str_outpath + '#g\" '
730  str_sedCommand += Str_pathCmsswBasePackage + '/scripts/SiStripDQMOfflineCAF_template.job > SiStripDQMOfflineCAF.job'
731  os.system(str_sedCommand)
732  # create main configuration file
733  str_sedCommand = str_sedCommandCommon
734  str_sedCommand += '-e \"s#xINCLUDE_DIRECTORYx#' + str_nameJobIncludeDir + '#g\" '
735  str_sedCommand += '-e \"s#xOUTPUT_DIRECTORYx#' + str_outputDir + '#g\" '
736  str_sedCommand += Str_pathCmsswBasePackage + '/test/SiStripDQMOfflineGlobalRunCAF_template_cfg.py > SiStripDQMOfflineGlobalRunCAF_cfg.py'
737  os.system(str_sedCommand)
738  # prepare job include dir
739  os.mkdir(str_pathJobIncludeDir)
740  # create included input files list
741  str_pathInputFilesJobCff = str_pathJobIncludeDir + '/inputFiles_cff.py'
742  file_inputFilesJobCff = file(str_pathInputFilesJobCff, 'w')
743  file_inputFilesJobCff.write('import FWCore.ParameterSet.Config as cms\n\nsource = cms.Source ("PoolSource",\n fileNames = cms.untracked.vstring (\n')
744  for n_iActualLine in range(int_nLinesRead, min(int_nLinesRead+int_nInputFilesJob, int_nInputFiles)):
745  str_linesInput = lstr_linesInput[n_iActualLine].replace(') );',',')
746  # fix commata and end of line
747  str_actualLine = str_linesInput
748  if (n_iActualLine+1)%int_nInputFilesJob == 0 or int_nLinesRead == int_nInputFiles-1:
749  str_actualLine = str_linesInput.split(',')[0] + '\n'
750  file_inputFilesJobCff.write(str_actualLine)
751  int_nLinesRead += 1
752  file_inputFilesJobCff.write(' )\n)\n')
753  file_inputFilesJobCff.close()
754  # finalize job creation
755  os.chdir(Str_pathCurrentDir)
756  # FIXME: This protection is currently needed. Review calculations again!
757  if int_nLinesRead >= int_nInputFiles:
758  Int_jobsNew = int_iJob
759  break
760 
761 # Compile
762 
763 os.chdir(Str_pathRunIncludeDir+'/..')
764 os.system('scramv1 b python')
765 os.chdir(Str_pathCurrentDir)
766 print()
767 
768 # Create CRAB
769 
770 if Bool_CRAB:
771  os.chdir(Str_nameRun)
772  os.system('crab -create')
773  print()
774  # extract number of really created jobs
775  bool_found = False
776  file_logCRAB = file('crab'+Str_nameRun+'/log/crab.log')
777  for str_iLine in file_logCRAB.readlines():
778  if str_iLine.startswith('Total of ') and str_iLine.endswith(' jobs created.\n'):
779  bool_found = True
780  Int_jobsNew = int(str_iLine.split()[2])
781  break
782  file_logCRAB.close()
783  os.chdir(Str_pathCurrentDir)
784  if not bool_found:
785  print('> submitDQMOfflineCAF.py > could not extract number of jobs created by CRAB; check')
786  print(' %s' %(Str_pathInputFilesCAFCff))
787  print(' and modify manually, if necessary')
788  print()
789 
790 # recreate included CAF input files list according to number of created jobs, if necessary
791 
792 print('> submitDQMOfflineCAF.py > number of created jobs: %i' %(Int_jobsNew))
793 print()
794 if Int_jobsNew != Int_jobs:
795  file_inputFilesCAFCff = file(Str_pathInputFilesCAFCff, 'w')
796  file_inputFilesCAFCff.write('import FWCore.ParameterSet.Config as cms\n\nsource = cms.Source ("PoolSource",\n processingMode = cms.untracked.string( \'Runs\' ),\n fileNames = cms.untracked.vstring(\n')
797  for int_iJob in range(1,Int_jobsNew+1): # FIXME use number of CRAB jobs created
798  str_lineInput = Str_outpath + '/SiStripDQMOfflineGlobalRunCAF-' + Str_nameRun + '_' + str(int_iJob) + '.root'
799  if Bool_useCastor:
800  str_lineInput = 'rfio:' + str_lineInput
801  str_lineInput = ' \'' + str_lineInput + '\''
802  if int_iJob == Int_jobsNew:
803  str_lineInput += '\n'
804  file_inputFilesCAFCff.write(str_lineInput)
805  break
806  str_lineInput += ',\n'
807  file_inputFilesCAFCff.write(str_lineInput)
808  file_inputFilesCAFCff.write(' )\n)\n')
809  file_inputFilesCAFCff.close()
810 
811 # Submit jobs
812 
813 if LSTR_functionLetters[0] in Dict_arguments:
814  os.chdir(Str_nameRun)
815  if Bool_CRAB:
816  str_crabCommand = 'crab -submit -c crab' + Str_nameRun
817  print('> submitDQMOfflineCAF.py >')
818  print(' %s : %s' %(os.getcwd(),str_crabCommand))
819  os.system(str_crabCommand)
820  print()
821  time.sleep(5)
822  os.system('crab -status -c crab' + Str_nameRun)
823  else:
824  for int_iJob in range(Int_jobs):
825  str_nameJobDir = Str_nameRun + '_' + str(int_iJob).zfill(4)
826  os.chdir(str_nameJobDir)
827  os.chmod('SiStripDQMOfflineCAF.job',OCT_rwx_r_r)
828  str_batchCommand = 'bsub -q cmscaf SiStripDQMOfflineCAF.job'
829  print('> submitDQMOfflineCAF.py >')
830  print(' %s : %s' %(os.getcwd(),str_batchCommand))
831  os.system(str_batchCommand)
832  print()
833  os.chdir('../')
834  time.sleep(5)
835  os.system('bjobs -q cmscaf')
836  os.chmod('SiStripCAFHarvest.job',OCT_rwx_r_r)
837  os.chdir(Str_pathCurrentDir)
838 
839 # Send reminder email to submitter (not needed for CRAB)
840 
841 if LSTR_functionLetters[0] in Dict_arguments and not Bool_CRAB:
842  str_mailFrom = os.getenv('USER') + STR_mailServer
843  str_mailTo = [str_mailFrom,
844  'volker.adler@cern.ch',
845  'suchandra.dutta@cern.ch',
846  'domenico.giordano@cern.ch',
847  'vitaliano.ciulli@cern.ch']
848  str_mailSubject = 'Your SiStrip offline DQM shift on ' + str(datetime.date.today()) + ', run ' + Str_run
849  str_mailText = STR_mailTextOpener + Str_run + STR_mailText
850  str_mailMessage = """From: %s
851 To: %s
852 Subject: %s
853 
854 %s
855 """ % (str_mailFrom, ", ".join(str_mailTo), str_mailSubject, str_mailText)
856  server = smtplib.SMTP(STR_mailSmtp)
857  server.sendmail(str_mailFrom, str_mailTo, str_mailMessage)
858  server.quit()
std::vector< std::string_view > split(std::string_view, const char *)
def Func_MagConfig(float_magFieldMeasured)
Function Func_MagConfig(float_magFieldMeasured)
def Func_ExitUsage()
Function Func_ExitUsage()
def Func_MkDir(str_path)
Function Func_MkDir()
def replace(string, replacements)
S & print(S &os, JobReport::InputFile const &f)
Definition: JobReport.cc:66
def Func_Exit()
Function Func_Exit()
def Func_Usage()
Function Func_Usage()
T min(T a, T b)
Definition: MathUtil.h:58
static std::string join(char **cmd)
Definition: RemoteFile.cc:17
#define str(s)
def Func_ExitBool(int_index)
Function Func_ExitBool()