CMS 3D CMS Logo

pyDBSguiBaseClass.py

Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 #################################################
00004 #
00005 # DQMfromDBSgui.py
00006 #
00007 # v1.3 Beta
00008 #
00009 # by Jeff Temple (jtemple@fnal.gov)
00010 #
00011 # 10 May 2008
00012 #
00013 # v1.3 updates -- separate code into subpackages
00014 #      introduce separate file, dataset substrings
00015 #      reposition daughter windows relative to parent
00016 
00017 # GUI to automatically grab new runs from DBS
00018 # and run HCAL DQM on any newly-found runs
00019 #
00020 #################################################
00021 
00022 import sys
00023 import os # used for sending user commands
00024 base=os.popen2("echo $CMSSW_BASE")
00025 base=base[1].read()
00026 if len(base)<2:
00027     print "No $CMSSW_BASE directory can be found."
00028     print "Are you sure you've set up your CMSSW release area?"
00029     sys.exit()
00030                                                  
00031 
00032 try:
00033     from Tkinter import *
00034 except:
00035     print "Could not import Tkinter module!"
00036     print "Cannot display GUI!"
00037     print "(If you are running from FNAL, this is a known problem --\n"
00038     print " Tkinter isn't available in the SL4 release of python for some reason."
00039     print "This is being investigated.)"
00040     sys.exit()
00041 
00042 import tkMessageBox # for displaying warning messages
00043 
00044 import thread # used for automated checking; may not be necessary
00045 import time # use to determine when to check for files
00046 import cPickle # stores file information
00047 import python_dbs # use for "sendmessage" function to get info from DBS
00048 import string # DBS output parsing
00049 import helpfunctions  # displays text in new window
00050 
00051 
00052 from pyDBSRunClass import FileInfo, DBSRun  # Gets class that holds information as to whether a given run has been processed through DQM
00053 
00054 from pydbsAccessor import dbsAccessor  # sends queries to DBS
00055 import pyRunSummaryBaseClass # accesses html output from RunSummary page
00056     
00057 
00058 ###################################################################
00059 class dbsBaseGui:
00060     '''
00061     dbsBaseGui:  Base Class for finding files in DBS, running analyses on them
00062 
00063     '''
00064     
00065     def __init__(self, parent=None, debug=False):
00066 
00067         '''
00068         **self.__init__(parent=None, debug=False)**
00069         dbsBaseGui.__init__  sets up all class variables used by the GUI.
00070         '''
00071 
00072         # Check that CMSSW environment has been set;
00073         # Set basedir to CMSSW release area
00074         checkCMSSW=os.popen2("echo $CMSSW_BASE")
00075         self.basedir=checkCMSSW[1].read()
00076         if len(self.basedir)<2:
00077             print "No $CMSSW_BASE directory can be found."
00078             print "Are you sure you've set up your CMSSW release area?"
00079             sys.exit()
00080 
00081 
00082         self.cmsVersion=string.split(self.basedir,"/")[-1]
00083         self.cmsVersion=string.strip(self.cmsVersion)
00084         self.cmsVersion=string.split(self.cmsVersion,"_")[1:]
00085 
00086 
00087         # Now set base directory to area of release containing GUI
00088         self.basedir=self.basedir.strip("\n")
00089         self.basedir=os.path.join(self.basedir,"src/DQM/HcalMonitorModule/python/dqmdbsGUI")
00090         if not os.path.exists(self.basedir):
00091             print "Unable to find directory '%s'"%self.basedir
00092             print "Have you checked out the appropriate package in your release area?"
00093             sys.exit()
00094 
00095         os.chdir(self.basedir)  # put all output into basedir
00096 
00097 
00098         # init function should define all variables needed for the creation of the GUI
00099         self.debug=debug
00100         if (self.debug):
00101             print self.__doc__
00102             print self.__init__.__doc__
00103 
00104         self.parent=parent  # parent window in which GUI is drawn (a new window is created if parent==None)
00105         # Create GUI window
00106         if (self.parent==None):
00107             self.root=Tk()
00108             self.root.title("HCAL DQM from DBS GUI")
00109             self.root.geometry('+25+25') # set initial position of GUI
00110         else:
00111             self.root=self.parent # could conceivably put GUI within another window
00112 
00113         #######################################
00114         # Set up bg, fg colors for use by GUI #
00115         #######################################
00116         self.bg="#ffff73cb7"  # basic background color -- peach-ish
00117         self.bg_alt="#b001d0180" # alternate bg - dark red-ish
00118         self.fg="#180580410" # basic fg color -- green/grey-ish
00119         self.alt_active="gold3" # active bg for buttons
00120 
00121         self.enableSCP=BooleanVar() # variable to determine whether 'scp' copying is enabled
00122         #self.enableSCP.set(True)# disabled this by default at Efe's request, 11 June 2008
00123         self.enableSCP.set(False) 
00124 
00125         # Set possible auto-update times (in minutes) for DBS, DQM
00126         self.updateTimes=(2,5,10,20,30,60,120)
00127         # Set blocks of Luminosity over which to search
00128         self.lumiBlockRanges=("All",1,2,5,10,20,50,100,200,500,1000)
00129         self.lumiBlockRange=StringVar()
00130         self.lumiBlockRange.set("All")
00131         
00132         # Variables used for starting point, range of runs to search when looking at DBS
00133         self.dbsRange=IntVar()
00134         self.lastFoundDBS=IntVar()
00135 
00136         # Create boolean for determining whether or not Auto-running
00137         # is enabled
00138         self.Automated=BooleanVar()
00139         self.Automated.set(False)
00140         # "Sub"-booleans for toggling DBS, DQM independently when Auto-running is enabled
00141         self.dbsAutoVar=BooleanVar()
00142         self.dbsAutoVar.set(False)
00143         self.dqmAutoVar=BooleanVar()
00144         self.dqmAutoVar.set(False)
00145         
00146         # DQM output is initially stored locally;
00147         #self.finalDir determines where
00148         # it will be sent once the DQM has finished running.
00149         self.finalDir=StringVar()
00150        
00151         # Store maximum # of events to be run for each DQM job 
00152         self.maxDQMEvents=IntVar()
00153         self.maxDQMEvents.set(1000)
00154 
00155         self.prescaleOverRun=BooleanVar()
00156         self.prescaleOverRun.set(False)
00157         self.prescaleOverRunText="# prescale (unused) = "
00158 
00159         # TO DO:  Make this default value changeable by user?  Save in cPickle?
00160         self.dbsRange.set(100) # specify range of runs over which to search, starting at the LastDBS value
00161 
00162         self.lastFoundDBS.set(64042) # specify last run # found in DBS
00163 
00164         self.foundfiles=0 # number of files found in the latest DBS search -- deprecated variable?
00165 
00166         self.dbsSearchInProgress=False
00167         self.pickleFileOpen=False
00168         self.runningDQM=False
00169 
00170 
00171         # Set initial DBS auto-update interval to 20 minutes
00172         self.dbsAutoUpdateTime=IntVar()
00173         self.dbsAutoUpdateTime.set(20) # dbs update time in minutes
00174         self.dbsAutoCounter=0
00175         # Set initial DQM auto-update interval to 20 minutes
00176         self.dqmAutoUpdateTime=IntVar()
00177         self.dqmAutoUpdateTime.set(20) # dqm update time in minutes
00178 
00179         self.dqmAutoCounter=0
00180         self.autoRunning=False
00181         self.hbcolor=self.bg # heartbeat color
00182 
00183         self.cfgFileName=StringVar()
00184         if (string.atoi(self.cmsVersion[0]) < 2 or (string.atoi(self.cmsVersion[0])==2 and string.atoi(self.cmsVersion[1])<1)):
00185             self.mycfg="hcal_dqm_dbsgui.cfg"
00186         else:
00187             self.mycfg="hcal_dqm_dbsgui_cfg.py"
00188 
00189 
00190         self.autoRunShift=True # automatically updates run entry when new run found
00191 
00192         self.cmsRunOutput=[] # will store files, dirs successfully created by cmsRun
00193         return
00194 
00195 
00196 
00197     
00198 
00199 
00200     def DrawGUI(self):
00201         '''
00202         ** self.DrawGUI() **
00203         Creates GUI window, grids all Tkinter objects within the window.
00204         This function should only contain calls to objects in the GUI display.
00205         Variables attached to those objects are created in the __init__ method.
00206         '''
00207 
00208         if (self.debug):
00209             print self.DrawGUI.__doc__
00210             
00211         self.root.configure(bg=self.bg)
00212         rootrow=0
00213         
00214         # Make menubar
00215         self.menubar=Frame(self.root,borderwidth=1,
00216                            bg=self.bg,
00217                            relief='raised')
00218         self.root.columnconfigure(0,weight=1) # allows column 0 to expand
00219         self.root.rowconfigure(1,weight=1)
00220         
00221         self.menubar.grid(row=rootrow,column=0,sticky=EW)
00222 
00223 
00224         # Create frame that holds search values (i.e., run range to search in DBS)
00225         rootrow=rootrow+1
00226         self.searchFrame=Frame(self.root,
00227                                bg=self.bg)
00228                                
00229         self.searchFrame.grid(row=rootrow,
00230                               sticky=EW,
00231                               column=0)
00232 
00233 
00234         # Create main Frame (holds "Check DBS" and "Check DQM" buttons and status values)
00235         rootrow=rootrow+1
00236         self.mainFrame=Frame(self.root,
00237                              bg=self.bg)
00238         self.mainFrame.grid(row=rootrow,column=0,sticky=EW)
00239 
00240         # Frame that will display overall status messages
00241         rootrow=rootrow+1
00242         self.statusFrame=Frame(self.root,
00243                                bg=self.bg
00244                                )
00245         self.statusFrame.grid(row=rootrow,column=0,sticky=EW)
00246 
00247 
00248         ########################################################
00249         #                                                      #
00250         #  Fill the menu bar                                   #
00251         #                                                      #
00252         ########################################################
00253         
00254         mycol=0
00255 
00256         # make File button on menubar
00257         self.BFile=Menubutton(self.menubar,
00258                               text = "File",
00259                               font = ('Times',12,'bold italic'),
00260                               activebackground=self.bg_alt,
00261                               activeforeground=self.bg,
00262                               bg=self.bg,
00263                               fg=self.fg,
00264                               padx=10, pady=8)
00265         self.BFile.grid(row=0,column=mycol,sticky=W)
00266 
00267         # Make DBS option menu on menubar
00268         mycol=mycol+1
00269         self.Bdbs=Menubutton(self.menubar,
00270                              text="DBS options",
00271                              font= ('Times',12,'bold italic'),
00272                              activebackground=self.bg_alt,
00273                              activeforeground=self.bg,
00274                              bg=self.bg,
00275                              fg=self.fg,
00276                              padx=10, pady=8)
00277         self.Bdbs.grid(row=0,column=mycol,sticky=W)
00278 
00279         # Make DQM option menu on menubar
00280         mycol=mycol+1
00281         self.Bdqm=Menubutton(self.menubar,
00282                              text="DQM options",
00283                              font= ('Times',12,'bold italic'),
00284                              activebackground=self.bg_alt,
00285                              activeforeground=self.bg,
00286                              bg=self.bg,
00287                              fg=self.fg,
00288                              padx=10, pady=8)
00289         self.Bdqm.grid(row=0,column=mycol,sticky=W)
00290 
00291         # Make status button on menubar
00292         mycol=mycol+1
00293         self.Bprogress=Menubutton(self.menubar,
00294                                   text="Status",
00295                                   font=('Times',12,'bold italic'),
00296                                   activebackground=self.bg_alt,
00297                                   activeforeground=self.bg,
00298                                   bg=self.bg,
00299                                   fg=self.fg,
00300                                   padx=10, pady=8)
00301         self.Bprogress.grid(row=0,column=mycol)
00302 
00303         # Eventually will allow copying of files to destinations
00304         # outside local areas
00305         mycol=mycol+1
00306         self.menubar.columnconfigure(mycol,weight=1)
00307         self.scpAutoButton=Checkbutton(self.menubar,
00308                                        bg=self.bg,
00309                                        fg=self.fg,
00310                                        text="scp copying enabled",
00311                                        activebackground=self.alt_active,
00312                                        variable=self.enableSCP,
00313                                        padx=10,
00314                                        command=self.toggleSCP)
00315 
00316         # Uncomment this line to bring back enablescp button
00317         #self.scpAutoButton.grid(row=0,column=mycol,sticky=E)
00318 
00319         # This is an old implementation of scp choices.
00320         # Can it be removed?  Jeff, 10 May 2008
00321         
00322         #mycol=mycol+1
00323         #self.menubar.columnconfigure(mycol,weight=1)
00324         #self.scpLabel=Label(self.menubar,
00325         #                    #text="Copy DQM to:",
00326         #                    text="scp copying enabled ",
00327         #                    fg=self.fg,bg=self.bg).grid(row=0,
00328         #                                                column=mycol,
00329         #                                                sticky=E)
00330         mycol=mycol+1
00331         # Add in variable copy abilities later
00332         #self.copyLocVar=StringVar()
00333         #self.copyLocVar.set("Local area")
00334         # List possible copy destinations
00335         # (not yet implemented, until we can figure out how to
00336         #  auto scp)
00337         #self.copyLoc=OptionMenu(self.menubar,self.copyLocVar,
00338         #                        "Local area"
00339         #                        #"cmshcal01"
00340         #                        )
00341         #self.copyLoc.configure(background=self.bg,
00342         #                       foreground=self.fg,
00343         #                       activebackground=self.alt_active)
00344 
00345 
00346         # for now, use a button to copy files with scp
00347         self.copyLoc=Button(self.menubar,
00348                             text="Copy Output\nto cmshcal01!",
00349                             command=lambda x=self:x.tempSCP())
00350         self.copyLoc.configure(background=self.bg_alt,
00351                                foreground=self.bg,
00352                                activebackground=self.alt_active)
00353 
00354         # uncomment this to allow scp copying
00355         #self.copyLoc.grid(row=0,column=mycol,sticky=E)
00356 
00357         # Turn off copying by default if user is not "cchcal"
00358         if os.getenv("USER")<>"cchcal":
00359             self.enableSCP.set(False)
00360             self.scpAutoButton.configure(text="scp copying disabled")
00361             self.copyLoc.configure(state=DISABLED)
00362                                     
00363 
00364 
00365         # Make 'heartbeat' label that shows when auto-checking is on
00366         mycol=mycol+1
00367         self.HeartBeat=Label(self.menubar,
00368                              text="Auto",
00369                              bg=self.bg,
00370                              fg=self.bg,
00371                              padx=10,pady=8)
00372         self.HeartBeat.grid(row=0,column=mycol,sticky=W)
00373 
00374         # Make 'About' menu to store help information 
00375         self.BAbout=Menubutton(self.menubar,
00376                                text="About",
00377                                font= ('Times',12,'bold italic'),
00378                                activebackground=self.bg_alt,
00379                                activeforeground=self.bg,
00380                                bg=self.bg,
00381                                fg=self.fg,
00382                                padx=10, pady=8)
00383         mycol=mycol+1
00384         self.BAbout.grid(row=0,column=mycol,sticky=W)
00385 
00386 
00387         # Fill 'File' Menu
00388         self.quitmenu=Menu(self.BFile, tearoff=0,
00389                            bg="white")
00390 
00391         # Clear out default values
00392         self.quitmenu.add_command(label="Clear all default files",
00393                                   command=lambda x=self:x.removeFiles(removeAll=False))
00394         # Clear out hidden files
00395         self.quitmenu.add_command(label="Clear ALL hidden files",
00396                                   command=lambda x=self:x.removeFiles(removeAll=True))
00397         self.quitmenu.add_separator()
00398         # Call Quit command
00399         self.quitmenu.add_command(label="Quit",
00400                                   command = lambda x=self: x.goodQuit())
00401         self.BFile['menu']=self.quitmenu
00402 
00403 
00404 
00405         # Fill 'Status' Menu
00406         self.statusmenu=Menu(self.Bprogress,
00407                              bg="white")
00408         self.statusmenu.add_command(label="Show run status",
00409                                     command = lambda x=self:x.displayFiles())
00410         self.statusmenu.add_separator()
00411         self.statusmenu.add_command(label="Change run status",
00412                                     command = lambda x=self:x.changeFileSettings())
00413         self.statusmenu.add_separator()
00414         self.statusmenu.add_command(label="Clear run file",
00415                                     command = lambda x=self:x.clearPickle())
00416         self.statusmenu.add_command(label="Restore from backup run file",
00417                                     command = lambda x=self:x.restoreFromBackupPickle())
00418         self.Bprogress['menu']=self.statusmenu
00419 
00420 
00421         # Fill 'About' menu"
00422         self.aboutmenu=Menu(self.BAbout,
00423                             bg="white")
00424         temptext="DQMfromDBS GUI\n\nv1.3 Beta\nby Jeff Temple\n10 May 2008\n\n"
00425         temptext=temptext+"GUI allows users to query DBS for files in a specified\nrun range, and then run HCAL DQM over those files.\n\nQuestions or comments?\nSend to:  jtemple@fnal.gov\n"
00426         self.aboutmenu.add_command(label="Info",
00427                                    command = lambda x=helpfunctions:
00428                                    x.Helpwin(temptext,usetext=1,title="About this program..."))
00429         self.aboutmenu.add_command(label="Help",
00430                                    command = lambda x=helpfunctions:
00431                                    x.Helpwin("%s"%os.path.join(self.basedir,"dqmdbs_instructions.txt"),title="Basic instructions for the user"))
00432         self.BAbout['menu']=self.aboutmenu
00433 
00434 
00435         
00436         # Fill 'DBS Options' Menu
00437         self.dbsmenu=Menu(self.Bdbs,
00438                           bg="white",
00439                           tearoff=0)
00440         self.dbsmenu.add_command(label="Change DBS settings",
00441                                  command = lambda x=self:x.printDBS())
00442         
00443         self.dbsmenu.add_separator()
00444 
00445         # Create submenu to allow changing of DBS auto-update interval
00446         self.dbsUpdateMenu=Menu(self.dbsmenu,
00447                                 bg="white",
00448                                 tearoff=0)
00449         self.dbsUpdateMenu.choices=Menu(self.dbsUpdateMenu,
00450                                         bg="white",
00451                                         tearoff=0)
00452 
00453         for upTime in range(len(self.updateTimes)):
00454             self.dbsUpdateMenu.choices.add_command(label='%s minutes'%self.updateTimes[upTime],
00455                                                    command = lambda x=upTime,y=self.updateTimes:self.dbsSetUpdateMenu(x,y)
00456                                                    )
00457         self.dbsmenu.add_cascade(label="Set DBS update time",
00458                                  menu=self.dbsUpdateMenu.choices)
00459         #self.Bdbs['menu']=self.dbsmenu
00460 
00461         # Create submenu to check only runs with HCAL present
00462         self.dbsHcalOnlyMenu=Menu(self.dbsmenu,
00463                                   bg="white",
00464                                   tearoff=0)
00465         self.dbsHcalOnlyMenu.choices=Menu(self.dbsHcalOnlyMenu,
00466                                           bg="white",
00467                                           tearoff=0)
00468         self.dbsSetHcalValue=StringVar()
00469         self.dbsHcalOnlyChoices=["All runs in range","Only runs including HCAL"]
00470         self.dbsSetHcalValue.set("All runs in range")
00471         for i in range(len(self.dbsHcalOnlyChoices)):
00472             self.dbsHcalOnlyMenu.choices.add_command(label="%s"%self.dbsHcalOnlyChoices[i],
00473                                                      command = lambda x=self.dbsHcalOnlyChoices[i],
00474                                                      y=self.dbsHcalOnlyChoices:self.dbsSetHcalOnly(x,y))
00475 
00476             if (self.dbsHcalOnlyChoices[i]==self.dbsSetHcalValue.get()):
00477                 self.dbsHcalOnlyMenu.choices.entryconfig(i,foreground="red")
00478 
00479         self.dbsmenu.add_cascade(label="Set DBS run type:",
00480                                  menu=self.dbsHcalOnlyMenu.choices)
00481         self.Bdbs['menu']=self.dbsmenu
00482 
00483         # Fill 'DQM Options' Menu
00484         self.dqmmenu=Menu(self.Bdqm,
00485                           bg="white",
00486                           tearoff=0)
00487         self.dqmmenu.add_command(label="Change DQM settings",
00488                                  command = lambda x=self:x.printDQM())
00489         self.dqmmenu.add_separator()
00490 
00491         # Create submenu to allow changing of DQM auto-update interval
00492         self.dqmUpdateMenu=Menu(self.dqmmenu,
00493                                 bg="white",
00494                                 tearoff=0)
00495         self.dqmUpdateMenu.choices=Menu(self.dqmUpdateMenu,
00496                                         bg="white",
00497                                         tearoff=0)
00498         for upTime in range(len(self.updateTimes)):
00499             self.dqmUpdateMenu.choices.add_command(label='%s minutes'%self.updateTimes[upTime],
00500                                                    command = lambda x=upTime,y=self.updateTimes:self.dqmSetUpdateMenu(x,y))
00501         self.dqmmenu.add_cascade(label="Set DQM update time",
00502                                  menu=self.dqmUpdateMenu.choices)
00503 
00504 
00505         # Create submenu for choosing luminosity block ranges
00506         self.lumiBlockRangeMenu=Menu(self.dqmmenu,
00507                                 bg="white",
00508                                 tearoff=0)
00509         self.lumiBlockRangeMenu.choices=Menu(self.lumiBlockRangeMenu,
00510                                         bg="white",
00511                                         tearoff=0)
00512         for lumiChoice in range(len(self.lumiBlockRanges)):
00513             self.lumiBlockRangeMenu.choices.add_command(label='%s'%self.lumiBlockRanges[lumiChoice],
00514                                                    command = lambda x=lumiChoice,y=self.lumiBlockRanges:self.setLumiBlockMenu(x,y))
00515 
00516         # For the moment ( 12 May 2008), keep this disabled, until we
00517         # understand how lumi blocks are arranged in files
00518         # Lumi setting will now run over all lumi blocks by default -- usual way of running
00519         self.dqmmenu.add_cascade(label="Set Lum'y Block Range",
00520                                 menu=self.lumiBlockRangeMenu.choices)
00521 
00522 
00523         self.Bdqm['menu']=self.dqmmenu
00524 
00525 
00526         ########################################################
00527         #                                                      #
00528         #  Fill the searchFrame                                #
00529         #                                                      #
00530         ########################################################
00531         
00532 
00533         # Declare variables for range of runs to be searched in DBS,
00534         # as well as the starting point
00535         # ("lastFoundDBS" is a bit of a misnomer -- this value will
00536         # actually be 1 greater than the last found run under normal
00537         # circumstances.)
00538 
00539         searchrow=0
00540         Label(self.searchFrame,text = "Search over ",
00541               bg=self.bg,
00542               fg=self.bg_alt).grid(row=searchrow,column=0)
00543 
00544         # Entry boxes hold IntVars
00545         self.dbsRangeEntry=Entry(self.searchFrame,
00546                                  bg="white",
00547                                  fg=self.bg_alt,
00548                                  width=8,
00549                                  textvar=self.dbsRange)
00550         self.dbsRangeEntry.grid(row=searchrow,column=1)
00551         self.lastFoundDBSEntry=Entry(self.searchFrame,
00552                                      bg="white",
00553                                      fg=self.bg_alt,
00554                                      width=8,
00555                                      textvar=self.lastFoundDBS)
00556         self.lastFoundDBSEntry.grid(row=searchrow,column=3)
00557 
00558         
00559         Label(self.searchFrame,
00560               text="runs, starting with run #",
00561               bg=self.bg,
00562               fg=self.bg_alt).grid(row=searchrow,column=2)
00563 
00564 
00565         #########################################################
00566         #                                                       #
00567         # Fill main window frame                                #
00568         #                                                       #
00569         #########################################################
00570         
00571         mainrow=0
00572         # This is a blank label that provides a green stripe across the GUI
00573         self.stripe=Label(self.mainFrame,text="",
00574                           font = ('Times',2,'bold italic'),
00575                           bg=self.fg)
00576         self.stripe.grid(row=mainrow,column=0,
00577                          columnspan=10,sticky=EW)
00578 
00579 
00580         # Make row showing column headings, Auto-Update button
00581         mainrow=mainrow+1
00582         Label(self.mainFrame,text="Current Status",
00583               bg=self.bg,
00584               fg=self.bg_alt).grid(row=mainrow,column=1)
00585         Label(self.mainFrame,text="Last Update",
00586               bg=self.bg,
00587               fg=self.bg_alt).grid(row=mainrow,column=2)
00588 
00589         # Button for enabling/disabling auto updating
00590         self.autoButton=Button(self.mainFrame,
00591                                text="Auto-Update\nDisabled!!",
00592                                bg="black",
00593                                fg="white",
00594                                command = lambda x=self:x.checkAutoUpdate())
00595         self.autoButton.grid(row=mainrow,column=4,padx=10,pady=6)
00596 
00597 
00598         # Make labels/entries/buttons dealing with DBS
00599         mainrow=mainrow+1
00600         self.dbsLabel=Label(self.mainFrame,
00601                             text="DBS:",
00602                             fg=self.fg, bg=self.bg,
00603                             width=10)
00604         self.dbsProgress=Label(self.mainFrame,
00605                                text="Nothing yet...",
00606                                bg="black",
00607                                width=40,
00608                                fg=self.bg)
00609         self.dbsStatus=Label(self.mainFrame,
00610                              text="Nothing yet...",
00611                              width=40,
00612                              bg=self.bg,
00613                              fg=self.fg)
00614         self.dbsButton=Button(self.mainFrame,
00615                               text="Check DBS\nfor runs",
00616                               height=2,
00617                               width=15,
00618                               fg=self.bg,
00619                               bg=self.bg_alt,
00620                               activebackground=self.alt_active,
00621                               command = lambda x=self:x.checkDBS()
00622                               )
00623 
00624         self.dbsAutoButton=Checkbutton(self.mainFrame,
00625                                        text="Auto DBS\nupdate OFF",
00626                                        state=DISABLED,
00627                                        bg=self.bg,
00628                                        fg=self.fg,
00629                                        width=20,
00630                                        activebackground=self.alt_active,
00631                                        variable=self.dbsAutoVar,
00632                                        command=self.toggleAutoDBS)
00633 
00634 
00635         # Grid the DBS stuff
00636         self.dbsLabel.grid(row=mainrow,column=0)
00637         self.dbsProgress.grid(row=mainrow,column=1)
00638         self.dbsStatus.grid(row=mainrow,column=2)
00639         self.dbsButton.grid(row=mainrow,column=3)
00640         self.dbsAutoButton.grid(row=mainrow,column=4)
00641         
00642         # Make labels/entries/buttons dealing with DQM searches
00643         self.dqmLabel=Label(self.mainFrame,
00644                             text="DQM:",
00645                             fg=self.fg, bg=self.bg,
00646                             width=10)
00647         self.dqmProgress=Label(self.mainFrame,
00648                                text="Nothing yet...",
00649                                bg="black",
00650                                width=40,
00651                                fg=self.bg)
00652         self.dqmStatus=Label(self.mainFrame,
00653                              text="Nothing yet...",
00654                              width=40,
00655                              bg=self.bg,
00656                              fg=self.fg)
00657         self.dqmButton=Button(self.mainFrame,
00658                               text="Run the \nHCAL DQM",
00659                               height=2,
00660                               width=15,
00661                               fg=self.bg,
00662                               bg=self.bg_alt,
00663                               activebackground=self.alt_active,
00664                               command = lambda x=self:x.runDQM_thread())
00665 
00666         self.dqmAutoButton=Checkbutton(self.mainFrame,
00667                                        text="Auto DQM\nupdate OFF",
00668                                        state=DISABLED,
00669                                        bg=self.bg,
00670                                        fg=self.fg,
00671                                        width=20,
00672                                        activebackground=self.alt_active,
00673                                        variable=self.dqmAutoVar,
00674                                        command=self.toggleAutoDQM)
00675 
00676 
00677         # Grid the DQM stuff
00678         mainrow=mainrow+1
00679         self.dqmLabel.grid(row=mainrow,column=0)
00680         self.dqmProgress.grid(row=mainrow,column=1)
00681         self.dqmStatus.grid(row=mainrow,column=2)
00682         self.dqmButton.grid(row=mainrow,column=3)
00683         self.dqmAutoButton.grid(row=mainrow,column=4)
00684         
00685 
00686         ######################################################
00687         #                                                    #
00688         #  Fill the statusFrame                              #
00689         #                                                    #
00690         ######################################################
00691         
00692         self.statusFrame.columnconfigure(0,weight=1)
00693         # commentLabel will display messages to user
00694         self.commentLabel=Label(self.statusFrame,
00695                                 bg=self.bg,
00696                                 fg=self.bg_alt,
00697                                 height=2)
00698 
00699         statusrow=0
00700         self.commentLabel.grid(row=statusrow,column=0,sticky=EW)
00701 
00702         # Call setup (initializes remaining needed variables)
00703         self.setup()
00704         return
00705 
00706 
00707 
00708     ##########################################################################
00709     def setup(self):
00710         '''
00711         **self.setup() **
00712         Setup performs some GUI tuning that cannot be completed until variables are declared and
00713         GUI is drawn.
00714         
00715             '''
00716 
00717         if self.debug:  print self.setup.__doc__
00718 
00719         #self.commentLabel.configure(text="Welcome to the HCAL DBS/DQM GUI")
00720         #self.commentLabel.update_idletasks()
00721 
00722         os.chdir(self.basedir) # cd to the self.basedir directory
00723 
00724         self.finalDir.set(self.basedir) # set this to some other location later?
00725 
00726         # Create DBS accessor
00727         self.myDBS = dbsAccessor(self.basedir,debug=self.debug) # Will access runs from DBS
00728         self.myDBS.getDefaultsFromPickle()
00729 
00730 
00731         # Default file settings may only be read/set once correct basedir location
00732         # is set.
00733         
00734         self.cfgFileName.set(os.path.join(self.basedir,self.mycfg))
00735         self.getDefaultDQMFromPickle(startup=True)
00736 
00737         self.readPickle() # Read defaults from cPickle file
00738         
00739         # Set lastFoundDBS to most recent run in filesInDBS 
00740         if len(self.filesInDBS.keys()):
00741             x=self.filesInDBS.keys()
00742             x.sort()
00743             x.reverse()
00744             self.lastFoundDBS.set(x[0])
00745 
00746         # Set update time in UpdateMenus to 20 minutes (they will appear in red in the menu)
00747         for temptime in range(len(self.updateTimes)):
00748             if self.updateTimes[temptime]==self.dbsAutoUpdateTime.get():
00749                 self.dbsUpdateMenu.choices.entryconfig(temptime,foreground="red")
00750             if self.updateTimes[temptime]==self.dqmAutoUpdateTime.get():
00751                 self.dqmUpdateMenu.choices.entryconfig(temptime,foreground="red")
00752 
00753         # Set initial lum'y block choice to red
00754         for templumi in range(len(self.lumiBlockRanges)):
00755             if self.lumiBlockRanges[templumi]==self.lumiBlockRange.get():
00756                 self.lumiBlockRangeMenu.choices.entryconfig(templumi,foreground="red")
00757 
00758 
00759         # Hidden trick to freeze starting run value!
00760         self.lastFoundDBSEntry.bind("<Shift-Up>",self.toggleAutoRunShift)
00761         self.lastFoundDBSEntry.bind("<Shift-Down>",self.toggleAutoRunShift)
00762 
00763         if not os.path.isdir(self.finalDir.get()):
00764             self.commentLabel.configure(text="WARNING -- specified Final DQM Save Directory does not exist!\nCheck settings in DQM options!")
00765             self.commentLabel.update_idletasks()
00766         return
00767 
00768 
00769     ############################################################
00770     def checkAutoUpdate(self):
00771         '''
00772         ** self.checkAutoUpdate() **
00773         This is the function associated with the "Auto Update" button.
00774         It toggles the self.Automated variable.
00775         If self.Automated is true, then DBS searches and DQM running
00776         are performed automatically.
00777         '''
00778 
00779         if (self.debug):
00780             print self.checkAutoUpdate.__doc__
00781         
00782         #self.dqmAutoButton.flash()
00783         self.Automated.set(1-self.Automated.get())  # toggle boolean
00784         if (self.debug):
00785             print "<checkAutoUpdate>  Checkpoint 1"
00786         if (self.Automated.get()==True):
00787             self.autoButton.configure(text="Auto Update\nEnabled",
00788                                       bg=self.bg_alt,
00789                                       fg=self.bg)
00790             # enable DQM, DBS buttons
00791             self.dqmAutoButton.configure(state=NORMAL,text="Auto DQM update\nevery %s minutes"%self.dqmAutoUpdateTime.get(),
00792                                          bg=self.bg,fg=self.fg)
00793             self.dbsAutoButton.configure(state=NORMAL,text="Auto DBS update\nevery %s minutes"%self.dbsAutoUpdateTime.get(),
00794                                          bg=self.bg,fg=self.fg)
00795             self.dbsAutoVar.set(True)
00796             self.dqmAutoVar.set(True)
00797             # Start autoUpdater thread
00798             if (self.debug):
00799                 print "<checkAutoUpdate> Starting autoUpdater thread"
00800             thread.start_new(self.autoUpdater,())
00801 
00802         else:
00803 
00804             if (self.debug):
00805                 print "<checkAutoUpdate>  Auto update turned off"
00806             # Boolean false; turn off auto updater
00807             self.autoButton.configure(text="Auto Update\nDisabled!!",
00808                                       bg="black",
00809                                       fg="white")
00810             self.dqmAutoButton.configure(text="Auto DQM \nupdate OFF",state=DISABLED)
00811             self.dbsAutoButton.configure(text="Auto DBS \nupdate OFF",state=DISABLED)
00812             self.dbsAutoVar.set(False)
00813             self.dqmAutoVar.set(False)
00814 
00815         self.commentLabel.update_idletasks()
00816 
00817         return
00818 
00819     #########################################################
00820     def heartbeat(self,interval=1):
00821         '''
00822         ** self.heartbeat(interval =1 ) **
00823         Make heartbeat label flash once per second.
00824         '''
00825 
00826         if (self.debug):
00827             print self.heartbeat.__doc__
00828         
00829         while (self.Automated.get()):
00830             if (self.hbcolor==self.bg):
00831                 self.hbcolor=self.bg_alt
00832             else:
00833                 self.hbcolor=self.bg
00834             self.HeartBeat.configure(bg=self.hbcolor)
00835             self.commentLabel.update_idletasks()
00836             time.sleep(interval)
00837 
00838         self.HeartBeat.configure(bg=self.bg)
00839         return
00840 
00841     #########################################################
00842     def autoUpdater(self):
00843         '''
00844         ** autoUpdate() **
00845         DQM/DBS Auto updater.
00846         '''
00847 
00848         if (self.debug):
00849             print self.autoUpdater.__doc__
00850 
00851         if self.autoRunning==True:
00852             # Don't allow more than one autoUpdater to run at one time
00853             # (I don't think this is possible anyway)
00854             self.commentLabel.configure(text="Auto Updater is already running!")
00855             self.commentLabel.update_idletasks()
00856             return
00857         if self.Automated.get()==False:
00858             self.commentLabel.configure(text="Auto Updater is disabled")
00859             self.commentLabel.update_idletasks()
00860             return
00861 
00862         thread.start_new(self.heartbeat,()) # create heartbeat to show auto-update is running
00863         self.checkDBS() # perform initial check of files
00864         self.runDQM_thread() # perform initial check of DQM
00865         
00866         while (self.Automated.get()):
00867             self.autoRunning=True
00868             for xx in range(0,60):
00869                 time.sleep(1)
00870                 if not self.Automated.get():
00871                     break
00872 
00873             # print self.dbsAutoVar.get(), self.dqmAutoVar.get()
00874             # Increment counters once per minute
00875             self.dbsAutoCounter=self.dbsAutoCounter+1
00876             self.dqmAutoCounter=self.dqmAutoCounter+1
00877             #print self.dbsAutoCounter
00878             
00879             # if DBS counter > update time ,check DBS for new files
00880             if (self.dbsAutoCounter >= self.dbsAutoUpdateTime.get()):
00881                 # Reset counter if auto dbs disabled
00882                 if (self.dbsAutoVar.get()==False):
00883                     self.dbsAutoCounter=0
00884                 else:
00885                     #print "Checking DBS!"
00886                     if (self.checkDBS()): # search was successful; reset counter
00887                         self.dbsAutoCounter=0
00888                         #print "DBS Check succeeded!"
00889                     else: # search unsuccessful; try again in 1 minute
00890                         self.dbsAutoCounter=(self.dbsAutoUpdateTime.get()-1)*60
00891                         #print "DBS Check unsuccessful"
00892 
00893             # repeat for DQM checking
00894             if (self.dqmAutoCounter >= self.dqmAutoUpdateTime.get()):
00895                 # Remind user to scp completed files
00896                 #self.tempSCP()
00897 
00898                 # If dqmAutoVar is off, reset counter
00899                 if (self.dqmAutoVar.get()==False):
00900                     self.dqmAutoCounter=0
00901                 # Otherwise, run DQM
00902                 else:
00903                     self.runDQM_thread()
00904 
00905 
00906         # Auto updating deactivated; reset counters and turn off heartbeat
00907         self.dbsAutoCounter=0
00908         self.dqmAutoCounter=0
00909         self.autoRunning=False
00910         return
00911         
00912 
00913     def printDBS(self):
00914         '''
00915         ** self.printDBS() **
00916         Create new window showing DBS values; allow user to change them.
00917         '''
00918 
00919         if (self.debug):
00920             print self.printDBS.__doc__
00921             
00922         try:
00923             self.dbsvaluewin.destroy()
00924             self.dbsvaluewin=Toplevel()
00925         except:
00926             self.dbsvaluewin=Toplevel()
00927 
00928         self.dbsvaluewin.title('Change DBS values')
00929         try:
00930             maingeom=self.root.winfo_geometry()
00931             maingeomx=string.split(maingeom,"+")[1]
00932             maingeomy=string.split(maingeom,"+")[2]
00933             maingeomx=int(maingeomx)
00934             maingeomy=int(maingeomy)
00935             self.dbsvaluewin.geometry('+%i+%i'%(maingeomx+575,maingeomy+275))
00936         except:
00937             self.dbsvaluewin.geometry('+600+300')
00938 
00939         myrow=0
00940 
00941         # Variables to be shown in window
00942         # Add spaces in front of some keys so that they appear
00943         # first when keys are sorted.
00944         myvars={"  DBS File Search String = ":self.myDBS.searchStringFile,
00945                 "  DBS Dataset Search String = ":self.myDBS.searchStringDataset,
00946                 "  DBS Files to Return = ":self.myDBS.limit,
00947                 " DBS Host = ":self.myDBS.host,
00948                 " DBS Port = ":self.myDBS.port,
00949                 " DBS Instance = ":self.myDBS.dbsInst,
00950                 "Output in XML Format? ":self.myDBS.xml,
00951                 "Show detailed output? ":self.myDBS.details,
00952                 "Case-sensitive matching? ":self.myDBS.case,
00953                 "Output page = ":self.myDBS.page,
00954                 "Debugging = ":self.myDBS.debug,
00955                 " Site = ":self.myDBS.site}
00956 
00957         temp=myvars.keys()
00958         temp.sort()
00959 
00960         # Grid variable labels, entreis
00961         for i in temp:
00962             Label(self.dbsvaluewin,
00963                   width=40,
00964                   text="%s"%i).grid(row=myrow,column=0)
00965             Entry(self.dbsvaluewin,
00966                   width=40,
00967                   bg="white",
00968                   textvar=myvars[i]).grid(row=myrow,column=1)
00969             myrow=myrow+1
00970 
00971         # Grid buttons for saving, restoring values
00972         buttonwin=Frame(self.dbsvaluewin)
00973         buttonwin.columnconfigure(0,weight=1)
00974         buttonwin.columnconfigure(1,weight=1)
00975         buttonwin.columnconfigure(2,weight=1)
00976         buttonwin.grid(row=myrow,column=0,columnspan=2,sticky=EW)
00977         Button(buttonwin,text="Save as new default values",
00978                command = lambda x=self.myDBS:x.writeDefaultsToPickle()).grid(row=0,column=0)
00979         Button(buttonwin,text="Restore default values",
00980                command = lambda x=self.myDBS:x.getDefaultsFromPickle()).grid(row=0,
00981                                                                              column=1)
00982         Button(buttonwin,text="Close window",
00983                command = lambda x=self.dbsvaluewin:x.destroy()).grid(row=0,column=2)
00984         return
00985 
00986 
00987     def printDQM(self):
00988         '''
00989         ** self.printDQM() **
00990         Create window for editing DQM values.
00991         '''
00992 
00993         if (self.debug):
00994             print self.printDQM.__doc__
00995 
00996         try:
00997             self.dqmvaluewin.destroy()
00998             self.dqmvaluewin=Toplevel()
00999         except:
01000             self.dqmvaluewin=Toplevel()
01001 
01002         try:
01003             maingeom=self.root.winfo_geometry()
01004             maingeomx=string.split(maingeom,"+")[1]
01005             maingeomy=string.split(maingeom,"+")[2]
01006             maingeomx=int(maingeomx)
01007             maingeomy=int(maingeomy)
01008             self.dqmvaluewin.geometry('+%i+%i'%(maingeomx+375,maingeomy+275))
01009         except:
01010             self.dqmvaluewin.geometry('+600+300')
01011 
01012         self.dqmvaluewin.title("Change DQM Values")
01013         myrow=0
01014 
01015         # List of variables to be shown in window.
01016         # Add spaces in front of some keys so that they
01017         # appear first when sorted.
01018         
01019         myvars={"  Final DQM Save Directory = ":self.finalDir,
01020                 "  # of events to run for each DQM = ":self.maxDQMEvents,
01021                 "  Prescale to run over entire run (1=yes/0=no)? ":self.prescaleOverRun,
01022                 "  .cfg file to run for each DQM = ":self.cfgFileName}
01023         temp=myvars.keys()
01024         temp.sort()
01025 
01026         # Create variable labels, entries
01027         for i in range(len(temp)):
01028             # Skip prescale-over-run option if prescaleOverRunText value is the default (user must specify his/her own text output option in inherited code for this option to become active)
01029 
01030             if (temp[i]== "  Prescale to run over entire run (1=yes/0=no)? " and self.prescaleOverRunText=="# prescale (unused) = "):
01031                 continue
01032             Label(self.dqmvaluewin,
01033                   width=40,
01034                   text="%s"%temp[i]).grid(row=myrow,column=0)
01035 
01036             if temp[i]=="  Prescale to run over entire run (1=yes/0=no)? ":
01037                 tempEnt=OptionMenu(self.dqmvaluewin,
01038                                    self.prescaleOverRun,
01039                                    'True',
01040                                    'False')
01041                 tempEnt.configure(width=75,bg="white")
01042             else:
01043                 tempEnt=Entry(self.dqmvaluewin,
01044                               width=80,
01045                           bg="white",
01046                               textvar=myvars[temp[i]])
01047             tempEnt.grid(row=myrow,column=1)
01048             if temp[i]=="  Final DQM Save Directory = ": 
01049                 tempEnt.bind("<Return>",(lambda event:self.checkExistence(self.finalDir)))
01050             elif temp[i]== "  .cfg file to run for each DQM = ":
01051                 tempEnt.bind("<Return>",(lambda event:self.checkExistence(self.cfgFileName)))
01052             myrow=myrow+1
01053         newFrame=Frame(self.dqmvaluewin)
01054         newFrame.grid(row=myrow,column=0,columnspan=2,sticky=EW)
01055         newFrame.columnconfigure(0,weight=1)
01056         newFrame.columnconfigure(1,weight=1)
01057         newFrame.columnconfigure(2,weight=1)
01058         Button(newFrame,text="Save as new default\n DQM values",
01059                command = lambda x=self:x.writeDefaultDQMToPickle()).grid(row=0,column=0)
01060         Button(newFrame,text="Restore default DQM values",
01061                command = lambda x=self:x.getDefaultDQMFromPickle()).grid(row=0,
01062                                                                          column=1)
01063         # Hey!  It seems that values are set whenever you change them in the entry window,
01064         # even if you don't press <Enter>.  Keen!
01065         Button(newFrame,text="Exit",
01066                command = lambda x=self.dqmvaluewin:x.destroy()).grid(row=0,column=2)
01067         return
01068 
01069 
01070     def getDefaultDQMFromPickle(self,startup=False):
01071         '''
01072         ** self.getDefaultDQMFromPickle(startup=False) **
01073         Get DQM default values from .dqmDefaults.cPickle.
01074         startup variable is set True for first function call on startup.
01075         (This only affects the message displayed in the comment label after the function call.)
01076         '''
01077 
01078         if (self.debug):
01079             print self.getDefaultDQMFromPickle.__doc__
01080 
01081         if os.path.isfile(os.path.join(self.basedir,".dqmDefaults.cPickle")):
01082             try:
01083                 pcl=open(os.path.join(self.basedir,".dqmDefaults.cPickle"),'rb')
01084                 self.finalDir.set(cPickle.load(pcl))
01085                 self.maxDQMEvents.set(cPickle.load(pcl))
01086                 self.cfgFileName.set(cPickle.load(pcl))
01087                 self.prescaleOverRun.set(cPickle.load(pcl))
01088                 pcl.close()
01089             except:
01090                 self.commentLabel.configure(text="Could not read file '.dqmDefaults.cPickle' ")
01091                 self.commentLabel.update_idletasks()
01092         else:
01093             if not startup:
01094                 self.commentLabel.configure(text="Sorry, no default values were found")
01095                 self.commentLabel.update_idletasks()
01096         return
01097 
01098     def writeDefaultDQMToPickle(self):
01099         '''
01100         ** self.writeDefaultDQMToPickle **
01101         Write DQM default values to basedir/.dqmDefaults.cPickle.
01102         '''
01103 
01104         if (self.debug):
01105             print self.writeDefaultDQMToPickle.__doc__
01106 
01107         try:
01108             pcl=open(os.path.join(self.basedir,".dqmDefaults.cPickle"),'wb')
01109             cPickle.dump(self.finalDir.get(),pcl)
01110             cPickle.dump(self.maxDQMEvents.get(),pcl)
01111             cPickle.dump(self.cfgFileName.get(),pcl)
01112             cPickle.dump(self.prescaleOverRun.get(),pcl)
01113             pcl.close()
01114             os.system("chmod a+rw %s"%os.path.join(self.basedir,".dqmDefaults.cPickle"))
01115                       
01116         except SyntaxError:
01117             self.commentLabel.configure(text="Could not write file '.dqmDefaults.cPickle' ")
01118             self.commentLabel.update_idletasks()
01119         return
01120 
01121 
01122     def readPickle(self):
01123         '''
01124         ** self.readPickle() **
01125         Read list of found runs from basedir/.filesInDBS.cPickle.
01126         '''
01127         
01128         if (self.debug):
01129             print self.readPickle.__doc__
01130         
01131         if (self.pickleFileOpen):
01132             self.commentLabel.configure(text="Sorry, .filesInDBS.cPickle is already open")
01133             return
01134         self.pickleFileOpen=True
01135 
01136         if os.path.isfile(os.path.join(self.basedir,".filesInDBS.cPickle")):
01137             try:
01138                 temp=open(os.path.join(self.basedir,".filesInDBS.cPickle"),'rb')
01139                 self.filesInDBS=cPickle.load(temp)
01140                 self.commentLabel.configure(text = "Loaded previously-read DBS entries from cPickle file")
01141                 self.commentLabel.update_idletasks()
01142             except:
01143                 self.commentLabel.configure(text="WARNING!  Could not read .filesInDBS.cPickle file!\n-- Starting DBS list from scratch")
01144                 self.filesInDBS={}
01145         else:
01146             self.filesInDBS={}
01147             self.commentLabel.configure(text = "Could not find file .filesInDBS.cPickle\n-- Starting DBS list from scratch")
01148             self.commentLabel.update_idletasks()
01149 
01150         self.pickleFileOpen=False
01151         return
01152 
01153 
01154     def writePickle(self):
01155         '''
01156         ** self.writePickle() **
01157         Write list of found runs to basedir/.filesInDBS.cPickle.
01158         '''
01159 
01160         if (self.debug):
01161             print self.writePickle.__doc__
01162 
01163         if (self.pickleFileOpen):
01164             self.commentLabel.configure(text="Sorry, could not write information to .filesInDBS.cPickle.\ncPickle file is currently in use.")
01165             self.commentLabel.update_idletasks()
01166             return
01167         self.pickleFileOpen=True
01168         if len(self.filesInDBS)>0:
01169             try:
01170                 myfile=open(os.path.join(self.basedir,".filesInDBS.cPickle"),'wb')
01171                 cPickle.dump(self.filesInDBS,myfile)
01172                 myfile.close()
01173                 os.system("chmod a+rw %s"%os.path.join(self.basedir,".filesInDBS.cPickle"))
01174             except:
01175                 self.commentLabel.configure(text="ERROR!  Could not write to file .filesInDBS.cPickle!\n  This bug will be investigated!")
01176                 self.commentLabel.update_idletasks()
01177         self.pickleFileOpen=False
01178         return
01179 
01180 
01181     def clearPickle(self):
01182         '''
01183         ** self.clearPickle() **
01184         Clear list of found runs, copying .cPickle info to backup file.
01185         '''
01186 
01187         if (self.debug):
01188             print self.clearPickle.__doc__
01189 
01190         if not (os.path.isfile(os.path.join(self.basedir,".filesInDBS.cPickle"))):
01191             self.commentLabel.configure(text="No run list .filesInDBS.cPickle exists!\nThere is nothing yet to clear!")
01192             self.commentLabel.update_idletasks()
01193             return
01194                 
01195         if tkMessageBox.askyesno("Remove .filesInDBS.cPickle?",
01196                                  "Clearing the list of runs is a major change!\nAre you sure you wish to proceed?"):
01197             os.system("mv %s %s"%(os.path.join(self.basedir,".filesInDBS.cPickle"),
01198                                   os.path.join(self.basedir,".backup_filesInDBS.cPickle")))
01199 
01200             self.filesInDBS={} # cleared files in memory
01201             self.commentLabel.configure(text="Run list cleared (saved as .backup_filesInDBS.cPickle)")
01202             self.commentLabel.update_idletasks()
01203 
01204         return
01205 
01206     def restoreFromBackupPickle(self):
01207         '''
01208         ** self.restoreFromBackupPickle() **
01209         Restore list of found runs from basedir/.backup_filesInDBS.cPickle file
01210         '''
01211 
01212         if (self.debug):
01213             print self.restoreFromBackupPickle.__doc__
01214         
01215         if not (os.path.isfile(os.path.join(self.basedir,".backup_filesInDBS.cPickle"))):
01216             self.commentLabel.configure(text="Sorry, backup file does not exist!")
01217             self.commentLabel.update_idletasks()
01218             return
01219         if tkMessageBox.askyesno("Restore from .backup_filesInDBS.cPickle",
01220                                  "Are you sure you want to restore files\nfrom backup?"):
01221             os.system("mv %s %s"%(os.path.join(self.basedir,".backup_filesInDBS.cPickle"),
01222                                   os.path.join(self.basedir,".filesInDBS.cPickle")))
01223             self.readPickle()
01224             self.commentLabel.configure(text="Run list restored from .backup_filesInDBS.cPickle")
01225             self.commentLabel.update_idletasks()
01226         return
01227     
01228 
01229 
01230     def removeFiles(self,removeAll=False):
01231         '''
01232         ** self.removeFiles(removeAll=False) **
01233         Removes hidden files (files starting with "."), such as default option settings, etc.
01234         If removeAll is set true, then the .filesInDBS.cPickle file that is used to store run history is also removed.
01235         One exception:  .backup_filesInDBS.cPickle can never be removed via the GUI
01236         '''
01237 
01238         if (self.debug):
01239             print self.removeFiles.__doc__
01240         
01241         if (removeAll):
01242             text="This will remove ALL hidden files\n used by the GUI, and will clear\nthe list of runs processed by the\n program.\n\nAre you ABSOLUTELY SURE \nthis is what you want?\n"
01243         else:
01244             text="This will remove hidden files used to\nstore certain user-set default values.\n\nAre you SURE this is what you want?\n"
01245         if tkMessageBox.askyesno("Remove default files???  Really???",
01246                                  text):
01247             temp=[".dqmDefaults.cPickle",".dbsDefaults.cPickle",".runOptions.cfi"]
01248             if (removeAll):
01249                 temp.append(".filesInDBS.cPickle")
01250                 self.filesInDBS={}
01251             for i in temp:
01252                 x=os.path.join(self.basedir,i)
01253                 if os.path.isfile(x):
01254                   self.commentLabel.configure(text="Removing file '%s'"%i)
01255                   self.commentLabel.update_idletasks()
01256                   os.system("rm -f %s"%x)
01257                   time.sleep(0.5)
01258         return
01259 
01260     def goodQuit(self):
01261         '''
01262         ** self.goodQuit() **
01263         A "clean exit" from the GUI program.
01264         Checks that DBS/ DQM calls are not currently in progress, and
01265         then closes the GUI.
01266         '''
01267 
01268         if (self.debug):
01269             print self.goodQuit.__doc__
01270         
01271         if (self.dbsSearchInProgress or self.runningDQM):
01272             text="The following jobs have not yet finished:"
01273             if (self.dbsSearchInProgress):
01274                 text=text+"\nA DBS Search is still in progress"
01275             if (self.runningDQM):
01276                 text=text+"\nDQM is currently running"
01277             text=text+"\nDo you want to exit anyway?"
01278             if not tkMessageBox.askyesno("Jobs not yet completed",text):
01279                 return
01280 
01281         # TO DO:  KILL EXISTING cmsRun jobs if they are running when the user decides to quit.
01282         self.Automated.set("False")
01283         self.root.destroy()
01284         return
01285 
01286 
01287     def runDQM_thread(self):
01288         '''
01289         ** self.runDQM_thread() **
01290         Starts new thread for running DQM,
01291         as long as DQM process is not already running
01292         '''
01293 
01294         if (self.debug):
01295             print self.runDQM_thread.__doc__
01296 
01297         if self.runningDQM:
01298             self.commentLabel.configure(text="Sorry, DQM is already running!")
01299             self.commentLabel.update_idletasks()
01300         else:
01301             thread.start_new(self.runDQM,())
01302         return
01303 
01304 
01305     def runDQM(self):
01306         '''
01307         ** self.runDQM() **
01308         Runs DQM over all found files.
01309         '''
01310 
01311         if (self.debug):
01312             print self.runDQM.__doc__
01313         
01314         mytime=time.time()
01315         
01316         if self.runningDQM:
01317             self.commentLabel.configure(text="Sorry, DQM is already running")
01318             self.commentLabel.update_idletasks()
01319             return
01320 
01321         self.dqmProgress.configure(text="Running DQM on available runs",
01322                                    bg=self.bg_alt)
01323         self.dqmStatus.configure(text="%s"%time.strftime("%d %b %Y at %H:%M:%S",time.localtime()))
01324         
01325         # Get list of runs -- whenever we change info, we write to pickle file
01326         # Therefore, read from the file to get the latest & greatest
01327         self.readPickle() 
01328 
01329         if (self.debug):
01330             print "<runDQM>  Read pickle file"
01331         if len(self.filesInDBS.keys())==0:
01332             self.commentLabel.configure(text = "Sorry, no file info available.\nTry the 'Check DBS for Runs' button first.")
01333             self.dqmProgress.configure(text="No Run Info available",
01334                                        bg="black")
01335             self.commentLabel.update_idletasks()
01336             return
01337 
01338         # If runs found, sort by run number (largest number first)
01339         if len(self.filesInDBS.keys()):
01340             foundruns=self.filesInDBS.keys()
01341             foundruns.sort()
01342             foundruns.reverse()
01343         else:
01344             self.commentLabel.configure(text="No unprocessed runs found")
01345             self.commentLabel.update_idletasks()
01346             return
01347         
01348         self.runningDQM=True
01349         self.dqmButton.configure(state=DISABLED)
01350 
01351         unfinished_run=0
01352         finished_run=0
01353         all_run=len(foundruns)
01354         if (self.debug):
01355             print "<runDQM>  Set finished, unfinished run vars"
01356         for i in foundruns:
01357 
01358             if self.filesInDBS[i].ignoreRun==False and self.filesInDBS[i].finishedDQM==False:
01359                 unfinished_run=unfinished_run+1
01360 
01361         newFiles=False # stores whether a new file is found in the midst of DQM processing
01362         for i in foundruns:
01363             if (self.debug):
01364                 print "<runDQM> Checking run #%i"%i
01365 
01366             self.commentLabel.configure(text="Running DQM on run #%i"%i)
01367             self.dqmProgress.configure(text="Running DQM on run #%i"%i,
01368                                        bg=self.bg_alt)
01369             self.commentLabel.update_idletasks()
01370             # Allow user to break loop via setting the runningDQM variable
01371             # (change to BooleanVar?)
01372             if (self.debug):
01373                 print "<runDQM> runningDQM bool = ",self.runningDQM
01374             if (self.runningDQM==False):
01375                 if (self.debug):
01376                     print "<runDQM> runningDQM bool = False"
01377                 self.dqmButton.configure(state=NORMAL)
01378                 break
01379             # ignore files if necessary
01380             if self.filesInDBS[i].ignoreRun:
01381                 continue
01382             # if DQM started, check to see if DQM has finished
01383             if self.filesInDBS[i].startedDQM:
01384                 
01385                 # Case 1:  DQM finished; no problem
01386                 if self.filesInDBS[i].finishedDQM:
01387                     self.filesInDBS[i].previouslyFinishedDQM=True # don't use this variable any more
01388                     #finished_run=finished_run+1
01389                     continue
01390 
01391                 # Case 2:  DQM not finished; look to see if its output files/dirs exist
01392                 #     Revise this in the future?  Check to see if output was moved to finalDir, but finishedDQM
01393                 #     boolean wasn't set True?  That should never be able to happen, right?
01394 
01395 
01396                 success=self.getcmsRunOutput(i)
01397                 if not success:
01398                     # If we're only running once (not checking multiple lumi block ranges),
01399                     # then the lack of output indicates that there was a real problem
01400 
01401                     if (self.lumiBlockRange.get()=="All"):
01402                     # Resetting lumiBlockIncrement via the gui menu doesn't seem to work; use lumiBlockRange directly
01403                     #print "RUN ",i," LUMY INC = ",self.filesInDBS[i].lumiBlockIncrement
01404                     #if (self.filesInDBS[i].lumiBlockIncrement==0):     
01405 
01406                         print "Problem with Run # %i -- DQM started but did not finish!"%i
01407                         self.commentLabel.configure(text="Problem with Run # %i -- DQM started but did not finish!"%i)
01408                         self.commentLabel.update_idletasks()
01409 
01410                 else:
01411                     # files have finished; need to update status
01412                     self.filesInDBS[i].finishedDQM=True
01413                     finished_run=finished_run+1
01414                     continue
01415             # Run DQM if DQM process hasn't started yet or if we want to re-run over a new luminosity
01416             # block (in which case "startedDQM" will be True, but "finishedDQM" will be False).
01417             if ((not self.filesInDBS[i].startedDQM ) or
01418                 (self.lumiBlockRange.get()<>"All" and
01419                  self.filesInDBS[i].startedDQM and not
01420                  self.filesInDBS[i].finishedDQM)):
01421                 
01422                 # nothing started yet; begin DQM
01423 
01424                 # First check that cmsRun is available
01425                 if (self.debug):
01426                     print "<runDQM> looking for cmsRun"
01427                 checkcmsRun=os.popen3("which cmsRun")
01428                 # popen3 returns 3 streams -- in, out, and stderr
01429                 # check that stderr is empty
01430                 if len(checkcmsRun[2].readlines())>0:
01431                     self.commentLabel.configure(text="Could not find 'cmsRun'\nHave you set up your CMSSW environment?")
01432                     self.commentLabel.update_idletasks()
01433                     return
01434 
01435                 self.runningDQM=True
01436                 self.filesInDBS[i].startedDQM=True  # Set to True, but info not yet saved to .cPickle file
01437                 # Here is where the cmsRun command is sent!
01438                 
01439                 if (self.callDQMscript(i)):
01440                     #if (self.filesInDBS[i].lumiBlockIncrement==0):
01441                     if (self.lumiBlockRange.get()=="All"):
01442                         self.filesInDBS[i].finishedDQM=True
01443                         
01444                     else:
01445                         #self.filesInDBS[i].currentLumiBlock=self.filesInDBS[i].currentLumiBlock+self.filesInDBS[i].lumiBlockIncrement
01446                         self.filesInDBS[i].currentLumiBlock=self.filesInDBS[i].currentLumiBlock+int(self.lumiBlockRange.get())
01447                         if (self.filesInDBS[i].currentLumiBlock>self.filesInDBS[i].numLumiBlocks):
01448                             self.filesInDBS[i].finishedDQM=True
01449                             
01450                     finished_run=finished_run+1 # increment finished regardless of whether all lum'y blocks completed?
01451                 
01452             if (self.debug):
01453                 print "<runDQM> made it through callDQMscript"
01454 
01455             # Every 20 minutes or so, check for updates to DBS files
01456             # We shouldn't need this check any more -- users can call
01457             # DBS on the fly, and set the ignore flags on the files if
01458             # they want dqm to finish early
01459             
01460             if (time.time()-mytime)>20*60:
01461             #if (1<0):
01462                 if (self.debug):
01463                     print "<runDQM> getting time info"
01464                 mytime=time.time()
01465                 self.checkDBS()
01466                 if len(self.filesInDBS.keys())<>len(foundruns):
01467                     self.commentLabel.configure(text="DBS files have been added since last call to DQM.\n  Restarting DQM.")
01468                     self.commentLabel.update_idletasks()
01469                     newFiles=True
01470                     break  # end loop on foundruns
01471         if (newFiles):
01472             # Save current progress
01473             self.writePickle()
01474             # Could this have caused the bug of .gif files written
01475             # to directory?
01476             # What happens if move call occurs during dqm running?
01477             
01478             self.dqmButton.configure(state=ACTIVE)
01479             self.runningDQM=False
01480             self.runDQM()
01481             return  # if need to runDQM again, do so, but then return out of this loop
01482         else:
01483             self.runningDQM=True
01484 
01485 
01486         self.runningDQM=False
01487         self.writePickle()
01488 
01489         if (finished_run==unfinished_run): # all unfinished_runs are now finished
01490             self.dqmProgress.configure(text="Successfully finished running DQM",
01491                                        bg="black")
01492         else:
01493             self.dqmProgress.configure(text="Ran DQM on %i/%i runs"%(finished_run, unfinished_run))
01494         self.dqmStatus.configure(text="%s"%time.strftime("%d %b %Y at %H:%M:%S",time.localtime()))
01495         self.commentLabel.configure(text="Finished running DQM:\n%i out of %i runs successfully processed"%(finished_run,unfinished_run))
01496         time.sleep(3)
01497 
01498         #self.tempSCP() # Call scp copying routine once dqm has finished
01499         self.dqmButton.configure(state=NORMAL)
01500         
01501         self.commentLabel.update_idletasks()
01502         return  #end of runDQM
01503                 
01504 
01505     def callDQMscript(self,i):
01506         '''
01507         ** self.callDQMscript(i) **
01508         Here is where we actually perform the cmsRun call for the given run number `i`.
01509         '''
01510 
01511         if (self.debug):
01512             print self.callDQMscript.__doc__
01513         
01514         time.sleep(1)
01515 
01516         # Get all files associated with run # i
01517         filesToRun=[]
01518         if (self.lumiBlockRange.get()=="All"):
01519             filesToRun=self.filesInDBS[i].files
01520         else:
01521             # If only running over a subset of files, calculate total number of events in the given range
01522             totalevents=0
01523             for myfile in range(len(self.filesInDBS[i].fileInfo)):
01524                 myval=self.filesInDBS[i].fileInfo[myfile].lumiBlock
01525                 
01526                 # Check over luminosity ranges
01527                 if (myval>=self.filesInDBS[i].currentLumiBlock and myval<self.filesInDBS[i].currentLumiBlock+int(self.lumiBlockRange.get())):
01528                     filesToRun.append(self.filesInDBS[i].fileInfo[myfile].fileName)
01529                     totalevents=totalevents+self.filesInDBS[i].fileInfo[myfile].numEvents
01530             self.filesInDBS[i].totalEvents=totalevents
01531             
01532         filelength=len(filesToRun)
01533         if (filelength==0):
01534             # increment to next set of lum'y blocks if no runs found in current range (is that what we want?)
01535             if (self.lumiBlockRange.get()<>"All"):
01536                 self.filesInDBS[i].currentLumiBlock=self.filesInDBS[i].currentLumiBlock+int(self.lumiBlockRange.get())
01537             self.commentLabel.configure(text = "<ERROR> No files found for run %i!"%i)
01538             self.commentLabel.update_idletasks()
01539             time.sleep(2)
01540             return
01541 
01542 
01543         # Choice 1:  CMSSW version < 2_1_0 (using old .cfg files)
01544         if (string.atoi(self.cmsVersion[0])<2 or (string.atoi(self.cmsVersion[0])==2 and string.atoi(self.cmsVersion[1])==0)):
01545             # Get rid of old .cfi file
01546             if os.path.isfile(os.path.join(self.basedir,".runOptions.cfi")):
01547                 os.system("rm %s"%(os.path.join(self.basedir,".runOptions.cfi")))
01548             time.sleep(1)
01549 
01550             #print os.path.join(self.basedir,".runOptions.cfi")
01551             try:
01552                 temp=open(os.path.join(self.basedir,".runOptions.cfi"),'w')
01553             except:
01554                 self.commentLabel.configure(text="MAJOR ERROR!  Could not write to .runOptions.cfi!  \nCheck file/directory permissions!")
01555                 self.dqmProgress.configure(text="FAILED!  Couldn't write .runOptions.cfi")
01556                 self.commentLabel.update_idletasks()
01557                 time.sleep(2)
01558                 return False
01559 
01560             # Allow a different # for each file?
01561             #temp.write("replace maxEvents.input=%i\n"%self.filesInDBS[i].maxEvents)
01562 
01563             # If wish to prescale over entire file, calculate prescale here:
01564             if (self.prescaleOverRun.get() and self.prescaleOverRunText<>"# prescale (unused) = "):
01565                 # No longer need to get run info from summary page; already have it from DBS
01566                 #myruninfo=pyRunSummaryBaseClass.goodHCALRun(i,self.debug)
01567 
01568                 try:
01569                     # Get prescale value
01570                     prescaleVal=int(self.filesInDBS[i].totalEvents/self.maxDQMEvents.get())
01571                     if (self.debug):
01572                         print "Run #%i  Total events = %i  Max Events to run = %i  Prescale = %i"%(i,self.filesInDBS[i].totalEvents, self.maxDQMEvents.get(),prescaleVal)
01573                     if (prescaleVal>0):
01574                         temp.write("%s %i\n\n"%(self.prescaleOverRunText,prescaleVal))
01575                         # Need to run over all events if using prescale
01576                         temp.write("replace maxEvents.input=%i\n"%self.filesInDBS[i].totalEvents)
01577 
01578                 except:
01579                     # If above fails for some reason, still dump out the maxEvents replacement (replace with maxDQMEvents)
01580                     temp.write("replace maxEvents.input=%i\n"%self.maxDQMEvents.get())
01581 
01582 
01583             # Set luminosity blocks over which to run
01584             else:
01585                 temp.write("replace maxEvents.input=%i\n"%self.maxDQMEvents.get())
01586 
01587             if (self.debug):
01588                 print "run= ",i," lumi increment = ",self.lumiBlockRange.get()
01589 
01590             #if (self.filesInDBS[i].lumiBlockIncrement>0):
01591             #    temp.write("# replace lumiblockFilter.startblock=%i\n"%self.filesInDBS[i].currentLumiBlock)
01592             #    temp.write("# replace lumiblockFilter.endblock=%i\n"%(self.filesInDBS[i].lumiBlockIncrement+self.filesInDBS[i].currentLumiBlock))
01593 
01594 
01595             temp.write("replace PoolSource.fileNames={\n")
01596 
01597             print "WRITING TO FILE!"
01598             for f in range(0,filelength):
01599                 if (f>200):
01600                     print "Skipping # ",f
01601                 # f can't be > 255:
01602                 if (f>200):
01603                     continue
01604                 temp.write("'%s'"%string.strip(filesToRun[f]))
01605                 if (f==filelength-1):
01606                     temp.write("\n")
01607                 else:
01608                     temp.write(",\n")
01609             temp.write("}\n")
01610             temp.close()
01611             os.system("chmod a+rw %s"%os.path.join(self.basedir,".runOptions.cfi"))
01612 
01613             # Set error if .runOptions.cfi not found
01614             if not (os.path.isfile(os.path.join(self.basedir,".runOptions.cfi"))):
01615                 self.commentLabel.configure(text="Could not find .runOptions.cfi file\nFor run #%i"%i)
01616                 self.commentLabel.update_idletasks()
01617                 time.sleep(2)
01618                 return False
01619 
01620 
01621         # Choice 2:  new _py file found.  Write file directly to _py; don't use auxiliary .cfi?
01622         else:
01623             tempinput=open(self.cfgFileName.get(),'r').readlines()
01624             tempoutput=[]
01625             temp_inreplaceloop=False
01626             
01627             for myline in tempinput:
01628                 if (temp_inreplaceloop==False):
01629                     tempoutput.append(myline)
01630                 if (string.find(myline,"###<<<<<<<<<<")>-1):
01631                     temp_inreplaceloop=True
01632                     # If prescale, need to run over all events (set input = -1) -- add this later?
01633                     tempoutput.append("process.maxEvents=cms.untracked.PSet(input = cms.untracked.int32(%i))\n"%self.maxDQMEvents.get())
01634                     
01635                     tempoutput.append('process.source = cms.Source("PoolSource",\n')
01636                     tempoutput.append('\tfileNames= cms.untracked.vstring(\n') # jeff
01637                     for f in range(0,filelength):
01638                         if (f==filelength-1 or f==250):
01639                             tempoutput.append("\t\t'%s')\n"%string.strip(filesToRun[f]))
01640                             break # can't have more than 255 runs in the fileList, for some dumb reason
01641                         else:
01642                             tempoutput.append("\t\t'%s',\n"%string.strip(filesToRun[f]))
01643                     tempoutput.append("\t)\n")
01644                 if (string.find(myline,"###>>>>>>>>>>>")>-1):
01645                     temp_inreplaceloop=False
01646                     tempoutput.append(myline)
01647             # rewrite cfg file
01648             newcfg=open(self.cfgFileName.get(),'w')
01649             for zzz in tempoutput:
01650                 newcfg.write(zzz)
01651             newcfg.close()
01652 
01653         #sys.exit()
01654         # Now run on cfgFile
01655         os.system("cmsRun %s"%self.cfgFileName.get())
01656 
01657 
01658         # Get list of output files, directories produced by cmsRun call
01659         success=self.getcmsRunOutput(i)
01660 
01661         if (self.debug):
01662             print "Were all expected files found? ",success
01663         if (success):
01664             for myobject in self.cmsRunOutput:
01665 
01666                 if (
01667                     self.finalDir.get()<>self.basedir
01668                     ):
01669 
01670                     if (self.debug):
01671                         print "myobject = ",myobject
01672                         print "BaseName = ",os.path.basename(myobject)
01673                         
01674                     # Delete old copies of output (stored in self.finalDir.get() directory)
01675                     if os.path.exists(os.path.join(self.finalDir.get(),os.path.basename(myobject))):
01676                         os.system("rm -rf %s"%os.path.join(self.finalDir.get(),os.path.basename(myobject)))
01677 
01678                     # now move object to final directory
01679                     os.system("mv %s %s"%(myobject,os.path.join(self.finalDir.get(),os.path.basename(myobject))))
01680 
01681                     # temporary code for moving hotcell, deadcell lists to new directory
01682                     # ADDED ON 2 NOV 2008
01683                     statusname="HcalDQMstatus_%i.txt"%i
01684                     if os.path.isfile(statusname):
01685                         os.system("mv %s %s/%s"%(statusname,self.finalDir.get(),statusname))
01686                     #if os.path.isfile("hcalHotCells.txt"):
01687                     #    os.system("mv %s %s/hcalHotCells_run%i.txt"%("hcalHotCells.txt",self.finalDir.get(),i))
01688 
01689                     #if os.path.isfile("hcalDeadCells.txt"):
01690                     #    os.system("mv %s %s/hcalDeadCells_run%i.txt"%("hcalDeadCells.txt",self.finalDir.get(),i))
01691 
01692                         
01693                     self.commentLabel.configure(text = "moved %s\n to directory %s"%(myobject,
01694                                                                                      self.finalDir.get()))
01695                     self.commentLabel.update_idletasks()
01696                 else:
01697                     #self.commentLabel.configure(text="ERROR -- Can't find %s\nDo you know where your output is?"%myobject)
01698                     self.commentLabel.configure(text="%s output created in \n%s"%(os.path.basename(myobject), self.basedir))
01699                     self.commentLabel.update_idletasks()
01700                 time.sleep(3)
01701 
01702                 # Call scp at the completion of each run?
01703                 #self.tempSCP()
01704 
01705 
01706         else: # success = False
01707             self.commentLabel.configure(text="ERROR -- did not retrieve all expected output from cmsRun")
01708             self.commentLabel.update_idletasks()
01709             time.sleep(3)
01710             
01711         if self.debug:
01712             print "<CallDQMScript> Success = %s"%success
01713         
01714         return success
01715 
01716 
01717         
01718     def getcmsRunOutput(self,runnum):
01719         '''
01720         ** self.getcmsRunOutput(runnum) **
01721         Looks for all the output files, directories that should be
01722         produced by cmsRun call for run #(runnum).
01723         Returns a boolean =  whether or not all files and directories have
01724         been found.
01725         '''
01726 
01727         if (self.debug):
01728             print self.getcmsRunOutput.__doc__
01729 
01730         success=True
01731         
01732         self.cmsRunOutput=[]
01733         if (runnum<100000):
01734             outname="DQM_Hcal_R0000%i"%runnum
01735         else:
01736             outname="DQM_Hcal_R000%i"%runnum
01737 
01738         # make fancier success requirement later -- for now, just check that directory exists
01739         if (self.debug):
01740             print "%s exists? %i"%(os.path.join(self.basedir,outname),os.path.isdir(os.path.join(self.basedir,outname)))
01741 
01742         outputdir=os.path.join(self.basedir,outname)
01743 
01744         success=success and (os.path.isdir(outputdir))
01745         # if directory exists, add it to cmsRunOutput
01746         if (success):
01747             if (self.debug):
01748                 print "<getcmsRunOutput> success=True!"
01749             # Move directory to new name if checking runs by lumi block
01750             if (self.lumiBlockRange.get()<>"All"):
01751                 #if (self.filesInDBS[runnum].lumiBlockIncrement>0):
01752                 newdirname="%s_L%i_%i"%(outputdir,self.filesInDBS[runnum].currentLumiBlock,
01753                                         #self.filesInDBS[runnum].currentLumiBlock+self.filesInDBS[runnum].lumiBlockIncrement-1)
01754                                         min(self.filesInDBS[runnum].currentLumiBlock+int(self.lumiBlockRange.get())-1,
01755                                             self.filesInDBS[runnum].numLumiBlocks)
01756                                         )
01757                 os.system("mv %s %s"%(outputdir,newdirname))
01758                 outputdir=newdirname
01759             self.cmsRunOutput.append(outputdir)
01760 
01761         # now check that root file exists
01762         #outputroot="%s.root"%(os.path.join(self.basedir,outname))
01763         if (runnum<100000):
01764             outname="DQM_V0001_Hcal_R0000%i"%runnum
01765         else:
01766             outname="DQM_V0001_Hcal_R000%i"%runnum
01767         outputroot="%s.root"%(os.path.join(self.basedir,outname))
01768         
01769         # Looks like output .root files are being changed to DQM_V0001_Hcal_R0000XXXX.root.  Make this name change.  I'm not sure if/when  the V0001 increments, though -- Jeff, 29 Sep. 2008
01770         
01771         success=success and (os.path.exists(outputroot))
01772         if os.path.exists(outputroot):
01773             # Perform additional move when lumi block checking is incremented
01774             #if (self.filesInDBS[runnum].lumiBlockIncrement>0):
01775             if (self.lumiBlockRange.get()<>"All"):
01776                 newfilename="%s_L%i_%i.root"%(os.path.join(self.basedir,outname),
01777                                               self.filesInDBS[runnum].currentLumiBlock,
01778                                               #self.filesInDBS[runnum].currentLumiBlock+self.filesInDBS[runnum].lumiBlockIncrement-1)
01779                                               min(self.filesInDBS[runnum].currentLumiBlock+int(self.lumiBlockRange.get())-1,
01780                                                   self.filesInDBS[runnum].numLumiBlocks)
01781                                               )
01782                 os.system("mv %s %s"%(outputroot,newfilename))
01783                 outputroot=newfilename
01784             self.cmsRunOutput.append(outputroot)
01785 
01786 
01787         # Hack for Jason to look at Timing Code
01788         timingoutput="HcalTiming_run%i.root"%runnum
01789         if os.path.exists(timingoutput):
01790             self.cmsRunOutput.append(timingoutput)
01791 
01792         if (self.debug):
01793             print "<getcmsRunOutput>  The following cmsRun outputs were found:"
01794             for i in self.cmsRunOutput:
01795                 print "\t%s"%i
01796             print "\nAll files found? %s"%success
01797             
01798         return success
01799 
01800 
01801 
01802 
01803     def checkDBS(self):
01804         '''
01805         ** self.checkDBS() **
01806         Looks in DBS for files with given file/dataset names, and in specified run range.
01807         '''
01808 
01809         if (self.debug):
01810             print self.checkDBS.__doc__
01811 
01812         if (self.dbsSearchInProgress):
01813             self.commentLabel.configure(text="Sorry, a DBS search is already in progress at the moment")
01814             return False
01815 
01816         self.dbsButton.configure(state=DISABLED)
01817         self.dbsSearchInProgress=True
01818         begin=self.lastFoundDBS.get()
01819         end=begin+self.dbsRange.get()
01820 
01821         self.dbsProgress.configure(text="Checking DBS for runs %i-%i..."%(begin,end),
01822                                    bg=self.bg_alt)
01823         self.dbsStatus.configure(text="%s"%time.strftime("%d %b %Y at %H:%M:%S",time.localtime()))
01824 
01825         self.commentLabel.configure(text="Checking DBS for runs in range %i-%i..."%(begin,end))
01826         self.commentLabel.update_idletasks()
01827         self.myDBS.searchDBS(begin,end) # Search, getting run numbers
01828 
01829         if (self.parseDBSInfo()):
01830             self.commentLabel.configure(text="Finished checking DBS runs (%i-%i)\nFound a total of %i files"%(begin,end,self.foundfiles))
01831 
01832         self.dbsSearchInProgress=False
01833         self.dbsButton.configure(state=NORMAL)
01834         return True
01835 
01836     
01837     def parseDBSInfo(self):
01838         '''
01839         ** self.parseDBSInfo() **
01840         Once we've checked DBS, let's parse the output for runs!
01841         We'll get info by checking DBS for all run numbers within range.
01842         Then, for each found run number, we'll grab all the files for that run number
01843         '''
01844 
01845         if (self.debug):
01846             print self.parseDBSInfo.__doc__
01847             
01848             
01849         hcalrunlist=[]
01850         # Added on 4 June 2008:  Try to get run list by explicitly check the RunSummary page to make sure that HCAL was included in the run.  Not yet enabled(need to generalize for non-HCAL running?)
01851 
01852         if (self.dbsSetHcalValue.get()=="Only runs including HCAL"):
01853             hcalRunSummary=pyRunSummaryBaseClass.goodHCALList(self.lastFoundDBS.get(),self.lastFoundDBS.get()+self.dbsRange.get(),debug=False)
01854             hcalrunlist=hcalRunSummary.hcalruns
01855             if (self.debug):
01856                 print hcalRunSummary.allruns
01857 
01858 
01859         runlist=[]
01860         begin=self.lastFoundDBS.get()
01861         end=begin+self.dbsRange.get()
01862         runs=string.split(self.myDBS.searchResult,"\n")
01863 
01864         for r in runs:
01865             if (len(r)==0):
01866                 continue # skip blank output lines
01867             # Use "Found ... runs" output line to determine # of runs found
01868             if (r.startswith("Found")):
01869                 
01870                 self.foundfiles=string.atoi(string.split(r)[1])
01871                 if (self.foundfiles==0):
01872                     self.commentLabel.configure(text="WARNING!  No runs found in the run range %i-%i"%(self.lastFoundDBS.get(),self.lastFoundDBS.get()+self.dbsRange.get()))
01873                     self.dbsProgress.configure(text="No runs found in range %i-%i"%(self.lastFoundDBS.get(),self.lastFoundDBS.get()+self.dbsRange.get()),
01874                                                bg="black")
01875                     self.commentLabel.update_idletasks()
01876                     return False
01877 
01878             try:
01879                 r.strip("\n")
01880                 r=string.atoi(r)
01881 
01882                 if r not in runlist:
01883                     # Skip runs which don't include HCAL
01884 
01885                     if (self.dbsSetHcalValue.get()=="Only runs including HCAL"):
01886                         if r not in hcalrunlist:
01887                             continue 
01888                     runlist.append(r)
01889             except:
01890                 continue
01891 
01892 
01893             
01894         if len(runlist)==0:
01895             self.commentLabel.configure(text="ODD BEHAVIOR!  Runs apparently found, but cannot be parsed!\nIt's possible runs did not contain HCAL -- DBS output being redirected to screen")
01896             
01897             print "DBS Run search result: ",self.myDBS.searchResult
01898             print "\n\nRunSummary page search result (Valid Hcal Runs): "
01899             for iii in hcalrunlist:
01900                 print iii
01901             self.dbsProgress.configure(text="No runs in (%i-%i) could be parsed!"%(self.lastFoundDBS.get(),self.lastFoundDBS.get()+self.dbsRange.get()),
01902                                        bg="black")
01903             self.commentLabel.update_idletasks()
01904             return False
01905 
01906 
01907         # Now loop over each run to get final search result
01908 
01909         self.foundfiles=0
01910         badcount=0
01911         for r in runlist:
01912 
01913             self.dbsProgress.configure(text="Found run %i in range (%i-%i)..."%(r,self.lastFoundDBS.get(),self.lastFoundDBS.get()+self.dbsRange.get()))
01914             self.commentLabel.update_idletasks()
01915             
01916             tempfiles=[]
01917         
01918             # For each run, create new accessor that will find files, datasets associated with the run
01919             x=dbsAccessor(debug=self.debug)
01920             x.host.set(self.myDBS.host.get())
01921             x.port.set(self.myDBS.port.get())
01922             x.dbsInst.set(self.myDBS.dbsInst.get())
01923             x.searchStringFile.set(self.myDBS.searchStringFile.get())
01924             x.searchStringDataset.set(self.myDBS.searchStringDataset.get())
01925             x.page.set(self.myDBS.page.get())
01926             x.limit.set(self.myDBS.limit.get())
01927             x.xml.set(self.myDBS.xml.get())
01928             x.case.set(self.myDBS.case.get())
01929             x.details.set(self.myDBS.details.get())
01930             x.debug.set(self.myDBS.debug.get())
01931             #x.site.set(self.myDBS.site.get())
01932             x.site.set("")  # we already know file exists at this site -- don't check for site again (causes crash in dbs search)
01933             # beginRun, endRun don't need to be set -- we're looking for one specific run here
01934             
01935             # give new accessor same defaults as set for self.myDBS
01936             text="find file,file.numevents,lumi,dataset where %s run=%i"%(self.myDBS.formParsedString(),r)
01937 
01938             x.searchDBS(mytext=text)
01939             
01940             searchfiles=string.split(x.searchResult,"\n")
01941             if (self.debug):
01942                 print "File,numevents,lumi,dataset search output = ",searchfiles
01943             dataset=None
01944             # Parse output looking over files for a given run number
01945             for searchfile in searchfiles:
01946             
01947                 # ignore blank lines
01948                 if len(searchfile)==0:
01949                     continue
01950 
01951                 # Don't try to split the response describing found files;
01952                 # simply store that info
01953                 # (Send warning if found files is greater than # allowed files?)
01954                 if (searchfile.startswith("Found")):
01955                     self.foundfiles=self.foundfiles+string.atoi(string.split(searchfile)[1])
01956                     if (self.foundfiles==0):
01957                         self.commentLabel.configure(text="WARNING!  No files found for run # %i"%r)
01958                         self.dbsProgress.configure(text="No files found for run # %i"%r,
01959                                                    bg="black")
01960                         self.commentLabel.update_idletasks()
01961                         #return False
01962                         continue
01963                 else:
01964                     if (self.debug): print "\tFile,dataset,lumi search output = ",searchfile
01965                     try:
01966                         i=string.split(searchfile,",")
01967                         if (i[0].endswith(".root")):
01968                             tempFileInfo=FileInfo(searchfile)
01969                             if (tempFileInfo.goodFile==False):
01970                                 self.commentLabel.configure(text="Could not properly parse DBS entry:\n'%s'"%i)
01971                                 badcount=badcount+1
01972                                 if (self.debug):
01973                                     print "Could not properly parse DBS entry: %s"%i
01974                                     self.commentLabel.update_idletasks()
01975                             else:
01976                                 tempfiles.append(tempFileInfo)
01977                         else:
01978                              self.commentLabel.configure(text="Could not recognize DBS entry:\n'%s'"%i)
01979                              badcount=badcount+1
01980                              if (self.debug):
01981                                  print "Could not parse DBS entry: %s"%i
01982                              self.commentLabel.update_idletasks()
01983 
01984                     except SyntaxError:
01985                         self.commentLabel.configure(text="Could not parse DBS entry:\n'%s'"%i)
01986                         badcount=badcount+1
01987                         print "Could not parse DBS entry: %s"%i
01988                         self.commentLabel.update_idletasks()
01989 
01990             if len(tempfiles)==0:
01991                 # no files found
01992                 self.commentLabel.configure(text="No valid files found for run # %i"%r)
01993                 self.commentLabel.update_idletasks()
01994                 continue
01995             tempDBS=DBSRun()
01996             tempDBS.runnum=r
01997             tempDBS.maxEvents=self.maxDQMEvents.get()
01998             for fileobject in tempfiles:
01999                 tempDBS.AddFileInfo(fileobject)
02000             tempDBS.UpdateRunInfo()
02001 
02002             # Run not found -- create a new DBSRun object
02003             if r not in self.filesInDBS.keys():
02004                 self.filesInDBS[r]=tempDBS
02005             else:
02006                 # Run found
02007                 for f in tempfiles:
02008                     # Run found, but not this particular file -- need to add file Info to self.filesInDBS[r]
02009                     if f.fileName not in self.filesInDBS[r].files:
02010                         self.filesInDBS[r].fileInfo.append(f)
02011                 # After all new files found for run r, update info
02012                 self.filesInDBS[r].UpdateRunInfo()
02013             
02014 
02015             tmpvar=self.lumiBlockRange.get()
02016             if (tmpvar=="All"):
02017                 tmpvar="0"
02018             self.filesInDBS[r].lumiBlockIncrement=string.atoi(tmpvar)
02019 
02020         # Set lastFoundDBS to most recent run in filesInDBS 
02021         
02022         if len(self.filesInDBS.keys()):
02023             x=self.filesInDBS.keys()
02024             x.sort()
02025             x.reverse()
02026             if (self.autoRunShift):
02027                 self.lastFoundDBS.set(x[0]+1) # move to next run after last-found
02028             #for zz in x:
02029             #    print self.filesInDBS[zz].Print()
02030             #    for ff in self.filesInDBS[zz].files:
02031             #        print ff
02032 
02033             #self.lastFoundDBS.set(self.lastFoundDBS.get()+self.dbsRange.get())
02034         self.writePickle()
02035 
02036         if (self.foundfiles>self.myDBS.limit.get()):
02037             self.commentLabel.configure(text="WARNING! A total of %i files were found in DBS, but the current DBS limit is set to %i.  \nConsider increasing your DBS limit, or running on a smaller range of runs."%(self.foundfiles,self.myDBS.limit.get()))
02038             self.dbsProgress.configure(text="%i files found; only %i stored!"%(foundfiles,self.myDBS.limit.get()),
02039                                        bg="black")
02040             self.commentLabel.update_idletasks()
02041             return False
02042 
02043         if badcount:
02044             self.dbsProgress.configure(text="%i lines from DBS could not be parsed!"%badcount)
02045             self.commentLabel.update_idletasks()
02046             return False
02047         
02048         self.dbsProgress.configure(text="Successfully grabbed runs %i-%i"%(begin,end),
02049                                    bg="black")
02050         self.commentLabel.update_idletasks()
02051         
02052         return True
02053     
02054 
02055 
02056     def displayFiles(self):
02057         '''
02058         ** self.displayFiles() **
02059         Show all run numbers that have been found from DBS, along with the
02060         DQM status of each run.
02061         '''
02062 
02063         if (self.debug):
02064             print self.displayFiles.__doc__
02065 
02066         # Get runs, sort highest-to-lowest
02067         x=self.filesInDBS.keys()
02068         x.sort()
02069         x.reverse()
02070         temp ="%10s     %35s%10s%10s     %10s%12s%15s%15s     %20s\n"%(" Run #", "Dataset"," ",
02071                                                                    "# of files","#events","IgnoreRun?",
02072                                                                    "Started DQM?","Finished DQM?","Starting Lumiblock")
02073         
02074         for i in x:
02075             temp=temp+self.filesInDBS[i].Print()
02076         # Make window displaying run info
02077         if (len(x)<>1):
02078             title="A total of %i runs have been found in DBS"%len(x)
02079         else:
02080             title="A total of 1 run has been found in DBS"
02081         helpfunctions.Helpwin(temp,usetext=1,title=title )
02082         return
02083 
02084 
02085     def changeFileSettings(self):
02086         '''
02087         ** self.changeFileSettings() **
02088         Allows user to change the DQM status of the runs found from DBS.
02089         (Mark runs as having already completed DQM, set ignoreRun true, etc.)
02090         '''
02091 
02092         if (self.debug):
02093             print self.changeFileSettings.__doc__
02094 
02095         # If window exists already, destroy it and recreate 
02096         try:
02097             self.changevaluewin.destroy()
02098             self.changevaluewin=Toplevel()
02099         except:
02100             self.changevaluewin=Toplevel()
02101 
02102         maingeom=self.root.winfo_geometry()
02103         maingeomx=string.split(maingeom,"+")[1]
02104         maingeomy=string.split(maingeom,"+")[2]
02105         try:
02106             maingeomx=string.atoi(maingeomx)
02107             maingeomy=string.atoi(maingeomy)
02108             # new window is ~380 pixels high, place it directly below main window (250 pix high),
02109             # if room exists
02110             if (self.root.winfo_screenheight()-(maingeomy+250)>350):
02111                 self.changevaluewin.geometry('+%i+%i'%(maingeomx,maingeomy+250))
02112             elif (maingeomy>380):
02113                 self.changevaluewin.geometry('+%i+%i'%(maingeomx,maingeomy-380))
02114         except:
02115             self.changevaluewin.geometry('+500+320')
02116 
02117 
02118         self.changevaluewin.title("Change status of files")
02119         
02120         # Add list of runs as a list box with attached scrollbar
02121 
02122         self.changevaluewin.rowconfigure(0,weight=1)
02123         self.changevaluewin.columnconfigure(0,weight=1)
02124         scrollwin=Frame(self.changevaluewin)
02125         scrollwin.grid(row=0,column=0,sticky=NSEW)
02126         scrollwin.rowconfigure(1,weight=1)
02127         scrollwin.columnconfigure(0,weight=1)
02128         myrow=0
02129         temp = "%s%s%s%s%s%s"%(string.ljust(" Run #",20),
02130                                string.ljust("Started DQM?",20),string.ljust("Finished DQM?",20),
02131                                string.ljust("IgnoreRun?",20),string.ljust("# of files",20),
02132                                string.ljust("Dataset",30))
02133         Label(scrollwin,
02134               text=temp).grid(row=myrow,column=0,sticky=W)
02135         myrow=myrow+1
02136         self.lb=Listbox(scrollwin,
02137                         bg="white",
02138                         selectmode = MULTIPLE)
02139         # Get list of runs
02140         self.listboxruns=self.filesInDBS.keys()
02141         self.listboxruns.sort()
02142         self.listboxruns.reverse()
02143 
02144         for i in self.listboxruns:
02145             self.lb.insert(END,self.filesInDBS[i].Print2(screenoutput=self.debug))
02146             
02147         scroll=Scrollbar(scrollwin,command=self.lb.yview)
02148         
02149         self.lb.configure(yscrollcommand=scroll.set)
02150 
02151         xscroll=Scrollbar(scrollwin,command=self.lb.xview,
02152                           orient=HORIZONTAL)
02153         self.lb.configure(xscrollcommand=xscroll.set)
02154         
02155         self.lb.grid(row=myrow,column=0,sticky=NSEW)
02156         scroll.grid(row=myrow,column=1,sticky=NS)
02157         myrow=myrow+1
02158         xscroll.grid(row=myrow,column=0,sticky=EW)
02159 
02160         # Add buttons for changing DQM values
02161         myrow=myrow+1
02162         #self.changevaluewin.rowconfigure(myrow,weight=1)
02163         bFrame=Frame(self.changevaluewin)
02164         bFrame.grid(row=1,column=0)
02165         igY=Button(bFrame,
02166                    text="Set\n'Ignore Run'\nTrue",
02167                    command=lambda x=self:x.commandChangeFileSettings(self.lb.curselection(),
02168                                                                      "ignoreRun",True),
02169                    width=14,height=3)
02170         igN=Button(bFrame,
02171                    text="Set\n'Ignore Run'\nFalse",
02172                    command=lambda x=self:x.commandChangeFileSettings(self.lb.curselection(),
02173                                                                      "ignoreRun",False),
02174                    width=14,height=3)
02175         stY=Button(bFrame,
02176                    text="Set\n'Started DQM'\nTrue",
02177                     command=lambda x=self:x.commandChangeFileSettings(self.lb.curselection(),
02178                                                                       "startedDQM",True),
02179                    width=14,height=3)
02180         stN=Button(bFrame,
02181                    text="Set\n'Started DQM'\nFalse",
02182                    command=lambda x=self:x.commandChangeFileSettings(self.lb.curselection(),
02183                                                                      "startedDQM",False),
02184                    width=14,height=3)
02185         fiY=Button(bFrame,
02186                    text="Set\n'Finished DQM'\nTrue",
02187                    command=lambda x=self:x.commandChangeFileSettings(self.lb.curselection(),
02188                                                                      "finishedDQM",True),
02189                    width=14,height=3)
02190         fiN=Button(bFrame,
02191                    text="Set\n'Finished DQM'\nFalse",
02192                    command=lambda x=self:x.commandChangeFileSettings(self.lb.curselection(),
02193                                                                      "finishedDQM",False),
02194                    width=14,height=3)
02195         selAll=Button(bFrame,
02196                       text="Select\nall runs",
02197                       command=lambda x=self:x.commandChangeFileSettings(self.lb.curselection(),
02198                                                                         "selectall",True),
02199                       width=14,height=3)
02200         deselAll=Button(bFrame,
02201                         text="Deselect\nall runs",
02202                         command=lambda x=self:x.commandChangeFileSettings(self.lb.curselection(),
02203                                                                           "deselectall",False),
02204                         width=14,height=3)
02205         dbsSearch=Button(bFrame,
02206                          text="Search\nDBS for new\nruns",
02207                          bg=self.bg,
02208                          fg=self.fg,
02209                          command=lambda x=self:x.commandChangeFileSettings(self.lb.curselection(),
02210                                                                            "searchDBS",False))
02211 
02212         quitButton=Button(bFrame,
02213                           text="Close\nwindow",
02214                           bg=self.bg_alt,
02215                           fg=self.bg,
02216                           command=lambda x=self:x.changevaluewin.destroy())
02217         # Grid buttons
02218         igY.grid(row=0,column=3)
02219         stY.grid(row=0,column=1)
02220         fiY.grid(row=0,column=2)
02221         igN.grid(row=1,column=3)
02222         stN.grid(row=1,column=1)
02223         fiN.grid(row=1,column=2)
02224         selAll.grid(row=0,column=4)
02225         deselAll.grid(row=1,column=4)
02226         dbsSearch.grid(row=0,column=0,rowspan=2,sticky=NS)
02227         quitButton.grid(row=0,column=5,rowspan=2,sticky=NS)
02228 
02229         return
02230 
02231 
02232     def updateListbox(self):
02233         '''
02234         ** self.updateListbox() **
02235         Grabs updated run info from self.filesInDBS.keys
02236         and displays it in listbox.
02237         '''
02238 
02239         if (self.debug):
02240             print self.updateListbox.__doc__
02241 
02242         self.lb.delete(0,END)
02243         temp = "%s%s%s%s%s%s"%(string.ljust(" Run #",20),
02244                                string.ljust("Started DQM?",20),string.ljust("Finished DQM?",20),
02245                                string.ljust("IgnoreRun?",20),string.ljust("# of files",20),
02246                                string.ljust("Dataset",80))
02247         #self.lb.insert(END,temp)
02248         # Get list of runs
02249         self.listboxruns=self.filesInDBS.keys()
02250         self.listboxruns.sort()
02251         self.listboxruns.reverse()
02252 
02253         for i in self.listboxruns:
02254 
02255             self.lb.insert(END,self.filesInDBS[i].Print2(screenoutput=self.debug))
02256         return
02257         
02258     def commandChangeFileSettings(self,selected,var,value=True):
02259         '''
02260         ** self.commandChangeFileSettings(selected, var, value=True) **
02261         Commands for changing DQM settings.
02262         "selected" is the set of listbox indices that have been
02263         highlighted by the user.
02264         (self.listboxruns[int(i)] returns the associated run #, for
02265          all i in selected.)
02266         Allowed options for var:
02267         "ignoreRun", "startedDQM", "finishedDQM", "selectall", "deselectall"
02268         Value indicates whether var should be set True or False.  Default is True.
02269         '''
02270 
02271         if (self.debug):
02272             print self.commandChangeFileSettings.__doc__
02273 
02274         if (var=="selectall"):
02275             for i in range(0,self.lb.size()):
02276                 self.lb.selection_set(i)
02277             return
02278         elif (var=="deselectall"):
02279             for i in range(0,self.lb.size()):
02280                 self.lb.selection_clear(i)
02281             return
02282         
02283         for i in selected:
02284             run=self.listboxruns[int(i)] # get run number from index
02285 
02286             if (var=="ignoreRun"):
02287                 self.filesInDBS[run].ignoreRun=value
02288             elif (var=="startedDQM"):
02289                 self.filesInDBS[run].startedDQM=value
02290                 self.filesInDBS[run].currentLumiBlock=1
02291             elif (var=="finishedDQM"):
02292                 self.filesInDBS[run].finishedDQM=value
02293             
02294         if (var=="searchDBS"):
02295             self.checkDBS()
02296         self.writePickle() # save to pickle file?  I think this is the sensible option (user can always change back)
02297         self.updateListbox()
02298         return
02299 
02300 
02301     def toggleSCP(self):
02302         
02303         '''
02304         ** self.toggleSCP() **
02305         configures scp label based on self.enableSCP value.
02306         If SCP variable is off, no scp copying will take place.'''
02307 
02308         if (self.debug):
02309             print self.toggleSCP.__doc__
02310 
02311         if (self.enableSCP.get()==0):
02312             self.scpAutoButton.configure(text="scp copying disabled")
02313             self.copyLoc.configure(state=DISABLED)
02314         else:
02315             self.scpAutoButton.configure(text="scp copying enabled")
02316             self.copyLoc.configure(state=NORMAL)
02317         return
02318 
02319     
02320     def toggleAutoDBS(self):
02321         '''
02322         ** self.toggleSCP() **
02323         Changes DBS Auto update label based on state of self.dbsAutoVar.
02324         '''
02325 
02326         if (self.debug):
02327             print self.toggleAutoDBS.__doc__
02328 
02329         if (self.Automated.get()==False):
02330             self.dbsAutoButton.configure(text="Auto DQM\nupdate OFF",state=DISABLED)
02331             return
02332         
02333         if self.dbsAutoVar.get()==0 :
02334             self.dbsAutoButton.configure(text="Auto DBS\nupdate OFF")
02335         else:
02336             self.dbsAutoButton.configure(text="Auto DBS update\nevery %s minutes"%self.dbsAutoUpdateTime.get())
02337                                      
02338         return
02339 
02340     def toggleAutoDQM(self):
02341         '''
02342         ** self.toggleAutoDQM() **
02343         Changes DQM Auto update label based on state of self.dqmAutoVar.
02344         '''
02345 
02346         if (self.debug):
02347             print self.toggleAutoDQM.__doc__
02348 
02349         if (self.Automated.get()==False):
02350             self.dqmAutoButton.configure(text="Auto DQM\nupdate OFF",state=DISABLED)
02351             return
02352         if self.dqmAutoVar.get()==0 :
02353             self.dqmAutoButton.configure(text="Auto DQM\nupdate OFF")
02354         else:
02355             self.dqmAutoButton.configure(text="Auto DQM update\nevery %s minutes"%self.dqmAutoUpdateTime.get())
02356                                      
02357         return
02358 
02359 
02360     def toggleAutoRunShift(self,event):
02361         '''
02362         ** self.toggleAutoRunShift(event) **
02363         This toggles the autoRunShift variable.
02364         If autoRunShift is true, then the run entry
02365         value will increment whenever a new run is found.
02366         If not, the run entry value will remain the same.
02367         '''
02368 
02369         if (self.debug):
02370             print self.toggleAutoRunShift.__doc__
02371         
02372         self.autoRunShift=1-self.autoRunShift # toggle value
02373         # Change entry box color if auto shifting is not enabled
02374         if (self.autoRunShift==False):
02375               self.lastFoundDBSEntry.configure(bg="yellow")
02376         else:
02377             self.lastFoundDBSEntry.configure(bg="white")
02378         return
02379 
02380 
02381     def checkExistence(self,obj):
02382         '''
02383         ** self.checkExistence(obj) **
02384         Checks to see whether file/dir "obj" exists.
02385         Returns true/false boolean based on object existence.
02386 
02387         '''
02388 
02389         if (self.debug):
02390             print self.checkExistence.__doc__
02391             print obj.get()
02392         exists=True
02393         if not os.path.exists(obj.get()):
02394             self.commentLabel.configure(text="ERROR!\n Object '%s' does not exist!"%obj.get())
02395             self.commentLabel.update_idletasks()
02396             obj.set("ERROR -- FILE/DIR DOES NOT EXIST")
02397             exists=False
02398         else:
02399             self.commentLabel.configure(text="Set value to '%s'"%obj.get())
02400             self.commentLabel.update_idletasks()
02401         return exists
02402 
02403     def tempSCP(self):
02404         '''
02405         ** self.tempSCP() **
02406         Temporary method for running scp from local final directory
02407         to hcalusc55@cmshcal01:hcaldqm/global_auto/
02408         This feature has now been disabled
02409         '''
02410 
02411         if (self.debug):
02412             print self.tempSCP.__doc__
02413 
02414         if (self.debug):
02415             self.commentLabel.configure(text="scp copying is no longer used")
02416             self.commentLabel.update_idletasks()
02417         return
02418         
02419 
02420         if not (self.enableSCP.get()):
02421             self.commentLabel.configure(text="scp copying is not currently enabled.\n(Check button in the middle of the menu bar)")
02422             self.commentLabel.update_idletasks()
02423             return
02424         
02425         if not (os.path.exists(self.finalDir.get())):
02426             self.commentLabel.configure(text="ERROR -- directory '%s' DOES NOT EXIST!!\nEdit the Final DQM Save Directory in DQM options!"%self.finalDir.get())
02427             return
02428 
02429         self.commentLabel.configure(text="Trying to scp results to cmshcal01")
02430         self.commentLabel.update_idletasks()
02431         
02432         # make directory for files/dirs that have already been copied.
02433         if not os.path.isdir(os.path.join(self.finalDir.get(),"copied_to_hcaldqm")):
02434             os.mkdir(os.path.join(self.finalDir.get(),"copied_to_hcaldqm"))
02435 
02436         movelist=os.listdir(self.finalDir.get())
02437         movelist.remove("copied_to_hcaldqm")
02438         if len(movelist)==0:
02439             self.commentLabel.configure(text="There are no files in %s\n to be copied to cmshcal01!"%self.finalDir.get())
02440             self.commentLabel.update_idletasks()
02441             return
02442         text1="scp -r "
02443         text="scp -r "
02444         for i in movelist:
02445             text=text+"%s "%os.path.join(self.finalDir.get(),"copied_to_hcaldqm",i)
02446             text1=text1+"%s "%os.path.join(self.finalDir.get(),i)
02447         text=text+" hcalusc55@cmshcal01:/hcaldqm/global_auto\n\n"
02448         text1=text1+" hcalusc55@cmshcal01:/hcaldqm/global_auto\n\n"
02449 
02450         
02451         #if at cms (specifically, on lxplus or caf (lxb...)):
02452         #if os.getenv("USER")=="cchcal":
02453         compname=os.uname()[1]
02454 
02455         if (string.find(compname,"lxplus")>-1 or string.find(compname,"lxb")) and string.find(compname,".cern.ch")>-1:
02456             zzz=os.system(text1)
02457             print text1
02458             #print zzz
02459             self.commentLabel.configure(text = "FINISHED!\nPerformed scp of files to cmshcal01!")
02460             self.commentLabel.update_idletasks()
02461         
02462         else:  # not at cern
02463             helpfunctions.Helpwin(text,usetext=1,title="Cut and paste this command into your lxplus window now!" )
02464             self.commentLabel.configure(text="Cannot auto-scp to cmshcal from your machine!\nFollow instructions in the help window!")
02465             self.commentLabel.update_idletasks()
02466             
02467         # move files to the copied_to_hcaldqm subdirectory (so they won't be scp'd again)
02468         for i in movelist:
02469             if os.path.isdir(os.path.join(self.finalDir.get(),"copied_to_hcaldqm",i)):
02470                 os.system("rm -rf %s"%os.path.join(self.finalDir.get(),"copied_to_hcaldqm",i))
02471             cmd="mv %s %s\n"%(os.path.join(self.finalDir.get(),i),
02472                               os.path.join(self.finalDir.get(),"copied_to_hcaldqm",i))
02473             os.system(cmd)
02474 
02475         return
02476 
02477 
02478 
02479     def dbsSetUpdateMenu(self,upTime,allTimes):
02480         '''
02481         ** self.dbsUpdateMenu(upTime, allTimes) **
02482         Sets colors in "Set DBS Option Time" menu, and configures the DBS auto button label.
02483         allTimes = list of all time options specified in the menu
02484         upTime = list index of chosen time.
02485         Chosen time appears in red; all other times in black
02486         '''
02487 
02488         if (self.debug):
02489             print self.dbsSetUpdateMenu.__doc__
02490 
02491         self.dbsAutoUpdateTime.set(allTimes[upTime])
02492         for i in range(len(allTimes)):
02493             if i==upTime:
02494                 self.dbsUpdateMenu.choices.entryconfig(i,foreground="red")
02495             else:
02496                 self.dbsUpdateMenu.choices.entryconfig(i,foreground="black")
02497         if (self.Automated.get()==True):
02498             self.dbsAutoButton.configure(state=NORMAL,text="Auto DBS update\nevery %s minutes"%self.dbsAutoUpdateTime.get(),
02499                                          bg=self.bg,fg=self.fg)
02500         return
02501 
02502 
02503     def dbsSetHcalOnly(self,value,choices):
02504         '''
02505         ** self.dbsSetHcalOnlyMenu(value, choices) **
02506         Sets colors in "Set Hcal Only" menu, and configures the bool for only
02507         checking runs in which HCAL was present.
02508         '''
02509 
02510         if (self.debug):
02511             print self.dbsSetHcalOnly.__doc__
02512 
02513         self.dbsSetHcalValue.set(value)
02514             
02515         for i in range(len(choices)):
02516             if choices[i]==value:
02517                 self.dbsHcalOnlyMenu.choices.entryconfig(i,foreground="red")
02518             else:
02519                 self.dbsHcalOnlyMenu.choices.entryconfig(i,foreground="black")
02520         return
02521 
02522 
02523 
02524         
02525 
02526 
02527     def dqmSetUpdateMenu(self,upTime,allTimes):
02528         '''
02529         ** self.dqmUpdateMenu(upTime, allTimes) **
02530         Sets colors in "Set DQM Option Time" menu, and configures the DQM auto button label.
02531         allTimes = list of all time options specified in the menu
02532         upTime = list index of chosen time.
02533         Chosen time appears in red; all other times in black
02534         '''
02535 
02536         if (self.debug):
02537             print self.dqmSetUpdateMenu.__doc__
02538 
02539         self.dqmAutoUpdateTime.set(allTimes[upTime])
02540         for i in range(len(allTimes)):
02541             if i==upTime:
02542                 self.dqmUpdateMenu.choices.entryconfig(i,foreground="red")
02543             else:
02544                 self.dqmUpdateMenu.choices.entryconfig(i,foreground="black")
02545         if (self.Automated.get()==True):
02546             self.dqmAutoButton.configure(state=NORMAL,text="Auto DQM update\nevery %s minutes"%self.dqmAutoUpdateTime.get(),
02547                                          bg=self.bg,fg=self.fg)
02548         return
02549 
02550 
02551 
02552     def setLumiBlockMenu(self,lumiChoice,allLumis):
02553         '''
02554         *** self.setLumiBlockMenu(lumiChoice, allLumis) ***
02555         Sets colors in "Set lum"y block range" menu,
02556         and sets value of self.lumiBlockRange variable.
02557         lumiChoice = index of chosen lumi range.
02558         allLumis = list of all possible choices.
02559         Will also set all the lumi choices for all previously-found runs to the selected value
02560         '''
02561 
02562         if (self.debug):
02563             print self.setLumiBlockMenu.__doc__
02564 
02565         self.lumiBlockRange.set(allLumis[lumiChoice])
02566         if (self.debug):
02567             print "Chosen lumi range = ",self.lumiBlockRange.get() 
02568         for i in range(len(allLumis)):
02569             if i==lumiChoice:
02570                 self.lumiBlockRangeMenu.choices.entryconfig(i,foreground="red")
02571             else:
02572                 self.lumiBlockRangeMenu.choices.entryconfig(i,foreground="black")
02573         choice=self.lumiBlockRange.get()
02574         if choice=="All":
02575             choice="0"
02576 
02577         for r in self.filesInDBS.keys():
02578             # Compute Number of events just in the current range of luminosity blocks
02579             totalevents=0
02580             for myfile in range(len(self.filesInDBS[r].fileInfo)):
02581                 myval=self.filesInDBS[r].fileInfo[myfile].lumiBlock
02582                 # Check over luminosity ranges
02583                 if (choice=="0" or (myval>=self.filesInDBS[r].currentLumiBlock and myval<self.filesInDBS[r].currentLumiBlock+int(choice))):
02584                         
02585                     totalevents=totalevents+self.filesInDBS[r].fileInfo[myfile].numEvents
02586             self.filesInDBS[r].totalEvents=totalevents
02587 
02588             
02589             self.filesInDBS[r].lumiBlockIncrement=string.atoi(choice)
02590             # This doesn't seem to work; use a direct "get" of self.lumiBlockRange
02591             if (self.debug):
02592                 print "<setLumiBlockMenu> run # = %i, lumi block increment = %i"%(r, self.filesInDBS[r].lumiBlockIncrement)
02593         return
02594     
02595 ############################################
02596 
02597 if __name__=="__main__":
02598 
02599     mygui=dbsBaseGui(debug=1)  # set up gui
02600     mygui.DrawGUI()
02601     mygui.root.mainloop() # run main loop
02602 
02603 
02604 

Generated on Tue Jun 9 17:32:56 2009 for CMSSW by  doxygen 1.5.4