def registration(self, grid_points_x=3, grid_points_y=3): galvothread = DAQmission() readinchan = [] x_coords = np.linspace(-10, 10, grid_points_x + 2)[1:-1] y_coords = np.linspace(-10, 10, grid_points_y + 2)[1:-1] xy_mesh = np.reshape(np.meshgrid(x_coords, y_coords), (2, -1), order='F').transpose() galvo_coordinates = xy_mesh camera_coordinates = np.zeros((galvo_coordinates.shape)) for i in range(galvo_coordinates.shape[0]): galvothread.sendSingleAnalog('galvosx', galvo_coordinates[i, 0]) galvothread.sendSingleAnalog('galvosy', galvo_coordinates[i, 1]) time.sleep(1) image = self.cam.SnapImage(0.06) plt.imsave( os.getcwd() + '/CoordinatesManager/Registration_Images/2P/image_' + str(i) + '.png', image) camera_coordinates[i, :] = readRegistrationImages.gaussian_fitting( image) print('Galvo Coordinate') print(galvo_coordinates) print('Camera coordinates') print(camera_coordinates) del galvothread self.cam.Exit() transformation = CoordinateTransformations.polynomial2DFit( camera_coordinates, galvo_coordinates, order=1) print('Transformation found for x:') print(transformation[:, :, 0]) print('Transformation found for y:') print(transformation[:, :, 1]) return transformation
def gather_reference_coordinates_galvos(self): galvothread = DAQmission() readinchan = [] camera_coordinates = np.zeros((3, 2)) galvo_coordinates = np.array([[0, 3], [3, -3], [-3, -3]]) for i in range(3): pos_x = galvo_coordinates[i, 0] pos_y = galvo_coordinates[i, 1] galvothread.sendSingleAnalog('galvosx', pos_x) galvothread.sendSingleAnalog('galvosy', pos_y) image = self.cam.SnapImage(0.04) camera_coordinates[i, :] = gaussian_fitting(image) del galvothread return np.array([camera_coordinates, galvo_coordinates])
def control_for_registration(self, wavelength, value): value = int(value) daq = DAQmission() if value == 0: switch = False else: switch = True if wavelength == "640": print(wavelength + ":" + str(value)) print(str(switch)) daq.sendSingleAnalog("640AO", value) daq.sendSingleDigital("640blanking", switch) elif wavelength == "532": print(wavelength + ":" + str(value)) print(str(switch)) daq.sendSingleAnalog("532AO", value) daq.sendSingleDigital("640blanking", switch) else: print(wavelength + ":" + str(value)) print(str(switch)) daq.sendSingleAnalog("488AO", value) daq.sendSingleDigital("640blanking", switch)
def control_for_registration(self, wavelength, value): value = int(value) daq = DAQmission() if value == 0: switch = False else: switch = True if wavelength == '640': print(wavelength + ':' + str(value)) print(str(switch)) daq.sendSingleAnalog('640AO', value) daq.sendSingleDigital('640blanking', switch) elif wavelength == '532': print(wavelength + ':' + str(value)) print(str(switch)) daq.sendSingleAnalog('532AO', value) daq.sendSingleDigital('640blanking', switch) else: print(wavelength + ':' + str(value)) print(str(switch)) daq.sendSingleAnalog('488AO', value) daq.sendSingleDigital('640blanking', switch)
def execute_tread_single_sample_analog(self, channel): daq = DAQmission() if channel == '640AO': self.lasers_status['640'][1] = self.slider640.value() daq.sendSingleAnalog(channel, self.slider640.value() / 100) elif channel == '532AO': self.lasers_status['532'][1] = self.slider532.value() daq.sendSingleAnalog(channel, self.slider532.value() / 100) elif channel == '488AO': self.lasers_status['488'][1] = self.slider488.value() daq.sendSingleAnalog(channel, self.slider488.value() / 100) self.sig_lasers_status_changed.emit(self.lasers_status)
def control_for_registration(self, wavelength, value): value = int(value) daq = DAQmission() if value == 0: switch = False else: switch = True if wavelength == '640': print(wavelength + ':' + str(value)) print(str(switch)) daq.sendSingleAnalog('640AO', value) # execute_tread_singlesample_AOTF_analog = execute_tread_singlesample_analog() # execute_tread_singlesample_AOTF_analog.set_waves('640AO', value) # execute_tread_singlesample_AOTF_analog.start() daq.sendSingleDigital('640blanking', switch) # execute_tread_singlesample_AOTF_digital = execute_tread_singlesample_digital() # execute_tread_singlesample_AOTF_digital.set_waves('640blanking', switch) # execute_tread_singlesample_AOTF_digital.start() elif wavelength == '532': print(wavelength + ':' + str(value)) print(str(switch)) daq.sendSingleAnalog('532AO', value) daq.sendSingleDigital('640blanking', switch) # execute_tread_singlesample_AOTF_analog = execute_tread_singlesample_analog() # execute_tread_singlesample_AOTF_analog.set_waves('532AO', value) # execute_tread_singlesample_AOTF_analog.start() # execute_tread_singlesample_AOTF_digital = execute_tread_singlesample_digital() # execute_tread_singlesample_AOTF_digital.set_waves('640blanking', switch) # execute_tread_singlesample_AOTF_digital.start() else: print(wavelength + ':' + str(value)) print(str(switch)) daq.sendSingleAnalog('488AO', value) daq.sendSingleDigital('640blanking', switch)
class PatchclampSealTestUI(QWidget): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.saving_dir = r'M:\tnw\ist\do\projects\Neurophotonics\Brinkslab\Data\Patch clamp\seal_test' #------------------------Initiating patchclamp class------------------- self.sealTest = PatchclampSealTest() self.sealTest.measurementThread.measurement.connect( self.handleMeasurement) #Connecting to the measurement signal self.holdTest = PatchclampSealTest_hold() self.holdTest.measurementThread_hold.measurement.connect( self.handleMeasurement) #Connecting to the measurement signal self.currentclampTest = PatchclampSealTest_currentclamp() self.currentclampTest.measurementThread_currentclamp.measurement.connect( self.handleMeasurement) #Connecting to the measurement signal self.zapfunction = PatchclampSealTest_zap() #---------------------------------------------------------------------- #----------------------------------GUI--------------------------------- #---------------------------------------------------------------------- self.setFixedHeight(700) self.setWindowTitle("Patchclamp Seal Test") self.ICON_RED_LED = "./Icons/off.png" self.ICON_GREEN_LED = '/Icons/on.png' self.is_sealtesting = False #------------------------------Gains----------------------------------- gainContainer = StylishQT.roundQGroupBox(title="Gains") # gainContainer.setFixedWidth(320) gainLayout = QGridLayout() gainLayout.addWidget(QLabel("Input Voltage"), 0, 0) self.inVolGainList = QComboBox() self.inVolGainList.addItems(['1/10', '1', '1/50']) gainLayout.addWidget(self.inVolGainList, 1, 0) gainLayout.addWidget(QLabel("Output Voltage"), 0, 1) self.outVolGainList = QComboBox() self.outVolGainList.addItems(['10', '2', '5', '1', '20', '50', '100']) gainLayout.addWidget(self.outVolGainList, 1, 1) gainLayout.addWidget(QLabel("Output Current"), 0, 2) self.outCurGainList = QComboBox() self.outCurGainList.addItems(['1', '2', '5', '10', '20', '50', '100']) gainLayout.addWidget(self.outCurGainList, 1, 2) gainLayout.addWidget(QLabel("Probe"), 0, 3) self.probeGainList = QComboBox() self.probeGainList.addItems(['100M\u03A9', '10G\u03A9']) gainLayout.addWidget(self.probeGainList, 1, 3) gainContainer.setLayout(gainLayout) #------------------------------Wavesettings----------------------------------- WavesettingsContainer = StylishQT.roundQGroupBox(title="Wave settings") # WavesettingsContainer.setFixedWidth(320) WavesettingsContainerLayout = QGridLayout() WavesettingsContainerLayout.addWidget(QLabel("Voltage step(mV)"), 0, 0) self.DiffVoltagebox = QSpinBox(self) self.DiffVoltagebox.setMaximum(2000) self.DiffVoltagebox.setMinimum(-2000) self.DiffVoltagebox.setValue(10) self.DiffVoltagebox.setSingleStep(10) WavesettingsContainerLayout.addWidget(self.DiffVoltagebox, 0, 1) WavesettingsContainerLayout.addWidget(QLabel("Voltage baseline(mV)"), 0, 2) self.LowerVoltagebox = QSpinBox(self) self.LowerVoltagebox.setMaximum(2000) self.LowerVoltagebox.setMinimum(-2000) self.LowerVoltagebox.setValue(0) self.LowerVoltagebox.setSingleStep(30) WavesettingsContainerLayout.addWidget(self.LowerVoltagebox, 0, 3) WavesettingsContainer.setLayout(WavesettingsContainerLayout) #------------------------------Membrane potential----------------------------------- Vm_measureContainer = StylishQT.roundQGroupBox(title="Vm measurement") # Vm_measureContainer.setFixedWidth(320) Vm_measureContainerLayout = QGridLayout() Vm_measureContainerLayout.addWidget(QLabel("Clamping current(pA)"), 0, 0) self.clampingcurrentbox = QSpinBox(self) self.clampingcurrentbox.setMaximum(2000) self.clampingcurrentbox.setMinimum(-2000) self.clampingcurrentbox.setValue(0) self.clampingcurrentbox.setSingleStep(100) Vm_measureContainerLayout.addWidget(self.clampingcurrentbox, 0, 1) self.membraneVoltLabel = QLabel("Vm: ") Vm_measureContainerLayout.addWidget(self.membraneVoltLabel, 0, 2) self.VmstartButton = StylishQT.runButton() self.VmstartButton.clicked.connect(lambda: self.measure_currentclamp()) Vm_measureContainerLayout.addWidget(self.VmstartButton, 0, 3) self.VmstopButton = StylishQT.stop_deleteButton() self.VmstopButton.setEnabled(False) self.VmstopButton.clicked.connect( lambda: self.stopMeasurement_currentclamp()) Vm_measureContainerLayout.addWidget(self.VmstopButton, 0, 4) Vm_measureContainer.setLayout(Vm_measureContainerLayout) #------------------------------zap----------------------------------- zapContainer = StylishQT.roundQGroupBox(title="ZAP") # zapContainer.setFixedWidth(320) zapContainerLayout = QGridLayout() self.ICON_zap = './Icons/zap.jpg' self.zapiconlabel = QLabel() self.zapiconlabel.setPixmap(QPixmap(self.ICON_zap)) zapContainerLayout.addWidget(self.zapiconlabel, 0, 0) self.zapButton = QPushButton("ZAP!") self.zapButton.setStyleSheet( "QPushButton {color:white;background-color: blue; border-style: outset;border-radius: 10px;border-width: 2px;font: bold 14px;padding: 6px}" "QPushButton:pressed {color:black;background-color: red; border-style: outset;border-radius: 10px;border-width: 2px;font: bold 14px;padding: 6px}" "QPushButton:hover:!pressed {color:blue;background-color: white; border-style: outset;border-radius: 10px;border-width: 2px;font: bold 14px;padding: 6px}" ) self.zapButton.setShortcut('z') zapContainerLayout.addWidget(self.zapButton, 0, 1) self.zapButton.clicked.connect(self.zap) zapContainerLayout.addWidget(QLabel("ZAP voltage(V)"), 0, 2) self.zapVbox = QDoubleSpinBox(self) self.zapVbox.setMaximum(1) self.zapVbox.setMinimum(-2000) self.zapVbox.setValue(1) self.zapVbox.setSingleStep(0.1) zapContainerLayout.addWidget(self.zapVbox, 0, 3) zapContainerLayout.addWidget(QLabel("ZAP duration(us)"), 0, 4) self.zaptimebox = QSpinBox(self) self.zaptimebox.setMaximum(200000000) self.zaptimebox.setMinimum(-200000000) self.zaptimebox.setValue(200) self.zaptimebox.setSingleStep(200) zapContainerLayout.addWidget(self.zaptimebox, 0, 5) zapContainer.setLayout(zapContainerLayout) #----------------------------Control----------------------------------- controlContainer = StylishQT.roundQGroupBox(title="Control") controlContainer.setFixedWidth(350) controlLayout = QGridLayout() # controlLayout.addWidget(QLabel("Holding Vm:"), 1, 0) # self.HoldingList = QComboBox() # self.HoldingList.addItems(['000 mV', '-30 mV', '-50 mV', '-40 mV', '-60 mV']) # controlLayout.addWidget(self.HoldingList, 2, 0) # # self.iconlabel = QLabel(self) # self.iconlabel.setPixmap(QPixmap(self.ICON_RED_LED)) # controlLayout.addWidget(self.iconlabel, 1, 1) # # self.holdingbutton = QPushButton("Hold") # self.holdingbutton.setCheckable(True) # #self.holdingbutton.toggle() # # self.holdingbutton.clicked.connect(lambda: self.btnstate()) # #self.holdingbutton.clicked.connect(lambda: self.hold()) # #self.holdingbutton.clicked.connect(self.setGreenlight) # controlLayout.addWidget(self.holdingbutton, 2, 1) # self.stopandholdbutton = QPushButton("Stop and Hold") # self.stopandholdbutton.clicked.connect(lambda: self.stopMeasurement()) # self.stopandholdbutton.clicked.connect(lambda: self.measure_hold()) # self.stopandholdbutton.clicked.connect(self.setGreenlight) # controlLayout.addWidget(self.stopandholdbutton, 0, 2) ''' self.stopholdingbutton = QPushButton("Stop holding") self.stopholdingbutton.clicked.connect(lambda: self.stophold()) self.stopholdingbutton.clicked.connect(self.setRedlight) controlLayout.addWidget(self.stopholdingbutton, 2, 2) ''' controlLayout.addWidget(gainContainer, 0, 0, 1, 2) controlLayout.addWidget(WavesettingsContainer, 1, 0, 1, 2) controlLayout.addWidget(Vm_measureContainer, 2, 0, 1, 2) controlLayout.addWidget(zapContainer, 3, 0, 1, 2) self.startButton = StylishQT.runButton("Start seal-test") self.startButton.clicked.connect(lambda: self.measure()) # self.startButton.setFixedWidth(120) # self.startButton.clicked.connect(self.setRedlight) # self.startButton.clicked.connect(self.startUpdatingGUIThread) controlLayout.addWidget(self.startButton, 4, 0, 1, 1) self.stopButton = StylishQT.stop_deleteButton() self.stopButton.setEnabled(False) # self.stopButton.setFixedWidth(120) self.stopButton.clicked.connect(lambda: self.stopMeasurement()) controlLayout.addWidget(self.stopButton, 4, 1, 1, 1) controlContainer.setLayout(controlLayout) #-----------------------------Plots------------------------------------ plotContainer = StylishQT.roundQGroupBox(title="Output") plotContainer.setFixedWidth(350) self.plotLayout = QGridLayout( ) #We set the plotLayout as an attribute of the object (i.e. self.plotLayout instead of plotLayout) #This is to prevent the garbage collector of the C++ wrapper from deleting the layout and thus triggering errors. #Derived from: https://stackoverflow.com/questions/17914960/pyqt-runtimeerror-wrapped-c-c-object-has-been-deleted # and http://enki-editor.org/2014/08/23/Pyqt_mem_mgmt.html # self.outVolPlotWidget = SlidingWindow(200, title = "Voltage", unit = "V") #Should be bigger than the readvalue self.outCurPlotWidget = SlidingWindow( 200, title="Current", unit="A") #Should be bigger than the readvalue self.display_tab_widget = QTabWidget() # self.plotLayout.addWidget(QLabel('Voltage (mV):'), 0, 0) self.display_tab_widget.addTab(self.outCurPlotWidget, "Current") # self.plotLayout.addWidget(self.outVolPlotWidget, 1, 0) # self.plotLayout.addWidget(QLabel('Current (pA):'), 0, 1) # self.display_tab_widget.addTab(self.outVolPlotWidget, "Voltage") # self.plotLayout.addWidget(self.outCurPlotWidget, 1, 1) valueContainer = QGroupBox("Resistance/Capacitance") self.valueLayout = QGridLayout() self.resistanceLabel = QLabel("Resistance: ") self.capacitanceLabel = QLabel("Capacitance: ") self.ratioLabel = QLabel("Ratio: ") self.valueLayout.addWidget(self.resistanceLabel, 0, 0) self.valueLayout.addWidget(self.capacitanceLabel, 0, 1) self.valueLayout.addWidget(self.ratioLabel, 0, 2) self.pipette_resistance = QLineEdit(self) self.pipette_resistance.setPlaceholderText('Pipette resistance') self.pipette_resistance.setFixedWidth(100) self.valueLayout.addWidget(self.pipette_resistance, 1, 0) self.savedataButton = QPushButton("Save figure") self.savedataButton.clicked.connect(lambda: self.savePatchfigure()) self.valueLayout.addWidget(self.savedataButton, 1, 1) self.resetButton = QPushButton("Reset Iplot") self.resetButton.clicked.connect(lambda: self.ResetCurrentImgView()) self.valueLayout.addWidget(self.resetButton, 1, 2) valueContainer.setLayout(self.valueLayout) self.plotLayout.addWidget(self.display_tab_widget, 0, 0, 1, 1) self.plotLayout.addWidget(valueContainer, 2, 0, 1, 1) plotContainer.setLayout(self.plotLayout) #---------------------------Adding to master--------------------------- master = QVBoxLayout() master.addWidget(controlContainer) master.addWidget(plotContainer) self.setLayout(master) #--------------------------Setting variables--------------------------- self.changeVolInGain(self.inVolGainList.currentText()) self.changeVolOutGain(self.outVolGainList.currentText()) self.changeCurOutGain(self.outCurGainList.currentText()) self.changeProbeGain(self.probeGainList.currentText()) self.inVolGainList.currentIndexChanged.connect( lambda: self.changeVolInGain(self.inVolGainList.currentText())) self.outVolGainList.currentIndexChanged.connect( lambda: self.changeVolOutGain(self.outVolGainList.currentText())) self.outCurGainList.currentIndexChanged.connect( lambda: self.changeCurOutGain(self.outCurGainList.currentText())) self.probeGainList.currentIndexChanged.connect( lambda: self.changeProbeGain(self.probeGainList.currentText())) def ResetCurrentImgView(self): """Closes the widget nicely, making sure to clear the graphics scene and release memory.""" self.outCurPlotWidget.close() # self.outVolPlotWidget.close() # Replot the imageview self.outCurPlotWidget = SlidingWindow(200, title="Current", unit="A") self.display_tab_widget.addTab(self.outCurPlotWidget, "Current") # self.display_tab_widget.addTab(self.outVolPlotWidget, "Voltage") def measure(self): """Pop up window asking to check the gains. Returns True if the measurement can be done and False if not. """ #check = QMessageBox.question(self, 'GAINS!', "Are all the gains corresponding?", #QMessageBox.Yes | QMessageBox.No) #if check == QMessageBox.Yes: """Start the patchclamp measurement""" self.stopButton.setEnabled(True) self.startButton.setEnabled(False) self.diffvoltage = self.DiffVoltagebox.value() / 1000 self.lowervoltage = self.LowerVoltagebox.value() / 1000 self.sealTest.setWave(self.inVolGain, self.diffvoltage, self.lowervoltage) self.sealTest.start() self.is_sealtesting = True self.startUpdatingGUIThread() def measure_hold(self): """Pop up window asking to check the gains. Returns True if the measurement can be done and False if not. """ self.holdTest.setWave(self.inVolGain, float(self.HoldingList.currentText()[0:3])) self.holdTest.start() self.is_sealtesting = True def measure_currentclamp(self): """Pop up window asking to check the gains. Returns True if the measurement can be done and False if not. """ #check = QMessageBox.question(self, 'GAINS!', "Are all the gains corresponding?", #QMessageBox.Yes | QMessageBox.No) #if check == QMessageBox.Yes: """Start the patchclamp measurement""" self.VmstartButton.setEnabled(False) self.VmstopButton.setEnabled(True) self.currentclamp_value = self.clampingcurrentbox.value() self.currentclampTest.setWave(self.inVolGain, self.probeGain, self.currentclamp_value) self.currentclampTest.start() self.is_sealtesting = True def hold(self): constant = float(self.HoldingList.currentText()[0:3]) self.executer = DAQmission() self.executer.sendSingleAnalog('patchAO', constant / 1000 * 10) print("Holding vm at " + str(constant) + ' mV') def stophold(self): self.executer.sendSingleAnalog('patchAO', 0) print('Stop holding') def btnstate(self): #source = self.sender() if self.holdingbutton.isChecked(): self.measure_hold() self.setGreenlight() else: self.stop_hold_Measurement() self.setRedlight() def setRedlight(self): self.iconlabel.setPixmap(QPixmap(self.ICON_RED_LED)) def setGreenlight(self): self.iconlabel.setPixmap(QPixmap(self.ICON_GREEN_LED)) def startUpdatingGUIThread(self): time.sleep(0.3) StartGUIThread = threading.Thread(target=self.startUpdatingGUI) StartGUIThread.start() # else: # .disconnect() def handleMeasurement(self, voltOut, curOut): """Handle the measurement. Update the graph.""" #Rescaling using gains self.voltOut = voltOut / self.outVolGain self.curOut = curOut / self.outCurGain / self.probeGain def startUpdatingGUI(self): while self.is_sealtesting == True: try: # self.outVolPlotWidget.append_(self.voltOut) self.outCurPlotWidget.append_(self.curOut) self.updateGraphs() self.updateLabels(self.curOut, self.voltOut) time.sleep(0.05) except: pass def updateGraphs(self): """Update graphs.""" self.outCurPlotWidget.updateWindow() # self.outVolPlotWidget.updateWindow() def updateLabels(self, curOut, voltOut): """Update the resistance and capacitance labels. http://scipy-lectures.org/intro/scipy/auto_examples/plot_curve_fit.html https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.curve_fit.html""" constants = MeasurementConstants() sampPerCyc = int(constants.patchSealSampRate / constants.patchSealFreq) try: curOutCyc = curOut.reshape(int(curOut.size / sampPerCyc), sampPerCyc) curData = np.mean(curOutCyc, axis=0) except: curData = curOut voltData = voltOut try: #Computing resistance tres = np.mean(voltData) dV = np.mean(voltData[voltData > tres]) - np.mean( voltData[voltData < tres]) #Computing the voltage difference dIss = np.mean( curData[math.floor(0.15 * sampPerCyc):math.floor(sampPerCyc / 2) - 2]) - np.mean( curData[math.floor(0.65 * sampPerCyc):sampPerCyc - 2]) #Computing the current distance membraneResistance = dV / (dIss * 1000000) #Ohms law (MegaOhm) self.resistanceLabel.setText("Resistance: %.4f M\u03A9" % membraneResistance) self.estimated_size_resistance = 10000 / ( membraneResistance * 1000000 ) #The resistance of a typical patch of membrane, RM is 10000 Omega/{cm}^2 except: self.resistanceLabel.setText("Resistance: %s" % 'NaN') try: measured_vlotage = np.mean(voltData) * 1000 self.membraneVoltLabel.setText("Vm: %.2f mV" % measured_vlotage) self.membraneVoltLabel.setStyleSheet('color: red') except: self.membraneVoltLabel.setText("Vm: %s" % 'NaN') try: #Computing capacitance points = 10 maxCur = np.amax(curData) maxCurIndex = np.where(curData == maxCur)[0][0] curFit = curData[int(maxCurIndex + 1):int( maxCurIndex + 1 + points - 1)] - 0.5 * (np.mean(curData[ math.floor(0.15 * sampPerCyc):math.floor(sampPerCyc / 2) - 2]) + np.mean( curData[math.floor(0.65 * sampPerCyc):sampPerCyc - 2])) timepoints = 1000 * np.arange( 3, points - 1 + 3) / constants.patchSealSampRate #Fitting the data to an exponential of the form y=a*exp(-b*x) where b = 1/tau and tau = RC #I(t)=I0*e^−t/τ, y=a*exp(-b*x), get log of both sides:log y = -bx + log a fit = np.polyfit( timepoints, curFit, 1 ) #Converting the exponential to a linear function and fitting it #Extracting data current = fit[0] resistance = dV * 1000 / current / 2 #Getting the resistance tau = -1 / fit[1] capacitance = 1000 * tau / resistance self.capacitanceLabel.setText("Capacitance: %.4f" % capacitance) self.estimated_size_capacitance = capacitance * (10**-12) * (10**6) if self.estimated_size_capacitance > self.estimated_size_resistance: self.estimated_ratio = self.estimated_size_capacitance / self.estimated_size_resistance else: self.estimated_ratio = self.estimated_size_resistance / self.estimated_size_capacitance self.ratioLabel.setText( "Ratio: %.4f" % self.estimated_ratio ) #http://www.cnbc.cmu.edu/~bard/passive2/node5.html except: self.capacitanceLabel.setText("Capacitance: %s" % 'NaN') self.ratioLabel.setText("Ratio: %s" % 'NaN') self.patch_parameters = "R_{}_C_{}".format( round(membraneResistance, 3), round(capacitance, 3)) def stopMeasurement(self): """Stop the seal test.""" self.stopButton.setEnabled(False) self.startButton.setEnabled(True) self.sealTest.aboutToQuitHandler() self.is_sealtesting = False #constant = float(self.HoldingList.currentText()[0:3]) #self.executer = execute_constant_vpatch(constant/1000*10) #print("Holding vm at "+str(constant)+' mV') ''' def closeEvent(self, event): """On closing the application we have to make sure that the measuremnt stops and the device gets freed.""" self.stopMeasurement() ''' def stop_hold_Measurement(self): """Stop the seal test.""" self.holdTest.aboutToQuitHandler() self.is_sealtesting = False def close_hold_Event(self, event): """On closing the application we have to make sure that the measuremnt stops and the device gets freed.""" self.stop_hold_Measurement() def stopMeasurement_currentclamp(self): """Stop the seal test.""" self.VmstartButton.setEnabled(True) self.VmstopButton.setEnabled(False) self.currentclampTest.aboutToQuitHandler() self.is_sealtesting = False #Change gain def changeVolInGain(self, gain): if gain == '1': self.inVolGain = 1 elif gain == '1/10': self.inVolGain = 0.1 elif gain == '1/50': self.inVolGain = 1. / 50 def changeVolOutGain(self, gain): self.outVolGain = float(gain) def changeCurOutGain(self, gain): self.outCurGain = float(gain) def changeProbeGain(self, gain): if gain == '100M\u03A9': self.probeGain = 100 * 10**6 elif gain == '10G\u03A9': self.probeGain = 10 * 10**9 def zap(self): self.zap_v = self.zapVbox.value() self.zap_time = self.zaptimebox.value() self.sealTest.aboutToQuitHandler() self.zapfunction.setWave(self.inVolGain, self.zap_v, self.zap_time) self.zapfunction.start() time.sleep(0.06) self.zapfunction.aboutToQuitHandler() """Start the patchclamp measurement""" self.diffvoltage = self.DiffVoltagebox.value() / 1000 self.lowervoltage = self.LowerVoltagebox.value() / 1000 self.sealTest.setWave(self.inVolGain, self.diffvoltage, self.lowervoltage) self.sealTest.start() def savePatchfigure(self): # create an exporter instance, as an argument give it # the item you wish to export exporter = pg.exporters.ImageExporter( self.outCurPlotWidget.getPlotItem()) # set export parameters if needed exporter.parameters( )['width'] = 500 # (note this also affects height parameter) # save to file exporter.export( os.path.join( self.saving_dir, 'SealTest_' + "Rpip_" + self.pipette_resistance.text() + "Mohm_" + self.patch_parameters + '.png'))
class FocusFinder(): def __init__(self, source_of_image = "PMT", init_search_range = 0.010, total_step_number = 5, imaging_conditions = {'edge_volt':5}, \ motor_handle = None, camera_handle = None, twophoton_handle = None, *args, **kwargs): """ Parameters ---------- source_of_image : string, optional The input source of image. The default is PMT. init_search_range : int, optional The step size when first doing coarse searching. The default is 0.010. total_step_number : int, optional Number of steps in total to find optimal focus. The default is 5. imaging_conditions : list Parameters for imaging. For PMT, it specifies the scanning voltage. For camera, it specifies the AOTF voltage and exposure time. motor_handle : TYPE, optional Handle to control PI motor. The default is None. twophoton_handle : TYPE, optional Handle to control Insight X3. The default is None. Returns ------- None. """ super().__init__(*args, **kwargs) # The step size when first doing coarse searching. self.init_search_range = init_search_range # Number of steps in total to find optimal focus. self.total_step_number = total_step_number # Parameters for imaging. self.imaging_conditions = imaging_conditions if motor_handle == None: # Connect the objective if the handle is not provided. self.pi_device_instance = PIMotor() else: self.pi_device_instance = motor_handle # Current position of the focus. self.current_pos = self.pi_device_instance.GetCurrentPos() # Number of steps already tried. self.steps_taken = 0 # The focus degree of previous position. self.previous_degree_of_focus = 0 # Number of going backwards. self.turning_point = 0 # The input source of image. self.source_of_image = source_of_image if source_of_image == "PMT": self.galvo = RasterScan(Daq_sample_rate = 500000, edge_volt = self.imaging_conditions['edge_volt']) elif source_of_image == "Camera": if camera_handle == None: # If no camera instance fed in, initialize camera. self.HamamatsuCam_ins = CamActuator() self.HamamatsuCam_ins.initializeCamera() else: self.HamamatsuCam_ins = camera_handle def gaussian_fit(self, move_to_focus = True): # The upper edge. upper_position = self.current_pos + self.init_search_range # The lower edge. lower_position = self.current_pos - self.init_search_range # Generate the sampling positions. sample_positions = np.linspace(lower_position, upper_position, self.total_step_number) degree_of_focus_list = [] for each_pos in sample_positions: # Go through each position and write down the focus degree. degree_of_focus = self.evaluate_focus(round(each_pos, 6)) degree_of_focus_list.append(degree_of_focus) print(degree_of_focus_list) try: interpolated_fitted_curve = ProcessImage.gaussian_fit(degree_of_focus_list) # Generate the inpterpolated new focus position axis. x_axis_new = np.linspace(lower_position, upper_position, len(interpolated_fitted_curve)) # Generate a dictionary and find the position where has the highest focus degree. max_focus_pos = dict(zip(interpolated_fitted_curve, x_axis_new))[np.amax(interpolated_fitted_curve)] if True: # Plot the fitting. plt.plot(sample_positions, np.asarray(degree_of_focus_list),'b+:',label='data') plt.plot(x_axis_new, interpolated_fitted_curve,'ro:',label='fit') plt.legend() plt.title('Fig. Fit for focus degree') plt.xlabel('Position') plt.ylabel('Focus degree') plt.show() max_focus_pos = round(max_focus_pos, 6) print(max_focus_pos) self.pi_device_instance.move(max_focus_pos) # max_focus_pos_focus_degree = self.evaluate_focus(round(max_focus_pos, 6)) except: print("Fitting failed. Find max in the list.") max_focus_pos = sample_positions[degree_of_focus_list.index(max(degree_of_focus_list))] print(max_focus_pos) if move_to_focus == True: self.pi_device_instance.move(max_focus_pos) return max_focus_pos def bisection(self): """ Bisection way of finding focus. Returns ------- mid_position : float DESCRIPTION. """ # The upper edge in which we run bisection. upper_position = self.current_pos + self.init_search_range # The lower edge in which we run bisection. lower_position = self.current_pos - self.init_search_range for step_index in range(1, self.total_step_number + 1): # In each step of bisection finding. # In the first round, get degree of focus at three positions. if step_index == 1: # Get degree of focus in the mid. mid_position = (upper_position + lower_position)/2 degree_of_focus_mid = self.evaluate_focus(mid_position) print("mid focus degree: {}".format(round(degree_of_focus_mid, 5))) # Break the loop if focus degree is below threshold which means # that there's no cell in image. if not ProcessImage.if_theres_cell(self.galvo_image.astype('float32')): print('no cell') mid_position = False break # Move to top and evaluate. degree_of_focus_up = self.evaluate_focus(obj_position = upper_position) print("top focus degree: {}".format(round(degree_of_focus_up, 5))) # Move to bottom and evaluate. degree_of_focus_low = self.evaluate_focus(obj_position = lower_position) print("bot focus degree: {}".format(round(degree_of_focus_low, 5))) # Sorting dicitonary of degrees in ascending. biesection_range_dic = {"top":[upper_position, degree_of_focus_up], "bot":[lower_position, degree_of_focus_low]} # In the next rounds, only need to go to center and update boundaries. elif step_index > 1: # The upper edge in which we run bisection. upper_position = biesection_range_dic["top"][0] # The lower edge in which we run bisection. lower_position = biesection_range_dic["bot"][0] # Get degree of focus in the mid. mid_position = (upper_position + lower_position)/2 degree_of_focus_mid = self.evaluate_focus(mid_position) print("Current focus degree: {}".format(round(degree_of_focus_mid, 5))) # If sits in upper half, make the middle values new bottom. if biesection_range_dic["top"][1] > biesection_range_dic["bot"][1]: biesection_range_dic["bot"] = [mid_position, degree_of_focus_mid] else: biesection_range_dic["top"] = [mid_position, degree_of_focus_mid] print("The upper pos: {}; The lower: {}".format(biesection_range_dic["top"][0], biesection_range_dic["bot"][0])) return mid_position def evaluate_focus(self, obj_position = None): """ Evaluate the focus degree of certain objective position. Parameters ---------- obj_position : float, optional The target objective position. The default is None. Returns ------- degree_of_focus : float Degree of focus. """ if obj_position != None: self.pi_device_instance.move(obj_position) # Get the image. if self.source_of_image == "PMT": self.galvo_image = self.galvo.run() plt.figure() plt.imshow(self.galvo_image) plt.show() if False: with skimtiff.TiffWriter(os.path.join(r'M:\tnw\ist\do\projects\Neurophotonics\Brinkslab\Data\Xin\2020-11-17 gaussian fit auto-focus cells\trial_11', str(obj_position).replace(".", "_")+ '.tif')) as tif: tif.save(self.galvo_image.astype('float32'), compress=0) degree_of_focus = ProcessImage.local_entropy(self.galvo_image.astype('float32')) elif self.source_of_image == "Camera": # First configure the AOTF. self.AOTF_runner = DAQmission() # Find the AOTF channel key for key in self.imaging_conditions: if 'AO' in key: # like '488AO' AOTF_channel_key = key # Set the AOTF first. self.AOTF_runner.sendSingleDigital('blankingall', True) self.AOTF_runner.sendSingleAnalog(AOTF_channel_key, self.imaging_conditions[AOTF_channel_key]) # Snap an image from camera self.camera_image = self.HamamatsuCam_ins.SnapImage(self.imaging_conditions['exposure_time']) time.sleep(0.5) # Set back AOTF self.AOTF_runner.sendSingleDigital('blankingall', False) self.AOTF_runner.sendSingleAnalog(AOTF_channel_key, 0) plt.figure() plt.imshow(self.camera_image) plt.show() if False: with skimtiff.TiffWriter(os.path.join(r'M:\tnw\ist\do\projects\Neurophotonics\Brinkslab\Data\Xin\2021-03-06 Camera AF\beads', str(obj_position).replace(".", "_")+ '.tif')) as tif: tif.save(self.camera_image.astype('float32'), compress=0) degree_of_focus = ProcessImage.variance_of_laplacian(self.camera_image.astype('float32')) time.sleep(0.2) return degree_of_focus
def registration(self, grid_points_x=3, grid_points_y=3): """ By default, generate 9 galvo voltage coordinates from (-5,-5) to (5,5), take the camera images of these points, return a function matrix that transforms camera_coordinates into galvo_coordinates using polynomial transform. Parameters ---------- grid_points_x : TYPE, optional DESCRIPTION. The default is 3. grid_points_y : TYPE, optional DESCRIPTION. The default is 3. Returns ------- transformation : TYPE DESCRIPTION. """ galvothread = DAQmission() readinchan = [] x_coords = np.linspace(-10, 10, grid_points_x + 2)[1:-1] y_coords = np.linspace(-10, 10, grid_points_y + 2)[1:-1] xy_mesh = np.reshape(np.meshgrid(x_coords, y_coords), (2, -1), order='F').transpose() galvo_coordinates = xy_mesh camera_coordinates = np.zeros((galvo_coordinates.shape)) for i in range(galvo_coordinates.shape[0]): galvothread.sendSingleAnalog('galvosx', galvo_coordinates[i, 0]) galvothread.sendSingleAnalog('galvosy', galvo_coordinates[i, 1]) time.sleep(1) image = self.cam.SnapImage(0.06) plt.imsave( os.getcwd() + '/CoordinatesManager/Registration_Images/2P/image_' + str(i) + '.png', image) camera_coordinates[i, :] = readRegistrationImages.gaussian_fitting( image) print('Galvo Coordinate') print(galvo_coordinates) print('Camera coordinates') print(camera_coordinates) del galvothread self.cam.Exit() transformation_cam2galvo = CoordinateTransformations.polynomial2DFit( camera_coordinates, galvo_coordinates, order=1) transformation_galvo2cam = CoordinateTransformations.polynomial2DFit( galvo_coordinates, camera_coordinates, order=1) print('Transformation found for x:') print(transformation_cam2galvo[:, :, 0]) print('Transformation found for y:') print(transformation_cam2galvo[:, :, 1]) print('galvo2cam found for x:') print(transformation_galvo2cam[:, :, 0]) print('galvo2cam found for y:') print(transformation_galvo2cam[:, :, 1]) return transformation_cam2galvo