ATLAS Offline Software
Loading...
Searching...
No Matches
ReadFromCrestCompare.py
Go to the documentation of this file.
1#!/bin/env python3
2# Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3#
4# ReadFromCrestCompare.py
5# (Based on ReadFromCoolCompare.py, adapted for CREST)
6# Ekaterina Ramakoti 2026-05-21
7
8# Note: this is a low level tool to be used only for tests
9# It reads conditions from two CREST servers (or/and JSON files),
10# compares values and dumps to the file difference, if it is above
11# specified threshould
12#
13#=== examples of folder/tag names
14#folderPath = "/TILE/OFL02/CALIB/CES"
15#folderPath = "/TILE/OFL02/TIME/CHANNELOFFSET/PHY"
16#folderPath = "/TILE/OFL02/NOISE/SAMPLE"
17#tag = "RUN2-HLT-UPD1-01"
18#folderPath = "/TILE/ONL01/CALIB/CIS/LIN"
19#folderPath = "/TILE/ONL01/MUID"
20#folderPath = "/TILE/ONL01/FRAG1"
21#tag = ""
22#
23# if folder tag is full tag like TileOfl02CalibCisLin-RUN2-UPD4-23
24# or TILEONL01CALIBCES-HEAD folder path is not needed
25#==================================================
26
27from TileCalibBlobPython import TileCalibCrest
28from TileCalibBlobObjs.Classes import TileCalibUtils
29import os, sys
30from builtins import input
31os.environ['TERM'] = 'linux'
32
33#------------------------------- parse arguments and change defaults
34import argparse
35
36parser = argparse.ArgumentParser(
37 prog='ReadFromCrestCompare.py',
38 description='Read conditions from CREST server (or/and JSON files), compare values and dump differences above specified thresholds',
39 formatter_class=argparse.RawDescriptionHelpFormatter,
40 epilog="""
41Notes:
42- Conditions are compared using logical AND: both maxdiff AND maxdiffpercent must be present (both have to be TRUE) to print
43- If *2 parameters (run2, lumi2, folder2, tag2, schema2) are not given, values from primary parameters are used
44- For single-version folders, use empty tag: --tag=""
45
46Usage:
47 # Compare values in last IOV in two different tags
48 # tag name can be short, it'll be resolved to proper current tag
49 %(prog)s \\
50 --maxdiffpercent=0.01 \\
51 --folder=/TILE/OFL02/CALIB/CIS/LIN \\
52 --tag=UPD1 \\
53 --tag2=UPD4
54
55 # Compare CREST server vs JSON file
56 # for JSON file folder name and tag are not needed
57 %(prog)s \\
58 --maxdiff=100 \\
59 --run=500000 \\
60 --folder=/TILE/ONL01/CALIB/CES \\
61 --tag='' \\
62 --jsonfn2=tileCalib.json
63
64 # Compare two runs from same tag/schema
65 # folder name is not needed if tag is full tag
66 %(prog)s \\
67 --tag=TileOfl02CalibLasLin-RUN2-UPD4-26 \\
68 --maxdiffpercent=5.5 \\
69 --run=400000 \\
70 --run2=999999999
71 """
72)
73
74# primary parameters
75parser.add_argument('--run', '-r', type=int, default=999999999,
76 help='Run number for first comparison (default: 999999999)')
77parser.add_argument('--lumi', '-l', type=int, default=0,
78 help='Luminosity block for first comparison (default: 0)')
79parser.add_argument('--folder', '-f', dest='folder', default="/TILE/OFL02/CALIB/CES",
80 help='Folder path for first comparison (default: /TILE/OFL02/CALIB/CES)')
81parser.add_argument('--tag', '-t', default="RUN2-HLT-UPD1-01",
82 help='Tag name for first comparison (default: RUN2-HLT-UPD1-01)')
83parser.add_argument('--schema', '-s', default="CREST",
84 help='CREST URL or JSON file path for first comparison (default: CREST from env)')
85parser.add_argument('--jsonfn', '-j', default="none",
86 help='JSON file path for first comparison (overrides schema if file exists)')
87
88# secondary parameters (*2) - default to primary values if not specified
89parser.add_argument('--run2', '-r2', type=int, default=0,
90 help='Run number for second comparison (default: same as --run)')
91parser.add_argument('--lumi2', '-l2', type=int, default=-1,
92 help='Luminosity block for second comparison (default: same as --lumi)')
93parser.add_argument('--folder2', '-f2', default="none",
94 help='Folder path for second comparison (default: same as --folder)')
95parser.add_argument('--tag2', '-t2', default="none",
96 help='Tag name for second comparison (default: same as --tag)')
97parser.add_argument('--schema2', '-s2', default="none",
98 help='CREST URL or JSON file path for second comparison (default: same as --schema)')
99parser.add_argument('--jsonfn2', '-j2', default="none",
100 help='JSON file path for second comparison (use "same" to use same as --jsonfn)')
101
102# threshold parameters
103parser.add_argument('--maxdiff', type=float, default=-1.0,
104 help='Maximum absolute difference threshold (default: -1.0 = dump all)')
105parser.add_argument('--maxdiffpercent', type=float, default=-1.0,
106 help='Maximum percent difference threshold (default: -1.0 = dump all)')
107# other parameters
108parser.add_argument('--stdout', '-o', action='store_true',
109 help='Print differences to standard output (in addition to file)')
110
111args = parser.parse_args()
112
113# apply default logic for *2 parameters (can be modified from command line)
114run = args.run
115run2 = args.run2 if args.run2 != 0 else run
116lumi = args.lumi
117lumi2 = args.lumi2 if args.lumi2 >= 0 else lumi
118folderPath = args.folder
119folderPath2 = args.folder2 if args.folder2 != "none" else folderPath
120tag = args.tag
121tag2 = args.tag2 if args.tag2 != "none" else tag
122schema = args.schema
123schema2 = args.schema2 if args.schema2 != "none" else schema
124jsonfn = args.jsonfn
125jsonfn2 = args.jsonfn2 if args.jsonfn2 != "same" else jsonfn
126maxdiff = args.maxdiff
127maxdiffpercent = args.maxdiffpercent
128print_to_stdout = args.stdout
129
130if tag.upper().startswith('TILE'):
131 folderPath=''
132if tag2.upper().startswith('TILE'):
133 folderPath2=''
134
135if (jsonfn != 'none' and os.path.isfile(jsonfn)):
136 tag=''
137 folderPath=''
138 schema=''
139elif (schema != 'CREST' and os.path.isfile(schema)):
140 tag=''
141 folderPath=''
142if (jsonfn2 != 'none' and os.path.isfile(jsonfn2)):
143 tag2=''
144 folderPath2=''
145 schema2=''
146elif (schema2 != 'CREST' and os.path.isfile(schema2)):
147 tag2=''
148 folderPath2=''
149
150print("\n" + "="*65)
151print(" ReadFromCrestCompare - Configuration")
152print("="*65)
153print(f" {'Run/Lumi:':<14} 1st: run={run:<10} lumi={lumi:<6}")
154print(f" {' ':<14} 2nd: run={run2:<10} lumi={lumi2:<6}")
155print(f" {'Thresholds:':<14} maxdiff={maxdiff:<8} maxdiffpercent={maxdiffpercent}")
156print(f" {'Folder:':<14} {folderPath}")
157print(f" {'Folder2:':<14} {folderPath2}")
158print(f" {'Tag:':<14} {tag}")
159print(f" {'Tag2:':<14} {tag2}")
160print(f" {'Schema:':<14} {schema}")
161print(f" {'Schema2:':<14} {schema2}")
162print(f" {'JSON File:':<14} {jsonfn}")
163print(f" {'JSON File2:':<14} {jsonfn2}")
164print("="*65 + "\n")
165
166#===================================================================
167#====================== FILL DB parameters BELOW ===================
168#===================================================================
169#--- Read from CREST server or from local JSON file:
170
171from TileCalibBlobPython.TileCalibLogger import getLogger
172log = getLogger("ReadFromCrest")
173import logging
174log.setLevel(logging.DEBUG)
175
176#==================================================
177
178if jsonfn != 'none' and os.path.isfile(jsonfn):
179 db = jsonfn
180else:
181 db = schema
182
183if jsonfn2 != 'none' and os.path.isfile(jsonfn2):
184 db2 = jsonfn2
185else:
186 db2 = schema2
187
188# f=open('output.ascii', 'w')
189f=open('output_crest.ascii', 'w')
190if run2!=run and tag2==tag and folderPath2==folderPath and ("/TIME" in folderPath or "TIME" in tag.upper()):
191 fd=open('from_%d_to_%d.dif'%(run2,run), 'w')
192 writedif=True
193else:
194 writedif=False
195
196try:
197 log.info("Connecting to DB1: schema=%s, folder=%s, tag=%s, run=%s, lumi=%s",
198 db, folderPath, tag, run, lumi)
199 blobReader = TileCalibCrest.TileBlobReaderCrest(db, folderPath, tag, run, lumi)
200 log.info("Connecting to DB2: schema=%s, folder=%s, tag=%s, run=%s, lumi=%s",
201 db2, folderPath2, tag2, run2, lumi2)
202 blobReader2 = TileCalibCrest.TileBlobReaderCrest(db2, folderPath2, tag2, run2, lumi2)
203except Exception as e:
204 log.error("Initialization failed: %s", e)
205 sys.exit(1)
206
207#=== get drawer with status at given run
208ros = 1 # ros 0 sometimes contains obsolete header !
209drawer = 0
210log.info("Initializing for run1 %d lumi %d run2 %d lumi2 %d maxdiff %f maxdiffpercent %f", run, lumi, run2, lumi2, maxdiff,maxdiffpercent)
211log.info("Comment1: %s", blobReader.getComment((run,lumi)))
212log.info("Comment2: %s", blobReader2.getComment((run2,lumi2)))
213
214flt=None
215r=5
216d=0
217while not flt:
218 d-=1
219 if d<0:
220 r-=1
221 if r<0:
222 log.error("No valid drawers in first database")
223 sys.exit()
225 flt = blobReader.getDrawer(r, d, (run,lumi), False, False)
226#flt.dump()
227ot = flt.getObjType()
228ov = flt.getObjVersion()
229os = flt.getObjSizeByte()//4
230no = flt.getNObjs()
231nc = flt.getNChans()
232ng = flt.getNGains()
233
234flt2=None
235r=5
236d=0
237while not flt2:
238 d-=1
239 if d<0:
240 r-=1
241 if r<0:
242 log.error("No valid drawers in second database")
243 sys.exit()
245 flt2 = blobReader2.getDrawer(r, d, (run2,lumi2), False, False)
246ot2 = flt2.getObjType()
247os2 = flt2.getObjSizeByte()//4
248
249if (os != os2) or (ot != ot2):
250 log.error("Object sizes (%s vs %s) or types (%s vs %s) are different", os, os2, ot, ot2)
251 answ=input(' continue anyway? (y/n)')
252 if (answ != 'y'):
253 sys.exit()
254
255v =[]
256v2=[]
257for ind in range(0,os):
258 v.append(0)
259 v2.append(0)
260
261f.write("Command line parameters used: \n %s \n" % sys.argv[1:])
262f.write("---- Object header for ros=%d drawer=%d \n" % (r,d))
263f.write("ObjType : %d \n" % ot)
264f.write("ObjVersion : %d \n" % ov)
265f.write("ObjSize[4bytes]: %d \n" % os)
266f.write("NObjs : %d \n" % no)
267f.write("NChannels : %d \n" % nc)
268f.write("NGains : %d \n" % ng)
269
270answ='n'
271#=== get value for a gived channel
272for ros in range(0,5):
273 for mod in range(0, min(64,TileCalibUtils.getMaxDrawer(ros))):
275 #log.info("ros %d, drawer %s at run %d" % (ros, modName, run))
276 flt = blobReader.getDrawer(ros, mod,(run,lumi), False, False)
277 flt2 = blobReader2.getDrawer(ros, mod,(run2,lumi2), False, False)
278 if flt and flt2:
279 osc = flt.getObjSizeByte()//4
280 os2c = flt2.getObjSizeByte()//4
281 oscMax = max(osc,os2c)
282 if (((os != osc) or (os2 != os2c)) and answ != 'y'):
283 if (ros==0 and osc==os2c and os==os2):
284 log.warning("Object sizes are different for last drawer in DB (%s) and default drawer %s (%s)", os, modName, osc)
285 else:
286 log.error("Object sizes are different for last drawer in DB (%s and %s) and drawer %s (%s and %s)", os, os2, modName, osc, os2c)
287 answ=input(' continue anyway? (y/n)')
288 if (answ != 'y'):
289 sys.exit()
290 else:
291 for ind in range(0,oscMax):
292 v.append(0)
293 v2.append(0)
294
295
296 for chn in range(TileCalibUtils.max_chan()):
297 chnName = " %2i" % chn
298 for adc in range(ng):
299 for ind in range(0,oscMax):
300 if (ind<osc):
301 v[ind] = flt.getData(chn, adc, ind)
302 if (ind<os2c):
303 v2[ind] = flt2.getData(chn, adc, ind)
304 dv12 = v[ind] - v2[ind]
305 if v2[ind] == 0:
306 if v[ind] == 0:
307 dv12percent=0
308 else:
309 dv12percent=dv12*100./v[ind]
310 else:
311 dv12percent=dv12*100./v2[ind]
312 #print ( modName, ' chann ', repr(chn), ' adc ', repr(adc), ' ind ', repr(ind), ' val1 ', repr(v[ind]),' val2 ', repr(v2[ind]), ' diff ', repr(dv12), 'percent ', repr(dv12percent))
313 if abs(dv12) > maxdiff and abs(dv12percent) > maxdiffpercent:
314 if ot==30: # integers
315 line = '%s chann %2d adc %d ind %d val1 %d val2 %d diff %d' % (modName,chn,adc,ind,v[ind],v2[ind],dv12)
316 elif ot==20: # bad channels
317 line = '%s chann %2d adc %d ind %d val1 %s val2 %s diff %f' % (modName,chn,adc,ind,hex(int(v[ind])),hex(int(v2[ind])),dv12)
318 else: # floats
319 line = '%s chann %2d adc %d ind %d val1 %.4f val2 %.4f diff %.4f %.2f%%' % (modName,chn,adc,ind,v[ind],v2[ind],dv12,dv12percent)
320 if writedif and adc==0 and ind==0:
321 fd.write("%s ch %2d %.4f\n" % (modName,chn,dv12))
322
323 f.write(line + '\n')
324 if print_to_stdout:
325 print(line)
326
327#=== close output file
328f.close()
329if writedif:
330 fd.close()
void print(char *figname, TCanvas *c1)
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41
static std::string getDrawerString(unsigned int ros, unsigned int drawer)
Return the drawer name, e.g.
static unsigned int max_chan()
Python compatibility function.
static unsigned int getMaxDrawer(unsigned int ros)
Returns the maximal channel number for a given drawer.