diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..68983c17 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,22 @@ +## Description + + +## Checklist +Before submitting this PR, please ensure the following: + +- [ ] I am using the **correct branches/versions** of all submodules. +- [ ] I have successfully **launched the Simplified GUI**. +- [ ] I have successfully **run a test in the Simplified GUI**. +- [ ] I have successfully **run a test in the Expert GUI**. + +## Related Issues + + +## Changes Made + + +## Testing + + +## Additional Notes + diff --git a/.github/workflows/require-checklist.yaml b/.github/workflows/require-checklist.yaml new file mode 100644 index 00000000..55c852b9 --- /dev/null +++ b/.github/workflows/require-checklist.yaml @@ -0,0 +1,15 @@ +name: Require Checklist + +on: + pull_request: + types: [opened, edited, synchronize] + issues: + types: [opened, edited, deleted] + +jobs: + job1: + runs-on: ubuntu-latest + steps: + - uses: mheap/require-checklist-action@v2 + with: + requireChecklist: false # If this is true and there are no checklists detected, the action will fail \ No newline at end of file diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml new file mode 100644 index 00000000..f98d599d --- /dev/null +++ b/.github/workflows/ruff.yml @@ -0,0 +1,15 @@ +name: Ruff +on: [ push, pull_request ] +jobs: + ruff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: astral-sh/ruff-action@v3 + with: + args: "check" + src: "./Gui" + - uses: astral-sh/ruff-action@v3 + with: + args: "format --check --diff" + src: "./Gui" diff --git a/Gui/GUIutils/ANSIColorText.py b/Gui/GUIutils/ANSIColorText.py index dd5bf46d..f3ef9196 100644 --- a/Gui/GUIutils/ANSIColorText.py +++ b/Gui/GUIutils/ANSIColorText.py @@ -1,14 +1,14 @@ """ - ANSIColorText.py - brief Text handler for Ph2 ACF GUI - author Kai Wei - version 0.1 - date 09/24/20 - Support: email to wei.856@osu.edu +ANSIColorText.py +brief Text handler for Ph2 ACF GUI +author Kai Wei +version 0.1 +date 09/24/20 +Support: email to wei.856@osu.edu """ + import tkinter as tk import re -from Gui.python.logging_config import logger class AnsiColorText(tk.Text): diff --git a/Gui/GUIutils/DBConnection.py b/Gui/GUIutils/DBConnection.py index 66c846a9..ac8f5d8c 100644 --- a/Gui/GUIutils/DBConnection.py +++ b/Gui/GUIutils/DBConnection.py @@ -1,26 +1,24 @@ """ - DBConnection.py - brief Setting up connection to database - author Kai Wei - version 0.1 - date 30/09/20 - Support: email to wei.856@osu.edu +DBConnection.py +brief Setting up connection to database +author Kai Wei +version 0.1 +date 30/09/20 +Support: email to wei.856@osu.edu """ import mysql.connector -from mysql.connector import Error import subprocess import os from itertools import compress -from subprocess import Popen, PIPE from PyQt5.QtWidgets import QMessageBox -#from Gui.GUIutils.settings import * + +# from Gui.GUIutils.settings import * from Gui.GUIutils.guiUtils import ( isActive, formatter, ) -from Gui.python.logging_config import logger from InnerTrackerTests.TestSequences import Test_to_Ph2ACF_Map DB_TestResult_Schema = [ @@ -30,8 +28,6 @@ # mySQL databse server as test, may need to extend to other DB format - - def QtStartConnection(TryUsername, TryPassword, TryHostAddress, TryDatabase): # For test, no connection to DB is made and output will not be registered # if TryHostAddress == "0.0.0.0": @@ -50,7 +46,7 @@ def QtStartConnection(TryUsername, TryPassword, TryHostAddress, TryDatabase): host=str(TryHostAddress), database=str(TryDatabase), ssl_disabled=True, - connection_timeout = 5000, + connection_timeout=5000, ) except (ValueError, RuntimeError, TypeError, NameError, mysql.connector.Error): msg = QMessageBox() @@ -103,13 +99,13 @@ def getAllTests(dbconnection): localList = list(Test_to_Ph2ACF_Map.keys()) remoteList = [remoteList[i][0] for i in range(len(remoteList))] for test in remoteList: - if not test in localList: + if test not in localList: localList.append(test) return sorted(set(localList), key=localList.index) def retrieveAllTests(dbconnection): - if dbconnection.is_connected() == False: + if not dbconnection.is_connected(): return cur = dbconnection.cursor() cur.execute("SELECT * FROM calibrationlist") @@ -144,9 +140,7 @@ def retrieveModuleLastTest(dbconnection, module_id): from results_test T WHERE Module_ID = {0} group by Module_ID ) LATEST ON T.Module_ID = LATEST.Module_ID AND T.ExecutionTime = LATEST.MaxDate - """.format( - str(module_id) - ) + """.format(str(module_id)) cur = dbconnection.cursor() cur.execute(sql_query) return cur.fetchall() @@ -155,9 +149,7 @@ def retrieveModuleLastTest(dbconnection, module_id): def insertTestResult(dbconnection, record): sql_query = """ INSERT INTO results_test ({},{},{},{},{},{}) VALUES ({},{},{},{},{},{}) - """.format( - *DB_TestResult_Schema, *record - ) + """.format(*DB_TestResult_Schema, *record) cur = dbconnection.cursor() cur.execute(sql_query) dbconnection.commit() @@ -215,7 +207,7 @@ def getLocalTests(module_id, columns=[]): def getLocalRemoteTests(dbconnection, module_id=None, columns=[]): if isActive(dbconnection): - if module_id == None: + if module_id is None: remoteTests = retrieveGenericTable( dbconnection, "module_tests", columns=columns ) # changed table name @@ -232,7 +224,7 @@ def getLocalRemoteTests(dbconnection, module_id=None, columns=[]): # localTests = [] try: timeIndex = columns.index("date") - except: + except ValueError: timeIndex = -1 if remoteTests != [] and timeIndex != -1: @@ -323,7 +315,7 @@ def retrieveWithConstraint(dbconnection, table, *args, **kwargs): values = [] columnList = [] for key, value in kwargs.items(): - if key == "columns" and type(value) == type(columnList): + if key == "columns" and type(value) is type(columnList): columnList = value else: values.append(value) @@ -355,7 +347,7 @@ def retrieveWithConstraintSyntax(dbconnection, table, syntax, **kwargs): try: columnList = [] for key, value in kwargs.items(): - if key == "columns" and type(value) == type(columnList): + if key == "columns" and type(value) is type(columnList): columnList = value if len(columnList) > 0: sql_query = ( @@ -383,7 +375,7 @@ def retrieveGenericTable(dbconnection, table, **kwargs): try: columnList = [] for key, value in kwargs.items(): - if key == "columns" and type(value) == type(columnList): + if key == "columns" and type(value) is type(columnList): columnList = value if len(columnList) > 0: sql_query = ( @@ -501,7 +493,7 @@ def updateGenericTable(dbconnection, table, column, data, **kwargs): def getByColumnName(column_name, header, databody): try: index = header.index(column_name) - except: + except ValueError: print("column_name not found") output = list(map(lambda x: databody[x][index], range(0, len(databody)))) return output @@ -512,77 +504,83 @@ def getByColumnName(column_name, header, databody): ########################################################################## - - - ########################################################################## ## Functions for getting trim value (Begin) ########################################################################## -class GetTrimClass(): - def __init__(self): - self.connection = [] - def get_connection(self): - return self.connection - def GetTrim(self,serialNumber,debug = False): - connection = self.connection - if connection == "Offline" or connection == []: - print("DB is offline") - return [],[] - connection.connect() - cursor = connection.cursor() - cursor.execute(f"select component.id from component where component.serial_number='{serialNumber}';") - results = cursor.fetchall() - #handle the error of can't find the data - if results == []: - return [],[] - if debug == True: - print("raw ID:"+str(result))# it should look like [(778,)] - parenetNum = results[0][0] - - cursor.execute(f"select component.description from component where component.serial_number='{serialNumber}';") - results = cursor.fetchall() #[('TFPX CROC 1x2 HPK sensor module',)] - if debug == True: - print("raw description"+str(results)) - - if "sensor" in str(results[0][0]): - cursor.execute(f"select component.id from component where component.parent='{parenetNum}';") - chipSensorResult=cursor.fetchall() - secondParent=chipSensorResult[0][0] - if debug == True: - print("it is sensor module") - print("secondParent" + str(secondParent)) - parenetNum = secondParent - - - #get VDDA value - VDDAList = [] - cursor.execute(f"SELECT component.serial_number,component.parent,measurement.name,type,component.site,ival from component,measurements,measurement where component.parent = {parenetNum} and measurements.name=measurement.name and component.id=measurement.part_id and measurement.name='TRIM_VDDA';") - results = cursor.fetchall() - for result in results: - VDDA = result[-1] - siteNum = result[-2] - VDDAList.append([siteNum,VDDA]) - sorted_VDDAlist = sorted(VDDAList, key=lambda x: x[0]) - if debug == True: - print("sorted_VDDAlist:"+str(sorted_VDDAlist)) - - - - VDDDList = [] - cursor.execute(f"SELECT component.serial_number,component.parent,measurement.name,type,component.site,ival from component,measurements,measurement where component.parent = {parenetNum} and measurements.name=measurement.name and component.id=measurement.part_id and measurement.name='TRIM_VDDD';") - results = cursor.fetchall() - for result in results: - VDDD = result[-1] - siteNum = result[-2] - VDDDList.append([siteNum,VDDD]) - - sorted_VDDDlist = sorted(VDDDList, key=lambda x: x[0]) #make sure the we can get VDDD value base on the order of rising chip no - if debug == True: - print("sorted_VDDDlist:" + str(sorted_VDDDlist)) - connection.close() - return sorted_VDDAlist,sorted_VDDDlist +class GetTrimClass: + def __init__(self): + self.connection = [] + + def get_connection(self): + return self.connection + + def GetTrim(self, serialNumber, debug=False): + connection = self.connection + if connection == "Offline" or connection == []: + print("DB is offline") + return [], [] + connection.connect() + cursor = connection.cursor() + cursor.execute( + f"select component.id from component where component.serial_number='{serialNumber}';" + ) + results = cursor.fetchall() + # handle the error of can't find the data + if results == []: + return [], [] + parenetNum = results[0][0] + + cursor.execute( + f"select component.description from component where component.serial_number='{serialNumber}';" + ) + results = cursor.fetchall() # [('TFPX CROC 1x2 HPK sensor module',)] + if debug: + print("raw description" + str(results)) + + if "sensor" in str(results[0][0]): + cursor.execute( + f"select component.id from component where component.parent='{parenetNum}';" + ) + chipSensorResult = cursor.fetchall() + secondParent = chipSensorResult[0][0] + if debug: + print("it is sensor module") + print("secondParent" + str(secondParent)) + parenetNum = secondParent + + # get VDDA value + VDDAList = [] + cursor.execute( + f"SELECT component.serial_number,component.parent,measurement.name,type,component.site,ival from component,measurements,measurement where component.parent = {parenetNum} and measurements.name=measurement.name and component.id=measurement.part_id and measurement.name='TRIM_VDDA';" + ) + results = cursor.fetchall() + for result in results: + VDDA = result[-1] + siteNum = result[-2] + VDDAList.append([siteNum, VDDA]) + sorted_VDDAlist = sorted(VDDAList, key=lambda x: x[0]) + if debug: + print("sorted_VDDAlist:" + str(sorted_VDDAlist)) + + VDDDList = [] + cursor.execute( + f"SELECT component.serial_number,component.parent,measurement.name,type,component.site,ival from component,measurements,measurement where component.parent = {parenetNum} and measurements.name=measurement.name and component.id=measurement.part_id and measurement.name='TRIM_VDDD';" + ) + results = cursor.fetchall() + for result in results: + VDDD = result[-1] + siteNum = result[-2] + VDDDList.append([siteNum, VDDD]) + + sorted_VDDDlist = sorted( + VDDDList, key=lambda x: x[0] + ) # make sure the we can get VDDD value base on the order of rising chip no + if debug: + print("sorted_VDDDlist:" + str(sorted_VDDDlist)) + connection.close() + return sorted_VDDAlist, sorted_VDDDlist + + ########################################################################## ## Functions for getting trim value (END) ########################################################################## - - diff --git a/Gui/GUIutils/FirmwareUtil.py b/Gui/GUIutils/FirmwareUtil.py index 49f69e1f..277c3dd7 100644 --- a/Gui/GUIutils/FirmwareUtil.py +++ b/Gui/GUIutils/FirmwareUtil.py @@ -1,14 +1,14 @@ """ - FirmwareUtil.py - brief utility functions for firmware - author Kai Wei - version 0.1 - date 03/11/20 - Support: email to wei.856@osu.edu +FirmwareUtil.py +brief utility functions for firmware +author Kai Wei +version 0.1 +date 03/11/20 +Support: email to wei.856@osu.edu """ + import subprocess from datetime import datetime -from Gui.python.logging_config import logger def firmwarePingCheck(firmware, fileName): @@ -59,8 +59,6 @@ def fwStatusParser(firmware, fileName, **kwargs): verboseInfo["FPGA configuration"] = "Unknown" return "FPGA configuration failed", "color:red", verboseInfo - ## Dummy test - test3ReturnCode = fpgaConfigCheck(firmware, fileName) if fpgaReturnCode == 1: verboseInfo["Fw test3"] = "Failed" return "Fw test3 failed", "color:red", verboseInfo @@ -70,7 +68,6 @@ def fwStatusParser(firmware, fileName, **kwargs): verboseInfo["Fw test3"] = "Unknown" return "Fw test3 failed", "color:red", verboseInfo - test4ReturnCode = fpgaConfigCheck(firmware, fileName) if fpgaReturnCode == 1: verboseInfo["Fw test4"] = "Failed" return "Fw test4 failed", "color:red", verboseInfo @@ -80,7 +77,6 @@ def fwStatusParser(firmware, fileName, **kwargs): verboseInfo["Fw test4"] = "Unknown" return "Fw test4 failed", "color:red", verboseInfo - test5ReturnCode = fpgaConfigCheck(firmware, fileName) if fpgaReturnCode == 1: verboseInfo["Fw test5"] = "Failed" return "Fw test5 failed", "color:red", verboseInfo diff --git a/Gui/GUIutils/GPIBInterface.py b/Gui/GUIutils/GPIBInterface.py deleted file mode 100644 index 383409e3..00000000 --- a/Gui/GUIutils/GPIBInterface.py +++ /dev/null @@ -1,474 +0,0 @@ -import pyvisa as visa -import importlib -import subprocess -import logging -import os -import time - - -#from Gui.GUIutils.settings import * -#from Configuration.XMLUtil import * -#from Gui.python.TCP_Interface import * -from Gui.siteSettings import ( - ModuleVoltageMapSLDO, - ModuleVoltageMap, - ModuleCurrentMap, - GPIB_DebugMode -) -from keysightE3633A import KeysightE3633A -from keithley2410 import Keithley2410 -from Gui.python.logging_config import logger - -if GPIB_DebugMode: - visa.log_to_screen() - - -class PowerSupply: - def __init__( - self, - model="Keithley", - boardnumber=0, - primaryaddress=24, - powertype="HV", - serverIndex=0, - ): - self.Model = model - self.Status = "OFF" - self.deviceMap = {} - self.Instrument = None - self.PowerType = powertype - self.PoweringMode = None - self.ModuleType = None - self.CompCurrent = 0.0 - self.XMLConfig = None - self.Port = None - self.DeviceNode = None - self.Answer = None - self.maxTries = 10 - self.ServerIndex = serverIndex - self.setResourceManager() - - def setPowerType(self, powertype): - if powertype != "HV" and powertype != "LV": - logger.error("Power Type: {} not supported".format(powertype)) - else: - self.PowerType = powertype - - def isHV(self): - return self.PowerType == "HV" - - def isLV(self): - return self.PowerType == "LV" - - def setPowerModel(self, model): - self.Model = model - - def setPoweringMode(self, powermode="Direct"): - self.PoweringMode = powermode - - def setCompCurrent(self, compcurrent=1.05): - self.CompCurrent = compcurrent - - def setModuleType(self, moduletype=None): - self.ModuleType = moduletype - - def setResourceManager(self): - os.environ["PYVISA_LIBRARY"] = "@py" - self.ResourcesManager = visa.ResourceManager("@py") - - def listResources(self): - try: - self.ResourcesList = self.ResourcesManager.list_resources() - self.getDeviceName() - return list(self.deviceMap.keys()) - except Exception as err: - logger.error("Failed to list all resources: {}".format(err)) - self.ResourcesList = () - return self.ResourcesList - - def setInstrument(self, resourceName): - try: - print(resourceName) - self.setResourceManager() - print(self.deviceMap.keys()) - - if "USBLV" in resourceName: - self.Instrument = KeysightE3633A( - resourceName, reset_on_init=False, off_on_close=True - ) - elif "USBHV" in resourceName: - self.Instrument = Keithley2410( - resourceName, reset_on_init=False, ramp_down_on_close=True - ) - - if resourceName in self.deviceMap.keys(): - self.Port = ( - self.deviceMap[resourceName].lstrip("ASRL").rstrip("::INSTR") - ) - - self.Instrument.__enter__() - - except Exception as err: - logger.error("Failed to open resource {0}: {1}".format(resourceName, err)) - - def hwUpdate(self, pHead, pAnswer): - if pAnswer is not None: - self.Answer = pAnswer - logger.info( - "TCP: PowerSupply {} - {}:{}".format(self.PowerType, pHead, pAnswer) - ) - else: - self.Answer = None - - def getDeviceName(self): - self.deviceMap = {} - for device in self.ResourcesList: - try: - pipe = subprocess.Popen( - [ - "udevadm", - "info", - " --query", - "all", - "--name", - device.lstrip("ASRL").rstrip("::INSTR"), - "--attribute-walk", - ], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - ) - raw_output = pipe.communicate()[0] - vendor_list = [ - info - for info in raw_output.splitlines() - if b"ATTRS{idVendor}" in info or b"ATTRS{vendor}" in info - ] - product_list = [ - info - for info in raw_output.splitlines() - if b"ATTRS{idProduct}" in info or b"ATTRS{product}" in info - ] - idvendor = ( - vendor_list[0] - .decode("UTF-8") - .split("==")[1] - .lstrip('"') - .rstrip('"') - .replace("0x", "") - ) - idproduct = ( - product_list[0] - .decode("UTF-8") - .split("==")[1] - .lstrip('"') - .rstrip('"') - .replace("0x", "") - ) - deviceId = "{}:{}".format(idvendor, idproduct) - pipeUSB = subprocess.Popen( - ["lsusb", "-d", deviceId], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - ) - usbInfo = pipeUSB.communicate()[0] - deviceName = ( - usbInfo.decode("UTF-8").split(deviceId)[-1].lstrip(" ").rstrip("\n") - ) - if deviceName == None: - logger.warning("No device name found for {}:".format(device)) - self.deviceMap[device] = device - else: - self.deviceMap[device] = deviceName - except Exception as err: - logger.error("Error found:{}".format(err)) - self.deviceMap[device] = device - - def getInfo(self): - try: - info = self.Instrument.query("IDENTIFIER") - return info - except Exception as err: - logging.error("Failed to get instrument information:{}".format(err)) - return "No valid device" - - def startRemoteCtl(self): - pass - - def InitialDevice(self): - if self.PowerType == "LV": - pass - if self.PowerType == "HV": - self.Instrument.reset() - self.Instrument.set("SOURCE", "VOLT") - self.Instrument.set("VOLTAGE_MODE", "FIX") - self.Instrument.set("SENSE_CURRENT_RANGE", 10e-6) - - def TurnOn(self): - try: - self.InitialDevice() - Voltage = 0.0 - Current = 0.0 - - if self.PowerType == "LV" and self.PoweringMode == "SLDO": - Voltage = ModuleVoltageMapSLDO[self.ModuleType] - Current = ModuleCurrentMap[self.ModuleType] - elif self.PowerType == "LV" and self.PoweringMode == "Direct": - Voltage = ModuleVoltageMap[self.ModuleType] - Current = ModuleCurrentMap[self.ModuleType] - - if self.PowerType == "LV": - self.Instrument.set("VOLTAGE1", Voltage) - self.Instrument.set("CURRENT1", Current) - self.Instrument.on(1) - - if self.PowerType == "HV": - try: - HVstatus = self.Instrument.status() - print(HVstatus) - if "1" in str(HVstatus): - print("found HV status {0}".format(HVstatus)) # debug - self.Instrument.off() - self.Instrument.set("VOLTAGE", 0) - self.Instrument.on() - except Exception as err: - logging.error("Failed to turn on the sourceMeter:{}".format(err)) - - except Exception as err: - logging.error("Failed to turn on the sourceMeter:{}".format(err)) - - # TurnOnLV is only used for SLDO Scan - - def TurnOnLV(self): - try: - self.Instrument.on(1) - except Exception as err: - logging.error("Failed to turn on the sourceMeter:{}".format(err)) - - # This will also disconnect the power supplies, so if you turn off the power supply but want to turn on the PS with the same object, it will break - def TurnOff(self): - try: - if self.PowerType == "LV": - self.Instrument.off(1) - elif self.PowerType == "HV": - self.Instrument.off() - - except Exception as err: - logging.error("Failed to turn off the sourceMeter:{}".format(err)) - - def ReadOutputStatus(self): - try: - HVoutputstatus = self.Instrument.status() - return str(HVoutputstatus) - except Exception as err: - return None - - def ReadVoltage(self): - try: - if self.PowerType == "LV": - voltage = self.Instrument.query("VOLTAGE1") - elif self.PowerType == "HV": - voltage = self.Instrument.query("VOLTAGE") - return voltage - except Exception as err: - return None - - def SetVoltage(self, voltage=0.0): - if self.PowerType == "HV": - return - - try: - self.Instrument.set("VOLTAGE1", voltage) - except Exception as err: - logging.err( - "Failed to set {} voltage to {}".format(self.PowerType, voltage) - ) - - def SetRange(self, voltRange): - if not self.isLV(): - logging.info("Try to setVoltage for non-LV power supply") - return - - try: - self.Instrument.set("OVP1", voltRange) - except Exception as err: - logging.error("Failed to set range for the sourceMeter:{}".format(err)) - return None - - def SetCurrent(self, current=0.0): - if self.PowerType == "HV": - return - try: - self.Instrument.set("CURRENT1", current) - except Exception as err: - logging.error( - "Failed to set {} current to {}".format(self.PowerType, current) - ) - - def ReadCurrent(self): - try: - if self.PowerType == "LV": - current = self.Instrument.query("CURRENT1") - return current - elif self.PowerType == "HV": - # self.Instrument.reset() - self.Instrument.set("SOURCE", "VOLT") - self.Instrument.set("VOLTAGE_MODE", "FIX") - # self.Instrument.set("SENSE_FUNCTION", 'CURR') - self.Instrument.set("OUTPUT", "ON") - - # This returns a comma seperated string of 5 numbers, looking at the keithley, the second entry is the actual current - current = float(self.Instrument.query("READ").split(",")[1]) - - return current - except Exception as err: - print(err) - pass - - def TurnOnHV(self): - print("TurnOnHV() starts") # debug - if not self.isHV(): - logging.info("Try to turn on non-HV as high voltage") - return - - try: - HVstatus = self.Instrument.status() - print(HVstatus) - if "1" in str(HVstatus): - print("found HV status {0}".format(HVstatus)) - self.Instrument.off() - self.Instrument.set("VOLTAGE", 0) - self.Instrument.on() - except Exception as err: - logging.error("Failed to turn on the sourceMeter:{}".format(err)) - return None - - def TurnOffHV(self): - print("inside TurnOFFHV") # debug - if not self.isHV(): - logging.info("Try to turn off non-HV as high voltage") - return - try: - HVstatus = self.ReadOutputStatus() - if "0" in HVstatus: - return - currentVoltage = float(self.ReadVoltage()) # does issue is here? - print("current voltage in TurnoffHV() is: " + str(currentVoltage)) # debug - stepLength = 3 - if 0 < currentVoltage: - stepLength = -3 - - for voltage in range(int(currentVoltage), 0, stepLength): - self.SetHVVoltage(voltage) - time.sleep(0.3) - self.SetHVVoltage(0) - self.TurnOff() - except Exception as err: - logging.error("Failed to turn off the sourceMeter:{}".format(err)) - return None - - def SetHVRange(self, voltRange): - if not self.isHV(): - logging.info("Try to setVoltage for non-HV power supply") - return - try: - self.Instrument.set("VOLTAGE_RANGE", voltRange) - except Exception as err: - logging.error("Failed to set range for the sourceMeter:{}".format(err)) - return None - - def SetHVVoltage(self, voltage): - if not self.isHV(): - logging.info("Try to setVoltage for non-HV power supply") - return - - try: - print("Using python interface") - print("set Voltage :" + str(voltage)) - self.Instrument.set("VOLTAGE", voltage) - except Exception as err: - logging.error("Failed to set HV target the sourceMeter:{}".format(err)) - return None - - def SetHVComplianceLimit(self, compliance): - if not self.isHV(): - logging.info("Try to setVoltage for non-HV power supply") - return - - try: - self.Instrument.set("COMPLIANCE_CURRENT", compliance) - except Exception as err: - logging.error( - "Failed to set compliance limit for the sourceMeter:{}".format(err) - ) - return None - - def RampingUp(self, hvTarget=0.0, stepLength=0.0): - if self.isHV(): - try: - print("RampingUp") # debug - HVstatus = self.ReadOutputStatus() - if "1" in HVstatus: - self.TurnOffHV() - print("doing turnOffHV in rampingUP") # debug - # self.Instrument.set('SENSE_CURRENT_RANGE', 10e-6) - # self.Instrument.set('VOLTAGE_MODE', 'FIX') - # self.SetHVComplianceLimit(default_hv_compliance_current) - self.SetHVVoltage(0) - self.TurnOn() - - currentVoltage = float(self.ReadVoltage()) - if hvTarget < currentVoltage: - stepLength = -abs(stepLength) - - for voltage in range( - int(currentVoltage), int(hvTarget), int(stepLength) - ): - self.SetHVVoltage(voltage) - print("doing SetHVVoltage") # debug - time.sleep(0.3) - self.SetHVVoltage(hvTarget) - - except Exception as err: - logging.error( - "Failed to ramp the voltage to {0}:{1}".format(hvTarget, err) - ) - else: - logging.info("Not a HV power supply, abort") - - def customized(self, cmd): - if "Keith" in self.Model: - cmd = "K2410:" + cmd - - def Status(self): - if not "KeySight" in self.Model: - return -1 - - try: - reply = self.Instrument.status() - return 1 - except Exception as err: - logging.error("Failed to get the status code:{}".format(err)) - return None - - def Reset(self): - if not "KeySight" in self.Model: - return -1 - try: - reply = self.Instrument.reset() - return 1 - except Exception as err: - logging.error("Failed to get the status code:{}".format(err)) - return None - - -if __name__ == "__main__": - # This allows icicle to use the right pyvisa library without changing the code. - LVpowersupply = PowerSupply(powertype="LV") - LVpowersupply.setPoweringMode() - - # HVpowersupply.setPowerModel("ahhh") - LVpowersupply.setInstrument("ASRL/dev/ttyUSBLV::INSTR") - LVpowersupply.setCompCurrent() - LVpowersupply.TurnOn() - time.sleep(10) - LVpowersupply.TurnOff() diff --git a/Gui/GUIutils/guiUtils.py b/Gui/GUIutils/guiUtils.py index 0377fc35..5c19e97d 100644 --- a/Gui/GUIutils/guiUtils.py +++ b/Gui/GUIutils/guiUtils.py @@ -1,10 +1,10 @@ """ - gui.py - brief Interface classes for pixel grading gui - author Kai Wei - version 1.0 - date 04/27/21 - Support: email to wei.856@osu.edu +gui.py +brief Interface classes for pixel grading gui +author Kai Wei +version 1.0 +date 04/27/21 +Support: email to wei.856@osu.edu """ import sys @@ -16,7 +16,8 @@ updatedGlobalValue, updatedXMLValues, ) -#from Gui.GUIutils.DBConnection import * + +# from Gui.GUIutils.DBConnection import * from Configuration.XMLUtil import ( HWDescription, BeBoardModule, @@ -25,7 +26,7 @@ FE, MonitoringModule, LoadXML, - GenerateHWDescriptionXML + GenerateHWDescriptionXML, ) from InnerTrackerTests.GlobalSettings import ( globalSettings_DictA, @@ -41,7 +42,6 @@ ) from InnerTrackerTests.MonitoringSettings import ( MonitoringListA, - MonitoringListB, Monitoring_DictB, ) from InnerTrackerTests.RegisterSettings import RegisterSettings @@ -70,13 +70,15 @@ def iter_except(function, exception): try: while True: yield function() - except: + except Exception as e: + logger.error(e) return ########################################################################## ########################################################################## + def ConfigureTest(Test, Module_ID, Output_Dir, Input_Dir): if not Output_Dir: test_dir = os.environ.get("DATA_dir") + "/Test_" + str(Test) @@ -143,7 +145,11 @@ def isActive(dbconnection): def SetupXMLConfig(Input_Dir, Output_Dir, BeBoardName=""): try: - os.system("cp {0}/CMSIT_{2}.xml {1}/CMSIT_2.xml".format(Input_Dir, Output_Dir, BeBoardName)) + os.system( + "cp {0}/CMSIT_{2}.xml {1}/CMSIT_2.xml".format( + Input_Dir, Output_Dir, BeBoardName + ) + ) except OSError: print("Can not copy the XML files to {0}".format(Output_Dir)) try: @@ -228,7 +234,6 @@ def SetupXMLConfigfromFile(InputFile, Output_Dir, BeBoardName=""): if len(updatedXMLValues[chipKeyName]) > 0: for key in updatedXMLValues[chipKeyName].keys(): Node.set(key, str(updatedXMLValues[chipKeyName][key])) - except Exception as error: print("Failed to set up the XML file, {}".format(error)) @@ -247,7 +252,7 @@ def SetupXMLConfigfromFile(InputFile, Output_Dir, BeBoardName=""): updatedGlobalValue[1]["TargetThr"] ) ) - except Exception as error: + except Exception: print( "Failed to update the TargetThr value, {0}".format( updatedGlobalValue[1]["TargetThr"] @@ -352,8 +357,8 @@ def UpdateXMLValue(pFilename, pAttribute, pValue): for Node in root.findall(".//Setting"): if Node.attrib["name"] == pAttribute: Node.text = pValue - #The next line should be done using logger, not print. - #print("{0} has been set to {1}.".format(pAttribute, pValue)) + # The next line should be done using logger, not print. + # print("{0} has been set to {1}.".format(pAttribute, pValue)) tree.write(pFilename) @@ -361,46 +366,69 @@ def CheckXMLValue(pFilename, pAttribute): root, tree = LoadXML(pFilename) for Node in root.findall(".//Setting"): if Node.attrib["name"] == pAttribute: - #The next line should be done using logger, not print. + # The next line should be done using logger, not print. print("{0} is set to {1}.".format(pAttribute, Node.text)) ########################################################################## ########################################################################## + def GenerateXMLConfig(BeBoard, testName, outputDir, **arg): - outputFile = f'{outputDir}/CMSIT_{BeBoard.getBoardName()}_{testName}.xml' + outputFile = f"{outputDir}/CMSIT_{BeBoard.getBoardName()}_{testName}.xml" print(outputFile) - + boardtype = "RD53A" - RegisterSettingsList = RegisterSettings #TODO: Investigate whether this actually matters (ie deep vs shallow copy) - revPolarity = False #Flag to determine whether or not to reverse the Aurora lane polarity - + RegisterSettingsList = RegisterSettings # TODO: Investigate whether this actually matters (ie deep vs shallow copy) + revPolarity = ( + False # Flag to determine whether or not to reverse the Aurora lane polarity + ) + # Get Hardware discription and a list of the modules HWDescription0 = HWDescription() - + BeBoardModule0 = BeBoardModule() - #Set up Optical Groups + # Set up Optical Groups for og in BeBoard.getAllOpticalGroups().values(): OpticalGroupModule0 = OGModule() OpticalGroupModule0.SetOpticalGrp(og.getOpticalGroupID(), og.getFMCID()) - + # Set up each module within the optical group for module in og.getAllModules().values(): HyBridModule0 = HyBridModule() HyBridModule0.SetHyBridModule(module.getFMCPort(), "1") HyBridModule0.SetHyBridName(module.getModuleName()) - + moduleType = module.getModuleType() - RxPolarities = "1" if "CROC" in moduleType and "Quad" in moduleType and "TFPX" in moduleType else "0" if "CROC" in moduleType else None + RxPolarities = ( + "1" + if "CROC" in moduleType + and "Quad" in moduleType + and "TFPX" in moduleType + else "0" + if "CROC" in moduleType + else None + ) revPolarity = bool(int(RxPolarities)) - FESettings_Dict = FESettings_DictB if "CROC" in moduleType else FESettings_DictA - globalSettings_Dict = globalSettings_DictB if "CROC" in moduleType else globalSettings_DictA - HWSettings_Dict = HWSettings_DictB if "CROC" in moduleType else HWSettings_DictA - FELaneConfig_Dict = FELaneConfig_DictB[module.getModuleType().split(" ")[0]] if "CROC" in moduleType else None - boardtype = "RD53B"+module.getModuleVersion() if "CROC" in moduleType else "RD53A" - + FESettings_Dict = ( + FESettings_DictB if "CROC" in moduleType else FESettings_DictA + ) + globalSettings_Dict = ( + globalSettings_DictB if "CROC" in moduleType else globalSettings_DictA + ) + HWSettings_Dict = ( + HWSettings_DictB if "CROC" in moduleType else HWSettings_DictA + ) + FELaneConfig_Dict = ( + FELaneConfig_DictB[module.getModuleType().split(" ")[0]] + if "CROC" in moduleType + else None + ) + boardtype = ( + "RD53B" + module.getModuleVersion() if "CROC" in moduleType else "RD53A" + ) + # Sets up all the chips on the module and adds them to the hybrid module to then be stored in the class for chip in module.getChips().values(): print("chip {0} status is {1}".format(chip.getID(), chip.getStatus())) @@ -414,29 +442,31 @@ def GenerateXMLConfig(BeBoard, testName, outputDir, **arg): module.getModuleName(), module.getFMCPort(), chip.getID() ), ) - + FEChip.ConfigureFE(FESettings_Dict[testName]) - FEChip.ConfigureLaneConfig(FELaneConfig_Dict[testName][int(chip.getLane())]) + FEChip.ConfigureLaneConfig( + FELaneConfig_Dict[testName][int(chip.getLane())] + ) FEChip.VDDAtrim = chip.getVDDA() FEChip.VDDDtrim = chip.getVDDD() FEChip.EfuseID = chip.getEfuseID() HyBridModule0.AddFE(FEChip) HyBridModule0.ConfigureGlobal(globalSettings_Dict[testName]) OpticalGroupModule0.AddHyBrid(HyBridModule0) - + BeBoardModule0.AddOGModule(OpticalGroupModule0) - - if revPolarity == True: - RegisterSettingsList['user.ctrl_regs.gtx_rx_polarity.fmc_l12'] = '0b1101' - RegisterSettingsList['user.ctrl_regs.gtx_rx_polarity.fmc_l8'] = '0x22' - + + if revPolarity: + RegisterSettingsList["user.ctrl_regs.gtx_rx_polarity.fmc_l12"] = "0b1101" + RegisterSettingsList["user.ctrl_regs.gtx_rx_polarity.fmc_l8"] = "0x22" + BeBoardModule0.SetURI(BeBoard.getIPAddress()) BeBoardModule0.SetBeBoard(BeBoard.getBoardID(), "RD53") - + BeBoardModule0.SetRegisterValue(RegisterSettingsList) HWDescription0.AddBeBoard(BeBoardModule0) - - HWDescription0.AddSettings(HWSettings_Dict[testName]) + + HWDescription0.AddSettings(HWSettings_Dict[testName]) MonitoringModule0 = MonitoringModule(boardtype) if "RD53A" in boardtype: MonitoringModule0.SetMonitoringList(MonitoringListA) @@ -477,7 +507,7 @@ def getGrade(self, file): def GetTBrowser(DQMFile): - process = Popen( + Popen( "{0}/Gui/GUIUtils/runBrowser.sh {1} {2}".format( os.environ.get("GUI_dir"), os.environ.get("GUI_dir") + "/Gui/GUIUtils", @@ -541,7 +571,7 @@ def formatter(DirName, columns, **kwargs): ReturnList.append(dirName.split("_")[-3]) ReturnDict.update({"test_name": dirName.split("_")[-3]}) if column == "test_grade": - if Module_ID != None: + if Module_ID is not None: gradeFileName = "{}/Grade_Module{}.txt".format(DirName, Module_ID) if os.path.isfile(gradeFileName): gradeFile = open(gradeFileName, "r") @@ -587,7 +617,7 @@ def formatter(DirName, columns, **kwargs): ReturnList[indexGrade] = Grade else: ReturnList[indexGrade] = -1 - except Exception as err: + except Exception: print("recheck failed") else: pass diff --git a/Gui/GUIutils/settingimport.py b/Gui/GUIutils/settingimport.py index 48fb330b..2d7e2cd1 100644 --- a/Gui/GUIutils/settingimport.py +++ b/Gui/GUIutils/settingimport.py @@ -2,14 +2,16 @@ import csv import logging -logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') +logging.basicConfig( + level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s" +) logger = logging.getLogger(__name__) class csvImport: def __init__(self): - self.settingsTemplatePath = 'Gui/siteSettings_template.py' - self.updatedsiteSettingsPath = 'Gui/siteSettings.py' + self.settingsTemplatePath = "Gui/siteSettings_template.py" + self.updatedsiteSettingsPath = "Gui/siteSettings.py" self.updated_settingslist = {} self.parser = variableParser() self.defaultSettings = self.parser.parse(self.settingsTemplatePath) @@ -20,14 +22,16 @@ def import_settings(self, csvpath): self._update_settings(csvdata) def _read_csv(self, readpath): - updated_settings = self.defaultSettings.copy() # Create a copy to preserve defaults - + updated_settings = ( + self.defaultSettings.copy() + ) # Create a copy to preserve defaults + noDefaultList = [] unUsedData = [] MissingDatalist = [] - + try: - with open(readpath, 'r', newline='') as csv_file: + with open(readpath, "r", newline="") as csv_file: reader = csv.reader(csv_file) for row in reader: @@ -35,41 +39,48 @@ def _read_csv(self, readpath): header = row[0] data = row[1] - if header == '': + if header == "": unUsedData.append(data) elif header not in self.defaultSettings: noDefaultList.append(header) - if data == '' or data == 'None': + if data == "" or data == "None": updated_settings[header] = None else: updated_settings[header] = data else: - if data == '' or data == 'None': + if data == "" or data == "None": updated_settings[header] = None else: updated_settings[header] = data else: MissingDatalist.append(row[0]) - + logger.info(f"CSV file '{readpath}' read successfully.") - + if len(noDefaultList) != 0: - logger.info(f'The "siteSettings.py" does not have default values set for variables',noDefaultList) + logger.info( + 'The "siteSettings.py" does not have default values set for variables', + noDefaultList, + ) if len(unUsedData) != 0: - logger.info(f'The following data {unUsedData} were not used because there was no header in the CSV file.') + logger.info( + f"The following data {unUsedData} were not used because there was no header in the CSV file." + ) if len(MissingDatalist) != 0: - logger.info(f'The following list {MissingDatalist} were skipped because there was no value associated or csv file had more than two columns.') - + logger.info( + f"The following list {MissingDatalist} were skipped because there was no value associated or csv file had more than two columns." + ) + return updated_settings except Exception as e: logger.error(f"Error reading CSV file: {str(e)}") - def _update_settings(self,updated_settings_dict): + def _update_settings(self, updated_settings_dict): try: # Write the updated settings (or create a new file) as siteSettings.py - with open(self.updatedsiteSettingsPath, 'w') as settings_file: + with open(self.updatedsiteSettingsPath, "w") as settings_file: for key, value in updated_settings_dict.items(): settings_file.write(f"{key} = {repr(value)}\n") @@ -81,13 +92,13 @@ def _update_settings(self,updated_settings_dict): def create_csv(self, writepath): try: # Open the CSV file for writing - with open(writepath, 'w', newline='') as csv_file: + with open(writepath, "w", newline="") as csv_file: writer = csv.writer(csv_file) # Write the headers in the first column and corresponding values in the second column for header, value in self.defaultSettings.items(): # Convert None to an empty string when writing to the CSV - value = '' if value is None else value + value = "" if value is None else value writer.writerow([header, value]) logger.info(f"CSV file '{writepath}' created successfully.") @@ -95,7 +106,8 @@ def create_csv(self, writepath): except Exception as e: logger.error(f"Error creating CSV file: {str(e)}") + if __name__ == "__main__": test = csvImport() - #create = test.create_csv('testcsv.csv') #this will create the csv using the existing template - test.import_settings('testcsv.csv') + # create = test.create_csv('testcsv.csv') #this will create the csv using the existing template + test.import_settings("testcsv.csv") diff --git a/Gui/GUIutils/settings.py b/Gui/GUIutils/settings.py index 3cfa3938..edbd4f77 100644 --- a/Gui/GUIutils/settings.py +++ b/Gui/GUIutils/settings.py @@ -1,9 +1,8 @@ # November 19 2021: Edited by Matt Joyce. Added information for Purdue database to DBNames and DBServerIP -import os from collections import defaultdict -#from Gui.siteSettings import * -#import InnerTrackerTests.TestSequences as TestSequences +# from Gui.siteSettings import * +# import InnerTrackerTests.TestSequences as TestSequences # List of expert users ExpertUserList = [ @@ -97,7 +96,6 @@ }, "TEPX CROC 1x2": { "Dev": "QUAD_ELE_CROC_v5-0.bit", - }, "TEPX CROC Quad": { "Dev": "QUAD_ELE_CROC_v5-0.bit", @@ -126,16 +124,17 @@ ChipMap = { "TFPX CROC 1x2": { - 'VDDD_B': '13', - 'VDDA_B': '13', - 'VDDA_A': '12', - 'VDDD_A': '12', - 'VMUX_B': '13', - 'IMUX_B': '13', - 'VMUX_A': '12', - 'IMUX_A': '12', - 'GND_A': '12'}, - } + "VDDD_B": "13", + "VDDA_B": "13", + "VDDA_A": "12", + "VDDD_A": "12", + "VMUX_B": "13", + "IMUX_B": "13", + "VMUX_A": "12", + "IMUX_A": "12", + "GND_A": "12", + }, +} BoxSize = { "SCC": 1, @@ -152,33 +151,28 @@ } optimizationTestMap = { - 'thradj':[ - 'DAC_GDAC_M_LIN', - 'DAC_GDAC_L_LIN', - 'DAC_GDAC_R_LIN', - 'Vthreshold_LIN', - ], - 'thrmin':[ - 'DAC_GDAC_M_LIN' - 'DAC_GDAC_L_LIN' - 'DAC_GDAC_R_LIN' - 'Vthreshold_LIN' + "thradj": [ + "DAC_GDAC_M_LIN", + "DAC_GDAC_L_LIN", + "DAC_GDAC_R_LIN", + "Vthreshold_LIN", ], - 'threq':[ - 'VCAL_HIGH', + "thrmin": ["DAC_GDAC_M_LINDAC_GDAC_L_LINDAC_GDAC_R_LINVthreshold_LIN"], + "threq": [ + "VCAL_HIGH", ], - 'gainopt':[ - 'DAC_KRUM_CURR_LIN', - 'KRUM_CURR_LIN', + "gainopt": [ + "DAC_KRUM_CURR_LIN", + "KRUM_CURR_LIN", ], - 'injdelay':[ + "injdelay": [ #'TriggerConfig', - 'LATENCY_CONFIG', - 'CAL_EDGE_FINE_DELAY', + "LATENCY_CONFIG", + "CAL_EDGE_FINE_DELAY", ], - 'gendacdac':[ - 'VCAL_HIGH', - 'CAL_EDGE_FINE_DELAY', + "gendacdac": [ + "VCAL_HIGH", + "CAL_EDGE_FINE_DELAY", ], } diff --git a/Gui/QtApplication.py b/Gui/QtApplication.py index 994a92ae..fe5e8f84 100644 --- a/Gui/QtApplication.py +++ b/Gui/QtApplication.py @@ -1,18 +1,11 @@ -from PyQt5.QtCore import QDateTime, Qt, QTimer -from PyQt5.QtWidgets import (QApplication, QCheckBox, QComboBox, QDateTimeEdit, - QDial, QDialog, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLineEdit, - QProgressBar, QPushButton, QRadioButton, QScrollBar, QSizePolicy, - QSlider, QSpinBox, QStyleFactory, QTableWidget, QTabWidget, QTextEdit, - QVBoxLayout, QWidget) +from PyQt5.QtWidgets import QApplication import sys -import os -import logging -from Gui.QtGUIutils.QtApplication import * +from Gui.QtGUIutils.QtApplication import QtApplication if __name__ == "__main__": - app = QApplication([]) - dimension = app.screens()[0].size() - qtApp = QtApplication(dimension) - sys.exit(app.exec_()) + app = QApplication([]) + dimension = app.screens()[0].size() + qtApp = QtApplication(dimension) + sys.exit(app.exec_()) diff --git a/Gui/QtGUIutils/LaudaApp.py b/Gui/QtGUIutils/LaudaApp.py index a058a03b..378e7390 100644 --- a/Gui/QtGUIutils/LaudaApp.py +++ b/Gui/QtGUIutils/LaudaApp.py @@ -6,9 +6,7 @@ class LaudaWidget(QWidget): - def __init__(self, dimension): - self.myLauda = Lauda(resource=site_settings.lauda_resource) super(LaudaWidget, self).__init__() @@ -50,24 +48,26 @@ def setupUi(self): self.SetTempEdit.setMinimumWidth(140) self.SetTempEdit.setEchoMode(QtWidgets.QLineEdit.Normal) self.SetTempEdit.setPlaceholderText("Set Temperature") - self.SetTempEdit.textChanged.connect(lambda : self.SetTempButton.setChecked(False)) + self.SetTempEdit.textChanged.connect( + lambda: self.SetTempButton.setChecked(False) + ) self.ChillerLayout = QtWidgets.QGridLayout(self) self.ChillerLayout.addWidget(self.StartChillerButton, 0, 0, 1, 1) - self.ChillerLayout.addWidget(self.StopChillerButton,1,0,1,1) - self.ChillerLayout.addWidget(self.SetTempButton,2,0,1,1) - self.ChillerLayout.addWidget(self.SetTempEdit,2,1,1,2) + self.ChillerLayout.addWidget(self.StopChillerButton, 1, 0, 1, 1) + self.ChillerLayout.addWidget(self.SetTempButton, 2, 0, 1, 1) + self.ChillerLayout.addWidget(self.SetTempEdit, 2, 1, 1, 2) self.setLayout(self.ChillerLayout) def resourceExists(self): - return False if self.lauda_resource == None else True + return False if self.lauda_resource is None else True def startChiller(self): self.StartChillerButton.setChecked(True) self.StopChillerButton.setChecked(False) - self.myLauda.set("START","START") + self.myLauda.set("START", "START") def stopChiller(self): self.StartChillerButton.setChecked(False) @@ -77,12 +77,13 @@ def stopChiller(self): def setTemperature(self): self.SetTempButton.setChecked(True) - + try: - self.myLauda.set("TEMPERATURE_TARGET",float(self.setTempEdit.text())) + self.myLauda.set("TEMPERATURE_TARGET", float(self.setTempEdit.text())) except ValueError: print("Temperature target must be a float.") + if __name__ == "__main__": import sys diff --git a/Gui/QtGUIutils/Loading.py b/Gui/QtGUIutils/Loading.py index bd30a6e0..16a42e9d 100644 --- a/Gui/QtGUIutils/Loading.py +++ b/Gui/QtGUIutils/Loading.py @@ -2,13 +2,15 @@ from PyQt5.QtCore import Qt, QTimer, QThread, pyqtSignal from PyQt5.QtGui import QPainter, QPen + class LoadingThread(QThread): finished_signal = pyqtSignal() - def __init__(self,function,interval,*args): + + def __init__(self, function, interval, *args): super(LoadingThread, self).__init__() self.function = function self.args = args - self.finished_signal.connect(lambda : self.timer.stop()) + self.finished_signal.connect(lambda: self.timer.stop()) self.timer = QTimer() self.timer.setInterval(interval) @@ -16,6 +18,7 @@ def run(self): self.function(*self.args) self.finished_signal.emit() + class LoadingWheel(QWidget): def __init__(self): # Accepts parent widget super().__init__() # Pass parent to QWidget @@ -37,4 +40,3 @@ def paintEvent(self, event): # Draw arc as spinner painter.drawArc(-10, -10, 20, 20, 0, 270 * 16) # 270 degrees (3/4 circle) - diff --git a/Gui/QtGUIutils/PeltierCoolingApp.py b/Gui/QtGUIutils/PeltierCoolingApp.py index 67ed9a2a..a6376c84 100644 --- a/Gui/QtGUIutils/PeltierCoolingApp.py +++ b/Gui/QtGUIutils/PeltierCoolingApp.py @@ -4,7 +4,6 @@ from Gui.python.Peltier import PeltierSignalGenerator import time import os -from Gui.python.logging_config import logger class Peltier(QWidget): @@ -92,35 +91,45 @@ def setup(self): self.pelt.createCommand( "Set Type Define Write", ["0", "0", "0", "0", "0", "0", "0", "0"] ) - )[1]: raise Exception("Could not communicate with Peltier") + )[1]: + raise Exception("Could not communicate with Peltier") # Allows set point to be set by computer software if not self.pelt.sendCommand( self.pelt.createCommand( "Control Type Write", ["0", "0", "0", "0", "0", "0", "0", "1"] ) - )[1]: raise Exception("Could not communicate with Peltier") # Temperature should be PID controlled + )[1]: + raise Exception( + "Could not communicate with Peltier" + ) # Temperature should be PID controlled if not self.pelt.sendCommand( self.pelt.createCommand( "Power On/Off Write", ["0", "0", "0", "0", "0", "0", "0", "0"] ) - )[1]: raise Exception("Could not communicate with Peltier") # Turn off power to Peltier in case it is on at the start + )[1]: + raise Exception( + "Could not communicate with Peltier" + ) # Turn off power to Peltier in case it is on at the start if not self.pelt.sendCommand( self.pelt.createCommand( "Proportional Bandwidth Write", ["0", "0", "0", "0", "0", "0", "c", "8"], ) - )[1]: raise Exception("Could not communicate with Peltier") # Set proportional bandwidth - + )[1]: + raise Exception( + "Could not communicate with Peltier" + ) # Set proportional bandwidth # Ensure the Peltier cannot heat up/change polarity to maintain setpoint if not self.pelt.sendCommand( self.pelt.createCommand( "Heat Multiplier Write", ["0", "0", "0", "0", "0", "0", "0", "0"] ) - )[1]: raise Exception("Could not communicate with Peltier") + )[1]: + raise Exception("Could not communicate with Peltier") message, _ = self.pelt.sendCommand( self.pelt.createCommand( @@ -150,7 +159,6 @@ def setup(self): except Exception as e: print("Error while attempting to setup Peltier Controller: ", e) - def enableButtons(self): self.powerButton.setEnabled(True) @@ -187,7 +195,7 @@ def powerToggle(self): ) except Exception as e: print("Could not turn off controller due to error: ", e) - + def setPolarityStatus(self, polarity): if polarity[8] == "0": self.polarityValue = "HEAT WP1+ and WP2-" @@ -306,16 +314,10 @@ def controllerMonitoring2(self): return def tempLimit(self, temp): - try: - if temp >= 35: - # self.closeEvent() #Will change this to take effect if the code runs - print("Temperature too high") - return - except: - return - - def setBandwidth(self): - signalworker = signalWorker("Proportional Bandwidth Write", message) + if temp >= 35: + self.closeEvent() # Will change this to take effect if the code runs + print("Temperature too high") + return if __name__ == "__main__": diff --git a/Gui/QtGUIutils/QtApplication.py b/Gui/QtGUIutils/QtApplication.py index 9d93c0d3..93d39e54 100644 --- a/Gui/QtGUIutils/QtApplication.py +++ b/Gui/QtGUIutils/QtApplication.py @@ -8,7 +8,6 @@ QDialog, QGridLayout, QGroupBox, - QHBoxLayout, QLabel, QLineEdit, QPushButton, @@ -47,14 +46,13 @@ from icicle.icicle.f4t_temperature_chamber import F4TTempChamber - - from Gui.python.logging_config import logger class QtApplication(QWidget): globalStop = pyqtSignal() errorMessageBoxSignal = pyqtSignal(str) + def __init__(self, dimension): super(QtApplication, self).__init__() self.mainLayout = QGridLayout() @@ -90,13 +88,12 @@ def __init__(self, dimension): logger.warning("Initialized variables for QtApplication") logger.debug("Initialized variables for QtApplication") - self.setLoginUI() self.initLog() self.createLogin() - self.errorMessageBoxSignal.connect( lambda message : - QMessageBox.information( + self.errorMessageBoxSignal.connect( + lambda message: QMessageBox.information( None, "Error", message, @@ -121,35 +118,43 @@ def setLoginUI(self): # If the Assets directory is not bound, then you can't use a custom theme if not os.path.isdir("Assets"): - logger.info("The Assets directory is not bound, cannot use custom themes," - "default theme will be used.") + logger.info( + "The Assets directory is not bound, cannot use custom themes," + "default theme will be used." + ) site_settings.use_custom_theme = False - if site_settings.use_custom_theme: + if site_settings.use_custom_theme: # Check if Assets directory exists/is bound - logger.debug("The Assets directory is bound correctly") - try: - with open(os.path.realpath(f"Assets/{site_settings.theme}"), "r") as f: - style_sheet = f.read() - - # If theme variable is not defined then use default theme - except AttributeError: - logger.info("Using default theme") - with open(os.path.realpath("Assets/ElegantDark.qss"), "r") as f: - style_sheet = f.read() - - # If there is a typo or user attempts to use theme that is not defined, set default theme - except FileNotFoundError: - logger.warning("Theme file not found, please confirm theme is in the Gui/Assets directory") - with open(os.path.realpath("Assets/ElegantDark.qss"), "r") as f: - style_sheet = f.read() - finally: - logger.debug("Setting StyleSheetPropagation") - QApplication.setAttribute(Qt.AA_UseStyleSheetPropagationInWidgetStyles) - QApplication.instance().setStyleSheet(style_sheet) + logger.debug("The Assets directory is bound correctly") + try: + with open( + os.path.realpath(f"Assets/{site_settings.theme}"), "r" + ) as f: + style_sheet = f.read() + + # If theme variable is not defined then use default theme + except AttributeError: + logger.info("Using default theme") + with open(os.path.realpath("Assets/ElegantDark.qss"), "r") as f: + style_sheet = f.read() + + # If there is a typo or user attempts to use theme that is not defined, set default theme + except FileNotFoundError: + logger.warning( + "Theme file not found, please confirm theme is in the Gui/Assets directory" + ) + with open(os.path.realpath("Assets/ElegantDark.qss"), "r") as f: + style_sheet = f.read() + finally: + logger.debug("Setting StyleSheetPropagation") + QApplication.setAttribute( + Qt.AA_UseStyleSheetPropagationInWidgetStyles + ) + QApplication.instance().setStyleSheet(style_sheet) # If Assets directory is not bound (ie. someone has not edited their - # run_docker script) then manually set theme to dark mode. + # run_docker script) then manually set theme to dark mode. else: logger.info("Using default theme") darkPalette = QPalette() @@ -170,14 +175,26 @@ def setLoginUI(self): darkPalette.setColor(QPalette.Disabled, QPalette.Window, Qt.lightGray) darkPalette.setColor(QPalette.Disabled, QPalette.WindowText, Qt.gray) darkPalette.setColor(QPalette.Disabled, QPalette.Base, Qt.darkGray) - darkPalette.setColor(QPalette.Disabled, QPalette.ToolTipBase, Qt.darkGray) + darkPalette.setColor( + QPalette.Disabled, QPalette.ToolTipBase, Qt.darkGray + ) darkPalette.setColor(QPalette.Disabled, QPalette.ToolTipText, Qt.white) darkPalette.setColor(QPalette.Disabled, QPalette.Text, Qt.gray) - darkPalette.setColor(QPalette.Disabled, QPalette.Button, QColor(73, 73, 73)) - darkPalette.setColor(QPalette.Disabled, QPalette.ButtonText, Qt.lightGray) - darkPalette.setColor(QPalette.Disabled, QPalette.BrightText, Qt.lightGray) - darkPalette.setColor(QPalette.Disabled, QPalette.Highlight, Qt.lightGray) - darkPalette.setColor(QPalette.Disabled, QPalette.HighlightedText, Qt.gray) + darkPalette.setColor( + QPalette.Disabled, QPalette.Button, QColor(73, 73, 73) + ) + darkPalette.setColor( + QPalette.Disabled, QPalette.ButtonText, Qt.lightGray + ) + darkPalette.setColor( + QPalette.Disabled, QPalette.BrightText, Qt.lightGray + ) + darkPalette.setColor( + QPalette.Disabled, QPalette.Highlight, Qt.lightGray + ) + darkPalette.setColor( + QPalette.Disabled, QPalette.HighlightedText, Qt.gray + ) QApplication.setStyle(QStyleFactory.create("Fusion")) QApplication.setPalette(darkPalette) @@ -187,7 +204,6 @@ def setLoginUI(self): def initLog(self): for index, firmwareName in enumerate(site_settings.FC7List.keys()): - LogFileName = "{0}/Gui/.{1}.log".format( os.environ.get("GUI_dir"), firmwareName ) @@ -195,7 +211,7 @@ def initLog(self): logFile = open(LogFileName, "w") self.LogList[index] = LogFileName logFile.close() - except: + except OSError: QMessageBox( None, "Error", "Can not create log files: {}".format(LogFileName) ) @@ -229,7 +245,7 @@ def createLogin(self): HostLabel = QLabel("HostName:") - if self.expertMode == False: + if not self.expertMode: self.HostName = QComboBox() HostLabel.setBuddy(self.HostName) else: @@ -240,8 +256,7 @@ def createLogin(self): self.HostEdit.setMaximumWidth(260) self.HostEdit.setMaximumHeight(30) - DatabaseLabel = QLabel("Database:") - if self.expertMode == False: + if not self.expertMode: self.DatabaseCombo = QComboBox() self.DBNames = self.HostName.currentText() + ".All_list" self.DatabaseCombo.addItem(self.DBNames) @@ -326,37 +341,40 @@ def destroyLogin(self): self.LoginGroupBox.deleteLater() def checkLogin(self): - expert_string = '_*' - if self.UsernameEdit.text() not in ['local', 'localexpert']: + expert_string = "_*" + if self.UsernameEdit.text() not in ["local", "localexpert"]: print("Connecting to Panthera...") credentials = { - 'username': self.UsernameEdit.text()[0:-(len(expert_string))] if self.UsernameEdit.text().endswith(expert_string) else self.UsernameEdit.text(), - 'userpass': self.PasswordEdit.text() + "username": self.UsernameEdit.text()[0 : -(len(expert_string))] + if self.UsernameEdit.text().endswith(expert_string) + else self.UsernameEdit.text(), + "userpass": self.PasswordEdit.text(), } - + status, message, data = get_accountInfo(*credentials.values()) if not status: msg = QMessageBox() - msg.information( - None, "Error", message, QMessageBox.Ok - ) + msg.information(None, "Error", message, QMessageBox.Ok) return - - self.username = credentials['username'] - self.password = credentials['userpass'] - self.operator_name_first = data['name_first'] - self.operator_name = data['name_first'] + " " + data['name_last'] + + self.username = credentials["username"] + self.password = credentials["userpass"] + self.operator_name_first = data["name_first"] + self.operator_name = data["name_first"] + " " + data["name_last"] self.panthera_connected = True self.purdue_connected = self.checkPurdueConnection() - - if data['privilege'] in ['Leader', 'Conductor', 'Admin', 'Shifter'] or self.operator_name == "Daniel Ziabicki": #FIXME 'Shifter' needs to be removed from this list once the TEPX and TBPX databases exist. - if self.UsernameEdit.text().endswith('_*'): + + if ( + data["privilege"] in ["Leader", "Conductor", "Admin", "Shifter"] + or self.operator_name == "Daniel Ziabicki" + ): # FIXME 'Shifter' needs to be removed from this list once the TEPX and TBPX databases exist. + if self.UsernameEdit.text().endswith("_*"): self.expertMode = False else: self.expertMode = True else: self.expertMode = False - + self.destroyLogin() if self.expertMode: logger.debug("Entering Expert GUI") @@ -367,18 +385,18 @@ def checkLogin(self): logger.debug("Entering Simplified GUI") self.createSimplifiedMain() else: - if self.UsernameEdit.text().split('_')[0] == 'local': + if self.UsernameEdit.text().split("_")[0] == "local": self.expertMode = False - elif self.UsernameEdit.text().split('_')[0] == 'localexpert': + elif self.UsernameEdit.text().split("_")[0] == "localexpert": self.expertMode = True - - self.username = self.UsernameEdit.text().split('_')[0] + + self.username = self.UsernameEdit.text().split("_")[0] self.password = "" self.operator_name = "Local User" self.operator_name_first = "Local User" self.panthera_connected = False self.purdue_connected = self.checkPurdueConnection() - + self.destroyLogin() if self.expertMode: logger.debug("Entering Expert GUI") @@ -388,12 +406,14 @@ def checkLogin(self): logger.debug("FwDict: {}".format(self.FwDict)) logger.debug("Entering Simplified GUI") self.createSimplifiedMain() - + def checkPurdueConnection(self): status = False message = "" try: - response = requests.get("https://www.physics.purdue.edu/cmsfpix/Phase2_Test/w.php?sn=") + response = requests.get( + "https://www.physics.purdue.edu/cmsfpix/Phase2_Test/w.php?sn=" + ) status = response.status_code == 200 if not status: message = f"Server responded with status code {response.status_code}" @@ -401,14 +421,14 @@ def checkPurdueConnection(self): logger.error(f"An error occurred: {e}") message = f"An error occurred: {e}" status = False - + if not status: msg = QMessageBox() msg.information( None, "Error", f"There was an issue connecting to the Purdue database, please check your internet connection.\nMessage: {message}", - QMessageBox.Ok + QMessageBox.Ok, ) return status @@ -430,19 +450,18 @@ def createSimplifiedMain(self): ############################################################### ## Main page and related functions ############################################################### + def create_status_label(self, text, is_connected): + label = QLabel(f"{text}") + status_label = QLabel("Connected" if is_connected else "Not Connected") + status_label.setStyleSheet(f"color: {'green' if is_connected else 'red'}") + return label, status_label def createMain(self): self.FirmwareStatus = QGroupBox("Hello, {}!".format(self.operator_name_first)) self.FirmwareStatus.setDisabled(True) - - create_status_label = lambda text, is_connected: ( - QLabel(f"{text}"), - (lambda label: (label.setStyleSheet(f"color: {'green' if is_connected else 'red'}"), label)[1]) - (QLabel("Connected" if is_connected else "Not Connected")) - ) self.StatusList = [ - create_status_label("Panthera DB", self.panthera_connected), + self.create_status_label("Panthera DB", self.panthera_connected), ] try: @@ -455,13 +474,12 @@ def createMain(self): BeBoard = QtBeBoard( BeBoardID=str(len(self.FwDict)), boardName=firmwareName, - ipAddress=ipaddress + ipAddress=ipaddress, ) self.FwDict[firmwareName] = BeBoard except Exception as err: print("Failed to list the firmware: {}".format(repr(err))) - logger.debug("Setup FC7s with the following FC7:\n" - f"{self.FwDict}") + logger.debug(f"Setup FC7s with the following FC7:\n{self.FwDict}") self.UseButtons = [] @@ -502,23 +520,22 @@ def createMain(self): FPGAConfigButton.clicked.connect( lambda state, x="{0}".format(index - 1): self.setuDTCFw(x) ) - + SolutionButton = QPushButton("&Firmware Status") SolutionButton.clicked.connect( lambda state, x="{0}".format(index - 1): self.showCommentFw(x) ) - + LogButton = QPushButton("&Log") LogButton.clicked.connect( lambda state, x="{0}".format(index - 1): self.showLogFw(x) ) - + logger.debug("Setup FC7 Buttons") if self.ActiveFC7s != {}: for index in self.ActiveFC7s.keys(): self.occupyFw("{0}".format(index)) - self.FirmwareStatus.setLayout(StatusLayout) self.FirmwareStatus.setDisabled(False) @@ -542,7 +559,7 @@ def createMain(self): self.DefaultLayout.addWidget(self.Wheel) self.DefaultLayout.addStretch(1) self.UseDefaultGroup.setLayout(self.DefaultLayout) - + logger.debug("About to setup HV and LV") self.HVPowerGroup = QGroupBox("HV Power") @@ -551,22 +568,24 @@ def createMain(self): self.HVPortLabel = QLabel() self.HVPortLabel.setText("HV Port:") self.HVPortName = QLabel() - - self.HVDeviceLabel = QLabel() self.HVDeviceLabel.setText("HV Device:") self.HVDeviceName = QLabel() - - if not site_settings.manual_powersupply_control: + + if not site_settings.manual_powersupply_control: HVDevices = [] - for device_name, device in site_settings.icicle_instrument_setup['instrument_dict'].items(): + for device_name, device in site_settings.icicle_instrument_setup[ + "instrument_dict" + ].items(): if "hv" in device_name: HVDevices.append(device) HVPorts = [] for device in HVDevices: - HVPorts.append(device['resource']) - self.HVDeviceName.setText(" | ".join([device['class'] for device in HVDevices])) + HVPorts.append(device["resource"]) + self.HVDeviceName.setText( + " | ".join([device["class"] for device in HVDevices]) + ) self.HVPortName.setText(" | ".join(HVPorts)) else: self.HVPortName.setText("") @@ -575,17 +594,15 @@ def createMain(self): self.HVPowerStatusValue = QLabel() logger.debug("Setup HV") - - self.HVPowerLayout.addWidget(self.HVDeviceLabel,0,0,1,1) - self.HVPowerLayout.addWidget(self.HVDeviceName,0,1,1,1) - self.HVPowerLayout.addWidget(self.HVPortLabel,1,0,1,1) - self.HVPowerLayout.addWidget(self.HVPortName,1,1,1,1) + self.HVPowerLayout.addWidget(self.HVDeviceLabel, 0, 0, 1, 1) + self.HVPowerLayout.addWidget(self.HVDeviceName, 0, 1, 1, 1) + self.HVPowerLayout.addWidget(self.HVPortLabel, 1, 0, 1, 1) + self.HVPowerLayout.addWidget(self.HVPortName, 1, 1, 1, 1) self.HVPowerGroup.setLayout(self.HVPowerLayout) logger.debug("Added HV widgets") - self.LVPowerGroup = QGroupBox("LV Power") self.LVPowerGroup.setDisabled(False) self.LVPowerLayout = QGridLayout() @@ -594,37 +611,47 @@ def createMain(self): self.LVPortLabel.setText("LV Port:") self.LVPortName = QLabel() - logger.debug("Setup LV") self.LVDeviceLabel = QLabel() self.LVDeviceLabel.setText("LV Device:") self.LVDeviceName = QLabel() self.LVPowerStatusValue = QLabel() - - + if not site_settings.manual_powersupply_control: LVDevices = [] - for device_name, device in site_settings.icicle_instrument_setup['instrument_dict'].items(): + for device_name, device in site_settings.icicle_instrument_setup[ + "instrument_dict" + ].items(): if "lv" in device_name: LVDevices.append(device) LVPorts = [] for device in LVDevices: - LVPorts.append(device['resource']) - self.LVDeviceName.setText(" | ".join([device['class'] for device in LVDevices])) + LVPorts.append(device["resource"]) + self.LVDeviceName.setText( + " | ".join([device["class"] for device in LVDevices]) + ) self.LVPortName.setText(" | ".join(LVPorts)) else: self.LVPortName.setText("") self.LVDeviceName.setText("Manual LV Control") - self.LVPowerLayout.addWidget(self.LVDeviceLabel,0,0,1,1) - self.LVPowerLayout.addWidget(self.LVDeviceName,0,1,1,1) - self.LVPowerLayout.addWidget(self.LVPortLabel,1,0,1,1,) - self.LVPowerLayout.addWidget(self.LVPortName,1,1,1,1) + self.LVPowerLayout.addWidget(self.LVDeviceLabel, 0, 0, 1, 1) + self.LVPowerLayout.addWidget(self.LVDeviceName, 0, 1, 1, 1) + self.LVPowerLayout.addWidget( + self.LVPortLabel, + 1, + 0, + 1, + 1, + ) + self.LVPowerLayout.addWidget(self.LVPortName, 1, 1, 1, 1) self.LVPowerGroup.setLayout(self.LVPowerLayout) logger.debug("setup LV and HV devices") - - if "relay_board" in site_settings.icicle_instrument_setup["instrument_dict"].keys(): + if ( + "relay_board" + in site_settings.icicle_instrument_setup["instrument_dict"].keys() + ): self.relay = True self.relay_group = QGroupBox("Relay Box") @@ -633,19 +660,26 @@ def createMain(self): self.relay_board_port_label = QLabel() self.relay_board_port_label.setText("Relay Port:") self.relay_board_port_name = QLabel() - + self.relay_device_label = QLabel() self.relay_device_label.setText("Relay Device:") self.relay_device_name = QLabel() - if not site_settings.manual_powersupply_control: - self.relay_device_name.setText('{0}'.format( - site_settings.icicle_instrument_setup['instrument_dict']['relay_board']['class'] - )) - self.relay_board_port_name.setText('{0}'.format( - site_settings.icicle_instrument_setup['instrument_dict']['relay_board']['resource'] - )) + self.relay_device_name.setText( + "{0}".format( + site_settings.icicle_instrument_setup["instrument_dict"][ + "relay_board" + ]["class"] + ) + ) + self.relay_board_port_name.setText( + "{0}".format( + site_settings.icicle_instrument_setup["instrument_dict"][ + "relay_board" + ]["resource"] + ) + ) self.relay_group.setDisabled(False) else: self.relay_device_name.setText("Manual Relay Control") @@ -653,16 +687,18 @@ def createMain(self): self.relay_model_status = QLabel() - relay_layout.addWidget(self.relay_board_port_label,1,0,1,1) - relay_layout.addWidget(self.relay_board_port_name,1,1,1,1) - relay_layout.addWidget(self.relay_device_label,0,0,1,1) - relay_layout.addWidget(self.relay_device_name,0,1,1,1) + relay_layout.addWidget(self.relay_board_port_label, 1, 0, 1, 1) + relay_layout.addWidget(self.relay_board_port_name, 1, 1, 1, 1) + relay_layout.addWidget(self.relay_device_label, 0, 0, 1, 1) + relay_layout.addWidget(self.relay_device_name, 0, 1, 1, 1) self.relay_group.setLayout(relay_layout) self.mainLayout.addWidget(self.relay_group, 3, 0, 1, 1) - if "multimeter" in site_settings.icicle_instrument_setup["instrument_dict"].keys(): - + if ( + "multimeter" + in site_settings.icicle_instrument_setup["instrument_dict"].keys() + ): self.multimeter = True self.multimeter_group = QGroupBox("Multimeter") @@ -671,18 +707,26 @@ def createMain(self): self.multimeter_port_label = QLabel() self.multimeter_port_label.setText("Multimeter Port") self.multimeter_port_name = QLabel() - + self.multimeter_device_label = QLabel() self.multimeter_device_label.setText("Multimeter Device:") self.multimeter_device_name = QLabel() if not site_settings.manual_powersupply_control: - self.multimeter_device_name.setText('{0}'.format( - site_settings.icicle_instrument_setup['instrument_dict']['multimeter']['class'] - )) - self.multimeter_port_name.setText('{0}'.format( - site_settings.icicle_instrument_setup['instrument_dict']['multimeter']['resource'] - )) + self.multimeter_device_name.setText( + "{0}".format( + site_settings.icicle_instrument_setup["instrument_dict"][ + "multimeter" + ]["class"] + ) + ) + self.multimeter_port_name.setText( + "{0}".format( + site_settings.icicle_instrument_setup["instrument_dict"][ + "multimeter" + ]["resource"] + ) + ) self.multimeter_group.setDisabled(False) else: self.multimeter_device_name.setText("Manual multimeter control") @@ -690,10 +734,10 @@ def createMain(self): self.multimeter_status = QLabel() - multimeter_layout.addWidget(self.multimeter_port_label,1,0,1,1) - multimeter_layout.addWidget(self.multimeter_port_name,1,1,1,1) - multimeter_layout.addWidget(self.multimeter_device_label,0,0,1,1) - multimeter_layout.addWidget(self.multimeter_device_name,0,1,1,1) + multimeter_layout.addWidget(self.multimeter_port_label, 1, 0, 1, 1) + multimeter_layout.addWidget(self.multimeter_port_name, 1, 1, 1, 1) + multimeter_layout.addWidget(self.multimeter_device_label, 0, 0, 1, 1) + multimeter_layout.addWidget(self.multimeter_device_name, 0, 1, 1, 1) self.multimeter_group.setLayout(multimeter_layout) self.mainLayout.addWidget(self.multimeter_group, 3, 1, 1, 3) @@ -710,7 +754,7 @@ def createMain(self): kMaximumWidth = 150 kMinimumHeight = 30 kMaximumHeight = 100 - + self.SummaryButton = QPushButton("&Status summary") if not self.expertMode: self.SummaryButton.setDisabled(True) @@ -719,7 +763,8 @@ def createMain(self): self.SummaryButton.setMinimumHeight(kMinimumHeight) self.SummaryButton.setMaximumHeight(kMaximumHeight) self.SummaryButton.clicked.connect(self.openSummaryWindow) - if self.expertMode: self.SummaryButton.setDisabled(False) + if self.expertMode: + self.SummaryButton.setDisabled(False) self.NewTestButton = QPushButton("&New") self.NewTestButton.setDefault(True) @@ -732,7 +777,7 @@ def createMain(self): self.NewTestButton.setDisabled(True) if self.ActiveFC7s != {}: self.NewTestButton.setDisabled(False) - if self.ProcessingTest == True: + if self.ProcessingTest: self.NewTestButton.setDisabled(True) NewTestLabel = QLabel("Open new test") @@ -745,7 +790,7 @@ def createMain(self): True ) # FIXME This is to temporarily disable the test until LV can be added. self.NewProductionTestButton.clicked.connect(self.openNewProductionTest) - NewProductionTestLabel = QLabel("Open production test") + # NewProductionTestLabel = QLabel("Open production test") self.ReviewButton = QPushButton("&Review") self.ReviewButton.setMinimumWidth(kMinimumWidth) @@ -779,8 +824,7 @@ def createMain(self): except AttributeError: self.ThermalTestButton.setEnabled(False) self.AbortThermalTestButton.setEnabled(False) - - + self.AbortThermalTestButton.setMinimumWidth(kMinimumWidth) self.AbortThermalTestButton.setMaximumWidth(kMaximumWidth) self.AbortThermalTestButton.setMinimumHeight(kMinimumHeight) @@ -796,14 +840,14 @@ def createMain(self): self.ThermalProfileEdit = QLineEdit("") self.ThermalProfileEdit.setEchoMode(QLineEdit.Normal) self.ThermalProfileEdit.setPlaceholderText("Enter Profile Number") - + self.CoolerBox = QGroupBox(f"{site_settings.cooler} Controller", self) self.CoolerLayout = QGridLayout() - if site_settings.cooler=="Peltier": + if site_settings.cooler == "Peltier": self.CoolerLayout.addWidget(Peltier(100)) - elif site_settings.cooler=="Tessie": + elif site_settings.cooler == "Tessie": self.CoolerLayout.addWidget(Tessie(100)) - elif site_settings.cooler=="Manual": + elif site_settings.cooler == "Manual": # Title label (Manual Cooling) title_label = QLabel("MANUAL COOLING") title_label.setFont(QFont("Arial", 16, QFont.Bold)) @@ -816,25 +860,29 @@ def createMain(self): subtitle_label.setAlignment(Qt.AlignCenter) self.CoolerLayout.setRowStretch(0, 1) # Add stretch at the top - self.CoolerLayout.addWidget(title_label, 1, 0, Qt.AlignCenter) # Centered title - self.CoolerLayout.addWidget(subtitle_label, 2, 0, Qt.AlignCenter) # Centered warning + self.CoolerLayout.addWidget( + title_label, 1, 0, Qt.AlignCenter + ) # Centered title + self.CoolerLayout.addWidget( + subtitle_label, 2, 0, Qt.AlignCenter + ) # Centered warning self.CoolerLayout.setRowStretch(3, 1) # Add stretch at the bottom else: + logger.error( + 'site_settings.cooler is invalid string. Must be "Peltier", "Tessie", or "Manual"' + ) - logger.error('site_settings.cooler is invalid string. Must be "Peltier", "Tessie", or "Manual"') - self.CoolerBox.setLayout(self.CoolerLayout) self.mainLayout.addWidget(self.CoolerBox, 4, 0, 3, 1) layout = QGridLayout() layout.addWidget(self.NewTestButton, 0, 0, 1, 1) layout.addWidget(NewTestLabel, 0, 1, 1, 2) - + layout.addWidget(self.ReviewButton, 2, 0, 1, 1) layout.addWidget(ReviewLabel, 2, 1, 1, 2) layout.addWidget(self.ReviewModuleButton, 3, 0, 1, 1) layout.addWidget(self.ReviewModuleEdit, 3, 1, 1, 2) - self.ChillerOption = QGroupBox("Chiller", self) self.ChillerLayout = QGridLayout() self.ChillerOption.setLayout(self.ChillerLayout) @@ -842,7 +890,7 @@ def createMain(self): layout.addWidget(self.ThermalTestButton, 4, 0, 1, 1) layout.addWidget(self.ThermalProfileEdit, 4, 1, 1, 1) layout.addWidget(self.AbortThermalTestButton, 5, 0, 1, 1) - + self.MainOption.setLayout(layout) self.AppOption = QGroupBox() @@ -892,11 +940,11 @@ def createMain(self): self.mainLayout.addWidget(self.UseDefaultGroup, 1, 0, 1, 1) self.mainLayout.addWidget(self.HVPowerGroup, 2, 0, 1, 1) self.mainLayout.addWidget(self.LVPowerGroup, 2, 1, 1, 3) - + self.mainLayout.addWidget(self.MainOption, 0, 1, 2, 3) self.mainLayout.addWidget(self.LogoGroupBox, 7, 0, 1, 4) - + # Placing in try/except to avoid needing to change siteConfig try: self.MyLauda = LaudaWidget(100) @@ -914,12 +962,11 @@ def createMain(self): self.setDefault() # create a dictionary to easily disable groupboxes later - self.groupbox_mapping = { - "hv": self.HVPowerGroup, - "lv": self.LVPowerGroup - } - if self.relay: self.groupbox_mapping["relay"] = self.relay_group - if self.multimeter: self.groupbox_mpaping["multimeter"] = self.multimeter_group + self.groupbox_mapping = {"hv": self.HVPowerGroup, "lv": self.LVPowerGroup} + if self.relay: + self.groupbox_mapping["relay"] = self.relay_group + if self.multimeter: + self.groupbox_mpaping["multimeter"] = self.multimeter_group def setDefault(self): if self.expertMode is False: @@ -933,14 +980,13 @@ def update_instrument_info(self, key, info): def connect_devices_starter(self): self.Wheel.setVisible(True) - self.connect_devices_thread = LoadingThread(self.connect_devices,50) + self.connect_devices_thread = LoadingThread(self.connect_devices, 50) self.connect_devices_thread.finished.connect(self.Wheel.close) self.connect_devices_thread.timer.timeout.connect(self.Wheel.update_spinner) self.connect_devices_thread.timer.start() self.connect_devices_thread.start() # Start the thread def connect_devices(self): - """ Use defaults set in siteConfig.py to setup instrument cluster. If default_checkbox is not checked change this variable to reflect @@ -962,7 +1008,7 @@ def connect_devices(self): self.instruments.open() lv_on = False hv_on = False - + for number in self.instruments.get_modules().keys(): if self.instruments.status()[number]["hv"]: hv_on = True @@ -971,8 +1017,8 @@ def connect_devices(self): if self.instruments.status()[number]["lv"]: lv_on = True break - - if (lv_on or hv_on): + + if lv_on or hv_on: self.instruments.off() if self.expertMode: self.disable_instrument_widgets() @@ -983,7 +1029,7 @@ def connect_devices(self): self.instruments = None if self.expertMode: - if self.ArduinoControl.isChecked(): + if self.ArduinoControl.isChecked(): self.ArduinoGroup.setBaudRate(site_settings.defaultSensorBaudRate) self.ArduinoGroup.frozeArduinoPanel() @@ -995,8 +1041,10 @@ def disable_instrument_widgets(self): """ self.HVPowerGroup.setDisabled(True) self.LVPowerGroup.setDisabled(True) - if self.relay: self.relay_group.setDisabled(True) - if self.multimeter: self.multimeter_group.setDisabled(True) + if self.relay: + self.relay_group.setDisabled(True) + if self.multimeter: + self.multimeter_group.setDisabled(True) def reconnectDevices(self): if self.instruments and not site_settings.manual_powersupply_control: @@ -1013,10 +1061,9 @@ def reconnectDevices(self): for instrument, useFlag in self.desired_devices.items(): if useFlag and instrument in self.groupbox_mapping: self.groupbox_mapping[instrument].setDisabled(False) - + else: - logger.info("You are running in manual mode. Reconnecting" - "does nothing") + logger.info("You are running in manual mode. Reconnectingdoes nothing") def reCreateMain(self): print("Refreshing the main page") @@ -1037,8 +1084,10 @@ def destroyMain(self): self.UseDefaultGroup.deleteLater() self.HVPowerGroup.deleteLater() self.LVPowerGroup.deleteLater() - if self.relay: self.relay_group.deleteLater() - if self.multimeter: self.multimeter_group.deleteLater() + if self.relay: + self.relay_group.deleteLater() + if self.multimeter: + self.multimeter_group.deleteLater() self.ArduinoGroup.deleteLater() self.ArduinoControl.deleteLater() self.CoolerBox.deleteLater() @@ -1050,8 +1099,10 @@ def destroyMain(self): self.mainLayout.removeWidget(self.HVPowerGroup) self.mainLayout.removeWidget(self.UseDefaultGroup) self.mainLayout.removeWidget(self.LVPowerGroup) - if self.relay: self.mainLayout.removeWidget(self.relay_group) - if self.multimeter: self.mainLayout.removeWidget(self.multimeter_group) + if self.relay: + self.mainLayout.removeWidget(self.relay_group) + if self.multimeter: + self.mainLayout.removeWidget(self.multimeter_group) self.mainLayout.removeWidget(self.ArduinoGroup) self.mainLayout.removeWidget(self.ArduinoControl) self.mainLayout.removeWidget(self.CoolerBox) @@ -1064,9 +1115,9 @@ def destroyMain(self): def abortThermalTest(self): """Stop the current profile running on thermal chamber""" - temp_chamber = F4TTempChamber(resource = site_settings.temp_chamber_resource) + temp_chamber = F4TTempChamber(resource=site_settings.temp_chamber_resource) with temp_chamber: - temp_chamber.set('CONTROL_PROFILE', 'STOP') + temp_chamber.set("CONTROL_PROFILE", "STOP") message_box = QMessageBox() message_box.setText("Profile Aborted") message_box.setStandardButtons(QMessageBox.Ok) @@ -1081,22 +1132,24 @@ def runThermalTest(self): profile_number = int(profile_number) except ValueError: QMessageBox.information( - None, "Error", "Please enter a valid profile number" - ". It must be an integer", QMessageBox.Ok + None, + "Error", + "Please enter a valid profile number. It must be an integer", + QMessageBox.Ok, ) return # Import icicle module for temperature chamber print(site_settings.temp_chamber_resource) - temp_chamber = F4TTempChamber(resource = site_settings.temp_chamber_resource) - + temp_chamber = F4TTempChamber(resource=site_settings.temp_chamber_resource) with temp_chamber: - temp_chamber.set('SELECT_PROFILE', profile_number) - profile_name = temp_chamber.query('SELECT_PROFILE') + temp_chamber.set("SELECT_PROFILE", profile_number) + profile_name = temp_chamber.query("SELECT_PROFILE") message_box = QMessageBox() - message_box.setText("Temperature chamber" - f"profile \"{profile_name}\" has been chosen") + message_box.setText( + f'Temperature chamberprofile "{profile_name}" has been chosen' + ) message_box.setInformativeText("Is this the correct profile?") message_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No) message_box.setDefaultButton(QMessageBox.Yes) @@ -1104,15 +1157,11 @@ def runThermalTest(self): if response == QMessageBox.Yes: with temp_chamber: - temp_chamber.set('CONTROL_PROFILE', 'START') + temp_chamber.set("CONTROL_PROFILE", "START") if response == QMessageBox.No: - return - - - + return - def openNewProductionTest(self): self.ProdTestPage = QtProductionTestWindow( self, instrumentCluster=self.instruments @@ -1124,9 +1173,11 @@ def openNewProductionTest(self): def openNewTest(self): FwModule = [ - board_object for firmware, board_object in self.FwDict.items() if firmware in self.ActiveFC7s.values() + board_object + for firmware, board_object in self.FwDict.items() + if firmware in self.ActiveFC7s.values() ] - print(f'FwModule is: {[board.getBoardName() for board in FwModule]}') + print(f"FwModule is: {[board.getBoardName() for board in FwModule]}") self.StartNewTest = QtStartWindow(self, FwModule) self.NewTestButton.setDisabled(True) @@ -1158,7 +1209,7 @@ def releaseHVPowerPanel(self): self.HVPowerStatusValue.setText("") self.UseHVPowerSupply.setDisabled(False) - except Exception as err: + except Exception: print("HV PowerPanel not released properly") else: logger.info("You must manually turn off the HV") @@ -1167,7 +1218,6 @@ def enableDevice(self, device): """Keep track of whether a device wants to be used""" self.desired_devices[device] = 1 if (self.desired_devices[device] == 0) else 0 - def releaseLVPowerPanel(self): if self.instruments: self.instruments.lv_off(1) @@ -1209,9 +1259,7 @@ def refreshFirmware(self): self.occupyFw("{0}".format(index)) def getFwComment(self, BeBoard: QtBeBoard, fileName): - comment, color, verboseInfo = fwStatusParser( - BeBoard, fileName - ) + comment, color, verboseInfo = fwStatusParser(BeBoard, fileName) return comment, color, verboseInfo def getIndex(self, element, List2D): @@ -1238,7 +1286,7 @@ def occupyFw(self, index): self.CheckButton.setDisabled(True) self.ActiveFC7s[i] = self.StatusList[i + 1][0].text() else: - #button.setDisabled(True) + # button.setDisabled(True) pass def releaseFw(self, index): @@ -1277,11 +1325,12 @@ def setuDTCFw(self, index): firmware.setFPGAConfig(changeuDTCDialog.uDTCFile) self.checkFirmware() + def releaseProdTestButton(self): self.NewProductionTestButton.setDisabled(False) self.LogoutButton.setDisabled(False) self.ExitButton.setDisabled(False) - + def goExpert(self): self.expertMode = True @@ -1290,7 +1339,7 @@ def goExpert(self): self.destroyMain() self.createMain() self.checkFirmware() - + ############################################################### ## Global stop signal ############################################################### @@ -1299,7 +1348,7 @@ def GlobalStop(self): print("Critical status detected: Emitting Global Stop signal") self.globalStop.emit() self.instruments.off() - if self.expertMode == True: + if self.expertMode: self.releaseHVPowerPanel() self.releaseLVPowerPanel() @@ -1308,12 +1357,16 @@ def GlobalStop(self): ############################################################### def manual_control_warning(self): if not self.instruments: - QMessageBox.warning(self, "Manual Control", - "You have opted for manual power supply " - "control. If this is incorrect edit " - "icicle_instrument_setup in siteConfig.py. " - "Otherwise, proceed at your own risk", - QMessageBox.Ok) + QMessageBox.warning( + self, + "Manual Control", + "You have opted for manual power supply " + "control. If this is incorrect edit " + "icicle_instrument_setup in siteConfig.py. " + "Otherwise, proceed at your own risk", + QMessageBox.Ok, + ) + def closeEvent(self, event): reply = QMessageBox.question( self, @@ -1334,7 +1387,12 @@ def closeEvent(self, event): self.PeltierCooling.shutdown() else: self.SimpleMain.worker.abort_worker() - self.SimpleMain.Peltier.sendCommand(self.SimpleMain.Peltier.createCommand("Power On/Off Write", ["0", "0", "0", "0", "0", "0", "0", "0"])) + self.SimpleMain.Peltier.sendCommand( + self.SimpleMain.Peltier.createCommand( + "Power On/Off Write", + ["0", "0", "0", "0", "0", "0", "0", "0"], + ) + ) except Exception as e: logger.error(f"Could not shutdown Peltier: {e}") @@ -1348,4 +1406,3 @@ def closeEvent(self, event): event.accept() else: event.ignore() - diff --git a/Gui/QtGUIutils/QtCustomizeWindow.py b/Gui/QtGUIutils/QtCustomizeWindow.py index 0d445cb0..bfb38fba 100644 --- a/Gui/QtGUIutils/QtCustomizeWindow.py +++ b/Gui/QtGUIutils/QtCustomizeWindow.py @@ -1,45 +1,20 @@ -from PyQt5 import QtCore from PyQt5.QtCore import Qt -from PyQt5.QtGui import QPixmap, QFont +from PyQt5.QtGui import QFont from PyQt5.QtWidgets import ( - QApplication, - QCheckBox, - QComboBox, - QDateTimeEdit, - QDial, - QDialog, QFileDialog, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLineEdit, - QMainWindow, QMessageBox, - QProgressBar, QPushButton, - QRadioButton, - QScrollBar, - QSizePolicy, - QSlider, - QSpinBox, - QSplitter, - QStyleFactory, - QTableWidget, - QTabWidget, - QTextEdit, - QVBoxLayout, QWidget, ) -import sys -import os -import subprocess -from subprocess import Popen, PIPE -#from Gui.GUIutils.DBConnection import * -#from Gui.GUIutils.guiUtils import * -from Gui.python.logging_config import logger +# from Gui.GUIutils.DBConnection import * +# from Gui.GUIutils.guiUtils import * class RD53Widget(QWidget): @@ -52,8 +27,6 @@ def __init__(self, index): def createBody(self): kMinimumWidth = 120 - kMaximumWidth = 150 - kMinimumHeight = 30 kMaximumHeight = 80 RD53Label = QLabel("RD53 ID: {}".format(self.id)) @@ -143,8 +116,6 @@ def createMain(self): mainbodylayout = QGridLayout() kMinimumWidth = 120 - kMaximumWidth = 150 - kMinimumHeight = 30 kMaximumHeight = 80 XMLLabel = QLabel("CMSIT XML:") @@ -224,7 +195,7 @@ def openFileBrowserXML(self): None, "Warning", "Not a valid XML file", QMessageBox.Ok ) - if self.validateXML() != True: + if not self.validateXML(): QMessageBox.information( None, "Warning", "XML file failed the validation", QMessageBox.Ok ) diff --git a/Gui/QtGUIutils/QtDBConsoleWindow.py b/Gui/QtGUIutils/QtDBConsoleWindow.py index a7b9b577..b9a49f2c 100644 --- a/Gui/QtGUIutils/QtDBConsoleWindow.py +++ b/Gui/QtGUIutils/QtDBConsoleWindow.py @@ -1,45 +1,23 @@ -from PyQt5 import QtCore from PyQt5.QtCore import Qt, QDateTime -from PyQt5.QtGui import QPixmap from PyQt5.QtWidgets import ( QAbstractItemView, QAction, - QApplication, - QCheckBox, QComboBox, QDateTimeEdit, - QDial, - QDialog, QGridLayout, QGroupBox, - QHBoxLayout, QLabel, QLineEdit, - QMenuBar, - QProgressBar, QPushButton, - QRadioButton, - QScrollBar, - QSizePolicy, - QSlider, - QSpinBox, - QStyleFactory, QTableView, - QTableWidget, QTabWidget, QTextEdit, QHBoxLayout, - QVBoxLayout, QWidget, QMainWindow, QMessageBox, - QSplitter, ) -import sys -import os -import subprocess -from subprocess import Popen, PIPE from Gui.GUIutils.DBConnection import ( QtStartConnection, @@ -52,14 +30,14 @@ describeInstitute, retrieveAllInstitute, updateGenericTable, - getByColumnName + getByColumnName, ) from Gui.GUIutils.guiUtils import isActive from Gui.QtGUIutils.QtDBTableWidget import QtDBTableWidget from Gui.QtGUIutils.QtViewTableTab import QtViewTableTab from Gui.QtGUIutils.QtImageInsertionTab import QtImageInsertionTab from Gui.QtGUIutils.QtImageViewerTab import QtImageViewerTab -from Gui.python.logging_config import logger + class QtDBConsoleWindow(QMainWindow): def __init__(self, master): @@ -329,8 +307,8 @@ def submitSPRequest(self): SubmitArgs.append(arg) try: insertGenericTable(self.connection, "shipment", SubmitArgs, Data) - except: - print("Failed to submit the shipment record") + except Exception as e: + print(f"Failed to submit the shipment record due to error: {e}") return self.SPSenderLabel.deleteLater() @@ -509,7 +487,8 @@ def fillRPRequest(self): shipmentInfo = retrieveWithConstraint( self.connection, "shipment", id=self.RPIDEdit.text() ) - except: + except Exception as e: + print(f"Failed to Retrieve Shipment Information Due to Error: {e}") return if len(shipmentInfo) > 0 and len(header) == len(shipmentInfo[0]): self.RPFeedBackLabel.setText("Delivery Record found") @@ -586,8 +565,8 @@ def submitRPRequest(self): Data, id=int(self.RPIDEdit.text()), ) - except: - print("Failed to submit the shipment record") + except Exception as e: + print(f"Failed to submit the shipment record due to error: {e}") return self.RPIDLabel.deleteLater() @@ -818,9 +797,9 @@ def submitAURequest(self): TimeZone = getByColumnName( "timezone", describeTable(self.connection, "institute"), InstituteInfo ) - except: + except Exception as e: self.AUFeedBackLabel.setText( - "Failed to extract institute info, try to reconnect to DB" + f"Failed to extract institute info, try to reconnect to DB due to error: {e}" ) Args = describeTable(self.connection, "people") Data = [] @@ -837,8 +816,8 @@ def submitAURequest(self): self.AUFeedBackLabel.setText("Query submitted") self.AUFeedBackLabel.setStyleSheet("color:green") return - except: - print("submitFailed") + except Exception as e: + print(f"submitFailed due to error: {e}") return def updateProfile(self): @@ -960,8 +939,8 @@ def submitFCRequest(self): # print(Data) try: insertGenericTable(self.connection, "complaint", Args, Data) - except: - print("Failed to submit the text") + except Exception as e: + print(f"Failed to submit the text due to error: {e}") return self.FCNameLabel.deleteLater() self.FCNameEdit.deleteLater() @@ -1147,6 +1126,8 @@ def connectDB(self): self.TryHostAddress = self.HostEdit.text() self.TryDatabase = self.DatabaseEdit.text() + msg = QMessageBox() + if self.TryUsername == "": msg.information( None, "Error", "Please enter a valid username", QMessageBox.Ok @@ -1168,12 +1149,6 @@ def connectDB(self): def syncDB(self): pass - def changeDBList(self): - self.DBNames = DBNames[str(self.HostName.currentText())] #only reference to DBNames I could find is commented out in Gui/GUIutils/settings.py - self.DatabaseCombo.clear() - self.DatabaseCombo.addItems(self.DBNames) - self.DatabaseCombo.setCurrentIndex(0) - def closeTab(self, index): self.releaseAction(self.MainTabs.tabText(index)) self.MainTabs.removeTab(index) diff --git a/Gui/QtGUIutils/QtDBTableWidget.py b/Gui/QtGUIutils/QtDBTableWidget.py index c8e18435..1855f726 100644 --- a/Gui/QtGUIutils/QtDBTableWidget.py +++ b/Gui/QtGUIutils/QtDBTableWidget.py @@ -1,47 +1,11 @@ from PyQt5 import QtCore from PyQt5.QtCore import QSortFilterProxyModel -from PyQt5.QtGui import QBrush, QColor, QPixmap, QStandardItemModel, QStandardItem -from PyQt5.QtWidgets import ( - QApplication, - QCheckBox, - QComboBox, - QDateTimeEdit, - QDial, - QDialog, - QGridLayout, - QGroupBox, - QHBoxLayout, - QLabel, - QLineEdit, - QProgressBar, - QPushButton, - QRadioButton, - QScrollBar, - QSizePolicy, - QSlider, - QSpinBox, - QStyleFactory, - QTableView, - QTableWidget, - QTabWidget, - QTextEdit, - QHBoxLayout, - QVBoxLayout, - QWidget, - QMainWindow, - QMessageBox, - QSplitter, -) +from PyQt5.QtGui import QStandardItemModel, QStandardItem -import sys -import os -import subprocess -from subprocess import Popen, PIPE -#from Gui.GUIutils.DBConnection import * -#from Gui.GUIutils.guiUtils import * -#from Gui.GUIutils.settings import * -from Gui.python.logging_config import logger +# from Gui.GUIutils.DBConnection import * +# from Gui.GUIutils.guiUtils import * +# from Gui.GUIutils.settings import * class QtDBTableWidget(QSortFilterProxyModel): diff --git a/Gui/QtGUIutils/QtFileDialogPreview.py b/Gui/QtGUIutils/QtFileDialogPreview.py index 999d1be3..f7106b3d 100644 --- a/Gui/QtGUIutils/QtFileDialogPreview.py +++ b/Gui/QtGUIutils/QtFileDialogPreview.py @@ -1,44 +1,14 @@ from PyQt5.QtCore import Qt -from PyQt5.QtGui import QFont, QPixmap +from PyQt5.QtGui import QPixmap from PyQt5.QtWidgets import ( - QAbstractItemView, - QApplication, - QCheckBox, - QComboBox, - QDateTimeEdit, - QDial, - QDialog, QFileDialog, - QGridLayout, - QGroupBox, - QHBoxLayout, QLabel, - QLineEdit, - QProgressBar, - QPushButton, - QRadioButton, - QScrollBar, - QSizePolicy, - QSlider, - QSpinBox, - QStyleFactory, - QTableWidget, - QTabWidget, - QTextEdit, - QHBoxLayout, QVBoxLayout, - QWidget, - QMainWindow, - QMessageBox, ) -import sys -import os -import numpy -#from Gui.GUIutils.DBConnection import * -#from Gui.GUIutils.guiUtils import * -from Gui.python.logging_config import logger +# from Gui.GUIutils.DBConnection import * +# from Gui.GUIutils.guiUtils import * class QtFileDialogPreview(QFileDialog): diff --git a/Gui/QtGUIutils/QtFwCheckDetails.py b/Gui/QtGUIutils/QtFwCheckDetails.py index b6799ddc..b1617f0b 100644 --- a/Gui/QtGUIutils/QtFwCheckDetails.py +++ b/Gui/QtGUIutils/QtFwCheckDetails.py @@ -2,7 +2,6 @@ from PyQt5.QtWidgets import ( QGridLayout, QGroupBox, - QHBoxLayout, QPushButton, QHBoxLayout, QWidget, @@ -11,10 +10,9 @@ import math from Gui.python.CustomizedWidget import StatusBox -#from Gui.GUIutils.DBConnection import * -#from Gui.GUIutils.FirmwareUtil import * -#from Gui.GUIutils.settings import * -from Gui.python.logging_config import logger +# from Gui.GUIutils.DBConnection import * +# from Gui.GUIutils.FirmwareUtil import * +# from Gui.GUIutils.settings import * class QtFwCheckDetails(QWidget): diff --git a/Gui/QtGUIutils/QtFwCheckWindow.py b/Gui/QtGUIutils/QtFwCheckWindow.py index 8ec0a169..d00cfb6e 100644 --- a/Gui/QtGUIutils/QtFwCheckWindow.py +++ b/Gui/QtGUIutils/QtFwCheckWindow.py @@ -1,37 +1,13 @@ -import sys -import os from PyQt5 import QtCore from PyQt5.QtCore import QProcess from PyQt5.QtWidgets import ( - QApplication, - QCheckBox, - QComboBox, - QDateTimeEdit, - QDial, - QDialog, QGridLayout, QGroupBox, - QHBoxLayout, - QLabel, - QLineEdit, - QProgressBar, QPushButton, - QRadioButton, - QScrollBar, - QSizePolicy, - QSlider, - QSpinBox, - QStyleFactory, - QTableWidget, - QTabWidget, QTextEdit, QHBoxLayout, - QVBoxLayout, QWidget, - QMainWindow, - QMessageBox, ) -from Gui.python.logging_config import logger class QtFwCheckWindow(QWidget): diff --git a/Gui/QtGUIutils/QtFwStatusWindow.py b/Gui/QtGUIutils/QtFwStatusWindow.py index 80200afb..0ce0815b 100644 --- a/Gui/QtGUIutils/QtFwStatusWindow.py +++ b/Gui/QtGUIutils/QtFwStatusWindow.py @@ -1,37 +1,13 @@ -import sys -import os -#from PyQt5 import QtCore -#from PyQt5.QtCore import * +# from PyQt5 import QtCore +# from PyQt5.QtCore import * from PyQt5.QtWidgets import ( - QApplication, - QCheckBox, - QComboBox, - QDateTimeEdit, - QDial, - QDialog, QGridLayout, QGroupBox, - QHBoxLayout, QLabel, - QLineEdit, - QProgressBar, QPushButton, - QRadioButton, - QScrollBar, - QSizePolicy, - QSlider, - QSpinBox, - QStyleFactory, - QTableWidget, - QTabWidget, - QTextEdit, QHBoxLayout, - QVBoxLayout, QWidget, - QMainWindow, - QMessageBox, ) -from Gui.python.logging_config import logger class QtFwStatusWindow(QWidget): @@ -58,7 +34,7 @@ def createMain(self): SummaryLayout = QGridLayout() - if type(self.verboseInfo) == type({}): + if type(self.verboseInfo) is type({}): for index, key in enumerate(self.verboseInfo): KeyLabel = QLabel("{}".format(key)) ValueLabel = QLabel("{}".format(self.verboseInfo[key])) diff --git a/Gui/QtGUIutils/QtImageInsertionTab.py b/Gui/QtGUIutils/QtImageInsertionTab.py index 44c66f0d..204011cc 100644 --- a/Gui/QtGUIutils/QtImageInsertionTab.py +++ b/Gui/QtGUIutils/QtImageInsertionTab.py @@ -1,49 +1,27 @@ from PyQt5.QtCore import Qt, QDateTime -#from PyQt5.QtGui import QFont, QPixmap + +# from PyQt5.QtGui import QFont, QPixmap from PyQt5.QtWidgets import ( - QAbstractItemView, - QApplication, - QCheckBox, - QComboBox, QDateTimeEdit, - QDial, - QDialog, QFileDialog, QGridLayout, QGroupBox, - QHBoxLayout, QLabel, QLineEdit, - QProgressBar, QPushButton, - QRadioButton, - QScrollBar, - QSizePolicy, - QSlider, - QSpinBox, - QStyleFactory, - QTableWidget, - QTabWidget, - QTextEdit, - QHBoxLayout, - QVBoxLayout, QWidget, - QMainWindow, QMessageBox, ) -import sys import os -import numpy from Gui.GUIutils.DBConnection import ( describeTable, insertGenericTable, ) -#from Gui.GUIutils.guiUtils import * -#from Gui.QtGUIutils.QtDBTableWidget import * -#from Gui.QtGUIutils.QtFileDialogPreview import * -from Gui.python.logging_config import logger +# from Gui.GUIutils.guiUtils import * +# from Gui.QtGUIutils.QtDBTableWidget import * +# from Gui.QtGUIutils.QtFileDialogPreview import * class QtImageInsertionTab(QWidget): @@ -156,7 +134,7 @@ def submitRequest(self): self.FeedBackLabel.setText("Failed: Submission is unsuccessful") self.InsertButton().setDisabled(False) return - if self.Inserted == False: + if not self.Inserted: self.FeedBackLabel.setStyleSheet("color:red") self.FeedBackLabel.setText("Failed: Submission is unsuccessful") self.InsertButton().setDisabled(False) diff --git a/Gui/QtGUIutils/QtImageViewer.py b/Gui/QtGUIutils/QtImageViewer.py index 7c53bebb..2850e2d8 100644 --- a/Gui/QtGUIutils/QtImageViewer.py +++ b/Gui/QtGUIutils/QtImageViewer.py @@ -1,42 +1,14 @@ -from PyQt5 import QtCore from PyQt5.QtCore import Qt, QSize -from PyQt5.QtGui import QFont, QPixmap, QPalette, QImage +from PyQt5.QtGui import QPixmap, QImage from PyQt5.QtWidgets import ( - QApplication, - QCheckBox, - QComboBox, - QDateTimeEdit, - QDial, - QDialog, QGridLayout, QGroupBox, - QHBoxLayout, QLabel, - QLineEdit, - QProgressBar, QPushButton, - QRadioButton, - QScrollBar, - QSizePolicy, - QSlider, - QSpinBox, - QStyleFactory, - QTableWidget, - QTabWidget, - QTextEdit, QHBoxLayout, - QVBoxLayout, QWidget, - QMainWindow, - QMessageBox, ) -import sys -import os -import io -from PIL.ImageQt import ImageQt -from Gui.python.logging_config import logger - class QtImageViewer(QWidget): def __init__(self, master, data): diff --git a/Gui/QtGUIutils/QtImageViewerTab.py b/Gui/QtGUIutils/QtImageViewerTab.py index b5c24210..9c90c47c 100644 --- a/Gui/QtGUIutils/QtImageViewerTab.py +++ b/Gui/QtGUIutils/QtImageViewerTab.py @@ -1,49 +1,27 @@ from PyQt5.QtCore import Qt, QSize -from PyQt5.QtGui import QImage, QFont, QPixmap +from PyQt5.QtGui import QImage, QPixmap from PyQt5.QtWidgets import ( QAbstractItemView, - QApplication, - QCheckBox, QComboBox, - QDateTimeEdit, - QDial, - QDialog, QGridLayout, QGroupBox, - QHBoxLayout, QLabel, QLineEdit, - QProgressBar, QPushButton, - QRadioButton, - QScrollBar, - QSizePolicy, - QSlider, - QSpinBox, - QStyleFactory, QTableView, - QTableWidget, - QTabWidget, - QTextEdit, - QHBoxLayout, - QVBoxLayout, QWidget, - QMainWindow, QMessageBox, ) -import sys -import os -import numpy from Gui.GUIutils.DBConnection import ( mysql, retrieveWithConstraint, - ) -#from Gui.GUIutils.guiUtils import * +) + +# from Gui.GUIutils.guiUtils import * from Gui.QtGUIutils.QtDBTableWidget import QtDBTableWidget -#from Gui.QtGUIutils.QtImageViewer import * -from Gui.python.logging_config import logger +# from Gui.QtGUIutils.QtImageViewer import * class QtImageViewerTab(QWidget): @@ -111,9 +89,8 @@ def viewBox(self, dataList=[]): for row in range(len(self.proxy.dataBody)): DetailButton = QPushButton("&Show...") DetailButton.clicked.connect( - lambda state, x="{0}".format( - self.proxy.dataBody[row][0] - ): self.openImage(x) + lambda state, + x="{0}".format(self.proxy.dataBody[row][0]): self.openImage(x) ) self.view.setIndexWidget(self.proxy.index(row, 0), DetailButton) @@ -169,9 +146,12 @@ def openImage(self, id): data = retrieveWithConstraint( self.connection, "images", id=int(id), columns=columns ) - except: + except Exception as e: QMessageBox().information( - None, "Warning", "Database connection broken", QMessageBox.Ok + None, + "Warning", + f"Database connection broken due to error {e}", + QMessageBox.Ok, ) try: diff --git a/Gui/QtGUIutils/QtLoginDialog.py b/Gui/QtGUIutils/QtLoginDialog.py index 9107b4ce..99c0ed39 100644 --- a/Gui/QtGUIutils/QtLoginDialog.py +++ b/Gui/QtGUIutils/QtLoginDialog.py @@ -1,50 +1,24 @@ -from PyQt5 import QtCore from PyQt5.QtCore import Qt -#from PyQt5.QtGui import QPixmap + +# from PyQt5.QtGui import QPixmap from PyQt5.QtWidgets import ( - QAbstractItemView, - QApplication, QCheckBox, QComboBox, - QDateTimeEdit, - QDial, QDialog, QGridLayout, QGroupBox, - QHBoxLayout, QLabel, QLineEdit, - QProgressBar, QPushButton, - QRadioButton, - QScrollBar, - QSizePolicy, - QSlider, - QSpinBox, - QStyleFactory, - QTableView, - QTableWidget, - QTabWidget, - QTextEdit, - QHBoxLayout, - QVBoxLayout, - QWidget, - QMainWindow, QMessageBox, - QSplitter, ) -import sys -import os -import subprocess -from subprocess import Popen, PIPE # from Gui.GUIutils.settings import dblist from Gui.GUIutils.DBConnection import ( QtStartConnection, isActive, ) -from Gui.python.logging_config import logger class QtLoginDialog(QDialog): diff --git a/Gui/QtGUIutils/QtMatplotlibUtils.py b/Gui/QtGUIutils/QtMatplotlibUtils.py index afd4445e..4784eb2a 100644 --- a/Gui/QtGUIutils/QtMatplotlibUtils.py +++ b/Gui/QtGUIutils/QtMatplotlibUtils.py @@ -1,33 +1,8 @@ -#from PyQt5.QtCore import * -#from PyQt5.QtGui import QFont, QPixmap +# from PyQt5.QtCore import * +# from PyQt5.QtGui import QFont, QPixmap from PyQt5.QtWidgets import ( - QApplication, - QCheckBox, - QComboBox, - QDateTimeEdit, - QDial, - QDialog, - QGridLayout, - QGroupBox, - QHBoxLayout, - QLabel, - QLineEdit, - QProgressBar, - QPushButton, - QRadioButton, - QScrollBar, QSizePolicy, - QSlider, - QSpinBox, - QStyleFactory, - QTableWidget, - QTabWidget, - QTextEdit, - QHBoxLayout, - QVBoxLayout, QWidget, - QMainWindow, - QMessageBox, ) import matplotlib @@ -38,12 +13,11 @@ import numpy -#from Gui.GUIutils.settings import * +# from Gui.GUIutils.settings import * from Gui.GUIutils.guiUtils import ( isCompositeTest, isSingleTest, ) -from Gui.python.logging_config import logger from InnerTrackerTests.TestSequences import CompositeTests, Test_to_Ph2ACF_Map @@ -71,7 +45,7 @@ def __init__( self.compute_initial_figure() FigureCanvas.__init__(self, self.fig) self.setMinimumHeight(100) - if type(parent) == type(QWidget()): + if type(parent) is type(QWidget()): self.setParent(parent) FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding) FigureCanvas.updateGeometry(self) @@ -80,35 +54,41 @@ def compute_initial_figure(self): self.axes.cla() self.axes.set_xlabel(self.xlabel) self.axes.set_ylabel(self.ylabel) - self.axes.plot(self.X, self.Y, '-x') -# self.axes.plot(self.X, self.Y, color="green", linestyle="dashed", linewidth=3) - + self.axes.plot(self.X, self.Y, "-x") + # self.axes.plot(self.X, self.Y, color="green", linestyle="dashed", linewidth=3) if len(self.X) > 1 and len(self.Y) > 1: - filtered_X = self.X[self.X < -20] filtered_Y = self.Y[self.X < -20] - + if len(filtered_X) > 1 and len(filtered_Y) > 1: - coeffs = numpy.polyfit(filtered_X, filtered_Y, 1) best_fit_line = numpy.poly1d(coeffs) - - + min_x = min(filtered_X) max_x = max(filtered_X) plot_range = numpy.linspace(min_x, max_x, 100) - self.axes.plot(plot_range, best_fit_line(plot_range), color="red", linestyle="dashed") + self.axes.plot( + plot_range, + best_fit_line(plot_range), + color="red", + linestyle="dashed", + ) slope, intercept = coeffs - textbox_text = f'Slope: {slope:.2e} A/V' - self.axes.text(0.05, 0.95, textbox_text, transform=self.axes.transAxes, fontsize=10, - verticalalignment='top', bbox=dict(boxstyle='round,pad=0.5', facecolor='white', alpha=0.5)) + textbox_text = f"Slope: {slope:.2e} A/V" + self.axes.text( + 0.05, + 0.95, + textbox_text, + transform=self.axes.transAxes, + fontsize=10, + verticalalignment="top", + bbox=dict(boxstyle="round,pad=0.5", facecolor="white", alpha=0.5), + ) if self.invert: self.axes.invert_xaxis() self.axes.invert_yaxis() - - def updatePlots(self, points): self.coordinates = points @@ -125,6 +105,7 @@ def saveToSVG(self, output): self.fig.savefig(output, format="svg", dpi=1200) return output + ## Class for Module testing Summary class SummaryCanvas(FigureCanvas): def __init__(self, parent=None, width=5, height=4, dpi=100): @@ -153,7 +134,9 @@ def __init__(self, parent, width=5, height=4, dpi=100): if isCompositeTest(self.parent.info[1]): for i in range(len(CompositeTests[self.parent.info[1]])): - self.xticks.append(Test_to_Ph2ACF_Map[CompositeTests[self.parent.info[1]][i]]) + self.xticks.append( + Test_to_Ph2ACF_Map[CompositeTests[self.parent.info[1]][i]] + ) if isSingleTest(self.parent.info[1]): self.xticks.append(Test_to_Ph2ACF_Map[self.parent.info[1]]) self.grades = self.parent.grades @@ -226,7 +209,9 @@ def renew(self): self.xticks = [""] if isCompositeTest(self.parent.info[1]): for i in range(len(CompositeTests[self.parent.info[1]])): - self.xticks.append(Test_to_Ph2ACF_Map[CompositeTests[self.parent.info[1]][i]]) + self.xticks.append( + Test_to_Ph2ACF_Map[CompositeTests[self.parent.info[1]][i]] + ) if isSingleTest(self.parent.info[1]): self.xticks.append(Test_to_Ph2ACF_Map[self.parent.info[1]]) self.grades = self.parent.grades diff --git a/Gui/QtGUIutils/QtModuleReviewWindow.py b/Gui/QtGUIutils/QtModuleReviewWindow.py index 75acc082..8762f538 100644 --- a/Gui/QtGUIutils/QtModuleReviewWindow.py +++ b/Gui/QtGUIutils/QtModuleReviewWindow.py @@ -1,44 +1,22 @@ -#from PyQt5 import QtCore -#from PyQt5.QtCore import * -#from PyQt5.QtGui import QPixmap +# from PyQt5 import QtCore +# from PyQt5.QtCore import * +# from PyQt5.QtGui import QPixmap from PyQt5.QtWidgets import ( QAbstractItemView, - QApplication, - QCheckBox, QComboBox, - QDateTimeEdit, - QDial, QDialog, QGridLayout, QGroupBox, - QHBoxLayout, QLabel, QLineEdit, - QProgressBar, QPushButton, - QRadioButton, - QScrollBar, - QSizePolicy, - QSlider, - QSpinBox, - QStyleFactory, QTableView, - QTableWidget, - QTabWidget, - QTextEdit, QHBoxLayout, - QVBoxLayout, QWidget, - QMainWindow, - QMessageBox, - QSplitter, ) -import sys -import os import subprocess import hashlib -from subprocess import Popen, PIPE from Gui.GUIutils.DBConnection import ( checkDBConnection, @@ -50,10 +28,12 @@ isActive, GetTBrowser, ) -#from Gui.QtGUIutils.QtStartWindow import * + +# from Gui.QtGUIutils.QtStartWindow import * from Gui.QtGUIutils.QtTableWidget import QtTableWidget from Gui.QtGUIutils.QtLoginDialog import QtLoginDialog -#from Gui.python.ROOTInterface import * + +# from Gui.python.ROOTInterface import * from Gui.python.logging_config import logger @@ -180,7 +160,8 @@ def addButtons(self): for row in range(self.proxy.rowCount()): DetailButton = QPushButton("&Show...") DetailButton.clicked.connect( - lambda state, x="{0}".format( + lambda state, + x="{0}".format( self.proxy.data(self.proxy.index(row, len(self.proxy.dataHeader))) ): self.openDQM(x) ) @@ -410,8 +391,8 @@ def syncDB(self): self.connection, "module_tests", SubmitArgs, Value ) print("trying to insert table") - except: - print("Failed to insert") + except Exception as e: + print(f"Failed to insert due to error {e}") except Exception as err: print("Error: {}".format(repr(err))) diff --git a/Gui/QtGUIutils/QtPowerSuppyConfig.py b/Gui/QtGUIutils/QtPowerSuppyConfig.py index 365b87f8..9cd29812 100644 --- a/Gui/QtGUIutils/QtPowerSuppyConfig.py +++ b/Gui/QtGUIutils/QtPowerSuppyConfig.py @@ -1,43 +1,18 @@ from PyQt5.QtCore import pyqtSignal from PyQt5.QtWidgets import ( - QApplication, - QCheckBox, - QComboBox, - QDateTimeEdit, - QDial, - QDialog, QGridLayout, QGroupBox, - QHBoxLayout, - QLabel, - QLineEdit, - QProgressBar, QPushButton, - QRadioButton, - QScrollBar, - QSizePolicy, - QSlider, - QSpinBox, - QStyleFactory, - QTableWidget, - QTabWidget, - QTextEdit, QHBoxLayout, - QVBoxLayout, QWidget, - QMainWindow, - QMessageBox, ) -import sys -import os import math from Gui.python.CustomizedWidget import StatusBox -#from Gui.GUIutils.DBConnection import * -#from Gui.GUIutils.FirmwareUtil import * -#from Gui.GUIutils.settings import * -from Gui.python.logging_config import logger +# from Gui.GUIutils.DBConnection import * +# from Gui.GUIutils.FirmwareUtil import * +# from Gui.GUIutils.settings import * #!!!!!!!!!!!!!!!!!!!!DEVELOPMENT required!!!!!!!!!!!!!!!!!!!! diff --git a/Gui/QtGUIutils/QtProductionTestWindow.py b/Gui/QtGUIutils/QtProductionTestWindow.py index 49370938..e9ef4f2a 100644 --- a/Gui/QtGUIutils/QtProductionTestWindow.py +++ b/Gui/QtGUIutils/QtProductionTestWindow.py @@ -1,62 +1,27 @@ -from PyQt5 import QtCore from PyQt5.QtCore import pyqtSignal -from PyQt5.QtGui import QPixmap, QTextCursor, QColor, QFont +from PyQt5.QtGui import QFont from PyQt5.QtWidgets import ( - QAbstractItemView, - QApplication, - QCheckBox, - QComboBox, - QDateTimeEdit, - QDial, - QDialog, QGridLayout, QGroupBox, - QHBoxLayout, QLabel, - QLineEdit, - QListWidget, - QPlainTextEdit, - QProgressBar, QPushButton, - QRadioButton, - QScrollBar, - QSizePolicy, - QSlider, - QSpinBox, - QStyleFactory, - QTableView, - QTableWidget, - QTableWidgetItem, QTabWidget, - QTextEdit, - QTreeWidget, QHBoxLayout, QVBoxLayout, QWidget, - QMainWindow, QMessageBox, - QSplitter, ) -import sys -import os -import re -import subprocess -import threading -import time -from datetime import datetime -import random -from subprocess import Popen, PIPE - -#from Gui.GUIutils.DBConnection import * -#from Gui.GUIutils.guiUtils import * + +# from Gui.GUIutils.DBConnection import * +# from Gui.GUIutils.guiUtils import * from Gui.QtGUIutils.QtMatplotlibUtils import ScanCanvas -#from Gui.QtGUIutils.QtLoginDialog import * -#from Gui.python.ResultTreeWidget import * -#from Gui.python.TestValidator import * + +# from Gui.QtGUIutils.QtLoginDialog import * +# from Gui.python.ResultTreeWidget import * +# from Gui.python.TestValidator import * from Gui.python.IVCurveHandler import IVCurveHandler -#from Gui.python.SLDOScanHandler import * -from Gui.python.logging_config import logger +from Gui.python.SLDOScanHandler import SLDOScanHandler class QtProductionTestWindow(QWidget): @@ -241,7 +206,6 @@ def updateMeasurement(self, measureType, measure): self.SLDOScanData.append([Voltage, Current]) self.SLDOScanResult.updatePlots(self.SLDOScanData) self.SLDOScanResult.update() - index = self.MainTabs.indexOf(self.SLDOScanResult) self.MainTabs.clear() self.MainTabs.addTab(self.SLDOScanResult, "SLDO scan") self.MainTabs.setCurrentWidget(self.SLDOScanResult) diff --git a/Gui/QtGUIutils/QtRunWindow.py b/Gui/QtGUIutils/QtRunWindow.py index d4e54050..03d9fb1d 100644 --- a/Gui/QtGUIutils/QtRunWindow.py +++ b/Gui/QtGUIutils/QtRunWindow.py @@ -5,7 +5,6 @@ QCheckBox, QGridLayout, QGroupBox, - QHBoxLayout, QLabel, QPlainTextEdit, QPushButton, @@ -16,10 +15,11 @@ QMessageBox, QSplitter, QProgressBar, - QApplication + QApplication, ) -import os, numpy as np +import os +import numpy as np import threading import Gui.siteSettings as site_settings @@ -27,14 +27,15 @@ from Gui.QtGUIutils.Loading import LoadingThread, LoadingWheel from Gui.QtGUIutils.QtCustomizeWindow import QtCustomizeWindow -#from Gui.QtGUIutils.QtTableWidget import * -#from Gui.QtGUIutils.QtMatplotlibUtils import * -from Gui.QtGUIutils.QtLoginDialog import QtLoginDialog + +# from Gui.QtGUIutils.QtTableWidget import * +# from Gui.QtGUIutils.QtMatplotlibUtils import * from Gui.python.ResultTreeWidget import ResultTreeWidget from Gui.python.TestHandler import TestHandler from Gui.python.logging_config import logger from InnerTrackerTests.TestSequences import CompositeTests + class QtRunWindow(QWidget): resized = pyqtSignal() @@ -48,21 +49,23 @@ def __init__(self, master, info, firmware): self.info = info # Removing for sequencefix -# if "AllScan_Tuning" in self.info: -# runTestList = pretuningList -# runTestList.extend(tuningList * len(defaultTargetThr)) -# runTestList.extend(posttuningList) -# CompositeList.update({"AllScan_Tuning": runTestList}) + # if "AllScan_Tuning" in self.info: + # runTestList = pretuningList + # runTestList.extend(tuningList * len(defaultTargetThr)) + # runTestList.extend(posttuningList) + # CompositeList.update({"AllScan_Tuning": runTestList}) self.ModuleMap = dict() - self.ModuleType = self.firmware[0].getModuleData()['type'] + self.ModuleType = self.firmware[0].getModuleData()["type"] self.RunNumber = "-1" # Add TestProcedureHandler self.testHandler = TestHandler(self, master, info, firmware) if not site_settings.manual_powersupply_control: - assert self.master.instruments is not None, logger.error("Unable to setup instruments") + assert self.master.instruments is not None, logger.error( + "Unable to setup instruments" + ) self.testHandler.powerSignal.connect(self.onPowerSignal) self.GroupBoxSeg = [1, 10, 1] @@ -103,20 +106,28 @@ def __init__(self, master, info, firmware): self.setLayout(self.mainLayout) self.ledMap = { - "off": QPixmap.fromImage(QImage("icons/led-off.png").scaled( - QSize(60, 30), Qt.KeepAspectRatio, Qt.SmoothTransformation) + "off": QPixmap.fromImage( + QImage("icons/led-off.png").scaled( + QSize(60, 30), Qt.KeepAspectRatio, Qt.SmoothTransformation + ) ), - "green": QPixmap.fromImage(QImage("icons/led-green-on.png").scaled( - QSize(60, 30), Qt.KeepAspectRatio, Qt.SmoothTransformation) + "green": QPixmap.fromImage( + QImage("icons/led-green-on.png").scaled( + QSize(60, 30), Qt.KeepAspectRatio, Qt.SmoothTransformation + ) ), - "orange": QPixmap.fromImage(QImage("icons/led-amber-on.png").scaled( - QSize(60, 30), Qt.KeepAspectRatio, Qt.SmoothTransformation) + "orange": QPixmap.fromImage( + QImage("icons/led-amber-on.png").scaled( + QSize(60, 30), Qt.KeepAspectRatio, Qt.SmoothTransformation + ) ), - "red": QPixmap.fromImage(QImage("icons/led-red-on.png").scaled( - QSize(60, 30), Qt.KeepAspectRatio, Qt.SmoothTransformation) + "red": QPixmap.fromImage( + QImage("icons/led-red-on.png").scaled( + QSize(60, 30), Qt.KeepAspectRatio, Qt.SmoothTransformation + ) ), } - + self.setLoginUI() # self.initializeRD53Dict() self.createHeadLine() @@ -126,13 +137,19 @@ def __init__(self, master, info, firmware): self.resized.connect(self.rescaleImage) - def onPowerSignal(self): - starting_voltages = [np.abs(getattr(module["hv"], "voltage")) for module in self.master.instruments._module_dict.values()] + starting_voltages = [ + np.abs(getattr(module["hv"], "voltage")) + for module in self.master.instruments._module_dict.values() + ] self.master.instruments.off( - hv_delay=0.3, hv_step_size=10, measure=False, - execute_each_step=lambda:self.testHandler.ramp_progress_bar(starting_voltages) - ) + hv_delay=0.3, + hv_step_size=10, + measure=False, + execute_each_step=lambda: self.testHandler.ramp_progress_bar( + starting_voltages + ), + ) def setLoginUI(self): X = self.master.dimension.width() / 10 @@ -150,9 +167,7 @@ def createHeadLine(self): self.HeadLayout = QHBoxLayout() - HeadLabel = QLabel( - ' Test: {0} '.format(self.info) - ) + HeadLabel = QLabel(' Test: {0} '.format(self.info)) HeadLabel.setMaximumHeight(30) colorString = "color: green" if self.master.panthera_connected else "color: red" @@ -212,7 +227,7 @@ def createMain(self): self.saveCheckBox.setChecked(False) self.saveCheckBox.setDisabled(True) - if self.master.expertMode == True: + if self.master.expertMode: self.ControlLayout.addWidget(self.RunButton, 0, 0, 1, 1) self.ControlLayout.addWidget(self.AbortButton, 0, 1, 1, 1) self.ControlLayout.addWidget(self.ResetButton, 0, 2, 1, 1) @@ -239,8 +254,8 @@ def createMain(self): ) self.ConsoleViews[i].ensureCursorVisible() self.ConsoleViews[i].setReadOnly(True) - ConsoleLayout.addWidget(QLabel(self.firmware[i].getBoardName()),0,i) - ConsoleLayout.addWidget(self.ConsoleViews[i],1,i) + ConsoleLayout.addWidget(QLabel(self.firmware[i].getBoardName()), 0, i) + ConsoleLayout.addWidget(self.ConsoleViews[i], 1, i) TerminalBox.setLayout(ConsoleLayout) @@ -293,10 +308,15 @@ def createMain(self): self.RampBox = QGroupBox() self.RampLayout = QGridLayout() - self.RampProgressBars = [QProgressBar()]*len(self.master.instruments._module_dict.values()) - RampProgressLabels = [QLabel("Bias Voltage:")]*len(self.master.instruments._module_dict.values()) - for label in RampProgressLabels: label.setStyleSheet("font-weight: bold;") - + self.RampProgressBars = [QProgressBar()] * len( + self.master.instruments._module_dict.values() + ) + RampProgressLabels = [QLabel("Bias Voltage:")] * len( + self.master.instruments._module_dict.values() + ) + for label in RampProgressLabels: + label.setStyleSheet("font-weight: bold;") + for i in range(len(self.master.instruments._module_dict.values())): self.RampLayout.addWidget(RampProgressLabels[i], i, 0, 1, 1) self.RampLayout.addWidget(self.RampProgressBars[i], i, 1, 1, 1) @@ -340,12 +360,12 @@ def destroyMain(self): def upload_to_Panthera_starter(self): self.UploadProgressBar = QProgressBar() self.UploadWheel = LoadingWheel() - self.UploadProgressBar.setFormat(f'0/{len(self.testHandler.modules)} uploaded') - self.StartLayout.insertWidget(1,self.UploadProgressBar) - self.StartLayout.insertWidget(1,self.UploadWheel) + self.UploadProgressBar.setFormat(f"0/{len(self.testHandler.modules)} uploaded") + self.StartLayout.insertWidget(1, self.UploadProgressBar) + self.StartLayout.insertWidget(1, self.UploadWheel) self.AppOption.repaint() - self.Panthera_thread = LoadingThread(self.testHandler.upload_to_Panthera,50) + self.Panthera_thread = LoadingThread(self.testHandler.upload_to_Panthera, 50) self.Panthera_thread.finished.connect(self.UploadWheel.close) self.Panthera_thread.timer.timeout.connect(self.UploadWheel.update_spinner) self.Panthera_thread.timer.start() @@ -410,7 +430,7 @@ def closeWindow(self): self.close() def creatStartWindow(self): - if self.backSignal == True and self.master.expertMode == True: + if self.backSignal and self.master.expertMode: self.master.openNewTest() def occupied(self): @@ -419,7 +439,7 @@ def occupied(self): def release(self): self.testHandler.abortTest() self.master.ProcessingTest = False - if self.master.expertMode == True: + if self.master.expertMode: self.master.NewTestButton.setDisabled(False) self.master.LogoutButton.setDisabled(False) self.master.ExitButton.setDisabled(False) @@ -440,9 +460,7 @@ def refreshHistory(self): row = self.StatusTable.rowCount() self.StatusTable.setRowCount(row + 1) if isCompositeTest(self.info): - self.StatusTable.setItem( - row, 0, QTableWidgetItem(test) - ) + self.StatusTable.setItem(row, 0, QTableWidgetItem(test)) else: self.StatusTable.setItem(row, 0, QTableWidgetItem(self.info)) for module_result in test_results: @@ -451,9 +469,7 @@ def refreshHistory(self): moduleID = f"Module{moduleName}" if moduleID in self.header: columnID = self.header.index(moduleID) - self.StatusTable.setItem( - row, columnID, QTableWidgetItem(status) - ) + self.StatusTable.setItem(row, columnID, QTableWidgetItem(status)) if status == "Pass": self.StatusTable.item(row, columnID).setBackground( QColor(Qt.green) @@ -468,16 +484,18 @@ def refreshHistory(self): def displayTestResultPopup(self, item): try: - row = item.row() #row = index, they are aligned in refreshHistory() + row = item.row() # row = index, they are aligned in refreshHistory() col = item.column() - message = self.modulestatus[row][self.header.index(self.header[col])-1][self.header[col].lstrip("Module")][1] - + message = self.modulestatus[row][self.header.index(self.header[col]) - 1][ + self.header[col].lstrip("Module") + ][1] + msg_box = QMessageBox() msg_box.setWindowTitle("Additional Information") msg_box.setText(message) msg_box.exec_() except KeyError as e: - if e.args[0] != 'TestName': + if e.args[0] != "TestName": raise e def sendBackSignal(self): @@ -559,15 +577,11 @@ def clickedOutputItem(self, qmodelindex): ) self.ReferLabel.setPixmap(self.ReferView) - def updateProgressBar(self, bar:QProgressBar, value:int, text:str): - bar.setFormat(text) - bar.setValue(value) - ####################################################################### ## For real-time terminal display ####################################################################### - def updateConsoleInfo(self, text:str, console:QPlainTextEdit): + def updateConsoleInfo(self, text: str, console: QPlainTextEdit): textCursor = console.textCursor() console.setTextCursor(textCursor) console.appendHtml(text) @@ -597,32 +611,32 @@ def updateIVResult(self, newResult): step, displayDict = newResult self.ResultWidget.updateDisplayList(step, displayDict) - def updateSLDOResult(self, newResult): + def updateSLDOResult(self, newResult): if self.master.expertMode: self.ResultWidget.updateSLDOResult(newResult) else: step, displayDict = newResult self.ResultWidget.updateDisplayList(step, displayDict) - def updateValidation(self, results:list): + def updateValidation(self, results: list): try: self.modulestatus.append(results) except Exception as err: logger.error(err) - def updateFinishedTests(self, tests:list): + def updateFinishedTests(self, tests: list): try: self.finished_tests = tests except Exception as err: logger.error(err) - def updateProgressBar(self, bar:QProgressBar, value:int, text:str): + def updateProgressBar(self, bar: QProgressBar, value: int, text: str): bar.setFormat(text) bar.setValue(value) - QApplication.processEvents() #So the "window not responding" popup doesn't appear - #QApplication.processEvents() is unideal though. It would have been better to - #run tests in a QThread, so we don't have to keep pinging the GUI. - #But ion finna make that happen. + QApplication.processEvents() # So the "window not responding" popup doesn't appear + # QApplication.processEvents() is unideal though. It would have been better to + # run tests in a QThread, so we don't have to keep pinging the GUI. + # But ion finna make that happen. ####################################################################### ## For real-time terminal display @@ -651,7 +665,7 @@ def setAutoSave(self): self.saveCheckBox.setChecked(self.testHandler.autoSave) def closeEvent(self, event): - if self.processingFlag == True: + if self.processingFlag: event.ignore() else: @@ -666,15 +680,25 @@ def closeEvent(self, event): if reply == QMessageBox.Yes: self.release() if self.master.instruments: - starting_voltages = [np.abs(getattr(module["hv"], "voltage")) for module in self.master.instruments._module_dict.values()] + starting_voltages = [ + np.abs(getattr(module["hv"], "voltage")) + for module in self.master.instruments._module_dict.values() + ] self.master.instruments.off( - hv_delay=0.3, hv_step_size=10, execute_each_step=lambda:self.testHandler.ramp_progress_bar(starting_voltages) + hv_delay=0.3, + hv_step_size=10, + execute_each_step=lambda: self.testHandler.ramp_progress_bar( + starting_voltages + ), ) else: - QMessageBox.information(self, "Info", "You must turn off " - "instruments manually", - QMessageBox.Ok) + QMessageBox.information( + self, + "Info", + "You must turn off instruments manually", + QMessageBox.Ok, + ) event.accept() else: self.backSignal = False - event.ignore() \ No newline at end of file + event.ignore() diff --git a/Gui/QtGUIutils/QtStartWindow.py b/Gui/QtGUIutils/QtStartWindow.py index e6a19bcc..4c5bcaad 100644 --- a/Gui/QtGUIutils/QtStartWindow.py +++ b/Gui/QtGUIutils/QtStartWindow.py @@ -1,61 +1,24 @@ +import os +import math +import subprocess import logging -# Customize the logging configuration -logging.basicConfig( - level=logging.INFO, - format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", - filename="my_project.log", # Specify a log file - filemode="w", # 'w' for write, 'a' for append -) - -logger = logging.getLogger(__name__) - -from PyQt5.QtCore import QSize, Qt, pyqtSignal, QThread +from PyQt5.QtCore import QSize, Qt, pyqtSignal from PyQt5.QtGui import QPixmap, QImage from PyQt5.QtWidgets import ( - QApplication, - QCheckBox, QComboBox, - QDateTimeEdit, - QDial, - QDialog, QGridLayout, QGroupBox, - QHBoxLayout, QLabel, - QLineEdit, - QProgressBar, QPushButton, - QRadioButton, - QScrollBar, - QSizePolicy, - QSlider, - QSpinBox, - QStyleFactory, - QTableWidget, - QTabWidget, - QTextEdit, QHBoxLayout, - QVBoxLayout, QWidget, - QMainWindow, QMessageBox, ) - - -import sys -import os -import math -import subprocess -import time - from Gui.QtGUIutils.QtRunWindow import QtRunWindow from Gui.QtGUIutils.Loading import LoadingThread from Gui.QtGUIutils.QtFwCheckDetails import QtFwCheckDetails -#from Gui.QtGUIutils.QtApplication import * from Gui.python.CustomizedWidget import BeBoardBox -#from Gui.python.Firmware import * -#from Gui.GUIutils.DBConnection import * from Gui.GUIutils.FirmwareUtil import FEPowerUpVD from Gui.GUIutils.settings import firmware_image, ModuleLaneMap from Gui.siteSettings import ( @@ -66,6 +29,23 @@ from InnerTrackerTests.TestSequences import TestList from siteSettings import icicle_instrument_setup + +# Customize the logging configuration +logging.basicConfig( + level=logging.INFO, + format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", + filename="my_project.log", # Specify a log file + filemode="w", # 'w' for write, 'a' for append +) + +logger = logging.getLogger(__name__) + + +# from Gui.QtGUIutils.QtApplication import * + +# from Gui.python.Firmware import * +# from Gui.GUIutils.DBConnection import * + # from Gui.QtGUIutils.QtProductionTestWindow import * @@ -80,7 +60,7 @@ def __init__(self, master, module, index=0): self.chipSwitches = {} self.mainLayout = QGridLayout() - + self.initResult() self.createBody() if icicle_instrument_setup is not None: @@ -104,7 +84,7 @@ def createBody(self): # self.ChipBoxWidget = ChipBox(self.module.getType()) self.CheckLabel = QLabel() - + self.mainLayout.addWidget(PowerModeLabel, 1, 0, 1, 1) self.mainLayout.addWidget(self.PowerModeCombo, 1, 1, 1, 1) self.mainLayout.addWidget(self.CheckLabel, 2, 0, 1, 1) @@ -118,33 +98,35 @@ def measureFwPar(self): "Set LV Current (A)", ] for item in measureList: - if 'LV Current' in item: + if "LV Current" in item: value[item] = ModuleCurrentMap[self.module.getType()] - if 'Bias Voltage' in item: - value[item] = icicle_instrument_setup['instrument_dict']['hv']['default_voltage'] - #assumes only 1 HV titled 'hv' in instruments.json + if "Bias Voltage" in item: + value[item] = icicle_instrument_setup["instrument_dict"]["hv"][ + "default_voltage" + ] + # assumes only 1 HV titled 'hv' in instruments.json self.verboseResult[key] = value @staticmethod def checkFwPar(pfirmwareName, module_type, fc7_ip): # To be finished try: - #self.result = True + # self.result = True FWisPresent = False boardtype = "RD53B" if "CROC" in module_type: boardtype = "RD53B" else: boardtype = "RD53A" - print('board type is: {0}'.format(boardtype)) + print("board type is: {0}".format(boardtype)) # updating uri value in template xml file with correct fc7 ip address, as specified in siteSettings.py - #fc7_ip = site_settings.FC7List[pfirmwareName] #Commented because I don't think we need it. Remove line after test. - print('The fc7 ip is: {0}'.format(fc7_ip)) - uricmd = "sed -i -e 's/fc7-1/{0}/g' {1}/Gui/CMSIT_{2}.xml".format( + # fc7_ip = site_settings.FC7List[pfirmwareName] #Commented because I don't think we need it. Remove line after test. + print("The fc7 ip is: {0}".format(fc7_ip)) + uricmd = "sed -i -e 's/fc7-1/{0}/g' {1}/Gui/CMSIT_{2}.xml".format( fc7_ip, os.environ.get("GUI_dir"), boardtype ) - updateuri = subprocess.call([uricmd], shell=True) - print('updated the uri value') + subprocess.call([uricmd], shell=True) + print("updated the uri value") firmwareImage = firmware_image[module_type][ os.environ.get("Ph2_ACF_VERSION") ] @@ -180,7 +162,8 @@ def checkFwPar(pfirmwareName, module_type, fc7_ip): [ "fpgaconfig", "-c", - os.environ.get("GUI_dir") + "/Gui/CMSIT_{}.xml".format(boardtype), + os.environ.get("GUI_dir") + + "/Gui/CMSIT_{}.xml".format(boardtype), "-f", "{}".format( os.environ.get("GUI_dir") @@ -196,12 +179,12 @@ def checkFwPar(pfirmwareName, module_type, fc7_ip): # self.fw_process.start("fpgaconfig",["-c","CMSIT.xml","-f","{}".format(os.environ.get("GUI_dir")+'/FirmwareImages/' + self.firmwareImage),"-i","{}".format(self.firmwareImage)]) print(fwsave.stdout.decode("UTF-8")) FWisPresent = True - except: + except OSError: print( "unable to save {0} to FC7 SD card".format( os.environ.get("GUI_dir") + "/FirmwareImages/" - + self.firmwareImage + + firmwareImage ) ) @@ -211,7 +194,8 @@ def checkFwPar(pfirmwareName, module_type, fc7_ip): [ "fpgaconfig", "-c", - os.environ.get("GUI_dir") + "/Gui/CMSIT_{}.xml".format(boardtype), + os.environ.get("GUI_dir") + + "/Gui/CMSIT_{}.xml".format(boardtype), "-i", "{}".format(firmwareImage), ], @@ -220,9 +204,17 @@ def checkFwPar(pfirmwareName, module_type, fc7_ip): ) print(fwload.stdout.decode("UTF-8")) print("resetting beboard") - print(f'command: CMSITminiDAQ -f {os.environ.get("GUI_dir") + "/Gui/CMSIT_{}.xml".format(boardtype)} -r') + print( + f"command: CMSITminiDAQ -f {os.environ.get('GUI_dir') + '/Gui/CMSIT_{}.xml'.format(boardtype)} -r" + ) fwreset = subprocess.run( - ["CMSITminiDAQ", "-f", os.environ.get("GUI_dir") + "/Gui/CMSIT_{}.xml".format(boardtype), "-r"], + [ + "CMSITminiDAQ", + "-f", + os.environ.get("GUI_dir") + + "/Gui/CMSIT_{}.xml".format(boardtype), + "-r", + ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) @@ -233,9 +225,9 @@ def checkFwPar(pfirmwareName, module_type, fc7_ip): logging.debug("Made it to turn on LV") return True except Exception as err: - #self.result = False - #self.CheckLabel.setText("No measurement") - #self.CheckLabel.setStyleSheet("color:red") + # self.result = False + # self.CheckLabel.setText("No measurement") + # self.CheckLabel.setStyleSheet("color:red") print(err) return False @@ -261,6 +253,7 @@ def release(self): class QtStartWindow(QWidget): openRunWindowSignal = pyqtSignal() errorMessageBoxSignal = pyqtSignal(str) + def __init__(self, master, firmware): super(QtStartWindow, self).__init__() self.master = master @@ -277,8 +270,8 @@ def __init__(self, master, firmware): self.loading_counter = 0 self.openRunWindowSignal.connect(self.openRunWindowGUI) - self.errorMessageBoxSignal.connect( lambda message : - QMessageBox.information( + self.errorMessageBoxSignal.connect( + lambda message: QMessageBox.information( None, "Error", message, @@ -301,7 +294,7 @@ def createHead(self): testlayout = QGridLayout() TestLabel = QLabel("Test:") self.TestCombo = QComboBox() - #self.TestList = getAllTests(self.master.connection) + # self.TestList = getAllTests(self.master.connection) self.TestList = TestList if not self.master.instruments: if "AllScan" in self.TestList: @@ -321,7 +314,7 @@ def createHead(self): for beboard in self.firmware: beboard.removeModules() beboard.removeAllOpticalGroups() - + self.BeBoardWidget = BeBoardBox(self.master, self.firmware) # FLAG self.mainLayout.addWidget(self.TestBox, 0, 0) @@ -369,8 +362,8 @@ def createApp(self): self.StartLayout.addStretch(1) self.StartLayout.addWidget(self.CancelButton) - #self.StartLayout.addWidget(self.ResetButton) - #self.StartLayout.addWidget(self.CheckButton) + # self.StartLayout.addWidget(self.ResetButton) + # self.StartLayout.addWidget(self.CheckButton) self.StartLayout.addWidget(self.NextButton) self.AppOption.setLayout(self.StartLayout) @@ -418,9 +411,11 @@ def release(self): def checkFwPar(self, pfirmwareName): GlobalCheck = True for item in self.ModuleList: - #item.checkFwPar(pfirmwareName, item.module.getType()) - GlobalCheck = GlobalCheck and item.checkFwPar(pfirmwareName, item.module.getType(), FC7List[pfirmwareName]) - #GlobalCheck = GlobalCheck and item.getResult() + # item.checkFwPar(pfirmwareName, item.module.getType()) + GlobalCheck = GlobalCheck and item.checkFwPar( + pfirmwareName, item.module.getType(), FC7List[pfirmwareName] + ) + # GlobalCheck = GlobalCheck and item.getResult() self.passCheck = GlobalCheck return GlobalCheck @@ -429,13 +424,15 @@ def setupBeBoard(self): pass def loader(self): - self.NextButton.setText(". "*(self.loading_counter+1)) - self.loading_counter = (self.loading_counter + 1)%3 + self.NextButton.setText(". " * (self.loading_counter + 1)) + self.loading_counter = (self.loading_counter + 1) % 3 def openRunWindow_starter(self): self.NextButton.setText(". . .") - self.run_window_thread = LoadingThread(self.openRunWindow,500) - self.run_window_thread.finished.connect(lambda : self.NextButton.setText("&Next")) + self.run_window_thread = LoadingThread(self.openRunWindow, 500) + self.run_window_thread.finished.connect( + lambda: self.NextButton.setText("&Next") + ) self.run_window_thread.timer.timeout.connect(self.loader) self.run_window_thread.timer.start() self.run_window_thread.start() @@ -454,22 +451,26 @@ def openRunWindow(self): for module in self.BeBoardWidget.getModules(): if module.getSerialNumber() == "": - self.master.errorMessageBoxSignal.emit("No valid serial number!",) #Needs to be in a signal or QThread throws an error + self.master.errorMessageBoxSignal.emit( + "No valid serial number!", + ) # Needs to be in a signal or QThread throws an error return if module.getFMCPort() == "": self.master.errorMessageBoxSignal.emit("No valid ID!") return self.firmwareDescription, message = self.BeBoardWidget.getFirmwareDescription() - - if not self.firmwareDescription: #firmware description returns none if no modules are entered + + if ( + not self.firmwareDescription + ): # firmware description returns none if no modules are entered self.master.errorMessageBoxSignal.emit(message) return for fw in self.firmwareDescription: self.checkFwPar(fw.getBoardName()) - if self.passCheck == False: - reply = QMessageBox().question( #For some reason this isn't an issue for QThread + if not self.passCheck: + reply = QMessageBox().question( # For some reason this isn't an issue for QThread None, "Error", "Front-End parameter check failed, forced to continue?", @@ -478,19 +479,19 @@ def openRunWindow(self): ) if reply == QMessageBox.No: return - + for beboard in self.firmwareDescription: print(beboard) - + self.info = self.TestCombo.currentText() - + self.runFlag = True self.master.BeBoardWidget = self.BeBoardWidget self.openRunWindowSignal.emit() self.close() def closeEvent(self, event): - if self.runFlag == True: + if self.runFlag: event.accept() else: @@ -508,14 +509,14 @@ def closeEvent(self, event): # This line was previosly commented try: if self.master.instruments: - self.master.instruments.off( - hv_delay=0.5, hv_step_size=10 - ) + self.master.instruments.off(hv_delay=0.5, hv_step_size=10) print("Window closed") else: - logger.info(" You are running in manual mode." - " You must turn off powers supplies yourself.") + logger.info( + " You are running in manual mode." + " You must turn off powers supplies yourself." + ) except Exception as e: print( "Waring: Incident detected while trying to turn of power supply, please check power status" diff --git a/Gui/QtGUIutils/QtSummaryWindow.py b/Gui/QtGUIutils/QtSummaryWindow.py index 0f24814c..dbb46ce5 100644 --- a/Gui/QtGUIutils/QtSummaryWindow.py +++ b/Gui/QtGUIutils/QtSummaryWindow.py @@ -1,41 +1,18 @@ -#from PyQt5.QtCore import * -from PyQt5.QtGui import QFont, QPixmap +# from PyQt5.QtCore import * +from PyQt5.QtGui import QFont from PyQt5.QtWidgets import ( - QApplication, QCheckBox, - QComboBox, - QDateTimeEdit, - QDial, - QDialog, QGridLayout, QGroupBox, - QHBoxLayout, QLabel, - QLineEdit, - QProgressBar, QPushButton, - QRadioButton, - QScrollBar, - QSizePolicy, - QSlider, - QSpinBox, - QStyleFactory, - QTableWidget, - QTabWidget, - QTextEdit, QHBoxLayout, QVBoxLayout, QWidget, - QMainWindow, - QMessageBox, ) -import sys -import os -import numpy from Gui.QtGUIutils.QtMatplotlibUtils import SummaryCanvas -from Gui.python.logging_config import logger class QtSummaryWindow(QWidget): @@ -89,7 +66,9 @@ def createChecks(self): self.OptionBox = QGroupBox() CheckBoxLayout = QHBoxLayout() - for site in self.SiteList: #this is the only accessible SiteList reference I could find + for site in ( + self.SiteList + ): # this is the only accessible SiteList reference I could find checkBox = QCheckBox("&{0}".format(site)) self.checkboxs.append(checkBox) CheckBoxLayout.addWidget(checkBox) diff --git a/Gui/QtGUIutils/QtTCanvasWidget.py b/Gui/QtGUIutils/QtTCanvasWidget.py index 7ed27af5..33046096 100644 --- a/Gui/QtGUIutils/QtTCanvasWidget.py +++ b/Gui/QtGUIutils/QtTCanvasWidget.py @@ -1,43 +1,10 @@ -from PyQt5 import QtCore from PyQt5.QtCore import pyqtSignal -from PyQt5.QtGui import QPixmap, QTextCursor from PyQt5.QtWidgets import ( - QAbstractItemView, - QApplication, - QCheckBox, - QComboBox, - QDateTimeEdit, - QDial, - QDialog, QGridLayout, - QGroupBox, - QHBoxLayout, QLabel, - QLineEdit, - QListWidget, - QPlainTextEdit, - QProgressBar, - QPushButton, - QRadioButton, - QScrollBar, - QSizePolicy, - QSlider, - QSpinBox, - QStyleFactory, - QTableView, - QTableWidget, - QTabWidget, - QTextEdit, - QTreeWidget, - QHBoxLayout, - QVBoxLayout, QWidget, - QMainWindow, - QMessageBox, - QSplitter, ) from PyQt5 import QtSvg -from Gui.python.logging_config import logger class QtTCanvasWidget(QWidget): diff --git a/Gui/QtGUIutils/QtTableWidget.py b/Gui/QtGUIutils/QtTableWidget.py index 65538d64..3cd823c5 100644 --- a/Gui/QtGUIutils/QtTableWidget.py +++ b/Gui/QtGUIutils/QtTableWidget.py @@ -1,47 +1,11 @@ from PyQt5 import QtCore from PyQt5.QtCore import QSortFilterProxyModel, pyqtSignal -from PyQt5.QtGui import QBrush, QColor, QPixmap, QStandardItemModel, QStandardItem -from PyQt5.QtWidgets import ( - QApplication, - QCheckBox, - QComboBox, - QDateTimeEdit, - QDial, - QDialog, - QGridLayout, - QGroupBox, - QHBoxLayout, - QLabel, - QLineEdit, - QProgressBar, - QPushButton, - QRadioButton, - QScrollBar, - QSizePolicy, - QSlider, - QSpinBox, - QStyleFactory, - QTableView, - QTableWidget, - QTabWidget, - QTextEdit, - QHBoxLayout, - QVBoxLayout, - QWidget, - QMainWindow, - QMessageBox, - QSplitter, -) - -import sys -import os -import subprocess -from subprocess import Popen, PIPE - -#from Gui.GUIutils.DBConnection import * -#from Gui.GUIutils.guiUtils import * -#from Gui.GUIutils.settings import * -from Gui.python.logging_config import logger +from PyQt5.QtGui import QBrush, QColor, QStandardItemModel, QStandardItem + + +# from Gui.GUIutils.DBConnection import * +# from Gui.GUIutils.guiUtils import * +# from Gui.GUIutils.settings import * Color = { "Local": QColor(255, 0, 0), diff --git a/Gui/QtGUIutils/QtViewTableTab.py b/Gui/QtGUIutils/QtViewTableTab.py index 908cfeee..e7376efa 100644 --- a/Gui/QtGUIutils/QtViewTableTab.py +++ b/Gui/QtGUIutils/QtViewTableTab.py @@ -1,40 +1,17 @@ -#from PyQt5.QtCore import * -#from PyQt5.QtGui import QFont, QPixmap +# from PyQt5.QtCore import * +# from PyQt5.QtGui import QFont, QPixmap from PyQt5.QtWidgets import ( QAbstractItemView, - QApplication, - QCheckBox, QComboBox, - QDateTimeEdit, - QDial, - QDialog, QGridLayout, QGroupBox, - QHBoxLayout, QLabel, QLineEdit, - QProgressBar, QPushButton, - QRadioButton, - QScrollBar, - QSizePolicy, - QSlider, - QSpinBox, - QStyleFactory, QTableView, - QTableWidget, - QTabWidget, - QTextEdit, - QHBoxLayout, - QVBoxLayout, QWidget, - QMainWindow, - QMessageBox, ) -import sys -import os -import numpy from Gui.GUIutils.DBConnection import ( getTableList, @@ -43,9 +20,9 @@ retrieveGenericTable, ) import mysql.connector -#from Gui.GUIutils.guiUtils import * + +# from Gui.GUIutils.guiUtils import * from Gui.QtGUIutils.QtDBTableWidget import QtDBTableWidget -from Gui.python.logging_config import logger class QtViewTableTab(QWidget): @@ -130,8 +107,8 @@ def viewBox(self, dataList=[]): self.ViewLayout.addWidget(comboBox, 0, 2, 1, 1) self.ViewLayout.addWidget(label, 0, 0, 1, 1) - except: - print("Error: failed to create viewBox") + except Exception as e: + print(f"Error: failed to create viewBox due to error: {e}") self.ViewBox.setLayout(self.ViewLayout) self.mainlayout.addWidget(self.ViewBox, 1, 0, 2, 1) diff --git a/Gui/QtGUIutils/QtuDTCDialog.py b/Gui/QtGUIutils/QtuDTCDialog.py index d8888a0c..995875a2 100644 --- a/Gui/QtGUIutils/QtuDTCDialog.py +++ b/Gui/QtGUIutils/QtuDTCDialog.py @@ -2,47 +2,23 @@ # from PyQt5.QtCore import * # from PyQt5.QtGui import QPixmap from PyQt5.QtWidgets import ( - QAbstractItemView, - QApplication, - QCheckBox, QComboBox, - QDateTimeEdit, - QDial, QDialog, QGridLayout, QGroupBox, - QHBoxLayout, QLabel, - QLineEdit, - QProgressBar, QPushButton, - QRadioButton, - QScrollBar, - QSizePolicy, - QSlider, - QSpinBox, - QStyleFactory, - QTableView, - QTableWidget, - QTabWidget, - QTextEdit, - QHBoxLayout, - QVBoxLayout, - QWidget, - QMainWindow, - QMessageBox, - QSplitter, ) -import sys import os import subprocess -from subprocess import Popen, PIPE +from subprocess import PIPE from Gui.python.logging_config import logger -#from Gui.GUIutils.settings import * + +# from Gui.GUIutils.settings import * from Configuration.XMLUtil import LoadXML -#from Gui.python.Firmware import * +# from Gui.python.Firmware import * class QtuDTCDialog(QDialog): @@ -94,20 +70,20 @@ def createMain(self): def fetchFPGAConfigs(self): try: - InputFile = os.environ.get("PH2ACF_BASE_DIR") + f"/settings/CMSIT_{self.module[1].getBoardName()}.xml" + InputFile = ( + os.environ.get("PH2ACF_BASE_DIR") + + f"/settings/CMSIT_{self.module[1].getBoardName()}.xml" + ) root, tree = LoadXML(InputFile) fwIP = self.module.getIPAddress() - changeMade = False for Node in root.findall(".//connection"): if fwIP not in Node.attrib["uri"]: Node.set( "uri", "chtcp-2.0://localhost:10203?target={}:50001".format(fwIP), ) - changeMade = True for Node in root.findall(".//RD53"): Node.set("configfile", "../Configuration/CMSIT_RD53.txt") - changeMode = True # if changeMode: # xml_output = ET.tostring(root,pretty_print=True) # print(xml_output) @@ -157,7 +133,8 @@ def configFwImage(self): [ "fpgaconfig", "-c", - os.environ.get("PH2ACF_BASE_DIR") + f"/settings/CMSIT_{self.module[1].getBoardName()}.xml.gui", + os.environ.get("PH2ACF_BASE_DIR") + + f"/settings/CMSIT_{self.module[1].getBoardName()}.xml.gui", "-i", self.uDTCFile, ], diff --git a/Gui/QtGUIutils/TessieCoolingApp.py b/Gui/QtGUIutils/TessieCoolingApp.py index 568514fc..37275913 100644 --- a/Gui/QtGUIutils/TessieCoolingApp.py +++ b/Gui/QtGUIutils/TessieCoolingApp.py @@ -2,6 +2,7 @@ from PyQt5.QtWidgets import QWidget from PyQt5.QtCore import Qt + class Tessie(QWidget): def __init__(self, dimension): super(Tessie, self).__init__() @@ -9,15 +10,18 @@ def __init__(self, dimension): self.show() def setupUi(self): - self.gridLayout = QtWidgets.QGridLayout(self) self.upperWidget = QWidget() - self.upperGridLayout = QtWidgets.QGridLayout(self.upperWidget) # Set layout here + self.upperGridLayout = QtWidgets.QGridLayout( + self.upperWidget + ) # Set layout here self.upperWidget.setLayout(self.upperGridLayout) self.lowerWidget = QWidget() - self.lowerGridLayout = QtWidgets.QGridLayout(self.lowerWidget) # Set layout here + self.lowerGridLayout = QtWidgets.QGridLayout( + self.lowerWidget + ) # Set layout here self.lowerWidget.setLayout(self.lowerGridLayout) self.gridLayout.addWidget(self.upperWidget, 0, 0) @@ -32,80 +36,97 @@ def setupUi(self): self.runtimeLabel = QtWidgets.QLabel("Runtime") self.statusLabel = QtWidgets.QLabel("Status") - self.upperGridLayout.addWidget(self.TessieLabel, 0,0,1,2) - self.upperGridLayout.addWidget(self.CANbus_errors_label, 1,0,1,1) - self.upperGridLayout.addWidget(self.I2C_errors_label, 2,0,1,1) - self.upperGridLayout.addWidget(self.runtimeLabel, 3,0,1,1) - self.upperGridLayout.addWidget(self.statusLabel, 4,0,1,1) + self.upperGridLayout.addWidget(self.TessieLabel, 0, 0, 1, 2) + self.upperGridLayout.addWidget(self.CANbus_errors_label, 1, 0, 1, 1) + self.upperGridLayout.addWidget(self.I2C_errors_label, 2, 0, 1, 1) + self.upperGridLayout.addWidget(self.runtimeLabel, 3, 0, 1, 1) + self.upperGridLayout.addWidget(self.statusLabel, 4, 0, 1, 1) self.CANbus_errors_edit = QtWidgets.QLineEdit("0") self.I2C_errors_edit = QtWidgets.QLineEdit("0") self.runtimeEdit = QtWidgets.QLineEdit("10346") self.statusEdit = QtWidgets.QLineEdit("no problem") - self.upperGridLayout.addWidget(self.CANbus_errors_edit, 1,1,1,1) - self.upperGridLayout.addWidget(self.I2C_errors_edit, 2,1,1,1) - self.upperGridLayout.addWidget(self.runtimeEdit, 3,1,1,1) - self.upperGridLayout.addWidget(self.statusEdit, 4,1,1,1) + self.upperGridLayout.addWidget(self.CANbus_errors_edit, 1, 1, 1, 1) + self.upperGridLayout.addWidget(self.I2C_errors_edit, 2, 1, 1, 1) + self.upperGridLayout.addWidget(self.runtimeEdit, 3, 1, 1, 1) + self.upperGridLayout.addWidget(self.statusEdit, 4, 1, 1, 1) self.upperGridLayout.setColumnMinimumWidth(1, 75) - self.airLabel = QtWidgets.QLabel("Air [° C]") self.waterLabel = QtWidgets.QLabel("Water [° C]") self.lid_status_label = QtWidgets.QLabel("Lid Status") - self.upperGridLayout.addWidget(self.airLabel, 1,2,1,1) - self.upperGridLayout.addWidget(self.waterLabel, 2,2,1,1) - self.upperGridLayout.addWidget(self.lid_status_label, 3,2,1,1) + self.upperGridLayout.addWidget(self.airLabel, 1, 2, 1, 1) + self.upperGridLayout.addWidget(self.waterLabel, 2, 2, 1, 1) + self.upperGridLayout.addWidget(self.lid_status_label, 3, 2, 1, 1) self.airEdit = QtWidgets.QLineEdit("23.25") self.waterEdit = QtWidgets.QLineEdit("21.34") self.lid_status_edit = QtWidgets.QLineEdit("locked") - self.airEdit.setStyleSheet("QLineEdit { background-color: green; color: black; }") - self.waterEdit.setStyleSheet("QLineEdit { background-color: green; color: black; }") - self.lid_status_edit.setStyleSheet("QLineEdit { background-color: green; color: black; }") - - self.upperGridLayout.addWidget(self.airEdit, 1,3,1,1) - self.upperGridLayout.addWidget(self.waterEdit, 2,3,1,1) - self.upperGridLayout.addWidget(self.lid_status_edit, 3,3,1,1) + self.airEdit.setStyleSheet( + "QLineEdit { background-color: green; color: black; }" + ) + self.waterEdit.setStyleSheet( + "QLineEdit { background-color: green; color: black; }" + ) + self.lid_status_edit.setStyleSheet( + "QLineEdit { background-color: green; color: black; }" + ) + + self.upperGridLayout.addWidget(self.airEdit, 1, 3, 1, 1) + self.upperGridLayout.addWidget(self.waterEdit, 2, 3, 1, 1) + self.upperGridLayout.addWidget(self.lid_status_edit, 3, 3, 1, 1) self.upperGridLayout.setColumnMinimumWidth(3, 50) self.ref_hum_label = QtWidgets.QLabel("Ref. Hum.") self.dew_point_label = QtWidgets.QLabel("Dew Point") - self.upperGridLayout.addWidget(self.ref_hum_label, 1,4,1,1) - self.upperGridLayout.addWidget(self.dew_point_label, 2,4,1,1) + self.upperGridLayout.addWidget(self.ref_hum_label, 1, 4, 1, 1) + self.upperGridLayout.addWidget(self.dew_point_label, 2, 4, 1, 1) self.ref_hum_edit = QtWidgets.QLineEdit("51.92") self.dew_point_edit = QtWidgets.QLineEdit("12.83") - self.ref_hum_edit.setStyleSheet("QLineEdit { background-color: yellow; color: black; }") - self.dew_point_edit.setStyleSheet("QLineEdit { background-color: green; color: black; }") + self.ref_hum_edit.setStyleSheet( + "QLineEdit { background-color: yellow; color: black; }" + ) + self.dew_point_edit.setStyleSheet( + "QLineEdit { background-color: green; color: black; }" + ) - self.upperGridLayout.addWidget(self.ref_hum_edit, 1,5,1,1) - self.upperGridLayout.addWidget(self.dew_point_edit, 2,5,1,1) + self.upperGridLayout.addWidget(self.ref_hum_edit, 1, 5, 1, 1) + self.upperGridLayout.addWidget(self.dew_point_edit, 2, 5, 1, 1) self.upperGridLayout.setColumnMinimumWidth(5, 50) self.stop_all_button = QtWidgets.QPushButton("STOP ALL") - self.stop_all_button.setStyleSheet("QPushButton {background-color: red; color: black}") + self.stop_all_button.setStyleSheet( + "QPushButton {background-color: red; color: black}" + ) self.upperGridLayout.addWidget(self.stop_all_button, 4, 2, 1, 4) self.flushButton = QtWidgets.QPushButton("Flush") self.rinseButton = QtWidgets.QPushButton("Rinse") - self.lowerGridLayout.addWidget(self.flushButton, 0,0) - self.lowerGridLayout.addWidget(self.rinseButton, 1,0) + self.lowerGridLayout.addWidget(self.flushButton, 0, 0) + self.lowerGridLayout.addWidget(self.rinseButton, 1, 0) - self.setTemperatures = [1]*8 - self.TEC_labels = [QtWidgets.QLabel(f'TEC {i}:') for i in range(1,9)] - self.TEC_edits = [QtWidgets.QLineEdit(f'{self.setTemperatures[i]}') for i in range(8)] + self.setTemperatures = [1] * 8 + self.TEC_labels = [QtWidgets.QLabel(f"TEC {i}:") for i in range(1, 9)] + self.TEC_edits = [ + QtWidgets.QLineEdit(f"{self.setTemperatures[i]}") for i in range(8) + ] for i in range(4): - self.lowerGridLayout.addWidget(self.TEC_labels[8-i-1],0,2*i+1,1,1,Qt.AlignRight) - self.lowerGridLayout.addWidget(self.TEC_edits[8-i-1],0,2*i+2) - self.lowerGridLayout.addWidget(self.TEC_labels[i], 1, 2*i+1,1,1,Qt.AlignRight) - self.lowerGridLayout.addWidget(self.TEC_edits[i], 1, 2*i+2) + self.lowerGridLayout.addWidget( + self.TEC_labels[8 - i - 1], 0, 2 * i + 1, 1, 1, Qt.AlignRight + ) + self.lowerGridLayout.addWidget(self.TEC_edits[8 - i - 1], 0, 2 * i + 2) + self.lowerGridLayout.addWidget( + self.TEC_labels[i], 1, 2 * i + 1, 1, 1, Qt.AlignRight + ) + self.lowerGridLayout.addWidget(self.TEC_edits[i], 1, 2 * i + 2) self.setLayout(self.gridLayout) diff --git a/Gui/database.py b/Gui/database.py index 8e1a8bb2..a3772ca8 100644 --- a/Gui/database.py +++ b/Gui/database.py @@ -1,60 +1,58 @@ - import logging +import config +import sqlite3 # Customize the logging configuration logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', - filename='my_project.log', # Specify a log file - filemode='w' # 'w' for write, 'a' for append + level=logging.INFO, + format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", + filename="my_project.log", # Specify a log file + filemode="w", # 'w' for write, 'a' for append ) logger = logging.getLogger(__name__) -''' +""" database.py brief Functions for database interfacing author Brandon Manley version 0.1 date 06/08/20 Support: email to manley.329@osu.edu -''' - -import config -import sqlite3 -from sqlite3 import Error +""" def createDatabaseConnection(db_file): conn = None - try: + try: conn = sqlite3.connect(db_file) - except: + except Exception as e: + print(f"Failed to connect to database due to error: {e}") pass return conn def createTestsTable(): - conn = createDatabaseConnection(config.database) - sql = ''' CREATE TABLE IF NOT EXISTS tests ( + sql = """ CREATE TABLE IF NOT EXISTS tests ( id integer PRIMARY KEY, module_id integer, user_name text, test_name text, date text, grade integer - ); ''' + ); """ try: c = conn.cursor() c.execute(sql) - except: + except Exception as e: + print(f"Failed to create test table due to error: {e}") pass def createTestEntry(runInfo): - sql = ''' INSERT INTO tests(module_id,user_name,test_name,date,grade) - VALUES(?,?,?,?,?) ''' + sql = """ INSERT INTO tests(module_id,user_name,test_name,date,grade) + VALUES(?,?,?,?,?) """ conn = createDatabaseConnection(config.database) cur = conn.cursor() cur.execute(sql, runInfo) @@ -63,13 +61,13 @@ def createTestEntry(runInfo): def updateTestEntry(newInfo): - sql = ''' UPDATE tests + sql = """ UPDATE tests SET module_id = ?, user_name = ?, test_name = ?, date = ?, grade = ? - WHERE id = ? ''' + WHERE id = ? """ conn = createDatabaseConnection(config.database) cur = conn.cursor() cur.execute(sql, newInfo) @@ -77,7 +75,7 @@ def updateTestEntry(newInfo): def deleteTestEntry(id): - sql = 'DELETE FROM tests WHERE id=?' + sql = "DELETE FROM tests WHERE id=?" conn = createDatabaseConnection(config.database) cur = conn.cursor() cur.execute(sql, (id,)) @@ -86,28 +84,28 @@ def deleteTestEntry(id): def retrieveAllTestTasks(): conn = createDatabaseConnection(config.database) - cur = conn.cursor() - cur.execute('SELECT * FROM tests') + cur = conn.cursor() + cur.execute("SELECT * FROM tests") return cur.fetchall() def createModesTable(): - conn = createDatabaseConnection(config.database) - sql = ''' CREATE TABLE IF NOT EXISTS modes ( + sql = """ CREATE TABLE IF NOT EXISTS modes ( id integer PRIMARY KEY, mode_name text - ); ''' + ); """ try: c = conn.cursor() c.execute(sql) - except: + except Exception as e: + print(f"Failed to create modes table due to error {e}") pass def createModeEntry(modeInfo): - sql = ''' INSERT INTO modes(mode_name) - VALUES(?) ''' + sql = """ INSERT INTO modes(mode_name) + VALUES(?) """ conn = createDatabaseConnection(config.database) cur = conn.cursor() cur.execute(sql, modeInfo) @@ -117,38 +115,38 @@ def createModeEntry(modeInfo): def retrieveAllModes(): conn = createDatabaseConnection(config.database) - cur = conn.cursor() - cur.execute('SELECT * FROM modes') + cur = conn.cursor() + cur.execute("SELECT * FROM modes") return cur.fetchall() def deleteAllModes(): - sql = 'DELETE FROM modes' + sql = "DELETE FROM modes" conn = createDatabaseConnection(config.database) - cur = conn.cursor() + cur = conn.cursor() cur.execute(sql) conn.commit() def retrieveModuleTests(module_id): - sql = 'SELECT * FROM tests WHERE module_id=?' - conn = createDatabaseConnection(config.database) - cur = conn.cursor() - cur.execute(sql, (module_id,)) - return cur.fetchall() + sql = "SELECT * FROM tests WHERE module_id=?" + conn = createDatabaseConnection(config.database) + cur = conn.cursor() + cur.execute(sql, (module_id,)) + return cur.fetchall() def retrieveModuleTest(row_id): - sql = 'SELECT * FROM tests WHERE id=?' - conn = createDatabaseConnection(config.database) - cur = conn.cursor() - cur.execute(sql, (row_id,)) - return cur.fetchall() + sql = "SELECT * FROM tests WHERE id=?" + conn = createDatabaseConnection(config.database) + cur = conn.cursor() + cur.execute(sql, (row_id,)) + return cur.fetchall() def deleteAllTests(): - sql = 'DELETE FROM tests' + sql = "DELETE FROM tests" conn = createDatabaseConnection(config.database) - cur = conn.cursor() + cur = conn.cursor() cur.execute(sql) conn.commit() diff --git a/Gui/python/ANSIColoringParser.py b/Gui/python/ANSIColoringParser.py index 3b2352a1..73014d20 100644 --- a/Gui/python/ANSIColoringParser.py +++ b/Gui/python/ANSIColoringParser.py @@ -1,6 +1,3 @@ -import re -from Gui.python.logging_config import logger - ConvertForSpan = { b"<": b"<", b">": b">", diff --git a/Gui/python/ArduinoWidget.py b/Gui/python/ArduinoWidget.py index c409b6b6..b1398eb1 100755 --- a/Gui/python/ArduinoWidget.py +++ b/Gui/python/ArduinoWidget.py @@ -2,34 +2,13 @@ from PyQt5 import QtSerialPort from PyQt5.QtCore import QIODevice, pyqtSignal from PyQt5.QtWidgets import ( - QApplication, - QCheckBox, QComboBox, - QDateTimeEdit, - QDial, - QDialog, - QFormLayout, QGridLayout, QGroupBox, - QHBoxLayout, QLabel, - QLineEdit, - QProgressBar, QPushButton, - QRadioButton, - QScrollBar, - QSizePolicy, - QSlider, - QSpinBox, - QStyleFactory, - QTableWidget, - QTabWidget, - QTextEdit, QHBoxLayout, - QVBoxLayout, QWidget, - QMainWindow, - QMessageBox, ) import pyvisa as visa @@ -157,9 +136,11 @@ def getDeviceName(self): stderr=subprocess.STDOUT, ) usbInfo = pipeUSB.communicate()[0] - deviceName = usbInfo.decode("UTF-8").split(deviceId)[-1].lstrip(" ").rstrip("\n") + deviceName = ( + usbInfo.decode("UTF-8").split(deviceId)[-1].lstrip(" ").rstrip("\n") + ) - if deviceName == None: + if deviceName is None: logger.warning("No device name found for {}:".format(device)) # self.deviceMap[device] = device elif "Arduino" in deviceName: @@ -195,24 +176,52 @@ def releaseArduinoPanel(self): self.ReleaseArduino.setDisabled(True) self.InstallFirmware.setDisabled(False) self.ArduinoList = self.listResources() - + def installArduinoFirmware(self): try: - device = self.deviceMap[self.ArduinoCombo.currentText()].lstrip("ASRL").rstrip("::INSTR") - subprocess.check_call(["../bin/arduino-cli", "lib", "install", "DHT sensor library@1.4.6"]) #install dependency - subprocess.check_call(["../bin/arduino-cli", "compile", "../FirmwareImages/DHT22_Sensor/DHT22_Sensor.ino", "-b", "arduino:avr:uno"]) #compile firmware - subprocess.check_call(["../bin/arduino-cli", "upload", "../FirmwareImages/DHT22_Sensor/", "-p", f"{device}", "-b", "arduino:avr:uno"]) #upload to Arduino - self.setBaudRate(site_settings.defaultSensorBaudRate) #default arduino baud rate + device = ( + self.deviceMap[self.ArduinoCombo.currentText()] + .lstrip("ASRL") + .rstrip("::INSTR") + ) + subprocess.check_call( + ["../bin/arduino-cli", "lib", "install", "DHT sensor library@1.4.6"] + ) # install dependency + subprocess.check_call( + [ + "../bin/arduino-cli", + "compile", + "../FirmwareImages/DHT22_Sensor/DHT22_Sensor.ino", + "-b", + "arduino:avr:uno", + ] + ) # compile firmware + subprocess.check_call( + [ + "../bin/arduino-cli", + "upload", + "../FirmwareImages/DHT22_Sensor/", + "-p", + f"{device}", + "-b", + "arduino:avr:uno", + ] + ) # upload to Arduino + self.setBaudRate( + site_settings.defaultSensorBaudRate + ) # default arduino baud rate self.ArduinoMeasureValue.setStyleSheet("QLabel {color : white}") self.ArduinoMeasureValue.setText("The Arduino firmware has been installed.") except Exception as err: logger.error("{0}".format(err)) self.ArduinoMeasureValue.setStyleSheet("QLabel {color : white}") - self.ArduinoMeasureValue.setText("The Arduino firmware could not be installed.") + self.ArduinoMeasureValue.setText( + "The Arduino firmware could not be installed." + ) def setPort(self, port): self.ArduinoCombo.setCurrentText(str(port)) - + def setBaudRate(self, baudRate): self.ArduinoBRCombo.setCurrentText(str(baudRate)) @@ -255,17 +264,16 @@ def receive(self): if temp >= dew_point: self.ArduinoMeasureValue.setStyleSheet("QLabel {color : green}") self.condensationRisk = False - #stopSignal = False + # stopSignal = False else: self.ArduinoMeasureValue.setStyleSheet("QLabel {color : red}") self.condensationRisk = True - #stopSignal = True - #look into this later, determine whether a global stop signal for condensation is necessary - + # stopSignal = True + # look into this later, determine whether a global stop signal for condensation is necessary climatetext = f"Temperature: {temp} C | Humidity: {humidity}% | Dew Point: {dew_point} C" self.ArduinoMeasureValue.setText(climatetext) - + if stopSignal: self.stopCount += 1 logger.warning( @@ -287,14 +295,16 @@ def receive(self): except Exception as err: self.readAttempts += 1 logger.error("{0}".format(err)) - + if self.readAttempts > 10: self.ArduinoMeasureValue.setStyleSheet("QLabel {color : red}") self.ArduinoMeasureValue.setText("The Arduino could not be read.") if self.readAttempts > 200: self.readAttempts = 0 self.releaseArduinoPanel() - logger.error("Could not communicate with the Arduino, check to ensure that you are using the appropriate baud rate and firmware.") + logger.error( + "Could not communicate with the Arduino, check to ensure that you are using the appropriate baud rate and firmware." + ) @QtCore.pyqtSlot() def StopSignal(self): diff --git a/Gui/python/CentralDBInterface.py b/Gui/python/CentralDBInterface.py index 9eaeee3f..7566836b 100644 --- a/Gui/python/CentralDBInterface.py +++ b/Gui/python/CentralDBInterface.py @@ -1,13 +1,13 @@ -import os, sys +import os + def ExtractChipData(chipserial): - #sqlcommand = f"select c.PART_NAME_LABEL, c.VDDA_TRIM_CODE, c.VDDD_TRIM_CODE, c.EFUSE_CODE from trker_cmsr.c18220 c where c.PART_NAME_LABEL = '{chipserial}'" #example of chipserial is N61F26_16E6_45 + # sqlcommand = f"select c.PART_NAME_LABEL, c.VDDA_TRIM_CODE, c.VDDD_TRIM_CODE, c.EFUSE_CODE from trker_cmsr.c18220 c where c.PART_NAME_LABEL = '{chipserial}'" #example of chipserial is N61F26_16E6_45 command = f'''python rhapi.py -nx -u https://cmsdca.cern.ch/trk_rhapi1 "select c.PART_NAME_LABEL, c.VDDA_TRIM_CODE, c.VDDD_TRIM_CODE, c.EFUSE_CODE from trker_cmsr.c13420 c where c.PART_NAME_LABEL like '%{chipserial}%'"''' - #chipdata = os.popen(command).read() + # chipdata = os.popen(command).read() chipdataoutput = os.popen(command).read() - chipdataoutput = chipdataoutput.split('\n') - datalabel = chipdataoutput[0].split(',') - datavalue = chipdataoutput[1].split(',') + chipdataoutput = chipdataoutput.split("\n") + datalabel = chipdataoutput[0].split(",") + datavalue = chipdataoutput[1].split(",") chipdata = dict(zip(datalabel, datavalue)) return chipdata - diff --git a/Gui/python/CustomizedWidget.py b/Gui/python/CustomizedWidget.py index 12947b3a..da0c44bb 100644 --- a/Gui/python/CustomizedWidget.py +++ b/Gui/python/CustomizedWidget.py @@ -1,29 +1,27 @@ from PyQt5 import QtCore from PyQt5.QtCore import Qt -from Gui.GUIutils.DBConnection import GetTrimClass from PyQt5.QtCore import pyqtSignal, QTimer from PyQt5.QtWidgets import ( QCheckBox, QComboBox, QGridLayout, QGroupBox, - QHBoxLayout, QLabel, QLineEdit, QMessageBox, QPushButton, QHBoxLayout, QWidget, + QVBoxLayout, + QScrollArea, ) import sys import requests from lxml import etree -from Gui.python.CentralDBInterface import ExtractChipData import Gui.siteSettings as site_settings from Gui.python.Firmware import ( - QtChip, QtModule, QtOpticalGroup, ) @@ -31,21 +29,24 @@ ModuleLaneMap, ModuleType, ) -#from Gui.GUIutils.FirmwareUtil import * -#from Gui.QtGUIutils.QtFwCheckDetails import * +# from Gui.GUIutils.FirmwareUtil import * +# from Gui.QtGUIutils.QtFwCheckDetails import * from Gui.python.logging_config import logger + class ClickOnlyComboBox(QComboBox): def __init__(self, parent=None): super().__init__(parent) def wheelEvent(self, event): - event.ignore() + event.ignore() + def debounce(wait): def decorator(fn): timer = None + def debounced(*args, **kwargs): nonlocal timer if timer is not None: @@ -54,9 +55,12 @@ def debounced(*args, **kwargs): timer.setSingleShot(True) timer.timeout.connect(lambda: fn(*args, **kwargs)) timer.start(wait) + return debounced + return decorator + class ModuleBox(QWidget): typechanged = pyqtSignal() @@ -75,7 +79,7 @@ def createRow(self): FMCLabel = QLabel("FMC:") self.FMCEdit = QLineEdit() - self.FMCEdit.setText('L12') + self.FMCEdit.setText("L12") PortLabel = QLabel("FMC port:") self.PortEdit = QLineEdit() @@ -108,10 +112,9 @@ def createRow(self): self.mainLayout.addWidget(self.TypeCombo, 0, 9, 1, 1) # self.mainLayout.addWidget(VersionLabel, 0, 10, 1, 1) self.mainLayout.addWidget(self.VersionCombo, 0, 11, 1, 1) - def setType(self): - #this method is created to set moudle type under online mode and comboBox is hidden + # this method is created to set moudle type under online mode and comboBox is hidden # This method is actually never used as far as I can tell. ~MJ 2025-01-16 if self.SerialEdit.text().startswith("RH"): chipType = "CROC 1x2" @@ -120,7 +123,7 @@ def setType(self): if self.SerialEdit.text().startswith("SH"): chipType = "TFPX CROC Quad" self.TypeCombo.setCurrentText(chipType) - numpart = ''.join(filter(str.isdigit, self.SerialEdit.text())) + numpart = "".join(filter(str.isdigit, self.SerialEdit.text())) if numpart.isdigit() and int(numpart) > 49: self.VersionCombo.setCurrentText(2) else: @@ -131,7 +134,7 @@ def getSerialNumber(self): def getFMCID(self): return self.FMCEdit.text() - + def getFC7(self): return self.FC7Combo.currentText() @@ -140,7 +143,7 @@ def getFMCPort(self): def getType(self): return self.TypeCombo.currentText() - + def getVersion(self): return self.VersionCombo.currentText() @@ -150,26 +153,27 @@ def getVDDD(self, pChipID): class ChipBox(QWidget): chipchanged = pyqtSignal(int, int) - #adding default value to serialNumber="RH0009" can prevent ChipBox from crashing under online mode + + # adding default value to serialNumber="RH0009" can prevent ChipBox from crashing under online mode def __init__(self, master, pChipType, serialNumber="RH0009"): super().__init__() logger.debug("Inside ChipBox") self.master = master self.serialNumber = serialNumber self.chipType = pChipType - logger.debug('the chip type passed to the chipbox is {0}'.format(self.chipType)) + logger.debug("the chip type passed to the chipbox is {0}".format(self.chipType)) self.mainLayout = QHBoxLayout() - self.ChipList = [] #chip id list for a single module - #self.initList() + self.ChipList = [] # chip id list for a single module + # self.initList() self.createList() self.VDDAMap = {} self.VDDDMap = {} self.ChipGroupBoxDict = {} self.trimValues = None self.chipData = None - + if self.master.purdue_connected and self.serialNumber != "": - #trims = self.fetchTrimFromDB(self.serialNumber) + # trims = self.fetchTrimFromDB(self.serialNumber) modulechipdata = self.fetchChipDataFromDB(self.serialNumber) if modulechipdata: self.chipData = modulechipdata @@ -181,20 +185,27 @@ def __init__(self, master, pChipType, serialNumber="RH0009"): # f"Module {serialNumber} chip layout does not correspond to typical {pChipType} chip layouts. Please modify the trim values manually.", # QMessageBox.Ok # ) - print(f"Module {serialNumber} chip layout does not correspond to typical {pChipType} chip layouts. Please modify the trim values manually.") + print( + f"Module {serialNumber} chip layout does not correspond to typical {pChipType} chip layouts. Please modify the trim values manually." + ) self.ChipGroupBoxDict.clear() for chipid in self.ChipList: self.ChipGroupBoxDict[chipid] = self.makeChipBox(chipid) else: for chipid in self.ChipList: - self.ChipGroupBoxDict[chipid] = self.makeChipBoxWithDB(chipid, modulechipdata[chipid]['VDDA'], modulechipdata[chipid]['VDDD'], modulechipdata[chipid]['EFUSE']) + self.ChipGroupBoxDict[chipid] = self.makeChipBoxWithDB( + chipid, + modulechipdata[chipid]["VDDA"], + modulechipdata[chipid]["VDDD"], + modulechipdata[chipid]["EFUSE"], + ) else: self.ChipGroupBoxDict.clear() for chipid in self.ChipList: self.ChipGroupBoxDict[chipid] = self.makeChipBox(chipid) - + self.makeChipGroupBox(self.ChipGroupBoxDict) - + self.setLayout(self.mainLayout) def initList(self): @@ -205,7 +216,7 @@ def createList(self): for lane in ModuleLaneMap[self.chipType]: self.ChipList.append(ModuleLaneMap[self.chipType][lane]) - #get trim values from DB + # get trim values from DB def makeChipBoxWithDB(self, pChipID, VDDA, VDDD, EfuseID="0"): self.ChipID = pChipID self.ChipLabel = QCheckBox("Chip ID: {0}".format(self.ChipID)) @@ -214,11 +225,11 @@ def makeChipBoxWithDB(self, pChipID, VDDA, VDDD, EfuseID="0"): self.ChipVDDDLabel = QLabel("VDDD:") self.ChipVDDDEdit = QLineEdit() self.ChipVDDDEdit.setObjectName("VDDDEdit_{0}".format(pChipID)) - + if not self.ChipVDDDEdit.text(): logger.debug("no VDDD text") self.ChipVDDALabel = QLabel("VDDA:") - self.ChipVDDAEdit = QLineEdit() + self.ChipVDDAEdit = QLineEdit() self.ChipVDDDEdit.setText(VDDD) self.ChipVDDAEdit.setText(VDDA) self.ChipVDDAEdit.setObjectName("VDDAEdit_{0}".format(pChipID)) @@ -239,7 +250,7 @@ def makeChipBoxWithDB(self, pChipID, VDDA, VDDD, EfuseID="0"): return self.VChipLayout - def makeChipBox(self, pChipID): + def makeChipBox(self, pChipID): self.ChipID = pChipID self.ChipLabel = QCheckBox("Chip ID: {0}".format(self.ChipID)) self.ChipLabel.setChecked(True) @@ -260,9 +271,7 @@ def makeChipBox(self, pChipID): else: self.ChipVDDDEdit.setText("16") self.ChipVDDAEdit.setText("16") - - - + self.VChipLayout = QGridLayout() self.VChipLayout.addWidget(self.ChipLabel, 0, 0, 1, 2) self.VChipLayout.addWidget(self.ChipVDDDLabel, 1, 0, 1, 1) @@ -311,9 +320,10 @@ def getVDDD(self, pChipID): def getEfuseID(self, pChipID): efuseID = self.findChild(QLineEdit, "EfuseIDEdit_{0}".format(pChipID)) return efuseID.text() - + def getChipData(self): return self.chipData + def getTrimValues(self): return self.trimValues @@ -321,7 +331,7 @@ def getChipStatus(self, pChipID): ChipCheckBox = self.findChild(QCheckBox, "ChipStatus_{0}".format(pChipID)) ChipStatus = ChipCheckBox.isChecked() return ChipStatus - + ## This function returns a list of dictionaries. Each element of the list is a chip dictinary. ## For example, chipdata[0]['EFUSE'] is the efuse ID of the first chip def fetchChipDataFromDB(self, moduleName): @@ -331,17 +341,17 @@ def fetchChipDataFromDB(self, moduleName): parser = etree.HTMLParser() tree = etree.fromstring(response.content, parser) - chip_table = tree.xpath('//body/table')[0] - #chipsitemap = {} - #chipsitemap['U1A'] = '12' - #chipsitemap['U1B'] = '13' - #chipsitemap['U1C'] = '14' - #chipsitemap['U1D'] = '15' + chip_table = tree.xpath("//body/table")[0] + # chipsitemap = {} + # chipsitemap['U1A'] = '12' + # chipsitemap['U1B'] = '13' + # chipsitemap['U1C'] = '14' + # chipsitemap['U1D'] = '15' chipidmap = {} - chipidmap['0'] = '12' - chipidmap['1'] = '13' - chipidmap['2'] = '14' - chipidmap['3'] = '15' + chipidmap["0"] = "12" + chipidmap["1"] = "13" + chipidmap["2"] = "14" + chipidmap["3"] = "15" chipdatalist = [] for row in chip_table: @@ -349,42 +359,46 @@ def fetchChipDataFromDB(self, moduleName): for element in row: elementdata.append(element.text) chipdatalist.append(elementdata) - chipdatadicts = [dict(zip(chipdatalist[0], values)) for values in chipdatalist[1:]] + chipdatadicts = [ + dict(zip(chipdatalist[0], values)) for values in chipdatalist[1:] + ] chipdata = {} for i, chip in enumerate(chipdatadicts): chipdata[chipidmap[str(i)]] = chip return chipdata - + except requests.exceptions.RequestException as req_err: - #some sort of connection issue, alert user + # some sort of connection issue, alert user msg = QMessageBox() msg.information( None, "Error", f"There was an issue connecting to the Purdue database.\nMessage: {repr(req_err)}", - QMessageBox.Ok + QMessageBox.Ok, ) - + self.master.purdue_connected = False self.ChipGroupBoxDict.clear() for chipid in self.ChipList: self.ChipGroupBoxDict[chipid] = self.makeChipBox(chipid) return None except IndexError: - #this occurs when an invalid modulename is input, alert user + # this occurs when an invalid modulename is input, alert user msg = QMessageBox() msg.information( None, "Error", f"Could not find {moduleName} in the database, using default values.", - QMessageBox.Ok + QMessageBox.Ok, ) for chipid in self.ChipList: self.ChipGroupBoxDict[chipid] = self.makeChipBox(chipid) return None except Exception as e: - #other issue - logger.error(f"Some error occurred while querying the Purdue DB for VDDD/VDDA trim values. \nError: {repr(e)}") + # other issue + logger.error( + f"Some error occurred while querying the Purdue DB for VDDD/VDDA trim values. \nError: {repr(e)}" + ) self.master.purdue_connected = False self.ChipGroupBoxDict.clear() for chipid in self.ChipList: @@ -394,17 +408,17 @@ def fetchChipDataFromDB(self, moduleName): def fetchTrimFromDB(self, moduleName): try: URL = f"https://www.physics.purdue.edu/cmsfpix/Phase2_Test/w.php?sn={moduleName}" - + response = requests.get(URL) - + parser = etree.HTMLParser() tree = etree.fromstring(response.content, parser) - chip_table = tree.xpath('//body/table')[0] - + chip_table = tree.xpath("//body/table")[0] + values = [] for row in chip_table[1:]: for element in row: - if element.text and element.text.startswith('U1'): + if element.text and element.text.startswith("U1"): values.append([]) elif element.text and element.text.isdigit(): @@ -412,39 +426,44 @@ def fetchTrimFromDB(self, moduleName): data = {} for i in range(len(values)): - data[str(i+12)] = {'VDDD': values[i][1], 'VDDA': values[i][2],} + data[str(i + 12)] = { + "VDDD": values[i][1], + "VDDA": values[i][2], + } return data except requests.exceptions.RequestException as req_err: - #some sort of connection issue, alert user + # some sort of connection issue, alert user msg = QMessageBox() msg.information( None, "Error", f"There was an issue connecting to the Purdue database.\nMessage: {repr(req_err)}", - QMessageBox.Ok + QMessageBox.Ok, ) - + self.master.purdue_connected = False self.ChipGroupBoxDict.clear() for chipid in self.ChipList: self.ChipGroupBoxDict[chipid] = self.makeChipBox(chipid) return None except IndexError: - #this occurs when an invalid modulename is input, alert user + # this occurs when an invalid modulename is input, alert user msg = QMessageBox() msg.information( None, "Error", f"Could not find {moduleName} in the database, using default values.", - QMessageBox.Ok + QMessageBox.Ok, ) for chipid in self.ChipList: self.ChipGroupBoxDict[chipid] = self.makeChipBox(chipid) return None except Exception as e: - #other issue - logger.error(f"Some error occurred while querying the Purdue DB for VDDD/VDDA trim values. \nError: {repr(e)}") + # other issue + logger.error( + f"Some error occurred while querying the Purdue DB for VDDD/VDDA trim values. \nError: {repr(e)}" + ) self.master.purdue_connected = False self.ChipGroupBoxDict.clear() for chipid in self.ChipList: @@ -452,8 +471,6 @@ def fetchTrimFromDB(self, moduleName): return None -from PyQt5.QtWidgets import QWidget, QGridLayout, QGroupBox, QPushButton, QVBoxLayout, QScrollArea - class BeBoardBox(QWidget): changed = pyqtSignal() @@ -473,15 +490,21 @@ def __init__(self, master, firmware): scrollContent.setLayout(self.mainLayout) # Set mainLayout to scrollable content scrollArea.setWidget(scrollContent) scrollArea.setWidgetResizable(True) - scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) # Ensure the scrollbar is always visible - scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # Hide the horizontal scrollbar + scrollArea.setVerticalScrollBarPolicy( + Qt.ScrollBarAlwaysOn + ) # Ensure the scrollbar is always visible + scrollArea.setHorizontalScrollBarPolicy( + Qt.ScrollBarAlwaysOff + ) # Hide the horizontal scrollbar mainLayout = QVBoxLayout() mainLayout.addWidget(scrollArea) self.setLayout(mainLayout) # Set mainLayout as the layout for BeBoardBox - self.setGeometry(100, 100, 800, 600) # Set initial geometry (x, y, width, height) + self.setGeometry( + 100, 100, 800, 600 + ) # Set initial geometry (x, y, width, height) self.setMinimumSize(900, 300) # Set minimum size (width, height) def initList(self): @@ -489,8 +512,10 @@ def initList(self): self.ModuleList.append(ModuleRow) ModuleRow.TypeCombo.currentTextChanged.connect(self.updateList) ModuleRow.VersionCombo.currentTextChanged.connect(self.updateList) - ModuleRow.SerialEdit.editingFinished.connect(self.createSerialUpdateCallback(ModuleRow)) - + ModuleRow.SerialEdit.editingFinished.connect( + self.createSerialUpdateCallback(ModuleRow) + ) + def createList(self): self.ListLayout = QGridLayout() self.ListLayout.setVerticalSpacing(0) @@ -515,7 +540,7 @@ def updateList(self, *args): if widget: self.ListLayout.removeWidget(widget) widget.setParent(None) - + for index, module in enumerate(self.ModuleList): if index == 0 and "CROC" not in module.TypeCombo.currentText(): module.VersionCombo.setCurrentText("v1") @@ -524,21 +549,27 @@ def updateList(self, *args): elif index == 0: module.TypeCombo.currentTextChanged.connect(self.updateList) if "SH" in module.getSerialNumber() or "RH" in module.getSerialNumber(): - numpart = ''.join(filter(str.isdigit, module.getSerialNumber())) + numpart = "".join(filter(str.isdigit, module.getSerialNumber())) if numpart.isdigit() and int(numpart) > 49: module.VersionCombo.setCurrentText("v2") else: module.VersionCombo.setCurrentText("v1") - + module.VersionCombo.currentTextChanged.connect(self.updateList) module.VersionCombo.setDisabled(False) if index != 0: - module.TypeCombo.setCurrentText(self.ModuleList[0].TypeCombo.currentText()) + module.TypeCombo.setCurrentText( + self.ModuleList[0].TypeCombo.currentText() + ) module.TypeCombo.setDisabled(True) - module.VersionCombo.setCurrentText(self.ModuleList[0].VersionCombo.currentText()) + module.VersionCombo.setCurrentText( + self.ModuleList[0].VersionCombo.currentText() + ) module.VersionCombo.setDisabled(True) - module.SerialEdit.editingFinished.connect(self.createSerialUpdateCallback(module)) - + module.SerialEdit.editingFinished.connect( + self.createSerialUpdateCallback(module) + ) + chipBox = ChipBox(self.master, module.getType(), module.getSerialNumber()) self.ChipWidgetDict[module] = chipBox module.setMaximumHeight(50) @@ -556,7 +587,8 @@ def updateList(self, *args): # Add remove and add buttons for index, module in enumerate(self.ModuleList): - if index == 0: continue #no remove button for the first module + if index == 0: + continue # no remove button for the first module removeButton = QPushButton("Remove") removeButton.setMaximumWidth(150) removeButton.clicked.connect(lambda checked, m=module: self.removeModule(m)) @@ -567,28 +599,29 @@ def updateList(self, *args): newButton.clicked.connect(self.addModule) self.ListLayout.addWidget(newButton, len(self.ModuleList), 1, 1, 1) self.update() - + def createSerialUpdateCallback(self, module): return lambda: self.onSerialNumberUpdate(module) - + @debounce(500) def onSerialNumberUpdate(self, module): data = self.fetchModuleTypeDB(module.getSerialNumber()) if data: if module.TypeCombo.isEnabled(): - module.TypeCombo.setCurrentText(data['type']) + module.TypeCombo.setCurrentText(data["type"]) if module.VersionCombo.isEnabled(): - module.VersionCombo.setCurrentText(data['version']) - + module.VersionCombo.setCurrentText(data["version"]) + self.updateList() - + def fetchModuleTypeDB(self, moduleName): - if not self.master.purdue_connected: return None + if not self.master.purdue_connected: + return None try: URL = f"https://www.physics.purdue.edu/cmsfpix/Phase2_Test/w.php?sn={moduleName}" - + response = requests.get(URL) - + moduletype, moduleversion = None, None res = str(response.content).split("\\n") for i in res: @@ -601,33 +634,35 @@ def fetchModuleTypeDB(self, moduleName): moduletype = "TFPX CROC 1x2" elif moduletype.startswith("croc_2x2"): moduletype = "TFPX CROC Quad" - + if moduletype == "" or moduleversion == "": msg = QMessageBox() msg.information( None, "Error", f"Could not find {moduleName} in the database.", - QMessageBox.Ok + QMessageBox.Ok, ) return None else: - return {'type': moduletype, 'version': f"v{moduleversion}"} + return {"type": moduletype, "version": f"v{moduleversion}"} except requests.exceptions.RequestException as req_err: - #some sort of connection issue, alert user + # some sort of connection issue, alert user msg = QMessageBox() msg.information( None, "Error", f"There was an issue connecting to the Purdue database.\nMessage: {repr(req_err)}", - QMessageBox.Ok + QMessageBox.Ok, ) - + self.master.purdue_connected = False return None except Exception as e: - #other issue - logger.error(f"Some error occurred while querying the Purdue DB for module type. \nError: {repr(e)}") + # other issue + logger.error( + f"Some error occurred while querying the Purdue DB for module type. \nError: {repr(e)}" + ) self.master.purdue_connected = False return None @@ -657,63 +692,86 @@ def getFirmwareDescription(self): BeBoard = board if BeBoard is None: raise Exception("There are no FC7s active.") - + # Access the currently selected QtOpticalGroup of the QtBeBoard OpticalGroup = None for og in BeBoard.getAllOpticalGroups().values(): if og.getFMCID() == module.getFMCID(): OpticalGroup = og - + # Create it if it doesn't already exist if OpticalGroup is None: OpticalGroup = QtOpticalGroup(FMCID=module.getFMCID()) - OpticalGroup.setBeBoard(BeBoard) # Ignore this line, see explanation in Firmware.py + OpticalGroup.setBeBoard( + BeBoard + ) # Ignore this line, see explanation in Firmware.py try: - BeBoard.addOpticalGroup(FMCID=module.getFMCID(), OpticalGroup=OpticalGroup) + BeBoard.addOpticalGroup( + FMCID=module.getFMCID(), OpticalGroup=OpticalGroup + ) except KeyError as e: - return None, f"Error while adding Optical Group to BeBoard: {repr(e)}" - + return ( + None, + f"Error while adding Optical Group to BeBoard: {repr(e)}", + ) + # Create a QtModule object based on the input data Module = QtModule( moduleName=module.getSerialNumber(), moduleType=module.getType(), moduleVersion=module.getVersion(), - FMCPort=module.getFMCPort() + FMCPort=module.getFMCPort(), ) - Module.setOpticalGroup(OpticalGroup) # Ignore this line, see explanation in Firmware.py - + Module.setOpticalGroup( + OpticalGroup + ) # Ignore this line, see explanation in Firmware.py + # Pull VDDA/VDDD trim and chip status from the ChipBox on the StartWindow. for chipID in ModuleLaneMap[module.getType()].values(): - Module.getChips()[chipID].setStatus(self.ChipWidgetDict[module].getChipStatus(chipID)) - Module.getChips()[chipID].setVDDA(self.ChipWidgetDict[module].getVDDA(chipID)) - Module.getChips()[chipID].setVDDD(self.ChipWidgetDict[module].getVDDD(chipID)) - Module.getChips()[chipID].setEfuseID(self.ChipWidgetDict[module].getEfuseID(chipID)) - + Module.getChips()[chipID].setStatus( + self.ChipWidgetDict[module].getChipStatus(chipID) + ) + Module.getChips()[chipID].setVDDA( + self.ChipWidgetDict[module].getVDDA(chipID) + ) + Module.getChips()[chipID].setVDDD( + self.ChipWidgetDict[module].getVDDD(chipID) + ) + Module.getChips()[chipID].setEfuseID( + self.ChipWidgetDict[module].getEfuseID(chipID) + ) + # Add the QtModule object to the currently selected Optical Group try: OpticalGroup.addModule(FMCPort=module.getFMCPort(), module=Module) except KeyError as e: return None, f"Error while adding Module to Optical Group: {repr(e)}" - module_types.append(Module.getModuleType() + " " + Module.getModuleVersion()) + module_types.append( + Module.getModuleType() + " " + Module.getModuleVersion() + ) if not all([i == module_types[0] for i in module_types]): - #iterate over module_types, if they're not all identical, return None - return None, f"All modules must be of the same type! Please ensure you have entered the module data correctly." - - #only include the board if there are connected modules, otherwise ignore it + # iterate over module_types, if they're not all identical, return None + return ( + None, + "All modules must be of the same type! Please ensure you have entered the module data correctly.", + ) + + # only include the board if there are connected modules, otherwise ignore it ret = [] for board in self.firmware: - if len(board.getAllOpticalGroups()) != 0: # If modules are connected to the board + if ( + len(board.getAllOpticalGroups()) != 0 + ): # If modules are connected to the board board.setBoardID(len(ret)) ret.append(board) - - if ret == list(): #nothing added to ret -> no connected modules + + if ret == list(): # nothing added to ret -> no connected modules return None, "No valid module found!" else: return ret, "Success" - # def getVDDA(self, module): # VDDAdict = {} # for key in self.ChipWidgetDict.keys(): @@ -800,7 +858,6 @@ def __init__(self): self.mainLayout = QGridLayout() self.createRow() self.setLayout(self.mainLayout) - def createRow(self): SerialLabel = QLabel("SerialNumber:") @@ -812,12 +869,10 @@ def createRow(self): self.CableIDEdit.textChanged.connect(self.on_TypeChanged) self.CableIDEdit.setReadOnly(True) - self.mainLayout.addWidget(SerialLabel, 0, 0) self.mainLayout.addWidget(self.SerialEdit, 0, 1) self.mainLayout.addWidget(CableIDLabel, 1, 0) self.mainLayout.addWidget(self.CableIDEdit, 1, 1) - def setSerialNumber(self, serial): self.SerialEdit.setText(serial) @@ -845,18 +900,18 @@ def getType(self, SerialNumber): elif "SH" in SerialNumber: self.Type = "TFPX CROC Quad" return self.Type - + def setVersion(self, versionStr): self.version = versionStr - + def getVersion(self, SerialNumber): - numpart = ''.join(filter(str.isdigit, SerialNumber)) + numpart = "".join(filter(str.isdigit, SerialNumber)) if "SH" in SerialNumber or "RH" in SerialNumber: if numpart.isdigit() and int(numpart) > 49: self.version = "v2" else: self.version = "v1" - + else: self.version = "v1" return self.version @@ -875,9 +930,6 @@ def on_editing_finished(self): self.SerialString = self.SerialEdit.text() self.textchanged.emit() - - - class SimpleBeBoardBox(QWidget): changed = pyqtSignal() @@ -901,16 +953,21 @@ def __init__(self, master, firmware): scrollContent.setLayout(self.mainLayout) # Set mainLayout to scrollable content scrollArea.setWidget(scrollContent) scrollArea.setWidgetResizable(True) - scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) # Ensure the scrollbar is always visible - scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # Hide the horizontal scrollbar + scrollArea.setVerticalScrollBarPolicy( + Qt.ScrollBarAlwaysOn + ) # Ensure the scrollbar is always visible + scrollArea.setHorizontalScrollBarPolicy( + Qt.ScrollBarAlwaysOff + ) # Hide the horizontal scrollbar mainLayout = QVBoxLayout() mainLayout.addWidget(scrollArea) self.setLayout(mainLayout) # Set mainLayout as the layout for BeBoardBox - self.setGeometry(100, 100, 800, 600) # Set initial geometry (x, y, width, height) - + self.setGeometry( + 100, 100, 800, 600 + ) # Set initial geometry (x, y, width, height) def initList(self): ModuleRow = SimpleModuleBox() @@ -918,7 +975,7 @@ def initList(self): self.ModuleList[-1].SerialEdit.setFocus() def createList(self): - logger.debug(f'{__name__} : Creating module list') + logger.debug(f"{__name__} : Creating module list") self.ListBox = QGroupBox() self.ListLayout = QGridLayout() @@ -934,7 +991,7 @@ def deleteList(self): self.mainLayout.removeWidget(self.ListBox) def updateList(self): - logger.debug(f'{__name__} : Updating module list') + logger.debug(f"{__name__} : Updating module list") [columns, rows] = [self.ListLayout.columnCount(), self.ListLayout.rowCount()] for i in range(columns): @@ -943,7 +1000,7 @@ def updateList(self): if item: widget = item.widget() self.ListLayout.removeWidget(widget) - logger.debug(f'{__name__} : Before connecting module signals') + logger.debug(f"{__name__} : Before connecting module signals") for index, module in enumerate(self.ModuleList): # module.setMaximumWidth(500) module.setMaximumHeight(50) @@ -951,7 +1008,7 @@ def updateList(self): module.textchanged.connect(self.on_ModuleFilled) module.setID(index) self.ListLayout.addWidget(module, index, 0, 1, 1) - logger.debug(f'{__name__} : After connecting module signals') + logger.debug(f"{__name__} : After connecting module signals") NewButton = QPushButton("add") NewButton.setMaximumWidth(150) NewButton.clicked.connect(self.addModule) @@ -964,7 +1021,7 @@ def updateList(self): # self.ListLayout.addWidget(NewButton,len(self.ModuleList),1,1,1) self.ListLayout.addWidget(ClearButton, len(self.ModuleList), 0, 1, 1) self.update() - logger.debug(f'{__name__} : Finished setting up module list') + logger.debug(f"{__name__} : Finished setting up module list") def removeModule(self, index): # For Manual change @@ -1021,84 +1078,118 @@ def getModules(self): def getFirmwareDescription(self): module_types = [] for module in self.ModuleList: - if module.getSerialNumber() is None: continue #ignore blank entries + if module.getSerialNumber() is None: + continue # ignore blank entries cable_properties = site_settings.CableMapping[module.getID()] if module.getID() not in site_settings.CableMapping.keys(): - raise Exception(f"Encountered cable ID {module.getID()} not present in siteConfig.") - + raise Exception( + f"Encountered cable ID {module.getID()} not present in siteConfig." + ) + # Access the currently selected QtBeBoard object BeBoard = None for beboard in self.firmware: if beboard.getBoardName() == cable_properties["FC7"]: BeBoard = beboard - + if BeBoard is None: - raise Exception(f"Could not find {cable_properties['FC7']} in the firmware list. This may occur if the connection to the FC7 is broken.") - + raise Exception( + f"Could not find {cable_properties['FC7']} in the firmware list. This may occur if the connection to the FC7 is broken." + ) + # Access the currently selected QtOpticalGroup of the QtBeBoard OpticalGroup = None for og in BeBoard.getAllOpticalGroups().values(): if og.getFMCID() == cable_properties["FMCID"]: OpticalGroup = og - + # Create it if it doesn't already exist if OpticalGroup is None: OpticalGroup = QtOpticalGroup(FMCID=cable_properties["FMCID"]) - OpticalGroup.setBeBoard(BeBoard) # Ignore this line, see explanation in Firmware.py + OpticalGroup.setBeBoard( + BeBoard + ) # Ignore this line, see explanation in Firmware.py try: - BeBoard.addOpticalGroup(FMCID=cable_properties["FMCID"], OpticalGroup=OpticalGroup) + BeBoard.addOpticalGroup( + FMCID=cable_properties["FMCID"], OpticalGroup=OpticalGroup + ) except KeyError as e: - return None, f"Error while adding Optical Group to BeBoard: {repr(e)}" - + return ( + None, + f"Error while adding Optical Group to BeBoard: {repr(e)}", + ) + # Create a QtModule object based on the input data Module = QtModule( moduleName=module.getSerialNumber(), moduleType=module.getType(module.getSerialNumber()), moduleVersion=module.getVersion(module.getSerialNumber()), - FMCPort=cable_properties["FMCPort"] + FMCPort=cable_properties["FMCPort"], + ) + Module.setOpticalGroup( + OpticalGroup + ) # Ignore this line, see explanation in Firmware.py + + # Fetch the VDDD/VDDA trim values from the Purdue DB, make a ChipBox due to built in error handling + chipBox = ChipBox( + self.master, + module.getType(module.getSerialNumber()), + module.getSerialNumber(), ) - Module.setOpticalGroup(OpticalGroup) # Ignore this line, see explanation in Firmware.py - - #Fetch the VDDD/VDDA trim values from the Purdue DB, make a ChipBox due to built in error handling - chipBox = ChipBox(self.master, module.getType(module.getSerialNumber()), module.getSerialNumber()) chipData = chipBox.getChipData() if chipData: - for chipID in ModuleLaneMap[module.getType(module.getSerialNumber())].values(): - Module.getChips()[chipID].setVDDA(chipData[chipID]['VDDA']) - Module.getChips()[chipID].setVDDD(chipData[chipID]['VDDD']) - Module.getChips()[chipID].setEfuseID(chipData[chipID]['EFUSE']) + for chipID in ModuleLaneMap[ + module.getType(module.getSerialNumber()) + ].values(): + Module.getChips()[chipID].setVDDA(chipData[chipID]["VDDA"]) + Module.getChips()[chipID].setVDDD(chipData[chipID]["VDDD"]) + Module.getChips()[chipID].setEfuseID(chipData[chipID]["EFUSE"]) else: - print("Something went wrong while fetching VDDD/VDDA from the database. Proceeding with default values.") + print( + "Something went wrong while fetching VDDD/VDDA from the database. Proceeding with default values." + ) - #trims = chipBox.getTrimValues() - #if trims: + # trims = chipBox.getTrimValues() + # if trims: # for chipID in ModuleLaneMap[module.getType(module.getSerialNumber())].values(): # Module.getChips()[chipID].setVDDA(trims[chipID]['VDDA']) # Module.getChips()[chipID].setVDDD(trims[chipID]['VDDD']) - #else: + # else: # print("Something went wrong while fetching VDDD/VDDA from the database. Proceeding with default values.") - + # Add the QtModule object to the currently selected Optical Group try: - OpticalGroup.addModule(FMCPort=cable_properties["FMCPort"], module=Module) + OpticalGroup.addModule( + FMCPort=cable_properties["FMCPort"], module=Module + ) except KeyError as e: return None, f"Error while adding Module to Optical Group: {repr(e)}" - - module_types.append(Module.getModuleType() + " " + Module.getModuleVersion()) + + module_types.append( + Module.getModuleType() + " " + Module.getModuleVersion() + ) if not all([i == module_types[0] for i in module_types]): - #iterate over module_types, if they're not all identical, return None - return None, f"All modules must be of the same type! Please ensure the serial numbers are correct." - - #only include the board if there are connected modules, otherwise ignore it + # iterate over module_types, if they're not all identical, return None + return ( + None, + "All modules must be of the same type! Please ensure the serial numbers are correct.", + ) + + # only include the board if there are connected modules, otherwise ignore it ret = [] for board in self.firmware: - if len(board.getAllOpticalGroups()) != 0: # If modules are connected to the board + if ( + len(board.getAllOpticalGroups()) != 0 + ): # If modules are connected to the board board.setBoardID(len(ret)) ret.append(board) - - if ret == list(): #nothing added to ret -> no connected modules - return None, "No valid module found! If manually entering module number be sure to press 'Enter' on keyboard." + + if ret == list(): # nothing added to ret -> no connected modules + return ( + None, + "No valid module found! If manually entering module number be sure to press 'Enter' on keyboard.", + ) else: return ret, "Success" diff --git a/Gui/python/Firmware.py b/Gui/python/Firmware.py index 8cc8ccd2..46df4e70 100644 --- a/Gui/python/Firmware.py +++ b/Gui/python/Firmware.py @@ -1,11 +1,18 @@ from Gui.GUIutils.settings import ( ModuleLaneMap, ) -from Gui.python.logging_config import logger class QtChip: - def __init__(self, chipID = "", chipLane = "", chipVDDA = 0, chipVDDD = 0, chipEfuseID = 0, chipStatus = True): + def __init__( + self, + chipID="", + chipLane="", + chipVDDA=0, + chipVDDD=0, + chipEfuseID=0, + chipStatus=True, + ): self.__chipID = chipID self.__chipLane = chipLane self.__chipVDDA = chipVDDA @@ -21,25 +28,25 @@ def getID(self): def setLane(self, lane: str): self.__chipLane = lane - + def getLane(self): return self.__chipLane def setVDDA(self, pVDDAtrim: int): self.__chipVDDA = pVDDAtrim - + def getVDDA(self): return self.__chipVDDA def setVDDD(self, pVDDDtrim: int): self.__chipVDDD = pVDDDtrim - + def getVDDD(self): return self.__chipVDDD def setEfuseID(self, pEfuseID: int): self.__chipEfuseID = pEfuseID - + def getEfuseID(self): return self.__chipEfuseID @@ -48,169 +55,188 @@ def setStatus(self, pStatus: bool): def getStatus(self): return self.__chipStatus - + def __str__(self): return f" ChipID: {self.__chipID}, LaneID: {self.__chipLane}, ChipVDDD: {self.__chipVDDD}, ChipVDDA: {self.__chipVDDA}, ChipStatus: {self.__chipStatus}" class QtModule: - def __init__(self, moduleName = "", moduleType = "", moduleVersion = "", FMCPort = "", enabled = "1", Fc7 = None): + def __init__( + self, + moduleName="", + moduleType="", + moduleVersion="", + FMCPort="", + enabled="1", + Fc7=None, + ): self.__moduleName = moduleName self.__moduleType = moduleType self.__moduleVersion = moduleVersion self.__FMCPort = FMCPort - self.__chipDict = {} #{ChipID : QtChip()}, deviates from pattern to make usage easier, laneID is not commonly used + self.__chipDict = {} # {ChipID : QtChip()}, deviates from pattern to make usage easier, laneID is not commonly used self.__enabled = enabled self.__Fc7 = Fc7 - + if self.__moduleType != "": - #if module type was specified, initialize chips to default + # if module type was specified, initialize chips to default self.__setupChips() - + def setModuleName(self, moduleName: str): self.__moduleName = moduleName - + def getModuleName(self): return self.__moduleName - + def setModuleType(self, moduleType: str): if moduleType not in ModuleLaneMap.keys(): - print(f"Module type '{moduleType}' is not familiar. Defaulting to 'CROC SCC'.") + print( + f"Module type '{moduleType}' is not familiar. Defaulting to 'CROC SCC'." + ) self.__moduleType = "CROC SCC" else: self.__moduleType = moduleType self.__setupChips() - + def getModuleType(self): return self.__moduleType - + def setModuleVersion(self, moduleVersion: str): self.__moduleVersion = moduleVersion - + def getModuleVersion(self): return self.__moduleVersion - + def setFMCPort(self, FMCPort: str): self.__FMCPort = FMCPort - + def getFMCPort(self): return self.__FMCPort - + def __setupChips(self): self.__chipDict.clear() - + for LaneID, ChipID in ModuleLaneMap[self.__moduleType].items(): FEChip = QtChip( - chipID = ChipID, - chipLane = LaneID, - chipVDDA = 8, - chipVDDD = 8, - chipStatus = True + chipID=ChipID, chipLane=LaneID, chipVDDA=8, chipVDDD=8, chipStatus=True ) self.__chipDict[ChipID] = FEChip def getChips(self): return self.__chipDict - + def getEnabledChips(self): - return {chipID : chip for chipID, chip in self.__chipDict.items() if chip.getStatus()} - - def setEnabled(self, enabled:str): + return { + chipID: chip for chipID, chip in self.__chipDict.items() if chip.getStatus() + } + + def setEnabled(self, enabled: str): self.__enabled = enabled def getEnabled(self) -> str: return self.__enabled - + def setFc7(self, Fc7) -> None: self.__Fc7 = Fc7 - + def getFc7(self): return self.__Fc7 - + """ These two functions define the parent object accessible from the current object. It's a shortcut to avoid rewriting some code that assumes modules know everything about themselves. """ + def setOpticalGroup(self, opticalgroup): self.__parent = opticalgroup - + def getOpticalGroup(self): return self.__parent - + def __str__(self): - chips_str = "\n".join([f" {chipID}: {str(chip)}" for chipID, chip in self.__chipDict.items()]) + chips_str = "\n".join( + [f" {chipID}: {str(chip)}" for chipID, chip in self.__chipDict.items()] + ) return f" ModuleName: {self.__moduleName}, ModuleType: {self.__moduleType} {self.__moduleVersion}, FMCPort: {self.__FMCPort}\n Chips:\n{chips_str}" class QtOpticalGroup: - def __init__(self, OpticalGroupID = "0", FMCID = ""): + def __init__(self, OpticalGroupID="0", FMCID=""): self.__OpticalGroupID = OpticalGroupID self.__FMCID = FMCID - self.__moduleDict = {} #{FMCPort : QtModule()} - + self.__moduleDict = {} # {FMCPort : QtModule()} + def setOpticalGroupID(self, OpticalGroupID: str): self.__OpticalGroupID = OpticalGroupID - + def getOpticalGroupID(self): return self.__OpticalGroupID - + def setFMCID(self, FMCID: str): self.__FMCID = FMCID - + def getFMCID(self): return self.__FMCID - + def addModule(self, FMCPort: str, module: QtModule): if FMCPort in self.__moduleDict.keys(): - raise KeyError(f"The provided FMC port, {FMCPort}, is already assigned to another module. You cannot connect two modules to the same port.") + raise KeyError( + f"The provided FMC port, {FMCPort}, is already assigned to another module. You cannot connect two modules to the same port." + ) self.__moduleDict[FMCPort] = module - + def removeModule(self, module: QtModule): for key, value in self.__moduleDict: if value == module: del self.__moduleDict[key] - + def removeModuleByIndex(self, FMCPort: str): del self.__moduleDict[FMCPort] - + def removeAllModules(self): self.__moduleDict.clear() - + def getModuleByIndex(self, FMCPort: str): return self.__moduleDict[FMCPort] - + def getAllModules(self): return self.__moduleDict - + """ These two functions define the parent object accessible from the current object. It's a shortcut to avoid rewriting some code that assumes modules know everything about themselves. """ + def setBeBoard(self, beboard): self.__parent = beboard - + def getBeBoard(self): return self.__parent - + def __str__(self): - modules_str = "\n".join([f" {FMCPort}: {str(module)}" for FMCPort, module in self.__moduleDict.items()]) + modules_str = "\n".join( + [ + f" {FMCPort}: {str(module)}" + for FMCPort, module in self.__moduleDict.items() + ] + ) return f" FMCID: {self.__FMCID}, OGID: {self.__OpticalGroupID}\n Modules:\n{modules_str}" class QtBeBoard: - def __init__(self, BeBoardID = "0", boardName = "", ipAddress = "0.0.0.0"): + def __init__(self, BeBoardID="0", boardName="", ipAddress="0.0.0.0"): self.__BeBoardID = BeBoardID self.__boardName = boardName self.__ipAddress = ipAddress - self.__OGDict = {} #{FMCID : QtOpticalGroup()} - #self.__fpgaConfigName = "" + self.__OGDict = {} # {FMCID : QtOpticalGroup()} + # self.__fpgaConfigName = "" def setBoardID(self, boardID: str): self.__BeBoardID = boardID def getBoardID(self): return self.__BeBoardID - + def setBoardName(self, boardName: str): self.__boardName = boardName @@ -225,7 +251,9 @@ def getIPAddress(self): def addOpticalGroup(self, FMCID: str, OpticalGroup: QtOpticalGroup): if FMCID in self.__OGDict.keys(): - raise KeyError(f"The provided FMC ID, {FMCID}, is already assigned to another FMC. You cannot assign two FMCs to the same FMC ID.") + raise KeyError( + f"The provided FMC ID, {FMCID}, is already assigned to another FMC. You cannot assign two FMCs to the same FMC ID." + ) OpticalGroup.setOpticalGroupID(str(len(self.__OGDict))) self.__OGDict[FMCID] = OpticalGroup @@ -245,28 +273,36 @@ def getOpticalGroupByIndex(self, FMCID: str): def getAllOpticalGroups(self): return self.__OGDict - + def __str__(self): - optical_groups_str = "\n".join([f" {FMCID}: {str(opticalGroup)}" for FMCID, opticalGroup in self.__OGDict.items()]) + optical_groups_str = "\n".join( + [ + f" {FMCID}: {str(opticalGroup)}" + for FMCID, opticalGroup in self.__OGDict.items() + ] + ) return f"BoardName: {self.__boardName}, BoardID: {self.__BeBoardID}, IPAddress: {self.__ipAddress}\nOpticalGroups:\n{optical_groups_str}" - + ############ Helper Functions for Convenience ############ - + def getModules(self): modules = [] for opticalgroup in self.getAllOpticalGroups().values(): for module in opticalgroup.getAllModules().values(): modules.append(module) return modules - + def removeModules(self): for og in self.__OGDict.values(): og.removeAllModules() - + def getModuleData(self): - #Implemented under the assumption that every module will be of the same type/version + # Implemented under the assumption that every module will be of the same type/version for OG in self.getAllOpticalGroups().values(): for module in OG.getAllModules().values(): - return {'type':module.getModuleType(), 'version':module.getModuleVersion()} - - ########################################################## \ No newline at end of file + return { + "type": module.getModuleType(), + "version": module.getModuleVersion(), + } + + ########################################################## diff --git a/Gui/python/IVCurveHandler.py b/Gui/python/IVCurveHandler.py index 1d9f15f8..1b0c8d6f 100644 --- a/Gui/python/IVCurveHandler.py +++ b/Gui/python/IVCurveHandler.py @@ -5,24 +5,27 @@ from Gui.siteSettings import IVcurve_range - class IVCurveThread(QThread): measureSignal = pyqtSignal(str, object) progressSignal = pyqtSignal(str, float) - def __init__(self, parent, testName, instrument_cluster=None, execute_each_step=lambda:None): + def __init__( + self, parent, testName, instrument_cluster=None, execute_each_step=lambda: None + ): super(IVCurveThread, self).__init__() self.instruments = instrument_cluster self.parent = parent self.measureSignal.connect(self.parent.transitMeasurment) - self.progressSignal.connect(self.parent.transmitProgress) #FIXME add slot function + self.progressSignal.connect( + self.parent.transmitProgress + ) # FIXME add slot function self.exiting = False self.setTerminationEnabled(True) self.execute_each_step = execute_each_step self.startVal = 0 self.target = 0 - #Making sure IVcurve peak is a negative voltage + # Making sure IVcurve peak is a negative voltage if IVcurve_range[testName] < 0: self.stopVal = IVcurve_range[testName] print("IVcurve range: ", self.stopVal) @@ -34,8 +37,13 @@ def __init__(self, parent, testName, instrument_cluster=None, execute_each_step= self.turnOn() def turnOn(self): - starting_voltages = [np.abs(getattr(module["hv"], "voltage")) for module in self.instruments._module_dict.values()] - self.instruments.hv_off(execute_each_step=lambda:self.execute_each_step(starting_voltages)) + starting_voltages = [ + np.abs(getattr(module["hv"], "voltage")) + for module in self.instruments._module_dict.values() + ] + self.instruments.hv_off( + execute_each_step=lambda: self.execute_each_step(starting_voltages) + ) self.instruments.hv_on(voltage=0, delay=0.5, step_size=10, no_lock=True) self.instruments.hv_set_ocp(0.00001) @@ -46,21 +54,25 @@ def breakTest(self): return False def getProgress(self): - self.percentStep = abs(100*self.stepLength/self.stopVal) + self.percentStep = abs(100 * self.stepLength / self.stopVal) self.progressSignal.emit("IVCurve", self.percentStep) - def abortTest(self): self.exiting = True def run(self): try: - starting_voltages = [np.abs(getattr(module["hv"], "voltage")) for module in self.instruments._module_dict.values()] - self.instruments.hv_off(execute_each_step=lambda:self.execute_each_step(starting_voltages)) - + starting_voltages = [ + np.abs(getattr(module["hv"], "voltage")) + for module in self.instruments._module_dict.values() + ] + self.instruments.hv_off( + execute_each_step=lambda: self.execute_each_step(starting_voltages) + ) + _, measurements = self.instruments.hv_on( voltage=self.stopVal, - step_size= self.stepLength, + step_size=self.stepLength, delay=0.2, measure=True, execute_each_step=self.getProgress, @@ -79,6 +91,7 @@ def run(self): except Exception as e: print("IV Curve scan failed with {}".format(e)) + class IVCurveHandler(QObject): measureSignal = pyqtSignal(str, object) stopSignal = pyqtSignal(object) @@ -91,20 +104,28 @@ def __init__(self, testName, instrument_cluster, execute_each_step): self.instruments = instrument_cluster self.execute_each_step = execute_each_step - assert self.instruments is not None, logger.debug("Error instantiating instrument cluster") + assert self.instruments is not None, logger.debug( + "Error instantiating instrument cluster" + ) - self.test = IVCurveThread(self, testName, instrument_cluster=self.instruments, execute_each_step=self.execute_each_step) + self.test = IVCurveThread( + self, + testName, + instrument_cluster=self.instruments, + execute_each_step=self.execute_each_step, + ) self.test.progressSignal.connect(self.transmitProgress) self.test.measureSignal.connect(self.finish) def isValid(self): - return self.instruments != None + return self.instruments is not None def IVCurve(self): if not self.isValid(): return self.test.start() self.startSignal.emit() + def transitMeasurment(self, measure): self.measureSignal.emit("IVCurve", measure) @@ -112,15 +133,26 @@ def transmitProgress(self, measurementType, percentStep): self.progressSignal.emit(measurementType, percentStep) def finish(self, test: str, measure: dict): - starting_voltages = [np.abs(getattr(module["hv"], "voltage")) for module in self.instruments._module_dict.values()] - self.instruments.hv_off(execute_each_step=lambda : self.execute_each_step(starting_voltages)) + starting_voltages = [ + np.abs(getattr(module["hv"], "voltage")) + for module in self.instruments._module_dict.values() + ] + self.instruments.hv_off( + execute_each_step=lambda: self.execute_each_step(starting_voltages) + ) self.finished.emit(test, measure) def stop(self): try: self.test.abortTest() - starting_voltages = [np.abs(getattr(module["hv"], "voltage")) for module in self.instruments._module_dict.values()] - self.instruments.hv_off(no_lock=True, execute_each_step=lambda : self.execute_each_step(starting_voltages)) + starting_voltages = [ + np.abs(getattr(module["hv"], "voltage")) + for module in self.instruments._module_dict.values() + ] + self.instruments.hv_off( + no_lock=True, + execute_each_step=lambda: self.execute_each_step(starting_voltages), + ) self.test.terminate() except Exception as err: print(f"Failed to stop the IV test due to error {err}") diff --git a/Gui/python/Keithley2400RS232.py b/Gui/python/Keithley2400RS232.py deleted file mode 100644 index 58aacdda..00000000 --- a/Gui/python/Keithley2400RS232.py +++ /dev/null @@ -1,104 +0,0 @@ -import logging -import time -logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') -logger = logging.getLogger(__name__) - -def InitialDevice(device): - try: - device.write("*RST") - except Exception as err: - logger.error("Error occured while restore defaults: {}".format(err)) - # Select voltage source mode - try: - device.write(":SOURCE:FUNCTION VOLT") - device.write(":SOURCE:VOLTAGE:MODE FIX") - device.write(":SENS:CURR:RANG 10E-6") - except Exception as err: - logger.error("Error occured while setting voltage source mode: {}".format(err)) - -def GetInfo(device): - try: - info = device.query("*IDN?") - print(info) - return info - except Exception as err: - logger.error("Error occured while requesting the identification: {}".format(err)) - -def TurnOn(device): - try: - device.write(":OUTPUT ON") - except Exception as err: - logger.error("Error occured while turning on the device: {}".format(err)) - -def TurnOff(device): - try: - #device.write(":SOURCE:VOLTAGE:LEV 0") - device.write(":OUTPUT OFF") - except Exception as err: - logger.error("Error occured while turning off the device: {}".format(err)) - -def SetVoltageProtection(device,voltProtection = 0.0): - try: - device.write(":SOURCE:VOLTAGE:RANGE {0}".format(voltProtection)) - except Exception as err: - logger.error("Error occured while setting voltage range: {}".format(err)) - -def SetVoltage(device, voltage = 0.0): - # Set Voltage range 2V and output to 1.78V - try: - device.write(":SOURCE:VOLTAGE:LEV {0}".format(voltage)) - except Exception as err: - logger.error("Error occured while setting voltage level: {}".format(err)) - -def setComplianceLimit(device, compcurrent = 0.0): - try: - device.write(":SENSE:CURR:PROT {0}".format(compcurrent)) - except Exception as err: - logger.error("Error occured while setting compliance: {}".format(err)) -def ReadOutputStatus(device): - device.write(":OUTPUT?") - outputstatus = device.read() - return outputstatus - -def ReadVoltage(device): - try: - device.write(":FORM:ELEM VOLT") - device.write(' :SENSE:FUNCTION "VOLT" ') - #device.read_termination = '\r' - device.write(':READ?') - Measure = device.read() - MeasureVolt = float(Measure) - return MeasureVolt - except Exception as err: - logger.error("Error occured while reading voltage value: {}".format(err)) - -def ReadCurrent(device): - try: - device.write(":FORM:ELEM CURR") - device.write(' :SENSE:FUNCTION "CURR" ') - #device.read_termination = '\r' - device.write(':READ?') - Measure = device.read() - MeasureCurr = float(Measure) - return MeasureCurr - except Exception as err: - logger.error("Error occured while reading current value: {}".format(err)) - -def RampingUpVoltage(device, hvTarget, stepLength): - try: - device.write(":FORM:ELEM VOLT") - device.write(' :SENSE:FUNCTION "VOLT" ') - #device.read_termination = '\r' - device.write(':READ?') - Measure = device.read() - currentVoltage = float(Measure) - - if hvTarget < currentVoltage: - stepLength = -abs(stepLength) - - for voltage in range(int(currentVoltage), int(hvTarget), int(stepLength)): - device.write(":SOURCE:VOLTAGE:LEV {0}".format(voltage)) - time.sleep(0.3) - device.write(":SOURCE:VOLTAGE:LEV {0}".format(hvTarget)) - except Exception as err: - logger.error("Error occured while ramping up the voltage to {0}, {1}".format(hvTarget,err)) \ No newline at end of file diff --git a/Gui/python/KeySightE3633RS232.py b/Gui/python/KeySightE3633RS232.py deleted file mode 100644 index fe43c1a1..00000000 --- a/Gui/python/KeySightE3633RS232.py +++ /dev/null @@ -1,110 +0,0 @@ -import logging -import time -logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') -logger = logging.getLogger(__name__) - -def InitialDevice(device): - try: - #device.write("*RST") - device.write(":SYSTEM:REMOTE") - #SetRemote(device) - except Exception as err: - logger.error("Error occured while restore defaults: {}".format(err)) - # Select voltage source mode - -def Reset(device): - try: - device.write("*RST") - except Exception as err: - logger.error("Error while resetting {}".format(err)) - -def GetInfo(device): - try: - info = device.query("*IDN?") - return info - except Exception as err: - logger.error("Error occured while requesting the identification: {}".format(err)) - -def TurnOn(device): - try: - device.write(":OUTPUT ON") - except Exception as err: - logger.error("Error occured while turning on the device: {}".format(err)) - -def TurnOff(device): - try: - device.write(":OUTPUT OFF") - except Exception as err: - logger.error("Error occured while turning off the device: {}".format(err)) - -def ApplyCurrent(device, voltage=0.0, current=0.0): - try: - device.write("VOLT {}".format(voltage)) - device.write("CURR {}".format(current)) - except Exception as err: - logger.error("Error occured while apply V = {0} V, I = {1} Amp".format(voltage,current)) - -def SetVoltage(device, voltage = 0.0, VoltProtection = 0.0): - # Set Voltage range 2V and output to 1.78V - try: - #reply = device.write(":SOURCE:VOLTAGE:PROTECTION:STATE ON") - #state = device.query(":SOURCE:VOLTAGE:PROTECTION:STATE?") - #if not state: - # logging.info("Voltage protection state: OFF") - #reply = device.write(":SOURCE:VOLTAGE:PROTECTION:LEV {0}".format(VoltProtection)) - #time.sleep(0.3) - #reply = device.query(":SOURCE:VOLTAGE:PROTECTION:LEV?") - #print(reply) - #time.sleep(0.05) - reply = device.write(":SOURCE:VOLTAGE:LEV:IMM {0}".format(voltage)) - except Exception as err: - logger.error("Error occured while setting voltage level: {}".format(err)) - -def SetCurrent(device, current, isMax = False): - try: - if isMax: - reply = device.write(":SOURCE:CURRENT:LEV:IMM 10") - else: - reply = device.write(":SOURCE:CURRENT:LEV:IMM {0}".format(current)) - except Exception as err: - logger.error("Error occured while setting current level: {}".format(err)) - -def SetVoltageProtection(device, voltRange = 0): - try: - reply = device.write(":SOURCE:VOLTAGE:PROTECTION:LEV {0}".format(voltRange)) - except Exception as err: - logger.error("Error occured while setting voltage level: {}".format(err)) - -def setComplianceLimit(device, compcurrent = 0.0): - ## Current limit should be passed as argument - try: - #device.write(":SOURCE:CURR:PROTECTION:STATE ON") - #state = device.query(":SOURCE:CURR:PROTECTION:STATE?") - #if not state: - # logging.info("Current protection state: OFF") - device.write(":SOURCE:CURR:PROTECTION:LEV {0}".format(compcurrent)) - except Exception as err: - logger.error("Error occured while setting compliance: {}".format(err)) - -def ReadVoltage(device): - try: - MeasureVolt = device.query("MEASURE:VOLTAGE?") - #MeasureVolt = float(Measure.split(',')[0]) - return float(MeasureVolt) - except Exception as err: - logger.error("Error occured while reading voltage value: {}".format(err)) - -def ReadCurrent(device): - try: - MeasureCurr = device.query("MEASURE:CURRENT?") - #MeasureCurr = float(Measure.split(',')[0]) - return float(MeasureCurr) - except Exception as err: - logger.error("Error occured while reading current value: {}".format(err)) - -def Status(device): - try: - status = device.query("STAT:QUES:COND?") - return status - except Exception as err: - logger.error("Error occured while getting status: {}".format(err)) diff --git a/Gui/python/PSIColdbox.py b/Gui/python/PSIColdbox.py index ba4ca056..6d427ca3 100644 --- a/Gui/python/PSIColdbox.py +++ b/Gui/python/PSIColdbox.py @@ -1,7 +1,6 @@ from paho.mqtt import client as mqtt_client -from paho.mqtt.enums import CallbackAPIVersion from time import sleep, time -import threading +import threading # Define monitoring payload types payload_types = { @@ -26,29 +25,30 @@ "flowswitch_status": int, # < 0 means not implemented, 0 means bad, otherwise good "throttle": int, }, - 'Supply_U': [float] * 8, - 'Supply_P': [float] * 8, - 'Supply_I': [float] * 8, - 'Peltier_U': [float] * 8, - 'Peltier_P': [float] * 8, - 'Peltier_I': [float] * 8, - 'Peltier_R': [float] * 8, - 'ControlVoltage_Set': [float] * 8, - 'Error': [int] * 8, # TEC controller errors in hex format (leading '0x') - 'Mode': [int] * 8, - 'Temp_Diff': [float] * 8, - 'Temp_M': [float] * 8, - 'Temp_Set': [float] * 8, - 'Temp_W': [float] * 8, - 'PID_Max': [float] * 8, - 'PID_Min': [float] * 8, - 'PID_kd': [float] * 8, - 'PID_ki': [float] * 8, - 'PID_kp': [float] * 8, - 'PowerState': [int] * 8, - 'Ref_U': [float] * 8, + "Supply_U": [float] * 8, + "Supply_P": [float] * 8, + "Supply_I": [float] * 8, + "Peltier_U": [float] * 8, + "Peltier_P": [float] * 8, + "Peltier_I": [float] * 8, + "Peltier_R": [float] * 8, + "ControlVoltage_Set": [float] * 8, + "Error": [int] * 8, # TEC controller errors in hex format (leading '0x') + "Mode": [int] * 8, + "Temp_Diff": [float] * 8, + "Temp_M": [float] * 8, + "Temp_Set": [float] * 8, + "Temp_W": [float] * 8, + "PID_Max": [float] * 8, + "PID_Min": [float] * 8, + "PID_kd": [float] * 8, + "PID_ki": [float] * 8, + "PID_kp": [float] * 8, + "PowerState": [int] * 8, + "Ref_U": [float] * 8, } + # General conversion function def convert(payload): payload_type, payload_data = payload.split("=", 1) @@ -64,24 +64,24 @@ def convert(payload): # Special parsing for 'VAR' payload payload_dict = {} for key, value in zip(payload_types["VAR"], payload_list): - if value.startswith(('G', 'Y', 'R', 'L', 'I', 'D', 'F', 'T')): + if value.startswith(("G", "Y", "R", "L", "I", "D", "F", "T")): # Extract numeric part from strings like 'G0', 'Y1' # Handle traffic light - if value.startswith(('G', 'Y', 'R')): + if value.startswith(("G", "Y", "R")): payload_dict[key] = "off" if int(value[1:]) == 1: payload_dict[key] = "on" # Handle lid sensor - elif value.startswith('L'): + elif value.startswith("L"): payload_dict[key] = "open" if int(value[1:]) == 1: payload_dict[key] = "locked" # Handle interlock status - elif value.startswith('I'): + elif value.startswith("I"): payload_dict[key] = "bad" if int(value[1:]) == 1: payload_dict[key] = "good" - elif value.startswith('F'): + elif value.startswith("F"): payload_dict[key] = "bad" if int(value[1:]) < 0: payload_dict[key] = "not implemented" @@ -97,22 +97,38 @@ def convert(payload): # Convert to dictionary for 'Env' type payload_dict = dict(zip(payload_types["Env"], payload_list)) for key, value in payload_dict.items(): - payload_dict[key] = payload_types["Env"][key](value) if value.lower() != "nan" else None + payload_dict[key] = ( + payload_types["Env"][key](value) if value.lower() != "nan" else None + ) return {"Env": payload_dict} elif payload_type == "Error": # Error returns hex values, convert to integers - return {payload_type: [payload_types[payload_type][i](value, 16) if value.lower() != "nan" else None for i, value in enumerate(payload_list)]} - + return { + payload_type: [ + payload_types[payload_type][i](value, 16) + if value.lower() != "nan" + else None + for i, value in enumerate(payload_list) + ] + } + elif isinstance(payload_types[payload_type], list): # General handling for list-based payloads (e.g., 'Peltier_U', 'Peltier_R', etc.) - return {payload_type: [payload_types[payload_type][i](value) if value.lower() != "nan" else None for i, value in enumerate(payload_list)]} + return { + payload_type: [ + payload_types[payload_type][i](value) + if value.lower() != "nan" + else None + for i, value in enumerate(payload_list) + ] + } raise ValueError(f"Unhandled payload type: {payload_type}") - + class ColdboxMonitor: - """ essentially Clemens' MonTessieClient + """essentially Clemens' MonTessieClient threaded, monitors tessies 'monTessie' topic provides @@ -120,7 +136,6 @@ class ColdboxMonitor: * read access to cached monitor data """ - def __init__(self, host, topic="monTessie", error_callback=None): """ Initialize the MonTessie MQTT client. @@ -148,11 +163,17 @@ def on_connect(self, client, userdata, flags, reason_code, properties=None): print(f"Connected to {self.host} successfully.") client.subscribe(self.topic) else: - print(f"Failed to connect to {self.host}, reason code: {reason_code}. Retrying...") + print( + f"Failed to connect to {self.host}, reason code: {reason_code}. Retrying..." + ) - def on_disconnect(self, client, userdata, disconnect_flags, reason_code, properties=None): + def on_disconnect( + self, client, userdata, disconnect_flags, reason_code, properties=None + ): """Callback for disconnection.""" - print(f"Disconnected from {self.host}. Reason code: {reason_code}. Reconnecting...") + print( + f"Disconnected from {self.host}. Reason code: {reason_code}. Reconnecting..." + ) threading.Thread(target=self.reconnect, daemon=True).start() def reconnect(self): @@ -188,7 +209,7 @@ def on_message(self, client, userdata, msg): with self.lock: for key in converted_payload: self.messages[key] = converted_payload[key] - + except Exception as e: print(f"Failed to process message: {e}") print(f"payload = '{payload}'") @@ -199,7 +220,9 @@ def start(self): self.client.connect(self.host, 1883, 60) self.client.loop_start() except Exception as e: - print(f"Failed to connect to {self.host}: {e}. Retrying in the background...") + print( + f"Failed to connect to {self.host}: {e}. Retrying in the background..." + ) threading.Thread(target=self.reconnect, daemon=True).start() def stop(self): @@ -213,56 +236,55 @@ def get(self, key): if key in self.messages: with self.lock: return self.messages[key] - + if key not in payload_types: - print("unknown key ",key) + print("unknown key ", key) return None return None - + class Tessie: """ - This class represents a client for the Tessie MQTT communication system. - - Attributes: - broker (str): The address of the MQTT broker. - port (int): The port number of the MQTT broker. - topic (str): The topic to subscribe to. - _client (mqtt_client.Client): The MQTT client object. - waiting (List[str]): A list of variables that are waiting to be received. - found (List[str, str]): A list of received variables and their corresponding values. - - Methods: - __init__(self): - Initializes the Tessie client by setting the attributes, connecting to the MQTT broker, and subscribing to the topic. - on_connect(client, userdata, flags, rc): - A callback function that is called when the client successfully connects to the MQTT broker. - _connect_mqtt(self): - Connects to the MQTT broker. - decode_msg(msg: str): - Decodes a received message and stores it in the `found` list if it matches a waiting variable. - on_message(client, userdata, msg_recv): - A callback function that is called when a message is received on the subscribed topic. - _subscribe(self): - Subscribes to the specified topic. - _wait_for_var(var): - Waits for a specified variable to be received and returns its value. - get(self, var, args=""): - Sends a request to get the value of a specified variable. Returns the value of the variable. - set(self, var, data, args=""): - Sends a request to set the value of a specified variable to a specified value. - cmd(self, cmd, args=""): - Sends a command to the Tessie system. - help(self): - Sends a request for help on the Tessie system. - """ + This class represents a client for the Tessie MQTT communication system. + + Attributes: + broker (str): The address of the MQTT broker. + port (int): The port number of the MQTT broker. + topic (str): The topic to subscribe to. + _client (mqtt_client.Client): The MQTT client object. + waiting (List[str]): A list of variables that are waiting to be received. + found (List[str, str]): A list of received variables and their corresponding values. + + Methods: + __init__(self): + Initializes the Tessie client by setting the attributes, connecting to the MQTT broker, and subscribing to the topic. + on_connect(client, userdata, flags, rc): + A callback function that is called when the client successfully connects to the MQTT broker. + _connect_mqtt(self): + Connects to the MQTT broker. + decode_msg(msg: str): + Decodes a received message and stores it in the `found` list if it matches a waiting variable. + on_message(client, userdata, msg_recv): + A callback function that is called when a message is received on the subscribed topic. + _subscribe(self): + Subscribes to the specified topic. + _wait_for_var(var): + Waits for a specified variable to be received and returns its value. + get(self, var, args=""): + Sends a request to get the value of a specified variable. Returns the value of the variable. + set(self, var, data, args=""): + Sends a request to set the value of a specified variable to a specified value. + cmd(self, cmd, args=""): + Sends a command to the Tessie system. + help(self): + Sends a request for help on the Tessie system. + """ - def __init__(self, broker, topic='ctrlTessie'): + def __init__(self, broker, topic="ctrlTessie"): self.broker = broker self.port = 1883 self.topic = topic - client_id = 'Python Tessie Client' - self._client = mqtt_client.Client(mqtt_client.CallbackAPIVersion.VERSION2) + self._client = mqtt_client.Client(mqtt_client.CallbackAPIVersion.VERSION2) Tessie.waiting = [] Tessie.found = [] self._connect_mqtt() @@ -296,15 +318,15 @@ def decode_msg(msg: str): @staticmethod def on_message(client, userdata, msg_recv): - if msg_recv.payload.decode().startswith('get'): + if msg_recv.payload.decode().startswith("get"): return - if msg_recv.payload.decode().startswith('set'): + if msg_recv.payload.decode().startswith("set"): return - if msg_recv.payload.decode().startswith('cmd'): + if msg_recv.payload.decode().startswith("cmd"): return - if msg_recv.payload.decode().startswith('help'): + if msg_recv.payload.decode().startswith("help"): return - if msg_recv.payload.decode().startswith('>'): + if msg_recv.payload.decode().startswith(">"): print(msg_recv.payload.decode()) return # print('recv: ' + msg_recv.payload.decode()) @@ -328,51 +350,51 @@ def _wait_for_var(var): return msg[1] def get(self, var, args="") -> str: - msg = 'get ' + var + args + msg = "get " + var + args Tessie.waiting.append(var) # print('send ' + msg) if self._client.publish(self.topic, msg)[0] != 0: - print(f'Failed to send message: {msg}') + print(f"Failed to send message: {msg}") result = Tessie._wait_for_var(var) if not result: - print('no result') + print("no result") return False if not result.startswith(var): - print('wrong result') + print("wrong result") return False - result = result[len(var) + 3:] + result = result[len(var) + 3 :] # print(result) return result def set(self, var, data, args=""): - msg = 'set ' + str(var) + ' ' + str(data) + args + msg = "set " + str(var) + " " + str(data) + args # print('send ' + msg) if self._client.publish(self.topic, msg)[0] != 0: - print(f'Failed to send message: {msg}') + print(f"Failed to send message: {msg}") def cmd(self, cmd, args="", answer=False): - msg = 'cmd ' + cmd + args + msg = "cmd " + cmd + args # print('send ' + msg) if answer: Tessie.waiting.append(cmd) if self._client.publish(self.topic, msg)[0] != 0: - print(f'Failed to send message: {msg}') + print(f"Failed to send message: {msg}") if answer: result = Tessie._wait_for_var(cmd) if not result: - print('no result') + print("no result") return False if not result.startswith(cmd): - print('wrong result') + print("wrong result") return False - result = result[len(cmd) + 3:] + result = result[len(cmd) + 3 :] # print(result) return result def help(self): - msg = 'help' + msg = "help" if self._client.publish(self.topic, msg)[0] != 0: - print(f'Failed to send message: {msg}') + print(f"Failed to send message: {msg}") class Valve: @@ -405,9 +427,8 @@ def getTempWater(self): def getVprobe(self, number): data = self._tessie.get(f"vprobe{number}") - return [float(x) for x in data.split(",")] # returns [-999.0] if not available + return [float(x) for x in data.split(",")] # returns [-999.0] if not available - class ConfTEC: def __init__(self, tessie: Tessie, i): @@ -424,9 +445,11 @@ def saveToFlash(self): return self._tessie.cmd("SaveVariables", self.name, True) def getPID(self): - return [self._single(self._tessie.get("PID_kp", self.name)), - self._single(self._tessie.get("PID_ki", self.name)), - self._single(self._tessie.get("PID_kd", self.name))] + return [ + self._single(self._tessie.get("PID_kp", self.name)), + self._single(self._tessie.get("PID_ki", self.name)), + self._single(self._tessie.get("PID_kd", self.name)), + ] def setPID(self, kp: float, ki: float, kd: float): self._tessie.set("PID_kp", str(kp), self.name) @@ -434,8 +457,10 @@ def setPID(self, kp: float, ki: float, kd: float): self._tessie.set("PID_kd", str(kd), self.name) def getPIDMinMax(self): - return [self._single(self._tessie.get("PID_Min", self.name)), - self._single(self._tessie.get("PID_Max", self.name))] + return [ + self._single(self._tessie.get("PID_Min", self.name)), + self._single(self._tessie.get("PID_Max", self.name)), + ] def setPIDMinMax(self, pidmin, pidmax): self._tessie.set("PID_Min", str(round(pidmin, 1)), self.name) @@ -486,10 +511,12 @@ def getTemp(self): return self._single(self._tessie.get("Temp_M", self.name)) def getUI(self): - return [self._single(self._tessie.get("Supply_U", self.name)), - self._single(self._tessie.get("Supply_I", self.name)), - self._single(self._tessie.get("Peltier_U", self.name)), - self._single(self._tessie.get("Peltier_I", self.name))] + return [ + self._single(self._tessie.get("Supply_U", self.name)), + self._single(self._tessie.get("Supply_I", self.name)), + self._single(self._tessie.get("Peltier_U", self.name)), + self._single(self._tessie.get("Peltier_I", self.name)), + ] def setTemp(self, temp: float): self._tessie.set("Temp_Set", str(round(temp)), self.name) @@ -509,18 +536,17 @@ def loadFromFlash(self): def getSWVersion(self): return self._tessie.cmd("GetSWVersion", self.name, True) - - class Coldbox: - """ + """ colbox controller based on Noah code allows two styles of access: a) through component objects, e.g. coldbox.valve0.set(1) b) through getters/setters e.g. coldbox.flush("on") an optional callback function is called in case of alarms """ - def __init__(self,host='coldbox02', error_callback=None): + + def __init__(self, host="coldbox02", error_callback=None): self._tessie = Tessie(host, topic="ctrlTessie") self.valve0 = Valve(self._tessie, 0) self.valve1 = Valve(self._tessie, 1) @@ -535,8 +561,18 @@ def __init__(self,host='coldbox02', error_callback=None): self.tec8 = TEC(self._tessie, 8) self.env = Env(self._tessie) - self.valid_channels = [1,2,3,4,5,6,7,8] - self._tecs = [self.tecall, self.tec1, self.tec2, self.tec3, self.tec4, self.tec5, self.tec6, self.tec7, self.tec8] + self.valid_channels = [1, 2, 3, 4, 5, 6, 7, 8] + self._tecs = [ + self.tecall, + self.tec1, + self.tec2, + self.tec3, + self.tec4, + self.tec5, + self.tec6, + self.tec7, + self.tec8, + ] self.monitor = ColdboxMonitor( host=host, @@ -546,58 +582,61 @@ def __init__(self,host='coldbox02', error_callback=None): def __enter__(self): self.monitor.start() - + def __exit__(self, *args): self.monitor.stop() self._tessie.stop() - #print("exit", args) - + # print("exit", args) def channel_arg(self, arg, caller=""): - """ helper for handling channel arguments """ + """helper for handling channel arguments""" if arg in (0, "all"): return [0] elif arg in self.valid_channels: return [arg] - elif isinstance(arg, list) and all(channel in self.valid_channels for channel in arg): + elif isinstance(arg, list) and all( + channel in self.valid_channels for channel in arg + ): return arg - elif isinstance(arg, tuple) and all(channel in self.valid_channels for channel in arg): + elif isinstance(arg, tuple) and all( + channel in self.valid_channels for channel in arg + ): return arg else: - print("Coldbox.{caller} : invalid channel argument ",arg) + print("Coldbox.{caller} : invalid channel argument ", arg) return [] - # pass-through functions for data available in the control topic - def get_air_temperature(self)->float: - """ query the the air temperature sensor""" + # pass-through functions for data available in the control topic + def get_air_temperature(self) -> float: + """query the the air temperature sensor""" return self.env.getTempAir() - def get_water_temperature(self)->float: - """ query the the air temperature sensor""" + def get_water_temperature(self) -> float: + """query the the air temperature sensor""" return self.env.getTempWater() - def get_relative_humidity(self)->float: - """ query the the relative humidity sensor""" + def get_relative_humidity(self) -> float: + """query the the relative humidity sensor""" return self.env.getRH() - - def get_dewpoint(self)->float: - """ query the dewpoint""" + + def get_dewpoint(self) -> float: + """query the dewpoint""" return self.env.getDP() - def get_tec_temperature(self, channel = 0): - """ tec temperatures of either of a single channel or all channels (channel=0)""" + def get_tec_temperature(self, channel=0): + """tec temperatures of either of a single channel or all channels (channel=0)""" return self._tec_get_property(channel, "Temp_M") if channel in (0, "all"): return self.tecall.getTemp() elif channel in self.valid_channels: return self._tecs[channel].getTemp() - + def rinse(self): - """ switch N2 to 'rinse'""" + """switch N2 to 'rinse'""" self.flush("rinse") - + def flush(self, cmd="flush"): - """ control the N2 valves. Possible options are + """control the N2 valves. Possible options are "flush", "on" : start flushing "rinse" : start rinsing "both" : open both valves @@ -616,10 +655,9 @@ def flush(self, cmd="flush"): self.valve0.set(0) self.valve1.set(0) - - def get_monitor_data(self, key, timeout = 0): - """ get data from the monitor topic""" - if not key in payload_types: + def get_monitor_data(self, key, timeout=0): + """get data from the monitor topic""" + if key not in payload_types: print("unknown key ", key) return None @@ -629,65 +667,69 @@ def get_monitor_data(self, key, timeout = 0): return result sleep(1) return None - - + def get_interlock_status(self, timeout=0): - """ get the interlock status, "good" | "bad" """ + """get the interlock status, "good" | "bad" """ var = self.get_monitor_data("VAR", timeout) if var is None: return "unknown" return var["interlock_status"] - def get_flow_switch(self, timeout=0): - """ get the flow switch status: "good" | "bad" | "not available" """ + """get the flow switch status: "good" | "bad" | "not available" """ var = self.get_monitor_data("VAR", timeout) if var is None: return "unknown" return var["flowswitch_status"] def get_lid_status(self, timeout=0): - """ get the lid status : "open" | "locked" """ + """get the lid status : "open" | "locked" """ var = self.get_monitor_data("VAR", timeout) if var is None: return "unknown" return var["lid_status"] def get_traffic_light(self, timeout=0): - """ get the status of the 'traffic light' as a dictionary + """get the status of the 'traffic light' as a dictionary {"green" : "on"|"off", "yellow" : "on"|"off", "red" : "on" | "off"} """ var = self.get_monitor_data("VAR", timeout) if var is None: - return {"unknown" for color in ("green","yellow","red")} - return {color:var[color] for color in ("green","yellow","red")} - - - def tec(self, channels=0, cmd=None, voltage = None, temperature = None): - """ control tec settings, cmd = "on" | "off" + return {"unknown" for color in ("green", "yellow", "red")} + return {color: var[color] for color in ("green", "yellow", "red")} + + def tec(self, channels=0, cmd=None, voltage=None, temperature=None): + """control tec settings, cmd = "on" | "off" voltage or temperature can be set, the mode is chosen to which value is present """ - + channels = self.channel_arg(channels, "tec") - + if cmd in ("off", "poff"): for c in channels: self._tecs[c].poff() - if isinstance(temperature,float) and voltage is None: + if isinstance(temperature, float) and voltage is None: for c in channels: self._tecs[c].setTemp(temperature) elif isinstance(voltage, float) and temperature is None: for c in channels: self._tecs[c].setVoltage(voltage) - + if cmd in ("on", "pon"): for c in channels: self._tecs[c].pon() def _tec_get_property(self, channel, key): - """ query tec values in the control topic, for either a single channel or all (channel=0)""" - if key in ("Temp_M", "PowerState", "Supply_U", "Supply_I", "Peltier_U", "Peltier_I"): + """query tec values in the control topic, for either a single channel or all (channel=0)""" + if key in ( + "Temp_M", + "PowerState", + "Supply_U", + "Supply_I", + "Peltier_U", + "Peltier_I", + ): if channel in (0, "all"): tec = self.tecall return tec._single(tec._tessie.get(key, tec.name)) @@ -700,43 +742,47 @@ def _tec_get_property(self, channel, key): else: print("unknown tec property", key) return None - + def get_tec_state(self, channel=0): - """ query the on/off state of a tec channel or all channels """ + """query the on/off state of a tec channel or all channels""" return self._tec_get_property(channel, "PowerState") - def on(self): - """ turn on all tecs """ + """turn on all tecs""" self.tecall.pon() def off(self): - """ turn off all tecs """ + """turn off all tecs""" self.tecall.poff() - def get_voltage_probe(self, channel): - """ return a dictionary with voltages or None if no probecard connected + """return a dictionary with voltages or None if no probecard connected for single channels only, channel must be an integer from [1..8] """ - if not channel in self.valid_channels: - print("Coldbox.get_voltage_probe : invalid channel ",channel) + if channel not in self.valid_channels: + print("Coldbox.get_voltage_probe : invalid channel ", channel) return None - + vprobe_names = [ - "VIN", "Voff1/2", "vdda0", "vddd0", - "vdda1", "vddd1", "vdda2", "vddd2", - "vdda3", "vddd3" + "VIN", + "Voff1/2", + "vdda0", + "vddd0", + "vdda1", + "vddd1", + "vdda2", + "vddd2", + "vdda3", + "vddd3", ] v = self.env.getVprobe(channel) try: - return {vprobe_names[n]:v[n] for n in range(10)} + return {vprobe_names[n]: v[n] for n in range(10)} except TypeError: return None - def handle_error_message(error_payload): """ Custom callback to handle "Error" messages. @@ -746,11 +792,9 @@ def handle_error_message(error_payload): print(error_payload) - if __name__ == "__main__": - # initialize the Coldbox controller and provide a callback for alarms - coldbox = Coldbox(host='coldbox02.psi.ch', error_callback=handle_error_message) + coldbox = Coldbox(host="coldbox02.psi.ch", error_callback=handle_error_message) with coldbox: coldbox.flush() @@ -761,13 +805,16 @@ def handle_error_message(error_payload): print("flow switch ", coldbox.get_flow_switch()) print("lid ", coldbox.get_lid_status()) channel = 8 - print(f"voltage probes for channel {channel} = ", coldbox.get_voltage_probe(channel)) + print( + f"voltage probes for channel {channel} = ", + coldbox.get_voltage_probe(channel), + ) try: while True: print("relative humidity ", coldbox.get_relative_humidity()) sleep(10) except KeyboardInterrupt: - print('interrupted!') - + print("interrupted!") + print("shutting down") diff --git a/Gui/python/Peltier.py b/Gui/python/Peltier.py index fae0150a..72cf21af 100644 --- a/Gui/python/Peltier.py +++ b/Gui/python/Peltier.py @@ -1,19 +1,21 @@ #!/usr/bin/env python3 import serial from Gui.siteSettings import defaultPeltierPort, defaultPeltierBaud -#from PyQt5 import QtCore -#from PyQt5.QtCore import * -#from PyQt5 import QtSerialPort -#from PyQt5.QtWidgets import QMessageBox import time from Gui.python.logging_config import logger class PeltierSignalGenerator: def __init__(self): - #print("Connecting Peltier Port") - self.ser = serial.Serial(defaultPeltierPort, defaultPeltierBaud, timeout=5, write_timeout=5, inter_byte_timeout=5) - #print("Peltier connected") + # print("Connecting Peltier Port") + self.ser = serial.Serial( + defaultPeltierPort, + defaultPeltierBaud, + timeout=5, + write_timeout=5, + inter_byte_timeout=5, + ) + # print("Peltier connected") self.commandDict = { "Input1": ["0", "1"], "Desired Control Value": ["0", "3"], @@ -39,7 +41,7 @@ def __init__(self): "Heat Multiplier Write": ["0", "c"], "Heat Multiplier Read": ["5", "c"], "Cool Multiplier Write": ["0", "d"], - "Cool Multiplier Read": ["5", "d"] + "Cool Multiplier Read": ["5", "d"], } self.checksumError = [ "*", @@ -70,14 +72,14 @@ def possibleCommands(self): @staticmethod def convertToHex(val): - if type(val) != list: + if type(val) is not list: return hex(val) for i, item in enumerate(val): val[i] = hex(ord(item)) return val def convertHexToDec(self, hex): - if type(hex) != list: + if type(hex) is not list: return int(hex, 16) else: for i, val in enumerate(hex): @@ -95,11 +97,10 @@ def checksum(self, command): # Used for all other commands that are not setTemp # Currently you need to format dd yourself which is the input value you want to send - def createCommand(self, command:str , dd:list[str]): + def createCommand(self, command: str, dd: list[str]): stx = ["*"] aa = ["0", "0"] cc = self.commandDict[command] - check = aa + cc + dd ss = self.checksum(aa + cc + dd) etx = ["\r"] command = stx + aa + cc + dd + ss + etx @@ -114,7 +115,8 @@ def sendCommand(self, command): message, passed = self.recieveMessage() logger.debug(f"Recieved message: {message}") return message, passed - except: + except Exception as e: + print(f"Failed to send command to Peltier due to error: {e}") return None, False # Will recieve message but will only check if the command gave an error, will not decode the message @@ -157,7 +159,7 @@ def convertSetTempValueToList(self, temp: float) -> list: def convertSetTempListToValue(self, temp: list) -> float: """ Convienience function to convert return value from peltier to a decimal temperature. The input to this - function should be the output of sendCommand() after sending a command to read some temperature. + function should be the output of sendCommand() after sending a command to read some temperature. """ temp = temp[1:9] temp = "".join(temp) diff --git a/Gui/python/QResultDialog.py b/Gui/python/QResultDialog.py index 572c0bd9..92b9bac0 100644 --- a/Gui/python/QResultDialog.py +++ b/Gui/python/QResultDialog.py @@ -1,45 +1,14 @@ -#from PyQt5 import QtCore -#from PyQt5.QtCore import * -#from PyQt5.QtGui import QFont, QPixmap, QPalette, QImage, QIcon +# from PyQt5 import QtCore +# from PyQt5.QtCore import * +# from PyQt5.QtGui import QFont, QPixmap, QPalette, QImage, QIcon from PyQt5.QtWidgets import ( - QApplication, - QButtonGroup, - QCheckBox, - QComboBox, - QDateTimeEdit, - QDial, QDialog, - QFormLayout, - QFrame, QGridLayout, - QGroupBox, - QHBoxLayout, QLabel, - QLineEdit, - QProgressBar, QPushButton, - QRadioButton, - QScrollBar, - QSizePolicy, - QSlider, - QSpinBox, - QStyleFactory, - QTableWidget, - QTabWidget, - QTextEdit, - QHBoxLayout, - QVBoxLayout, - QWidget, - QMainWindow, - QMessageBox, ) from PyQt5 import QtSvg -import sys -import os -import re -from Gui.python.logging_config import logger - class QResultDialog(QDialog): def __init__(self, parent=None, image=None): diff --git a/Gui/python/ROOTInterface.py b/Gui/python/ROOTInterface.py index 9052c723..f2f95154 100644 --- a/Gui/python/ROOTInterface.py +++ b/Gui/python/ROOTInterface.py @@ -78,7 +78,6 @@ def DirectoryVLR(node, depth): def showDirectory(nodes): for node in nodes: - keyName = node.getKeyName() DirectoryVLR(node, 0) @@ -95,7 +94,7 @@ def TCanvas2JPG(outputDir, canvas, name=None): canvas.Print(outputFile) # canvas.Close() logger.info(outputFile + " is saved") - except: + except OSError: logger.warning("Failed to save " + outputFile) return outputFile @@ -113,9 +112,9 @@ def TCanvas2SVG(outputDir, canvas, name=None): if "SCurve" in name: canvas.SetLogz() if "PixelAlive" in name: - ROOT.gStyle.SetOptStat(0) #no statistics box + ROOT.gStyle.SetOptStat(0) # no statistics box else: - ROOT.gStyle.SetOptStat(1111) #default statistics box + ROOT.gStyle.SetOptStat(1111) # default statistics box canvas.Print(outputFile) # canvas.Close() logger.info(outputFile + " is saved") @@ -129,7 +128,7 @@ def GetBinary(fileName): return binaryData -#@precondition: commands must be a list of strings representing valid root shell commands +# @precondition: commands must be a list of strings representing valid root shell commands def executeCommandSequence(commands: list): for command in commands: ROOT.gROOT.ProcessLine(command) diff --git a/Gui/python/ResultTreeWidget.py b/Gui/python/ResultTreeWidget.py index d2f50d8f..6fdd8be3 100644 --- a/Gui/python/ResultTreeWidget.py +++ b/Gui/python/ResultTreeWidget.py @@ -1,47 +1,23 @@ from PyQt5 import QtCore from PyQt5.QtCore import Qt, QTimer -#from PyQt5.QtGui import QPixmap + +# from PyQt5.QtGui import QPixmap from PyQt5.QtWidgets import ( - QAbstractItemView, - QApplication, - QCheckBox, - QComboBox, - QDateTimeEdit, - QDial, - QDialog, QGridLayout, - QGroupBox, - QHBoxLayout, QLabel, - QLineEdit, - QListWidget, QProgressBar, QPushButton, - QRadioButton, - QScrollBar, QScrollArea, - QSizePolicy, - QSlider, - QSpinBox, - QStyleFactory, - QTableView, - QTableWidget, - QTabWidget, - QTextEdit, QTreeWidget, QTreeWidgetItem, QWidget, - QMainWindow, ) from PyQt5 import QtSvg -import sys import os import subprocess -import logging -from functools import partial -#from Gui.GUIutils.settings import * +# from Gui.GUIutils.settings import * from Gui.GUIutils.guiUtils import isCompositeTest from Gui.python.ROOTInterface import ( GetDirectory, @@ -51,6 +27,7 @@ from Gui.python.logging_config import logger from InnerTrackerTests.TestSequences import CompositeTests + class ResultTreeWidget(QWidget): def __init__(self, info, width, height, master): super(ResultTreeWidget, self).__init__() @@ -197,13 +174,13 @@ def onItemClicked(self, item, col): temp = item.clone() while item.parent().text(0) != "Files..": item = item.parent() - runNumber = item.text(0).split('_')[0] - #print("the test is {0}".format(item.text(0))) - #print("This item is a TCanvas") + runNumber = item.text(0).split("_")[0] + # print("the test is {0}".format(item.text(0))) + # print("This item is a TCanvas") canvas = temp.data(0, Qt.UserRole) canvasname = str(temp.text(0)) canvasname = canvasname.split(";")[0] - #print("The canvas is {0}".format(canvas)) + # print("The canvas is {0}".format(canvas)) self.displayResult(canvas, canvasname, runNumber) elif "svg" in str(item.data(0, Qt.UserRole)): canvas = item.data(0, Qt.UserRole) @@ -269,7 +246,7 @@ def rightArrowFunc(self): if len(self.displayList) > 0: self.displayIndex += 1 self.showPlot() - + def leftArrowFunc(self): self.timer.start(3000) if len(self.displayList) > 0: @@ -285,7 +262,7 @@ def controlDisplay(self): self.timer.start() self.timerFrozen = False self.ControlButtom.setText("Pause") - + def updateResult(self, sourceFolder): process = subprocess.run( 'find {0} -type f -name "*.root" '.format(sourceFolder), @@ -306,9 +283,8 @@ def updateResult(self, sourceFolder): CurrentNode.setData(0, Qt.UserRole, File) self.TreeRoot.addChild(CurrentNode) self.getResult(CurrentNode, File) - - def updateIVResult(self, sourceFolder): + def updateIVResult(self, sourceFolder): process2 = subprocess.run( 'find {0} -type f -name "*IVCurve_Module_*.svg" '.format(sourceFolder), shell=True, @@ -317,9 +293,9 @@ def updateIVResult(self, sourceFolder): stepFiles2 = process2.stdout.decode("utf-8").rstrip("\n").split("\n") if stepFiles2 == [""]: - #print("No IV files found.") # Debugging output if no IV files are found + # print("No IV files found.") # Debugging output if no IV files are found return - #print("IV files found:", stepFiles2) # Debugging output to show the found IV files + # print("IV files found:", stepFiles2) # Debugging output to show the found IV files self.IVFileList += stepFiles2 @@ -328,7 +304,7 @@ def updateIVResult(self, sourceFolder): CurrentNode.setText(0, File.split("/")[-1]) CurrentNode.setData(0, Qt.UserRole, File) self.TreeRoot.addChild(CurrentNode) - #print("IV files processed.") # Debugging output to indicate IV files processing is done + # print("IV files processed.") # Debugging output to indicate IV files processing is done def updateSLDOResult(self, sourceFolder): process2 = subprocess.run( @@ -342,7 +318,9 @@ def updateSLDOResult(self, sourceFolder): print("No SLD files found.") # Debugging output if no SLD files are found return - print("SLD files found:", stepFiles2) # Debugging output to show the found SLD files + print( + "SLD files found:", stepFiles2 + ) # Debugging output to show the found SLD files self.SLDOFileList += stepFiles2 @@ -351,16 +329,18 @@ def updateSLDOResult(self, sourceFolder): CurrentNode.setText(0, File.split("/")[-1]) CurrentNode.setData(0, Qt.UserRole, File) self.TreeRoot.addChild(CurrentNode) - print("SLD files processed.") # Debugging output to indicate SLD files processing is done + print( + "SLD files processed." + ) # Debugging output to indicate SLD files processing is done def displayResult(self, canvas, name=None, runNumber=""): tmpDir = os.environ.get("GUI_dir") + f"/Gui/.tmp/{runNumber}" - #tmpDir = os.environ.get("GUI_dir") + "/Gui/.tmp" + # tmpDir = os.environ.get("GUI_dir") + "/Gui/.tmp" if not os.path.isdir(tmpDir) and os.environ.get("GUI_dir"): try: os.mkdir(tmpDir) logger.info("Creating " + tmpDir) - except: + except OSError: logger.warning("Failed to create " + tmpDir) if "svg" in str(canvas): @@ -375,6 +355,6 @@ def displayResult(self, canvas, name=None, runNumber=""): # self.update self.Plot.append(QtTCanvasWidget(self.master, svgFile)) logger.info("Displaying " + svgFile) - except: - logger.error("Failed to display " + svgFile) - pass \ No newline at end of file + except Exception as e: + logger.error("Failed to display " + svgFile + f"due to error {e}") + pass diff --git a/Gui/python/SLDOScanHandler.py b/Gui/python/SLDOScanHandler.py index 291a431d..5f79a73d 100644 --- a/Gui/python/SLDOScanHandler.py +++ b/Gui/python/SLDOScanHandler.py @@ -10,6 +10,7 @@ import numpy as np import math + class SLDOCurveWorker(QThread): finishedSignal = pyqtSignal() progressSignal = pyqtSignal(str, float) @@ -27,7 +28,7 @@ def __init__( starting_current=1, max_voltage=1.8, pin_list=[], - execute_each_step=lambda:None + execute_each_step=lambda: None, ): super().__init__() self.instruments = instrument_cluster @@ -41,8 +42,8 @@ def __init__( self.exiting = False self.moduleType = moduleType self.PIN_MAPPINGS = { - 'DEFAULT': AdcBoard.DEFAULT_PIN_MAP, - 'DOUBLE': { + "DEFAULT": AdcBoard.DEFAULT_PIN_MAP, + "DOUBLE": { # 0: 'VDDA_ROC2', # 1: 'VDDA_ROC3', # 2: 'VDDD_ROC2', @@ -54,18 +55,18 @@ def __init__( # 8: None, # 9: 'TP10', #VIN # 10: None, - 11: 'VDDA_ROC0', - 12: 'VDDA_ROC1', - 13: 'VDDD_ROC0', - 14: 'VDDD_ROC1', + 11: "VDDA_ROC0", + 12: "VDDA_ROC1", + 13: "VDDD_ROC0", + 14: "VDDD_ROC1", # 15: 'TP7A', #VOFS OUT # 16: 'TP7B', #VOFS OUT }, - 'QUAD': { - 0: 'VDDA_ROC2', - 1: 'VDDA_ROC3', - 2: 'VDDD_ROC2', - 3: 'VDDD_ROC3', + "QUAD": { + 0: "VDDA_ROC2", + 1: "VDDA_ROC3", + 2: "VDDD_ROC2", + 3: "VDDD_ROC3", # 4: 'TP7C', #VOFS OUT # 5: 'TP7D', #VOFS OUT # 6: None, @@ -73,10 +74,10 @@ def __init__( # 8: None, # 9: 'TP10', #VIN # 10: None, - 11: 'VDDA_ROC0', - 12: 'VDDA_ROC1', - 13: 'VDDD_ROC0', - 14: 'VDDD_ROC1', + 11: "VDDA_ROC0", + 12: "VDDA_ROC1", + 13: "VDDD_ROC0", + 14: "VDDD_ROC1", # 15: 'TP7A', #VOFS OUT # 16: 'TP7B', #VOFShv_off OUT }, @@ -89,13 +90,18 @@ def run(self) -> None: self.adc_board = self.instruments._instrument_dict["adc_board"] logger.info("Running with ADC.") self.runWithADC() - elif "multimeter" in self.instruments._instrument_dict.keys() and "relay_board" in self.instruments._instrument_dict.keys(): + elif ( + "multimeter" in self.instruments._instrument_dict.keys() + and "relay_board" in self.instruments._instrument_dict.keys() + ): self.multimeter = self.instruments._instrument_dict["multimeter"] self.relayboard = self.instruments._instrument_dict["relay_board"] logger.info("Running with Relay+DMM.") self.runWithRelayDMM() else: - logger.error("You do not have instruments required to run an SLDOScan connected.\nYou must have an Adc Board or (Relay Board and Multimeter).") + logger.error( + "You do not have instruments required to run an SLDOScan connected.\nYou must have an Adc Board or (Relay Board and Multimeter)." + ) def runWithADC(self) -> None: """ @@ -108,12 +114,17 @@ def runWithADC(self) -> None: # Initialize a list to store the results self.labels = [] # Turn off instruments - starting_voltages = [np.abs(getattr(module["hv"], "voltage")) for module in self.instruments._module_dict.values()] - self.instruments.hv_off(execute_each_step=lambda : self.execute_each_step(starting_voltages)) + starting_voltages = [ + np.abs(getattr(module["hv"], "voltage")) + for module in self.instruments._module_dict.values() + ] + self.instruments.hv_off( + execute_each_step=lambda: self.execute_each_step(starting_voltages) + ) self.instruments.lv_off() self.adc_board.__enter__() logger.info("Turned off the LV and HV") - + self.instruments.lv_on(current=self.starting_current, voltage=self.max_voltage) # sweep from the starting current to the target current, preliminary data processing data_up = self.instruments.lv_sweep( @@ -125,10 +136,10 @@ def runWithADC(self) -> None: measure_args={}, set_property="current", ) - + self.determineLVIndex(data_up) data_up = data_up[self.LV_index][1] - + # sweep from the target current to the starting current, preliminary data processing data_down = self.instruments.lv_sweep( target=self.starting_current, @@ -140,30 +151,30 @@ def runWithADC(self) -> None: set_property="current", )[self.LV_index][1] self.instruments.lv_off() - + # extract lv voltage and lv current LV_Voltage_Up = [res[4] for res in data_up] Currents_Up = [res[5] for res in data_up] LV_Voltage_Down = [res[4] for res in data_down] Currents_Down = [res[5] for res in data_down] - - - for index, pin in self.PIN_MAPPINGS[self.moduleType.split(" ")[-1].replace("1x2","DOUBLE").upper()].items(): - + + for index, pin in self.PIN_MAPPINGS[ + self.moduleType.split(" ")[-1].replace("1x2", "DOUBLE").upper() + ].items(): ADC_Voltage_Up = [res[6][index] for res in data_up] result_up = np.array([Currents_Up, LV_Voltage_Up, ADC_Voltage_Up]) ADC_Voltage_Down = [res[6][index] for res in data_down] result_down = np.array([Currents_Down, LV_Voltage_Down, ADC_Voltage_Down]) - + results = np.concatenate((result_up, result_down), axis=0) # 0:up current, 1:up lv voltage, 2: up adc voltage 3: down current, 4: down lv voltage, 5: down adc voltage - print('total result for pin {0}: {1}'.format(pin, results)) - + print("total result for pin {0}: {1}".format(pin, results)) + self.measure.emit(results, pin) - + # All pins have been scanned so we emit the finished signal self.finishedSignal.emit() - + def runWithRelayDMM(self) -> None: """ Run thread that will ramp up the LV while measuring from the multimeter, then ramp down doing the same thing. @@ -176,25 +187,34 @@ def runWithRelayDMM(self) -> None: self.result_list = [] self.labels = [] # Turn off instruments - starting_voltages = [np.abs(getattr(module["hv"], "voltage")) for module in self.instruments._module_dict.values()] - self.instruments.hv_off(execute_each_step=lambda : self.execute_each_step(starting_voltages)) + starting_voltages = [ + np.abs(getattr(module["hv"], "voltage")) + for module in self.instruments._module_dict.values() + ] + self.instruments.hv_off( + execute_each_step=lambda: self.execute_each_step(starting_voltages) + ) self.instruments.lv_off() - self.multimeter.set("SYSTEM_MODE","REM") - logger.info('turned off the lv and hv') - for key in self.relayboard.PIN_MAP[self.moduleType.split(" ")[-1].replace("1x2","DOUBLE").upper()].keys(): + self.multimeter.set("SYSTEM_MODE", "REM") + logger.info("turned off the lv and hv") + for key in self.relayboard.PIN_MAP[ + self.moduleType.split(" ")[-1].replace("1x2", "DOUBLE").upper() + ].keys(): if "VDD" in key: self.pin_list.append(key) - print('adding {0} to pin_list'.format(key)) + print("adding {0} to pin_list".format(key)) for pin in self.pin_list: - logger.info('made it inside the pin loop') - + logger.info("made it inside the pin loop") + # Make label for plot self.labels.append(pin) # Connect to relay pin self.setRelayPin(pin) # turn on LV - self.instruments.lv_on(current=self.starting_current, voltage=self.max_voltage) - + self.instruments.lv_on( + current=self.starting_current, voltage=self.max_voltage + ) + # sweep from the starting current to the target current, preliminary data processing results = self.instruments.lv_sweep( target=self.target_current, @@ -207,15 +227,17 @@ def runWithRelayDMM(self) -> None: ) self.determineLVIndex(results) results = results[self.LV_index][1] - + # separate measurements into different lists lvVoltageList = [res[4] for res in results] currentList = [res[5] for res in results] adcVoltageList = [res[6][0] for res in results] - + result_up = np.array([currentList, lvVoltageList, adcVoltageList]) - print(f"Currents: {currentList}\nPower Supply Voltages: {lvVoltageList}\nBoard Voltages: {adcVoltageList}") - + print( + f"Currents: {currentList}\nPower Supply Voltages: {lvVoltageList}\nBoard Voltages: {adcVoltageList}" + ) + # sweep from the target current to the starting current, preliminary data processing results = self.instruments.lv_sweep( target=self.starting_current, @@ -226,38 +248,51 @@ def runWithRelayDMM(self) -> None: measure_args={}, set_property="current", )[self.LV_index][1] - + # separate measurements into different lists lvVoltageList = [res[4] for res in results] currentList = [res[5] for res in results] adcVoltageList = [res[6][0] for res in results] - + result_down = np.array([currentList, lvVoltageList, adcVoltageList]) - print(f"Currents: {currentList}\nPower Supply Voltages: {lvVoltageList}\nBoard Voltages: {adcVoltageList}") + print( + f"Currents: {currentList}\nPower Supply Voltages: {lvVoltageList}\nBoard Voltages: {adcVoltageList}" + ) total_result = np.concatenate((result_up, result_down), axis=0) - print('total result is {0}'.format(total_result)) + print("total result is {0}".format(total_result)) self.instruments.lv_off() - - # Emit a signal that passes the list of results to the SLDOCurveHandler. + + # Emit a signal that passes the list of results to the SLDOCurveHandler. self.measure.emit(total_result, pin) - #All pins have been scanned so we emit the finished signal + # All pins have been scanned so we emit the finished signal self.finishedSignal.emit() def measureADC(self, no_lock=True, *args, **kwargs): self.updateProgress(1) return [self.adc_board.query_adc(no_lock=no_lock)] - + def measureMM(self, no_lock=True, *args, **kwargs): - self.updateProgress(len(self.pin_list)) - return [self.multimeter.measure(what="VOLT:DC", cycles=self.integration_cycles, no_lock=no_lock)] - + self.updateProgress(len(self.pin_list)) + return [ + self.multimeter.measure( + what="VOLT:DC", cycles=self.integration_cycles, no_lock=no_lock + ) + ] + def updateProgress(self, nLoops): - num_steps = math.ceil(abs(self.target_current-self.starting_current)/self.step_size)+1 - num_sweeps = 2 * nLoops * sum(1 for key in self.instruments._instrument_dict.keys() if "lv" in key) #number of LVs connected, each LV gets its own sweep - percentStep = 100/(num_steps * num_sweeps) + num_steps = ( + math.ceil(abs(self.target_current - self.starting_current) / self.step_size) + + 1 + ) + num_sweeps = ( + 2 + * nLoops + * sum(1 for key in self.instruments._instrument_dict.keys() if "lv" in key) + ) # number of LVs connected, each LV gets its own sweep + percentStep = 100 / (num_steps * num_sweeps) self.progressSignal.emit("SLDOScan", percentStep) - + def determineLVIndex(self, data): if self.LV_index == -1: for i, (_, ps) in enumerate(data): @@ -265,17 +300,19 @@ def determineLVIndex(self, data): self.LV_index = i break if self.LV_index == -1: - self.stopSignal.emit("No current was read from any LV power supply. Please ensure that a module is connected.") - + self.stopSignal.emit( + "No current was read from any LV power supply. Please ensure that a module is connected." + ) + def setRelayPin(self, pin): if not isinstance(self.relayboard, RelayBoard): return True - + current_pin = self.relayboard.query_pin() if current_pin == pin: return True - - #Ensures that LV and HV are off + + # Ensures that LV and HV are off for module in self.instruments._module_dict.values(): self.instruments.assert_status( lambda: module["lv"].state, @@ -285,7 +322,7 @@ def setRelayPin(self, pin): proposed_solution="Turn off LV", solution=lambda: self.instruments._module_off(module["lv"]), ) - + sense_function = self.multimeter.query("SENSE_FUNCTION") if ( not isinstance(sense_function, InstrumentNotInstantiated) @@ -307,21 +344,34 @@ class SLDOCurveHandler(QObject): makeplotSignal = pyqtSignal(np.ndarray, str) progressSignal = pyqtSignal(str, float) abortSignal = pyqtSignal() - #measureSignal = pyqtSignal(str, object) + # measureSignal = pyqtSignal(str, object) - def __init__(self, instrument_cluster, moduleType, end_current, voltage_limit, execute_each_step): + def __init__( + self, + instrument_cluster, + moduleType, + end_current, + voltage_limit, + execute_each_step, + ): super(SLDOCurveHandler, self).__init__() self.instruments = instrument_cluster self.end_current = end_current self.voltage_limit = voltage_limit self.execute_each_step = execute_each_step - self.test = SLDOCurveWorker(self.instruments, moduleType=moduleType, target_current=self.end_current, max_voltage=self.voltage_limit, execute_each_step=self.execute_each_step) + self.test = SLDOCurveWorker( + self.instruments, + moduleType=moduleType, + target_current=self.end_current, + max_voltage=self.voltage_limit, + execute_each_step=self.execute_each_step, + ) self.test.measure.connect(self.makePlots) self.test.progressSignal.connect(self.transmitProgress) self.test.finishedSignal.connect(self.finish) self.test.stopSignal.connect(self.stop) - #This should take the list of results and make plots. I think we should maybe move this to the TestHandler. + # This should take the list of results and make plots. I think we should maybe move this to the TestHandler. def makePlots(self, total_result, pin): self.makeplotSignal.emit(total_result, pin) @@ -334,19 +384,29 @@ def transmitProgress(self, measurementType, percentStep): self.progressSignal.emit(measurementType, percentStep) def finish(self): - starting_voltages = [np.abs(getattr(module["hv"], "voltage")) for module in self.instruments._module_dict.values()] - self.instruments.hv_off(execute_each_step=lambda : self.execute_each_step(starting_voltages)) + starting_voltages = [ + np.abs(getattr(module["hv"], "voltage")) + for module in self.instruments._module_dict.values() + ] + self.instruments.hv_off( + execute_each_step=lambda: self.execute_each_step(starting_voltages) + ) self.instruments.lv_off() self.finishedSignal.emit() - def stop(self, reason = None): - # Should only have a reason internally where the abort signal is necessary. + def stop(self, reason=None): + # Should only have a reason internally where the abort signal is necessary. # External calls can handle abort themselves. Avoiding accidental recursion. if reason: print(f"Aborting SLDO Scan. Reason: {reason}") try: - starting_voltages = [np.abs(getattr(module["hv"], "voltage")) for module in self.instruments._module_dict.values()] - self.instruments.hv_off(execute_each_step=lambda : self.execute_each_step(starting_voltages)) + starting_voltages = [ + np.abs(getattr(module["hv"], "voltage")) + for module in self.instruments._module_dict.values() + ] + self.instruments.hv_off( + execute_each_step=lambda: self.execute_each_step(starting_voltages) + ) self.instruments.lv_off() self.test.terminate() self.abortSignal.emit() @@ -354,9 +414,14 @@ def stop(self, reason = None): logger.error(f"Failed to stop the SLDO test due to error {err}") else: try: - starting_voltages = [np.abs(getattr(module["hv"], "voltage")) for module in self.instruments._module_dict.values()] - self.instruments.hv_off(execute_each_step=lambda : self.execute_each_step(starting_voltages)) + starting_voltages = [ + np.abs(getattr(module["hv"], "voltage")) + for module in self.instruments._module_dict.values() + ] + self.instruments.hv_off( + execute_each_step=lambda: self.execute_each_step(starting_voltages) + ) self.instruments.lv_off() self.test.terminate() except Exception as err: - logger.error(f"Failed to stop the SLDO test due to error {err}") \ No newline at end of file + logger.error(f"Failed to stop the SLDO test due to error {err}") diff --git a/Gui/python/SimplifiedMainWidget.py b/Gui/python/SimplifiedMainWidget.py index 16096cc9..107a4e25 100644 --- a/Gui/python/SimplifiedMainWidget.py +++ b/Gui/python/SimplifiedMainWidget.py @@ -21,16 +21,13 @@ from Gui.QtGUIutils.QtRunWindow import QtRunWindow from Gui.GUIutils.FirmwareUtil import fwStatusParser -from Gui.python.CustomizedWidget import SimpleBeBoardBox, SimpleModuleBox +from Gui.python.CustomizedWidget import SimpleBeBoardBox from Gui.python.Firmware import QtBeBoard -from Gui.GUIutils.DBConnection import checkDBConnection -import Gui.GUIutils.settings as default_settings from Gui.python.ArduinoWidget import ArduinoWidget from Gui.python.Peltier import PeltierSignalGenerator from Gui.python.logging_config import logger import Gui.siteSettings as site_settings -from icicle.icicle.instrument_cluster import InstrumentCluster, InstrumentNotInstantiated - +from icicle.icicle.instrument_cluster import InstrumentNotInstantiated class SimplifiedMainWidget(QWidget): @@ -42,14 +39,14 @@ def __init__(self, master, dimension): super().__init__() self.master = master self.dimension = dimension - + try: self.instruments = master.instruments except SerialException: instrument_warning_message = QMessageBox() instrument_warning_message.setIcon(QMessageBox.Critical) instrument_warning_message.setInformativeText( - """ + """ Your instruments could not be connected! Check siteConfig.py to make sure you have set the @@ -59,7 +56,7 @@ def __init__(self, master, dimension): """ ) self.close() - + # ↓↓↓↓↓ New FC7 code from QtApplication ↓↓↓↓↓ # self.LogList = {} self.FwDict = {} @@ -83,8 +80,8 @@ def __init__(self, master, dimension): self.createWindow() def setupBeBoard(self): - #self.BeBoard.setFPGAConfig(default_settings.FPGAConfigList[site_settings.defaultFC7]) - #logger.debug(f"Default FC7: {site_settings.defaultFC7}") + # self.BeBoard.setFPGAConfig(default_settings.FPGAConfigList[site_settings.defaultFC7]) + # logger.debug(f"Default FC7: {site_settings.defaultFC7}") logger.debug("Initialized BeBoard in SimplifiedGUI") self.BeBoardWidget = SimpleBeBoardBox(self.master, self.firmware) logger.debug("Initialized SimpleBeBoardBox in Simplified GUI") @@ -101,7 +98,9 @@ def setupArduino(self): def setupLogFile(self): for firmwareName in site_settings.FC7List.keys(): - LogFileName = "{0}/Gui/.{1}.log".format(os.environ.get("GUI_dir"), firmwareName) + LogFileName = "{0}/Gui/.{1}.log".format( + os.environ.get("GUI_dir"), firmwareName + ) logger.debug(f"FC7 log file saved to {LogFileName}") try: @@ -116,7 +115,7 @@ def setupLogFile(self): def setupPeltier(self): try: - self.instrument_info["peltier"] = {"Label" : QLabel(), "Value" : QLabel()} + self.instrument_info["peltier"] = {"Label": QLabel(), "Value": QLabel()} self.instrument_info["peltier"]["Label"].setText("Peltier Temperature") logger.debug("Setting up Peltier") self.Peltier = PeltierSignalGenerator() @@ -127,7 +126,8 @@ def setupPeltier(self): self.Peltier.createCommand( "Set Type Define Write", ["0", "0", "0", "0", "0", "0", "0", "0"] ) - )[1]: raise Exception("Could not communicate with Peltier") + )[1]: + raise Exception("Could not communicate with Peltier") logger.debug("Execute Peltier write command") # Allows set point to be set by computer software @@ -135,31 +135,42 @@ def setupPeltier(self): self.Peltier.createCommand( "Control Type Write", ["0", "0", "0", "0", "0", "0", "0", "1"] ) - )[1]: raise Exception("Could not communicate with Peltier") # Temperature should be PID controlled + )[1]: + raise Exception( + "Could not communicate with Peltier" + ) # Temperature should be PID controlled logger.debug("Executed Peltier PID command") - message = self.Peltier.convertSetTempValueToList(site_settings.defaultPeltierSetTemp) + message = self.Peltier.convertSetTempValueToList( + site_settings.defaultPeltierSetTemp + ) self.Peltier.sendCommand( - self.Peltier.createCommand("Fixed Desired Control Setting Write", message) + self.Peltier.createCommand( + "Fixed Desired Control Setting Write", message + ) ) logger.debug("Set peltier temp") if not self.Peltier.sendCommand( self.Peltier.createCommand( "Power On/Off Write", ["0", "0", "0", "0", "0", "0", "0", "1"] ) - )[1]: raise Exception("Could not communicate with Peltier") # Turn on Peltier + )[1]: + raise Exception("Could not communicate with Peltier") # Turn on Peltier logger.debug("Turned off Peltier") if not self.Peltier.sendCommand( self.Peltier.createCommand( "Proportional Bandwidth Write", ["0", "0", "0", "0", "0", "0", "c", "8"], ) - )[1]: raise Exception("Could not communicate with Peltier") # Set proportional bandwidth + )[1]: + raise Exception( + "Could not communicate with Peltier" + ) # Set proportional bandwidth logger.debug("Set Peltier Bandwidth") time.sleep(0.5) - self.peltier_temperature_label = QLabel(self) + self.peltier_temperature_label = QLabel(self) except Exception as e: print("Error while attempting to set Peltier", e) self.Peltier = None @@ -167,8 +178,12 @@ def setupPeltier(self): def setupStatusWidgets(self): logger.debug("Set device status") self.StatusLayout = QGridLayout() - self.StatusLayout.addWidget(self.instrument_info["database"]["Label"], 0, 1, 1, 1) - self.StatusLayout.addWidget(self.instrument_info["database"]["Value"], 0, 2, 1, 1) + self.StatusLayout.addWidget( + self.instrument_info["database"]["Label"], 0, 1, 1, 1 + ) + self.StatusLayout.addWidget( + self.instrument_info["database"]["Value"], 0, 2, 1, 1 + ) self.StatusLayout.addWidget(self.instrument_info["hv"]["Label"], 0, 3, 1, 1) self.StatusLayout.addWidget(self.instrument_info["hv"]["Value"], 0, 4, 1, 1) @@ -176,51 +191,81 @@ def setupStatusWidgets(self): self.StatusLayout.addWidget(self.instrument_info["lv"]["Value"], 1, 2, 1, 1) offset = -1 for index, firmwareName in enumerate(site_settings.FC7List.keys()): - self.StatusLayout.addWidget(self.instrument_info[f"fc7_{firmwareName}"]["Label"], 1+index, 3, 1, 1) - self.StatusLayout.addWidget(self.instrument_info[f"fc7_{firmwareName}"]["Value"], 1+index, 4, 1, 1) + self.StatusLayout.addWidget( + self.instrument_info[f"fc7_{firmwareName}"]["Label"], 1 + index, 3, 1, 1 + ) + self.StatusLayout.addWidget( + self.instrument_info[f"fc7_{firmwareName}"]["Value"], 1 + index, 4, 1, 1 + ) offset += 1 - self.StatusLayout.addWidget(self.instrument_info["arduino"]["Label"], 2, 1, 1, 1) - self.StatusLayout.addWidget(self.instrument_info["arduino"]["Value"], 2, 2, 1, 1) + self.StatusLayout.addWidget( + self.instrument_info["arduino"]["Label"], 2, 1, 1, 1 + ) + self.StatusLayout.addWidget( + self.instrument_info["arduino"]["Value"], 2, 2, 1, 1 + ) if self.Peltier: - self.StatusLayout.addWidget(self.instrument_info["peltier"]["Label"], 2+offset, 3, 1, 1) - self.StatusLayout.addWidget(self.instrument_info["peltier"]["Value"], 2+offset, 4, 1, 1) - self.StatusLayout.addWidget(self.peltier_temperature_label, 3+offset, 3, 1, 1) + self.StatusLayout.addWidget( + self.instrument_info["peltier"]["Label"], 2 + offset, 3, 1, 1 + ) + self.StatusLayout.addWidget( + self.instrument_info["peltier"]["Value"], 2 + offset, 4, 1, 1 + ) + self.StatusLayout.addWidget( + self.peltier_temperature_label, 3 + offset, 3, 1, 1 + ) self.RefreshButton = QPushButton("&Refresh") self.RefreshButton.clicked.connect(self.setDeviceStatus) - self.StatusLayout.addWidget(self.RefreshButton, 3+offset, 3, 1, 1) + self.StatusLayout.addWidget(self.RefreshButton, 3 + offset, 3, 1, 1) logger.debug("Setup StatusLayout") def setupUI(self): - self.StatusLayout = QGridLayout() - self.StatusLayout.addWidget(self.instrument_info["database"]["Label"], 0, 1, 1, 1) - self.StatusLayout.addWidget(self.instrument_info["database"]["Value"], 0, 2, 1, 1) + self.StatusLayout.addWidget( + self.instrument_info["database"]["Label"], 0, 1, 1, 1 + ) + self.StatusLayout.addWidget( + self.instrument_info["database"]["Value"], 0, 2, 1, 1 + ) self.StatusLayout.addWidget(self.instrument_info["hv"]["Label"], 0, 3, 1, 1) self.StatusLayout.addWidget(self.instrument_info["hv"]["Value"], 0, 4, 1, 1) self.StatusLayout.addWidget(self.instrument_info["lv"]["Label"], 1, 1, 1, 1) self.StatusLayout.addWidget(self.instrument_info["lv"]["Value"], 1, 2, 1, 1) - + offset = -1 for index, firmwareName in enumerate(site_settings.FC7List.keys()): - self.StatusLayout.addWidget(self.instrument_info[f"fc7_{firmwareName}"]["Label"], 1+index, 3, 1, 1) - self.StatusLayout.addWidget(self.instrument_info[f"fc7_{firmwareName}"]["Value"], 1+index, 4, 1, 1) + self.StatusLayout.addWidget( + self.instrument_info[f"fc7_{firmwareName}"]["Label"], 1 + index, 3, 1, 1 + ) + self.StatusLayout.addWidget( + self.instrument_info[f"fc7_{firmwareName}"]["Value"], 1 + index, 4, 1, 1 + ) offset += 1 - self.StatusLayout.addWidget(self.instrument_info["arduino"]["Label"], 2, 1, 1, 1) - self.StatusLayout.addWidget(self.instrument_info["arduino"]["Value"], 2, 2, 1, 1) + self.StatusLayout.addWidget( + self.instrument_info["arduino"]["Label"], 2, 1, 1, 1 + ) + self.StatusLayout.addWidget( + self.instrument_info["arduino"]["Value"], 2, 2, 1, 1 + ) if self.Peltier: - self.StatusLayout.addWidget(self.instrument_info["peltier"]["Label"], 2+offset, 3, 1, 1) - self.StatusLayout.addWidget(self.instrument_info["peltier"]["Value"], 2+offset, 4, 1, 1) - self.StatusLayout.addWidget(self.peltier_temperature_label, 3+offset, 3, 1, 1) - #self.StatusLayout.addWidget(self.RefreshButton, 3, 3, 1, 1) + self.StatusLayout.addWidget( + self.instrument_info["peltier"]["Label"], 2 + offset, 3, 1, 1 + ) + self.StatusLayout.addWidget( + self.instrument_info["peltier"]["Value"], 2 + offset, 4, 1, 1 + ) + self.StatusLayout.addWidget( + self.peltier_temperature_label, 3 + offset, 3, 1, 1 + ) + # self.StatusLayout.addWidget(self.RefreshButton, 3, 3, 1, 1) logger.debug("Setup StatusLayout") ModuleEntryLayout = QGridLayout() ModuleEntryLayout.addWidget(self.BeBoardWidget) logger.debug("Setup ModuleEntryLayout") - self.AppOption = QGroupBox() self.StartLayout = QHBoxLayout() self.TestGroup = QGroupBox() @@ -232,7 +277,6 @@ def setupUI(self): self.TestGroupLayout.addWidget(self.FunctionTestButton) self.TestGroupLayout.addWidget(self.AssemblyTestButton) self.TestGroupLayout.addWidget(self.FullPerformanceTestButton) - self.TestGroup.setLayout(self.TestGroupLayout) logger.debug("Added Boxes/Layouts to Simplified GUI") @@ -302,7 +346,9 @@ def setupUI(self): logger.debug("Simplied GUI UI Loaded") def createWindow(self): - self.simplifiedStatusBox = QGroupBox("Hello, {}!".format(self.master.operator_name_first)) + self.simplifiedStatusBox = QGroupBox( + "Hello, {}!".format(self.master.operator_name_first) + ) self.instrument_info["database"] = {"Label": QLabel(), "Value": QLabel()} self.instrument_info["database"]["Label"].setText("Database connection:") @@ -314,34 +360,36 @@ def createWindow(self): self.instrument_info["lv"]["Label"].setText("LV status") for firmwareName in site_settings.FC7List.keys(): - self.instrument_info[f"fc7_{firmwareName}"] = {"Label": QLabel(), "Value": QLabel()} + self.instrument_info[f"fc7_{firmwareName}"] = { + "Label": QLabel(), + "Value": QLabel(), + } self.instrument_info[f"fc7_{firmwareName}"]["Label"].setText(firmwareName) - self.setupLogFile() + self.setupLogFile() self.setupArduino() if site_settings.cooler == "Peltier": self.setupPeltier() else: self.Peltier = None - self.setDeviceStatus() + self.setDeviceStatus() self.setupBeBoard() - #self.setupStatusWidgets() + # self.setupStatusWidgets() self.setupUI() def updateArduinoIndicator(self): - if(self.ArduinoGroup.condensationRisk): + if self.ArduinoGroup.condensationRisk: self.instrument_info["arduino"]["Value"].setPixmap(self.redledpixmap) else: self.instrument_info["arduino"]["Value"].setPixmap(self.greenledpixmap) - def updatePeltierTemp(self, temp:float): + def updatePeltierTemp(self, temp: float): self.peltier_temperature_label.setText("{}C".format(temp)) if abs(temp - site_settings.defaultPeltierSetTemp) < 15: self.instrument_info["peltier"]["Value"].setPixmap(self.greenledpixmap) - else: + else: self.instrument_info["peltier"]["Value"].setPixmap(self.redledpixmap) - def runNewTest(self): for module in self.BeBoardWidget.getModules(): if module.getSerialNumber() == "": @@ -354,7 +402,9 @@ def runNewTest(self): return self.firmwareDescription, message = self.BeBoardWidget.getFirmwareDescription() - if not self.firmwareDescription: #firmware description returns none if no modules are entered + if ( + not self.firmwareDescription + ): # firmware description returns none if no modules are entered QMessageBox.information( None, "Error", @@ -362,7 +412,7 @@ def runNewTest(self): QMessageBox.Ok, ) return - + if self.FunctionTestButton.isChecked(): self.info = "TFPX_Functional_Test" elif self.AssemblyTestButton.isChecked(): @@ -375,19 +425,21 @@ def runNewTest(self): self.StopButton.setDisabled(False) self.RunTest.resetConfigTest() - + module = self.firmwareDescription[0].getModules()[0] module_type = module.getModuleType() self.master.module_in_use = module_type - + print("Firmware Description") for beboard in self.firmwareDescription: print(beboard) - + print("Firmware Check") for beboard in self.firmwareDescription: - fw_check = SummaryBox.checkFwPar(beboard.getBoardName(), module_type, beboard.getIPAddress()) - + SummaryBox.checkFwPar( + beboard.getBoardName(), module_type, beboard.getIPAddress() + ) + self.RunTest.initialTest() # self.RunTest.runTest() @@ -404,12 +456,12 @@ def setDeviceStatus(self) -> None: The qualifications for a passing status are HV -> HV is on and connected as stated by InstrumentCluster.status() LV -> LV is on and connected as stated by InstrumentCluster.status() - Arduino -> Can read correctly from the Arduino sensor as defined in ArduinoWidget.py + Arduino -> Can read correctly from the Arduino sensor as defined in ArduinoWidget.py Database -> Check if you can connect to database as defined in checkDBConnection() - Peltier -> check if the Peltier is at the right temperature and is reachable - """ + Peltier -> check if the Peltier is at the right temperature and is reachable + """ - #self.instrument_status = self.check_icicle_devices() + # self.instrument_status = self.check_icicle_devices() self.instrument_status = { "arduino": False, "fc7_1": False, @@ -417,30 +469,29 @@ def setDeviceStatus(self) -> None: "database": False, "hv": False, "lv": False, - "peltier": True if site_settings.cooler == "Peltier" else False + "peltier": True if site_settings.cooler == "Peltier" else False, } - #logger.debug(f"Instrument status is {self.instrument_status}") - + # logger.debug(f"Instrument status is {self.instrument_status}") + logger.debug("Getting FC7 Comment") # ↓↓↓↓↓ New FC7 code from QtApplication ↓↓↓↓↓ # - self.StatusList = [] #Panthera is NOT in here + self.StatusList = [] # Panthera is NOT in here self.firmware = [] try: for firmwareName, ipaddress in site_settings.FC7List.items(): - self.StatusList.append( [firmwareName, "Not Connected"] ) + self.StatusList.append([firmwareName, "Not Connected"]) self.FwStatusVerboseDict[str(firmwareName)] = {} BeBoard = QtBeBoard( BeBoardID=str(len(self.FwDict)), boardName=firmwareName, - ipAddress=ipaddress + ipAddress=ipaddress, ) self.FwDict[firmwareName] = BeBoard except Exception as err: print("Failed to list the firmware: {}".format(repr(err))) - logger.debug("Setup FC7s with the following FC7:\n" - f"{self.FwDict}") - - self.UseButtons = [] #Not a list of buttons but serves same function as in QtApplication.py + logger.debug(f"Setup FC7s with the following FC7:\n{self.FwDict}") + + self.UseButtons = [] # Not a list of buttons but serves same function as in QtApplication.py for i in self.StatusList: self.UseButtons.append(False) @@ -450,7 +501,7 @@ def setDeviceStatus(self) -> None: self.checkFirmware() # ↑↑↑↑↑ New FC7 code from QtApplication ↑↑↑↑↑ # - + logger.debug("Checking DB Connection") # Launch QThread to monitor Peltier temperature/power and Arduino temperature/humidity @@ -465,7 +516,7 @@ def setDeviceStatus(self) -> None: logger.debug("Setting up instrument_status") logger.debug("instrument_status: {}".format(self.instrument_status)) - logger.debug("instruments: ".format(self.instruments)) + logger.debug("instruments: ") self.firmware = self.firmware[:-1] print(self.firmware) @@ -478,28 +529,27 @@ def setDeviceStatus(self) -> None: # ↑↑↑↑↑ Original FC7 code from SimplifiedMainWidget.py ↑↑↑↑↑ # # Icicle will deal with the powersupplies, so I will just always set their status to good - # Technically a false sense of security for the user. + # Technically a false sense of security for the user. self.instrument_status["hv"] = True self.instrument_status["lv"] = True if site_settings.cooler == "Peltier": self.instrument_status["peltier"] = False - - print(f'instruments: {self.instruments}') - print(f'instrument_info: {self.instrument_info}') - print(f'instrument_status: {self.instrument_status}') + print(f"instruments: {self.instruments}") + print(f"instrument_info: {self.instrument_info}") + print(f"instrument_status: {self.instrument_status}") if self.instruments: - logger.debug(f'{__name__} Setup instrument status {self.instrument_status}') + logger.debug(f"{__name__} Setup instrument status {self.instrument_status}") for key, value in self.instrument_info.items(): - if self.instrument_status[key]: + if self.instrument_status[key]: value["Value"].setPixmap(self.greenledpixmap) else: value["Value"].setPixmap(self.redledpixmap) else: for key, value in self.instrument_info.items(): value["Value"].setPixmap(self.redledpixmap) - logger.debug(f'{__name__} Setup led labels') + logger.debug(f"{__name__} Setup led labels") # ↑↑↑↑↑ Original (FC7 et al) code from SimplifiedMainWidget.py ↑↑↑↑↑ # # ↓↓↓↓↓ New FC7 methods from QtApplication ↓↓↓↓↓ # @@ -511,7 +561,7 @@ def checkFirmware(self): self.FwDict[firmwareName], fileName ) self.StatusList[index][1] = FwStatusComment - if FwStatusComment=="Connected": + if FwStatusComment == "Connected": self.firmware.append(self.FwDict[firmwareName]) self.FwStatusVerboseDict[str(firmwareName)] = FwStatusVerbose if self.ActiveFC7s != {}: @@ -523,12 +573,11 @@ def checkFirmware(self): def occupyFw(self, index): for i in range(len(self.UseButtons)): if i == int(index): - self.UseButtons[i]=True + self.UseButtons[i] = True self.ActiveFC7s[i] = self.StatusList[i][0] def initLog(self): for index, firmwareName in enumerate(site_settings.FC7List.keys()): - LogFileName = "{0}/Gui/.{1}.log".format( os.environ.get("GUI_dir"), firmwareName ) @@ -536,13 +585,14 @@ def initLog(self): logFile = open(LogFileName, "w") self.LogList[index] = LogFileName logFile.close() - except: + except OSError: QMessageBox( None, "Error", "Can not create log files: {}".format(LogFileName) ) + # ↑↑↑↑↑ New FC7 methods from QtApplication ↑↑↑↑↑ # - def check_icicle_devices(self) ->Optional[dict[str, int]]: + def check_icicle_devices(self) -> Optional[dict[str, int]]: """ Check if LV, HV, and relay board are connected and communicable @@ -552,7 +602,7 @@ def check_icicle_devices(self) ->Optional[dict[str, int]]: this part the HV and LV should always have a good status and we need to invert the values from instrument_cluster.status() """ - try: + try: status = self.instruments.status(lv_channel=1) except RuntimeError: error_box = QMessageBox() @@ -563,19 +613,19 @@ def check_icicle_devices(self) ->Optional[dict[str, int]]: as stated in siteConfig.py in the icicle_instrument_setup dictionary. """ - ) + ) error_box.setIcon(QMessageBox.Critical) error_box.setStandardButtons(QMessageBox.Ok) error_box.exec() self.destroySimplified() logger.debug(f"Status of instrument_cluster instruments: {status}") - return_status = {} + return_status = {} for key, value in status.items(): if value == 0: return_status[key] = 1 - elif type(value) == InstrumentNotInstantiated: + elif type(value) is InstrumentNotInstantiated: return_status[key] = 0 - return return_status + return return_status def retryLogin(self): self.master.mainLayout.removeWidget(self) @@ -595,31 +645,47 @@ def clearLayout(self, layout): class Worker_Polling(QObject): temp = pyqtSignal(float) power = pyqtSignal(bool) + def __init__(self): super().__init__() # Delay in seconds between polling self.delay = 0.5 self.abort = False + def run(self): - while not self.abort and site_settings.cooler == "Peltier": + while not self.abort and site_settings.cooler == "Peltier": self.Peltier = PeltierSignalGenerator() - peltier_power_status = 1 if int(self.Peltier.sendCommand(self.Peltier.createCommand("Power On/Off Read", ["0", "0"]))[-1]) == 1 else 0 - peltier_temp_message, temp_message_pass = self.Peltier.sendCommand(self.Peltier.createCommand("Input1", ["0", "0", "0", "0", "0", "0", "0", "0"])) + peltier_power_status = ( + 1 + if int( + self.Peltier.sendCommand( + self.Peltier.createCommand("Power On/Off Read", ["0", "0"]) + )[-1] + ) + == 1 + else 0 + ) + peltier_temp_message, temp_message_pass = self.Peltier.sendCommand( + self.Peltier.createCommand( + "Input1", ["0", "0", "0", "0", "0", "0", "0", "0"] + ) + ) if not temp_message_pass: peltier_temp_message = None logger.debug("Formatting peltier output") if peltier_temp_message: - peltier_temp = int("".join(peltier_temp_message[1:9]), 16)/100 + peltier_temp = int("".join(peltier_temp_message[1:9]), 16) / 100 else: peltier_temp = None self.temp.emit(peltier_temp) self.power.emit(peltier_power_status) time.sleep(self.delay) - + while not self.abort: self.temp.emit(0.0) time.sleep(self.delay) + def abort_worker(self): print("Worker aborted") self.abort = True diff --git a/Gui/python/TCP.py b/Gui/python/TCP.py deleted file mode 100644 index 4f52e5b5..00000000 --- a/Gui/python/TCP.py +++ /dev/null @@ -1,174 +0,0 @@ - -import logging - -# Customize the logging configuration -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', - filename='my_project.log', # Specify a log file - filemode='w' # 'w' for write, 'a' for append -) - -logger = logging.getLogger(__name__) - -import ctypes -import subprocess, os, signal -import time, datetime -#g++ -std=c++1y -fPIC -shared *.cc -o NetworkUtils.so -lm -lboost_regex -#from PySide2.QtCore import QThreadPool, Signal, QObject -from PyQt5.QtCore import QObject, pyqtSignal - -class TCPServer(): - def __init__( self, pFolder = None, index = 0): - print("Ph2_ACF_GUI:\tNew TCP Server") - self.index = index - self.folder = pFolder - #self.serverSubprocess = None - self.config = None - #self.killAnyPowerSupplyProcess() - - self.serverProcess = None - self.logFile = open(os.environ.get('GUI_dir')+"/Gui/.tmp/" + str(self.index) + ".txt", "w") - - def start( self , pConfigFile ) : - self.config = pConfigFile - - if self.folder is not None: - print("Ph2_ACF_GUI:\tTCP Server: Start TCP Device Server at " + self.folder + " with config file " + self.config) - if not self.isRunning(): - print("Ph2_ACF_GUI:\tStarting TCP server ...") - cmd = "source setup.sh && " + os.environ.get('GUI_dir')+ "/power_supply/bin/PowerSupplyController -c " + self.config + " -p " + str( 7000 + self.index) - self.serverProcess = subprocess.Popen(cmd, stdout=self.logFile, stderr=subprocess.PIPE, encoding = 'UTF-8', shell= True, executable="/bin/bash", cwd=self.folder) - self.isRunning() - return True - else: - print("Ph2_ACF_GUI:\tTCP Device Server already running") - return False - else: - print("Ph2_ACF_GUI:\tNo folder given for TCP Device Server, abort!") - return False - - def checkDeviceSubProcess ( self ): - search = subprocess.Popen(['ps', '-A'], stdout=subprocess.PIPE) - output, error = search.communicate() - target_process = "PowerSupplyCont" - - for line in output.splitlines(): - #print(str(line)) - if target_process in str(line): - pid = int(line.split(None, 1)[0]) - #print("PID:" + str(pid)) - - - if self.serverProcess is not None: - response = self.serverProcess.poll() - #print( "Response: " + str( response) ) - print("Ph2_ACF_GUI:\tCheck subprocess of device " + self.config + ": is running") - return response is None - else: - print("Ph2_ACF_GUI:\tCheck subprocess of device " + self.config + ": is not running") - return False - - - - def killAnyPowerSupplyProcess( self ): - search = subprocess.Popen(['ps', '-A'], stdout=subprocess.PIPE) - output, error = search.communicate() - target_process = "PowerSupplyCont" - - for line in output.splitlines(): - #print(str(line)) - if target_process in str(line): - pid = int(line.split(None, 1)[0]) - #print("PID") - #print(pid) - - os.kill(pid, 9) - return True - return False - def stop ( self ): - print("TCP Server: Kill TCP Device Server at " + self.folder + " with config file " + self.config) - - return self.killAnyPowerSupplyProcess() - #os.kill(self.serverSubprocess.pid, signal.SIGHUP) - #os.kill(self.serverSubprocess.pid, signal.SIGTERM) - - def isRunning( self): - return self.checkDeviceSubProcess() - - -class TCPClient(QObject): - tcpAnswer = pyqtSignal(object) - - def __init__( self,index = 0 ): - super(TCPClient, self).__init__( ) - self.index = index - print("Ph2_ACF_GUI:\tNew TCP Client " + str( self.index )) - - self.lib = ctypes.cdll.LoadLibrary(os.environ.get('GUI_dir') + '/power_supply/NetworkUtils/NetworkUtils.so') - - self.lib.TCPClient_new.argtypes = [ctypes.c_char_p,ctypes.c_int] - self.lib.TCPClient_new.restype = ctypes.c_void_p - - self.lib.sendAndReceivePacket_new.argtypes =[ctypes.c_void_p,ctypes.c_char_p] - self.lib.sendAndReceivePacket_new.restype = ctypes.c_char_p - - #self.lib.connect_new.restype = ctype.c_void_p - self.lib.connect_new.restype = ctypes.c_bool - - self.lib.disconnect_new.restype = ctypes.c_bool - - #self.client = self.lib.TCPClient_new(b'127.0.0.1',7000 + self.index) - self.client = self.lib.TCPClient_new(b'0.0.0.0',7000 + self.index) - - self.timeOut = 100 #Milliseconds - self.lastPoll = datetime.datetime.now() - self.lastData = None - - - def isRunning( self ): - return True - - def connectClient ( self ): - self.lib.connect_new(self.client,2)# CLient and number of retries - - def disconnectClient( self ): - self.lib.disconnect_new(self.client) - - - def sendAndReceivePacket( self, pBuffer ): - #There is only one TCP Client if last call is not long ago, just return most recent value to avoid polling too often - #result = self.lib.sendAndReceivePacket_new( self.client, pBuffer.encode() ).decode() - result = self.lib.sendAndReceivePacket_new(self.client, pBuffer.encode() ) - result = result.decode() - if result == "-1" or result == '': - result = None - self.tcpAnswer.emit(result) - - - def decodeStatus( self, pStatus ): - statusList = pStatus.split(',') - - timestamp = None - statusDict = {} - - - splitTimestamp = statusList[0].split(':') - timestamp = splitTimestamp[1] + ":" + splitTimestamp[2] + ":" + splitTimestamp[3] - - for entry in statusList[1:]: - device = entry.split('_')[0] - statusDict[device] = {} - - for entry in statusList[1:]: - device = entry.split('_')[0] - channel = entry.split('_')[1] - statusDict[device][channel] = {} - - for entry in statusList[1:]: - device = entry.split('_')[0] - channel = entry.split('_')[1] - meas, value = entry.split('_')[2].split(':') - statusDict[device][channel][meas]=value - - return timestamp, statusDict diff --git a/Gui/python/TCP_Interface.py b/Gui/python/TCP_Interface.py deleted file mode 100644 index 46efc627..00000000 --- a/Gui/python/TCP_Interface.py +++ /dev/null @@ -1,48 +0,0 @@ - -import logging - -# Customize the logging configuration -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', - filename='my_project.log', # Specify a log file - filemode='w' # 'w' for write, 'a' for append -) - -logger = logging.getLogger(__name__) - -from PyQt5.QtCore import QObject, pyqtSignal -import os, re, subprocess, errno - -from Gui.python.TCP import ( - TCPServer, - TCPClient, -) - -import threading - -class TCP_Interface(QObject): - update = pyqtSignal ( object , object ) - - def __init__( self, pPackageFolder,pConfigFile, index ): - super(TCP_Interface, self).__init__( ) - print("PH2_ACF_GUI:\tNew TCP Interface") - self.server = TCPServer(pPackageFolder,index) - self.server.start(pConfigFile) - self.client = TCPClient(index) - self.client.connectClient() - self.client.tcpAnswer.connect(self.handleAnswer) - - def executeCommand( self , pCmd, pPrintLog = False): - self.client.sendAndReceivePacket(pCmd) - - def handleAnswer( self, pAnswer ): - print("answer:",pAnswer) - if pAnswer is not None: - self.update.emit("data", pAnswer) - else: - self.update.emit("noData", None) - - #To be defined - def stopTask( self ): - pass diff --git a/Gui/python/TestHandler.py b/Gui/python/TestHandler.py index c215f811..7aa8c4b7 100644 --- a/Gui/python/TestHandler.py +++ b/Gui/python/TestHandler.py @@ -1,6 +1,16 @@ from PyQt5 import QtCore -from PyQt5.QtCore import pyqtSignal, QObject, QProcess -from PyQt5.QtWidgets import QMessageBox, QTableWidget, QTableWidgetItem, QPlainTextEdit +from PyQt5.QtCore import pyqtSignal, QObject, QProcess, Qt +from PyQt5.QtWidgets import ( + QMessageBox, + QTableWidget, + QTableWidgetItem, + QPlainTextEdit, + QProgressBar, + QDialog, + QVBoxLayout, + QPushButton, + QLabel, +) import os import glob @@ -35,12 +45,8 @@ from InnerTrackerTests.Analysis.SLDO_CSV_to_ROOT import SLDO_CSV_to_ROOT -# from Gui.QtGUIutils.QtStartWindow import * -#from Gui.QtGUIutils.QtCustomizeWindow import * -#from Gui.QtGUIutils.QtTableWidget import * from Gui.QtGUIutils.QtMatplotlibUtils import ScanCanvas -from Gui.QtGUIutils.QtLoginDialog import * -#from Gui.python.ResultTreeWidget import * + from Gui.python.TestValidator import ResultGrader from Gui.python.ANSIColoringParser import parseANSI from Gui.python.IVCurveHandler import IVCurveHandler @@ -49,13 +55,6 @@ from Gui.python.logging_config import logger from InnerTrackerTests.TestSequences import CompositeTests, Test_to_Ph2ACF_Map -import logging - -logging.basicConfig( - level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s" -) -logger = logging.getLogger(__name__) - class TestHandler(QObject): backSignal = pyqtSignal(object) @@ -77,32 +76,38 @@ def __init__(self, runwindow, master, info, firmware): super(TestHandler, self).__init__() self.master = master self.instruments = self.master.instruments - self.mod_dict={} - self.fused_dict_index=[-1,-1] - # self.LVpowersupply.Reset() - - # self.LVpowersupply.setCompCurrent(compcurrent = 1.05) # Fixed for different chip - # self.LVpowersupply.TurnOn() + self.mod_dict = {} + self.fused_dict_index = [-1, -1] self.FWisPresent = False self.FWisLoaded = False self.master.globalStop.connect(self.urgentStop) self.runwindow = runwindow self.firmware = firmware - self.info = info # This is the name of the test sequence or just the name of the test if it is a single test + self.info = info # This is the name of the test sequence or just the name of the test if it is a single test self.ModuleMap = dict() - - self.modules = [module for beboard in self.firmware for module in beboard.getModules()] - + + self.modules = [ + module for beboard in self.firmware for module in beboard.getModules() + ] + self.finished_tests = [] self.BBanalysis_root_files = [] - - self.numChips = len([chipID for module in self.modules for chipID in module.getEnabledChips().keys()]) - + + self.numChips = len( + [ + chipID + for module in self.modules + for chipID in module.getEnabledChips().keys() + ] + ) + self.ModuleType = self.runwindow.ModuleType if "CROC" in self.ModuleType: self.boardType = "RD53B" - self.moduleVersion = self.firmware[0].getModuleData()['version'] #module types/versions should be identical for all modules + self.moduleVersion = self.firmware[0].getModuleData()[ + "version" + ] # module types/versions should be identical for all modules else: self.boardType = "RD53A" self.moduleVersion = "" @@ -140,7 +145,7 @@ def __init__(self, runwindow, master, info, firmware): self.listWidgetIndex = 0 self.outputDirQueue = [] # Fixme: QTimer to be added to update the page automatically - + felisScratchDir = "/home/cmsTkUser/Ph2_ACF_GUI/data/scratch" if not os.path.isdir(felisScratchDir): try: @@ -148,18 +153,18 @@ def __init__(self, runwindow, master, info, firmware): logger.info("New Felis scratch directory created.") except OSError as e: logger.error(f"Error making Felis scratch directory: {e.strerror}") - + self.felis = Felis("/home/cmsTkUser/Ph2_ACF_GUI/data/scratch", False) self.grades = [] - + self.figurelist = {} self.run_processes = [QProcess(self) for i in range(len(self.firmware))] for i in range(len(self.run_processes)): self.run_processes[i].readyReadStandardOutput.connect( - lambda:self.on_readyReadStandardOutput(i) + lambda: self.on_readyReadStandardOutput(i) ) - self.run_processes[i].finished.connect(lambda:self.on_finish(i)) + self.run_processes[i].finished.connect(lambda: self.on_finish(i)) self.readingOutput = False self.ProgressingMode = "None" self.ProgressValue = 0 @@ -169,7 +174,7 @@ def __init__(self, runwindow, master, info, firmware): self.info_processes = [QProcess(self) for i in range(len(self.firmware))] for i in range(len(self.info_processes)): self.info_processes[i].readyReadStandardOutput.connect( - lambda:self.on_readyReadStandardOutput_info(i) + lambda: self.on_readyReadStandardOutput_info(i) ) ##---Adding firmware setting----- @@ -233,13 +238,13 @@ def configTest(self): runNumberText = runNumberFile.readlines() self.RunNumber = runNumberText[0].split("\n")[0] logger.info("RunNumber: {}".format(self.RunNumber)) - except: - logger.warning("Failed to retrieve RunNumber") + except OSError: + logger.warning("Failed to retrieve RunNumber due to OSError") # If currentTest is not set check if it's a compositeTest and if so set testname accordingly, otherwise set it based off the test set in info[1] if self.currentTest == "" and isCompositeTest(self.info): testName = CompositeTests[self.info][0] - elif self.currentTest == None: + elif self.currentTest is None: testName = self.info else: testName = self.currentTest @@ -249,10 +254,12 @@ def configTest(self): # FIXME Fix rd53_file[key] so that it reads the correct txt file depending on what module is connected. -> Done! for key in self.rd53_file.keys(): - if self.rd53_file[key] == None: + if self.rd53_file[key] is None: self.rd53_file[key] = os.environ.get( "PH2ACF_BASE_DIR" - ) + "/settings/RD53Files/CMSIT_{0}{1}.txt".format(self.boardType, self.moduleVersion) + ) + "/settings/RD53Files/CMSIT_{0}{1}.txt".format( + self.boardType, self.moduleVersion + ) print("Getting config file {0}".format(self.rd53_file[key])) if self.input_dir == "": # Copies file given in rd53[key] to test directory in Ph2_ACF test area as CMSIT_RD53.txt and the output dir. @@ -269,7 +276,7 @@ def configTest(self): try: os.mkdir(tmpDir) logger.info("Creating " + tmpDir) - except: + except OSError: logger.warning("Failed to create " + tmpDir) # Create the xml file from the text file for firmware in self.firmware: @@ -299,7 +306,7 @@ def configTest(self): try: os.mkdir(tmpDir) logger.info("Creating " + tmpDir) - except: + except OSError: logger.warning("Failed to create " + tmpDir) # Create the xml file from the text file for firmware in self.firmware: @@ -324,7 +331,7 @@ def saveConfigs(self): os.environ.get("PH2ACF_BASE_DIR"), key, self.output_dir ) ) - except: + except OSError: print( "Failed to copy {0}/test/CMSIT_RD53_{1}.txt {2}/CMSIT_RD53_{1}_OUT.txt".format( os.environ.get("PH2ACF_BASE_DIR"), key, self.output_dir @@ -353,7 +360,7 @@ def runTest(self, reRun=False): else: QMessageBox.information(None, "Warning", "Not a valid test", QMessageBox.Ok) return - + # This loops over all the tests by using the on_finish pyqt decorator defined below def runCompositeTest(self, testName): if self.halt: @@ -367,24 +374,23 @@ def runCompositeTest(self, testName): self.runSingleTest(testName) def ramp_progress_bar(self, max): - - voltages = [getattr(module["hv"], "voltage") for module in self.instruments._module_dict.values()] + voltages = [ + getattr(module["hv"], "voltage") + for module in self.instruments._module_dict.values() + ] for i in range(len(self.runwindow.RampProgressBars)): - - text = f'{np.abs(voltages[i])} V' - value = 100*np.abs(voltages[i]/max[i]) if max[i]!=0 else 0 + text = f"{np.abs(voltages[i])} V" + value = 100 * np.abs(voltages[i] / max[i]) if max[i] != 0 else 0 self.updateProgressBar.emit(self.runwindow.RampProgressBars[i], value, text) def runSingleTest(self, testName): - if "analyze" in testName.lower(): - self.output_dir, self.input_dir = self.config_output_dir(testName) self.currentTest = testName - EnableReRun = self.onFinalTest(self.testIndexTracker+1) + EnableReRun = self.onFinalTest(self.testIndexTracker + 1) self.stepFinished.emit(EnableReRun) if self.master.expertMode: @@ -402,25 +408,32 @@ def runSingleTest(self, testName): if self.instruments: lv_on = False for number in self.instruments.get_modules().keys(): - if self.instruments.status()[number]["lv"]: + if self.instruments.status()[number]["lv"]: lv_on = True - continue - if not lv_on: - self.instruments.lv_on( - voltage=site_settings.ModuleVoltageMapSLDO[self.master.module_in_use], - current=site_settings.ModuleCurrentMap[self.master.module_in_use], - ) - + break + if not lv_on: + self.instruments.lv_on( + voltage=site_settings.ModuleVoltageMapSLDO[ + self.master.module_in_use + ], + current=site_settings.ModuleCurrentMap[self.master.module_in_use], + ) + if "IVCurve" in testName: self.currentTest = testName self.configTest() self.IVCurveData = [] self.IVProgressValue = 0 - self.IVCurveHandler = IVCurveHandler(self.currentTest, self.instruments,execute_each_step=self.ramp_progress_bar) + self.IVCurveHandler = IVCurveHandler( + self.currentTest, + self.instruments, + execute_each_step=self.ramp_progress_bar, + ) self.IVCurveHandler.finished.connect(self.IVCurveFinished) self.IVCurveHandler.progressSignal.connect(self.updateProgress) self.IVCurveHandler.startSignal.connect(self.setupQProcess) - for console in self.runwindow.ConsoleViews: self.outputString.emit("Beginning IVCurve", console) + for console in self.runwindow.ConsoleViews: + self.outputString.emit("Beginning IVCurve", console) self.IVCurveHandler.IVCurve() return @@ -430,46 +443,66 @@ def runSingleTest(self, testName): self.SLDOScanData = [] self.SLDOfilelist = [] self.SLDOProgressValue = 0 - self.SLDOScanHandler = SLDOCurveHandler(self.instruments, moduleType=self.ModuleType[5:], - end_current=site_settings.ModuleCurrentMap[self.master.module_in_use], - voltage_limit=site_settings.ModuleVoltageMapSLDO[self.master.module_in_use], - execute_each_step=self.ramp_progress_bar) + self.SLDOScanHandler = SLDOCurveHandler( + self.instruments, + moduleType=self.ModuleType[5:], + end_current=site_settings.ModuleCurrentMap[self.master.module_in_use], + voltage_limit=site_settings.ModuleVoltageMapSLDO[ + self.master.module_in_use + ], + execute_each_step=self.ramp_progress_bar, + ) self.SLDOScanHandler.makeplotSignal.connect(self.makeSLDOPlot) self.SLDOScanHandler.finishedSignal.connect(self.SLDOScanFinished) self.SLDOScanHandler.progressSignal.connect(self.updateProgress) self.SLDOScanHandler.abortSignal.connect(self.urgentStop) - for console in self.runwindow.ConsoleViews: self.outputString.emit("Beginning SLDOScan", console) + for console in self.runwindow.ConsoleViews: + self.outputString.emit("Beginning SLDOScan", console) self.SLDOScanHandler.SLDOScan() return - #If the HV is not already on, turn it on. + # If the HV is not already on, turn it on. if self.instruments: - default_hv_voltage = site_settings.icicle_instrument_setup['instrument_dict']['hv']['default_voltage'] - #assumes only 1 HV titled 'hv' in instruments.json + default_hv_voltage = site_settings.icicle_instrument_setup[ + "instrument_dict" + ]["hv"]["default_voltage"] + # assumes only 1 HV titled 'hv' in instruments.json hv_on_module = False - mod_dict = self.instruments.get_modules() + mod_dict = self.instruments.get_modules() for number in self.instruments.get_modules().keys(): - if self.instruments.status()[number]["hv"] == '1': + if self.instruments.status()[number]["hv"] == "1": hv_on_module = True break if testName == "SCurveScan_2100_FWD": if hv_on_module: self.instruments.hv_off() - self.instruments.hv_on_module(module=mod_dict[number], voltage=site_settings.forward_bias_voltage, delay=0.3, step_size=10) + self.instruments.hv_on_module( + module=mod_dict[number], + voltage=site_settings.forward_bias_voltage, + delay=0.3, + step_size=10, + ) else: - self.instruments.hv_on_module(module=mod_dict[number], voltage=site_settings.forward_bias_voltage, delay=0.3, step_size=10) + self.instruments.hv_on_module( + module=mod_dict[number], + voltage=site_settings.forward_bias_voltage, + delay=0.3, + step_size=10, + ) testName = "SCurveScan_2100" hv_on_module = True if not hv_on_module: - self.instruments.hv_on_module( module = mod_dict[number], - voltage=default_hv_voltage, delay=0.3, step_size=10, - - ) + self.instruments.hv_on_module( + module=mod_dict[number], + voltage=default_hv_voltage, + delay=0.3, + step_size=10, + ) self.tempHistory = [0.0] * self.numChips self.tempindex = 0 - + self.starttime = None self.ProgressingMode = "None" self.currentTest = testName @@ -504,12 +537,10 @@ def setupQProcess(self): self.outputfile = open(self.outputFile, "a") else: self.outputfile = open(self.outputFile, "w") - + for process in self.info_processes: process.setProcessChannelMode(QtCore.QProcess.MergedChannels) - process.setWorkingDirectory( - os.environ.get("PH2ACF_BASE_DIR") + "/test/" - ) + process.setWorkingDirectory(os.environ.get("PH2ACF_BASE_DIR") + "/test/") if self.currentTest == "CommunicationTest": for i in range(len(self.firmware)): @@ -525,24 +556,24 @@ def setupQProcess(self): "echo", [ "Running COMMAND: CMSITminiDAQ -f CMSIT_{0}.xml -c {1}".format( - self.firmware[i].getBoardName(), Test_to_Ph2ACF_Map[self.currentTest] + self.firmware[i].getBoardName(), + Test_to_Ph2ACF_Map[self.currentTest], ) ], ) - - for process in self.info_processes: process.waitForFinished() + + for process in self.info_processes: + process.waitForFinished() for process in self.run_processes: process.setProcessChannelMode(QtCore.QProcess.MergedChannels) - process.setWorkingDirectory( - os.environ.get("PH2ACF_BASE_DIR") + "/test/" - ) + process.setWorkingDirectory(os.environ.get("PH2ACF_BASE_DIR") + "/test/") self.fw_process.setProcessChannelMode(QtCore.QProcess.MergedChannels) self.fw_process.setWorkingDirectory( os.environ.get("PH2ACF_BASE_DIR") + "/test/" ) - + if self.currentTest == "CommunicationTest": for i in range(len(self.firmware)): self.run_processes[i].start( @@ -553,37 +584,45 @@ def setupQProcess(self): for i in range(len(self.firmware)): self.run_processes[i].start( "CMSITminiDAQ", - ["-f", f"CMSIT_{self.firmware[i].getBoardName()}.xml", "-c", "{}".format(Test_to_Ph2ACF_Map[self.currentTest])], + [ + "-f", + f"CMSIT_{self.firmware[i].getBoardName()}.xml", + "-c", + "{}".format(Test_to_Ph2ACF_Map[self.currentTest]), + ], ) - def abortTest(self): self.halt = True - for process in self.run_processes: process.kill() + for process in self.run_processes: + process.kill() self.haltSignal.emit(self.halt) self.starttime = None if self.IVCurveHandler: - for console in self.runwindow.ConsoleViews: self.outputString.emit("Aborting IVCurve", console) + for console in self.runwindow.ConsoleViews: + self.outputString.emit("Aborting IVCurve", console) self.IVCurveHandler.stop() if self.SLDOScanHandler: - for console in self.runwindow.ConsoleViews: self.outputString.emit("Aborting SLDOScan", console) + for console in self.runwindow.ConsoleViews: + self.outputString.emit("Aborting SLDOScan", console) self.SLDOScanHandler.stop() def urgentStop(self): - for process in self.run_processes: process.kill() + for process in self.run_processes: + process.kill() self.halt = True self.haltSignal.emit(self.halt) self.starttime = None - def validateTest(self): #ATOC = At time of commit + def validateTest(self): # ATOC = At time of commit self.finished_tests.append(self.currentTest) try: passed = [] results = [] runNumber = "000000" if self.RunNumber == "-1" else self.RunNumber - + for beboard in self.firmware: boardID = beboard.getBoardID() for OG in beboard.getAllOpticalGroups().values(): @@ -591,53 +630,63 @@ def validateTest(self): #ATOC = At time of commit for module in OG.getAllModules().values(): hybridID = module.getFMCPort() module_data = { - 'boardID':boardID, - 'ogID':ogID, - 'hybridID':hybridID, - 'module':module + "boardID": boardID, + "ogID": ogID, + "hybridID": hybridID, + "module": module, } result, self.BBanalysis_root_files = ResultGrader( - self.felis, self.output_dir, self.currentTest, - self.testIndexTracker, runNumber, module_data, self.BBanalysis_root_files + self.felis, + self.output_dir, + self.currentTest, + self.testIndexTracker, + runNumber, + module_data, + self.BBanalysis_root_files, ) results.append(result) passed.append(list(result.values())[0][0]) - - self.figurelist[module.getModuleName()] = self.collect_plots(module.getModuleName()) - + + self.figurelist[module.getModuleName()] = self.collect_plots( + module.getModuleName() + ) + self.updateValidation.emit(results) - self.updateFinishedTests.emit(self.finished_tests) #Obsolete ATOC: "return all(passed)" + self.updateFinishedTests.emit( + self.finished_tests + ) # Obsolete ATOC: "return all(passed)" except Exception as err: logger.error(err) - + def collect_plots(self, moduleName): try: plot_paths = [] scratch = os.path.join(self.felis.path_scratch, moduleName) test = "{0:02d}_{1}".format(self.testIndexTracker, self.currentTest) directory = os.path.join(scratch, test) - + for filename in os.listdir(directory): - if filename.lower().endswith('.svg') or filename.lower().endswith('.png'): + if filename.lower().endswith(".svg") or filename.lower().endswith( + ".png" + ): plot_paths.append(os.path.join(directory, filename)) - + return plot_paths except Exception as e: - if 'IVCurve' in self.currentTest or 'SLDOScan' in self.currentTest: + if "IVCurve" in self.currentTest or "SLDOScan" in self.currentTest: if moduleName in self.figurelist.keys(): return self.figurelist[moduleName] else: return [] else: - print('testHandler.collect_plots Exception:', repr(e)) + print("testHandler.collect_plots Exception:", repr(e)) return [] - - #For root files with the same RunNumber in the PH2ACF directory, this function only copies over to - #self.output_dir the .root file modified most recently. This will copy over the wrong file if somebody - #manually edits the .root file in the PH2ACF directory, so there may be a better way to do this - def copyMostRecentRootFile(self,RunNumber,base_dir,output_dir,test): - + + # For root files with the same RunNumber in the PH2ACF directory, this function only copies over to + # self.output_dir the .root file modified most recently. This will copy over the wrong file if somebody + # manually edits the .root file in the PH2ACF directory, so there may be a better way to do this + def copyMostRecentRootFile(self, RunNumber, base_dir, output_dir, test): files = root_files[test] if test in root_files.keys() else (test,) for name in files: # Construct the search pattern for files @@ -648,23 +697,27 @@ def copyMostRecentRootFile(self,RunNumber,base_dir,output_dir,test): # Find all matching files matching_files = glob.glob(search_pattern) - if len(matching_files)==0: - raise Exception(f"Failed to copy root file to output directory. \ + if len(matching_files) == 0: + raise Exception( + f"Failed to copy root file to output directory. \ Module disconnection detected because Ph2_ACF didn't \ -create {search_pattern}.") +create {search_pattern}." + ) # Sort files by modification time (newest first) latest_file = max(matching_files, key=os.path.getmtime) - if os.path.getsize(latest_file)==0: - raise Exception(f"Failed to copy root file to output directory. \ + if os.path.getsize(latest_file) == 0: + raise Exception( + f"Failed to copy root file to output directory. \ Module disconnection detected because {latest_file} \ -created by Ph2_ACF is empty.") +created by Ph2_ACF is empty." + ) # Copy the most recent file to the output directory os.system(f"cp {latest_file} {output_dir}/") - def saveTest(self, processIndex:int): + def saveTest(self, processIndex: int): if self.run_processes[processIndex].state() == QProcess.Running: QMessageBox.critical(self, "Error", "Process not finished", QMessageBox.Ok) return @@ -686,7 +739,12 @@ def saveTest(self, processIndex:int): ) ) else: - self.copyMostRecentRootFile(self.RunNumber,os.environ.get("PH2ACF_BASE_DIR")+"/test/Results",self.output_dir,self.currentTest) + self.copyMostRecentRootFile( + self.RunNumber, + os.environ.get("PH2ACF_BASE_DIR") + "/test/Results", + self.output_dir, + self.currentTest, + ) except Exception as e: logger.error(e) @@ -697,15 +755,17 @@ def saveTest(self, processIndex:int): ####################################################################### @QtCore.pyqtSlot() - def on_readyReadStandardOutput(self, processIndex:int): - if self.readingOutput == True: + def on_readyReadStandardOutput(self, processIndex: int): + if self.readingOutput: print("Thread competition detected") return self.readingOutput = True - alltext = self.run_processes[processIndex].readAllStandardOutput().data().decode() + alltext = ( + self.run_processes[processIndex].readAllStandardOutput().data().decode() + ) self.outputfile.write(alltext) - #print(alltext) + # print(alltext) # outputfile.close() textline = alltext.split("\n") # fileLines = open(self.outputFile,"r") @@ -713,27 +773,30 @@ def on_readyReadStandardOutput(self, processIndex:int): for textStr in textline: import re + try: if "Configuring chips of hybrid" in textStr: - ansi_escape = re.compile(r'\x1b\[.*?m') - clean_text = ansi_escape.sub('', textStr) + ansi_escape = re.compile(r"\x1b\[.*?m") + clean_text = ansi_escape.sub("", textStr) hybrid_id = clean_text.split("hybrid: ")[-1].strip() self.mod_dict[hybrid_id] = {} self.fused_dict_index[0] = hybrid_id if "Configuring RD53" in textStr: - ansi_escape = re.compile(r'\x1b\[.*?m') - clean_text = ansi_escape.sub('', textStr) - chip_number= clean_text.split("RD53: ")[-1].strip() - self.fused_dict_index[1]= chip_number + ansi_escape = re.compile(r"\x1b\[.*?m") + clean_text = ansi_escape.sub("", textStr) + chip_number = clean_text.split("RD53: ")[-1].strip() + self.fused_dict_index[1] = chip_number if "Fused ID" in textStr: - ansi_escape = re.compile(r'\x1b\[.*?m') - clean_text = ansi_escape.sub('', textStr) - fuse_id =clean_text.split("Fused ID: ")[-1].strip() - self.mod_dict[self.fused_dict_index[0]][self.fused_dict_index[1]]= fuse_id - - if self.starttime != None: + ansi_escape = re.compile(r"\x1b\[.*?m") + clean_text = ansi_escape.sub("", textStr) + fuse_id = clean_text.split("Fused ID: ")[-1].strip() + self.mod_dict[self.fused_dict_index[0]][ + self.fused_dict_index[1] + ] = fuse_id + + if self.starttime is not None: self.currentTime = time.time() runningTime = self.currentTime - self.starttime self.runwindow.ResultWidget.runtime[self.testIndexTracker].setText( @@ -745,88 +808,119 @@ def on_readyReadStandardOutput(self, processIndex:int): except Exception as err: logger.info("Error occures while parsing running time, {0}".format(err)) - if '@@@ End of CMSIT miniDAQ @@@' in textStr: + if "@@@ End of CMSIT miniDAQ @@@" in textStr: self.ProgressingMode = "Summary" if self.ProgressingMode == "Perform": if "Progress:" in textStr: try: - index = textStr.split().index("Progress:") + 2 - #self.ProgressValue = float(textStr.split()[index].rstrip("%")) - self.ProgressValue = float(re.sub(r'\x1b\[\d+m', '', textStr.split()[index].strip("%"))) + index = textStr.split().index("Progress:") + 2 + # self.ProgressValue = float(textStr.split()[index].rstrip("%")) + self.ProgressValue = float( + re.sub(r"\x1b\[\d+m", "", textStr.split()[index].strip("%")) + ) if self.ProgressValue == 100: self.ProgressingMode = "Summary" self.runwindow.ResultWidget.ProgressBar[ self.testIndexTracker ].setValue(self.ProgressValue) ##Added because of Ph2_ACF bug: - - except: - print('something went wrong in progress') + + except Exception as e: + print(f"Error while updating progress bar {e}") pass if self.check_for_end_of_test(textStr): - self.runwindow.ResultWidget.ProgressBar[self.testIndexTracker].setValue(100) + self.runwindow.ResultWidget.ProgressBar[ + self.testIndexTracker + ].setValue(100) elif "TEMPSENS_" in textStr: try: output = textStr.split("[") sensor = output[8] sensorMeasure = sensor[3:] - - if sensorMeasure != "" or sensorMeasure != "44.086 +/- 1.763 °C": - temp = float(sensorMeasure.split('+')[0].strip()) + + if ( + sensorMeasure != "" + or sensorMeasure != "44.086 +/- 1.763 °C" + ): + temp = float(sensorMeasure.split("+")[0].strip()) self.tempHistory[self.tempindex] = temp - if any(num > site_settings.Warning_Threshold for num in self.tempHistory): + if any( + num > site_settings.Warning_Threshold + for num in self.tempHistory + ): self.runwindow.updateTempIndicator("orange") - elif any(num > site_settings.Emergency_Threshold for num in self.tempHistory): + elif any( + num > site_settings.Emergency_Threshold + for num in self.tempHistory + ): self.runwindow.updateTempIndicator("red") else: self.runwindow.updateTempIndicator("green") else: - #bad reading + # bad reading self.tempHistory[self.tempindex] = 0.0 if not all(self.tempHistory): self.runwindow.updateTempIndicator("off") - self.tempindex = self.tempindex+1 % self.numChips - + self.tempindex = self.tempindex + 1 % self.numChips + except Exception as e: print("Failed due to {0}".format(e)) elif "INTERNAL_NTC" in textStr: try: - ansi_pattern = re.compile(r'\x1B[@-_][0-?]*[ -/]*[@-~]') - clean_text=ansi_pattern.sub('', textStr) + ansi_pattern = re.compile(r"\x1B[@-_][0-?]*[ -/]*[@-~]") + clean_text = ansi_pattern.sub("", textStr) if "INTERNAL_NTC" in clean_text: - sensor=clean_text.split("INTERNAL_NTC:")[1].strip().split("C")[0].strip() - sensorMeasure0=re.sub(r'[^\d\.\+\- ]', '', sensor) + sensor = ( + clean_text.split("INTERNAL_NTC:")[1] + .strip() + .split("C")[0] + .strip() + ) + sensorMeasure0 = re.sub(r"[^\d\.\+\- ]", "", sensor) sensorMeasure0 += " °C" sensorMeasure = sensorMeasure0.replace("+-", "+/-") - - if sensorMeasure != "" or sensorMeasure != "44.086 +/- 1.763 °C": - temp = float(sensorMeasure.split('+')[0].strip()) + + if ( + sensorMeasure != "" + or sensorMeasure != "44.086 +/- 1.763 °C" + ): + temp = float(sensorMeasure.split("+")[0].strip()) self.tempHistory[self.tempindex] = temp - if any(num > site_settings.Warning_Threshold for num in self.tempHistory): + if any( + num > site_settings.Warning_Threshold + for num in self.tempHistory + ): self.runwindow.updateTempIndicator("orange") - elif any(num > site_settings.Emergency_Threshold for num in self.tempHistory): + elif any( + num > site_settings.Emergency_Threshold + for num in self.tempHistory + ): self.runwindow.updateTempIndicator("red") else: self.runwindow.updateTempIndicator("green") else: - #bad reading + # bad reading self.tempHistory[self.tempindex] = 0.0 if not all(self.tempHistory): self.runwindow.updateTempIndicator("off") self.tempindex = (self.tempindex + 1) % self.numChips - + except Exception as e: print("Failed due to {0}".format(e)) text = textStr.encode("ascii") _, text = parseANSI(text) - self.outputString.emit(text.decode("utf-8"), self.runwindow.ConsoleViews[processIndex]) + self.outputString.emit( + text.decode("utf-8"), self.runwindow.ConsoleViews[processIndex] + ) continue - #This next block needs to be edited once Ph2ACF bug is fixed. Remove the Fixme when ready. - + # This next block needs to be edited once Ph2ACF bug is fixed. Remove the Fixme when ready. + elif self.ProgressingMode == "Summary": if self.check_for_end_of_test(textStr): - self.runwindow.ResultWidget.ProgressBar[self.testIndexTracker].setValue(100) + self.runwindow.ResultWidget.ProgressBar[ + self.testIndexTracker + ].setValue(100) elif "@@@ Initializing the Hardware @@@" in textStr: self.ProgressingMode = "Configure" elif "@@@ Performing" in textStr: @@ -834,22 +928,31 @@ def on_readyReadStandardOutput(self, processIndex:int): self.outputString.emit( ' Performing the {} test '.format( self.currentTest - ),self.runwindow.ConsoleViews[processIndex] + ), + self.runwindow.ConsoleViews[processIndex], ) text = textStr.encode("ascii") _, text = parseANSI(text) - self.outputString.emit(text.decode("utf-8"),self.runwindow.ConsoleViews[processIndex]) + self.outputString.emit( + text.decode("utf-8"), self.runwindow.ConsoleViews[processIndex] + ) self.readingOutput = False def updateOptimizedXMLValues(self): - print('trying to update the xml value') + print("trying to update the xml value") try: if Test_to_Ph2ACF_Map[self.currentTest] in optimizationTestMap.keys(): - updatedFEKeys = optimizationTestMap[Test_to_Ph2ACF_Map[self.currentTest]] + updatedFEKeys = optimizationTestMap[ + Test_to_Ph2ACF_Map[self.currentTest] + ] for module in self.modules: - chipIDs = [chip.getID() for chip in module.getChips().values() if chip.getStatus()] + chipIDs = [ + chip.getID() + for chip in module.getChips().values() + if chip.getStatus() + ] hybridID = module.getFMCPort() print("HybridID {0}".format(hybridID)) @@ -859,18 +962,25 @@ def updateOptimizedXMLValues(self): updatedXMLValues[f"{hybridID}/{chipID}"] = {} for updatedFEKey in updatedFEKeys: if CROC: - if updatedFEKey in ["LATENCY_CONFIG", "Vthreshold_LIN"]: # registers not on CROC modules + if updatedFEKey in [ + "LATENCY_CONFIG", + "Vthreshold_LIN", + ]: # registers not on CROC modules continue elif not CROC: - if updatedFEKey in ["TriggerConfig", "DAC_GDAC_", "CAL_EDGE_FINE_DELAY"]: # registers only on CROC modules + if updatedFEKey in [ + "TriggerConfig", + "DAC_GDAC_", + "CAL_EDGE_FINE_DELAY", + ]: # registers only on CROC modules continue updatedXMLValues[f"{hybridID}/{chipID}"][updatedFEKey] = "" except Exception as err: logger.error(f"Failed to update, {err}") - + def check_for_end_of_test(self, textStr): - #function to support the quick fix in on_readyReadStandardOutput() where - #the progress bar doesn't always reach 100%. + # function to support the quick fix in on_readyReadStandardOutput() where + # the progress bar doesn't always reach 100%. currentTest = Test_to_Ph2ACF_Map[self.currentTest] if currentTest in ["thradj", "thrmin"] and "Global threshold for" in textStr: return True @@ -889,34 +999,38 @@ def check_for_end_of_test(self, textStr): # Reads data that is normally printed to the terminal and saves it to the output file @QtCore.pyqtSlot() - def on_readyReadStandardOutput_info(self, processIndex:int): + def on_readyReadStandardOutput_info(self, processIndex: int): if os.path.exists(self.outputFile): outputfile = open(self.outputFile, "a") else: outputfile = open(self.outputFile, "w") - alltext = self.info_processes[processIndex].readAllStandardOutput().data().decode() + alltext = ( + self.info_processes[processIndex].readAllStandardOutput().data().decode() + ) outputfile.write(alltext) outputfile.close() textline = alltext.split("\n") for textStr in textline: - self.outputString.emit(textStr,self.runwindow.ConsoleViews[processIndex]) + self.outputString.emit(textStr, self.runwindow.ConsoleViews[processIndex]) @QtCore.pyqtSlot() - def on_finish(self, processIndex:int): + def on_finish(self, processIndex: int): self.outputfile.close() # While the process is killed: - if self.halt == True: + if self.halt: self.haltSignal.emit(True) return if self.run_processes[processIndex].state() == QProcess.Running: - print("process is still running... Attempting to terminate before next test.") + print( + "process is still running... Attempting to terminate before next test." + ) self.run_processes[processIndex].terminate() if not self.run_processes[processIndex].waitForFinished(3000): - print('process would not terminate, so killing it now...') + print("process would not terminate, so killing it now...") self.run_processes[processIndex].kill() if "IVCurve" in self.currentTest: @@ -953,7 +1067,9 @@ def onFinalTest(self, index): EnableReRun = False # Will send signal to turn off power supply after composite or single tests are run if isCompositeTest(self.info): - if index == len(CompositeTests[self.info]): # Checks that this was the last test in the sequence. + if index == len( + CompositeTests[self.info] + ): # Checks that this was the last test in the sequence. self.powerSignal.emit() EnableReRun = True if self.autoSave: @@ -961,7 +1077,7 @@ def onFinalTest(self, index): if self.info == "FWD-RVS Bias" or self.info == "CrossTalk": self.bumpbond_analysis() - if len(self.BBanalysis_root_files)>0: + if len(self.BBanalysis_root_files) > 0: for beboard in self.firmware: boardID = beboard.getBoardID() for OG in beboard.getAllOpticalGroups().values(): @@ -969,21 +1085,23 @@ def onFinalTest(self, index): for module in OG.getAllModules().values(): hybridID = module.getFMCPort() module_data = { - 'boardID':boardID, - 'ogID':ogID, - 'hybridID':hybridID, - 'module':module + "boardID": boardID, + "ogID": ogID, + "hybridID": hybridID, + "module": module, } "This works" self.felis.set_result( self.BBanalysis_root_files, - module_data['module'].getModuleName(), + module_data["module"].getModuleName(), f"{index:02d}_{self.currentTest}", Test_to_Ph2ACF_Map[self.currentTest], ) - self.figurelist[module.getModuleName()] = self.collect_plots(module.getModuleName()) - + self.figurelist[module.getModuleName()] = ( + self.collect_plots(module.getModuleName()) + ) + elif isSingleTest(self.info): EnableReRun = True self.powerSignal.emit() @@ -993,38 +1111,72 @@ def onFinalTest(self, index): return EnableReRun def updateProgress(self, measurementType, stepSize): - if measurementType=='IVCurve': - self.IVProgressValue += stepSize/2.0 - self.runwindow.ResultWidget.ProgressBar[self.testIndexTracker].setValue(self.IVProgressValue) - self.ramp_progress_bar([site_settings.IVcurve_range[self.currentTest] if site_settings.IVcurve_range[self.currentTest]<0 else 80]*len(self.instruments._module_dict.values())) - if 'SLDO' in measurementType: + if measurementType == "IVCurve": + self.IVProgressValue += stepSize / 2.0 + self.runwindow.ResultWidget.ProgressBar[self.testIndexTracker].setValue( + self.IVProgressValue + ) + self.ramp_progress_bar( + [ + site_settings.IVcurve_range[self.currentTest] + if site_settings.IVcurve_range[self.currentTest] < 0 + else 80 + ] + * len(self.instruments._module_dict.values()) + ) + if "SLDO" in measurementType: self.SLDOProgressValue += stepSize - self.runwindow.ResultWidget.ProgressBar[self.testIndexTracker].setValue(self.SLDOProgressValue) + self.runwindow.ResultWidget.ProgressBar[self.testIndexTracker].setValue( + self.SLDOProgressValue + ) def makeSLDOPlot(self, total_result: np.ndarray, pin: str): for module in self.modules: moduleName = module.getModuleName() - filename = "{0}/SLDOCurve_Module_{1}_{2}.svg".format(self.output_dir, moduleName, pin) - csvfilename = "{0}/SLDOCurve_Module_{1}_{2}.csv".format(self.output_dir, moduleName, pin) + filename = "{0}/SLDOCurve_Module_{1}_{2}.svg".format( + self.output_dir, moduleName, pin + ) + csvfilename = "{0}/SLDOCurve_Module_{1}_{2}.csv".format( + self.output_dir, moduleName, pin + ) self.SLDOfilelist.append(csvfilename) - #The pin is passed here, so we can use that as the key in the chipmap dict from settings.py + # The pin is passed here, so we can use that as the key in the chipmap dict from settings.py total_result_stacked = np.vstack(total_result) - np.savetxt(csvfilename, total_result_stacked, delimiter=',') + np.savetxt(csvfilename, total_result_stacked, delimiter=",") - #Make the actual graph + # Make the actual graph plt.figure() - plt.plot(total_result_stacked[0], total_result_stacked[1], '-x', label="module input voltage (up)") - plt.plot(total_result_stacked[0], total_result_stacked[2], '-x', label=f"{pin} (up)") - plt.plot(total_result_stacked[3], total_result_stacked[4], '-x', label="module input voltage (down)") - plt.plot(total_result_stacked[3], total_result_stacked[5], '-x', label=f"{pin} (down)") + plt.plot( + total_result_stacked[0], + total_result_stacked[1], + "-x", + label="module input voltage (up)", + ) + plt.plot( + total_result_stacked[0], + total_result_stacked[2], + "-x", + label=f"{pin} (up)", + ) + plt.plot( + total_result_stacked[3], + total_result_stacked[4], + "-x", + label="module input voltage (down)", + ) + plt.plot( + total_result_stacked[3], + total_result_stacked[5], + "-x", + label=f"{pin} (down)", + ) plt.grid(True) plt.xlabel("Current (A)") plt.ylabel("Voltage (V)") plt.legend() plt.savefig(filename) - - self.figurelist[moduleName] = [filename] + self.figurelist[moduleName] = [filename] def IVCurveFinished(self, test: str, measure: dict): # Get the current timestamp @@ -1034,9 +1186,9 @@ def IVCurveFinished(self, test: str, measure: dict): process.waitForBytesWritten() process.waitForFinished() - #3/17/25 : Once HV distributor box arrives, functionality needs to be added for running - #IVCurve on multiple modules. Once that happens, the loop under this comment can be edited - #to output the results only to the console of the fc7 that each module is connnected to. + # 3/17/25 : Once HV distributor box arrives, functionality needs to be added for running + # IVCurve on multiple modules. Once that happens, the loop under this comment can be edited + # to output the results only to the console of the fc7 that each module is connnected to. for console in self.runwindow.ConsoleViews: self.outputString.emit(f"Voltages: {measure['voltage']}", console) self.outputString.emit(f"Currents: {measure['current']}", console) @@ -1056,25 +1208,32 @@ def IVCurveFinished(self, test: str, measure: dict): invert=True, ) - csvfilename = "{0}/IVCurve_Module_{1}_{2}.csv".format(self.output_dir, moduleName, timestamp) - np.savetxt(csvfilename, (measure["voltage"], measure["current"]), delimiter=',') + csvfilename = "{0}/IVCurve_Module_{1}_{2}.csv".format( + self.output_dir, moduleName, timestamp + ) + np.savetxt( + csvfilename, (measure["voltage"], measure["current"]), delimiter="," + ) module_canvas_path = "Detector/Board_{boardID}/OpticalGroup_{ogID}/Hybrid_{hybridID}/".format( - boardID=beboardId, - ogID=ogId, - hybridID=hybridId) - - IVCurve_CSV_to_ROOT(moduleName, module_canvas_path, csvfilename, self.output_dir) - - filename = "{0}/IVCurve_Module_{1}_{2}.svg".format(self.output_dir, moduleName, timestamp) - #filename2 = "IVCurve_Module_{0}_{1}.svg".format(moduleName, timestamp) + boardID=beboardId, ogID=ogId, hybridID=hybridId + ) + + IVCurve_CSV_to_ROOT( + moduleName, module_canvas_path, csvfilename, self.output_dir + ) + + filename = "{0}/IVCurve_Module_{1}_{2}.svg".format( + self.output_dir, moduleName, timestamp + ) + # filename2 = "IVCurve_Module_{0}_{1}.svg".format(moduleName, timestamp) self.IVCurveResult.saveToSVG(filename) - #self.IVCurveResult.saveToSVG(filename2) - + # self.IVCurveResult.saveToSVG(filename2) + self.figurelist[moduleName] = [filename] self.validateTest() - step="IVCurve" + step = "IVCurve" self.testIndexTracker += 1 @@ -1082,15 +1241,19 @@ def IVCurveFinished(self, test: str, measure: dict): # Will send signal to turn off power supply after composite or single tests are run if isCompositeTest(self.info): - default_hv_voltage = site_settings.icicle_instrument_setup['instrument_dict']['hv']['default_voltage'] - #assumes only 1 HV titled 'hv' in instruments.json + default_hv_voltage = site_settings.icicle_instrument_setup[ + "instrument_dict" + ]["hv"]["default_voltage"] + # assumes only 1 HV titled 'hv' in instruments.json self.master.instruments.hv_on( voltage=default_hv_voltage, delay=0.3, step_size=3, measure=False, - execute_each_step=lambda:self.ramp_progress_bar([default_hv_voltage]*len(self.instruments._module_dict.values())) + execute_each_step=lambda: self.ramp_progress_bar( + [default_hv_voltage] * len(self.instruments._module_dict.values()) + ), ) if self.testIndexTracker == len(CompositeTests[self.info]): @@ -1109,25 +1272,29 @@ def IVCurveFinished(self, test: str, measure: dict): self.historyRefresh.emit() if self.master.expertMode: self.updateIVResult.emit(self.output_dir) - else: - self.updateIVResult.emit((step, self.figurelist)) ##Add else statement to add signal in simple mode + else: + self.updateIVResult.emit( + (step, self.figurelist) + ) ##Add else statement to add signal in simple mode if isCompositeTest(self.info): self.runTest() def SLDOScanFinished(self): - for module in self.modules: ogId = module.getOpticalGroup().getOpticalGroupID() beboardId = module.getOpticalGroup().getBeBoard().getBoardID() moduleName = module.getModuleName() hybridId = module.getFMCPort() - module_canvas_path = "Detector/Board_{boardID}/OpticalGroup_{ogID}/Hybrid_{hybridID}".format( - boardID=beboardId, - ogID=ogId, - hybridID=hybridId) - - SLDO_CSV_to_ROOT(moduleName, module_canvas_path, self.SLDOfilelist, self.output_dir) + module_canvas_path = ( + "Detector/Board_{boardID}/OpticalGroup_{ogID}/Hybrid_{hybridID}".format( + boardID=beboardId, ogID=ogId, hybridID=hybridId + ) + ) + + SLDO_CSV_to_ROOT( + moduleName, module_canvas_path, self.SLDOfilelist, self.output_dir + ) self.validateTest() self.testIndexTracker += 1 @@ -1139,14 +1306,18 @@ def SLDOScanFinished(self): voltage=site_settings.ModuleVoltageMapSLDO[self.master.module_in_use], current=site_settings.ModuleCurrentMap[self.master.module_in_use], ) - default_hv_voltage = site_settings.icicle_instrument_setup['instrument_dict']['hv']['default_voltage'] - #assumes only 1 HV titled 'hv' in instruments.json + default_hv_voltage = site_settings.icicle_instrument_setup[ + "instrument_dict" + ]["hv"]["default_voltage"] + # assumes only 1 HV titled 'hv' in instruments.json self.master.instruments.hv_on( voltage=default_hv_voltage, delay=0.3, step_size=5, measure=False, - execute_each_step=lambda:self.ramp_progress_bar([default_hv_voltage]*len(self.instruments._module_dict.values())) + execute_each_step=lambda: self.ramp_progress_bar( + [default_hv_voltage] * len(self.instruments._module_dict.values()) + ), ) if self.testIndexTracker == len(CompositeTests[self.info]): @@ -1165,23 +1336,28 @@ def SLDOScanFinished(self): self.historyRefresh.emit() if self.master.expertMode: self.updateSLDOResult.emit(self.output_dir) - else: - self.updateSLDOResult.emit(("SLDOScan", self.figurelist)) ##Add else statement to add signal in simple mode + else: + self.updateSLDOResult.emit( + ("SLDOScan", self.figurelist) + ) ##Add else statement to add signal in simple mode if isCompositeTest(self.info): self.runTest() def interactiveCheck(self, plot): pass - - def forceContinue(self, board): #board:QtBeBoard. Runs when module disconnection is suspected. - + + def forceContinue( + self, board + ): # board:QtBeBoard. Runs when module disconnection is suspected. fc7modules = board.getModules() # Create the main widget self.force_continue_window = QDialog() self.force_continue_window.setMaximumWidth(375) - self.force_continue_window.setWindowTitle(f"{board.getBoardName()}: Failed Component Detected") + self.force_continue_window.setWindowTitle( + f"{board.getBoardName()}: Failed Component Detected" + ) # Create layout self.force_continue_window.layout = QVBoxLayout(self.force_continue_window) @@ -1197,16 +1373,24 @@ def forceContinue(self, board): #board:QtBeBoard. Runs when module disconnection # Create table for modules with checkboxes self.force_continue_window.table = QTableWidget(len(fc7modules), 2) - self.force_continue_window.table.setHorizontalHeaderLabels(["Module", "Enabled"]) - + self.force_continue_window.table.setHorizontalHeaderLabels( + ["Module", "Enabled"] + ) + for row, module in enumerate(fc7modules): # Set the module name in the first column module_name = module.getModuleName() - self.force_continue_window.table.setItem(row, 0, QTableWidgetItem(module_name)) - + self.force_continue_window.table.setItem( + row, 0, QTableWidgetItem(module_name) + ) + # Create a QTableWidgetItem for the checkbox in the second column checkbox_item = QTableWidgetItem() - checkbox_item.setCheckState(Qt.Checked) if module.getEnabled()=="1" else checkbox_item.setCheckState(Qt.Unchecked) + checkbox_item.setCheckState( + Qt.Checked + ) if module.getEnabled() == "1" else checkbox_item.setCheckState( + Qt.Unchecked + ) self.force_continue_window.table.setItem(row, 1, checkbox_item) self.force_continue_window.layout.addWidget(self.force_continue_window.table) @@ -1214,52 +1398,69 @@ def forceContinue(self, board): #board:QtBeBoard. Runs when module disconnection self.force_continue_window.abort = True - def check_enabledModules(): #Not sure if this is maximally efficient + def check_enabledModules(): # Not sure if this is maximally efficient for row in range(len(fc7modules)): - if self.force_continue_window.table.item(row,1).checkState()==Qt.Checked: - + if ( + self.force_continue_window.table.item(row, 1).checkState() + == Qt.Checked + ): for row in range(len(fc7modules)): - if self.force_continue_window.table.item(row,1).checkState()==Qt.Checked: + if ( + self.force_continue_window.table.item(row, 1).checkState() + == Qt.Checked + ): fc7modules[row].setEnabled("1") else: fc7modules[row].setEnabled("0") self.force_continue_window.abort = False return True - - if hasattr(self.force_continue_window, "label")==False: - self.force_continue_window.label = QLabel("At least one module must be enabled.") - self.force_continue_window.label.setStyleSheet('color: red;') - self.force_continue_window.layout.insertWidget(3,self.force_continue_window.label) + + if not hasattr(self.force_continue_window, "label"): + self.force_continue_window.label = QLabel( + "At least one module must be enabled." + ) + self.force_continue_window.label.setStyleSheet("color: red;") + self.force_continue_window.layout.insertWidget( + 3, self.force_continue_window.label + ) return False # Define button handlers def handle_close(event): - if self.force_continue_window.abort==True: - for process in self.run_processes: process.kill() + if self.force_continue_window.abort: + for process in self.run_processes: + process.kill() self.halt = True self.haltSignal.emit(self.halt) self.starttime = None for row in range(self.force_continue_window.table.rowCount()): - if self.force_continue_window.table.item(row,1).checkState()==False: - self.statuses[self.force_continue_window.table.item(row,0).text()]="0" + if not self.force_continue_window.table.item(row, 1).checkState(): + self.statuses[ + self.force_continue_window.table.item(row, 0).text() + ] = "0" event.accept() def handle_retry(): if check_enabledModules(): - self.outputString.emit(f'Retrying {self.currentTest}...') - self.runwindow.ResultWidget.runtime[self.testIndexTracker].setText("") #may need to .update() - self.runwindow.ResultWidget.ProgressBar[self.testIndexTracker].setValue(0) #may need to .update(). Automatically adds "0%" text on Progress bar. + self.outputString.emit(f"Retrying {self.currentTest}...") + self.runwindow.ResultWidget.runtime[self.testIndexTracker].setText( + "" + ) # may need to .update() + self.runwindow.ResultWidget.ProgressBar[self.testIndexTracker].setValue( + 0 + ) # may need to .update(). Automatically adds "0%" text on Progress bar. self.testIndexTracker -= 1 self.force_continue_window.close() - + def handle_continue(): - if check_enabledModules(): self.force_continue_window.close() + if check_enabledModules(): + self.force_continue_window.close() # Connect buttons to handlers - exit_button.clicked.connect(lambda : self.force_continue_window.close()) + exit_button.clicked.connect(lambda: self.force_continue_window.close()) retry_button.clicked.connect(handle_retry) continue_button.clicked.connect(handle_continue) @@ -1267,11 +1468,10 @@ def handle_continue(): self.force_continue_window.exec_() # This will block until the window is closed def upload_to_Panthera(self): - self.updateProgressBar.emit(self.runwindow.UploadProgressBar, - 0, - f'{0}/{len(self.modules)} uploaded') + self.updateProgressBar.emit( + self.runwindow.UploadProgressBar, 0, f"{0}/{len(self.modules)} uploaded" + ) try: - self.runwindow.UploadButton.setDisabled(True) counter = 0 @@ -1280,67 +1480,83 @@ def upload_to_Panthera(self): module.getModuleName(), self.master.username, self.master.password, - type_sequence = self.info, - version_ph2acf = os.environ.get("PH2ACF_VERSION"), + type_sequence=self.info, + version_ph2acf=os.environ.get("PH2ACF_VERSION"), ) if not status: raise ConnectionError(message) - counter+=1 - self.updateProgressBar.emit(self.runwindow.UploadProgressBar, - 100*counter/len(self.modules), - f'{counter}/{len(self.modules)} uploaded') + counter += 1 + self.updateProgressBar.emit( + self.runwindow.UploadProgressBar, + 100 * counter / len(self.modules), + f"{counter}/{len(self.modules)} uploaded", + ) except ConnectionError as e: error_message = repr(e) logger.error(error_message) self.master.errorMessageBoxSignal.emit(error_message) - - except Exception as e: + + except Exception: if not self.master.panthera_connected: - error_message = "Cannot upload test results, you are not signed in to Panthera." + error_message = ( + "Cannot upload test results, you are not signed in to Panthera." + ) else: error_message = "Failed to upload to Panthera." self.runwindow.UploadButton.setDisabled(False) if self.autoSave: - self.runwindow.UploadButton.setDisabled(False) #if autosave fails, allow manual + self.runwindow.UploadButton.setDisabled( + False + ) # if autosave fails, allow manual logger.error(error_message) self.master.errorMessageBoxSignal.emit(error_message) - def bumpbond_analysis(self): - runNumber = "000000" if self.RunNumber == "-1" else self.RunNumber - commands = ['.L /home/cmsTkUser/Ph2_ACF_GUI/InnerTrackerTests/Analysis/bumpbond_analysis.cpp'] + commands = [ + ".L /home/cmsTkUser/Ph2_ACF_GUI/InnerTrackerTests/Analysis/bumpbond_analysis.cpp" + ] command_template = "" - + if self.info == "FWD-RVS Bias": process = subprocess.run( 'find /home/cmsTkUser/Ph2_ACF_GUI/Ph2_ACF/test/Results -type f -name "*SCurve.root"', shell=True, stdout=subprocess.PIPE, ) - all_root_files = sorted(process.stdout.decode('utf-8').rstrip("\n").split("\n")) + all_root_files = sorted( + process.stdout.decode("utf-8").rstrip("\n").split("\n") + ) relevant_root_files = all_root_files[-2:] - + save_file = f"Run{runNumber}_FWDRVS-Bias.root" commands.append(f'createROOTFile("{self.output_dir}/{save_file}")') - command_template = f'bias("{relevant_root_files[0]}", "{relevant_root_files[1]}", "{self.output_dir}/{save_file}", '+'const_cast(std::array{{{0}, {1}, {2}, {3}}}.data()))' - + command_template = ( + f'bias("{relevant_root_files[0]}", "{relevant_root_files[1]}", "{self.output_dir}/{save_file}", ' + + "const_cast(std::array{{{0}, {1}, {2}, {3}}}.data()))" + ) + elif self.info == "Crosstalk": process = subprocess.run( 'find /home/cmsTkUser/Ph2_ACF_GUI/Ph2_ACF/test/Results -type f -name "*PixelAlive.root"', shell=True, stdout=subprocess.PIPE, ) - all_root_files = sorted(process.stdout.decode('utf-8').rstrip("\n").split("\n")) + all_root_files = sorted( + process.stdout.decode("utf-8").rstrip("\n").split("\n") + ) relevant_root_files = all_root_files[-3:] - + save_file = f"Run{runNumber}_Crosstalk.root" commands.append(f'createROOTFile("{self.output_dir}/{save_file}")') - command_template = f'xtalk("{relevant_root_files[0]}", "{relevant_root_files[1]}", "{relevant_root_files[2]}", "{self.output_dir}/{save_file}",'+'const_cast(std::array{{{0}, {1}, {2}, {3}}}.data()))' - + command_template = ( + f'xtalk("{relevant_root_files[0]}", "{relevant_root_files[1]}", "{relevant_root_files[2]}", "{self.output_dir}/{save_file}",' + + "const_cast(std::array{{{0}, {1}, {2}, {3}}}.data()))" + ) + for beboard in self.firmware: boardID = beboard.getBoardID() for OG in beboard.getAllOpticalGroups().values(): @@ -1348,5 +1564,7 @@ def bumpbond_analysis(self): for module in OG.getAllModules().values(): hybridID = module.getFMCPort() for chipID in module.getEnabledChips().keys(): - commands.append(command_template.format(boardID, ogID, hybridID, chipID)) + commands.append( + command_template.format(boardID, ogID, hybridID, chipID) + ) executeCommandSequence(commands) diff --git a/Gui/python/TestValidator.py b/Gui/python/TestValidator.py index 96fdf874..3b7ebe59 100644 --- a/Gui/python/TestValidator.py +++ b/Gui/python/TestValidator.py @@ -1,70 +1,105 @@ +import os import ROOT +from InnerTrackerTests.TestSequences import Test_to_Ph2ACF_Map + ROOT.gROOT.SetBatch(ROOT.kTRUE) -import os -from Gui.python.logging_config import logger -from InnerTrackerTests.TestSequences import Test_to_Ph2ACF_Map -from InnerTrackerTests.Analysis.IVCurve_CSV_to_ROOT import IVCurve_CSV_to_ROOT -def ResultGrader(felis, outputDir, testName, testIndexInSequence, runNumber, module_data, BBanalysis_root_files): +def ResultGrader( + felis, + outputDir, + testName, + testIndexInSequence, + runNumber, + module_data, + BBanalysis_root_files, +): try: - module_name = module_data['module'].getModuleName() - module_type = module_data['module'].getModuleType() - module_version = module_data['module'].getModuleVersion() - if 'SLDOScan' in testName or 'CommunicationTest' in testName: - explanation = 'No grading currently available for SLDOScan or CommunicationTest.' - return {module_name:(True, explanation)} + module_name = module_data["module"].getModuleName() + module_type = module_data["module"].getModuleType() + module_version = module_data["module"].getModuleVersion() + if "SLDOScan" in testName or "CommunicationTest" in testName: + explanation = ( + "No grading currently available for SLDOScan or CommunicationTest." + ) + return {module_name: (True, explanation)} + + root_file_name = testName.split("_")[0] + if "SCurveScan" in root_file_name: + root_file_name = "SCurve" + elif "GainScan" in root_file_name: + root_file_name = "Gain" + elif "Threshold" in root_file_name: + root_file_name = root_file_name.replace("Threshold", "Thr") + if "IVCurve" in testName: + root_file_name = testName.split("_")[0] + "_" + module_name + + # NOTE: This may be useful + # module_canvas_path = ( + # "Detector/Board_{boardID}/OpticalGroup_{ogID}/Hybrid_{hybridID}".format( + # boardID=module_data["boardID"], + # ogID=module_data["ogID"], + # hybridID=module_data["hybridID"], + # ) + # ) - root_file_name = testName.split('_')[0] - if 'SCurveScan' in root_file_name: - root_file_name = 'SCurve' - elif 'GainScan' in root_file_name: - root_file_name = 'Gain' - elif 'Threshold' in root_file_name: - root_file_name = root_file_name.replace('Threshold', 'Thr') - if 'IVCurve' in testName: - root_file_name = testName.split('_')[0]+"_"+module_name - module_canvas_path = "Detector/Board_{boardID}/OpticalGroup_{ogID}/Hybrid_{hybridID}".format( - boardID=module_data['boardID'], - ogID=module_data['ogID'], - hybridID=module_data['hybridID']) ROOT_file_path = "{0}/Result_{1}.root".format(outputDir, root_file_name) - if root_file_name in ("PixelAlive_highcharge_xtalk","PixelAlive_coupled_xtalk","PixelAlive_uncoupled_xtalk"): + if root_file_name in ( + "PixelAlive_highcharge_xtalk", + "PixelAlive_coupled_xtalk", + "PixelAlive_uncoupled_xtalk", + ): BBanalysis_root_files.append(ROOT_file_path) - relevant_files = [outputDir+"/"+os.fsdecode(file) for file in os.listdir(outputDir)] + relevant_files = [ + outputDir + "/" + os.fsdecode(file) for file in os.listdir(outputDir) + ] _1, _2 = felis.set_module( - module_name, module_type.split(" ")[0], module_type.split(" ")[2].replace("Quad","2x2"), module_version.strip('v'), True, "link" + module_name, + module_type.split(" ")[0], + module_type.split(" ")[2].replace("Quad", "2x2"), + module_version.strip("v"), + True, + "link", ) - module_canvases = [module_canvas_path] status, message, sanity, explanation = felis.set_result( relevant_files, module_name, f"{testIndexInSequence:02d}_{testName}", - 'ivcurve', + "ivcurve", ) else: ROOT_file_path = "{0}/Run{1}_{2}.root".format( outputDir, runNumber, root_file_name ) - if root_file_name in ("PixelAlive_highcharge_xtalk","PixelAlive_coupled_xtalk","PixelAlive_uncoupled_xtalk"): + if root_file_name in ( + "PixelAlive_highcharge_xtalk", + "PixelAlive_coupled_xtalk", + "PixelAlive_uncoupled_xtalk", + ): BBanalysis_root_files.append(ROOT_file_path) - chip_canvas_path_template = "Detector/Board_{boardID}/OpticalGroup_{ogID}/Hybrid_{hybridID}/Chip_{chipID:02d}" - active_chips = [chip.getID() for chip in module_data['module'].getChips().values() if chip.getStatus()] - chip_canvases = [ - chip_canvas_path_template.format( - boardID=module_data['boardID'], - ogID=module_data['ogID'], - hybridID=module_data['hybridID'], - chipID=int(chipID) - ) - for chipID in active_chips + + # Note: This may be useful + # chip_canvas_path_template = "Detector/Board_{boardID}/OpticalGroup_{ogID}/Hybrid_{hybridID}/Chip_{chipID:02d}" + + # active_chips = [ + # chip.getID() + # for chip in module_data["module"].getChips().values() + # if chip.getStatus() + # ] + + relevant_files = [ + outputDir + "/" + os.fsdecode(file) for file in os.listdir(outputDir) ] - relevant_files = [outputDir+"/"+os.fsdecode(file) for file in os.listdir(outputDir)] _1, _2 = felis.set_module( - module_name, module_type.split(" ")[0], module_type.split(" ")[2].replace("Quad","2x2"), module_version.strip('v'), True, "link" + module_name, + module_type.split(" ")[0], + module_type.split(" ")[2].replace("Quad", "2x2"), + module_version.strip("v"), + True, + "link", ) status, message, sanity, explanation = felis.set_result( @@ -75,8 +110,8 @@ def ResultGrader(felis, outputDir, testName, testIndexInSequence, runNumber, mod ) if not status: raise RuntimeError(message) - - return {module_name:(True, explanation)}, BBanalysis_root_files + + return {module_name: (True, explanation)}, BBanalysis_root_files except Exception as err: - #logger.error("An error was thrown while grading: {}".format(repr(err))) - return {module_name:(False, repr(err))}, BBanalysis_root_files \ No newline at end of file + # logger.error("An error was thrown while grading: {}".format(repr(err))) + return {module_name: (False, repr(err))}, BBanalysis_root_files diff --git a/Gui/python/logging_config.py b/Gui/python/logging_config.py index c230833a..8aef4db0 100644 --- a/Gui/python/logging_config.py +++ b/Gui/python/logging_config.py @@ -15,7 +15,7 @@ formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") console_handler.setFormatter(formatter) -file_handler = logging.FileHandler('../data/Ph2_ACF_GUI.log') +file_handler = logging.FileHandler("../data/Ph2_ACF_GUI.log") file_handler.setLevel(logging.INFO) diff --git a/Gui/runApplication.py b/Gui/runApplication.py deleted file mode 100644 index 4b84befc..00000000 --- a/Gui/runApplication.py +++ /dev/null @@ -1,47 +0,0 @@ - -import logging - -# Customize the logging configuration -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', - filename='my_project.log', # Specify a log file - filemode='w' # 'w' for write, 'a' for append -) - -logger = logging.getLogger(__name__) - -''' - runApplication.py - brief Interface for GUI Application - author Kai Wei - version 0.1 - date 10/02/20 - Support: email to wei.856@osu.edu -''' - -import tkinter as tk -import Gui.GUIutils.Application as App -import Gui.GUIutils.LoginFrame as login -import database -from PIL import ImageTk, Image -from tkinter import ttk - - - -app = App.Application() -app.SetGeometry() -app.SetTitle() - -#app.root.title('Ph2_ACF Grading System') -#app.root.geometry('{}x{}'.format(600, 300)) -#app.root.rowconfigure(0, weight=1, minsize=50) -#app.root.rowconfigure(1, weight=1, minsize=250) -#app.root.columnconfigure(0, weight=1, minsize=300) -#app.root.columnconfigure(1, weight=1, minsize=300) - -#title_label = tk.Label(master = app.root, text = "Phase 2 Pixel Grading System", relief=tk.GROOVE, font=('Helvetica', 25, 'bold')) -#title_label.grid(row=0, column=0, columnspan=2, sticky="new") - -login.LoginFrame(app) -app.root.mainloop() diff --git a/Gui/setupDatabase.py b/Gui/setupDatabase.py deleted file mode 100644 index 52a90fb4..00000000 --- a/Gui/setupDatabase.py +++ /dev/null @@ -1,140 +0,0 @@ - -import logging - -# Customize the logging configuration -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', - filename='my_project.log', # Specify a log file - filemode='w' # 'w' for write, 'a' for append -) - -logger = logging.getLogger(__name__) - -''' - setupDatabase.py - \brief Setup database for pixel grading gui - \author Brandon Manley - \version 0.1 - \date 06/08/20 - Support: email to manley.329@osu.edu -''' - -import config -import gui -import database - -if __name__ == "__main__": - # setup test entries table - database.createTestsTable() - - test_entries = [ - (1942, 'bmanley', 'pixelalive', '12/06/2019 10:25:27', 19), - (1942, 'bmanley', 'latency scan', '03/06/2020 18:01:14', 92), - (1942, 'bmanley', 'pixelalive', '01/06/2020 08:25:27', 48), - (1942, 'bmanley', 'pixelalive', '01/06/2020 08:25:25', 87), - (1942, 'bmanley', 'gain', '09/06/2020 08:25:27', 52), - (1942, 'bmanley', 'threshold optimization', '12/06/2009 10:25:27', 33), - (12, 'johndoe', 'threshold optimization', '11/06/2020 08:25:27', 100), - (12, 'johndoe', 'threshold optimization', '11/06/2020 06:13:34', 42), - (12, 'johndoe', 'threshold optimization', '10/06/2020 08:25:27', 55), - (12, 'johndoe', 'threshold optimization', '11/06/2020 08:25:27', 9), - (12, 'johndoe', 'threshold optimization', '11/06/2020 08:25:27', 17), - (978, 'tester', 'full', '01/06/2020 08:25:27', 83), - (978, 'tester', 'full', '01/06/2020 04:25:27', 85), - (20, 'dev', 'pixelalive', '11/06/2020 08:25:27', -1), - (20, 'dev', 'pixelalive', '11/06/2020 07:25:27', 100), - (20, 'dev', 'pixelalive', '11/06/2020 10:22:27', 93), - (20, 'dev', 'full', '11/06/2020 10:25:30', 62), - (1942, 'bmanley', 'pixelalive', '12/06/2019 10:25:27', 19), - (1942, 'bmanley', 'latency scan', '03/06/2020 18:01:14', 92), - (1942, 'bmanley', 'pixelalive', '01/06/2020 08:25:27', 48), - (1942, 'bmanley', 'pixelalive', '01/06/2020 08:25:25', 87), - (1942, 'bmanley', 'gain', '09/06/2020 08:25:27', 52), - (1942, 'bmanley', 'threshold optimization', '12/06/2009 10:25:27', 33), - (12, 'johndoe', 'threshold optimization', '11/06/2020 08:25:27', 100), - (12, 'johndoe', 'threshold optimization', '11/06/2020 06:13:34', 42), - (12, 'johndoe', 'threshold optimization', '10/06/2020 08:25:27', 55), - (12, 'johndoe', 'threshold optimization', '11/06/2020 08:25:27', 9), - (12, 'johndoe', 'threshold optimization', '11/06/2020 08:25:27', 17), - (978, 'tester', 'full', '01/06/2020 08:25:27', 83), - (978, 'tester', 'full', '01/06/2020 04:25:27', 85), - (20, 'dev', 'pixelalive', '11/06/2020 08:25:27', -1), - (20, 'dev', 'pixelalive', '11/06/2020 07:25:27', 100), - (20, 'dev', 'pixelalive', '11/06/2020 10:22:27', 93), - (20, 'dev', 'full', '11/06/2020 10:25:30', 62), - (1942, 'bmanley', 'pixelalive', '12/06/2019 10:25:27', 19), - (1942, 'bmanley', 'latency scan', '03/06/2020 18:01:14', 92), - (1942, 'bmanley', 'pixelalive', '01/06/2020 08:25:27', 48), - (1942, 'bmanley', 'pixelalive', '01/06/2020 08:25:25', 87), - (1942, 'bmanley', 'gain', '09/06/2020 08:25:27', 52), - (1942, 'bmanley', 'threshold optimization', '12/06/2009 10:25:27', 33), - (12, 'johndoe', 'threshold optimization', '11/06/2020 08:25:27', 100), - (12, 'johndoe', 'threshold optimization', '11/06/2020 06:13:34', 42), - (12, 'johndoe', 'threshold optimization', '10/06/2020 08:25:27', 55), - (12, 'johndoe', 'threshold optimization', '11/06/2020 08:25:27', 9), - (12, 'johndoe', 'threshold optimization', '11/06/2020 08:25:27', 17), - (978, 'tester', 'full', '01/06/2020 08:25:27', 83), - (978, 'tester', 'full', '01/06/2020 04:25:27', 85), - (20, 'dev', 'pixelalive', '11/06/2020 08:25:27', -1), - (20, 'dev', 'pixelalive', '11/06/2020 07:25:27', 100), - (20, 'dev', 'pixelalive', '11/06/2020 10:22:27', 93), - (20, 'dev', 'full', '11/06/2020 10:25:30', 62), - (1942, 'bmanley', 'pixelalive', '12/06/2019 10:25:27', 19), - (1942, 'bmanley', 'latency scan', '03/06/2020 18:01:14', 92), - (1942, 'bmanley', 'pixelalive', '01/06/2020 08:25:27', 48), - (1942, 'bmanley', 'pixelalive', '01/06/2020 08:25:25', 87), - (1942, 'bmanley', 'gain', '09/06/2020 08:25:27', 52), - (1942, 'bmanley', 'threshold optimization', '12/06/2009 10:25:27', 33), - (12, 'johndoe', 'threshold optimization', '11/06/2020 08:25:27', 100), - (12, 'johndoe', 'threshold optimization', '11/06/2020 06:13:34', 42), - (12, 'johndoe', 'threshold optimization', '10/06/2020 08:25:27', 55), - (12, 'johndoe', 'threshold optimization', '11/06/2020 08:25:27', 9), - (12, 'johndoe', 'threshold optimization', '11/06/2020 08:25:27', 17), - (978, 'tester', 'full', '01/06/2020 08:25:27', 83), - (978, 'tester', 'full', '01/06/2020 04:25:27', 85), - (20, 'dev', 'pixelalive', '11/06/2020 08:25:27', -1), - (20, 'dev', 'pixelalive', '11/06/2020 07:25:27', 100), - (20, 'dev', 'pixelalive', '11/06/2020 10:22:27', 93), - (20, 'dev', 'full', '11/06/2020 10:25:30', 62), - (1942, 'bmanley', 'pixelalive', '12/06/2019 10:25:27', 19), - (1942, 'bmanley', 'latency scan', '03/06/2020 18:01:14', 92), - (1942, 'bmanley', 'pixelalive', '01/06/2020 08:25:27', 48), - (1942, 'bmanley', 'pixelalive', '01/06/2020 08:25:25', 87), - (1942, 'bmanley', 'gain', '09/06/2020 08:25:27', 52), - (1942, 'bmanley', 'threshold optimization', '12/06/2009 10:25:27', 33), - (12, 'johndoe', 'threshold optimization', '11/06/2020 08:25:27', 100), - (12, 'johndoe', 'threshold optimization', '11/06/2020 06:13:34', 42), - (12, 'johndoe', 'threshold optimization', '10/06/2020 08:25:27', 55), - (12, 'johndoe', 'threshold optimization', '11/06/2020 08:25:27', 9), - (12, 'johndoe', 'threshold optimization', '11/06/2020 08:25:27', 17), - (978, 'tester', 'full', '01/06/2020 08:25:27', 83), - (978, 'tester', 'full', '01/06/2020 04:25:27', 85), - (20, 'dev', 'pixelalive', '11/06/2020 08:25:27', -1), - (20, 'dev', 'pixelalive', '11/06/2020 07:25:27', 100), - (20, 'dev', 'pixelalive', '11/06/2020 10:22:27', 93), - (20, 'dev', 'full', '11/06/2020 10:25:30', 62) - ] - - database.deleteAllTests() - - for test_entry in test_entries: - database.createTestEntry(test_entry) - - print(database.retrieveAllTestTasks()) - - # setup mode entries table - testnames = [ - 'pretest', 'full', 'latency scan', 'pixelalive', 'noise scan', 'scurve scan', - 'gain scan', 'threshold equalization', 'gain optimization', - 'threshold minimization', 'threshold adjustment', 'injection delay scan', - 'clock delay scan', 'physics' - ] - - database.createModesTable() - database.deleteAllModes() - - for runName in testnames: - database.createModeEntry((runName,)) - - print(database.retrieveAllModes()) \ No newline at end of file diff --git a/Gui/siteSettings_template.py b/Gui/siteSettings_template.py index 62bd29ad..c2193c46 100644 --- a/Gui/siteSettings_template.py +++ b/Gui/siteSettings_template.py @@ -1,12 +1,11 @@ - import logging # Customize the logging configuration logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', - filename='my_project.log', # Specify a log file - filemode='w' # 'w' for write, 'a' for append + level=logging.INFO, + format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", + filename="my_project.log", # Specify a log file + filemode="w", # 'w' for write, 'a' for append ) logger = logging.getLogger(__name__) @@ -25,17 +24,17 @@ # default FC7 boardName defaultFC7 = "fc7.board.1" # default IP address of IP address -defaultFC7IP = '192.168.1.80' +defaultFC7IP = "192.168.1.80" # default FMC board number -defaultFMC = '0' +defaultFMC = "0" # default mode for LV powering (Direct,SLDO,etc) defaultPowerMode = "SLDO" -#default DBServerIP -#defaultDBServerIP = '127.0.0.1' -defaultDBServerIP = 'cmsfpixdb.physics.purdue.edu' -#default DBName -#defaultDBName = 'SampleDB' -defaultDBName = 'cmsfpix_phase2' +# default DBServerIP +# defaultDBServerIP = '127.0.0.1' +defaultDBServerIP = "cmsfpixdb.physics.purdue.edu" +# default DBName +# defaultDBName = 'SampleDB' +defaultDBName = "cmsfpix_phase2" ################################## @@ -49,26 +48,28 @@ defaultUSBPortLV = ["ASRL/dev/ttyUSBLV::INSTR"] # default model for LV power supply defaultLVModel = ["KeySight E3633 (RS232)"] -#default BaudRate for Arduino sensor +# default BaudRate for Arduino sensor defaultSensorBaudRate = 9600 ################################# # Icicle variables -icicle_instrument_setup = { "lv":"KeysightE3633A", - "lv_resource" : "ASRL/dev/ttyUSBLV::INSTR", - "default_lv_channel" : 1, - "default_lv_voltage" : 1.8, - "default_lv_current" : 3, - "hv": "Keithley2410", - "hv_resource": "ASRL/dev/ttyUSBHV::INSTR", - "default_hv_voltage": -80, #in volts - "default_hv_compliance_current": 5e-6, #in amperes - "default_hv_delay": 2, - "default_hv_step_size": 10, - "relay_board": "RelayBoard", - "relay_board_resource": "ASRL/dev/ttyUSB4::INSTR", - "multimeter": "Keithley2000", - "multimeter_resource": "ASRL/dev/ttyUSB3::INSTR"} +icicle_instrument_setup = { + "lv": "KeysightE3633A", + "lv_resource": "ASRL/dev/ttyUSBLV::INSTR", + "default_lv_channel": 1, + "default_lv_voltage": 1.8, + "default_lv_current": 3, + "hv": "Keithley2410", + "hv_resource": "ASRL/dev/ttyUSBHV::INSTR", + "default_hv_voltage": -80, # in volts + "default_hv_compliance_current": 5e-6, # in amperes + "default_hv_delay": 2, + "default_hv_step_size": 10, + "relay_board": "RelayBoard", + "relay_board_resource": "ASRL/dev/ttyUSB4::INSTR", + "multimeter": "Keithley2000", + "multimeter_resource": "ASRL/dev/ttyUSB3::INSTR", +} ## Specify whether of not you want to monitor chip temperature during the tests ## @@ -76,53 +77,49 @@ Monitor_RD53A = "1" Monitor_CROC = "1" -## Configuring the current settings for each module type. These values are in Amps. +## Configuring the current settings for each module type. These values are in Amps. ModuleCurrentMap = { - "TFPX SCC" : 0.6, - "TFPX Quad" : 6.5, - "TEPX Quad" : 6, - "TBPX Quad" : 6.5, - "Yellow Module (Purdue)": 6.5, - - "TFPX CROC 1x2" : 4.5, - - "TFPX CROC Quad" : 6.5, - "TFPX CROC SCC" : 2.0, + "TFPX SCC": 0.6, + "TFPX Quad": 6.5, + "TEPX Quad": 6, + "TBPX Quad": 6.5, + "Yellow Module (Purdue)": 6.5, + "TFPX CROC 1x2": 4.5, + "TFPX CROC Quad": 6.5, + "TFPX CROC SCC": 2.0, } ## Configuring the voltage limit for each module type when operating in SLDO mode. These values are in Volts. ModuleVoltageMapSLDO = { - "TFPX SCC" : 1.8, - "TFPX Quad" : 2.98, - "TEPX Quad" : 2.0, - "TBPX Quad" : 2.98, - "Yellow Module (Purdue)": 2.8, - - "TFPX CROC 1x2" : 2.2, - - "TFPX CROC Quad" : 2.98, - "TFPX CROC SCC" : 1.8, + "TFPX SCC": 1.8, + "TFPX Quad": 2.98, + "TEPX Quad": 2.0, + "TBPX Quad": 2.98, + "Yellow Module (Purdue)": 2.8, + "TFPX CROC 1x2": 2.2, + "TFPX CROC Quad": 2.98, + "TFPX CROC SCC": 1.8, } ## Configuring the voltage settings for each module type. These values are in Volts. ModuleVoltageMap = { - "TFPX SCC" : 1.3, - "TFPX CROC SCC" : 1.6, + "TFPX SCC": 1.3, + "TFPX CROC SCC": 1.6, } -#setting the sequence of threshold tuning targets: -defaultTargetThr = ['2000','1500','1200','1000','800'] +# setting the sequence of threshold tuning targets: +defaultTargetThr = ["2000", "1500", "1200", "1000", "800"] ##### The following settings are for SLDO scans developed for Purdue.##### ##### Do not modify these settings unless you know what you are doing.#### -#default settings for SLDO scan. +# default settings for SLDO scan. defaultSLDOscanVoltage = 0.0 defaultSLDOscanMaxCurrent = 0.0 ### Setting for Peltier Controller usePeltier = True -defaultPeltierPort = '/dev/ttyUSBPeltier' +defaultPeltierPort = "/dev/ttyUSBPeltier" defaultPeltierBaud = 9600 defaultPeltierSetTemp = 20 defaultPeltierWarningTemp = 40 @@ -131,4 +128,3 @@ # Possible themes can be found inside the Gui/Assets directory use_custom_theme = False theme = "ElegantDark.qss" - diff --git a/InnerTrackerTests b/InnerTrackerTests index 1d7e80d1..5842e69e 160000 --- a/InnerTrackerTests +++ b/InnerTrackerTests @@ -1 +1 @@ -Subproject commit 1d7e80d1f1d89cf7c692dccd6109c047a3054aa1 +Subproject commit 5842e69eedd42e23b2b85d80766739f32a6e3cfc diff --git a/Ph2_ACF b/Ph2_ACF index 5b4c72e6..b7a6eb45 160000 --- a/Ph2_ACF +++ b/Ph2_ACF @@ -1 +1 @@ -Subproject commit 5b4c72e61f30775afffe7db8095a2b8488ddfdf8 +Subproject commit b7a6eb45c96eb92c64068fd76816ea97d13e1d35 diff --git a/felis b/felis index 629ab836..e395f2a0 160000 --- a/felis +++ b/felis @@ -1 +1 @@ -Subproject commit 629ab836ac911a3d7cbe8f5982cfe43777a5046d +Subproject commit e395f2a06cae8be04e8a16b29dbce720ec160fa4