File indexing completed on 2024-11-25 02:29:11
0001
0002
0003
0004
0005 import os,datetime, pickle
0006 def GetLogTimestamps(ManualO2Ologfilename):
0007 """
0008 This function opens the ManualO2O log chosen, and it prints out the Tmin/Tmax intervals
0009 for the individual O2O jobs that were run.
0010 This information can in turn be used with the function GetLogInfoByTimeStamp,
0011 to extract from the log the (DEBUG) information only from the wanted time interval.
0012 """
0013 ManualO2Olog=open(ManualO2Ologfilename,'r')
0014 LinesCounter=0
0015 IOVCounter=1
0016 TmaxDict={}
0017 for line in ManualO2Olog:
0018 LinesCounter+=1
0019 if 'Tmin:' in line:
0020 Tmin=line.split(':')[1].strip()
0021 if 'Tmax:' in line:
0022 Tmax=line.split(':')[1].strip()
0023
0024
0025
0026 print("%s- Tmin: %s and Tmax: %s (number log lines %s)"%(IOVCounter,Tmin,Tmax,LinesCounter))
0027
0028 if Tmax not in ListOfTmax.keys():
0029 TmaxDict.update({Tmax:LinesCounter})
0030 else:
0031 print("This Tmax (%s) seems to be duplicated!!!"%Tmax)
0032 LinesCounter=0
0033 IOVCounter+=1
0034 ManualO2Olog.close()
0035 return TmaxDict
0036
0037
0038 def GetLogInfoByTimeStamp(ManualO2Ologfilename,StartTime,StopTime):
0039 """
0040 This function takes a ManualO2Ologfilename, a start and a stop timestamps (that should be
0041 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",
0042 and it parses the given logfile to just print out the lines relevant to the given timestamp.
0043 """
0044
0045 ManualO2Olog=open(ManualO2Ologfilename,'r')
0046
0047 PrintLines=False
0048 WantedLines=[]
0049 for line in ManualO2Olog:
0050 if 'Tmax:' in line and StopTime in line:
0051 PrintLines=True
0052 if PrintLines:
0053 if 'Tmin:' in line:
0054 break
0055 else:
0056 print(line.strip())
0057 WantedLines.append(line)
0058 ManualO2Olog.close()
0059 return WantedLines
0060
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 def GetQueryResults(ManualO2Ologfilename):
0118 """
0119 This function takes a ManualO2Ologfilename,
0120 and if it was run with the debug option True,
0121 it extracts all the query results.
0122 It uses StartTime/StopTime to identify the interval of the query (i.e. the ManualO2O.py running)
0123 and uses the tuple (StartTime,StopTime) as a key, as stores the results rows as a list.
0124 It returns the QueryResults dictionary that has for keys the (Tmin,Tmax) tuple, and as values lists of rows,
0125 where the rows are dictionaries with 3 keys:
0126 {
0127 'change_date':datetime.datetime,
0128 'actual_status':int,
0129 'dpname':str
0130 }
0131 The idea is that any massaging of this information is done later, while this function returns the query results in bulk.
0132 """
0133 print("Parsing file %s to extract query results"%ManualO2Ologfilename)
0134
0135 ManualO2Olog=open(ManualO2Ologfilename,'r')
0136
0137 Tmin=""
0138 Tmax=""
0139 ReadRows=False
0140 QueryResultsDict={}
0141 for line in ManualO2Olog:
0142 if 'Tmin:' in line:
0143 if Tmin=="":
0144 Tmin=datetime.datetime(*[int(x) for x in (line.split(':')[1].strip()).split()])
0145 else:
0146 Tmin=Tmax
0147 if 'Tmax:' in line:
0148 Tmax=datetime.datetime(*[int(x) for x in (line.split(':')[1].strip()).split()])
0149
0150
0151
0152
0153 if (Tmin,Tmax) not in QueryResultsDict.keys():
0154 QueryResultsDict.update({(Tmin,Tmax):[]})
0155 else:
0156 print("This Tmax (%s) seems to be duplicated!!!"%Tmax)
0157 if "Dumping all query results" in line:
0158 ReadRows=True
0159 if "Finished dumping query results" in line:
0160 NumOfRows=int(line.split(",")[1].split()[0])
0161 ReadRows=False
0162
0163
0164 if ReadRows:
0165 Row={}
0166 RowTokens=line.split(",")
0167 for token in RowTokens:
0168 if 'CHANGE_DATE' in token:
0169 try:
0170
0171
0172
0173
0174 changeDate=datetime.datetime.strptime(token[token.index(":")+2:-1],"%Y/%m/%d %H:%M:%S.%f")
0175
0176
0177
0178
0179
0180
0181
0182
0183 deltaTimezone=datetime.timedelta(seconds=7200)
0184 Row.update({'change_date':changeDate+deltaTimezone})
0185 except:
0186 print("WEIRD!\n Timestamp had a format YYYY/MM/DD HH:MM:0SS.millisecond (extra 0 tabbing for seconds!)")
0187 print(line)
0188
0189
0190
0191
0192 changeDate=datetime.datetime.strptime(token[token.index(":")+2:-1],"%Y/%m/%d %H:%M:0%S.%f")
0193
0194
0195
0196
0197
0198
0199
0200
0201 deltaTimezone=datetime.timedelta(seconds=7200)
0202 Row.update({'change_date':changeDate+deltaTimezone})
0203 if 'ACTUAL_STATUS' in token:
0204 Row.update({'actual_status':int(token[token.index(":")+2:-1])})
0205 if 'DPNAME' in token:
0206 Row.update({'dpname':token[token.index(":")+2:-2]})
0207 if len(Row)>0:
0208 QueryResultsDict[(Tmin,Tmax)].append(Row)
0209 ManualO2Olog.close()
0210 return QueryResultsDict
0211
0212 class TrkVoltageStatus:
0213 """
0214 #How about we make a class and instantiate an object TrackerVoltageStatus that we update at each row:
0215 #1-initialize it with a list of detID (from the most complete maps) OFF and ON (the masked ones):
0216 #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
0217 # 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)
0218 # b-a LV ON/OFF bit
0219 # c-a HV ON/OFF bit
0220 # d-add extra (VMON, V0_SETTINGS) info in the query?
0221 # e-add the power group turning off info in the query to check the effect
0222 # f-add a RAMPING UP/DOWN flag on top of the conventional O2O ON/OFF?
0223 #3-define an update(row) method that for each row takes the timestamp:
0224 # a-if timestamp already exist, updates the channel status of the relevant detIDs contained
0225 # 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
0226 #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)
0227 """
0228 import datetime,sys,copy
0229 def __init__(self,detIDPSUmapfilename="map.txt",mask_mapfilename="mask_map.txt",DetIDAliasFile="StripDetIDAlias.pkl",startTime=datetime.datetime.now(),debug=False):
0230 """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)"""
0231 self.debug=debug
0232 try:
0233 mapfile=open(detIDPSUmapfilename,'r')
0234 maplines=mapfile.readlines()
0235 mapfile.close()
0236
0237 self.detIDs=[int(line.split()[0]) for line in maplines]
0238
0239
0240
0241 if len(list(set(self.detIDs)))!=15148:
0242 print("There is an issue with the map provided: not reporting 15148 unique detIDs!")
0243
0244
0245
0246
0247
0248 self.PSUChannelListed=[line.split()[1] for line in maplines]
0249
0250 self.PSUs=list(set([PSUChannel[:-10] for PSUChannel in self.PSUChannelListed]))
0251
0252 if len(self.PSUs)!=1944:
0253 print("There is an issue with the map provided: not reporting 1944 unique Power Supplies!")
0254
0255
0256 self.PSUChannels=[]
0257 for PSU in self.PSUs:
0258 self.PSUChannels.append(PSU+"channel000")
0259 self.PSUChannels.append(PSU+"channel001")
0260 self.PSUChannels.append(PSU+"channel002")
0261 self.PSUChannels.append(PSU+"channel003")
0262
0263
0264 try:
0265 maskfile=open(mask_mapfilename,'r')
0266 self.masked_detIDs=[int(detID.rstrip()) for detID in maskfile]
0267 maskfile.close()
0268 except:
0269 self.masked_detIDs=[]
0270 print("No mask map was provided, assuming to start from a complete Tracker OFF state")
0271 try:
0272 DetIDAlias=open(DetIDAliasFile,"rb")
0273 DetIDAliasDict=pickle.load(DetIDAlias)
0274 DetIDAlias.close()
0275 self.DetIDAliasDict=DetIDAliasDict
0276 except:
0277 self.DetIDAliasDict={}
0278 print("No valid detID-Alias map pickle file was provided!")
0279 print("The TkrVoltageStatus object could not be initialized properly!")
0280 print("Please use an existing detIDPSUChannel mapfilename as argument!")
0281 sys.exit()
0282 except:
0283 print("Could not find detID-PSUchannel map to initialize the detIDs")
0284 print("The TkrVoltageStatus object could not be initialized properly! Please use an existing detIDPSUChannel mapfilename as argument!")
0285 sys.exit()
0286
0287
0288 self.DetIDPSUmap={}
0289 for detID in self.detIDs:
0290 self.DetIDPSUmap.update({detID:self.PSUChannelListed[self.detIDs.index(detID)]})
0291
0292 self.PSUDetIDmap={}
0293
0294
0295
0296
0297
0298
0299
0300
0301 for PSUChannel in self.PSUChannels:
0302 if PSUChannel.endswith("0") or PSUChannel.endswith("1"):
0303 self.PSUDetIDmap.update({PSUChannel:[detid for detid in self.DetIDPSUmap.keys() if PSUChannel[:-3] in self.DetIDPSUmap[detid]]})
0304 else:
0305 self.PSUDetIDmap.update({PSUChannel:[detid for detid in self.DetIDPSUmap.keys() if (PSUChannel in self.DetIDPSUmap[detid])]})
0306
0307
0308 self.PSUDetIDUnmappedMap={}
0309 UnmappedPSUs=list(set([psuchannel[:-10] for psuchannel in self.DetIDPSUmap.values() if psuchannel.endswith("000")]))
0310 self.PSUDetIDCrosstalkingMap={}
0311 CrosstalkingPSUs=list(set([psuchannel[:-10] for psuchannel in self.DetIDPSUmap.values() if psuchannel.endswith("999")]))
0312 for PSU in self.PSUs:
0313 if PSU in UnmappedPSUs:
0314 self.PSUDetIDUnmappedMap.update({PSU:[detid for detid in self.DetIDPSUmap.keys() if (self.DetIDPSUmap[detid].endswith("000") and PSU in self.DetIDPSUmap[detid])]})
0315 if PSU in CrosstalkingPSUs:
0316 self.PSUDetIDCrosstalkingMap.update({PSU:[detid for detid in self.DetIDPSUmap.keys() if (self.DetIDPSUmap[detid].endswith("999") and PSU in self.DetIDPSUmap[detid])]})
0317
0318
0319 self.UnmappedPSUChannelStatus={}
0320
0321 for PSU in self.PSUDetIDUnmappedMap.keys():
0322 self.UnmappedPSUChannelStatus.update({PSU+"channel002":0})
0323 self.UnmappedPSUChannelStatus.update({PSU+"channel003":0})
0324 self.CrosstalkingPSUChannelStatus={}
0325
0326 for PSU in self.PSUDetIDCrosstalkingMap.keys():
0327 self.CrosstalkingPSUChannelStatus.update({PSU+"channel002":0})
0328 self.CrosstalkingPSUChannelStatus.update({PSU+"channel003":0})
0329
0330
0331
0332
0333 self.startTime=startTime
0334
0335 self.PSUChannelHistory={startTime:range(len(self.PSUChannels))}
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347 for detID in self.masked_detIDs:
0348
0349
0350 self.PSUChannelHistory[startTime].remove(index(detIDPSUmap[detid][-1]+'0'))
0351 self.PSUChannelHistory[startTime].remove(index(detIDPSUmap[detid][-1]+'1'))
0352 self.PSUChannelHistory[startTime].remove(index(detIDPSUmap[detid][-1]+'2'))
0353 self.PSUChannelHistory[startTime].remove(index(detIDPSUmap[detid][-1]+'3'))
0354
0355
0356
0357
0358
0359
0360
0361 def updateO2OQuery(self,row):
0362 """Function to automatically handle the updating the of history dictionary
0363 with the results rows from the O2O query (PSUchannel name based).
0364 Note that row can be an actual row from SQLAlchemy from direct online DB querying
0365 but also a dictionary extracted parsing ManualO2O.log files.
0366 """
0367
0368
0369
0370
0371
0372
0373 if row['dpname'] not in self.PSUChannels:
0374 if self.debug:
0375 print("Discarding results row since it is not in the currently considered map:\n%s"%row['dpname'])
0376 return
0377
0378
0379
0380 lastTimeStamp,nextTimeStamp=self.getIOV(row['change_date'],self.PSUChannelHistory)
0381
0382 if self.debug:
0383 if row['change_date'] not in self.PSUChannelHistory.keys():
0384 if nextTimeStamp!="Infinity":
0385 print("WARNING! Asynchronous updating of the Tracker Voltage Status")
0386 print("WARNING! Inserting an IOV between %s, and %s existing timestamps!"%(lastTimeStamp,nextTimeStamp))
0387 print("The state will be correctly updated (if necessary) starting from the state at %s"%lastTimeStamp)
0388 else:
0389 print("Appending one more IOV to the PSUChannelHistory dictionary")
0390 else:
0391 print("Updating already present IOV with timestamp %s"%row['change_date'])
0392
0393
0394
0395 PSUChannelOFFList=self.PSUChannelHistory[lastTimeStamp][:]
0396 if row['actual_status']==1:
0397 try:
0398 PSUChannelOFFList.remove(self.PSUChannels.index(row['dpname']))
0399 self.PSUChannelHistory.update({row['change_date']:PSUChannelOFFList})
0400 except:
0401 if self.debug:
0402 print("Found a channel that turned ON but as already ON apparently!")
0403 print(row)
0404 else:
0405 PSUChannelOFFList.append(self.PSUChannels.index(row['dpname']))
0406 self.PSUChannelHistory.update({row['change_date']:list(set(PSUChannelOFFList))})
0407
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 def updateDetIDQuery(self,row):
0443 """Function to automatically handle the updating of the history dictionary
0444 with the result rows from detID based query
0445 """
0446
0447
0448 if row['change_date'] not in self.history.keys():
0449
0450
0451 lastTimeStamp=sorted(self.history.keys()).pop(0)
0452 self.history.update({row['change_date']:self.history[lastTimeStamp]})
0453
0454 channelStatus=self.history[row['change_date']][row['detid']]
0455
0456 channelStatus[row['channel']]=row['voltage_status']
0457
0458 self.history[row['change_date']].update({row['detid']:channelStatus})
0459
0460
0461
0462
0463
0464
0465 def getPSUChannelsOff(self,timestamp):
0466 """
0467 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.
0468 NOTE: No distinction between HV and LV is made since all PSUChannels (000/001 and 002/003) are reported.
0469 """
0470 StartTime,StopTime=self.getIOV(timestamp,self.PSUChannelHistory)
0471 PSUChannelsOFF=map(lambda x: self.PSUChannels[x],self.PSUChannelHistory[StartTime])
0472 PSUChannelsON=list(set(self.PSUChannels).difference(set(PSUChannelsOFF)))
0473 return PSUChannelsOFF,PSUChannelsON,StartTime,StopTime
0474
0475 def getDetIDsHVOff(self,timestamp):
0476 """
0477 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.
0478 """
0479 StartTime,StopTime=self.getIOV(timestamp,self.PSUChannelHistory)
0480 DetIDsHVOFF=[]
0481
0482
0483
0484 for index in self.PSUChannelHistory[StartTime]:
0485
0486 if self.PSUChannels[index].endswith("2") or self.PSUChannels[index].endswith("3") :
0487
0488 if self.PSUChannels[index] in self.PSUDetIDmap.keys():
0489
0490 DetIDsHVOFF.extend(self.PSUDetIDmap[self.PSUChannels[index]])
0491
0492 if self.PSUChannels[index][:-10] in self.PSUDetIDUnmappedMap.keys():
0493
0494
0495 DetIDsHVOFF.extend(self.PSUDetIDUnmappedMap[self.PSUChannels[index][:-10]])
0496
0497 if self.PSUChannels[index][:-10] in self.PSUDetIDCrosstalkingMap.keys():
0498
0499 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]):
0500
0501 DetIDsHVOFF.extend(self.PSUDetIDCrosstalkingMap[self.PSUChannels[index][:-10]])
0502 DetIDsHVON=list(set(self.detIDs).difference(set(DetIDsHVOFF)))
0503 return list(set(DetIDsHVOFF)),DetIDsHVON,StartTime,StopTime
0504
0505 def getDetIDsLVOff(self,timestamp):
0506 """
0507 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.
0508 """
0509
0510 StartTime,StopTime=self.getIOV(timestamp,self.PSUChannelHistory)
0511 DetIDsLVOFF=[]
0512 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"))]):
0513 DetIDsLVOFF.extend(detids)
0514 DetIDsLVON=list(set(self.detIDs).difference(set(DetIDsLVOFF)))
0515 return list(set(DetIDsLVOFF)),DetIDsLVON,StartTime,StopTime
0516
0517 def getAliasesHVOff(self,timestamp):
0518 """
0519 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.
0520 """
0521 DetIDsHVOFF,DetIDsHVON,StartTime,StopTime=self.getDetIDsHVOff(timestamp)
0522 AliasesHVOFF=list(set([list(self.DetIDAliasDict[detid])[0] for detid in DetIDsHVOFF]))
0523 AliasesHVON=list(set([list(self.DetIDAliasDict[detid])[0] for detid in DetIDsHVON]))
0524 return AliasesHVOFF,AliasesHVON,StartTime,StopTime
0525
0526 def getAliasesLVOff(self,timestamp):
0527 """
0528 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.
0529 """
0530 DetIDsLVOFF,DetIDsLVON,StartTime,StopTime=self.getDetIDsLVOff(timestamp)
0531 AliasesLVOFF=list(set([list(self.DetIDAliasDict[detid])[0] for detid in DetIDsLVOFF]))
0532 AliasesLVON=list(set([list(self.DetIDAliasDict[detid])[0] for detid in DetIDsLVON]))
0533 return AliasesLVOFF,AliasesLVON,StartTime,StopTime
0534
0535
0536
0537 def getDetIDsHVOffVsTime(self):
0538 """
0539 Function that returns the number of DetIDs with HV OFF vs time for all IOVs available in the PSUChannelHistory.
0540 The results is one list of tuples [(datetime.datetime,#DetIDsHVOFF),...] and the timestamp of the last entry processed in the PSUChannelHistory.
0541 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).
0542 This can be easily used to
0543 -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.
0544 -Plot the graph of number of HV OFF (or ON by complementing to 15148) vs time using pyRoot
0545 """
0546
0547 DetIDsHVOffVsTime=[]
0548 PreviousTimeStamp=None
0549 PreviousDetIDsHVOFF=[]
0550 for timestamp in sorted(self.PSUChannelHistory.keys()):
0551 DetIDsHVOFF=self.getDetIDsHVOff(timestamp)[0]
0552
0553 if PreviousTimeStamp:
0554 if DetIDsHVOFF!=PreviousDetIDsHVOFF:
0555 DetIDsHVOffVsTime.append((timestamp,len(DetIDsHVOFF)))
0556 else:
0557 DetIDsHVOffVsTime.append((timestamp,len(DetIDsHVOFF)))
0558 PreviousTimeStamp=timestamp
0559 PreviousDetIDsHVOFF=DetIDsHVOFF
0560 LastTimeStamp=PreviousTimeStamp
0561 return DetIDsHVOffVsTime,PreviousTimeStamp
0562
0563 def getDetIDsLVOffVsTime(self):
0564 """
0565 Function that returns the number of DetIDs with LV OFF vs time for all IOVs available in the PSUChannelHistory.
0566 The results is one list of tuples [(datetime.datetime,#DetIDsLVOFF),...], basically 1 entry per IOV (change in the LV channels only),
0567 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).
0568 This can be easily used to
0569 -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.
0570 -Plot the graph of number of HV OFF (or ON by complementing to 15148) vs time using pyRoot
0571 """
0572
0573 DetIDsLVOffVsTime=[]
0574 PreviousTimeStamp=None
0575 for timestamp in sorted(self.PSUChannelHistory.keys()):
0576 DetIDsLVOFF=set(self.getDetIDsLVOff(timestamp)[0])
0577
0578 if PreviousTimeStamp:
0579 if DetIDsLVOFF!=PreviousDetIDsLVOFF:
0580 DetIDsLVOffVsTime.append((timestamp,len(DetIDsLVOFF)))
0581 else:
0582 DetIDsLVOffVsTime.append((timestamp,len(DetIDsLVOFF)))
0583 PreviousTimeStamp=timestamp
0584 PreviousDetIDsLVOFF=DetIDsLVOFF
0585 LastTimeStamp=PreviousTimeStamp
0586 return DetIDsLVOffVsTime,LastTimeStamp
0587
0588
0589 def getArraysForTimePlots(self,TimeStampsValuesTuple):
0590 """
0591 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).
0592 """
0593 import array, time
0594
0595
0596 Timestamps=[]
0597 Values=[]
0598
0599 for item in sorted(TimeStampsValuesTuple):
0600
0601
0602
0603
0604 timestamp=int(time.mktime(item[0].timetuple()))
0605 if item==TimeStampsValuesTuple[0]:
0606 Timestamps.append(timestamp)
0607 Value=item[1]
0608 Values.append(Value)
0609 else:
0610 Timestamps.append(timestamp)
0611 Values.append(Value)
0612 Value=item[1]
0613 Timestamps.append(timestamp)
0614 Values.append(Value)
0615
0616 TimestampsArray=array.array('i',Timestamps)
0617 ValuesArray=array.array('i',Values)
0618
0619 return TimestampsArray,ValuesArray
0620
0621 def getReducedArraysForTimePlots(self,TimeStamps,Values):
0622 """
0623 Implement IOV reduction based on timestamp delta, following O2O algorithm.
0624 """
0625
0626 return
0627
0628
0629 def plotGraphSeconds(self,TimeArray,ValuesArray,GraphTitle="Graph",YTitle="Number of channels",GraphFilename="test.gif"):
0630 """
0631 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.
0632 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.
0633 """
0634 import ROOT
0635 canvas=ROOT.TCanvas()
0636 graph=ROOT.TGraph(len(TimeArray),TimeArray,ValuesArray)
0637 graph.GetXaxis().SetTimeDisplay(1)
0638 graph.GetXaxis().SetLabelOffset(0.02)
0639
0640 TotalTimeIntervalSecs=TimeArray[-1]-TimeArray[0]
0641 if TotalTimeIntervalSecs <= 120:
0642 graph.GetXaxis().SetTimeFormat("#splitline{ %d/%m}{%H:%M:%S}")
0643 elif 120 < TotalTimeIntervalSecs < 6400:
0644 graph.GetXaxis().SetTimeFormat("#splitline{%d/%m}{%H:%M}")
0645 else:
0646 graph.GetXaxis().SetTimeFormat("#splitline{%d/%m}{ %H}")
0647 graph.GetYaxis().SetTitle(YTitle)
0648 graph.GetYaxis().SetTitleOffset(1.4)
0649 graph.SetTitle(GraphTitle)
0650 graph.Draw("APL")
0651 canvas.SaveAs(GraphFilename)
0652 print("Saved graph as %s"%GraphFilename)
0653 return
0654 def plotPSUChannelvsTime(self,TimeArray,ValuesArray,GraphTitle="PSUChannelGraph",YTitle="Channel HV Status",GraphFilename="PSUChannel.gif"):
0655 """
0656 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.
0657 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.
0658 """
0659 import ROOT
0660 canvas=ROOT.TCanvas()
0661 graph=ROOT.TGraph(len(TimeArray),TimeArray,ValuesArray)
0662 graph.GetXaxis().SetTimeDisplay(1)
0663 graph.GetXaxis().SetLabelOffset(0.02)
0664
0665 TotalTimeIntervalSecs=TimeArray[-1]-TimeArray[0]
0666 if TotalTimeIntervalSecs <= 120:
0667 graph.GetXaxis().SetTimeFormat("#splitline{ %d/%m}{%H:%M:%S}")
0668 elif 120 < TotalTimeIntervalSecs < 6400:
0669 graph.GetXaxis().SetTimeFormat("#splitline{%d/%m}{%H:%M}")
0670 else:
0671 graph.GetXaxis().SetTimeFormat("#splitline{%d/%m}{ %H}")
0672 graph.GetYaxis().SetTitle(YTitle)
0673 graph.GetYaxis().SetTitleOffset(1.4)
0674 graph.SetTitle(GraphTitle)
0675 graph.Draw("APL")
0676 canvas.SaveAs(GraphFilename)
0677 print("Saved graph as %s"%GraphFilename)
0678 return
0679
0680 def plotHVOFFvsTime(self):
0681 """
0682 """
0683 return
0684
0685 def plotLVOFFvsTime(self):
0686 """
0687 """
0688 return
0689
0690 def plotDetIDHVOFFVsTime(self,detID):
0691 """
0692 """
0693 return
0694 def plotDetIDLVOFFVsTime(self,detID):
0695 """
0696 """
0697 return
0698
0699 def plotDetIDHistory(self):
0700 return
0701
0702 def getIOV(self,timeStamp,HistoryDict):
0703 """
0704 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.
0705 This can be used by all functions that need to access HistoryDict by timeStamp.
0706 """
0707
0708 TimeStamps=HistoryDict.keys()[:]
0709
0710 if timeStamp not in TimeStamps:
0711 TimeStamps.append(timeStamp)
0712
0713 TimeStamps.sort()
0714 TimeStampStart=TimeStamps[TimeStamps.index(timeStamp)-1]
0715
0716 TimeStamps.remove(timeStamp)
0717 else:
0718 TimeStamps.sort()
0719 TimeStampStart=timeStamp
0720
0721 if len(TimeStamps)>TimeStamps.index(TimeStampStart)+1:
0722 TimeStampStop=TimeStamps[TimeStamps.index(TimeStampStart)+1]
0723 else:
0724 TimeStampStop="Infinity"
0725 if self.debug:
0726 print("TimeStamp %s falls into IOV starting at %s and ending at %s"%(timeStamp,TimeStampStart,TimeStampStop))
0727 return (TimeStampStart,TimeStampStop)
0728
0729 def getIOVsInTimeInterval(self,StartTime,StopTime,HistoryDict):
0730 """
0731 Function that returns the IOV timestamps (ordered) contained in a given interval.
0732 """
0733
0734 TimeStamps=sorted(HistoryDict.keys()[:])
0735 IOVsInTimeInterval=[]
0736
0737 for timestamp in TimeStamps:
0738 if timestamp>=StartTime and timestamp<=StopTime:
0739 if self.debug:
0740 print("Found timestamp %s in the wanted interval [%s,%s]"%(timestamp,StartTime,StopTime))
0741 IOVsInTimeInterval.append(timestamp)
0742 return IOVsInTimeInterval
0743
0744 def getReducedIOVs (self,StartTime,StopTime,HistoryDict,deltaT,maxIOVLength):
0745 """
0746 Apply the reduction algorithm to the timeintervals and return them so that one can test the reduction (and do plots more easily).
0747 """
0748 deltaTime=datetime.timedelta(seconds=deltaT)
0749 maxSequenceLength=datetime.timedelta(seconds=maxIOVLength)
0750
0751 TimeStamps=sorted(HistoryDict.keys()[:])
0752 ReducedIOVs=TimeStamps[:]
0753 PreviousTimestamp=TimeStamps[0]
0754 SequenceStart=TimeStamps[0]
0755 SequenceOn=False
0756
0757
0758 for timestamp in TimeStamps[1:]:
0759
0760 if timestamp>=StartTime and timestamp<=StopTime:
0761
0762 if timestamp-PreviousTimestamp<=deltaTime:
0763
0764 if SequenceOn:
0765
0766 if (timestamp-SequenceStart)<=maxSequenceLength and timestamp!=TimeStamps[-1]:
0767 if self.debug:
0768 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))
0769 ReducedIOVs.remove(timestamp)
0770 elif timestamp==TimeStamps[-1]:
0771 if self.debug:
0772 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))
0773 else:
0774
0775 SequenceOn=False
0776
0777 ReducedIOVs.append(PreviousTimestamp)
0778
0779 ReducedIOVs.sort()
0780 if self.debug:
0781 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))
0782 else:
0783
0784 SequenceOn=True
0785
0786 if self.debug:
0787 print("@@@Starting a new IOV sequence with previous timestamp %s (current being %s)"%(PreviousTimestamp,timestamp))
0788
0789 ReducedIOVs.remove(timestamp)
0790 SequenceStart=PreviousTimestamp
0791 else:
0792
0793 if SequenceOn:
0794
0795 SequenceOn=False
0796
0797 ReducedIOVs.append(PreviousTimestamp)
0798
0799 ReducedIOVs.sort()
0800 if self.debug:
0801 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))
0802
0803 else:
0804
0805
0806
0807 ReducedIOVs.remove(timestamp)
0808
0809 if SequenceOn:
0810
0811 SequenceOn=False
0812
0813 ReducedIOVs.append(PreviousTimestamp)
0814
0815 ReducedIOVs.sort()
0816 if self.debug:
0817 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))
0818 PreviousTimestamp=timestamp
0819 return ReducedIOVs
0820
0821
0822
0823 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)
0824
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 QueryResults=GetQueryResults("ManualO2O.log")
0927
0928
0929
0930
0931 counter=0
0932 hours=72
0933 for interval in sorted(QueryResults.keys()):
0934 counter+=1
0935 if counter<hours:
0936 print("Updating TkStatus with query results for time interval %s to %s"%interval)
0937 for row in QueryResults[interval]:
0938 TkStatus.updateO2OQuery(row)
0939 print(len(TkStatus.PSUChannelHistory))
0940 if counter-hours>0:
0941 print("Number of intervals skipped %s"%(counter-hours))
0942
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 ReducedIOVsTimestamps=TkStatus.getReducedIOVs(datetime.datetime(2010, 8, 27, 12, 0),datetime.datetime(2010, 8, 29, 17, 45),TkStatus.PSUChannelHistory,15,120)
1082
1083 print("Dumping ReducedIOVsTimestamps and the corresponding timestamp index and number of HV/LV channels off:")
1084 for timestamp in ReducedIOVsTimestamps:
1085 TkStatus.debug=False
1086 print(timestamp,sorted(TkStatus.PSUChannelHistory.keys()).index(timestamp),len(TkStatus.getDetIDsHVOff(timestamp)[0]), len(TkStatus.getDetIDsLVOff(timestamp)[0]))
1087
1088
1089 def ReducedIOVsHistory(ReducedIOVsTimestamps):
1090 """
1091 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.
1092 """
1093
1094 AllTimestamps=sorted(TkStatus.PSUChannelHistory.keys())
1095 PreviousTimestampIndex=-1
1096 ReducedIOVsDict={}
1097 for timestamp in ReducedIOVsTimestamps:
1098 if AllTimestamps.index(timestamp)!=(PreviousTimestampIndex+1):
1099
1100 LVOffEnd=TkStatus.getDetIDsLVOff(timestamp)[0]
1101
1102 LVOffStart=TkStatus.getDetIDsLVOff(AllTimestamps[PreviousTimestampIndex])[0]
1103
1104 HVOffEnd=TkStatus.getDetIDsHVOff(timestamp)[0]
1105
1106 HVOffStart=TkStatus.getDetIDsHVOff(AllTimestamps[PreviousTimestampIndex])[0]
1107
1108
1109
1110 if len(LVOffEnd)>len(LVOffStart) or len(HVOffEnd)>len(HVOffStart):
1111 ReducedIOVsDict.update({AllTimestamps[PreviousTimestampIndex]:(TkStatus.getDetIDsHVOff(timestamp)[0],TkStatus.getDetIDsLVOff(timestamp)[0])})
1112
1113
1114
1115
1116 if set(TkStatus.getDetIDsHVOff(timestamp)[0])!=set(TkStatus.getDetIDsHVOff(AllTimestamps[PreviousTimestampIndex])[0]) or set(TkStatus.getDetIDsLVOff(timestamp)[0])!=set(TkStatus.getDetIDsLVOff(AllTimestamps[PreviousTimestampIndex])[0]):
1117 ReducedIOVsDict.update({timestamp:(TkStatus.getDetIDsHVOff(timestamp)[0],TkStatus.getDetIDsLVOff(timestamp)[0])})
1118 PreviousTimestampIndex=AllTimestamps.index(timestamp)
1119 return ReducedIOVsDict
1120
1121
1122 ValidationReducedIOVsHistory=ReducedIOVsHistory(ReducedIOVsTimestamps)
1123
1124
1125
1126
1127
1128
1129 print("Dumping ValidationReducedIOVsHistory contents:")
1130 for timestamp in sorted(ValidationReducedIOVsHistory.keys()):
1131 print(timestamp, len(ValidationReducedIOVsHistory[timestamp][0]),len(ValidationReducedIOVsHistory[timestamp][1]))
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144 def ExtractDetVOffInfo(directory=os.getcwd()):
1145 """
1146 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).
1147 """
1148 ls=os.listdir(directory)
1149 TimesLogs=[]
1150 O2OData={}
1151 for log in ls:
1152 if "DetVOffReaderDebug__FROM" in log:
1153 (start,end)=log[:-4].split("FROM_")[1].split("_TO_")
1154 TimeStamp=datetime.datetime.strptime(start.replace("__","_0"),"%a_%b_%d_%H_%M_%S_%Y")
1155
1156 file=open(log,'r')
1157 filelines=file.readlines()
1158 file.close()
1159 LVOff=[]
1160 HVOff=[]
1161 for line in filelines:
1162
1163 if "OFF" in line:
1164 detid,hv,lv=line.split()
1165
1166 if hv=="OFF":
1167 HVOff.append(int(detid))
1168 if lv=="OFF":
1169 LVOff.append(int(detid))
1170
1171 O2OData.update({TimeStamp:(HVOff,LVOff)})
1172 return O2OData
1173
1174
1175 O2OReducedIOVs=ExtractDetVOffInfo()
1176
1177 print("Dumping the O2OReducedIOVs contents:")
1178 for timestamp in sorted(O2OReducedIOVs.keys()):
1179 print(timestamp, len(O2OReducedIOVs[timestamp][0]),len(O2OReducedIOVs[timestamp][1]))
1180
1181
1182
1183
1184
1185
1186 def CompareReducedDetIDs(FirstDict,SecondDict):
1187 """
1188 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.
1189 """
1190 DifferenceDict={}
1191 for timestamp in sorted(FirstDict.keys()):
1192 if timestamp.replace(microsecond=0) in SecondDict.keys():
1193 secondtimestamp=timestamp.replace(microsecond=0)
1194 print("Timestamp %s is present in both Dictionaries!"%timestamp)
1195 else:
1196 secondtimestamps=sorted(SecondDict.keys())
1197 secondtimestamps.append(timestamp)
1198 secondtimestamps.sort()
1199 if secondtimestamps.index(timestamp)!=0:
1200 secondtimestamp=secondtimestamps[secondtimestamps.index(timestamp)-1]
1201 else:
1202 secondtimestamp=secondtimestamps[secondtimestamps.index(timestamp)+1]
1203 print("Comparing the IOV with timestamp %s (1st dict) with IOV with timestamp %s (2nd dict)"%(timestamp,secondtimestamp))
1204 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])):
1205 if len(set(FirstDict[timestamp][0]))<=len(set(SecondDict[secondtimestamp][0])):
1206 differenceHV=set(map(lambda x:int(x),SecondDict[secondtimestamp][0]))-set(map(lambda x:int(x),FirstDict[timestamp][0]))
1207 else:
1208
1209 differenceHV=set(map(lambda x:int(x),FirstDict[timestamp][0]))-set(map(lambda x:int(x),SecondDict[secondtimestamp][0]))
1210
1211
1212
1213
1214 if len(set(FirstDict[timestamp][1]))<=len(set(SecondDict[secondtimestamp][1])):
1215 differenceLV=set(map(lambda x:int(x),SecondDict[secondtimestamp][1]))-set(map(lambda x:int(x),FirstDict[timestamp][1]))
1216 else:
1217
1218 differenceLV=set(map(lambda x:int(x),FirstDict[timestamp][1]))-set(map(lambda x:int(x),SecondDict[secondtimestamp][1]))
1219
1220
1221
1222
1223 DifferenceDict.update({(timestamp,secondtimestamp):(differenceHV,differenceLV)})
1224 print("Difference in timestamp %s (corresponding to %s):"%(timestamp,secondtimestamp))
1225
1226
1227
1228
1229
1230
1231 else:
1232 print("Timestamp %s is identical in both dictionaries"%timestamp)
1233 return DifferenceDict
1234 Comparison=CompareReducedDetIDs(ValidationReducedIOVsHistory,O2OReducedIOVs)
1235 print("Dumping the results of the comparisons of the two dictionaries:")
1236 for timestamps in sorted(Comparison.keys()):
1237 print(timestamps, Comparison[timestamps])
1238 if Comparison[timestamps][0]:
1239 print("HV:")
1240 if Comparison[timestamps][0].issubset(set(O2OReducedIOVs[timestamps[1]][0])):
1241 print("Only in O2O Dict!")
1242 else:
1243 print("Only in Validation Dict!")
1244 for detid in Comparison[timestamps][0]:
1245 print(detid,TkStatus.DetIDAliasDict[detid])
1246 if Comparison[timestamps][1]:
1247 print("LV:")
1248 if Comparison[timestamps][1].issubset(set(O2OReducedIOVs[timestamps[1]][1])):
1249 print("Only in O2O Dict!")
1250 else:
1251 print("Only in Validation Dict!")
1252 for detid in Comparison[timestamps][1]:
1253 print(detid,TkStatus.DetIDAliasDict[detid])
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263 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)
1264 DBQueryPickle=open('/afs/cern.ch/user/g/gbenelli/scratch0/O2OValidation/QueryResults.pkl','rb')
1265 DBQueryResults=[]
1266 DBQueryResults=pickle.load(DBQueryPickle)
1267 DBQueryPickle.close()
1268 for row in DBQueryResults:
1269 TkStatusFromQuery.updateO2OQuery(row)
1270 print(len(TkStatusFromQuery.PSUChannelHistory))
1271
1272 delta=datetime.timedelta(seconds=7200)
1273 counter=0
1274 DifferingTimestamps=[]
1275 for timestamp in sorted(TkStatus.PSUChannelHistory.keys()):
1276 if timestamp-delta!=sorted(TkStatusFromQuery.PSUChannelHistory.keys())[counter]:
1277 print(timestamp, sorted(TkStatusFromQuery.PSUChannelHistory.keys())[counter])
1278 DifferingTimestamps.append(timestamp,sorted(TkStatusFromQuery.PSUChannelHistory.keys())[counter])
1279 counter=counter+1
1280 if DifferingTimestamps:
1281 print("There are %s timestamps that are different in the 2 TkVoltageStatus objects!"%len(DifferingTimestamps))
1282
1283
1284
1285
1286
1287
1288 LVChannelHistory={}
1289 HVChannelHistory={}
1290 for interval in QueryResults.keys():
1291 for row in QueryResults[interval]:
1292 if row['dpname'].endswith('0') or row['dpname'].endswith('1'):
1293 if row['dpname'][:-1] not in LVChannelHistory.keys():
1294 LVChannelHistory.update({row['dpname'][:-1]:[(row['change_date'],row['actual_status'])]})
1295 else:
1296 LVChannelHistory[row['dpname'][:-1]].append((row['change_date'],row['actual_status']))
1297 else:
1298 if row['dpname'] not in HVChannelHistory.keys():
1299 HVChannelHistory.update({row['dpname']:[(row['change_date'],row['actual_status'])]})
1300 else:
1301 HVChannelHistory[row['dpname']].append((row['change_date'],row['actual_status']))
1302
1303
1304
1305
1306
1307 if row['change_date']>datetime.datetime(2010, 8, 28, 22, 44) and row['change_date']<datetime.datetime(2010, 8, 28, 23, 5,37):
1308 print(row)
1309
1310
1311
1312 for row in sorted(HVChannelHistory['cms_trk_dcs_04:CAEN/CMS_TRACKER_SY1527_6/branchController02/easyCrate3/easyBoard15/channel002']):
1313 print(row[0],row[1])
1314 for row in sorted(HVChannelHistory['cms_trk_dcs_04:CAEN/CMS_TRACKER_SY1527_6/branchController02/easyCrate3/easyBoard15/channel003']):
1315 print(row[0],row[1])
1316 print(TkStatus.PSUChannelHistory[sorted(TkStatus.PSUChannelHistory.keys())[sorted(TkStatus.PSUChannelHistory.keys()).index(datetime.datetime(2010, 8, 28, 22, 52, 8, 994000))-1]])
1317 a=TkStatus.getIOV(datetime.datetime(2010, 8, 28, 22, 51, 16),TkStatus.PSUChannelHistory)
1318
1319
1320 import array, time
1321 TOBminus_1_3_1_4_HV1_Status=HVChannelHistory['cms_trk_dcs_04:CAEN/CMS_TRACKER_SY1527_6/branchController02/easyCrate3/easyBoard15/channel002']
1322
1323 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)]
1324 TOBTimestamps=[]
1325 TOBHVStatus=[]
1326 for item in TOBminus_1_3_1_4_HV1_Status:
1327 timestamp=int(time.mktime(item[0].timetuple()))
1328 if item==TOBminus_1_3_1_4_HV1_Status[0]:
1329 TOBTimestamps.append(timestamp)
1330 HVStatus=int(item[1]==1)
1331 TOBHVStatus.append(HVStatus)
1332 else:
1333 TOBTimestamps.append(timestamp)
1334 TOBHVStatus.append(HVStatus)
1335 HVStatus=int(item[1]==1)
1336 TOBTimestamps.append(timestamp)
1337 TOBHVStatus.append(HVStatus)
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352 TOBTimestampsArray=array.array('i',TOBTimestamps)
1353 TOBHVStatusArray=array.array('i',TOBHVStatus)
1354
1355 TkStatus.plotGraphSeconds(TOBTimestampsArray,TOBHVStatusArray,GraphTitle="PSUChannelGraph",YTitle="Channel HV Status",GraphFilename="PSUChannel.gif")
1356 TOBminus_1_3_1_4_HV1_Status=HVChannelHistory['cms_trk_dcs_04:CAEN/CMS_TRACKER_SY1527_6/branchController02/easyCrate3/easyBoard15/channel003']
1357
1358 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)]
1359 TOBTimestamps=[]
1360 TOBHVStatus=[]
1361 for item in TOBminus_1_3_1_4_HV1_Status:
1362 timestamp=int(time.mktime(item[0].timetuple()))
1363 if item==TOBminus_1_3_1_4_HV1_Status[0]:
1364 TOBTimestamps.append(timestamp)
1365 HVStatus=int(item[1]==1)
1366 TOBHVStatus.append(HVStatus)
1367 else:
1368 TOBTimestamps.append(timestamp)
1369 TOBHVStatus.append(HVStatus)
1370 HVStatus=int(item[1]==1)
1371 TOBTimestamps.append(timestamp)
1372 TOBHVStatus.append(HVStatus)
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387 TOBTimestampsArray=array.array('i',TOBTimestamps)
1388 TOBHVStatusArray=array.array('i',TOBHVStatus)
1389
1390 TkStatus.plotGraphSeconds(TOBTimestampsArray,TOBHVStatusArray,GraphTitle="PSUChannelGraph",YTitle="Channel HV Status",GraphFilename="PSUChannelHV2.gif")
1391 def plotPSUChannelvsTime(self,TimeArray,ValuesArray,GraphTitle="PSUChannelGraph",YTitle="Channel HV Status",GraphFilename="PSUChannel.gif"):
1392 """
1393 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.
1394 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.
1395 """
1396 import ROOT
1397 canvas=ROOT.TCanvas()
1398 graph=ROOT.TGraph(len(TimeArray),TimeArray,ValuesArray)
1399 graph.GetXaxis().SetTimeDisplay(1)
1400 graph.GetXaxis().SetLabelOffset(0.02)
1401
1402 TotalTimeIntervalSecs=TimeArray[-1]-TimeArray[0]
1403 if TotalTimeIntervalSecs <= 120:
1404 graph.GetXaxis().SetTimeFormat("#splitline{ %d/%m}{%H:%M:%S}")
1405 elif 120 < TotalTimeIntervalSecs < 6400:
1406 graph.GetXaxis().SetTimeFormat("#splitline{%d/%m}{%H:%M}")
1407 else:
1408 graph.GetXaxis().SetTimeFormat("#splitline{%d/%m}{ %H}")
1409 graph.GetYaxis().SetTitle(YTitle)
1410 graph.GetYaxis().SetTitleOffset(1.4)
1411 graph.SetTitle(GraphTitle)
1412 graph.Draw("APL")
1413 canvas.SaveAs(GraphFilename)
1414 print("Saved graph as %s"%GraphFilename)
1415 return
1416
1417
1418 ReducedIOVsTimestampsTEST=TkStatus.getReducedIOVs(datetime.datetime(2010, 8, 27, 12, 0),datetime.datetime(2010, 8, 29, 17, 45),TkStatus.PSUChannelHistory,2,90)
1419
1420 print("Dumping ReducedIOVsTimestamps and the corresponding timestamp index and number of HV/LV channels off:")
1421 for timestamp in ReducedIOVsTimestampsTEST:
1422 TkStatus.debug=False
1423 print(timestamp,sorted(TkStatus.PSUChannelHistory.keys()).index(timestamp),len(TkStatus.getDetIDsHVOff(timestamp)[0]), len(TkStatus.getDetIDsLVOff(timestamp)[0]))
1424 ValidationReducedIOVsHistoryTEST=ReducedIOVsHistory(ReducedIOVsTimestampsTEST)
1425 print("Dumping ValidationReducedIOVsHistory contents:")
1426 for timestamp in sorted(ValidationReducedIOVsHistoryTEST.keys()):
1427 print(timestamp, len(ValidationReducedIOVsHistoryTEST[timestamp][0]),len(ValidationReducedIOVsHistoryTEST[timestamp][1]))