diff --git a/qcodes/utils/qcodes_device_annotator.py b/qcodes/utils/qcodes_device_annotator.py index 997652e652b..7031cf3f971 100644 --- a/qcodes/utils/qcodes_device_annotator.py +++ b/qcodes/utils/qcodes_device_annotator.py @@ -32,17 +32,30 @@ def __init__(self, folder, station): self.setLayout(grid) self.imageCanvas = qt.QLabel() + self.imageCanvas.setToolTip("Left click to insert a label and right click to insert an annotation.") self.loadButton = qt.QPushButton('Load image') - self.labelButton = qt.QRadioButton("Insert Label") - self.labelButton.setChecked(True) - self.annotButton = qt.QRadioButton('Place annotation') self.okButton = qt.QPushButton('Save and close') - + self.removeButton = qt.QPushButton('Remove') + self.removeButton.setToolTip("Remove annotation and label for this parameter") + self.labeltitle = qt.QLabel('Label:') + self.labelfield = qt.QLineEdit() + self.labelfield.setText('') + self.labelfield.setToolTip("String to be used as label. Defaults to instrument_parameter") + self.formattertitle = qt.QLabel('Formatter:') + self.formatterfield = qt.QLineEdit() + self.formatterfield.setText('') + self.formatterfield.setToolTip("Formatter to be used for this parameter:\n" + "Uses new style python formatters. I.e.\n" + "':.4f' standard formatter with 4 digits after the decimal point\n" + "':.2e' exponential formatter with 2 digits after the decimal point\n" + "Leave blank for default. \n" + "See www.pyformat.info for more examples") self.loadButton.clicked.connect(self.loadimage) self.imageCanvas.mousePressEvent = self.set_label_or_annotation self.imageCanvas.setStyleSheet('background-color: white') self.okButton.clicked.connect(self.saveAndClose) + self.removeButton.clicked.connect(self.remove_label_and_annotation) self.treeView = qt.QTreeView() self.model = gui.QStandardItemModel() @@ -51,10 +64,14 @@ def __init__(self, folder, station): self.treeView.setModel(self.model) self.treeView.sortByColumn(0, core.Qt.AscendingOrder) self.treeView.setSortingEnabled(True) + self.treeView.clicked.connect(self.selection_changed) grid.addWidget(self.imageCanvas, 0, 0, 4, 6) grid.addWidget(self.loadButton, 4, 0) - grid.addWidget(self.labelButton, 4, 1) - grid.addWidget(self.annotButton, 4, 2) + grid.addWidget(self.labeltitle, 4, 1) + grid.addWidget(self.labelfield, 4, 2) + grid.addWidget(self.formattertitle, 4, 4) + grid.addWidget(self.formatterfield, 4, 5) + grid.addWidget(self.removeButton, 4, 8) grid.addWidget(self.okButton, 4, 9) grid.addWidget(self.treeView, 0, 6, 4, 4) @@ -95,9 +112,21 @@ def loadimage(self): self.imageCanvas.setMaximumWidth(width) self.imageCanvas.setMaximumHeight(height) - def set_label_or_annotation(self, event): - + def selection_changed(self): + if not self.treeView.selectedIndexes(): + return + selected = self.treeView.selectedIndexes()[0] + selected_instrument = selected.parent().data() + selected_parameter = selected.data() + self.labelfield.setText("{}_{} ".format(selected_instrument, selected_parameter)) + def set_label_or_annotation(self, event): + insertlabel = False + insertannotation = False + if event.button() == core.Qt.LeftButton: + insertlabel = True + elif event.button() == core.Qt.RightButton: + insertannotation = True # verify valid if not self.treeView.selectedIndexes(): return @@ -113,12 +142,29 @@ def set_label_or_annotation(self, event): if selected_parameter not in self._data[selected_instrument].keys(): self._data[selected_instrument][selected_parameter] = {} - if self.labelButton.isChecked(): + if insertlabel: self._data[selected_instrument][selected_parameter]['labelpos'] = (self.click_x, self.click_y) - elif self.annotButton.isChecked(): + self._data[selected_instrument][selected_parameter]['labelstring'] = self.labelfield.text() + elif insertannotation: self._data[selected_instrument][selected_parameter]['annotationpos'] = (self.click_x, self.click_y) - self._data[selected_instrument][selected_parameter]['value'] = 'NaN' + if self.formatterfield.text(): + formatstring = '{' + self.formatterfield.text() + "}" + self._data[selected_instrument][selected_parameter]['annotationformatter'] = formatstring + self._data[selected_instrument][selected_parameter]['value'] = formatstring + else: + self._data[selected_instrument][selected_parameter]['value'] = 'NaN' + + # draw it + self.imageCanvas, _ = self._renderImage(self._data, + self.imageCanvas, + self.filename) + def remove_label_and_annotation(self): + selected = self.treeView.selectedIndexes()[0] + selected_instrument = selected.parent().data() + selected_parameter = selected.data() + if selected_parameter in self._data[selected_instrument].keys(): + self._data[selected_instrument][selected_parameter] = {} # draw it self.imageCanvas, _ = self._renderImage(self._data, self.imageCanvas, @@ -170,13 +216,19 @@ def _renderImage(data, canvas, filename, title=None): title) for instrument, parameters in data.items(): - for parameter, positions in parameters.items(): - - if 'labelpos' in positions: - label_string = "{}_{} ".format(instrument, parameter) - (lx, ly) = positions['labelpos'] - painter.setBrush(gui.QColor(255, 255, 255, 100)) + for parameter, paramsettings in parameters.items(): + if 'labelpos' in paramsettings: + if paramsettings.get('labelstring'): + label_string = paramsettings.get('labelstring') + else: + label_string = "{}_{} ".format(instrument, parameter) + if paramsettings.get('update'): + #parameters that are sweeped should be red. + painter.setBrush(gui.QColor(255, 0, 0, 100)) + else: + painter.setBrush(gui.QColor(255, 255, 255, 100)) + (lx, ly) = paramsettings['labelpos'] textfont = gui.QFont('Decorative', label_size) textwidth = gui.QFontMetrics(textfont).width(label_string) rectangle_start_x = lx - spacing @@ -195,9 +247,9 @@ def _renderImage(data, canvas, filename, title=None): core.Qt.AlignCenter, label_string) - if 'annotationpos' in positions: - (ax, ay) = positions['annotationpos'] - annotationstring = data[instrument][parameter]['value'] + if 'annotationpos' in paramsettings: + (ax, ay) = paramsettings['annotationpos'] + annotationstring = paramsettings['value'] textfont = gui.QFont('Decorative', label_size) textwidth = gui.QFontMetrics(textfont).width(annotationstring) @@ -270,7 +322,7 @@ def loadAnnotations(self): with open(json_filename, 'r') as fid: self._data = json.load(fid) - def updateValues(self, station): + def updateValues(self, station, sweeptparameters=None): """ Update the data with actual voltages from the QDac """ @@ -280,13 +332,19 @@ def updateValues(self, station): value = station.components[instrument][parameter].get_latest() try: floatvalue = float(station.components[instrument][parameter].get_latest()) - if floatvalue > 1000 or floatvalue < 0.1: + if self._data[instrument][parameter].get('annotationformatter'): + valuestr = self._data[instrument][parameter].get('annotationformatter').format(floatvalue) + elif floatvalue > 1000 or floatvalue < 0.1: valuestr = "{:.2e}".format(floatvalue) else: valuestr = "{:.2f}".format(floatvalue) except (ValueError, TypeError): valuestr = str(value) self._data[instrument][parameter]['value'] = valuestr + if sweeptparameters: + for sweeptparameter in sweeptparameters: + if sweeptparameter._instrument.name == instrument and sweeptparameter.name == parameter: + self._data[instrument][parameter]['update'] = True def makePNG(self, counter, path=None, title=None): """ diff --git a/qcodes/utils/wrappers.py b/qcodes/utils/wrappers.py index 02eeca6906b..11c62f24195 100644 --- a/qcodes/utils/wrappers.py +++ b/qcodes/utils/wrappers.py @@ -218,11 +218,11 @@ def _create_plot(i, name, data, counter_two): -def save_device_image(): +def save_device_image(sweeptparameters): counter = CURRENT_EXPERIMENT['provider'].counter title = "{} #{:03d}".format(CURRENT_EXPERIMENT["sample_name"], counter) di = CURRENT_EXPERIMENT['device_image'] - di.updateValues(CURRENT_EXPERIMENT['station']) + di.updateValues(CURRENT_EXPERIMENT['station'], sweeptparameters) log.debug(os.path.join(CURRENT_EXPERIMENT["exp_folder"], '{:03d}'.format(counter))) @@ -267,7 +267,7 @@ def do1d(inst_set, start, stop, num_points, delay, *inst_meas): _save_individual_plots(data, plottables) if CURRENT_EXPERIMENT.get('device_image'): log.debug('Saving device image') - save_device_image() + save_device_image((inst_set,)) # add the measurement ID to the logfile with open(CURRENT_EXPERIMENT['logfile'], 'a') as fid: @@ -314,7 +314,7 @@ def do1dDiagonal(inst_set, inst2_set, start, stop, num_points, delay, start2, sl _save_individual_plots(data, plottables) pdfplot.save("{}.pdf".format(plot.get_default_title())) if CURRENT_EXPERIMENT.get('device_image'): - save_device_image() + save_device_image((inst_set, inst2_set)) # add the measurement ID to the logfile with open(CURRENT_EXPERIMENT['logfile'], 'a') as fid: @@ -367,7 +367,7 @@ def do2d(inst_set, start, stop, num_points, delay, inst_set2, start2, stop2, num _save_individual_plots(data, plottables) pdfplot.save("{}.pdf".format(plot.get_default_title())) if CURRENT_EXPERIMENT.get('device_image'): - save_device_image() + save_device_image((inst_set, inst_set2)) # add the measurement ID to the logfile with open(CURRENT_EXPERIMENT['logfile'], 'a') as fid: