CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
roll_playback.py
Go to the documentation of this file.
1 #!/usr/bin/env python2
2 
3 # TODO list
4 # - handle the situation where no .jsn of data files are found in the source directory in a better way
5 # - automatically determine from which LS to start (currently this is hard-coded to 1)
6 # - when dealing with file I/O use the python "file scope"
7 
8 import os
9 import sys
10 import time
11 import re
12 import shutil
13 import json
14 
15 dat_source = '/fff/ramdisk/playback_files/run233238/'
16 pb_source = '/fff/ramdisk/playback_files/run233238/'
17 calib_source = '/fff/ramdisk/playback_files/run233238/'
18 
19 destination = '/fff/ramdisk'
20 lumi_len = 23 # in seconds
21 run_padding = 6
22 lumi_padding = 4
23 files_copied_buffer_len = 60 # the number of file to keep in the ramdisk
24 run_switch_interval = 90 # in seconds
25 
26 lumi_skip_length = 10
27 
28 file_types = { 'general_files': {'extension':'.dat', 're_pattern':r'run([0-9]+)_ls([0-9]+)_streamDQM_mrg-[A-Za-z0-9-]+\.jsn'},
29  'hlt_pb_files': {'extension':'.pb', 're_pattern':r'run([0-9]+)_ls([0-9]+)_streamDQMHistograms_mrg-[A-Za-z0-9-]+\.jsn'},
30  'calib_files': {'extension':'.dat', 're_pattern':r'run([0-9]+)_ls([0-9]+)_streamDQMCalibration_mrg-[A-Za-z0-9-]+\.jsn'}, }
31 
32 
33 def sanity_check(source, file_info):
34  jsn_files = []
35  data_files = []
36  run_number = None
37 
38  # find the json files that match the given pattern
39  files = os.listdir(source)
40  jsn_pattern = re.compile(file_info['re_pattern'])
41  jsn_files = sorted(filter(lambda x: jsn_pattern.match(x), files))
42 
43  # check if the data files exist
44  jsn_files_tobe_removed = []
45  for jsn_file in jsn_files:
46  data_file = jsn_file.replace('.jsn', file_info['extension'])
47  if os.path.exists(source + '/' + data_file):
48  data_files.append(data_file)
49  else:
50  print('The data file {0} does NOT exist! Removing the corresponding json file.'.format(data_file))
51  jsn_files_tobe_removed.append(jsn_file)
52 
53  # remove the json files that don't have corresponding data file
54  jsn_files = [x for x in jsn_files if x not in jsn_files_tobe_removed]
55 
56  run_number = int(jsn_pattern.match(jsn_files[0]).group(1))
57  # check for run_number consistency
58  for i in range(1,len(jsn_files)):
59  run_number_current = int(jsn_pattern.match(jsn_files[i]).group(1))
60  if run_number_current != run_number:
61  print('Non consistent run numbers: "{0}" - expected, "{1}" - found'.format(run_nummber, run_nummber_current))
62  print('\t "{0}" - will be used as a run number'.format(run_nummber))
63 
64  return True, jsn_files, data_files, run_number
65 
66 
67 def copy_next_lumi(jsn_file, file, run_number, current_lumi, source, destination, copy_file=True):
68  index = current_lumi % len(jsn_file)
69 
70  # copy the file
71  input_fn = source + '/' + file
72  output_fn = file
73  run_start = output_fn.find('run') + 3
74  output_fn = output_fn[:run_start] + str(run_number).zfill(run_padding) + output_fn[run_start + run_padding:]
75  lumi_start = output_fn.find('ls') + 2
76  output_fn = destination + '/' + output_fn[:lumi_start] + str(current_lumi).zfill(lumi_padding) + output_fn[lumi_start + lumi_padding:]
77  if copy_file:
78  os.link(input_fn, output_fn) # instead of copying the file create a hard link
79  print(input_fn + ' -> ' + output_fn)
80 
81  # load the original json contents
82  input_jsn_fn = source + '/' + jsn_file
83  input_jsn = open(input_jsn_fn, 'r')
84  jsn_data = json.load(input_jsn)
85  input_jsn.close()
86 
87  # generate the output jsn file name
88  output_jsn_fn = jsn_file
89  run_start = output_jsn_fn.find('run') + 3
90  output_jsn_fn = output_jsn_fn[:run_start] + str(run_number).zfill(run_padding) + output_jsn_fn[run_start + run_padding:]
91  lumi_start = output_jsn_fn.find('ls') + 2
92  output_jsn_fn = destination + '/' + output_jsn_fn[:lumi_start] + str(current_lumi).zfill(lumi_padding) + output_jsn_fn[lumi_start + lumi_padding:]
93 
94  # modify the json file contents
95  jsn_data['data'][3] = output_fn[output_fn.rfind('/')+1:]
96 
97  # create the outpuf jsn file
98  output_jsn = open(output_jsn_fn, 'w')
99  output_jsn.write(json.dumps(jsn_data, indent=4))
100  output_jsn.close()
101 
102  print(input_jsn_fn + ' -> ' + output_jsn_fn)
103 
104  return (output_jsn_fn, output_fn) if copy_file else (output_jsn_fn, )
105 
106 
107 if __name__ == '__main__':
108  dat_dir_ok, dat_jsn_files, dat_files, run_number = sanity_check(dat_source, file_types['general_files'])
109  pb_dir_ok, pb_jsn_files, pb_files, pb_run_number = sanity_check(pb_source, file_types['hlt_pb_files'])
110  calib_dir_ok, calib_jsn_files, calib_files, calib_run_number = sanity_check(calib_source, file_types['calib_files'])
111 
112  if dat_dir_ok and pb_dir_ok and calib_dir_ok:
113  if (run_number != pb_run_number) or (run_number != calib_run_number):
114  print('The DAT run number differs from the PB or Calibration run number.')
115  print('"{0}" is going to be used as a run number. \n'.format(run_number))
116 
117  run_length = len(dat_jsn_files)
118  lumi_skip_at = None
119  copy_file = True
120  if run_length > 25:
121  lumi_skip_at = run_length/10
122 
123  files_copied = []
124 
125  while True:
126  global_runfile = destination + '/' + '.run{0}.global'.format(str(run_number).zfill(run_padding))
127  gf = open(global_runfile, 'w')
128  gf.write('run_type = cosmic_run')
129  gf.close()
130 
131  output_dir = destination + '/' + 'run' + str(run_number).zfill(run_padding)
132  os.mkdir(output_dir)
133 
134  time.sleep(1) # a hack in order python inotify to work correctly
135 
136  current_lumi = 1
137  for i in range(len(dat_jsn_files)):
138  files_copied += copy_next_lumi(dat_jsn_files[i], dat_files[i], run_number, current_lumi, dat_source, output_dir, copy_file)
139 
140  j = i%len(pb_jsn_files)
141  files_copied += copy_next_lumi(pb_jsn_files[j], pb_files[j], run_number, current_lumi, pb_source, output_dir, copy_file)
142 
143  k = i%len(calib_jsn_files)
144  files_copied += copy_next_lumi(calib_jsn_files[k], calib_files[k], run_number, current_lumi, calib_source, output_dir, copy_file)
145 
146  if not lumi_skip_at or (current_lumi != lumi_skip_at): current_lumi += 1
147  else: current_lumi += lumi_skip_length
148 
149  if not lumi_skip_at or (current_lumi < 2*lumi_skip_at) or (current_lumi > 2*lumi_skip_at+lumi_skip_length): copy_file = True
150  else: copy_file = False
151 
152  time.sleep(lumi_len)
153 
154  # clear some of the old files
155  while files_copied_buffer_len < len(files_copied):
156  os.remove(files_copied.pop(0))
157 
158  print('')
159 
160  EoRfile = output_dir + '/' + 'run' + str(run_number).zfill(run_padding) + '_ls0000_EoR.jsn' # create the EoR file
161  open(EoRfile, 'w').close()
162  run_number += 1
163  print('\n\n')
164  time.sleep(run_switch_interval)
165 
std::string print(const Track &, edm::Verbosity=edm::Concise)
Track print utility.
Definition: print.cc:10
tuple group
Definition: watchdog.py:82