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