def __init__(self, configFile, logDir, logScheme='?', bufferSize=4000, startTimeFromFilepathFun=None): self.logDir = logDir conf = configLoader.load_confDict(configFile) if logScheme == '?': logScheme = self.detect_logScheme(conf) print("Detected logFile scheme:", logScheme) self.logScheme = logScheme self.conf = conf[logScheme] self.columns = collections.OrderedDict() self.units = collections.OrderedDict() for qualifier in ["essential", "optional"]: if not qualifier + "Columns" in conf.keys(): continue for key in conf[qualifier + "Columns"][logScheme].keys(): self.columns[key] = conf[qualifier + "Columns"][logScheme][key] self.units[key] = conf[qualifier + "Columns"]["units"][key] self.current = None self.dataBuffer = None self.lastTime = 0 self.bufferSize = bufferSize self.startTimeFromFilepathFun = startTimeFromFilepathFun sys.stdout.write("Filling data buffer...") self.fill_dataBuffer() sys.stdout.write("done!\n")
def __init__(self, master, conf, *args, **kwargs): if not type(conf) is dict: conf = configLoader.load_confDict(conf) self.valveReader = LogFileReader.Reader(conf["valveLogDescriptor"], conf["valveLogPath"]) super(ValvePicarroFrame, self).__init__(master, conf, *args, **kwargs)
def refresh_configuration(self): freshConf = configLoader.load_confDict(self.conf["confFile"]) for key in freshConf.keys(): if key in [ "autoSwitchEnable", "autoSwitchCooldown", "H2O_yellowAlert", "H2O_redAlert" ]: self.conf[key] = freshConf[key]
def refresh_configuration(self): # step 1: reload conf for the valve controller super(ValveControlFrame, self).refresh_configuration() # step 2: reload conf for the flow controller freshFlowConf = configLoader.load_confDict( self.metaController.flow.conf["confFile"]) for key in freshFlowConf["probeType"].keys(): self.metaController.flow.conf["probeType"][key] = freshFlowConf[ "probeType"][key] self.metaController.flow.fc.set_flowCalibration( freshFlowConf["calibration"])
def refresh_configuration(self): activeSlot = self.conf["ID"][self.activeID]["slot"] self.conf = check_valveCfg( configLoader.load_confDict(self.conf["confFile"])) self.valveDict = self.fill_buttonFrame() self.valveSequence = self.fill_sequenceButtonFrame() # these lines take care of cases where the previously active slot has been given to a new ID for ID in self.valveDict.keys(): if '%d#%d' % (self.valveDict[ID].box, self.valveDict[ID].slot) == activeSlot: self.activeID = ID self.valveDict[ID].stateVar = self.conf["ID"][ID]["state"] > 0 self.update_valveButtons()
def __init__(self, master, vc, valveConfigFile="../config/valve.cfg", *args, **kwargs): super(ValveControlFrame, self).__init__(master, *args, **kwargs) self.master = master self.vc = vc self.switchCode = const.SWITCH_START self.activeID = "" self.sequencePosition = -1 self.flowMode = "measure" self.sequMode = "inactive" self.startTime = 0 self.conf = check_valveCfg(configLoader.load_confDict(valveConfigFile)) # ----- prepare valve log file ---- parActiveValve = DataBuffer.Parameter(name="ID", unit="active valve") parMeasurement = DataBuffer.Parameter(name="measurement", unit="state") parSwitchCode = DataBuffer.Parameter(name = "switchCode", unit = "%d = manual | %d = timeout | %d = optimal | %d = alert"\ %(const.SWITCH_MANUAL, const.SWITCH_TIMEOUT, const.SWITCH_OPTIMUM, const.SWITCH_ALERT)) self.valveBuffer = DataBuffer.Buffer( 100, self.conf["logFile"], parameters=[parActiveValve, parMeasurement, parSwitchCode]) #-------------------------------------------------------------- if not vc.check_status(): self.infoFrame = tk.Frame(master) self.infoFrame.place(relheight=1, relwidth=1, x=0, y=0) self.infoFrame.config(bg="#fbb") tk.Button( self.infoFrame, command=self.hide_infoFrame, text= "No valve controller connected\n Click to proceed without functional valve controller" ).pack(side=tk.TOP) # create basic frames for layout self.buttonFrame = tk.Frame(self) self.buttonFrame.grid(row=0, column=0, sticky="nsew") self.rightFrame = tk.Frame(self) self.rightFrame.grid(row=0, column=1, sticky="nsew") self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) self.columnconfigure(1, weight=2) # ---- right frame (mainly valve sequence)------------- ----------- self.rightFrame.rowconfigure(0, weight=0) self.rightFrame.rowconfigure(1, weight=5) self.rightFrame.columnconfigure(0, weight=1) self.upperRightFrame = tk.Frame(self.rightFrame) self.upperRightFrame.grid(row=0, column=0, sticky="nsew") self.upperRightFrame.rowconfigure(0, weight=1) self.upperRightFrame.columnconfigure(0, weight=1) self.upperRightFrame.columnconfigure(1, weight=3) self.upperRightFrame.columnconfigure(2, weight=1) self.lowerRightFrame = tk.Frame(self.rightFrame) self.lowerRightFrame.grid(row=1, column=0, sticky="nsew") self.lowerRightFrame.rowconfigure(0, weight=1) self.lowerRightFrame.columnconfigure(0, weight=0) self.lowerRightFrame.columnconfigure(1, weight=1) self.progressFrame = tk.Frame(self.lowerRightFrame) self.progressFrame.grid(row=0, column=0, sticky="nsew") self.sequenceFrame = tk.Frame(self.lowerRightFrame) self.sequenceFrame.grid(row=0, column=1, sticky="nsew") self.sequenceFrame.rowconfigure(1, weight=1) self.sequenceFrame.columnconfigure(0, weight=1) self.sequenceControlFrame = tk.Frame(self.sequenceFrame) self.sequenceControlFrame.grid(row=0, column=0, sticky="nsew") self.sequenceControlFrame.columnconfigure(0, weight=1) self.sequenceControlFrame.columnconfigure(1, weight=2) self.sequenceButtonFrame = tk.Frame(self.sequenceFrame) self.sequenceButtonFrame.grid(row=1, column=0, sticky="nsew") # ------------ create valve control buttons ------------------- self.valveDict = self.fill_buttonFrame() #-------- schedule, status and refresh ----------------------------- self._scheduleButtonImage = tk.PhotoImage(file="../images/time_24.gif") self.scheduleButton = tk.Button(self.upperRightFrame, text="Schedule", image=self._scheduleButtonImage, command=self.schedule, width=24) self.scheduleButton.grid(row=0, column=0, sticky="nsew") ExtraWidgets.ToolTip(self.scheduleButton, u"To be implemented...") self.extraLabel = tk.Label(self.upperRightFrame, text="~~~~~~~~~~~", bg='#ddd') self.extraLabel.grid(row=0, column=1, sticky='nsew') self.extraLabel.bind("<Button-1>", self.extraLabel_click) self._refreshButtonImage = tk.PhotoImage( file="../images/refresh_16.gif") self.refreshButton = tk.Button(self.upperRightFrame, text="Refresh", image=self._refreshButtonImage, command=self.refresh_configuration) self.refreshButton.grid(row=0, column=2, sticky="nsew") ExtraWidgets.ToolTip(self.refreshButton, u"Reload flow profiles (from flow.cfg) and H\u2082O thresholds (from valve.cfg)\n"+\ "Changing the logfile path requires a restart") #-------- progress bars ------------------------------------------ self.progBars = {} for mode, side, anchor in [("flush", 'bottom', 'n'), ("measure", 'top', 's')]: style = ttk.Style() style.configure("%s.Vertical.TProgressbar" % mode, background=colors[mode]) progBar = ttk.Progressbar(self.progressFrame, style="%s.Vertical.TProgressbar" % mode, orient=tk.VERTICAL, maximum=50, mode='determinate') label = tk.Label(progBar, text=u"\u221e", bg=colors[mode], wraplength=1) label.place(relx=0.2, rely=0.5) progBar.pack(side=side, anchor=anchor, expand=2, fill=tk.BOTH) self.progBars[mode] = {"bar": progBar, "label": label} #----- sequence buttons -------------------------------------- self.valveSequence = self.fill_sequenceButtonFrame() #------ sequence control buttons-------------------------------- self._sequenceButtonImages = [] for name in ["start_32", "stop_32", "next_32", "hourglass_32"]: try: image = tk.PhotoImage(file="../images/" + name + ".gif") except: image = None self._sequenceButtonImages.append(image) buttonFont = tkFont.Font(family="Sans", weight="bold") self.sequenceButton = tk.Button(self.sequenceControlFrame, command=self.toggle_sequence, text="start\nsequence", font=buttonFont, image=self._sequenceButtonImages[0]) self.sequenceButton_skip = tk.Button( self.sequenceControlFrame, command=lambda: self.continueSequence(skip=True), text="start\nsequence", font=buttonFont, image=self._sequenceButtonImages[2]) self.sequenceButton.grid(row=0, column=0, sticky="nsew") self.sequenceButton_skip.grid(row=0, column=1, sticky="nsew") ExtraWidgets.ToolTip( self.sequenceButton, text= "Start/Stop the valve sequence\nThe seuquence goes from left to right and from top to bottom" ) ExtraWidgets.ToolTip( self.sequenceButton_skip, text= "Skip current valve and continue with the next one in the sequence" ) colors["neutralButton"] = self.sequenceButton.cget("bg") self.set_probeProfile() self._job = None self.sequencePaused = False print("Giving the valve controller some time...") self.after(2500, self.startup)
from tkinter import font as tkFont import datetime import time import os import math import collections import gc import PlotCanvas import ExtraWidgets import DataBuffer import configLoader import support import const colors = configLoader.load_confDict("../config/default/colors.cfg") MAX_VALVES_PER_COLUMN = const.MAX_VALVES_PER_COLUMN def check_valveCfg(cfg): # make sure that a group and state is assigned (even if not specified in cfg file) for ID in cfg["ID"].keys(): if not "group" in cfg["ID"][ID].keys(): cfg["ID"][ID]["group"] = "A" if not "state" in cfg["ID"][ID].keys(): cfg["ID"][ID]["state"] = 1 if not "sequence" in cfg.keys(): cfg["sequence"] = [
def __init__(self, master, conf, *args, **kwargs): super(PicarroFrame, self).__init__(master, *args, **kwargs) self.master = master if type(conf) is dict: self.conf = conf else: self.conf = configLoader.load_confDict(confFile) # try to locate the picarro log dir if type(conf["rawLogSearchPaths"]) is list: for entry in conf["rawLogSearchPaths"]: if os.path.exists(entry): logDir = entry break else: logDir = conf["rawLogSearchPaths"] # initialize the picarro log file reader self.reader = LogFileReader.Reader( conf["logDescriptor"], logDir, bufferSize=int(conf["bufferSize"]), startTimeFromFilepathFun=startTimeFromFilepathFun) self.parCanvas = [] self.parListboxLabel = [] self.statLabels = [] self.recentStats = None self.conf = conf self.current = collections.OrderedDict() for p in self.conf["plotPars"]: self.current[p] = 0 self.currentSelection = None self.latestInfo = None self.currentRecord = 0 #------------------------------ self.canvasHolders = collections.OrderedDict() dummySummary = summary([0, 1, 2, 3, 4, 5]) for i, parName in enumerate(self.conf["plotPars"]): x = tk.Frame(self) x.grid(row=i, column=0, sticky='nsew', pady=0) self.rowconfigure(i, weight=1) x.columnconfigure(0, weight=1) x.columnconfigure(1, weight=1) self.parCanvas.append( PlotCanvas.PlotCanvas(x, plotRangeX=[0, 20], plotRangeY=[0, 20], marginX=60, marginY=17, axes=True, bg="white", selectionHandler=self.change_selection, height=117, width=600)) self.parCanvas[i].grid(row=0, column=0, rowspan=len(dummySummary.keys()) + 2, sticky='nsew') #x.rowconfigure(0, weight=1) self.parListboxLabel.append( ExtraWidgets.ListboxLabel(x, self.reader.dataBuffer.keys(), i)) self.parListboxLabel[i].grid(row=1, column=1, sticky='we') tk.Label(x, text='').grid(row=4, column=1) # dummy label for spacing labelDict = collections.OrderedDict() for n, key in enumerate(dummySummary.keys()): if key.startswith("_"): continue labelDict[key] = tk.Label(x, text=key) labelDict[key].grid(row=n + 2, column=1, sticky="nsew") x.rowconfigure(2 * n, weight=1) x.rowconfigure(2 * n + 1, weight=1) self.statLabels.append(labelDict) self.canvasHolders[parName] = x self.bind("<Configure>", self.on_resize) #---------- self._buttonImages = collections.OrderedDict() for name in ["start_24", "pause_24", "refresh_16"]: try: image = tk.PhotoImage(file="../images/" + name + ".gif") except: image = None self._buttonImages[name] = image refreshButton = tk.Button(self.canvasHolders[parName], text="Reload", command=self.reload_configuration, image=self._buttonImages["refresh_16"]) refreshButton.place(rely=1.0, relx=1.0, x=0, y=0, anchor=tk.SE) ExtraWidgets.ToolTip( refreshButton, text="Reload evaluation specs\n(from piccaro.cfg)") self.pauseButton = tk.Button(self.canvasHolders[parName], text="Reload", command=self.toggle_plotState, image=self._buttonImages["pause_24"]) self.pauseButton.place(rely=1., relx=1.0, x=-40, y=0, anchor=tk.SE) ExtraWidgets.ToolTip(self.pauseButton, text="Pause/Resume plotting") self.do_plots = True #---------- self.master.bind("<KeyPress>", self.keydown) self.maxZoomOutMinutes = self.conf["plotMinutes"] self.lastPlotRange = [time.time() - 60, time.time()] #--------- self.update()
def reload_configuration(self): freshConf = configLoader.load_confDict(self.conf["confFile"]) self.conf = freshConf.copy()
def __init__(self, master, fc, flowConfigFile="../config/flow.cfg", *args, **kwargs): super(FlowControlFrame, self).__init__(master, *args, **kwargs) self.fc = fc self.status = -1 self.master = master self.master.grid_columnconfigure(0, weight=1) self.master.grid_rowconfigure(0, weight=1) self.isFlushing = True self.isCycling = False self.cycleStartTime = time.time() self.job = None self.conf = configLoader.load_confDict(flowConfigFile) self.profiles = [ self.conf["profile"][key] for key in self.conf["profile"].keys() ] if not self.conf["logfile"]: logfilePath = None #self.fc.apply_calibration(configLoader.load_confDict("../config/flow.cal")) #----------- preapre the dataBuffer (and logfile) ---------- rD = self.conf["relevantDifference"] parList = [ DataBuffer.Parameter(name="flowValueA", unit="mL/min", relevantDifference=rD), DataBuffer.Parameter(name="flowValueB", unit="mL/min", relevantDifference=rD), DataBuffer.Parameter(name="targetValueA", unit="mL/min", relevantDifference=0), DataBuffer.Parameter(name="targetValueB", unit="mL/min", relevantDifference=0) ] if "logfile" in self.conf.keys(): logfile = self.conf["logfile"] else: None self.dataBuffer = DataBuffer.Buffer(int(self.conf["bufferSize"]), logfile, parList, flushChunk=20) #----left frame: controls and labels---------------- self.font = tkFont.Font(family="Sans", size=11, weight="bold") self.leftFrame = tk.Frame(self, width=100) self.leftFrame.pack(side=tk.LEFT, fill=tk.Y) for n in range(4): self.leftFrame.grid_rowconfigure(n, weight=n > 1) tk.Label(self.leftFrame, text="flow [mL/min]", font=self.font).grid(row=0, column=1, columnspan=3, sticky="nsew") tk.Label(self.leftFrame, text="A", font=self.font, bg=colors["fcA"]).grid(row=1, column=2, columnspan=1, sticky="nsew") tk.Label(self.leftFrame, text="B", font=self.font, bg=colors["fcB"]).grid(row=1, column=3, columnspan=1, sticky="nsew") self.button_flush = tk.Button(self.leftFrame, command=self.toggle_mode, text="flush", font=self.font, wraplength=1, relief=tk.SUNKEN, bg=colors["active"]) self.button_flush.grid(row=3, column=1, sticky="nsew") self.button_measure = tk.Button(self.leftFrame, command=self.toggle_mode, text="measure", font=self.font, wraplength=1, relief=tk.RAISED) self.button_measure.grid(row=2, column=1, sticky="nsew") colors["neutralButton"] = self.button_measure.cget("bg") self.flushScaleA = tk.Scale(self.leftFrame, from_=fc.maxFlowA, to=0, orient=tk.VERTICAL, length=50, bg=colors["flush"]) self.flushScaleA.grid(row=3, column=2, sticky="nsew") self.flushScaleA.set(self.profiles[0]["fRateA"]) self.flushScaleA.bind("<ButtonRelease-1>", self.changeFlowRate) self.measureScaleA = tk.Scale(self.leftFrame, from_=fc.maxFlowA, to=0, orient=tk.VERTICAL, length=50, bg=colors["measure"]) self.measureScaleA.grid(row=2, column=2, sticky="nsew") self.measureScaleA.set(self.profiles[0]["mRateA"]) self.measureScaleA.bind("<ButtonRelease-1>", self.changeFlowRate) self.flushScaleB = tk.Scale(self.leftFrame, from_=fc.maxFlowB, to=0, orient=tk.VERTICAL, length=50, bg=colors["flush"]) self.flushScaleB.grid(row=3, column=3, sticky="nsew") self.flushScaleB.set(self.profiles[0]["fRateB"]) self.flushScaleB.bind("<ButtonRelease-1>", self.changeFlowRate) self.measureScaleB = tk.Scale(self.leftFrame, from_=fc.maxFlowB, to=0, orient=tk.VERTICAL, length=50, bg=colors["measure"]) self.measureScaleB.grid(row=2, column=3, sticky="nsew") self.measureScaleB.set(self.profiles[0]["mRateB"]) self.measureScaleB.bind("<ButtonRelease-1>", self.changeFlowRate) #------ right frame: plot canvas ------ self.plotCanvas = PlotCanvas.PlotCanvas(self, plotRangeX=[0, 20], plotRangeY=[0, 50], axes=True, bg="white", marginX=50, marginY=25, height=300, width=400) self.plotCanvas.create_text(400, 50, text="waiting for connection...", font=tkFont.Font(size=20), tags="initial") self.plotCanvas.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1) #------------------- self.bind("<Configure>", self.on_resize) self.changeFlowRate() self.update() self.after(5000, self.after_startup)
import tkinter as tk from tkinter import font as tkFont import datetime import time import os import PlotCanvas import DataBuffer import configLoader colors = configLoader.load_confDict("../config/default/colors.cfg") class FlowControlFrame(tk.Frame): def __init__(self, master, fc, flowConfigFile="../config/flow.cfg", *args, **kwargs): super(FlowControlFrame, self).__init__(master, *args, **kwargs) self.fc = fc self.status = -1 self.master = master self.master.grid_columnconfigure(0, weight=1) self.master.grid_rowconfigure(0, weight=1) self.isFlushing = True self.isCycling = False self.cycleStartTime = time.time()
def __init__(self, master, vc, valveConfigFile="../config/valve.cfg", *args, **kwargs): super(ValveControlFrame, self).__init__(master, *args, **kwargs) self.master = master self.vc = vc self.switchCodeDict = { "startup": 0, "manual": 1, "timeout": 2, "optimal": 3, "alert": 4 } self.switchCode = 0 self.activeID = "" self.sequencePosition = -1 self.flowMode = "measure" self.sequMode = "inactive" self.startTime = 0 self.conf = configLoader.load_confDict(valveConfigFile) # make sure that a group and state is assigned (even if not specified in cfg file) for ID in self.conf["ID"].keys(): if not "group" in self.conf["ID"][ID].keys(): self.conf["ID"][ID]["group"] = "A" if not "state" in self.conf["ID"][ID].keys(): self.conf["ID"][ID]["state"] = 1 # ----- prepare valve log file ---- parActiveValve = DataBuffer.Parameter(name="ID", unit="active valve") parMeasurement = DataBuffer.Parameter(name="measurement", unit="state") parSwitchCode = DataBuffer.Parameter( name="switchCode", unit="0 = manual | 1 = timeout | 2 = optimal | 3 = alert") self.valveBuffer = DataBuffer.Buffer( 100, self.conf["logFile"], parameters=[parActiveValve, parMeasurement, parSwitchCode]) #-------------------------------------------------------------- if not vc.check_status(): self.infoFrame = tk.Frame(master) self.infoFrame.place(relheight=1, relwidth=1, x=0, y=0) self.infoFrame.config(bg="#fbb") tk.Button( self.infoFrame, command=self.hide_infoFrame, text= "No valve controller connected\n Click to proceed without functional valve controller" ).pack(side=tk.TOP) if not "sequence" in self.conf.keys(): self.conf["sequence"] = [ self.conf["ID"][key]["name"] for key in self.conf["valve"].keys() ] # create basic frames for layout self.buttonFrame = tk.Frame(self) self.buttonFrame.grid(row=0, column=0, sticky="nsew") self.rightFrame = tk.Frame(self) self.rightFrame.grid(row=0, column=1, sticky="nsew") self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) self.columnconfigure(1, weight=2) # ---- right frame (mainly valve sequence)------------- ----------- self.rightFrame.rowconfigure(0, weight=0) self.rightFrame.rowconfigure(1, weight=5) self.rightFrame.columnconfigure(0, weight=1) self.upperRightFrame = tk.Frame(self.rightFrame) self.upperRightFrame.grid(row=0, column=0, sticky="nsew") self.upperRightFrame.rowconfigure(0, weight=1) self.upperRightFrame.columnconfigure(0, weight=1) self.upperRightFrame.columnconfigure(1, weight=3) self.upperRightFrame.columnconfigure(2, weight=1) self.lowerRightFrame = tk.Frame(self.rightFrame) self.lowerRightFrame.grid(row=1, column=0, sticky="nsew") self.lowerRightFrame.rowconfigure(0, weight=1) self.lowerRightFrame.columnconfigure(0, weight=0) self.lowerRightFrame.columnconfigure(1, weight=1) self.progressFrame = tk.Frame(self.lowerRightFrame) self.progressFrame.grid(row=0, column=0, sticky="nsew") self.sequenceFrame = tk.Frame(self.lowerRightFrame) self.sequenceFrame.grid(row=0, column=1, sticky="nsew") self.sequenceFrame.rowconfigure(1, weight=1) self.sequenceFrame.columnconfigure(0, weight=1) self.sequenceControlFrame = tk.Frame(self.sequenceFrame) self.sequenceControlFrame.grid(row=0, column=0, sticky="nsew") self.sequenceControlFrame.columnconfigure(0, weight=1) self.sequenceControlFrame.columnconfigure(1, weight=2) self.sequenceButtonFrame = tk.Frame(self.sequenceFrame) self.sequenceButtonFrame.grid(row=1, column=0, sticky="nsew") # ------------ create valve control buttons ------------------- self.valveDict = collections.OrderedDict() N = len(self.conf["ID"].keys()) columnCount = math.ceil(N / maxValvesPerColumn) rowCount = math.ceil(N / columnCount) for i, ID in enumerate(self.conf["ID"].keys()): button = tk.Button(self.buttonFrame, command=lambda j=i: self.valveButton_click(j), font=tkFont.Font(family="Sans", size=9, weight="bold"), text=ID, bg=colors["group_" + self.conf["ID"][ID]["group"]], disabledforeground="#866") button.bind('<Button-3>', self.rightClick) stateVar = tk.IntVar() checkbox = tk.Checkbutton(self.buttonFrame, text="", variable=stateVar, command=self.update_valveButtons, relief=tk.FLAT) self.valveDict[ID] = Valve(ID, self.conf["ID"][ID]["slot"], self.conf["ID"][ID]["profile"], button, checkbox, stateVar, self.conf["ID"][ID]["group"]) row = math.floor(i / columnCount) column = i - math.floor(row * columnCount) self.valveDict[ID].grid(row=row, column=column) self.buttonFrame.rowconfigure(row, weight=1) self.buttonFrame.columnconfigure(column, weight=1) #-------- schedule, status and refresh ----------------------------- self._scheduleButtonImage = tk.PhotoImage(file="../images/time_24.gif") self.scheduleButton = tk.Button(self.upperRightFrame, text="Schedule", image=self._scheduleButtonImage, command=self.schedule, width=24) self.scheduleButton.grid(row=0, column=0, sticky="nsew") ExtraWidgets.ToolTip(self.scheduleButton, u"To be implemented...") self.extraLabel = tk.Label(self.upperRightFrame, text="~~~~~~~~~~~", bg='#ddd') self.extraLabel.grid(row=0, column=1, sticky='nsew') self.extraLabel.bind("<Button-1>", self.extraLabel_click) self._refreshButtonImage = tk.PhotoImage( file="../images/refresh_16.gif") self.refreshButton = tk.Button(self.upperRightFrame, text="Refresh", image=self._refreshButtonImage, command=self.refresh_configuration) self.refreshButton.grid(row=0, column=2, sticky="nsew") ExtraWidgets.ToolTip(self.refreshButton, u"Reload flow profiles (from flow.cfg) and H\u2082O thresholds (from valve.cfg)\n"+\ "Changes to the valve sequence require a restart") #-------- progress bars ------------------------------------------ self.progBars = {} for mode, side, anchor in [("flush", 'bottom', 'n'), ("measure", 'top', 's')]: style = ttk.Style() style.configure("%s.Vertical.TProgressbar" % mode, background=colors[mode]) progBar = ttk.Progressbar(self.progressFrame, style="%s.Vertical.TProgressbar" % mode, orient=tk.VERTICAL, maximum=50, mode='determinate') label = tk.Label(progBar, text=u"\u221e", bg=colors[mode], wraplength=1) label.place(relx=0.2, rely=0.5) progBar.pack(side=side, anchor=anchor, expand=2, fill=tk.BOTH) self.progBars[mode] = {"bar": progBar, "label": label} #----- sequence buttons -------------------------------------- N = len(self.conf["sequence"]) columnCount = math.ceil(N / maxValvesPerColumn) rowCount = math.ceil(N / columnCount) #for col in range(columnCount): # self.sequenceButtonFrame.columnconfigure(col, weight=1) #for row in range(rowCount): # self.sequenceButtonFrame.rowconfigure(row, weight=1) self.valveSequence = [] for i, ID in enumerate(self.conf["sequence"]): button = (tk.Button( self.sequenceButtonFrame, command=lambda j=i: self.sequenceButton_click(j), font=tkFont.Font(family="Sans", size=9, weight="bold"), text=ID, bg=colors["group_" + self.conf["ID"][ID]["group"]])) button.bind('<Button-3>', self.rightClick) stateVar = tk.IntVar() checkbox = tk.Checkbutton(self.sequenceButtonFrame, text="", variable=stateVar, command=self.update_valveButtons, relief=tk.FLAT) self.valveSequence.append( Valve(ID, self.conf["ID"][ID]["slot"], self.conf["ID"][ID]["profile"], button, checkbox, stateVar, self.conf["ID"][ID]["group"])) row = math.floor(i / columnCount) column = i - math.floor(row * columnCount) self.valveSequence[-1].grid(row=row, column=column) self.sequenceButtonFrame.rowconfigure(row, weight=1) self.sequenceButtonFrame.columnconfigure(column, weight=1) #------ sequence control buttons-------------------------------- self._sequenceButtonImages = [] for name in ["start_32", "stop_32", "next_32", "hourglass_32"]: try: image = tk.PhotoImage(file="../images/" + name + ".gif") except: image = None self._sequenceButtonImages.append(image) buttonFont = tkFont.Font(family="Sans", weight="bold") self.sequenceButton = tk.Button(self.sequenceControlFrame, command=self.toggle_sequence, text="start\nsequence", font=buttonFont, image=self._sequenceButtonImages[0]) self.sequenceButton_skip = tk.Button( self.sequenceControlFrame, command=lambda: self.continueSequence(skip=True), text="start\nsequence", font=buttonFont, image=self._sequenceButtonImages[2]) self.sequenceButton.grid(row=0, column=0, sticky="nsew") self.sequenceButton_skip.grid(row=0, column=1, sticky="nsew") ExtraWidgets.ToolTip( self.sequenceButton, text= "Start/Stop the valve sequence\nThe seuquence goes from left to right and from top to bottom" ) ExtraWidgets.ToolTip( self.sequenceButton_skip, text= "Skip current valve and continue with the next one in the sequence" ) colors["neutralButton"] = self.sequenceButton.cget("bg") self.set_probeProfile() self._job = None self.sequencePaused = False # give the val print("Giving the valve controller some time...") self.after(2500, self.startup)
propagate=False) def on_resize(self, event): self.plotCanvas.on_resize(self.master.winfo_width() - 120, self.master.winfo_height() - 30) class PicarroFrame(GUI_Picarro.ValvePicarroFrame): def broadcast(self, message): pass if __name__ == "__main__": # load the flow calibration before initializing the hardware flowCalibration = configLoader.load_confDict( "../config/flow.cfg")["calibration"] # scan all ports to find the one, where the "IsWISaS_Controller" is connected #deviceDict, portDict = SerialDevices.scan_serialPorts(9600, "../temp/serial.cch") dInfo = SerialDevices.find_device("IsWISaS_Controller", [9600], cachePath="../temp/serial.cch") d = SerialDevices.IsWISaS_Controller(dInfo["port"], dInfo["baudRate"], flowCalibration) root = tk.Tk() root.title("IsWISaS2") root.geometry("%dx%d+%d+%d" % (1200, 850, 1, 0)) tab_parent = ttk.Notebook(root)