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