def __init__(self, path, runName, voltStart, voltEnd, numPoints, exposure_Seconds): self.path = path self.runName = runName self.voltStart = voltStart self.numPoints = numPoints self.voltArr = np.linspace(voltStart, voltEnd, numPoints) self.exposure_MilliSeconds = exposure_Seconds * 1000 self.MKSFullScale = 500.0 #full scale of N2, sccm self.scaleFact = 1.4 #scael factor for He self.flowRate = 50.0 self.binning = 1 #don't use binnig for absorption self.nozzleWaitTime_Seconds = 5 #time to wait for turning on or off the nozzle self.waitTimeToFlow_Seconds = self.nozzleWaitTime_Seconds - exposure_Seconds if self.waitTimeToFlow_Seconds < 0.0: self.waitTimeToFlow_Seconds = 0.0 self.waitTimeToStopFlow_Seconds = self.nozzleWaitTime_Seconds self.camera = Camera('FAR', self.exposure_MilliSeconds, bin=self.binning) self.galvoOut = DAQPin(gv.galvoOutPin) self.shutterOut = DAQPin(gv.shutterPin) #open the shutter contorl pin self.darkImageList = [] self.noFlowImageList = [] self.flowImageList = [] self.absorptionSignalImageList = []
def run(self): self.save_Settings() self.galvoOut = DAQPin(gv.galvoOutPin) self.shutterOut = DAQPin(gv.shutterPin) self.galvoOut.write(float(self.voltStartBox.get())) x1 = int(self.x1Box.get()) y1 = int(self.y1Box.get()) x2 = int(self.x2Box.get()) y2 = int(self.y2Box.get()) imageParams = [x1, x2, y1, y2] binSize = int(self.binSizeBox.get()) self.camera = Camera(self.cameraVar.get(), float(self.expTimeBox.get()), imageParams=imageParams, bin=binSize) self.voltArr = np.linspace(float(self.voltStartBox.get()), float(self.voltStopBox.get()), num=int(self.numImagesBox.get())) if os.path.isdir(self.folderPath.get()) == False: print('-----ERROR-----------') print('YOU HAVE ENTERED AN INVALID FOLDERPATH') if os.path.isfile(self.folderPath.get() + '\\' + self.fileName.get() + '.png') == True: print('--------------ERROR-------') print('THERE IS ALREADY A FILE WITH THAT NAME IN THAT FOLDER') gv.error_Sound() sys.exit() plt.close('all') if self.ratioVar.get() == True: self.sweep_Ratio() else: self.sweep_Single()
def cool_Camera(self): if self.cameraVar.get() == "NEAR": print("YOU CAN'T COOL THE NEAR FIELD CAMERA") gv.warning_Sound() else: tempCamera = Camera(self.cameraVar.get(), 1000) #the camera will cool down tempCamera.close() #now close it. It will stay cool though
def __init__(self, ckey, csecret, atoken, asecret, plant=False): self.auth = OAuthHandler(ckey, csecret) self.auth.set_access_token(atoken, asecret) self.api = tweepy.API(self.auth) self.twitterStream = Stream(self.auth, self.listener(self)) self.twitterStream.filter(track=['@literally_plant'], is_async=True) self.plant = plant self.camera = Camera()
def initialize_Camera(self): x1 = int(self.x1Box.get()) #image region values y1 = int(self.y1Box.get()) #image region values x2 = int(self.x2Box.get()) #image region values y2 = int(self.y2Box.get()) #image region values imageParams = [x1, x2, y1, y2] binSize = int(self.binSizeBox.get()) #binning value #initialize camera object. can be near or far field camera expTime = int(self.expTimeBox.get()) #exposure time, ms whichCam = self.cameraVar.get() #which camera to use, 'FAR' or 'NEAR' self.camera = Camera(whichCam, expTime, imageParams=imageParams, bin=binSize)
def _initialize_Cameras(self): binNearX = self.binSizeNear binNearY = self.binSizeNear binFarX = self.binSizeFarX binFarY = self.binSizeFarY if binFarX <= 0 and binFarY <= 0: raise Exception('Both bin values cannot be zero') elif binFarX == 0: binFarX = binFarY elif binFarY == 0: binFarY = binFarX if binNearX <= 0 and binNearY <= 0: raise Exception('Both bin values cannot be zero') elif binNearX == 0: binNearX = binNearY elif binNearY == 0: binNearY = binNearX if self.GUI.cameraVarData.get() == 'BOTH': self.cameraFar = Camera('FAR', self.expTimeFar, self.imageParamFar, binx=binFarX, biny=binFarY) self.cameraNear = Camera('NEAR', self.expTimeNear, self.imageParamNear, binx=binNearX, biny=binNearY) elif self.GUI.cameraVarData.get() == 'NEAR': self.cameraNear = Camera('NEAR', self.expTimeNear, self.imageParamNear, binx=binNearX, biny=binNearY) elif self.GUI.cameraVarData.get() == 'FAR': self.cameraFar = Camera('FAR', self.expTimeFar, self.imageParamFar, binx=binFarX, biny=binFarY) else: gv.error_Sound() raise Exception('NO VALID CAMERA NAME PROVIDED')
class GUI: def __init__(self): self.settingsList = [] self.x1Box = None self.x2Box = None self.y1Box = None self.y2 = None self.voltArr = None #array to to hold voltage value sto scan over self.camera = None #to hold the camera opject self.galvoOut = None self.shutterOut = None #shutter control self.window = tk.Tk() self.window.title("Simple Scan") self.window.geometry('800x600') lbl1 = tk.Label(self.window, text='Scan Range (V)') lbl1.grid(column=0, row=0) self.voltStartBox = tk.Entry(self.window) self.voltStartBox.config(width=5) self.voltStartBox.grid(column=1, row=0, sticky='W') self.settingsList.append(self.voltStartBox) lbl2 = tk.Label(self.window, text='to') lbl2.grid(column=2, row=0) self.voltStopBox = tk.Entry(self.window) self.voltStopBox.config(width=5) self.voltStopBox.grid(column=3, row=0, sticky='W') self.settingsList.append(self.voltStopBox) lbl3 = tk.Label(self.window, text='Num images') lbl3.grid(column=0, row=1) self.numImagesBox = tk.Entry(self.window) self.numImagesBox.config(width=5) self.numImagesBox.grid(column=1, row=1, sticky='W') self.settingsList.append(self.numImagesBox) lbl31 = tk.Label(self.window, text='Exp time (ms)') lbl31.grid(column=2, row=1) self.expTimeBox = tk.Entry(self.window) self.expTimeBox.config(width=5) self.expTimeBox.grid(column=3, row=1, sticky='W') self.settingsList.append(self.expTimeBox) lbl32 = tk.Label(self.window, text='bin size') lbl32.grid(column=4, row=1) self.binSizeBox = tk.Entry(self.window) self.binSizeBox.config(width=5) self.binSizeBox.grid(column=5, row=1, sticky='W') self.settingsList.append(self.binSizeBox) lbl4 = tk.Label(self.window, text='Camera') lbl4.grid(column=0, row=4) self.cameraVar = tk.StringVar(self.window) self.cameraVar.set("FAR") cameraChoice = ["NEAR", "FAR"] CAMERA_MENU = tk.OptionMenu(self.window, self.cameraVar, *cameraChoice) CAMERA_MENU.grid(column=1, row=4, columnspan=2) self.settingsList.append(self.cameraVar) lbl5 = tk.Label(self.window, text='image x1') lbl5.grid(column=0, row=5) self.x1Box = tk.Entry(self.window) self.x1Box.config(width=5) self.x1Box.grid(column=1, row=5, sticky='W') self.settingsList.append(self.x1Box) lbl5 = tk.Label(self.window, text='image x2') lbl5.grid(column=2, row=5) self.x2Box = tk.Entry(self.window) self.x2Box.config(width=5) self.x2Box.grid(column=3, row=5, sticky='W') self.settingsList.append(self.x2Box) lbl5 = tk.Label(self.window, text='image y1') lbl5.grid(column=0, row=6) self.y1Box = tk.Entry(self.window) self.y1Box.config(width=5) self.y1Box.grid(column=1, row=6, sticky='W') self.settingsList.append(self.y1Box) lbl5 = tk.Label(self.window, text='image y2') lbl5.grid(column=2, row=6) self.y2Box = tk.Entry(self.window) self.y2Box.config(width=5) self.y2Box.grid(column=3, row=6, sticky='W') self.settingsList.append(self.y2Box) self.saveDataVar = tk.BooleanVar() saveDataCheckButton = tk.Checkbutton(self.window, text='save data', variable=self.saveDataVar) saveDataCheckButton.grid(column=1, row=7) self.settingsList.append(self.saveDataVar) self.ratioVar = tk.BooleanVar() ratioVarButton = tk.Checkbutton(self.window, text='ratio', variable=self.ratioVar) ratioVarButton.grid(column=1, row=8) self.settingsList.append(self.ratioVar) self.showPlotVar = tk.BooleanVar() showDataAnalysiButton = tk.Checkbutton(self.window, text='Show plot', variable=self.showPlotVar) showDataAnalysiButton.grid(column=1, row=9) self.settingsList.append(self.showPlotVar) lbl3 = tk.Label(self.window, text='Run name') lbl3.grid(column=0, row=15) self.fileName = tk.Entry(self.window) self.fileName.config(width=20) self.fileName.grid(column=1, row=15, sticky='W', columnspan=20) self.settingsList.append(self.fileName) lbl3 = tk.Label(self.window, text='Folder path') lbl3.grid(column=0, row=16) self.folderPath = tk.Entry(self.window) self.folderPath.config(width=30) self.folderPath.grid(column=1, row=16, sticky='W', columnspan=30) self.settingsList.append(self.folderPath) runButton = tk.Button(self.window, text='RUN', font=("Arial", 20), background="green", command=self.run) runButton.config(height=2, width=10) runButton.grid(column=0, row=17, columnspan=4, rowspan=4) coolCameraButton = tk.Button(self.window, text='cool camera', background="royal blue", command=self.cool_Camera) #coolCameraButton.config(height=2, width=10) coolCameraButton.grid(column=0, row=21, columnspan=4, rowspan=4) self.load_Settings() self.window.protocol("WM_DELETE_WINDOW", self.close_GUI) self.window.mainloop() def cool_Camera(self): if self.cameraVar.get() == "NEAR": print("YOU CAN'T COOL THE NEAR FIELD CAMERA") gv.warning_Sound() else: tempCamera = Camera(self.cameraVar.get(), 1000) #the camera will cool down tempCamera.close() #now close it. It will stay cool though def open_Aperture(self): self.shutterOut.write_High() time.sleep(.05) def close_Aperture(self): self.shutterOut.write_Low() time.sleep(.05) def close_GUI(self): self.save_Settings() self.window.destroy() sys.exit() def run(self): self.save_Settings() self.galvoOut = DAQPin(gv.galvoOutPin) self.shutterOut = DAQPin(gv.shutterPin) self.galvoOut.write(float(self.voltStartBox.get())) x1 = int(self.x1Box.get()) y1 = int(self.y1Box.get()) x2 = int(self.x2Box.get()) y2 = int(self.y2Box.get()) imageParams = [x1, x2, y1, y2] binSize = int(self.binSizeBox.get()) self.camera = Camera(self.cameraVar.get(), float(self.expTimeBox.get()), imageParams=imageParams, bin=binSize) self.voltArr = np.linspace(float(self.voltStartBox.get()), float(self.voltStopBox.get()), num=int(self.numImagesBox.get())) if os.path.isdir(self.folderPath.get()) == False: print('-----ERROR-----------') print('YOU HAVE ENTERED AN INVALID FOLDERPATH') if os.path.isfile(self.folderPath.get() + '\\' + self.fileName.get() + '.png') == True: print('--------------ERROR-------') print('THERE IS ALREADY A FILE WITH THAT NAME IN THAT FOLDER') gv.error_Sound() sys.exit() plt.close('all') if self.ratioVar.get() == True: self.sweep_Ratio() else: self.sweep_Single() def take_Dark_Image_Average(self, num=3): image = self.camera.aquire_Image() for i in range(num - 1): image += self.camera.aquire_Image() image = image / num #average the three images return image def sweep_Ratio(self): gv.begin_Sound() self.galvoOut.write(self.voltArr[0]) image1MeanList = [] #shutter open list of image sums image2MeanList = [] #shutter closed list of image sums image1List = [] image2List = [] for volt in self.voltArr: self.galvoOut.write(volt) #take with shutter open self.open_Aperture() image1 = self.camera.aquire_Image() image1List.append(image1) image1MeanList.append(np.mean(image1)) #take with shutter closed self.close_Aperture() image2 = self.camera.aquire_Image() image2List.append(image2) image2MeanList.append(np.mean(image2)) self.galvoOut.close() self.shutterOut.close() self.camera.close() gv.finished_Sound() y1 = np.asarray(image1MeanList) #shutter open y2 = np.asarray(image2MeanList) #shutter closed numImages = 3 delta1 = np.max(y1) - np.mean((y1[:numImages] + y1[-numImages:]) / 2) delta2 = np.max(y2) - np.mean((y2[:numImages] + y2[-numImages:]) / 2) ratio = delta1 / delta2 plt.suptitle('Signal with shutter closed and open') plt.title('ratio of peaks of open to close = ' + str(np.round(ratio, 6))) plt.plot(self.voltArr, y1, label='open,delta= ' + str(np.round(delta1, 1))) plt.plot(self.voltArr, y2, label='close,delta= ' + str(np.round(delta2, 1))) plt.xlabel('Volts') plt.ylabel('Pixel counts') plt.legend() plt.grid() if self.saveDataVar.get() == True: plt.savefig(self.folderPath.get() + '\\' + self.fileName.get() + 'Graph.png') image1SaveList = [] image2SaveList = [] for i in range(len(image1List)): image1SaveList.append(np.rot90(np.transpose(image1List[i]))) image2SaveList.append(np.rot90(np.transpose(image2List[i]))) hdu1 = fits.PrimaryHDU( image1SaveList) #make a Header/Data Unit of images hdul1 = fits.HDUList([hdu1]) #list of HDUs to save hdu2 = fits.PrimaryHDU( image2SaveList) #make a Header/Data Unit of images hdul2 = fits.HDUList([hdu2]) #list of HDUs to save fitsFileName = self.fileName.get() try: hdul1.writeto(self.folderPath.get() + '\\' + fitsFileName + 'ShutterOpen.fits') #now save it hdul2.writeto(self.folderPath.get() + '\\' + fitsFileName + 'ShutterClosed.fits') #now save it except: #fits doesn't let you delete stuff accidently print('THAT FILE ALREADY EXISTS. DELETE IT TO OVERWRITE@') if self.showPlotVar.get() == True: plt.show() def sweep_Single(self): #self.close_Aperture() gv.begin_Sound() self.galvoOut.write(self.voltArr[0]) darkImage = self.take_Dark_Image_Average() imageMeanList = [] imageList = [] for volt in self.voltArr: self.galvoOut.write(volt) image = self.camera.aquire_Image() imageList.append(image) image = image - darkImage * 0 imageMeanList.append(np.mean(image)) imageSumArr = np.asarray(imageMeanList) self.galvoOut.close() self.shutterOut.close() self.camera.close() gv.finished_Sound() numImages = 3 delta = np.max(imageSumArr) - np.mean( (imageSumArr[:numImages] + imageSumArr[-numImages:]) / 2) plt.plot(self.voltArr, imageSumArr) plt.title('Peak minus first few values= ' + str(np.round(delta, 2))) plt.xlabel('Volts') plt.ylabel('Pixel counts') plt.grid() if self.saveDataVar.get() == True: print(self.folderPath.get() + '\\' + self.fileName.get() + 'Graph') plt.savefig(self.folderPath.get() + '\\' + self.fileName.get()) #save plot #now save fits file saveImageList = [] for item in imageList: saveImageList.append(np.rot90(np.transpose(item))) hdu = fits.PrimaryHDU( saveImageList) #make a Header/Data Unit of images hdul = fits.HDUList([hdu]) #list of HDUs to save fitsFileName = self.fileName.get() + '.fits' try: hdul.writeto(self.folderPath.get() + '\\' + fitsFileName) #now save it except: #fits doesn't let you delete stuff accidently print('THAT FILE ALREADY EXISTS. DELETE IT TO OVERWRITE@') if self.showPlotVar.get() == True: plt.show() def save_Settings(self): file = open("simpleScaneGUI_Settings.txt", "w") for item in self.settingsList: file.write(str(item.get()) + '\n') file.close() def load_Settings(self): try: file = open("simpleScaneGUI_Settings.txt", "r") except: print("NO SETTINGS FILE FOUND") return i = 0 for item in file: item = item.strip() if i >= len(self.settingsList): pass else: if isinstance(self.settingsList[i], tk.StringVar): self.settingsList[i].set(item) elif isinstance(self.settingsList[i], tk.Entry): self.settingsList[i].insert(0, item) elif isinstance(self.settingsList[i], tk.BooleanVar): if item == 'False' or item == 'True': self.settingsList[i].set(item) i += 1 file.close()
class Twitter: def __init__(self, ckey, csecret, atoken, asecret, plant=False): self.auth = OAuthHandler(ckey, csecret) self.auth.set_access_token(atoken, asecret) self.api = tweepy.API(self.auth) self.twitterStream = Stream(self.auth, self.listener(self)) self.twitterStream.filter(track=['@literally_plant'], is_async=True) self.plant = plant self.camera = Camera() def tweet(self, msg): self.api.update_status(msg) class listener(StreamListener): def __init__(self, tObj): self.tObj = tObj def on_data(self, data): data = json.loads(data) dataDict = { 'id': data['id'], 'text': data['text'], 'user': { 'name': data['user']['name'], 'screen_name': data['user']['screen_name'] } } print("Tweet Received By: @" + dataDict['user']['screen_name'] + " - " + dataDict['text']) if "moist" in dataDict['text'] and "?" in dataDict['text']: print("Sending Moisture Level...") self.tObj.api.update_status( "@" + dataDict['user']['screen_name'] + " Soil Moisture: " + str(self.tObj.plant.getPinInfo("P0")['data']) + "%\nAt " + self.tObj.getFormattedTime(), in_reply_to_status_id=dataDict['id']) elif "picture" in dataDict['text'] and "?" in dataDict['text']: print("Sending Picture...") filename = "./img/pic.jpg" self.tObj.camera.takePhoto(filename) self.tObj.api.update_with_media( filename, status="@" + dataDict['user']['screen_name'] + " Picture taken at " + self.tObj.getFormattedTime() + "\nDay: " + str( abs((datetime.datetime.today() - self.tObj.plant.startDate).days)), in_reply_to_status_id=dataDict['id']) def on_error(self, status): print(status) def refresh(self, ckey, csecret, atoken, asecret): print("Refreshing Credentials...") self.auth = OAuthHandler(ckey, csecret) self.auth.set_access_token(atoken, asecret) self.api = tweepy.API(self.auth) # self.twitterStream = Stream(self.auth, self.listener(self)) # self.twitterStream.filter(track=['@literally_plant'], is_async=True) def getFormattedTime(self): now = datetime.datetime.now() - datetime.timedelta(hours=7) fmt = '%I:%M:%S%p MDT %m/%d/%Y' return str(now.strftime(fmt)) def takeTimelapse(self, filename): print("Taking Timelapse Picture...") filename = "./timelapse/" + filename + ".jpg" self.camera.takePhoto(filename) self.api.update_with_media( filename, status="Timelapse picture taken at " + self.getFormattedTime() + "\nDay: " + str(abs((datetime.datetime.today() - self.plant.startDate).days)))
class Ui_MainWindow(object): db = Database() cam = Camera(0) camTimer = QtCore.QTimer() tempTimer = QtCore.QTimer() cam.setDaemon(True) holes = NetHoleDetection() clean = NetCleaning() def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(1002, 872) MainWindow.setWindowFlags(QtCore.Qt.CustomizeWindowHint) MainWindow.setWindowFlags(QtCore.Qt.FramelessWindowHint) MainWindow.setObjectName("MainWindow") MainWindow.resize(999, 872) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.stackedWidget = QtWidgets.QStackedWidget(self.centralwidget) self.stackedWidget.setGeometry(QtCore.QRect(0, 0, 1000, 873)) self.stackedWidget.setObjectName("stackedWidget") self.loginPage = QtWidgets.QWidget() self.loginPage.setStyleSheet( "border-image: url(:/Images/Resources/signInBG.png);") self.loginPage.setObjectName("loginPage") self.button_signIn_signIn = QtWidgets.QPushButton(self.loginPage) self.button_signIn_signIn.setGeometry(QtCore.QRect(320, 590, 320, 45)) self.button_signIn_signIn.setStyleSheet( "QPushButton{\n" " border-image: url(:/Images/Resources/signIn.png);\n" "background-repeat: none;\n" "}\n" "\n" "QPushButton:hover{\n" " border-image: url(:/Images/Resources/signInPressed.png);\n" "}\n" "\n" "QPushButton:pressed{\n" " border-image: url(:/Images/Resources/signInPressed.png);\n" "}") self.button_signIn_signIn.setText("") self.button_signIn_signIn.setObjectName("button_signIn_signIn") self.button_faceID_signIn = QtWidgets.QPushButton(self.loginPage) self.button_faceID_signIn.setGeometry(QtCore.QRect(320, 660, 320, 45)) self.button_faceID_signIn.setStyleSheet( "QPushButton{\n" " border-image: url(:/Images/Resources/faceID.png);\n" "background-repeat: none;\n" "}\n" "\n" "QPushButton:hover{\n" " border-image: url(:/Images/Resources/faceIDClicked.png);\n" "}\n" "\n" "QPushButton:pressed{\n" " border-image: url(:/Images/Resources/faceIDClicked.png);\n" "}") self.button_faceID_signIn.setText("") self.button_faceID_signIn.setObjectName("button_faceID_signIn") self.button_signUp_signIn = QtWidgets.QPushButton(self.loginPage) self.button_signUp_signIn.setGeometry(QtCore.QRect(320, 730, 320, 45)) self.button_signUp_signIn.setStyleSheet( "QPushButton{\n" " border-image: url(:/Images/Resources/signUp.png);\n" "background-repeat: none;\n" "}\n" "\n" "QPushButton:hover{\n" " border-image: url(:/Images/Resources/signUpPressed.png);\n" "}\n" "\n" "QPushButton:pressed{\n" " border-image: url(:/Images/Resources/signUpPressed.png);\n" "}") self.button_signUp_signIn.setText("") self.button_signUp_signIn.setObjectName("button_signUp_signIn") self.lineEdit_username_signIn = QtWidgets.QLineEdit(self.loginPage) self.lineEdit_username_signIn.setGeometry( QtCore.QRect(310, 345, 281, 31)) self.lineEdit_username_signIn.setStyleSheet( "border-image: url(:/Images/Resources/darkBlackBG.png);\n" "color: rgb(167, 167, 167);") self.lineEdit_username_signIn.setObjectName("lineEdit_username_signIn") self.lineEdit_password_signIn = QtWidgets.QLineEdit(self.loginPage) self.lineEdit_password_signIn.setGeometry( QtCore.QRect(310, 419, 281, 41)) self.lineEdit_password_signIn.setContextMenuPolicy( QtCore.Qt.DefaultContextMenu) self.lineEdit_password_signIn.setStyleSheet( "border-image: url(:/Images/Resources/darkBlackBG.png);\n" "color: rgb(167, 167, 167);\n" "") self.lineEdit_password_signIn.setEchoMode(QtWidgets.QLineEdit.Password) self.lineEdit_password_signIn.setObjectName("lineEdit_password_signIn") self.button_close = QtWidgets.QPushButton(self.loginPage) self.button_close.setGeometry(QtCore.QRect(940, 40, 21, 21)) self.button_close.setStyleSheet( "QPushButton{\n" " border-image: url(:/Images/Resources/exitBlue.png);\n" "background-repeat: none;\n" "}\n" "\n" "QPushButton:hover{\n" " border-image: url(:/Images/Resources/exitRed.png);\n" "}\n" "\n" "QPushButton:pressed{\n" " border-image: url(:/Images/Resources/exitRed.png);\n" "}") self.button_close.setText("") self.button_close.setObjectName("button_close") self.label_invalid = QtWidgets.QLabel(self.loginPage) self.label_invalid.setGeometry(QtCore.QRect(400, 300, 201, 16)) self.label_invalid.setStyleSheet( "border-image: url(:/Images/Resources/semiDarkBG.png);\n" "color: rgb(255, 61, 55);") self.label_invalid.setText("") self.label_invalid.setObjectName("label_invalid") self.stackedWidget.addWidget(self.loginPage) self.signupPage = QtWidgets.QWidget() self.signupPage.setStyleSheet( "border-image: url(:/Images/Resources/signUpBG.png);") self.signupPage.setObjectName("signupPage") self.lineEdit_firstName_signUp = QtWidgets.QLineEdit(self.signupPage) self.lineEdit_firstName_signUp.setGeometry( QtCore.QRect(310, 330, 151, 29)) self.lineEdit_firstName_signUp.setStyleSheet( "border-image: url(:/Images/Resources/darkBlackBG.png);\n" "color: rgb(167, 167, 167);") self.lineEdit_firstName_signUp.setObjectName( "lineEdit_firstName_signUp") self.lineEdit_lastName_signUp = QtWidgets.QLineEdit(self.signupPage) self.lineEdit_lastName_signUp.setGeometry( QtCore.QRect(530, 330, 151, 29)) self.lineEdit_lastName_signUp.setStyleSheet( "border-image: url(:/Images/Resources/darkBlackBG.png);\n" "color: rgb(167, 167, 167);") self.lineEdit_lastName_signUp.setObjectName("lineEdit_lastName_signUp") self.lineEdit_email_signUp = QtWidgets.QLineEdit(self.signupPage) self.lineEdit_email_signUp.setGeometry(QtCore.QRect(310, 408, 371, 21)) self.lineEdit_email_signUp.setStyleSheet( "border-image: url(:/Images/Resources/darkBlackBG.png);\n" "color: rgb(167, 167, 167);") self.lineEdit_email_signUp.setObjectName("lineEdit_email_signUp") self.lineEdit_username_signUp = QtWidgets.QLineEdit(self.signupPage) self.lineEdit_username_signUp.setGeometry( QtCore.QRect(310, 490, 371, 21)) self.lineEdit_username_signUp.setStyleSheet( "border-image: url(:/Images/Resources/darkBlackBG.png);\n" "color: rgb(167, 167, 167);") self.lineEdit_username_signUp.setObjectName("lineEdit_username_signUp") self.lineEdit_password_signUp = QtWidgets.QLineEdit(self.signupPage) self.lineEdit_password_signUp.setGeometry( QtCore.QRect(310, 570, 371, 21)) self.lineEdit_password_signUp.setStyleSheet( "border-image: url(:/Images/Resources/darkBlackBG.png);\n" "color: rgb(167, 167, 167);") self.lineEdit_password_signUp.setObjectName("lineEdit_password_signUp") self.button_signUp_signUp = QtWidgets.QPushButton(self.signupPage) self.button_signUp_signUp.setGeometry(QtCore.QRect(340, 640, 320, 45)) self.button_signUp_signUp.setStyleSheet( "QPushButton{\n" " border-image: url(:/Images/Resources/signUp.png);\n" "background-repeat: none;\n" "}\n" "\n" "QPushButton:hover{\n" " border-image: url(:/Images/Resources/signUpPressed.png);\n" "}\n" "\n" "QPushButton:pressed{\n" " border-image: url(:/Images/Resources/signUpPressed.png);\n" "}") self.button_signUp_signUp.setText("") self.button_signUp_signUp.setObjectName("button_signUp_signUp") self.button_backToSignIn = QtWidgets.QPushButton(self.signupPage) self.button_backToSignIn.setGeometry(QtCore.QRect(340, 720, 320, 45)) self.button_backToSignIn.setStyleSheet( "QPushButton{\n" " border-image: url(:/Images/Resources/backSignInPressed.png);\n" "background-repeat: none;\n" "}\n" "\n" "QPushButton:hover{\n" " border-image: url(:/Images/Resources/backSignIn.png);\n" "}\n" "\n" "QPushButton:pressed{\n" " border-image: url(:/Images/Resources/backSignIn.png);\n" "}") self.button_backToSignIn.setText("") self.button_backToSignIn.setObjectName("button_backToSignIn") self.button_close_2 = QtWidgets.QPushButton(self.signupPage) self.button_close_2.setGeometry(QtCore.QRect(940, 40, 21, 21)) self.button_close_2.setStyleSheet( "QPushButton{\n" " border-image: url(:/Images/Resources/exitBlue.png);\n" "background-repeat: none;\n" "}\n" "\n" "QPushButton:hover{\n" " border-image: url(:/Images/Resources/exitRed.png);\n" "}\n" "\n" "QPushButton:pressed{\n" " border-image: url(:/Images/Resources/exitRed.png);\n" "}") self.button_close_2.setText("") self.button_close_2.setObjectName("button_close_2") self.stackedWidget.addWidget(self.signupPage) self.faceidPage = QtWidgets.QWidget() self.faceidPage.setStyleSheet( "border-image: url(:/Images/Resources/faceIDWidget.png);") self.faceidPage.setObjectName("faceidPage") self.label_cam = QtWidgets.QLabel(self.faceidPage) self.label_cam.setGeometry(QtCore.QRect(90, 230, 821, 401)) self.label_cam.setStyleSheet( "border-image: url(:/Images/Resources/semiDarkBG.png);") self.label_cam.setText("") self.label_cam.setObjectName("label_cam") self.stackedWidget.addWidget(self.faceidPage) self.mainPage = QtWidgets.QWidget() self.mainPage.setStyleSheet( "border-image: url(:/Images/Resources/mainWidgetBG.png);") self.mainPage.setObjectName("mainPage") self.button_dashboard = QtWidgets.QPushButton(self.mainPage) self.button_dashboard.setGeometry(QtCore.QRect(0, 230, 291, 54)) self.button_dashboard.setStyleSheet( "QPushButton{\n" " border-image: url(:/Images/Resources/dasboard.png);\n" "background-repeat: none;\n" "}\n" "\n" "QPushButton:hover{\n" " border-image: url(:/Images/Resources/dashboardPressed.png);\n" "}\n" "\n" "QPushButton:pressed{\n" " border-image: url(:/Images/Resources/dashboardPressed.png);\n" "}") self.button_dashboard.setText("") self.button_dashboard.setObjectName("button_dashboard") self.button_createTank = QtWidgets.QPushButton(self.mainPage) self.button_createTank.setGeometry(QtCore.QRect(0, 290, 291, 54)) self.button_createTank.setStyleSheet( "QPushButton{\n" " border-image: url(:/Images/Resources/create.png);\n" "background-repeat: none;\n" "}\n" "\n" "QPushButton:hover{\n" " border-image: url(:/Images/Resources/createPressed.png);\n" "}\n" "\n" "QPushButton:pressed{\n" " border-image: url(:/Images/Resources/createPressed.png);\n" "}") self.button_createTank.setText("") self.button_createTank.setObjectName("button_createTank") self.button_analyzeTank = QtWidgets.QPushButton(self.mainPage) self.button_analyzeTank.setGeometry(QtCore.QRect(0, 350, 291, 54)) self.button_analyzeTank.setStyleSheet( "QPushButton{\n" " border-image: url(:/Images/Resources/analyze.png);\n" "background-repeat: none;\n" "}\n" "\n" "QPushButton:hover{\n" " border-image: url(:/Images/Resources/analyzePressed.png);\n" "}\n" "\n" "QPushButton:pressed{\n" " border-image: url(:/Images/Resources/analyzePressed.png);\n" "}") self.button_analyzeTank.setText("") self.button_analyzeTank.setObjectName("button_analyzeTank") self.button_settings = QtWidgets.QPushButton(self.mainPage) self.button_settings.setGeometry(QtCore.QRect(0, 410, 291, 54)) self.button_settings.setStyleSheet( "QPushButton{\n" " border-image: url(:/Images/Resources/settings.png);\n" "background-repeat: none;\n" "}\n" "\n" "QPushButton:hover{\n" " border-image: url(:/Images/Resources/settingsPressed.png);\n" "}\n" "\n" "QPushButton:pressed{\n" " border-image: url(:/Images/Resources/settingsPressed.png);\n" "}") self.button_settings.setText("") self.button_settings.setObjectName("button_settings") self.button_logout = QtWidgets.QPushButton(self.mainPage) self.button_logout.setGeometry(QtCore.QRect(78, 790, 130, 42)) self.button_logout.setStyleSheet( "QPushButton{\n" " border-image: url(:/Images/Resources/logoutPressed.png);\n" "background-repeat: none;\n" "}\n" "\n" "QPushButton:hover{\n" " border-image: url(:/Images/Resources/logout.png);\n" "}\n" "\n" "QPushButton:pressed{\n" " border-image: url(:/Images/Resources/logout.png);\n" "}") self.button_logout.setText("") self.button_logout.setObjectName("button_logout") self.stackedWidget_2 = QtWidgets.QStackedWidget(self.mainPage) self.stackedWidget_2.setGeometry(QtCore.QRect(290, 0, 711, 861)) self.stackedWidget_2.setStyleSheet( "border-image: url(:/Images/Resources/CreateBG.png);") self.stackedWidget_2.setObjectName("stackedWidget_2") self.dashboardPage = QtWidgets.QWidget() self.dashboardPage.setStyleSheet( "border-image: url(:/Images/Resources/dashboardWidget.png);") self.dashboardPage.setObjectName("dashboardPage") self.label_fishType_tankData = QtWidgets.QLabel(self.dashboardPage) self.label_fishType_tankData.setGeometry(QtCore.QRect( 190, 176, 81, 16)) self.label_fishType_tankData.setStyleSheet( "border-image: url(:/Images/Resources/whiteBG.png);\n" "font: 11pt \"Helvetica LT Std\";") self.label_fishType_tankData.setObjectName("label_fishType_tankData") self.label_harvestDate_tankData = QtWidgets.QLabel(self.dashboardPage) self.label_harvestDate_tankData.setGeometry( QtCore.QRect(220, 225, 111, 16)) self.label_harvestDate_tankData.setStyleSheet( "border-image: url(:/Images/Resources/whiteBG.png);\n" "font: 11pt \"Helvetica LT Std\";") self.label_harvestDate_tankData.setObjectName( "label_harvestDate_tankData") self.label_feeding_tankData = QtWidgets.QLabel(self.dashboardPage) self.label_feeding_tankData.setGeometry(QtCore.QRect( 250, 273, 101, 16)) self.label_feeding_tankData.setStyleSheet( "border-image: url(:/Images/Resources/whiteBG.png);\n" "font: 11pt \"Helvetica LT Std\";") self.label_feeding_tankData.setObjectName("label_feeding_tankData") self.label_ph_tankData = QtWidgets.QLabel(self.dashboardPage) self.label_ph_tankData.setGeometry(QtCore.QRect(140, 324, 71, 16)) self.label_ph_tankData.setStyleSheet( "border-image: url(:/Images/Resources/whiteBG.png);\n" "font: 11pt \"Helvetica LT Std\";") self.label_ph_tankData.setObjectName("label_ph_tankData") self.label_temperature_tankData = QtWidgets.QLabel(self.dashboardPage) self.label_temperature_tankData.setGeometry( QtCore.QRect(210, 370, 500, 20)) self.label_temperature_tankData.setStyleSheet( "border-image: url(:/Images/Resources/whiteBG.png);\n" "color: rgb(255, 61, 55);\n" "font: 11pt \"Helvetica LT Std\";") self.label_temperature_tankData.setObjectName( "label_temperature_tankData") self.label_fishNetHoles_tankData = QtWidgets.QLabel(self.dashboardPage) self.label_fishNetHoles_tankData.setGeometry( QtCore.QRect(220, 418, 71, 16)) self.label_fishNetHoles_tankData.setStyleSheet( "border-image: url(:/Images/Resources/whiteBG.png);\n" "font: 11pt \"Helvetica LT Std\";") self.label_fishNetHoles_tankData.setObjectName( "label_fishNetHoles_tankData") self.label_fishnetNeedsCleaning_tankData = QtWidgets.QLabel( self.dashboardPage) self.label_fishnetNeedsCleaning_tankData.setGeometry( QtCore.QRect(290, 465, 55, 16)) self.label_fishnetNeedsCleaning_tankData.setStyleSheet( "border-image: url(:/Images/Resources/whiteBG.png);\n" "font: 11pt \"Helvetica LT Std\";") self.label_fishnetNeedsCleaning_tankData.setObjectName( "label_fishnetNeedsCleaning_tankData") self.label_pipesNeedChanging_tankData = QtWidgets.QLabel( self.dashboardPage) self.label_pipesNeedChanging_tankData.setGeometry( QtCore.QRect(280, 513, 55, 16)) self.label_pipesNeedChanging_tankData.setStyleSheet( "border-image: url(:/Images/Resources/whiteBG.png);\n" "font: 11pt \"Helvetica LT Std\";") self.label_pipesNeedChanging_tankData.setObjectName( "label_pipesNeedChanging_tankData") self.comboBox = QtWidgets.QComboBox(self.dashboardPage) self.comboBox.setGeometry(QtCore.QRect(300, 70, 128, 33)) self.comboBox.setStyleSheet( "QComboBox {\n" "border-image: url(:/Resources/comboBoxBG.png);\n" " border-image: url(:/Images/Resources/comboBoxBG.png);\n" " color: black;\n" " font: 14px;\n" " padding: 1px 0px 1px 3px; /* This (useless) line resolves a bug with the font color */\n" "}\n" "\n" "QComboBox:focus {\n" " color: red;\n" "}\n" "\n" "QComboBox::drop-down \n" "{\n" " border: 0px; /* This seems to replace the whole arrow of the combo box */\n" "}") self.comboBox.setObjectName("comboBox") self.comboBox.addItem("") self.button_email = QtWidgets.QPushButton(self.dashboardPage) self.button_email.setGeometry(QtCore.QRect(220, 810, 127, 33)) self.button_email.setStyleSheet( "QPushButton{\n" " border-image: url(:/Images/Resources/EmailButton.png);\n" "background-repeat: none;\n" "}\n" "\n" "QPushButton:hover{\n" " border-image: url(:/Images/Resources/EmailButtonPressed.png);\n" "}\n" "\n" "QPushButton:pressed{\n" " border-image: url(:/Images/Resources/EmailButtonPressed.png);\n" "}") self.button_email.setText("") self.button_email.setObjectName("button_email") self.button_report = QtWidgets.QPushButton(self.dashboardPage) self.button_report.setGeometry(QtCore.QRect(370, 810, 127, 33)) self.button_report.setStyleSheet( "QPushButton{\n" " border-image: url(:/Images/Resources/report.png);\n" "background-repeat: none;\n" "}\n" "\n" "QPushButton:hover{\n" " border-image: url(:/Images/Resources/reportPressed.png);\n" "}\n" "\n" "QPushButton:pressed{\n" " border-image: url(:/Images/Resources/reportPressed.png);\n" "}") self.button_report.setText("") self.button_report.setObjectName("button_report") self.button_close_3 = QtWidgets.QPushButton(self.dashboardPage) self.button_close_3.setGeometry(QtCore.QRect(670, 40, 21, 21)) self.button_close_3.setStyleSheet( "QPushButton{\n" " border-image: url(:/Images/Resources/exitBlue.png);\n" "background-repeat: none;\n" "}\n" "\n" "QPushButton:hover{\n" " border-image: url(:/Images/Resources/exitGrey.png);\n" "}\n" "\n" "QPushButton:pressed{\n" " border-image: url(:/Images/Resources/exitGrey.png);\n" "}") self.button_close_3.setText("") self.button_close_3.setObjectName("button_close_3") self.stackedWidget_2.addWidget(self.dashboardPage) self.createtankPage = QtWidgets.QWidget() self.createtankPage.setObjectName("createtankPage") self.lineEdit_fishType_createTank = QtWidgets.QLineEdit( self.createtankPage) self.lineEdit_fishType_createTank.setGeometry( QtCore.QRect(480, 490, 71, 31)) self.lineEdit_fishType_createTank.setStyleSheet( "border-image: url(:/Images/Resources/darkBlackBG.png);\n" "color: rgb(167, 167, 167);") self.lineEdit_fishType_createTank.setObjectName( "lineEdit_fishType_createTank") self.lineEdit_date_createTank = QtWidgets.QLineEdit( self.createtankPage) self.lineEdit_date_createTank.setGeometry( QtCore.QRect(480, 540, 101, 22)) self.lineEdit_date_createTank.setStyleSheet( "border-image: url(:/Images/Resources/darkBlackBG.png);\n" "color: rgb(167, 167, 167);") self.lineEdit_date_createTank.setObjectName("lineEdit_date_createTank") self.lineEdit_feeding_createTank = QtWidgets.QLineEdit( self.createtankPage) self.lineEdit_feeding_createTank.setGeometry( QtCore.QRect(480, 590, 61, 22)) self.lineEdit_feeding_createTank.setStyleSheet( "border-image: url(:/Images/Resources/darkBlackBG.png);\n" "color: rgb(167, 167, 167);") self.lineEdit_feeding_createTank.setObjectName( "lineEdit_feeding_createTank") self.lineEdit_lowerTemperatureThreshold_createTank = QtWidgets.QLineEdit( self.createtankPage) self.lineEdit_lowerTemperatureThreshold_createTank.setGeometry( QtCore.QRect(480, 640, 81, 22)) self.lineEdit_lowerTemperatureThreshold_createTank.setStyleSheet( "border-image: url(:/Images/Resources/darkBlackBG.png);\n" "color: rgb(167, 167, 167);") self.lineEdit_lowerTemperatureThreshold_createTank.setObjectName( "lineEdit_lowerTemperatureThreshold_createTank") self.lineEdit_upperTemperatureThreshold_createTank = QtWidgets.QLineEdit( self.createtankPage) self.lineEdit_upperTemperatureThreshold_createTank.setGeometry( QtCore.QRect(480, 690, 81, 22)) self.lineEdit_upperTemperatureThreshold_createTank.setStyleSheet( "border-image: url(:/Images/Resources/darkBlackBG.png);\n" "color: rgb(167, 167, 167);") self.lineEdit_upperTemperatureThreshold_createTank.setObjectName( "lineEdit_upperTemperatureThreshold_createTank") self.lineEdit_waterQualityThreshold_createTank = QtWidgets.QLineEdit( self.createtankPage) self.lineEdit_waterQualityThreshold_createTank.setGeometry( QtCore.QRect(480, 740, 81, 22)) self.lineEdit_waterQualityThreshold_createTank.setStyleSheet( "border-image: url(:/Images/Resources/darkBlackBG.png);\n" "color: rgb(167, 167, 167);") self.lineEdit_waterQualityThreshold_createTank.setObjectName( "lineEdit_waterQualityThreshold_createTank") self.button_create_createTank = QtWidgets.QPushButton( self.createtankPage) self.button_create_createTank.setGeometry( QtCore.QRect(290, 810, 127, 33)) self.button_create_createTank.setStyleSheet( "border-image: url(:/Images/Resources/createButton.png);") self.button_create_createTank.setText("") self.button_create_createTank.setObjectName("button_create_createTank") self.button_close_4 = QtWidgets.QPushButton(self.createtankPage) self.button_close_4.setGeometry(QtCore.QRect(670, 40, 21, 21)) self.button_close_4.setStyleSheet( "QPushButton{\n" " border-image: url(:/Images/Resources/exitWhiteBlue.png);\n" "background-repeat: none;\n" "}\n" "\n" "QPushButton:hover{\n" " border-image: url(:/Images/Resources/exitRed.png);\n" "}\n" "\n" "QPushButton:pressed{\n" " border-image: url(:/Images/Resources/exitRed.png);\n" "}") self.button_close_4.setText("") self.button_close_4.setObjectName("button_close_4") self.stackedWidget_2.addWidget(self.createtankPage) self.analyzetankPage = QtWidgets.QWidget() self.analyzetankPage.setStyleSheet( "border-image: url(:/Images/Resources/AnalyzeBG.png);") self.analyzetankPage.setObjectName("analyzetankPage") self.button_holes_analyzeTank = QtWidgets.QPushButton( self.analyzetankPage) self.button_holes_analyzeTank.setGeometry( QtCore.QRect(150, 530, 127, 33)) self.button_holes_analyzeTank.setStyleSheet( "QPushButton{\n" " border-image: url(:/Images/Resources/Holes.png);\n" "background-repeat: none;\n" "}\n" "\n" "QPushButton:hover{\n" " border-image: url(:/Images/Resources/HolesPressed.png);\n" "}\n" "\n" "QPushButton:pressed{\n" " border-image: url(:/Images/Resources/HolesPressed.png);\n" "}") self.button_holes_analyzeTank.setText("") self.button_holes_analyzeTank.setObjectName("button_holes_analyzeTank") self.button_cleaning_analyzeTank = QtWidgets.QPushButton( self.analyzetankPage) self.button_cleaning_analyzeTank.setGeometry( QtCore.QRect(300, 530, 127, 33)) self.button_cleaning_analyzeTank.setStyleSheet( "QPushButton{\n" " border-image: url(:/Images/Resources/Cleaning.png);\n" "background-repeat: none;\n" "}\n" "\n" "QPushButton:hover{\n" " border-image: url(:/Images/Resources/CleaningPressed.png);\n" "}\n" "\n" "QPushButton:pressed{\n" " border-image: url(:/Images/Resources/CleaningPressed.png);\n" "}") self.button_cleaning_analyzeTank.setText("") self.button_cleaning_analyzeTank.setObjectName( "button_cleaning_analyzeTank") self.button_pipes_analyzeTank = QtWidgets.QPushButton( self.analyzetankPage) self.button_pipes_analyzeTank.setGeometry( QtCore.QRect(450, 530, 127, 33)) self.button_pipes_analyzeTank.setStyleSheet( "QPushButton{\n" " border-image: url(:/Images/Resources/Pipes.png);\n" "background-repeat: none;\n" "}\n" "\n" "QPushButton:hover{\n" " border-image: url(:/Images/Resources/PipesPressed.png);\n" "}\n" "\n" "QPushButton:pressed{\n" " border-image: url(:/Images/Resources/PipesPressed.png);\n" "}") self.button_pipes_analyzeTank.setText("") self.button_pipes_analyzeTank.setObjectName("button_pipes_analyzeTank") self.button_predict_analyzeTank = QtWidgets.QPushButton( self.analyzetankPage) self.button_predict_analyzeTank.setGeometry( QtCore.QRect(440, 740, 222, 34)) self.button_predict_analyzeTank.setStyleSheet( "QPushButton{\n" " border-image: url(:/Images/Resources/predict.png);\n" "background-repeat: none;\n" "}\n" "\n" "QPushButton:hover{\n" " border-image: url(:/Images/Resources/predictPressed.png);\n" "}\n" "\n" "QPushButton:pressed{\n" " border-image: url(:/Images/Resources/predictPressed.png);\n" "}") self.button_predict_analyzeTank.setText("") self.button_predict_analyzeTank.setObjectName( "button_predict_analyzeTank") self.label_fishnetNeedsPatching_analyzeTank = QtWidgets.QLabel( self.analyzetankPage) self.label_fishnetNeedsPatching_analyzeTank.setGeometry( QtCore.QRect(300, 613, 55, 16)) self.label_fishnetNeedsPatching_analyzeTank.setStyleSheet( "border-image: url(:/Images/Resources/whiteBG.png);\n" "font: 11pt \"Helvetica LT Std\";") self.label_fishnetNeedsPatching_analyzeTank.setObjectName( "label_fishnetNeedsPatching_analyzeTank") self.label_fishnetNeedsCleaning_analyzeTank = QtWidgets.QLabel( self.analyzetankPage) self.label_fishnetNeedsCleaning_analyzeTank.setGeometry( QtCore.QRect(300, 655, 55, 16)) self.label_fishnetNeedsCleaning_analyzeTank.setStyleSheet( "border-image: url(:/Images/Resources/whiteBG.png);\n" "font: 11pt \"Helvetica LT Std\";") self.label_fishnetNeedsCleaning_analyzeTank.setObjectName( "label_fishnetNeedsCleaning_analyzeTank") self.label_pipesNeedChanging_analyzeTank = QtWidgets.QLabel( self.analyzetankPage) self.label_pipesNeedChanging_analyzeTank.setGeometry( QtCore.QRect(300, 705, 55, 16)) self.label_pipesNeedChanging_analyzeTank.setStyleSheet( "border-image: url(:/Images/Resources/whiteBG.png);\n" "font: 11pt \"Helvetica LT Std\";") self.label_pipesNeedChanging_analyzeTank.setObjectName( "label_pipesNeedChanging_analyzeTank") self.lineEdit_temperature_analyzeTank = QtWidgets.QLineEdit( self.analyzetankPage) self.lineEdit_temperature_analyzeTank.setGeometry( QtCore.QRect(570, 610, 113, 22)) self.lineEdit_temperature_analyzeTank.setStyleSheet( "border-image: url(:/Images/Resources/whiteBG.png);\n" "font: 11pt \"Helvetica LT Std\";") self.lineEdit_temperature_analyzeTank.setObjectName( "lineEdit_temperature_analyzeTank") self.lineEdit_waterSalinity_analyzeTank = QtWidgets.QLineEdit( self.analyzetankPage) self.lineEdit_waterSalinity_analyzeTank.setGeometry( QtCore.QRect(570, 700, 113, 22)) self.lineEdit_waterSalinity_analyzeTank.setStyleSheet( "border-image: url(:/Images/Resources/whiteBG.png);\n" "font: 11pt \"Helvetica LT Std\";") self.lineEdit_waterSalinity_analyzeTank.setObjectName( "lineEdit_waterSalinity_analyzeTank") self.label_camFeed = QtWidgets.QLabel(self.analyzetankPage) self.label_camFeed.setGeometry(QtCore.QRect(80, 200, 551, 281)) self.label_camFeed.setStyleSheet( "border-image: url(:/Images/Resources/semiDarkBG.png);") self.label_camFeed.setText("") self.label_camFeed.setObjectName("label_camFeed") self.button_close_5 = QtWidgets.QPushButton(self.analyzetankPage) self.button_close_5.setGeometry(QtCore.QRect(670, 40, 21, 21)) self.button_close_5.setStyleSheet( "QPushButton{\n" " border-image: url(:/Images/Resources/exitBlue.png);\n" "background-repeat: none;\n" "}\n" "\n" "QPushButton:hover{\n" " border-image: url(:/Images/Resources/exitGrey.png);\n" "}\n" "\n" "QPushButton:pressed{\n" " border-image: url(:/Images/Resources/exitGrey.png);\n" "}") self.button_close_5.setText("") self.button_close_5.setObjectName("button_close_5") self.stackedWidget_2.addWidget(self.analyzetankPage) self.settingsPage = QtWidgets.QWidget() self.settingsPage.setStyleSheet( "border-image: url(:/Images/Resources/settingsWidget.png);") self.settingsPage.setObjectName("settingsPage") self.stackedWidget_2.addWidget(self.settingsPage) self.label_username_mainPage = QtWidgets.QLabel(self.mainPage) self.label_username_mainPage.setGeometry( QtCore.QRect(120, 137, 141, 41)) self.label_username_mainPage.setStyleSheet( "border-image: url(:/Images/Resources/blueBG.png);\n" "font: 11pt \"Helvetica LT Std\";\n" "color: rgb(229, 229, 229);") self.label_username_mainPage.setObjectName("label_username_mainPage") self.label_userLetter = QtWidgets.QLabel(self.mainPage) self.label_userLetter.setGeometry(QtCore.QRect(50, 137, 31, 31)) self.label_userLetter.setStyleSheet( "border-image: url(:/Images/Resources/greyBG.png);\n" "font: 75 26pt \"Helvetica LT Std\";") self.label_userLetter.setObjectName("label_userLetter") self.stackedWidget.addWidget(self.mainPage) MainWindow.setCentralWidget(self.centralwidget) self.buttonsConnections() self.retranslateUi(MainWindow) self.stackedWidget.setCurrentIndex(0) self.button_close.clicked.connect(MainWindow.close) self.button_close_5.clicked.connect(MainWindow.close) self.button_close_2.clicked.connect(MainWindow.close) self.button_close_3.clicked.connect(MainWindow.close) self.button_close_4.clicked.connect(MainWindow.close) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.lineEdit_username_signIn.setText(_translate("MainWindow", "")) self.lineEdit_password_signIn.setText(_translate("MainWindow", "")) self.lineEdit_firstName_signUp.setText( _translate("MainWindow", "First name")) self.lineEdit_lastName_signUp.setText( _translate("MainWindow", "Last name")) self.lineEdit_email_signUp.setText( _translate("MainWindow", "Email address")) self.lineEdit_username_signUp.setText( _translate("MainWindow", "Username")) self.lineEdit_password_signUp.setText( _translate("MainWindow", "Password")) self.label_fishType_tankData.setText(_translate( "MainWindow", "Salmon")) self.label_harvestDate_tankData.setText( _translate("MainWindow", "29/7/2019")) self.label_feeding_tankData.setText(_translate("MainWindow", "6:00:00")) self.label_ph_tankData.setText(_translate("MainWindow", "5")) self.label_temperature_tankData.setText(_translate("MainWindow", "22")) self.label_fishNetHoles_tankData.setText(_translate("MainWindow", "1")) self.label_fishnetNeedsCleaning_tankData.setText( _translate("MainWindow", "No")) self.label_pipesNeedChanging_tankData.setText( _translate("MainWindow", "No")) self.comboBox.setItemText(0, _translate("MainWindow", "Tank 1")) self.lineEdit_fishType_createTank.setText( _translate("MainWindow", "Salmon")) self.lineEdit_date_createTank.setText( _translate("MainWindow", "DD/MM/YY")) self.lineEdit_feeding_createTank.setText(_translate( "MainWindow", "DD")) self.lineEdit_lowerTemperatureThreshold_createTank.setText( _translate("MainWindow", "18")) self.lineEdit_upperTemperatureThreshold_createTank.setText( _translate("MainWindow", "24")) self.lineEdit_waterQualityThreshold_createTank.setText( _translate("MainWindow", "0.9")) self.label_fishnetNeedsPatching_analyzeTank.setText( _translate("MainWindow", "No")) self.label_fishnetNeedsCleaning_analyzeTank.setText( _translate("MainWindow", "No")) self.label_pipesNeedChanging_analyzeTank.setText( _translate("MainWindow", "No")) self.lineEdit_temperature_analyzeTank.setText( _translate("MainWindow", "24")) self.lineEdit_waterSalinity_analyzeTank.setText( _translate("MainWindow", "21")) self.label_username_mainPage.setText( _translate("MainWindow", "Abdullah Salah")) self.label_userLetter.setText(_translate("MainWindow", "A")) def signInIsClicked(self): username_signIn = self.lineEdit_username_signIn.text() password_signIn = self.lineEdit_password_signIn.text() self.label_temperature_tankData.setText("18.43") self.user = self.db.authenticateLogIn(username_signIn, password_signIn) self.tankList = self.db.loadTankList(self.user.getUserID()) self.numberOfTanks = len(self.tankList) self.label_userLetter.setText("R") for i in range(self.numberOfTanks - 2): name = "Tank" + str(i + 2) self.comboBox.addItem(name) self.tankIndex = self.comboBox.currentIndex() self.waterQualityList = self.db.loadWaterQualityList( self.tankList[self.tankIndex].getTankID()) self.sen = Sensors("http://192.168.43.223/") if (self.user): self.displayList(self.tankIndex) self.stackedWidget.setCurrentIndex(3) self.cam.start() self.camTimer.timeout.connect(lambda: self.camFeedFunc()) self.camTimer.start(100) else: print("INVALID USERNAME OR PASSWORD") def camFeedFunc(self): self.fr = self.cam.getFrame() self.im = cv2.imread( "/Users/rowanhisham/Desktop/833a7b77-7744-4662-b1b9-5a22c948285b.jpg", 1) frame = cv2.cvtColor(self.im, cv2.COLOR_BGR2RGB) img = QtGui.QImage(frame, frame.shape[1], frame.shape[0], QtGui.QImage.Format_RGB888) pix = QtGui.QPixmap.fromImage(img) self.label_camFeed.setScaledContents(True) self.label_camFeed.setPixmap(pix) def captureImage(self): return self.im # return self.fr.copy() def displayList(self, tankIndex): if (self.user): self.label_username_mainPage.setText(self.user.getFirstName() + " " + self.user.getLastName()) # self.label_user_admin.setText("") self.label_fishType_tankData.setText( self.tankList[tankIndex].getFishType()) self.label_harvestDate_tankData.setText( self.tankList[tankIndex].getHarvestDate()) self.label_feeding_tankData.setText( self.tankList[tankIndex].getFeedingSchedule()) self.label_ph_tankData.setText( str(self.waterQualityList[0].getpH())) self.temperatureReading() def temperatureReading(self): print("temp timerrrrr") self.temp = self.sen.getTemperature() if (float(self.temp) >= 18): self.label_temperature_tankData.setText( "WARNING! Temperature is " + self.temp + " C") self.em = emailNotifier(self.user, self.temp) self.em.sendEmail() else: self.label_temperature_tankData.setText(self.sen.getTemperature()) def updateTankData(self): self.tankIndex = self.comboBox.currentIndex() self.displayList(self.tankIndex) def signUpfromLoginPageIsClicked(self): self.stackedWidget.setCurrentIndex(1) def signUpfromsignUpPageIsClicked(self): self.stackedWidget.setCurrentIndex(0) username_signUp = self.lineEdit_username_signUp.text() password_signUp = self.lineEdit_password_signUp.text() firstName_signUp = self.lineEdit_firstName_signUp.text() lastName_signUp = self.lineEdit_lastName_signUp.text() email_signUp = self.lineEdit_email_signUp.text() def faceIdIsClicked(self): self.stackedWidget.setCurrentIndex(2) def goToLoginPage(self): self.stackedWidget.setCurrentIndex(0) def dashboardIsClicked(self): self.stackedWidget_2.setCurrentIndex(0) def createTankIsClicked(self): self.stackedWidget_2.setCurrentIndex(1) def createTankButtonClicked(self): fishType_createTank = self.lineEdit_fishType_createTank.text() date_createTank = self.lineEdit_date_createTank.text() feeding_createTank = self.lineEdit_feeding_createTank.text() lowerTemperatureThreshold_createTank = self.lineEdit_lowerTemperatureThreshold_createTank.text( ) upperTemperatureThreshold_createTank = self.lineEdit_upperTemperatureThreshold_createTank.text( ) waterQualityThreshold_createTank = self.lineEdit_waterQualityThreshold_createTank.text( ) def reportIsClicked(self): webbrowser.open( "https://app.powerbi.com/view?r=eyJrIjoiZjhkMzViNTUtMDU3Yy00NTBhLTg1OWUtZjU1OGU1NzcyZjFiIiwidCI6ImVhZjYyNGM4LWEwYzQtNDE5NS04N2QyLTQ0M2U1ZDc1MTZjZCIsImMiOjh9&fbclid=IwAR29_qNsg6Nwu1QKUFX6OjKhhUDT77pEpZHJDb0ZE1-OwoRCjhy1En90DAc" ) def emailIsClicked(self): pass def analyzeTankIsClicked(self): self.stackedWidget_2.setCurrentIndex(2) def settingsIsClicked(self): self.stackedWidget_2.setCurrentIndex(3) def cleaningIsClicked(self): pred = self.clean.predict(self.captureImage()) if (pred == "yes"): self.label_fishnetNeedsCleaning_analyzeTank.setText("Yes") elif (pred == "no"): self.label_fishnetNeedsCleaning_analyzeTank.setText("No") else: self.label_fishnetNeedsCleaning_analyzeTank.setText( "Can't determine") def holesIsClicked(self): pred = self.holes.predict(self.captureImage()) if (pred == "yes"): self.label_fishnetNeedsPatching_analyzeTank.setText("Yes") elif (pred == "no"): self.label_fishnetNeedsPatching_analyzeTank.setText("No") else: self.label_fishnetNeedsPatching_analyzeTank.setText( "Can't determine") def pipesIsClicked(self): pass def predictIsClicked(self): pass def buttonsConnections(self): self.button_signIn_signIn.clicked.connect(self.signInIsClicked) self.button_signUp_signIn.clicked.connect( self.signUpfromLoginPageIsClicked) self.button_faceID_signIn.clicked.connect(self.faceIdIsClicked) self.button_backToSignIn.clicked.connect(self.goToLoginPage) self.button_signUp_signUp.clicked.connect( self.signUpfromsignUpPageIsClicked) self.button_logout.clicked.connect(self.goToLoginPage) self.button_dashboard.clicked.connect(self.dashboardIsClicked) self.button_createTank.clicked.connect(self.createTankIsClicked) self.button_analyzeTank.clicked.connect(self.analyzeTankIsClicked) self.button_settings.clicked.connect(self.settingsIsClicked) self.button_cleaning_analyzeTank.clicked.connect( self.cleaningIsClicked) self.button_holes_analyzeTank.clicked.connect(self.holesIsClicked) self.button_pipes_analyzeTank.clicked.connect(self.pipesIsClicked) self.button_predict_analyzeTank.clicked.connect(self.predictIsClicked) self.button_create_createTank.clicked.connect( self.createTankButtonClicked) self.button_report.clicked.connect(self.reportIsClicked) self.button_email.clicked.connect(self.emailIsClicked) self.comboBox.currentIndexChanged.connect(self.updateTankData)
class AbsorptionImager: def __init__(self, path, runName, voltStart, voltEnd, numPoints, exposure_Seconds): self.path = path self.runName = runName self.voltStart = voltStart self.numPoints = numPoints self.voltArr = np.linspace(voltStart, voltEnd, numPoints) self.exposure_MilliSeconds = exposure_Seconds * 1000 self.MKSFullScale = 500.0 #full scale of N2, sccm self.scaleFact = 1.4 #scael factor for He self.flowRate = 50.0 self.binning = 1 #don't use binnig for absorption self.nozzleWaitTime_Seconds = 5 #time to wait for turning on or off the nozzle self.waitTimeToFlow_Seconds = self.nozzleWaitTime_Seconds - exposure_Seconds if self.waitTimeToFlow_Seconds < 0.0: self.waitTimeToFlow_Seconds = 0.0 self.waitTimeToStopFlow_Seconds = self.nozzleWaitTime_Seconds self.camera = Camera('FAR', self.exposure_MilliSeconds, bin=self.binning) self.galvoOut = DAQPin(gv.galvoOutPin) self.shutterOut = DAQPin(gv.shutterPin) #open the shutter contorl pin self.darkImageList = [] self.noFlowImageList = [] self.flowImageList = [] self.absorptionSignalImageList = [] def catch_Errors(self): if self.flowRate <= 0: gv.error_Sound() raise Exception('The flowrate is zero or invalid!') if self.exposure_MilliSeconds < 500: gv.error_Sound() raise Exception( 'The camera exposure is too low. Remember you enter it as seconds' ) def make_Info_File(self): with open('info.txt', 'w') as file: file.write('Run Info \n') file.write('Exposure time: ' + str(self.exposure_MilliSeconds) + ' ms \n') file.write('flow wait time: ' + str(self.nozzleWaitTime_Seconds) + 's \n') file.write('binning :' + str(self.binning) + '\n') file.write('Nozzle flow rate: ' + str(self.flowRate) + ' SCCM \n') file.write('Image galvo voltages: ' + str(self.voltArr) + ' volts \n') def save_Images(self, name, imageList): hdu = fits.PrimaryHDU(np.asarray(imageList)) hdul = fits.HDUList([hdu]) hdul.writeto(name + '.fits') def make_Flow(self, flowDesired): flowOut = DAQPin(gv.flowOutPin) if flowDesired > 500.0: raise Exception('REQUESTED FLOW IS GREATER THAN MAXIMUM') elif flowDesired > 0.0: volt = (flowDesired / (self.MKSFullScale * self.scaleFact)) * 5.0 flowOut.write(volt) else: flowOut.write(0.0) flowOut.close(zero=False) def take_Dark_Image(self): self.shutterOut.close_Shutter() image = self.camera.aquire_Image().astype(float) self.shutterOut.open_Shutter() return image def take_No_Flow_Image(self): image = self.camera.aquire_Image().astype(float) return image def take_Flow_Image(self): image = self.camera.aquire_Image().astype(float) return image def make_Copies_To_Not_Modify_Originals(self, darkImage, noFlowImage, flowImage): #copy the images to prevent modifying them by accident! noFlowImage = noFlowImage.copy() flowImage = flowImage.copy() darkImage = darkImage.copy() return darkImage, noFlowImage, flowImage def construct_Absorption_Signal_Image(self, darkImage, noFlowImage, flowImage): eps = 1.0 #to avoid divide by zero darkImage, noFlowImage, flowImage = self.make_Copies_To_Not_Modify_Originals( darkImage, noFlowImage, flowImage) noFlowImage = noFlowImage - darkImage flowImage = flowImage - darkImage flowImage[ np.abs(flowImage) < eps] = eps #get rid of small numbers to prevent divide by zero noFlowImage[np.abs(noFlowImage) < eps] = eps signalImage = flowImage / noFlowImage return signalImage def save_Image_Lists(self): self.save_Images(self.runName + '_darkImages', self.darkImageList) self.save_Images(self.runName + '_noFlowImages', self.noFlowImageList) self.save_Images(self.runName + '_flowImages', self.flowImageList) self.save_Images(self.runName + '_absorptionSignalImages', self.absorptionSignalImageList) def change_Directory_And_Catch_File_Errors(self): imagesFolder = self.runName + 'Folder' try: os.mkdir(self.path + '\\' + imagesFolder) except FileExistsError: gv.error_Sound() print('That file already exists!!') exit() except: raise Exception('some other file issue') os.chdir(self.path + '\\' + imagesFolder) def update_Image_Lists(self, darkImage, noFlowImage, flowImage, absorptionSignalImage): self.darkImageList.append(darkImage) self.noFlowImageList.append(noFlowImage) self.flowImageList.append(flowImage) self.absorptionSignalImageList.append(absorptionSignalImage) def close_Pins(self): self.galvoOut.close() self.shutterOut.close() def wait_To_Flow_After_Dark_Image(self, ): time.sleep(self.waitTimeToFlow_Seconds) def wait_To_Stop_Flow_After_Flow_Image(self): time.sleep(self.waitTimeToStopFlow_Seconds) def run(self): self.change_Directory_And_Catch_File_Errors() self.catch_Errors() gv.begin_Sound() self.make_Flow(0.0) self.shutterOut.open_Shutter() for volt in self.voltArr: print(volt) self.galvoOut.write(volt) noFlowImage = self.take_No_Flow_Image() self.make_Flow(self.flowRate) darkImage = self.take_Dark_Image() self.wait_To_Flow_After_Dark_Image() flowImage = self.take_Flow_Image() self.make_Flow(0.0) self.wait_To_Stop_Flow_After_Flow_Image() absorptionSignalImage = self.construct_Absorption_Signal_Image( darkImage, noFlowImage, flowImage) self.update_Image_Lists(darkImage, noFlowImage, flowImage, absorptionSignalImage) self.close_Pins() self.save_Image_Lists() self.make_Info_File() gv.finished_Sound()
class Sweeper: def __init__(self, GUI): self.GUI = GUI self.cameraNear = None self.cameraFar = None self.DAQDataArr = None #array to hold data read from DAQ board. each row is a sample of data like # [outputVoltage, Lithium reference chamber voltage] self.imageArrList = [ ] #list to hold array of images. looks like [[imageN1,imageF1],[imageN2,imageF2],..] #where each image is a numpy array. So first image in each pair is for near, second for far self.galvoOut = DAQPin(gv.galvoOutPin) self.lithiumRefIn = DAQPin(gv.lithiumRefInPin) self.minVolt = gv.minScanVal self.maxVolt = gv.maxScanVal self.DAQVoltArr = np.linspace(self.minVolt, self.maxVolt, num=int((self.maxVolt - self.minVolt) * gv.samplesPerVoltDAQ)) x1N = int(GUI.x1NearBox.get()) x2N = int(GUI.x2NearBox.get()) y1N = int(GUI.y1NearBox.get()) y2N = int(GUI.y2NearBox.get()) self.imageParamNear = [x1N, x2N, y1N, y2N] x1F = int(GUI.x1FarBox.get()) x2F = int(GUI.x2FarBox.get()) y1F = int(GUI.y1FarBox.get()) y2F = int(GUI.y2FarBox.get()) self.imageParamFar = [x1F, x2F, y1F, y2F] self.numExp = int(GUI.expNumBox.get()) self.imageStartVolt = float(GUI.startVoltBox.get()) self.imageStopVolt = float(GUI.stopVoltBox.get()) self.expTimeNear = int(GUI.expTimeNearBox.get()) self.expTimeFar = int(GUI.expTimeFarBox.get()) self.binSizeNear = int(self.GUI.binSizeNearBox.get()) self.binSizeFarX = int(self.GUI.binSizeFarBoxX.get()) self.binSizeFarY = int(self.GUI.binSizeFarBoxY.get()) if self.imageStartVolt < self.minVolt or self.imageStartVolt > self.maxVolt or self.imageStopVolt < self.minVolt or self.imageStopVolt > self.maxVolt: raise Exception( 'VOLTAGE RANGE FOR IMAGE SWEEP EXCEEDS MAXIMUM AND/OR MINIMUM ALLOWED RANGE!' ) if self.imageStopVolt < self.imageStartVolt: raise Exception( 'ENDING VOLTAGE IS BEFORE STARTING VOLTAGE FOR IMAGE SWEEP!') self.imageVoltArr = np.linspace(self.imageStartVolt, self.imageStopVolt, num=self.numExp) def sweep(self): #this sweeps the galvo output voltage. There are two arrays, DAQVoltArr and imageVoltArr. DAQVoltArr contains all #the voltage values to collect DAQ data at. imageVoltArr contains the values to take iamges at. imageVolt array's #range must be less than or equal to DAQVoltArr's range. The loop searchs for which step is next, jumps to that point #and then increments the counter. self._initialize_Cameras() if self.cameraNear is not None: for _ in range(10): self.cameraNear.aquire_Image() i = 0 #counter for DAQVoltArr j = 0 #coutner for imageVoltArr loop = True volt = 0 tempList = [] gv.begin_Sound() lastImage = False #this is so that the last image is taken. It will flip from False to True once, and then no more #images takeImage = False #wether to take images totalSteps = self.DAQVoltArr.shape[0] + self.imageVoltArr.shape[0] print('\n \n \n \n') print('-----SWEEPING NOW----') time.sleep( .001 ) #if you don't wait a little then the progress bar and other messages will get messed up #in the terminal because they will try to write on top of each other progressBar = tqdm(total=totalSteps) while loop == True: progressBar.update() if i == self.DAQVoltArr.shape[ 0] - 1 and j == self.imageVoltArr.shape[0] - 1: loop = False volt = self.DAQVoltArr[i] if lastImage == False: #if the last image occurs at the last DAQ voltage as well takeImage = True lastImage = False else: if self.DAQVoltArr[i] == self.imageVoltArr[ j]: #if potential next voltages are equal volt = self.DAQVoltArr[i] if i != self.DAQVoltArr.shape[ 0] - 1: #don't increment if its at the end! i += 1 if j != self.imageVoltArr.shape[ 0] - 1: #don't increment if its at the end! j += 1 takeImage = True elif self.DAQVoltArr[i] < self.imageVoltArr[j]: if i != self.DAQVoltArr.shape[ 0] - 1: #don't increment if its at the end! volt = self.DAQVoltArr[i] i += 1 else: volt = self.imageVoltArr[i] j += 1 takeImage = True elif self.imageVoltArr[j] < self.DAQVoltArr[i]: if j != self.imageVoltArr.shape[ 0] - 1: #don't increment if its at the end! volt = self.imageVoltArr[j] j += 1 takeImage = True elif lastImage == False: #special case for taking the last image lastImage = True #Now it won't do this again. The loop will come here from now on, but it won't #do anything but increment the galvo voltage because j!=self.imageVoltArr.shape[0]-1 will be\ #false and lastImage==False will be false also volt = self.imageVoltArr[j] takeImage = True else: volt = self.DAQVoltArr[i] i += 1 self.galvoOut.write(volt) tempList.append([volt, self.lithiumRefIn.read(numSamples=1000)]) if takeImage == True: #for i in range(10): # self._take_Exposures() #print((time.time()-t)/10) self.imageArrList.append( self._take_Exposures() ) #the appended object is a list like [imageNear,imageFar]. If #there is no camera active for a given image the entry is None takeImage = False progressBar.close() time.sleep( .01 ) #like I said above. Pause to allow the progress bar to finish writting so it doesn't get messed up print('-----END OF SWEEP-----') self._close_DAQ_Pins() self._close_Cameras() self.DAQDataArr = np.asarray(tempList) gv.finished_Sound() #np.savetxt('data1.txt',self.DAQDataArr) #y=self.DAQDataArr[:,1] #plt.plot(y) #plt.show() self.GUI.imageArrList = self.imageArrList #this way if there is a previous list it is overwritten self.GUI.DAQDataArr = self.DAQDataArr def _close_DAQ_Pins(self): self.galvoOut.close() self.lithiumRefIn.close() def _initialize_Cameras(self): binNearX = self.binSizeNear binNearY = self.binSizeNear binFarX = self.binSizeFarX binFarY = self.binSizeFarY if binFarX <= 0 and binFarY <= 0: raise Exception('Both bin values cannot be zero') elif binFarX == 0: binFarX = binFarY elif binFarY == 0: binFarY = binFarX if binNearX <= 0 and binNearY <= 0: raise Exception('Both bin values cannot be zero') elif binNearX == 0: binNearX = binNearY elif binNearY == 0: binNearY = binNearX if self.GUI.cameraVarData.get() == 'BOTH': self.cameraFar = Camera('FAR', self.expTimeFar, self.imageParamFar, binx=binFarX, biny=binFarY) self.cameraNear = Camera('NEAR', self.expTimeNear, self.imageParamNear, binx=binNearX, biny=binNearY) elif self.GUI.cameraVarData.get() == 'NEAR': self.cameraNear = Camera('NEAR', self.expTimeNear, self.imageParamNear, binx=binNearX, biny=binNearY) elif self.GUI.cameraVarData.get() == 'FAR': self.cameraFar = Camera('FAR', self.expTimeFar, self.imageParamFar, binx=binFarX, biny=binFarY) else: gv.error_Sound() raise Exception('NO VALID CAMERA NAME PROVIDED') def _take_Exposure_Wrapper(self, resultsDict, camera): #wrapper for taking images concurrently. if camera.camName == 'NEAR': resultsDict['NEAR'] = self.cameraNear.aquire_Image() elif camera.camName == 'FAR': resultsDict['FAR'] = self.cameraFar.aquire_Image() else: gv.error_Sound() raise Exception('NO VALID CAMERA NAME PROVIDED') def _take_Exposures(self): if self.GUI.cameraVarData.get() == 'BOTH': resultsDict = { } #this is used to add the images taken concurrently. I use a dictionary so I can keep track of #which image belongs to which camera T1 = threading.Thread(target=self._take_Exposure_Wrapper, args=(resultsDict, self.cameraNear)) T2 = threading.Thread(target=self._take_Exposure_Wrapper, args=(resultsDict, self.cameraFar)) T1.start() T2.start() T1.join() T2.join() imgNear = resultsDict['NEAR'] imgFar = resultsDict['FAR'] return [imgNear, imgFar] elif self.GUI.cameraVarData.get() == 'NEAR': imgNear = self.cameraNear.aquire_Image() return [imgNear, None] elif self.GUI.cameraVarData.get() == 'FAR': imgFar = self.cameraFar.aquire_Image() return [None, imgFar] else: gv.error_Sound() raise Exception('NO VALID CAMERA NAME PROVIDED') def _close_Cameras(self): if self.GUI.cameraVarData.get() == 'BOTH': self.cameraNear.close() self.cameraFar.close() elif self.GUI.cameraVarData.get() == 'NEAR': self.cameraNear.close() elif self.GUI.cameraVarData.get() == 'FAR': self.cameraFar.close() else: raise Exception('NO VALID CAMERA NAME PROVIDED')
from CameraClass import Camera import cv2 while (1): cam = Camera(camAddress=0) cam.start() while (1): # cam.setDaemon(True) fr = cam.getFrame() cv2.imshow("fr", fr) cv2.waitKey(10) cam.closeCam()
class GUI: def __init__(self): self.settingsList = [ ] #list of tkinter field objects to save to a settings file self.x1Box = None #tkinter box object for image parameters self.x2Box = None #tkinter box object for image parameters self.y1Box = None #tkinter box object for image parameters self.y2Box = None #tkinter box object for image parameters self.voltOnResArr = None #array to to hold voltage values to scan over near resonance self.voltPlotArr = None #array to be used in plotting self.camera = None #to hold the camera opject self.galvoOut = None #galvo voltage control self.shutterOut = DAQPin(gv.shutterPin) #shutter control for OP laser self.sigmaGuess = .025 #guess of value for sigma in volts self.gammaGuess = 1e-3 #guess for value of gamma in volts self.window = tk.Tk() self.window.title("Fast Height Finder") self.window.geometry('800x600') lbl1 = tk.Label(self.window, text='Profile Center (v)') lbl1.grid(column=0, row=0, sticky='E') self.v0Box = tk.Entry(self.window) self.v0Box.config(width=5) self.v0Box.grid(column=1, row=0, sticky='W') self.settingsList.append(self.v0Box) lbl32 = tk.Label(self.window, text='bin size') lbl32.grid(column=2, row=0) self.binSizeBox = tk.Entry(self.window) self.binSizeBox.config(width=5) self.binSizeBox.grid(column=3, row=0, sticky='W') self.settingsList.append(self.binSizeBox) lbl3 = tk.Label(self.window, text='FWHM (v)') lbl3.grid(column=0, row=1, sticky='E') self.fwhmBox = tk.Entry(self.window) self.fwhmBox.config(width=5) self.fwhmBox.grid(column=1, row=1, sticky='W') self.settingsList.append(self.fwhmBox) lbl3 = tk.Label(self.window, text='num images off resonance') lbl3.grid(column=0, row=2) self.numImgOffResBox = tk.Entry(self.window) self.numImgOffResBox.config(width=5) self.numImgOffResBox.grid(column=1, row=2, sticky='W') self.settingsList.append(self.numImgOffResBox) lbl31 = tk.Label(self.window, text='Exp time (ms)') lbl31.grid(column=2, row=1) self.expTimeBox = tk.Entry(self.window) self.expTimeBox.config(width=5) self.expTimeBox.grid(column=3, row=1, sticky='W') self.settingsList.append(self.expTimeBox) lbl3 = tk.Label(self.window, text='num images on resonance') lbl3.grid(column=0, row=3) self.numImgOnResBox = tk.Entry(self.window) self.numImgOnResBox.config(width=5) self.numImgOnResBox.grid(column=1, row=3, sticky='W') self.settingsList.append(self.numImgOnResBox) lbl5 = tk.Label(self.window, text='image x1') lbl5.grid(column=0, row=4) self.x1Box = tk.Entry(self.window) self.x1Box.config(width=5) self.x1Box.grid(column=1, row=4, sticky='W') self.settingsList.append(self.x1Box) lbl5 = tk.Label(self.window, text='image x2') lbl5.grid(column=2, row=4) self.x2Box = tk.Entry(self.window) self.x2Box.config(width=5) self.x2Box.grid(column=3, row=4, sticky='W') self.settingsList.append(self.x2Box) lbl5 = tk.Label(self.window, text='image y1') lbl5.grid(column=0, row=5) self.y1Box = tk.Entry(self.window) self.y1Box.config(width=5) self.y1Box.grid(column=1, row=5, sticky='W') self.settingsList.append(self.y1Box) lbl5 = tk.Label(self.window, text='image y2') lbl5.grid(column=2, row=5) self.y2Box = tk.Entry(self.window) self.y2Box.config(width=5) self.y2Box.grid(column=3, row=5, sticky='W') self.settingsList.append(self.y2Box) lbl4 = tk.Label(self.window, text='Camera') lbl4.grid(column=0, row=6) self.cameraVar = tk.StringVar(self.window) self.cameraVar.set("FAR") cameraChoice = ["NEAR", "FAR"] CAMERA_MENU = tk.OptionMenu(self.window, self.cameraVar, *cameraChoice) CAMERA_MENU.grid(column=1, row=6, columnspan=2, sticky='W') self.settingsList.append(self.cameraVar) lbl4 = tk.Label(self.window, text='Shutter') lbl4.grid(column=2, row=6) self.shutterVar = tk.StringVar(self.window) self.shutterVar.set("OPEN") shutterChoice = ["CLOSED", "OPEN"] shutter_MENU = tk.OptionMenu(self.window, self.shutterVar, *shutterChoice, command=self.toggle_Shutter) shutter_MENU.grid(column=3, row=6, columnspan=2, sticky='W') self.settingsList.append(self.shutterVar) self.saveDataVar = tk.BooleanVar() saveDataCheckButton = tk.Checkbutton(self.window, text='save data', variable=self.saveDataVar) saveDataCheckButton.grid(column=1, row=7) self.settingsList.append(self.saveDataVar) self.ratioVar = tk.BooleanVar() ratioVarButton = tk.Checkbutton(self.window, text='ratio', variable=self.ratioVar) ratioVarButton.grid(column=1, row=8) self.settingsList.append(self.ratioVar) self.showPlotVar = tk.BooleanVar() showDataAnalysiButton = tk.Checkbutton(self.window, text='Show plot', variable=self.showPlotVar) showDataAnalysiButton.grid(column=1, row=9) self.settingsList.append(self.showPlotVar) lbl3 = tk.Label(self.window, text='Run name') lbl3.grid(column=0, row=15) self.fileName = tk.Entry(self.window) self.fileName.config(width=60) self.fileName.grid(column=1, row=15, sticky='W', columnspan=40) self.settingsList.append(self.fileName) lbl3 = tk.Label(self.window, text='Folder path') lbl3.grid(column=0, row=16) self.folderPath = tk.Entry(self.window) self.folderPath.config(width=60) self.folderPath.grid(column=1, row=16, sticky='W', columnspan=40) self.settingsList.append(self.folderPath) runButton = tk.Button(self.window, text='RUN', font=("Arial", 20), background="green", command=self.run) runButton.config(height=2, width=10) runButton.grid(column=0, row=17, columnspan=4, rowspan=4) coolCameraButton = tk.Button(self.window, text='cool camera', background="royal blue", command=self.cool_Camera) #coolCameraButton.config(height=2, width=10) coolCameraButton.grid(column=0, row=21, columnspan=4, rowspan=4) self.load_Settings() self.window.protocol("WM_DELETE_WINDOW", self.close_GUI) self.window.mainloop() def toggle_Shutter(self, x): if x == 'CLOSED': self.close_Aperture() if x == 'OPEN': self.open_Aperture() def cool_Camera(self): #cool the far field camera down if self.cameraVar.get() == "NEAR": print("YOU CAN'T COOL THE NEAR FIELD CAMERA") gv.warning_Sound() else: tempCamera = Camera(self.cameraVar.get(), 1000) #the camera will cool down tempCamera.close() #now close it. It will stay cool though def open_Aperture(self): #open the OP shutter self.shutterOut.write_Low() time.sleep(.01) def close_Aperture(self): #close the OP shutter self.shutterOut.write_High() time.sleep(.01) def close_GUI(self): self.shutterOut.close() self.save_Settings() self.window.destroy() sys.exit() def initialize_Camera(self): x1 = int(self.x1Box.get()) #image region values y1 = int(self.y1Box.get()) #image region values x2 = int(self.x2Box.get()) #image region values y2 = int(self.y2Box.get()) #image region values imageParams = [x1, x2, y1, y2] binSize = int(self.binSizeBox.get()) #binning value #initialize camera object. can be near or far field camera expTime = int(self.expTimeBox.get()) #exposure time, ms whichCam = self.cameraVar.get() #which camera to use, 'FAR' or 'NEAR' self.camera = Camera(whichCam, expTime, imageParams=imageParams, bin=binSize) def close_Camera(self): self.camera.close() self.camera = None def initialize_Scan_And_Plot_Arrays(self): v0 = float(self.v0Box.get()) #center value of transition from user df = float(self.fwhmBox.get()) #fwhm value from user offResFact = 4 #go this many fwhm away from center for 'far' off resonance background numImagesOnRes = int(self.numImgOnResBox.get() ) #number of images to take near the resonance numImagesOffRes = int(self.numImgOffResBox.get()) self.voltOffResArr = np.linspace( v0 - offResFact * df - df / 2, v0 - offResFact * df + df / 2, num=numImagesOffRes ) #voltage value to take images at 'far' off resonance self.voltOnResArr = np.linspace( v0 - 1.5 * df, v0 + 1.5 * df, num=numImagesOnRes ) #array of voltages to take images of near the peak self.voltPlotArr = np.linspace( v0 - (offResFact + 1) * df, v0 + (offResFact + 1) * df, num=1000) #voltages to make plot with. This should #be dense and uniform so it looks good def run(self): self.save_Settings() self.initialize_Camera() if os.path.isdir(self.folderPath.get()) == False: print('-----ERROR-----------') print('YOU HAVE ENTERED AN INVALID FOLDERPATH') if os.path.isfile(self.folderPath.get() + '\\' + self.fileName.get() + '.png') == True: print('--------------ERROR-------') print('THERE IS ALREADY A FILE WITH THAT NAME IN THAT FOLDER') gv.error_Sound() sys.exit() if self.ratioVar.get() == True: self.sweep_With_Shutter() else: self.sweep_Without_Shutter() self.camera.close() def sweep_With_Shutter(self): self.initialize_Scan_And_Plot_Arrays() self.initialize_Camera() voltList = [] #list to hold voltage values of corresponding images signalList1 = [] #list for signal values for apeture open signalList2 = [] #list for signal values for apeture open gv.begin_Sound(noWait=True) #beep without waiting after the beep self.galvoOut = DAQPin(gv.galvoOutPin) #open the galvo control pin #take images 'far' off resonance. This scan is very close to together for volt in self.voltOffResArr: print(volt) self.galvoOut.write(volt) #move galvo to new position voltList.append(volt) #record the voltage value self.open_Aperture() #'turn on' the optical pumping img = self.camera.aquire_Image() signalList1.append(np.mean(img)) self.close_Aperture() #'turn off' the optical pumping img = self.camera.aquire_Image() signalList2.append(np.mean(img)) #now sweep around the peak near resonance for volt in self.voltOnResArr: self.galvoOut.write(volt) #move galvo to new position voltList.append(volt) #record the voltage value self.open_Aperture() #'turn on' the optical pumping img = self.camera.aquire_Image() #capture an image signalList1.append(np.mean(img)) #add the average of the pixels self.close_Aperture() #'turn off' the optical pumping img = self.camera.aquire_Image() #capture an image signalList2.append(np.mean(img)) #add the average of the pixels self.galvoOut.close() #close and zero the pin self.open_Aperture() #open the shutter up again when done gv.finished_Sound(noWait=True) #beep without waiting after the beep #convert lists to arrays signalArr1 = np.asarray(signalList1) signalArr2 = np.asarray(signalList2) voltArr = np.asarray(voltList) #fit the data and get the optimal parameters and the error params1, perr1 = self.fit_Data(voltArr, signalArr1) params2, perr2 = self.fit_Data(voltArr, signalArr2) plt.close('all') plt.figure(figsize=(13, 8)) plt.plot(self.voltPlotArr, self.spectral_Profile(self.voltPlotArr, *params1), c='blue', label='fit, opened shutter') plt.plot(self.voltPlotArr, self.spectral_Profile(self.voltPlotArr, *params2), c='red', label='fit, closed shutter') plt.scatter(voltArr, signalArr1, label='data, opened shutter', c='blue') plt.scatter(voltArr, signalArr2, label='data, closed shutter', c='red', marker='x', s=100) v0 = (params1[0] + params2[0] ) / 2 #Get the center from the average of the two centers floor = (params1[1] + params2[1] ) / 2 #get the floor from the average of the two floors #now use the v0 above for when the user runs again. This helps compensate for the laser drifting without the user #having to self.v0Box.delete(0, 'end') #clear existing number self.v0Box.insert(0, str(np.round(v0, 3))) #insert new number plt.axvline(x=v0, c='r', linestyle=':') plt.grid() plt.text(v0, floor, np.round(float(v0), 3)) #TODO: WHY IS THIS NOT WORKING ONLY HERE? plt.legend() ratio = np.round(params1[1] / params2[1], 2) error = np.round( ratio * np.sqrt((perr1[1] / params1[1])**2 + (perr2[1] / params2[1])**2), 3) plt.suptitle('Ratio of open to close shutter height = ' + str(ratio) + ' +/- ' + str(error)) plt.title("shutter open= " + str(np.round(params1[1], 2)) + ' +/-' + str(np.round(perr1[1], 1)) + " . shutter closed= " + str(np.round(params2[1], 2)) + ' +/-' + str(np.round(perr2[1], 1))) if self.saveDataVar.get() == True: plt.savefig(self.folderPath.get() + '\\' + self.fileName.get() + 'Graph.png') if self.showPlotVar.get() == True: plt.show() def sweep_Without_Shutter(self): self.initialize_Scan_And_Plot_Arrays() self.initialize_Camera() voltList = [] signalList = [] gv.begin_Sound(noWait=True) #beep without waiting after the beep self.galvoOut = DAQPin(gv.galvoOutPin) #take images 'far' off resonance. This scan is very close to together for volt in self.voltOffResArr: self.galvoOut.write(volt) #move the galvo to a new voltage value voltList.append(volt) #record the voltage img = self.camera.aquire_Image() #capture image signalList.append( np.mean(img)) #add the average of the image's pixels for volt in self.voltOnResArr: print(volt) self.galvoOut.write(volt) #move the galvo to a new voltage value voltList.append(volt) #record the voltage img = self.camera.aquire_Image() #capture image print(np.mean(img)) signalList.append( np.mean(img)) #add the average of the image's pixels self.galvoOut.close() #close and zero the galvo self.camera.close() self.open_Aperture() #open the apeture up when done gv.finished_Sound(noWait=True) #beep without waiting after the beep voltArr = np.asarray(voltList) signalArr = np.asarray(signalList) params, perr = self.fit_Data(voltArr, signalArr) print(params) plt.close('all') plt.plot(self.voltPlotArr, self.spectral_Profile(self.voltPlotArr, *params), c='orange', label='fit') plt.scatter(voltArr, signalArr, label='data') v0 = params[0] floor = params[2] #now use the v0 above for when the user runs again. This helps compensate for the laser drifting without the user #having to self.v0Box.delete(0, 'end') #clear existing number self.v0Box.insert(0, str(np.round(v0, 3))) #insert new number plt.axvline(x=v0, c='r', linestyle=':') plt.text(v0, floor, np.round(float(v0), 3)) plt.legend() plt.grid() plt.title('Height = ' + str(np.round(params[1], 1)) + '+/- ' + str(np.round(perr[1], 1))) if self.saveDataVar.get() == True: plt.savefig(self.folderPath.get() + '\\' + self.fileName.get() + 'Graph.png') if self.showPlotVar.get() == True: plt.show() def fit_Data(self, x, y): print('here') #fit the data to get the optimal parameters x0Guess = float(self.v0Box.get()) aGuess = np.max(y) - np.min(y) bGuess = np.min(y) guess = [x0Guess, aGuess, bGuess, self.sigmaGuess, self.gammaGuess] bounds = ([-5, 0, 0, 0, 0], [5, 100000, 100000, .1, .1]) if bGuess > bounds[1][2] or aGuess > bounds[1][1]: print( 'GUESS VALUES ARE LARGER THAN BOUNDS. SIGNAL STRENGTH IS VERY HIGH' ) gv.error_Sound() sys.exit() try: params, pcov = spo.curve_fit(self.spectral_Profile, x, y, p0=guess, bounds=bounds) except: print('FIT FAILED') plt.plot(x, y) plt.show() perr = np.sqrt(np.diag(pcov)) return params, perr def spectral_Profile(self, x, x0, a, b, sigma, gamma): v0 = sps.voigt_profile(0, sigma, gamma) v = sps.voigt_profile(x - x0, sigma, gamma) return a * (v / v0) + b def save_Settings(self): file = open("fastHeightFinderGUI_Settings.txt", "w") for item in self.settingsList: file.write(str(item.get()) + '\n') file.close() def load_Settings(self): try: file = open("fastHeightFinderGUI_Settings.txt", "r") except: print("NO SETTINGS FILE FOUND") return i = 0 for item in file: item = item.strip() if i >= len(self.settingsList): pass else: if isinstance(self.settingsList[i], tk.StringVar): self.settingsList[i].set(item) elif isinstance(self.settingsList[i], tk.Entry): self.settingsList[i].insert(0, item) elif isinstance(self.settingsList[i], tk.BooleanVar): if item == 'False' or item == 'True': self.settingsList[i].set(item) i += 1 file.close()