File indexing completed on 2023-03-17 10:44:28
0001
0002
0003
0004
0005 from __future__ import print_function
0006 import os,datetime, pickle
0007 def GetLogTimestamps(ManualO2Ologfilename):
0008 """
0009 This function opens the ManualO2O log chosen, and it prints out the Tmin/Tmax intervals
0010 for the individual O2O jobs that were run.
0011 This information can in turn be used with the function GetLogInfoByTimeStamp,
0012 to extract from the log the (DEBUG) information only from the wanted time interval.
0013 """
0014 ManualO2Olog=open(ManualO2Ologfilename,'r')
0015 LinesCounter=0
0016 IOVCounter=1
0017 TmaxDict={}
0018 for line in ManualO2Olog:
0019 LinesCounter+=1
0020 if 'Tmin:' in line:
0021 Tmin=line.split(':')[1].strip()
0022 if 'Tmax:' in line:
0023 Tmax=line.split(':')[1].strip()
0024
0025
0026
0027 print("%s- Tmin: %s and Tmax: %s (number log lines %s)"%(IOVCounter,Tmin,Tmax,LinesCounter))
0028
0029 if Tmax not in ListOfTmax.keys():
0030 TmaxDict.update({Tmax:LinesCounter})
0031 else:
0032 print("This Tmax (%s) seems to be duplicated!!!"%Tmax)
0033 LinesCounter=0
0034 IOVCounter+=1
0035 ManualO2Olog.close()
0036 return TmaxDict
0037
0038
0039 def GetLogInfoByTimeStamp(ManualO2Ologfilename,StartTime,StopTime):
0040 """
0041 This function takes a ManualO2Ologfilename, a start and a stop timestamps (that should be
0042 in the "YYYY M D H M S" format, e.g. Tmin: "2010 8 27 10 0 0 0",Tmax: "2010 8 27 11 0 0 0",
0043 and it parses the given logfile to just print out the lines relevant to the given timestamp.
0044 """
0045
0046 ManualO2Olog=open(ManualO2Ologfilename,'r')
0047
0048 PrintLines=False
0049 WantedLines=[]
0050 for line in ManualO2Olog:
0051 if 'Tmax:' in line and StopTime in line:
0052 PrintLines=True
0053 if PrintLines:
0054 if 'Tmin:' in line:
0055 break
0056 else:
0057 print(line.strip())
0058 WantedLines.append(line)
0059 ManualO2Olog.close()
0060 return WantedLines
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118 def GetQueryResults(ManualO2Ologfilename):
0119 """
0120 This function takes a ManualO2Ologfilename,
0121 and if it was run with the debug option True,
0122 it extracts all the query results.
0123 It uses StartTime/StopTime to identify the interval of the query (i.e. the ManualO2O.py running)
0124 and uses the tuple (StartTime,StopTime) as a key, as stores the results rows as a list.
0125 It returns the QueryResults dictionary that has for keys the (Tmin,Tmax) tuple, and as values lists of rows,
0126 where the rows are dictionaries with 3 keys:
0127 {
0128 'change_date':datetime.datetime,
0129 'actual_status':int,
0130 'dpname':str
0131 }
0132 The idea is that any massaging of this information is done later, while this function returns the query results in bulk.
0133 """
0134 print("Parsing file %s to extract query results"%ManualO2Ologfilename)
0135
0136 ManualO2Olog=open(ManualO2Ologfilename,'r')
0137
0138 Tmin=""
0139 Tmax=""
0140 ReadRows=False
0141 QueryResultsDict={}
0142 for line in ManualO2Olog:
0143 if 'Tmin:' in line:
0144 if Tmin=="":
0145 Tmin=datetime.datetime(*[int(x) for x in (line.split(':')[1].strip()).split()])
0146 else:
0147 Tmin=Tmax
0148 if 'Tmax:' in line:
0149 Tmax=datetime.datetime(*[int(x) for x in (line.split(':')[1].strip()).split()])
0150
0151
0152
0153
0154 if (Tmin,Tmax) not in QueryResultsDict.keys():
0155 QueryResultsDict.update({(Tmin,Tmax):[]})
0156 else:
0157 print("This Tmax (%s) seems to be duplicated!!!"%Tmax)
0158 if "Dumping all query results" in line:
0159 ReadRows=True
0160 if "Finished dumping query results" in line:
0161 NumOfRows=int(line.split(",")[1].split()[0])
0162 ReadRows=False
0163
0164
0165 if ReadRows:
0166 Row={}
0167 RowTokens=line.split(",")
0168 for token in RowTokens:
0169 if 'CHANGE_DATE' in token:
0170 try:
0171
0172
0173
0174
0175 changeDate=datetime.datetime.strptime(token[token.index(":")+2:-1],"%Y/%m/%d %H:%M:%S.%f")
0176
0177
0178
0179
0180
0181
0182
0183
0184 deltaTimezone=datetime.timedelta(seconds=7200)
0185 Row.update({'change_date':changeDate+deltaTimezone})
0186 except:
0187 print("WEIRD!\n Timestamp had a format YYYY/MM/DD HH:MM:0SS.millisecond (extra 0 tabbing for seconds!)")
0188 print(line)
0189
0190
0191
0192
0193 changeDate=datetime.datetime.strptime(token[token.index(":")+2:-1],"%Y/%m/%d %H:%M:0%S.%f")
0194
0195
0196
0197
0198
0199
0200
0201
0202 deltaTimezone=datetime.timedelta(seconds=7200)
0203 Row.update({'change_date':changeDate+deltaTimezone})
0204 if 'ACTUAL_STATUS' in token:
0205 Row.update({'actual_status':int(token[token.index(":")+2:-1])})
0206 if 'DPNAME' in token:
0207 Row.update({'dpname':token[token.index(":")+2:-2]})
0208 if len(Row)>0:
0209 QueryResultsDict[(Tmin,Tmax)].append(Row)
0210 ManualO2Olog.close()
0211 return QueryResultsDict
0212
0213 class TrkVoltageStatus:
0214 """
0215 #How about we make a class and instantiate an object TrackerVoltageStatus that we update at each row:
0216 #1-initialize it with a list of detID (from the most complete maps) OFF and ON (the masked ones):
0217 #2-Has a member history, a dictionary, with keeps, by timestamp (key) a list of detIDs with their channel 0,1,2,[3] status (to decide later if we need to already handle here the checks that
0218 # a-channel 0==1, for example by having a list of detIDs that do not have matching LV channels statuses (easy to check later, for sure it will be not empty during little transition IOVs due to different sub-second timing... we could introduce deadbands later)
0219 # b-a LV ON/OFF bit
0220 # c-a HV ON/OFF bit
0221 # d-add extra (VMON, V0_SETTINGS) info in the query?
0222 # e-add the power group turning off info in the query to check the effect
0223 # f-add a RAMPING UP/DOWN flag on top of the conventional O2O ON/OFF?
0224 #3-define an update(row) method that for each row takes the timestamp:
0225 # a-if timestamp already exist, updates the channel status of the relevant detIDs contained
0226 # b-if timestamp does not exist, creates an entry for it carrying over the information for the relevant detIDs from previous timestamp and update it with the information in the row
0227 #4-define a getVoltageHistory(start,end) method to dump the list of IOVs, and for each IOV dump a list with the detIDs and their LV/HV status, the number of LV OFF modules and HV OFF modules, (check that there is no module with LV OFF and HV ON... basic check can be done at the update level)
0228 """
0229 import datetime,sys,copy
0230 def __init__(self,detIDPSUmapfilename="map.txt",mask_mapfilename="mask_map.txt",DetIDAliasFile="StripDetIDAlias.pkl",startTime=datetime.datetime.now(),debug=False):
0231 """Initialize the object with a timestamp for the start time of the query (defaults to datetime.datetime.now()) and a list of modules OFF and ON depending on masking map (for now all OFF)"""
0232 self.debug=debug
0233 try:
0234 mapfile=open(detIDPSUmapfilename,'r')
0235 maplines=mapfile.readlines()
0236 mapfile.close()
0237
0238 self.detIDs=[int(line.split()[0]) for line in maplines]
0239
0240
0241
0242 if len(list(set(self.detIDs)))!=15148:
0243 print("There is an issue with the map provided: not reporting 15148 unique detIDs!")
0244
0245
0246
0247
0248
0249 self.PSUChannelListed=[line.split()[1] for line in maplines]
0250
0251 self.PSUs=list(set([PSUChannel[:-10] for PSUChannel in self.PSUChannelListed]))
0252
0253 if len(self.PSUs)!=1944:
0254 print("There is an issue with the map provided: not reporting 1944 unique Power Supplies!")
0255
0256
0257 self.PSUChannels=[]
0258 for PSU in self.PSUs:
0259 self.PSUChannels.append(PSU+"channel000")
0260 self.PSUChannels.append(PSU+"channel001")
0261 self.PSUChannels.append(PSU+"channel002")
0262 self.PSUChannels.append(PSU+"channel003")
0263
0264
0265 try:
0266 maskfile=open(mask_mapfilename,'r')
0267 self.masked_detIDs=[int(detID.rstrip()) for detID in maskfile]
0268 maskfile.close()
0269 except:
0270 self.masked_detIDs=[]
0271 print("No mask map was provided, assuming to start from a complete Tracker OFF state")
0272 try:
0273 DetIDAlias=open(DetIDAliasFile,"rb")
0274 DetIDAliasDict=pickle.load(DetIDAlias)
0275 DetIDAlias.close()
0276 self.DetIDAliasDict=DetIDAliasDict
0277 except:
0278 self.DetIDAliasDict={}
0279 print("No valid detID-Alias map pickle file was provided!")
0280 print("The TkrVoltageStatus object could not be initialized properly!")
0281 print("Please use an existing detIDPSUChannel mapfilename as argument!")
0282 sys.exit()
0283 except:
0284 print("Could not find detID-PSUchannel map to initialize the detIDs")
0285 print("The TkrVoltageStatus object could not be initialized properly! Please use an existing detIDPSUChannel mapfilename as argument!")
0286 sys.exit()
0287
0288
0289 self.DetIDPSUmap={}
0290 for detID in self.detIDs:
0291 self.DetIDPSUmap.update({detID:self.PSUChannelListed[self.detIDs.index(detID)]})
0292
0293 self.PSUDetIDmap={}
0294
0295
0296
0297
0298
0299
0300
0301
0302 for PSUChannel in self.PSUChannels:
0303 if PSUChannel.endswith("0") or PSUChannel.endswith("1"):
0304 self.PSUDetIDmap.update({PSUChannel:[detid for detid in self.DetIDPSUmap.keys() if PSUChannel[:-3] in self.DetIDPSUmap[detid]]})
0305 else:
0306 self.PSUDetIDmap.update({PSUChannel:[detid for detid in self.DetIDPSUmap.keys() if (PSUChannel in self.DetIDPSUmap[detid])]})
0307
0308
0309 self.PSUDetIDUnmappedMap={}
0310 UnmappedPSUs=list(set([psuchannel[:-10] for psuchannel in self.DetIDPSUmap.values() if psuchannel.endswith("000")]))
0311 self.PSUDetIDCrosstalkingMap={}
0312 CrosstalkingPSUs=list(set([psuchannel[:-10] for psuchannel in self.DetIDPSUmap.values() if psuchannel.endswith("999")]))
0313 for PSU in self.PSUs:
0314 if PSU in UnmappedPSUs:
0315 self.PSUDetIDUnmappedMap.update({PSU:[detid for detid in self.DetIDPSUmap.keys() if (self.DetIDPSUmap[detid].endswith("000") and PSU in self.DetIDPSUmap[detid])]})
0316 if PSU in CrosstalkingPSUs:
0317 self.PSUDetIDCrosstalkingMap.update({PSU:[detid for detid in self.DetIDPSUmap.keys() if (self.DetIDPSUmap[detid].endswith("999") and PSU in self.DetIDPSUmap[detid])]})
0318
0319
0320 self.UnmappedPSUChannelStatus={}
0321
0322 for PSU in self.PSUDetIDUnmappedMap.keys():
0323 self.UnmappedPSUChannelStatus.update({PSU+"channel002":0})
0324 self.UnmappedPSUChannelStatus.update({PSU+"channel003":0})
0325 self.CrosstalkingPSUChannelStatus={}
0326
0327 for PSU in self.PSUDetIDCrosstalkingMap.keys():
0328 self.CrosstalkingPSUChannelStatus.update({PSU+"channel002":0})
0329 self.CrosstalkingPSUChannelStatus.update({PSU+"channel003":0})
0330
0331
0332
0333
0334 self.startTime=startTime
0335
0336 self.PSUChannelHistory={startTime:range(len(self.PSUChannels))}
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348 for detID in self.masked_detIDs:
0349
0350
0351 self.PSUChannelHistory[startTime].remove(index(detIDPSUmap[detid][-1]+'0'))
0352 self.PSUChannelHistory[startTime].remove(index(detIDPSUmap[detid][-1]+'1'))
0353 self.PSUChannelHistory[startTime].remove(index(detIDPSUmap[detid][-1]+'2'))
0354 self.PSUChannelHistory[startTime].remove(index(detIDPSUmap[detid][-1]+'3'))
0355
0356
0357
0358
0359
0360
0361
0362 def updateO2OQuery(self,row):
0363 """Function to automatically handle the updating the of history dictionary
0364 with the results rows from the O2O query (PSUchannel name based).
0365 Note that row can be an actual row from SQLAlchemy from direct online DB querying
0366 but also a dictionary extracted parsing ManualO2O.log files.
0367 """
0368
0369
0370
0371
0372
0373
0374 if row['dpname'] not in self.PSUChannels:
0375 if self.debug:
0376 print("Discarding results row since it is not in the currently considered map:\n%s"%row['dpname'])
0377 return
0378
0379
0380
0381 lastTimeStamp,nextTimeStamp=self.getIOV(row['change_date'],self.PSUChannelHistory)
0382
0383 if self.debug:
0384 if row['change_date'] not in self.PSUChannelHistory.keys():
0385 if nextTimeStamp!="Infinity":
0386 print("WARNING! Asynchronous updating of the Tracker Voltage Status")
0387 print("WARNING! Inserting an IOV between %s, and %s existing timestamps!"%(lastTimeStamp,nextTimeStamp))
0388 print("The state will be correctly updated (if necessary) starting from the state at %s"%lastTimeStamp)
0389 else:
0390 print("Appending one more IOV to the PSUChannelHistory dictionary")
0391 else:
0392 print("Updating already present IOV with timestamp %s"%row['change_date'])
0393
0394
0395
0396 PSUChannelOFFList=self.PSUChannelHistory[lastTimeStamp][:]
0397 if row['actual_status']==1:
0398 try:
0399 PSUChannelOFFList.remove(self.PSUChannels.index(row['dpname']))
0400 self.PSUChannelHistory.update({row['change_date']:PSUChannelOFFList})
0401 except:
0402 if self.debug:
0403 print("Found a channel that turned ON but as already ON apparently!")
0404 print(row)
0405 else:
0406 PSUChannelOFFList.append(self.PSUChannels.index(row['dpname']))
0407 self.PSUChannelHistory.update({row['change_date']:list(set(PSUChannelOFFList))})
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443 def updateDetIDQuery(self,row):
0444 """Function to automatically handle the updating of the history dictionary
0445 with the result rows from detID based query
0446 """
0447
0448
0449 if row['change_date'] not in self.history.keys():
0450
0451
0452 lastTimeStamp=sorted(self.history.keys()).pop(0)
0453 self.history.update({row['change_date']:self.history[lastTimeStamp]})
0454
0455 channelStatus=self.history[row['change_date']][row['detid']]
0456
0457 channelStatus[row['channel']]=row['voltage_status']
0458
0459 self.history[row['change_date']].update({row['detid']:channelStatus})
0460
0461
0462
0463
0464
0465
0466 def getPSUChannelsOff(self,timestamp):
0467 """
0468 Function that given a timestamp, returns the list of PSUChannels OFF, the list of PSUChannels ON and the IOV (start/stop timestamps) of the reported status.
0469 NOTE: No distinction between HV and LV is made since all PSUChannels (000/001 and 002/003) are reported.
0470 """
0471 StartTime,StopTime=self.getIOV(timestamp,self.PSUChannelHistory)
0472 PSUChannelsOFF=map(lambda x: self.PSUChannels[x],self.PSUChannelHistory[StartTime])
0473 PSUChannelsON=list(set(self.PSUChannels).difference(set(PSUChannelsOFF)))
0474 return PSUChannelsOFF,PSUChannelsON,StartTime,StopTime
0475
0476 def getDetIDsHVOff(self,timestamp):
0477 """
0478 Function that given a timestamp, returns the list of detIDs with HV OFF, the list of detIDs with HV ON and the IOV (start/stop times) of the reported status.
0479 """
0480 StartTime,StopTime=self.getIOV(timestamp,self.PSUChannelHistory)
0481 DetIDsHVOFF=[]
0482
0483
0484
0485 for index in self.PSUChannelHistory[StartTime]:
0486
0487 if self.PSUChannels[index].endswith("2") or self.PSUChannels[index].endswith("3") :
0488
0489 if self.PSUChannels[index] in self.PSUDetIDmap.keys():
0490
0491 DetIDsHVOFF.extend(self.PSUDetIDmap[self.PSUChannels[index]])
0492
0493 if self.PSUChannels[index][:-10] in self.PSUDetIDUnmappedMap.keys():
0494
0495
0496 DetIDsHVOFF.extend(self.PSUDetIDUnmappedMap[self.PSUChannels[index][:-10]])
0497
0498 if self.PSUChannels[index][:-10] in self.PSUDetIDCrosstalkingMap.keys():
0499
0500 if (self.PSUChannels.index(self.PSUChannels[index][:-1]+"2") in self.PSUChannelHistory[StartTime]) and (self.PSUChannels.index(self.PSUChannels[index][:-1]+"3") in self.PSUChannelHistory[StartTime]):
0501
0502 DetIDsHVOFF.extend(self.PSUDetIDCrosstalkingMap[self.PSUChannels[index][:-10]])
0503 DetIDsHVON=list(set(self.detIDs).difference(set(DetIDsHVOFF)))
0504 return list(set(DetIDsHVOFF)),DetIDsHVON,StartTime,StopTime
0505
0506 def getDetIDsLVOff(self,timestamp):
0507 """
0508 Function that given a timestamp, returns the list of detIDs with LV OFF, the list of detIDs with LV ON and the IOV (start/stop times) of the reported status.
0509 """
0510
0511 StartTime,StopTime=self.getIOV(timestamp,self.PSUChannelHistory)
0512 DetIDsLVOFF=[]
0513 for detids in map(lambda x: self.PSUDetIDmap[self.PSUChannels[x]],[index for index in self.PSUChannelHistory[StartTime] if (self.PSUChannels[index].endswith("0") or self.PSUChannels[index].endswith("1"))]):
0514 DetIDsLVOFF.extend(detids)
0515 DetIDsLVON=list(set(self.detIDs).difference(set(DetIDsLVOFF)))
0516 return list(set(DetIDsLVOFF)),DetIDsLVON,StartTime,StopTime
0517
0518 def getAliasesHVOff(self,timestamp):
0519 """
0520 Function that given a timestamp, returns the list of (PSU) Aliases with HV OFF, the list of (PSU) Aliases with HV ON and the IOV (start/stop times) of the reported status.
0521 """
0522 DetIDsHVOFF,DetIDsHVON,StartTime,StopTime=self.getDetIDsHVOff(timestamp)
0523 AliasesHVOFF=list(set([list(self.DetIDAliasDict[detid])[0] for detid in DetIDsHVOFF]))
0524 AliasesHVON=list(set([list(self.DetIDAliasDict[detid])[0] for detid in DetIDsHVON]))
0525 return AliasesHVOFF,AliasesHVON,StartTime,StopTime
0526
0527 def getAliasesLVOff(self,timestamp):
0528 """
0529 Function that given a timestamp, returns the list of (PSU) Aliases with HV OFF, the list of (PSU) Aliases with HV ON and the IOV (start/stop times) of the reported status.
0530 """
0531 DetIDsLVOFF,DetIDsLVON,StartTime,StopTime=self.getDetIDsLVOff(timestamp)
0532 AliasesLVOFF=list(set([list(self.DetIDAliasDict[detid])[0] for detid in DetIDsLVOFF]))
0533 AliasesLVON=list(set([list(self.DetIDAliasDict[detid])[0] for detid in DetIDsLVON]))
0534 return AliasesLVOFF,AliasesLVON,StartTime,StopTime
0535
0536
0537
0538 def getDetIDsHVOffVsTime(self):
0539 """
0540 Function that returns the number of DetIDs with HV OFF vs time for all IOVs available in the PSUChannelHistory.
0541 The results is one list of tuples [(datetime.datetime,#DetIDsHVOFF),...] and the timestamp of the last entry processed in the PSUChannelHistory.
0542 This is important, so that the user can check until when in time the last tuple in the list is valid until (closing the last IOV).
0543 This can be easily used to
0544 -Do spot checks by IOV: picking a timestamp inside one of the IOVs one can use the getDetIDsHVOff function to get a list of the detIDs ON/OFF.
0545 -Plot the graph of number of HV OFF (or ON by complementing to 15148) vs time using pyRoot
0546 """
0547
0548 DetIDsHVOffVsTime=[]
0549 PreviousTimeStamp=None
0550 PreviousDetIDsHVOFF=[]
0551 for timestamp in sorted(self.PSUChannelHistory.keys()):
0552 DetIDsHVOFF=self.getDetIDsHVOff(timestamp)[0]
0553
0554 if PreviousTimeStamp:
0555 if DetIDsHVOFF!=PreviousDetIDsHVOFF:
0556 DetIDsHVOffVsTime.append((timestamp,len(DetIDsHVOFF)))
0557 else:
0558 DetIDsHVOffVsTime.append((timestamp,len(DetIDsHVOFF)))
0559 PreviousTimeStamp=timestamp
0560 PreviousDetIDsHVOFF=DetIDsHVOFF
0561 LastTimeStamp=PreviousTimeStamp
0562 return DetIDsHVOffVsTime,PreviousTimeStamp
0563
0564 def getDetIDsLVOffVsTime(self):
0565 """
0566 Function that returns the number of DetIDs with LV OFF vs time for all IOVs available in the PSUChannelHistory.
0567 The results is one list of tuples [(datetime.datetime,#DetIDsLVOFF),...], basically 1 entry per IOV (change in the LV channels only),
0568 and the timestamp of the last entry processed in the PSUChannelHistory. This timestamp is important, so that the user can check until when in time the last tuple in the list is valid until (closing the last IOV).
0569 This can be easily used to
0570 -Do spot checks by IOV: picking a timestamp inside one of the IOVs one can use the getDetIDsHVOff function to get a list of the detIDs ON/OFF.
0571 -Plot the graph of number of HV OFF (or ON by complementing to 15148) vs time using pyRoot
0572 """
0573
0574 DetIDsLVOffVsTime=[]
0575 PreviousTimeStamp=None
0576 for timestamp in sorted(self.PSUChannelHistory.keys()):
0577 DetIDsLVOFF=set(self.getDetIDsLVOff(timestamp)[0])
0578
0579 if PreviousTimeStamp:
0580 if DetIDsLVOFF!=PreviousDetIDsLVOFF:
0581 DetIDsLVOffVsTime.append((timestamp,len(DetIDsLVOFF)))
0582 else:
0583 DetIDsLVOffVsTime.append((timestamp,len(DetIDsLVOFF)))
0584 PreviousTimeStamp=timestamp
0585 PreviousDetIDsLVOFF=DetIDsLVOFF
0586 LastTimeStamp=PreviousTimeStamp
0587 return DetIDsLVOffVsTime,LastTimeStamp
0588
0589
0590 def getArraysForTimePlots(self,TimeStampsValuesTuple):
0591 """
0592 Function that given a tuple with (datetime.datetime,values) returns the arrays ready to the plotting vs time function (basically renders data histogram-like adding extra data points).
0593 """
0594 import array, time
0595
0596
0597 Timestamps=[]
0598 Values=[]
0599
0600 for item in sorted(TimeStampsValuesTuple):
0601
0602
0603
0604
0605 timestamp=int(time.mktime(item[0].timetuple()))
0606 if item==TimeStampsValuesTuple[0]:
0607 Timestamps.append(timestamp)
0608 Value=item[1]
0609 Values.append(Value)
0610 else:
0611 Timestamps.append(timestamp)
0612 Values.append(Value)
0613 Value=item[1]
0614 Timestamps.append(timestamp)
0615 Values.append(Value)
0616
0617 TimestampsArray=array.array('i',Timestamps)
0618 ValuesArray=array.array('i',Values)
0619
0620 return TimestampsArray,ValuesArray
0621
0622 def getReducedArraysForTimePlots(self,TimeStamps,Values):
0623 """
0624 Implement IOV reduction based on timestamp delta, following O2O algorithm.
0625 """
0626
0627 return
0628
0629
0630 def plotGraphSeconds(self,TimeArray,ValuesArray,GraphTitle="Graph",YTitle="Number of channels",GraphFilename="test.gif"):
0631 """
0632 Function that given an array with timestamps (massaged to introduce a second timestamp for each value to produce an histogram-looking plot) and a corresponding array with values to be plotted, a title, a Y axis title and a plot filename, produces with pyROOT a time plot and saves it locally.
0633 The function can be used for cumulative plots (number of channels with HV/LV OFF/ON vs time) or for individual (single detID HV/LV status vs time) plots.
0634 """
0635 import ROOT
0636 canvas=ROOT.TCanvas()
0637 graph=ROOT.TGraph(len(TimeArray),TimeArray,ValuesArray)
0638 graph.GetXaxis().SetTimeDisplay(1)
0639 graph.GetXaxis().SetLabelOffset(0.02)
0640
0641 TotalTimeIntervalSecs=TimeArray[-1]-TimeArray[0]
0642 if TotalTimeIntervalSecs <= 120:
0643 graph.GetXaxis().SetTimeFormat("#splitline{ %d/%m}{%H:%M:%S}")
0644 elif 120 < TotalTimeIntervalSecs < 6400:
0645 graph.GetXaxis().SetTimeFormat("#splitline{%d/%m}{%H:%M}")
0646 else:
0647 graph.GetXaxis().SetTimeFormat("#splitline{%d/%m}{ %H}")
0648 graph.GetYaxis().SetTitle(YTitle)
0649 graph.GetYaxis().SetTitleOffset(1.4)
0650 graph.SetTitle(GraphTitle)
0651 graph.Draw("APL")
0652 canvas.SaveAs(GraphFilename)
0653 print("Saved graph as %s"%GraphFilename)
0654 return
0655 def plotPSUChannelvsTime(self,TimeArray,ValuesArray,GraphTitle="PSUChannelGraph",YTitle="Channel HV Status",GraphFilename="PSUChannel.gif"):
0656 """
0657 Function that given an array with timestamps (massaged to introduce a second timestamp for each value to produce an histogram-looking plot) and a corresponding array with values to be plotted, a title, a Y axis title and a plot filename, produces with pyROOT a time plot and saves it locally.
0658 The function can be used for cumulative plots (number of channels with HV/LV OFF/ON vs time) or for individual (single detID HV/LV status vs time) plots.
0659 """
0660 import ROOT
0661 canvas=ROOT.TCanvas()
0662 graph=ROOT.TGraph(len(TimeArray),TimeArray,ValuesArray)
0663 graph.GetXaxis().SetTimeDisplay(1)
0664 graph.GetXaxis().SetLabelOffset(0.02)
0665
0666 TotalTimeIntervalSecs=TimeArray[-1]-TimeArray[0]
0667 if TotalTimeIntervalSecs <= 120:
0668 graph.GetXaxis().SetTimeFormat("#splitline{ %d/%m}{%H:%M:%S}")
0669 elif 120 < TotalTimeIntervalSecs < 6400:
0670 graph.GetXaxis().SetTimeFormat("#splitline{%d/%m}{%H:%M}")
0671 else:
0672 graph.GetXaxis().SetTimeFormat("#splitline{%d/%m}{ %H}")
0673 graph.GetYaxis().SetTitle(YTitle)
0674 graph.GetYaxis().SetTitleOffset(1.4)
0675 graph.SetTitle(GraphTitle)
0676 graph.Draw("APL")
0677 canvas.SaveAs(GraphFilename)
0678 print("Saved graph as %s"%GraphFilename)
0679 return
0680
0681 def plotHVOFFvsTime(self):
0682 """
0683 """
0684 return
0685
0686 def plotLVOFFvsTime(self):
0687 """
0688 """
0689 return
0690
0691 def plotDetIDHVOFFVsTime(self,detID):
0692 """
0693 """
0694 return
0695 def plotDetIDLVOFFVsTime(self,detID):
0696 """
0697 """
0698 return
0699
0700 def plotDetIDHistory(self):
0701 return
0702
0703 def getIOV(self,timeStamp,HistoryDict):
0704 """
0705 Function that given a timeStamp return the TimeStampStart and TimeStampStop of the IOV in the wanted HistoryDict (assumed to have timestamps as keys) that contains the timestamp.
0706 This can be used by all functions that need to access HistoryDict by timeStamp.
0707 """
0708
0709 TimeStamps=HistoryDict.keys()[:]
0710
0711 if timeStamp not in TimeStamps:
0712 TimeStamps.append(timeStamp)
0713
0714 TimeStamps.sort()
0715 TimeStampStart=TimeStamps[TimeStamps.index(timeStamp)-1]
0716
0717 TimeStamps.remove(timeStamp)
0718 else:
0719 TimeStamps.sort()
0720 TimeStampStart=timeStamp
0721
0722 if len(TimeStamps)>TimeStamps.index(TimeStampStart)+1:
0723 TimeStampStop=TimeStamps[TimeStamps.index(TimeStampStart)+1]
0724 else:
0725 TimeStampStop="Infinity"
0726 if self.debug:
0727 print("TimeStamp %s falls into IOV starting at %s and ending at %s"%(timeStamp,TimeStampStart,TimeStampStop))
0728 return (TimeStampStart,TimeStampStop)
0729
0730 def getIOVsInTimeInterval(self,StartTime,StopTime,HistoryDict):
0731 """
0732 Function that returns the IOV timestamps (ordered) contained in a given interval.
0733 """
0734
0735 TimeStamps=sorted(HistoryDict.keys()[:])
0736 IOVsInTimeInterval=[]
0737
0738 for timestamp in TimeStamps:
0739 if timestamp>=StartTime and timestamp<=StopTime:
0740 if self.debug:
0741 print("Found timestamp %s in the wanted interval [%s,%s]"%(timestamp,StartTime,StopTime))
0742 IOVsInTimeInterval.append(timestamp)
0743 return IOVsInTimeInterval
0744
0745 def getReducedIOVs (self,StartTime,StopTime,HistoryDict,deltaT,maxIOVLength):
0746 """
0747 Apply the reduction algorithm to the timeintervals and return them so that one can test the reduction (and do plots more easily).
0748 """
0749 deltaTime=datetime.timedelta(seconds=deltaT)
0750 maxSequenceLength=datetime.timedelta(seconds=maxIOVLength)
0751
0752 TimeStamps=sorted(HistoryDict.keys()[:])
0753 ReducedIOVs=TimeStamps[:]
0754 PreviousTimestamp=TimeStamps[0]
0755 SequenceStart=TimeStamps[0]
0756 SequenceOn=False
0757
0758
0759 for timestamp in TimeStamps[1:]:
0760
0761 if timestamp>=StartTime and timestamp<=StopTime:
0762
0763 if timestamp-PreviousTimestamp<=deltaTime:
0764
0765 if SequenceOn:
0766
0767 if (timestamp-SequenceStart)<=maxSequenceLength and timestamp!=TimeStamps[-1]:
0768 if self.debug:
0769 print("Eliminating timestamp %s since it is %s (<=%s)seconds from previous timestamp %s and %s (<=%s) seconds from the IOV sequence start %s!"%(timestamp,timestamp-PreviousTimestamp,deltaTime,PreviousTimestamp,timestamp-SequenceStart,maxSequenceLength,SequenceStart))
0770 ReducedIOVs.remove(timestamp)
0771 elif timestamp==TimeStamps[-1]:
0772 if self.debug:
0773 print("###Terminating the IOV sequence started with %s, since current timestamp %s is the last one in the input list of timestamps to REDUCE!"%(SequenceStart,timestamp))
0774 else:
0775
0776 SequenceOn=False
0777
0778 ReducedIOVs.append(PreviousTimestamp)
0779
0780 ReducedIOVs.sort()
0781 if self.debug:
0782 print("###Terminating the IOV sequence started with %s, since current timestamp %s is %s seconds (>%s) away from the IOV sequence starting timestamp (%s). Re-appending the last timestamp in the sequence %s."%(SequenceStart,timestamp,timestamp-SequenceStart,maxIOVLength,PreviousTimestamp,PreviousTimestamp))
0783 else:
0784
0785 SequenceOn=True
0786
0787 if self.debug:
0788 print("@@@Starting a new IOV sequence with previous timestamp %s (current being %s)"%(PreviousTimestamp,timestamp))
0789
0790 ReducedIOVs.remove(timestamp)
0791 SequenceStart=PreviousTimestamp
0792 else:
0793
0794 if SequenceOn:
0795
0796 SequenceOn=False
0797
0798 ReducedIOVs.append(PreviousTimestamp)
0799
0800 ReducedIOVs.sort()
0801 if self.debug:
0802 print("$$$Terminating the IOV sequence started with %s, since current timestamp %s is %s seconds (>%s) away from the previous timestamp (%s) in the sequence. Re-appending the last timestamp in the sequence %s."%(SequenceStart,timestamp,timestamp-PreviousTimestamp,deltaT,PreviousTimestamp,PreviousTimestamp))
0803
0804 else:
0805
0806
0807
0808 ReducedIOVs.remove(timestamp)
0809
0810 if SequenceOn:
0811
0812 SequenceOn=False
0813
0814 ReducedIOVs.append(PreviousTimestamp)
0815
0816 ReducedIOVs.sort()
0817 if self.debug:
0818 print("^^^ Terminating the IOV sequence started with %s, since current timestamp %s is no more in the wanted time interval under investigation ([%s,%s]). Sequence might have been continuing beyond the StopTime %s limit! Re-appending the last timestamp in the sequence %s."%(SequenceStart,timestamp,StartTime,StopTime,StopTime,PreviousTimestamp))
0819 PreviousTimestamp=timestamp
0820 return ReducedIOVs
0821
0822
0823
0824 TkStatus=TrkVoltageStatus(detIDPSUmapfilename=os.path.join(os.getenv('CMSSW_BASE'),'src/CalibTracker/SiStripDCS/data/StripPSUDetIDMap_FromJan132010_Crosstalk.dat'),DetIDAliasFile=os.path.join(os.getenv('CMSSW_BASE'),'src/CalibTracker/SiStripDCS/data/StripDetIDAlias.pkl'),startTime=datetime.datetime(2010,8,27,12,00,00),debug=True)
0825
0826
0827
0828
0829
0830
0831
0832
0833
0834
0835
0836
0837
0838
0839
0840
0841
0842
0843
0844
0845
0846
0847
0848
0849
0850
0851
0852
0853
0854
0855
0856
0857
0858
0859
0860
0861
0862
0863
0864
0865
0866
0867
0868
0869
0870
0871
0872
0873
0874
0875
0876
0877
0878
0879
0880
0881
0882
0883
0884
0885
0886
0887
0888
0889
0890
0891
0892
0893
0894
0895
0896
0897
0898
0899
0900
0901
0902
0903
0904
0905
0906
0907
0908
0909
0910
0911
0912
0913
0914
0915
0916
0917
0918
0919
0920
0921
0922
0923
0924
0925
0926
0927 QueryResults=GetQueryResults("ManualO2O.log")
0928
0929
0930
0931
0932 counter=0
0933 hours=72
0934 for interval in sorted(QueryResults.keys()):
0935 counter+=1
0936 if counter<hours:
0937 print("Updating TkStatus with query results for time interval %s to %s"%interval)
0938 for row in QueryResults[interval]:
0939 TkStatus.updateO2OQuery(row)
0940 print(len(TkStatus.PSUChannelHistory))
0941 if counter-hours>0:
0942 print("Number of intervals skipped %s"%(counter-hours))
0943
0944
0945
0946
0947
0948
0949
0950
0951
0952
0953
0954
0955
0956
0957
0958
0959
0960
0961
0962
0963
0964
0965
0966
0967
0968
0969
0970
0971
0972
0973
0974
0975
0976
0977
0978
0979
0980
0981
0982
0983
0984
0985
0986
0987
0988
0989
0990
0991
0992
0993
0994
0995
0996
0997
0998
0999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082 ReducedIOVsTimestamps=TkStatus.getReducedIOVs(datetime.datetime(2010, 8, 27, 12, 0),datetime.datetime(2010, 8, 29, 17, 45),TkStatus.PSUChannelHistory,15,120)
1083
1084 print("Dumping ReducedIOVsTimestamps and the corresponding timestamp index and number of HV/LV channels off:")
1085 for timestamp in ReducedIOVsTimestamps:
1086 TkStatus.debug=False
1087 print(timestamp,sorted(TkStatus.PSUChannelHistory.keys()).index(timestamp),len(TkStatus.getDetIDsHVOff(timestamp)[0]), len(TkStatus.getDetIDsLVOff(timestamp)[0]))
1088
1089
1090 def ReducedIOVsHistory(ReducedIOVsTimestamps):
1091 """
1092 Function that given a list of reduced IOVs timestamps (output of getReducedIOVs()), analyses the timestamps to identify the IOV sequences and treats them differently when ramping-up or ramping-down, to return a dictionary that has timestamp as a key and the list of LV and HV channels OFF, that can be compared with the content of the CheckAllIOVs output DetVOffReaderDebug logs for validation.
1093 """
1094
1095 AllTimestamps=sorted(TkStatus.PSUChannelHistory.keys())
1096 PreviousTimestampIndex=-1
1097 ReducedIOVsDict={}
1098 for timestamp in ReducedIOVsTimestamps:
1099 if AllTimestamps.index(timestamp)!=(PreviousTimestampIndex+1):
1100
1101 LVOffEnd=TkStatus.getDetIDsLVOff(timestamp)[0]
1102
1103 LVOffStart=TkStatus.getDetIDsLVOff(AllTimestamps[PreviousTimestampIndex])[0]
1104
1105 HVOffEnd=TkStatus.getDetIDsHVOff(timestamp)[0]
1106
1107 HVOffStart=TkStatus.getDetIDsHVOff(AllTimestamps[PreviousTimestampIndex])[0]
1108
1109
1110
1111 if len(LVOffEnd)>len(LVOffStart) or len(HVOffEnd)>len(HVOffStart):
1112 ReducedIOVsDict.update({AllTimestamps[PreviousTimestampIndex]:(TkStatus.getDetIDsHVOff(timestamp)[0],TkStatus.getDetIDsLVOff(timestamp)[0])})
1113
1114
1115
1116
1117 if set(TkStatus.getDetIDsHVOff(timestamp)[0])!=set(TkStatus.getDetIDsHVOff(AllTimestamps[PreviousTimestampIndex])[0]) or set(TkStatus.getDetIDsLVOff(timestamp)[0])!=set(TkStatus.getDetIDsLVOff(AllTimestamps[PreviousTimestampIndex])[0]):
1118 ReducedIOVsDict.update({timestamp:(TkStatus.getDetIDsHVOff(timestamp)[0],TkStatus.getDetIDsLVOff(timestamp)[0])})
1119 PreviousTimestampIndex=AllTimestamps.index(timestamp)
1120 return ReducedIOVsDict
1121
1122
1123 ValidationReducedIOVsHistory=ReducedIOVsHistory(ReducedIOVsTimestamps)
1124
1125
1126
1127
1128
1129
1130 print("Dumping ValidationReducedIOVsHistory contents:")
1131 for timestamp in sorted(ValidationReducedIOVsHistory.keys()):
1132 print(timestamp, len(ValidationReducedIOVsHistory[timestamp][0]),len(ValidationReducedIOVsHistory[timestamp][1]))
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145 def ExtractDetVOffInfo(directory=os.getcwd()):
1146 """
1147 Function that given a directory (defaults to the local one in case no dir indicated), parses all local DetVOffReaderDebug*.log files and returna a dictionary with timestamps for keys and a tuple with the list of LV and HV channels OFF (LVOff,HVOff).
1148 """
1149 ls=os.listdir(directory)
1150 TimesLogs=[]
1151 O2OData={}
1152 for log in ls:
1153 if "DetVOffReaderDebug__FROM" in log:
1154 (start,end)=log[:-4].split("FROM_")[1].split("_TO_")
1155 TimeStamp=datetime.datetime.strptime(start.replace("__","_0"),"%a_%b_%d_%H_%M_%S_%Y")
1156
1157 file=open(log,'r')
1158 filelines=file.readlines()
1159 file.close()
1160 LVOff=[]
1161 HVOff=[]
1162 for line in filelines:
1163
1164 if "OFF" in line:
1165 detid,hv,lv=line.split()
1166
1167 if hv=="OFF":
1168 HVOff.append(int(detid))
1169 if lv=="OFF":
1170 LVOff.append(int(detid))
1171
1172 O2OData.update({TimeStamp:(HVOff,LVOff)})
1173 return O2OData
1174
1175
1176 O2OReducedIOVs=ExtractDetVOffInfo()
1177
1178 print("Dumping the O2OReducedIOVs contents:")
1179 for timestamp in sorted(O2OReducedIOVs.keys()):
1180 print(timestamp, len(O2OReducedIOVs[timestamp][0]),len(O2OReducedIOVs[timestamp][1]))
1181
1182
1183
1184
1185
1186
1187 def CompareReducedDetIDs(FirstDict,SecondDict):
1188 """
1189 Function that given 2 Dictionaries (key=timestamp, value=(LVOff,HVOff)) loops through the first one and compared the content of its IOVs with the IOV in the other dict that overlaps with it.
1190 """
1191 DifferenceDict={}
1192 for timestamp in sorted(FirstDict.keys()):
1193 if timestamp.replace(microsecond=0) in SecondDict.keys():
1194 secondtimestamp=timestamp.replace(microsecond=0)
1195 print("Timestamp %s is present in both Dictionaries!"%timestamp)
1196 else:
1197 secondtimestamps=sorted(SecondDict.keys())
1198 secondtimestamps.append(timestamp)
1199 secondtimestamps.sort()
1200 if secondtimestamps.index(timestamp)!=0:
1201 secondtimestamp=secondtimestamps[secondtimestamps.index(timestamp)-1]
1202 else:
1203 secondtimestamp=secondtimestamps[secondtimestamps.index(timestamp)+1]
1204 print("Comparing the IOV with timestamp %s (1st dict) with IOV with timestamp %s (2nd dict)"%(timestamp,secondtimestamp))
1205 if set(map(lambda x:int(x),FirstDict[timestamp][0]))!=set(map(lambda x:int(x),SecondDict[secondtimestamp][0])) or set(map(lambda x:int(x),FirstDict[timestamp][1]))!=set(map(lambda x:int(x),SecondDict[secondtimestamp][1])):
1206 if len(set(FirstDict[timestamp][0]))<=len(set(SecondDict[secondtimestamp][0])):
1207 differenceHV=set(map(lambda x:int(x),SecondDict[secondtimestamp][0]))-set(map(lambda x:int(x),FirstDict[timestamp][0]))
1208 else:
1209
1210 differenceHV=set(map(lambda x:int(x),FirstDict[timestamp][0]))-set(map(lambda x:int(x),SecondDict[secondtimestamp][0]))
1211
1212
1213
1214
1215 if len(set(FirstDict[timestamp][1]))<=len(set(SecondDict[secondtimestamp][1])):
1216 differenceLV=set(map(lambda x:int(x),SecondDict[secondtimestamp][1]))-set(map(lambda x:int(x),FirstDict[timestamp][1]))
1217 else:
1218
1219 differenceLV=set(map(lambda x:int(x),FirstDict[timestamp][1]))-set(map(lambda x:int(x),SecondDict[secondtimestamp][1]))
1220
1221
1222
1223
1224 DifferenceDict.update({(timestamp,secondtimestamp):(differenceHV,differenceLV)})
1225 print("Difference in timestamp %s (corresponding to %s):"%(timestamp,secondtimestamp))
1226
1227
1228
1229
1230
1231
1232 else:
1233 print("Timestamp %s is identical in both dictionaries"%timestamp)
1234 return DifferenceDict
1235 Comparison=CompareReducedDetIDs(ValidationReducedIOVsHistory,O2OReducedIOVs)
1236 print("Dumping the results of the comparisons of the two dictionaries:")
1237 for timestamps in sorted(Comparison.keys()):
1238 print(timestamps, Comparison[timestamps])
1239 if Comparison[timestamps][0]:
1240 print("HV:")
1241 if Comparison[timestamps][0].issubset(set(O2OReducedIOVs[timestamps[1]][0])):
1242 print("Only in O2O Dict!")
1243 else:
1244 print("Only in Validation Dict!")
1245 for detid in Comparison[timestamps][0]:
1246 print(detid,TkStatus.DetIDAliasDict[detid])
1247 if Comparison[timestamps][1]:
1248 print("LV:")
1249 if Comparison[timestamps][1].issubset(set(O2OReducedIOVs[timestamps[1]][1])):
1250 print("Only in O2O Dict!")
1251 else:
1252 print("Only in Validation Dict!")
1253 for detid in Comparison[timestamps][1]:
1254 print(detid,TkStatus.DetIDAliasDict[detid])
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264 TkStatusFromQuery=TrkVoltageStatus(detIDPSUmapfilename=os.path.join(os.getenv('CMSSW_BASE'),'src/CalibTracker/SiStripDCS/data/StripPSUDetIDMap_FromJan132010_Crosstalk.dat'),DetIDAliasFile=os.path.join(os.getenv('CMSSW_BASE'),'src/CalibTracker/SiStripDCS/data/StripDetIDAlias.pkl'),startTime=datetime.datetime(2010,8,27,10,00,00),debug=True)
1265 DBQueryPickle=open('/afs/cern.ch/user/g/gbenelli/scratch0/O2OValidation/QueryResults.pkl','rb')
1266 DBQueryResults=[]
1267 DBQueryResults=pickle.load(DBQueryPickle)
1268 DBQueryPickle.close()
1269 for row in DBQueryResults:
1270 TkStatusFromQuery.updateO2OQuery(row)
1271 print(len(TkStatusFromQuery.PSUChannelHistory))
1272
1273 delta=datetime.timedelta(seconds=7200)
1274 counter=0
1275 DifferingTimestamps=[]
1276 for timestamp in sorted(TkStatus.PSUChannelHistory.keys()):
1277 if timestamp-delta!=sorted(TkStatusFromQuery.PSUChannelHistory.keys())[counter]:
1278 print(timestamp, sorted(TkStatusFromQuery.PSUChannelHistory.keys())[counter])
1279 DifferingTimestamps.append(timestamp,sorted(TkStatusFromQuery.PSUChannelHistory.keys())[counter])
1280 counter=counter+1
1281 if DifferingTimestamps:
1282 print("There are %s timestamps that are different in the 2 TkVoltageStatus objects!"%len(DifferingTimestamps))
1283
1284
1285
1286
1287
1288
1289 LVChannelHistory={}
1290 HVChannelHistory={}
1291 for interval in QueryResults.keys():
1292 for row in QueryResults[interval]:
1293 if row['dpname'].endswith('0') or row['dpname'].endswith('1'):
1294 if row['dpname'][:-1] not in LVChannelHistory.keys():
1295 LVChannelHistory.update({row['dpname'][:-1]:[(row['change_date'],row['actual_status'])]})
1296 else:
1297 LVChannelHistory[row['dpname'][:-1]].append((row['change_date'],row['actual_status']))
1298 else:
1299 if row['dpname'] not in HVChannelHistory.keys():
1300 HVChannelHistory.update({row['dpname']:[(row['change_date'],row['actual_status'])]})
1301 else:
1302 HVChannelHistory[row['dpname']].append((row['change_date'],row['actual_status']))
1303
1304
1305
1306
1307
1308 if row['change_date']>datetime.datetime(2010, 8, 28, 22, 44) and row['change_date']<datetime.datetime(2010, 8, 28, 23, 5,37):
1309 print(row)
1310
1311
1312
1313 for row in sorted(HVChannelHistory['cms_trk_dcs_04:CAEN/CMS_TRACKER_SY1527_6/branchController02/easyCrate3/easyBoard15/channel002']):
1314 print(row[0],row[1])
1315 for row in sorted(HVChannelHistory['cms_trk_dcs_04:CAEN/CMS_TRACKER_SY1527_6/branchController02/easyCrate3/easyBoard15/channel003']):
1316 print(row[0],row[1])
1317 print(TkStatus.PSUChannelHistory[sorted(TkStatus.PSUChannelHistory.keys())[sorted(TkStatus.PSUChannelHistory.keys()).index(datetime.datetime(2010, 8, 28, 22, 52, 8, 994000))-1]])
1318 a=TkStatus.getIOV(datetime.datetime(2010, 8, 28, 22, 51, 16),TkStatus.PSUChannelHistory)
1319
1320
1321 import array, time
1322 TOBminus_1_3_1_4_HV1_Status=HVChannelHistory['cms_trk_dcs_04:CAEN/CMS_TRACKER_SY1527_6/branchController02/easyCrate3/easyBoard15/channel002']
1323
1324 TOBminus_1_3_1_4_HV1_Status=[item for item in HVChannelHistory['cms_trk_dcs_04:CAEN/CMS_TRACKER_SY1527_6/branchController02/easyCrate3/easyBoard15/channel002'] if item[0]>datetime.datetime(2010,8,28,22) and item[0]<datetime.datetime(2010,8,29,2)]
1325 TOBTimestamps=[]
1326 TOBHVStatus=[]
1327 for item in TOBminus_1_3_1_4_HV1_Status:
1328 timestamp=int(time.mktime(item[0].timetuple()))
1329 if item==TOBminus_1_3_1_4_HV1_Status[0]:
1330 TOBTimestamps.append(timestamp)
1331 HVStatus=int(item[1]==1)
1332 TOBHVStatus.append(HVStatus)
1333 else:
1334 TOBTimestamps.append(timestamp)
1335 TOBHVStatus.append(HVStatus)
1336 HVStatus=int(item[1]==1)
1337 TOBTimestamps.append(timestamp)
1338 TOBHVStatus.append(HVStatus)
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353 TOBTimestampsArray=array.array('i',TOBTimestamps)
1354 TOBHVStatusArray=array.array('i',TOBHVStatus)
1355
1356 TkStatus.plotGraphSeconds(TOBTimestampsArray,TOBHVStatusArray,GraphTitle="PSUChannelGraph",YTitle="Channel HV Status",GraphFilename="PSUChannel.gif")
1357 TOBminus_1_3_1_4_HV1_Status=HVChannelHistory['cms_trk_dcs_04:CAEN/CMS_TRACKER_SY1527_6/branchController02/easyCrate3/easyBoard15/channel003']
1358
1359 TOBminus_1_3_1_4_HV1_Status=[item for item in HVChannelHistory['cms_trk_dcs_04:CAEN/CMS_TRACKER_SY1527_6/branchController02/easyCrate3/easyBoard15/channel003'] if item[0]>datetime.datetime(2010,8,28,22) and item[0]<datetime.datetime(2010,8,29,2)]
1360 TOBTimestamps=[]
1361 TOBHVStatus=[]
1362 for item in TOBminus_1_3_1_4_HV1_Status:
1363 timestamp=int(time.mktime(item[0].timetuple()))
1364 if item==TOBminus_1_3_1_4_HV1_Status[0]:
1365 TOBTimestamps.append(timestamp)
1366 HVStatus=int(item[1]==1)
1367 TOBHVStatus.append(HVStatus)
1368 else:
1369 TOBTimestamps.append(timestamp)
1370 TOBHVStatus.append(HVStatus)
1371 HVStatus=int(item[1]==1)
1372 TOBTimestamps.append(timestamp)
1373 TOBHVStatus.append(HVStatus)
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388 TOBTimestampsArray=array.array('i',TOBTimestamps)
1389 TOBHVStatusArray=array.array('i',TOBHVStatus)
1390
1391 TkStatus.plotGraphSeconds(TOBTimestampsArray,TOBHVStatusArray,GraphTitle="PSUChannelGraph",YTitle="Channel HV Status",GraphFilename="PSUChannelHV2.gif")
1392 def plotPSUChannelvsTime(self,TimeArray,ValuesArray,GraphTitle="PSUChannelGraph",YTitle="Channel HV Status",GraphFilename="PSUChannel.gif"):
1393 """
1394 Function that given an array with timestamps (massaged to introduce a second timestamp for each value to produce an histogram-looking plot) and a corresponding array with values to be plotted, a title, a Y axis title and a plot filename, produces with pyROOT a time plot and saves it locally.
1395 The function can be used for cumulative plots (number of channels with HV/LV OFF/ON vs time) or for individual (single detID HV/LV status vs time) plots.
1396 """
1397 import ROOT
1398 canvas=ROOT.TCanvas()
1399 graph=ROOT.TGraph(len(TimeArray),TimeArray,ValuesArray)
1400 graph.GetXaxis().SetTimeDisplay(1)
1401 graph.GetXaxis().SetLabelOffset(0.02)
1402
1403 TotalTimeIntervalSecs=TimeArray[-1]-TimeArray[0]
1404 if TotalTimeIntervalSecs <= 120:
1405 graph.GetXaxis().SetTimeFormat("#splitline{ %d/%m}{%H:%M:%S}")
1406 elif 120 < TotalTimeIntervalSecs < 6400:
1407 graph.GetXaxis().SetTimeFormat("#splitline{%d/%m}{%H:%M}")
1408 else:
1409 graph.GetXaxis().SetTimeFormat("#splitline{%d/%m}{ %H}")
1410 graph.GetYaxis().SetTitle(YTitle)
1411 graph.GetYaxis().SetTitleOffset(1.4)
1412 graph.SetTitle(GraphTitle)
1413 graph.Draw("APL")
1414 canvas.SaveAs(GraphFilename)
1415 print("Saved graph as %s"%GraphFilename)
1416 return
1417
1418
1419 ReducedIOVsTimestampsTEST=TkStatus.getReducedIOVs(datetime.datetime(2010, 8, 27, 12, 0),datetime.datetime(2010, 8, 29, 17, 45),TkStatus.PSUChannelHistory,2,90)
1420
1421 print("Dumping ReducedIOVsTimestamps and the corresponding timestamp index and number of HV/LV channels off:")
1422 for timestamp in ReducedIOVsTimestampsTEST:
1423 TkStatus.debug=False
1424 print(timestamp,sorted(TkStatus.PSUChannelHistory.keys()).index(timestamp),len(TkStatus.getDetIDsHVOff(timestamp)[0]), len(TkStatus.getDetIDsLVOff(timestamp)[0]))
1425 ValidationReducedIOVsHistoryTEST=ReducedIOVsHistory(ReducedIOVsTimestampsTEST)
1426 print("Dumping ValidationReducedIOVsHistory contents:")
1427 for timestamp in sorted(ValidationReducedIOVsHistoryTEST.keys()):
1428 print(timestamp, len(ValidationReducedIOVsHistoryTEST[timestamp][0]),len(ValidationReducedIOVsHistoryTEST[timestamp][1]))