def main(camera): app = Qt.QApplication([]) t = ParameterTree() t.resize(600, 800) t.show() def value_changed(param, value): try: setattr(camera, param.name(), value) except Exception as err: Qt.QMessageBox.critical(None, "Error setting {}".format(param.name()), repr(err)) def connect(param, slot): param.sigValueChanged.connect(slot) for child in param.children(): connect(child, slot) with camera: t.setWindowTitle(camera.device_info.GetFriendlyName()) data = parameter_dict(camera) # limits are dynamic (ex: max offset-x depends on current value # of width). strip_limits(data) p = Parameter.create(**data) t.setParameters(p, showTop=False) connect(p, value_changed) app.exec_()
class GuiMetadata(HasPyQtGraphParams): """General class for a group of metadata that can be controlled via a GUI. Parameters ---------- Returns ------- """ def __init__(self): super().__init__() self.protocol_params_tree = ParameterTree(showHeader=False) def get_param_dict(self): """ Return values of the parameters. Returns ------- OrderedDict with the params values """ return self.params.getValues() def show_metadata_gui(self): """ Create and return a ParameterTree window (documented `here <http://www.pyqtgraph.org/documentation/parametertree/index.html/>`_ ) Returns ------- ParameterTree object to control the metadata """ self.protocol_params_tree = ParameterTree(showHeader=False) self.protocol_params_tree.setParameters(self.params) self.protocol_params_tree.setWindowTitle("Metadata") self.protocol_params_tree.resize(450, 600) # TODO figure out this window return self.protocol_params_tree
#}}} qt_mav = QtMav(outdevice, indevice) # create gui app = QtGui.QApplication(sys.argv) f = open("tuner_ui.py.tmp", "w") uic.compileUi("tuner.ui", f) tuner = uic.loadUi("tuner.ui") params = [] parameter = Parameter(name='params', type='group', children=params) parameter_tree = ParameterTree(parent=tuner.tabTime) parameter_tree.setParameters(parameter, showTop=False) parameter_tree.resize(300, 500) def get_group_index(params, gname): #{{{ """ recursive group refreshing/adding params -- parameters structure gname -- string representing name return: index in params structure -1 if not found """ i = 0 for g in params: if g['name'] == gname: return i
state = p.saveState() def restore(): global state add = p['Save/Restore functionality', 'Restore State', 'Add missing items'] rem = p['Save/Restore functionality', 'Restore State', 'Remove extra items'] p.restoreState(state, addChildren=add, removeChildren=rem) p.param('Save/Restore functionality', 'Save State').sigActivated.connect(save) p.param('Save/Restore functionality', 'Restore State').sigActivated.connect(restore) ## Create two ParameterTree widgets, both accessing the same data t = ParameterTree() t.setParameters(p, showTop=False) t.show() t.resize(400,800) t2 = ParameterTree() t2.setParameters(p, showTop=False) t2.show() t2.resize(400,800) ## test save/restore s = p.saveState() p.restoreState(s) ## Start Qt event loop unless running in interactive mode or using pyside. if __name__ == '__main__': import sys if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'): QtGui.QApplication.instance().exec_()
'name': 'TextParam', 'type': 'text', 'value': 'Some text...' }, ] #p = pTypes.ParameterSet("params", params) p = Parameter(name='params', type='group', children=params) def change(param, changes): print "tree changes:" for param, change, data in changes: print " [" + '.'.join(p.childPath(param)) + "] ", change, data p.sigTreeStateChanged.connect(change) t = ParameterTree() t.setParameters(p, showTop=False) t.show() t.resize(400, 600) t2 = ParameterTree() t2.setParameters(p, showTop=False) t2.show() t2.resize(400, 600) import sys if sys.flags.interactive == 0: app.exec_()
qt_mav = QtMav(outdevice, indevice) # create gui app = QtGui.QApplication(sys.argv) f = open("tuner_ui.py.tmp", "w") uic.compileUi("tuner.ui", f) tuner = uic.loadUi("tuner.ui") params = [] parameter = Parameter(name='params', type='group', children=params) parameter_tree = ParameterTree(parent=tuner.tabTime) parameter_tree.setParameters(parameter, showTop=False) parameter_tree.resize(300, 500) def get_group_index(params, gname):#{{{ """ recursive group refreshing/adding params -- parameters structure gname -- string representing name return: index in params structure -1 if not found """ i = 0 for g in params: if g['name'] == gname: return i i += 1
class ProtocolControlWidget(QWidget): """GUI for controlling a ProtocolRunner. This class implements: - selection box of the Protocol to be run; - window for controlling Protocol parameters; - toggle button for starting/stopping the Protocol; - progress bar to display progression of the Protocol. Parameters ---------- protocol_runner: :class:`ProtocolRunner <stytra.stimulation.ProtocolRunner>` object ProtocolRunner that is controlled by the GUI. **Signals** """ sig_start_protocol = pyqtSignal() """ Emitted via the toggle button click, meant to start the protocol """ sig_stop_protocol = pyqtSignal() """ Emitted via the toggle button click, meant to abort the protocol""" def __init__(self, protocol_runner=None, *args): """ """ super().__init__(*args) self.protocol_runner = protocol_runner # Create parametertree for protocol parameter control self.protocol_params_tree = ParameterTree(showHeader=False) # Layout for selecting the protocol: self.lyt_prot_selection = QHBoxLayout() # Dropdown menu with the protocol classes found in the Experiment: self.combo_prot = QComboBox() self.combo_prot.addItems( list(self.protocol_runner.prot_class_dict.keys())) self.combo_prot.currentIndexChanged.connect(self.set_protocol) self.lyt_prot_selection.addWidget(self.combo_prot) # Window with the protocol parameters: self.protocol_params_butt = QPushButton("Protocol parameters") self.protocol_params_butt.clicked.connect(self.show_stim_params_gui) self.lyt_prot_selection.addWidget(self.protocol_params_butt) # Layout for protocol start and progression report: self.lyt_run = QHBoxLayout() # Button for startup: self.button_toggle_prot = QPushButton("▶") self.button_toggle_prot.clicked.connect(self.toggle_protocol_running) self.lyt_run.addWidget(self.button_toggle_prot) # Progress bar for monitoring the protocol: self.progress_bar = QProgressBar() self.progress_bar.setFormat("%p% %v/%m") self.lyt_run.addWidget(self.progress_bar) # Global layout: self.lyt = QVBoxLayout() self.lyt.setContentsMargins(0, 0, 0, 0) self.lyt.addLayout(self.lyt_run) self.lyt.addLayout(self.lyt_prot_selection) self.setLayout(self.lyt) self.timer = None # Connect events and signals from the ProtocolRunner to update the GUI: self.protocol_runner.sig_protocol_updated.connect( self.update_stim_duration) self.protocol_runner.sig_timestep.connect(self.update_progress) self.protocol_runner.sig_protocol_started.connect(self.toggle_icon) self.protocol_runner.sig_protocol_finished.connect(self.toggle_icon) self.protocol_runner.sig_protocol_updated.connect( self.update_stim_duration) # If a previous protocol was already set in the protocol runner # change the GUI values accordingly: if protocol_runner.protocol is not None: self.combo_prot.setCurrentText(protocol_runner.protocol.name) else: self.set_protocol() def show_stim_params_gui(self): """Create and show window to update protocol parameters. """ if self.protocol_runner.protocol.params is not None: self.protocol_params_tree.setParameters( self.protocol_runner.protocol.params) self.protocol_params_tree.show() self.protocol_params_tree.setWindowTitle("Protocol parameters") self.protocol_params_tree.resize(300, 600) def toggle_protocol_running(self): """Emit the start and stop signals. These can be used in the Experiment class or directly connected with the respective ProtocolRunner start() and stop() methods. Parameters ---------- Returns ------- """ # Start/stop the protocol: if not self.protocol_runner.running: self.sig_start_protocol.emit() else: self.sig_stop_protocol.emit() self.toggle_icon() def toggle_icon(self): """Change the play/stop icon of the GUI. """ if self.button_toggle_prot.text() == "■": self.button_toggle_prot.setText("▶") self.progress_bar.setValue(0) else: self.button_toggle_prot.setText("■") def update_stim_duration(self): """ """ self.progress_bar.setMaximum(int(self.protocol_runner.duration)) self.progress_bar.setValue(0) def update_progress(self): """ """ self.progress_bar.setValue(int(self.protocol_runner.t)) def set_protocol(self): """Use value in the dropdown menu to change the protocol. """ protocol_name = self.combo_prot.currentText() self.protocol_runner.set_new_protocol(protocol_name) self.button_toggle_prot.setEnabled(True)
class CameraViewWidget(QWidget): """A widget to show images from a frame source and display the camera controls. ***It does not implement a frame dispatcher by itself so it may lag behind the camera at high frame rates!*** Parameters ---------- Returns ------- """ def __init__(self, experiment=None, camera=None): """ :param experiment: experiment to which this belongs (:class:Experiment <stytra.Experiment> object) """ super().__init__() self.experiment = experiment if experiment is not None: self.camera = experiment.camera experiment.gui_timer.timeout.connect(self.update_image) else: self.camera = camera self.gui_timer = QTimer() self.gui_timer.setSingleShot(False) self.control_params = CameraControlParameters() # Create the layout for the camera view: self.camera_display_widget = pg.GraphicsLayoutWidget() # Display area for showing the camera image: self.display_area = pg.ViewBox(lockAspect=1, invertY=False) self.display_area.setRange( QRectF(0, 0, 640, 640), update=True, disableAutoRange=True ) # Image to which the frame will be set, initially black: self.image_item = pg.ImageItem() self.image_item.setImage(np.zeros((640, 480), dtype=np.uint8)) self.display_area.addItem(self.image_item) self.camera_display_widget.addItem(self.display_area) # Queue of frames coming from the camera if hasattr(experiment, "frame_dispatcher"): self.frame_queue = self.experiment.frame_dispatcher.gui_queue else: self.frame_queue = self.camera.frame_queue # Queue of control parameters for the camera: self.control_queue = self.camera.control_queue self.camera_rotation = self.camera.rotation self.camera_params_tree = ParameterTree(showHeader=False) # Connect changes in the camera parameters: for c in self.control_params.params.children(): c.sigValueChanged.connect(self.update_controls) self.layout = QVBoxLayout() self.layout.setContentsMargins(0, 0, 0, 0) self.layout.addWidget(self.camera_display_widget) self.layout_control = QHBoxLayout() if self.control_queue is not None: self.params_button = QPushButton("Camera params") self.params_button.clicked.connect(self.show_params_gui) self.layout_control.addWidget(self.params_button) self.captureButton = QPushButton("Capture frame") self.captureButton.clicked.connect(self.save_image) self.layout_control.addWidget(self.captureButton) self.layout.addLayout(self.layout_control) self.current_image = None self.setLayout(self.layout) def update_controls(self, value): """ Parameters ---------- value : Parameter object that have changed Returns ------- """ # Put in the queue tuple with name and new value of the parameter: self.control_queue.put((value.name(), value.value())) def update_image(self): """Update displayed frame while emptying frame source queue. This is done through a while loop that takes all available frames at every update. # TODO fix this somehow? **Important!** if the input queue is too fast this will produce an infinite loop and block the interface! Parameters ---------- Returns ------- """ first = True while True: try: # In this way, the frame displayed is actually the most # recent one added to the queue, as a queue is FILO: if first: time, self.current_image = self.frame_queue.get(timeout=0.0001) first = False else: # Else, get to free the queue: _, _ = self.frame_queue.get(timeout=0.001) except Empty: break # Once obtained current image, display it: if self.current_image is not None: self.image_item.setImage(self.current_image) def save_image(self): """Save a frame to the current directory.""" timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") imsave( self.experiment.filename_base() + timestamp + "_img.png", self.image_item.image, ) def show_params_gui(self): """ """ self.camera_params_tree.setParameters(self.control_params.params) self.camera_params_tree.show() self.camera_params_tree.setWindowTitle("Camera parameters") self.camera_params_tree.resize(450, 600)
]) ]}, {'name': 'Param 5', 'type': 'bool', 'value': True, 'tip': "This is a checkbox"}, {'name': 'Param 6', 'type': 'color', 'value': "FF0", 'tip': "This is a color button. It cam be renamed.", 'renamable': True}, {'name': 'TextParam', 'type': 'text', 'value': 'Some text...'}, ] #p = pTypes.ParameterSet("params", params) p = Parameter(name='params', type='group', children=params) def change(param, changes): print "tree changes:" for param, change, data in changes: print " [" + '.'.join(p.childPath(param))+ "] ", change, data p.sigTreeStateChanged.connect(change) t = ParameterTree() t.setParameters(p, showTop=False) t.show() t.resize(400,600) t2 = ParameterTree() t2.setParameters(p, showTop=False) t2.show() t2.resize(400,600) import sys if sys.flags.interactive == 0: app.exec_()
def restore(): global state add = p['Save/Restore functionality', 'Restore State', 'Add missing items'] rem = p['Save/Restore functionality', 'Restore State', 'Remove extra items'] p.restoreState(state, addChildren=add, removeChildren=rem) p.param('Save/Restore functionality', 'Save State').sigActivated.connect(save) p.param('Save/Restore functionality', 'Restore State').sigActivated.connect(restore) ## Create two ParameterTree widgets, both accessing the same data t = ParameterTree() t.setParameters(p, showTop=False) t.show() t.setWindowTitle('pyqtgraph example: Parameter Tree') t.resize(400,800) t2 = ParameterTree() t2.setParameters(p, showTop=False) t2.show() t2.resize(400,800) ## test save/restore s = p.saveState() p.restoreState(s) ## Start Qt event loop unless running in interactive mode or using pyside. if __name__ == '__main__': import sys if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'): QtGui.QApplication.instance().exec_()