CMS 3D CMS Logo

scoutingToRaw.py
Go to the documentation of this file.
1 #!/bin/env python3
2 
3 import struct
4 import os,sys
5 import json
6 import shutil
7 
8 os.umask(0)
9 
10 #struct muon{
11 # uint32_t f;
12 # uint32_t s;
13 #};
14 
15 #struct block{
16 # uint32_t bx;
17 # uint32_t orbit;
18 # muon mu[16];
19 #};
20 
21 #class masks:
22 # phiext = 0x3ff
23 # pt = 0x1ff
24 # qual = 0xf
25 # etaext = 0x1ff
26 # etaextv = 0xff
27 # etaexts = 0x100
28 # iso = 0x3
29 # chrg = 0x1
30 # chrgv = 0x1
31 # index = 0x7f
32 # phi = 0x3ff
33 # eta = 0x1ff
34 # etav = 0xff
35 # etas = 0x100
36 # phiv = 0x1ff
37 # phis = 0x200
38 # sv = 0x3
39 
40 #class shifts:
41 # phiext = 0
42 # pt = 10
43 # qual = 19
44 # etaext = 23
45 # iso = 0
46 # chrg = 2
47 # chrgv = 3
48 # index = 4
49 # phi = 11
50 # eta = 21
51 # rsv = 30
52 
53 #class gmt_scales:
54 # pt_scale = 0.5
55 # phi_scale = 2.*M_PI/576.
56 # eta_scale = 0.0870/8 #9th MS bit is sign
57 # phi_range = M_PI
58 
59 
60 #need to read this to find orbit ("event") boundary and calculate size per orbit
62  bxmatch = 32;
63  mAcount = 16;
64  orbitmatch = 8;
65  mBcount = 0;
66 
68  bxmatch = 0xff << header_shifts.bxmatch;
69  mAcount = 0xf << header_shifts.mAcount;
70  orbitmatch = 0xff << header_shifts.orbitmatch;
71  mBcount = 0xf
72 
73 
74 #new V2 FRD file header (32 bytes)
76  ver_id = "RAW_0002".encode() # 64 (offset 0B)
77  header_size = 32 #16 (offset 8B)
78  data_type = 20 #16 (offset 10)
79  event_count = 0 #32 (offset 12B)
80  run_number = 0 #32 (offset 16B)
81  lumisection = 0 #32 (offset 20B)
82  file_size = 0 #64 (offset 24B)
83 
84 
85 def parseMuonScoutingRawFile(infilepath, outdir, rn_override, maxorbits):
86 
87  if infilepath != 'stdin':
88  fin = open(infilepath,'rb')
89  else:
90  fin = sys.stdin.buffer
91 
92  #sys.stdout.flush()
93 
94  #orbit count per file
95  orbitcount=0
96  #total
97  orbitcount_total=0
98 
99  last_ls = 0
100 
101  orbit_data = bytes()
102  orbit_nr = 0
103  orbit_size = 0
104  flags = 0
105  c_crc32c = 0
106 
107  #ls = 1
108  #event header (FRD format) const
109  version = 6
110 
111  #files
112  fout = None
113  if infilepath != 'stdin':
114  fin = open(infilepath,'rb')
115  else:
116  fin = sys.stdin.buffer
117 
118 
119  #write header before closing the file
120  def update_header():
121  nonlocal orbitcount
122  nonlocal last_ls
123  h = frd_file_header_v2()
124  h.event_count = orbitcount
125  h.run_number = rn_override
126  h.lumisection = last_ls
127  h.file_size = fout.tell()
128  fout.seek(0, 0)
129  fout.write(frd_file_header_v2.ver_id)
130  fout.write(struct.pack('H',h.header_size))
131  fout.write(struct.pack('H',h.data_type))
132  fout.write(struct.pack('I',h.event_count))
133  fout.write(struct.pack('I',h.run_number))
134  fout.write(struct.pack('I',h.lumisection))
135  fout.write(struct.pack('Q',h.file_size))
136 
137  orbitcount = 0
138  print(h.ver_id, h.header_size, h.data_type, h.event_count, h.lumisection, h.file_size)
139 
140 
141  #write orbit when next one is detected or file is closed
142  def write_orbit():
143  nonlocal orbit_size
144  nonlocal orbit_data
145  if not orbit_size:
146  return
147 
148  #print(fout.tell(), struct.pack('H',version))
149  fout.write(struct.pack('H',version)) #could be 8 bytes
150  fout.write(struct.pack('H',flags)) #could be 8 bytes
151  fout.write(struct.pack('I',rn_override)) #run
152  #fout.write(struct.pack('I',ls)) #ls
153  fout.write(struct.pack('I',last_ls)) #ls
154  fout.write(struct.pack('I',orbit_nr)) #eid (orbit number, 32-bit)
155  fout.write(struct.pack('I',orbit_size)) #payload size
156  fout.write(struct.pack('I',c_crc32c)) #payload checksum (not used)
157  fout.write(orbit_data)
158 
159  orbit_data = bytes()
160  orbit_size = 0
161 
162  def writeout_close():
163  write_orbit()
164  update_header()
165  fout.close()
166  orbit_nr = 0
167 
168  #read loop
169  while True:
170 
171  #check if exceeded max orbits specified
172  if orbitcount_total > maxorbits:
173  print(f"finish: {orbitcount_total-1}/{maxorbits} orbits")
174  writeout_close()
175 
176  if infilepath != 'stdin':
177  fin.close()
178  sys.exit(0)
179 
180  try:
181  h_raw = fin.read(4)
182  bxmatch = struct.unpack('B', h_raw[3:4])[0]
183  mAcount = struct.unpack('B', h_raw[2:3])[0]
184  orbitmatch = struct.unpack('B', h_raw[1:2])[0]
185  mBcount = struct.unpack('B', h_raw[0:1])[0]
186 
187  #print("bxmatch", bxmatch, "mA", mAcount, "orbitmatch", orbitmatch, "mB", mBcount)
188 
189  bx_raw = fin.read(4)
190  bx = struct.unpack('i', bx_raw)[0]
191  #print("bx",bx)
192  orbit_raw = fin.read(4)
193  orbit = struct.unpack('i', orbit_raw)[0]
194 
195  new_ls = orbit >> 18
196 
197  if new_ls > last_ls:
198  #open a new output file if crossing LS boundary or on first orbit
199  if last_ls:
200  write_orbit()
201  update_header()
202  fout.close()
203  orbitcount = 0
204 
205  last_ls = new_ls
206  fout = open(os.path.join(outdir, f'run{rn_override}_ls{str(new_ls).zfill(4)}_index000000.raw') ,'wb')
207  #empty file header, will be updated later
208  fout.write(frd_file_header_v2.ver_id)
209 # fout.write(bytes(16))
210  fout.write(bytes(24))
211 
212  read_len = 8*(mAcount+mBcount)
213  mu_blk = fin.read(8*(mAcount+mBcount))
214  if len(mu_blk) != read_len:
215  print('incomplete read')
216  sys.exit(1)
217 
218  if not orbit_nr or orbit != orbit_nr:
219  #received new orbit, write previous one
220  if orbit_nr:
221  write_orbit()
222 
223  #should not decrease:
224  if orbit < orbit_nr:
225  orbit_count = -1
226  print("got smaller orbit than earlier!")
227  sys.exit(1)
228 
229  print("new orbit", orbit)
230  orbit_nr = orbit
231 
232  #per LS file counter:
233  orbitcount += 1
234  #total counter:
235  orbitcount_total += 1
236 
237  #update orbit size and data variables
238  orbit_size += 12 + read_len
239  orbit_data += (h_raw + bx_raw + orbit_raw) + mu_blk
240 
241  except Exception as ex:
242  #reached premature end of the file?
243  print(f"exception: {ex}")
244  #writeout_close()
245  #if infilepath != 'stdin':
246  # fin.close()
247  sys.exit(1)
248 
249  #print count," : ",version,run,lumi,eid,esize,crc32c,"override id/ls/run:",count,1,rn_override
250  #lumi=1
251 
252 if len(sys.argv) < 5:
253  print("parameters: input file (or stdin), output directory, run number (use same as input file), orbits to write")
254 else:
255  parseMuonScoutingRawFile(sys.argv[1], sys.argv[2], int(sys.argv[3]), int(sys.argv[4]))
256 
257 
258 
259 
def parseMuonScoutingRawFile(infilepath, outdir, rn_override, maxorbits)
void print(TMatrixD &m, const char *label=nullptr, bool mathematicaFormat=false)
Definition: Utilities.cc:47
def encode(args, files)