Completed
Push — pulsed_with_queued_connections ( b02de1...6b1460 )
by
unknown
03:27
created

ODMRGui.odmr_started()   A

Complexity

Conditions 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
c 0
b 0
f 0
dl 0
loc 5
rs 9.4285
1
# -*- coding: utf-8 -*-
2
"""
3
This file contains the Qudi GUI module for ODMR control.
4
5
Qudi is free software: you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation, either version 3 of the License, or
8
(at your option) any later version.
9
10
Qudi is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License
16
along with Qudi. If not, see <http://www.gnu.org/licenses/>.
17
18
Copyright (c) the Qudi Developers. See the COPYRIGHT.txt file at the
19
top-level directory of this distribution and at <https://github.com/Ulm-IQO/qudi/>
20
"""
21
22
23
from qtpy import QtCore
24
from qtpy import QtWidgets
25
from qtpy import uic
26
import pyqtgraph as pg
27
import numpy as np
28
import os
29
30
from gui.guibase import GUIBase
31
from gui.guiutils import ColorBar
32
from gui.colordefs import ColorScaleInferno
33
from gui.colordefs import QudiPalettePale as palette
34
from gui.fitsettings import FitSettingsWidget
35
from core.util import units
36
37
class ODMRMainWindow(QtWidgets.QMainWindow):
38
    def __init__(self):
39
        # Get the path to the *.ui file
40
        this_dir = os.path.dirname(__file__)
41
        ui_file = os.path.join(this_dir, 'ui_odmrgui.ui')
42
43
        # Load it
44
        super(ODMRMainWindow, self).__init__()
45
        uic.loadUi(ui_file, self)
46
        self.show()
47
48
class ODMRSettingDialog(QtWidgets.QDialog):
49
    def __init__(self):
50
        # Get the path to the *.ui file
51
        this_dir = os.path.dirname(__file__)
52
        ui_file = os.path.join(this_dir, 'ui_odmr_settings.ui')
53
54
        # Load it
55
        super(ODMRSettingDialog, self).__init__()
56
        uic.loadUi(ui_file, self)
57
58
class ODMRGui(GUIBase):
59
    """
60
    This is the GUI Class for ODMR
61
    """
62
63
    _modclass = 'ODMRGui'
64
    _modtype = 'gui'
65
66
    # declare connectors
67
    _in = {'odmrlogic1': 'ODMRLogic',
68
           'savelogic': 'SaveLogic'}
69
70
    sigStartODMRScan = QtCore.Signal()
71
    sigStopODMRScan = QtCore.Signal()
72
    sigContinueODMRScan = QtCore.Signal()
73
    sigClearPlots = QtCore.Signal()
74
    sigMWOn = QtCore.Signal()
75
    sigMWOff = QtCore.Signal()
76
    sigMWPowerChanged = QtCore.Signal(float)
77
    sigMWFreqChanged = QtCore.Signal(float)
78
79
    def __init__(self, config, **kwargs):
80
        super().__init__(config=config, **kwargs)
81
82
        self.log.info('The following configuration was found.')
83
84
        # checking for the right configuration
85
        for key in config.keys():
86
            self.log.info('{0}: {1}'.format(key, config[key]))
87
88
    def on_activate(self, e=None):
89
        """ Definition, configuration and initialisation of the ODMR GUI.
90
91
        @param object e: Fysom.event object from Fysom class.
92
                         An object created by the state machine module Fysom,
93
                         which is connected to a specific event (have a look in
94
                         the Base Class). This object contains the passed event,
95
                         the state before the event happened and the destination
96
                         of the state which should be reached after the event
97
                         had happened.
98
99
        This init connects all the graphic modules, which were created in the
100
        *.ui file and configures the event handling between the modules.
101
        """
102
103
        self._odmr_logic = self.get_in_connector('odmrlogic1')
104
        self._save_logic = self.get_in_connector('savelogic')
105
106
        # Use the inherited class 'Ui_ODMRGuiUI' to create now the
107
        # GUI element:
108
        self._mw = ODMRMainWindow()
109
        self._sd = ODMRSettingDialog()
110
111
        # Adjust range of scientific spinboxes above what is possible in Qt Designer
112
        self._mw.frequency_DoubleSpinBox.setMaximum(100e9)
113
        self._mw.start_freq_DoubleSpinBox.setMaximum(100e9)
114
        self._mw.step_freq_DoubleSpinBox.setMaximum(100e9)
115
        self._mw.stop_freq_DoubleSpinBox.setMaximum(100e9)
116
117
        # Add save file tag input box
118
        self._mw.save_tag_LineEdit = QtWidgets.QLineEdit(self._mw)
119
        self._mw.save_tag_LineEdit.setMaximumWidth(200)
120
        self._mw.save_tag_LineEdit.setToolTip(
121
            'Enter a nametag which will be\nadded to the filename.')
122
        self._mw.save_ToolBar.addWidget(self._mw.save_tag_LineEdit)
123
124
        # add a clear button to clear the ODMR plots:
125
        self._mw.clear_odmr_PushButton = QtWidgets.QPushButton(self._mw)
126
        self._mw.clear_odmr_PushButton.setText('Clear ODMR')
127
        self._mw.clear_odmr_PushButton.setToolTip(
128
            'Clear the plots of the\ncurrent ODMR measurements.')
129
        self._mw.clear_odmr_PushButton.setEnabled(False)
130
        self._mw.save_ToolBar.addWidget(self._mw.clear_odmr_PushButton)
131
        self.sigClearPlots.connect(self._odmr_logic.clear_odmr_plots)
132
133
        # Get the image from the logic
134
        self.odmr_matrix_image = pg.ImageItem(self._odmr_logic.ODMR_plot_xy.transpose())
135
        self.odmr_matrix_image.setRect(
136
            QtCore.QRectF(
137
                self._odmr_logic.mw_start,
138
                0,
139
                self._odmr_logic.mw_stop - self._odmr_logic.mw_start,
140
                self._odmr_logic.number_of_lines
141
            ))
142
143
        self.odmr_image = pg.PlotDataItem(
144
            self._odmr_logic.ODMR_plot_x,
145
            self._odmr_logic.ODMR_plot_y,
146
            pen=pg.mkPen(palette.c1, style=QtCore.Qt.DotLine),
147
            symbol='o',
148
            symbolPen=palette.c1,
149
            symbolBrush=palette.c1,
150
            symbolSize=7
151
        )
152
153
        self.odmr_fit_image = pg.PlotDataItem(
154
            self._odmr_logic.ODMR_fit_x,
155
            self._odmr_logic.ODMR_fit_y,
156
            pen=pg.mkPen(palette.c2)
157
        )
158
159
        # Add the display item to the xy and xz VieWidget, which was defined in
160
        # the UI file.
161
        self._mw.odmr_PlotWidget.addItem(self.odmr_image)
162
        self._mw.odmr_PlotWidget.setLabel(axis='left', text='Counts',
163
                                          units='Counts/s')
164
        self._mw.odmr_PlotWidget.setLabel(axis='bottom', text='Frequency',
165
                                          units='Hz')
166
167
        #self._mw.odmr_PlotWidget.addItem(self.odmr_fit_image)
168
        self._mw.odmr_matrix_PlotWidget.addItem(self.odmr_matrix_image)
169
        self._mw.odmr_matrix_PlotWidget.setLabel(axis='left',
170
                                                 text='Matrix Lines',
171
                                                 units='#')
172
        self._mw.odmr_matrix_PlotWidget.setLabel(axis='bottom', text='Frequency',
173
                                                 units='Hz')
174
175
        self._mw.odmr_PlotWidget.showGrid(x=True, y=True, alpha=0.8)
176
177
        # Get the colorscales at set LUT
178
        my_colors = ColorScaleInferno()
179
        self.odmr_matrix_image.setLookupTable(my_colors.lut)
180
181
        # Set the state button as ready button as default setting.
182
        # self._mw.idle_StateWidget.click()
183
184
        # Configuration of the comboWidget
185
        self._mw.mode_ComboBox.addItem('Off')
186
        self._mw.mode_ComboBox.addItem('CW')
187
188
        fit_functions = self._odmr_logic.get_fit_functions()
189
        self._mw.fit_methods_ComboBox.clear()
190
        self._mw.fit_methods_ComboBox.addItems(fit_functions)
191
192
        ########################################################################
193
        ##                 Configuration of the Colorbar                      ##
194
        ########################################################################
195
196
        self.odmr_cb = ColorBar(my_colors.cmap_normed, 100, 0, 100000)
197
198
        #adding colorbar to ViewWidget
199
        self._mw.odmr_cb_PlotWidget.addItem(self.odmr_cb)
200
        self._mw.odmr_cb_PlotWidget.hideAxis('bottom')
201
        self._mw.odmr_cb_PlotWidget.hideAxis('left')
202
        self._mw.odmr_cb_PlotWidget.setLabel('right', 'Fluorescence', units='counts/s')
203
204
        # Connect the buttons and inputs for the odmr colorbar
205
        self._mw.odmr_cb_manual_RadioButton.clicked.connect(self.refresh_matrix)
206
        self._mw.odmr_cb_centiles_RadioButton.clicked.connect(self.refresh_matrix)
207
208
209
        ########################################################################
210
        ##          Configuration of the various display Widgets              ##
211
        ########################################################################
212
213
        # Take the default values from logic:
214
        self._mw.frequency_DoubleSpinBox.setValue(self._odmr_logic.mw_frequency)
215
        self._mw.start_freq_DoubleSpinBox.setValue(self._odmr_logic.mw_start)
216
217
        self._mw.step_freq_DoubleSpinBox.setValue(self._odmr_logic.mw_step)
218
        self._mw.step_freq_DoubleSpinBox.setOpts(minStep=1.0) # set the minimal step to 1Hz.
219
220
        self._mw.stop_freq_DoubleSpinBox.setValue(self._odmr_logic.mw_stop)
221
222
        self._mw.power_DoubleSpinBox.setValue(self._odmr_logic.mw_power)
223
        self._mw.power_DoubleSpinBox.setOpts(minStep=0.1)
224
225
        self._mw.runtime_DoubleSpinBox.setValue(self._odmr_logic.run_time)
226
        self._mw.elapsed_time_DisplayWidget.display(int(self._odmr_logic.elapsed_time))
227
228
        self._sd.matrix_lines_SpinBox.setValue(self._odmr_logic.number_of_lines)
229
        self._sd.clock_frequency_DoubleSpinBox.setValue(self._odmr_logic._clock_frequency)
230
        self._sd.fit_tabs = {}
231
        for name, model in self._odmr_logic.fit_models.items():
232
            try:
233
                self._sd.fit_tabs[name] = FitSettingsWidget(model[1])
234
            except:
235
                self.log.warning('Could not load fitmodel {0}'.format(name))
236
            else:
237
                self._sd.tabWidget.addTab(self._sd.fit_tabs[name], name)
238
239
        # Update the inputed/displayed numbers if return key is hit:
240
241
        # If the attribute setKeyboardTracking is set in a SpinBox or
242
        # DoubleSpinBox the valueChanged method will actually hold on the signal
243
        #  until the return key is pressed which is pretty useful ;)
244
245
        # self._mw.frequency_DoubleSpinBox.setKeyboardTracking(False)
246
247
        # Update the inputed/displayed numbers if the cursor has left the field:
248
249
        self._mw.frequency_DoubleSpinBox.editingFinished.connect(self.change_frequency)
250
        self._mw.start_freq_DoubleSpinBox.editingFinished.connect(self.change_start_freq)
251
        self._mw.step_freq_DoubleSpinBox.editingFinished.connect(self.change_step_freq)
252
        self._mw.stop_freq_DoubleSpinBox.editingFinished.connect(self.change_stop_freq)
253
        self._mw.power_DoubleSpinBox.editingFinished.connect(self.change_power)
254
        self._mw.runtime_DoubleSpinBox.editingFinished.connect(self.change_runtime)
255
256
        self._mw.odmr_cb_max_DoubleSpinBox.valueChanged.connect(self.refresh_matrix)
257
        self._mw.odmr_cb_min_DoubleSpinBox.valueChanged.connect(self.refresh_matrix)
258
        self._mw.odmr_cb_high_percentile_DoubleSpinBox.valueChanged.connect(self.refresh_matrix)
259
        self._mw.odmr_cb_low_percentile_DoubleSpinBox.valueChanged.connect(self.refresh_matrix)
260
261
        ########################################################################
262
        ##                       Connect signals                              ##
263
        ########################################################################
264
265
        # Connect the RadioButtons and connect to the events if they are clicked:
266
        self._mw.action_run_stop.toggled.connect(self.run_stop)
267
        self._mw.action_resume_odmr.toggled.connect(self.resume_odmr)
268
        self._mw.action_Save.triggered.connect(self.save_data)
269
        self.sigStartODMRScan.connect(self._odmr_logic.start_odmr_scan)
270
        self.sigStopODMRScan.connect(self._odmr_logic.stop_odmr_scan)
271
        self.sigContinueODMRScan.connect(self._odmr_logic.continue_odmr_scan)
272
273
        self.sigMWOn.connect(self._odmr_logic.MW_on)
274
        self.sigMWOff.connect(self._odmr_logic.MW_off)
275
        self.sigMWFreqChanged.connect(self._odmr_logic.set_frequency)
276
        self.sigMWPowerChanged.connect(self._odmr_logic.set_power)
277
278
        # react on an axis change in the logic by adapting the display:
279
        self._odmr_logic.sigODMRMatrixAxesChanged.connect(self.update_matrix_axes)
280
281
        # connect the clear button:
282
        self._mw.clear_odmr_PushButton.clicked.connect(self.clear_odmr_plots_clicked)
283
284
        self._odmr_logic.sigOdmrPlotUpdated.connect(self.refresh_plot)
285
        self._odmr_logic.sigOdmrFitUpdated.connect(self.refresh_plot_fit)
286
        self._odmr_logic.sigOdmrMatrixUpdated.connect(self.refresh_matrix)
287
        self._odmr_logic.sigOdmrElapsedTimeChanged.connect(self.refresh_elapsedtime)
288
        # connect settings signals
289
        self._mw.action_Settings.triggered.connect(self.menu_settings)
290
        self._sd.accepted.connect(self.update_settings)
291
        self._sd.rejected.connect(self.reject_settings)
292
        self._sd.buttonBox.button(QtWidgets.QDialogButtonBox.Apply).clicked.connect(self.update_settings)
293
        self.reject_settings()
294
        # Connect stop odmr
295
        self._odmr_logic.sigOdmrStarted.connect(self.odmr_started)
296
        self._odmr_logic.sigOdmrStopped.connect(self.odmr_stopped)
297
        # Combo Widget
298
        self._mw.mode_ComboBox.activated[str].connect(self.mw_stop)
299
        self._mw.fit_methods_ComboBox.activated[str].connect(self.update_fit_variable)
300
        # Push Buttons
301
        self._mw.do_fit_PushButton.clicked.connect(self.update_fit)
302
303
        # let the gui react on the signals from the GUI
304
        self._odmr_logic.sigMicrowaveCWModeChanged.connect(self.update_cw_display)
305
        self._odmr_logic.sigMicrowaveListModeChanged.connect(self.update_run_stop_display)
306
307
        # Show the Main ODMR GUI:
308
        self._mw.show()
309
310
    def on_deactivate(self, e):
311
        """ Reverse steps of activation
312
313
        @param object e: Fysom.event object from Fysom class. A more detailed
314
                         explanation can be found in the method initUI.
315
316
        @return int: error code (0:OK, -1:error)
317
        """
318
        self._mw.close()
319
        return 0
320
321
    def show(self):
322
        """Make window visible and put it above all other windows. """
323
        QtWidgets.QMainWindow.show(self._mw)
324
        self._mw.activateWindow()
325
        self._mw.raise_()
326
327
    def run_stop(self, is_checked):
328
        """ Manages what happens if odmr scan is started/stopped. """
329
        if is_checked:
330
            # change the axes appearance according to input values:
331
            self.sigStopODMRScan.emit()
332
            self.sigStartODMRScan.emit()
333
            self._mw.action_run_stop.setEnabled(False)
334
            self._mw.action_resume_odmr.setEnabled(False)
335
            self._mw.odmr_PlotWidget.removeItem(self.odmr_fit_image)
336
337
            # during scan, enable the clear plot possibility.
338
            self._mw.clear_odmr_PushButton.setEnabled(True)
339
        else:
340
            self.sigStopODMRScan.emit()
341
            self._mw.action_run_stop.setEnabled(False)
342
            self._mw.action_resume_odmr.setEnabled(False)
343
            # Disable the clear functionality since that is not needed if no
344
            # scan is running:
345
            self._mw.clear_odmr_PushButton.setEnabled(False)
346
347
    def update_cw_display(self, cw_on):
348
        """ Update the display for the cw state of the microwave.
349
350
        @param bool cw_on: for True the mw on display will be shown, otherwise
351
                           mw off will be displayed.
352
        """
353
        if cw_on:
354
            # # prevent any triggering, which results from changing the state of
355
            # # the combobox:
356
            # self._mw.mode_ComboBox.blockSignals(True)
357
            text = 'CW'
358
        else:
359
            text = 'Off'
360
361
        index = self._mw.mode_ComboBox.findText(text, QtCore.Qt.MatchFixedString)
362
        if index >= 0:
363
            self._mw.mode_ComboBox.setCurrentIndex(index)
364
        else:
365
            self.log.warning('No proper state to display was found in the combobox!')
366
367
    def update_run_stop_display(self, run_odmr):
368
        """ Update the display for the odmr measurement.
369
370
        @param bool run_odmr: True indicates that the measurement is running and
371
                              False that it is stopped.
372
        """
373
374
        if run_odmr:
375
            self._mw.action_resume_odmr.setEnabled(False)
376
            self._mw.clear_odmr_PushButton.setEnabled(True)
377
        else:
378
            self._mw.action_resume_odmr.setEnabled(True)
379
            self._mw.clear_odmr_PushButton.setEnabled(False)
380
381
    def resume_odmr(self, is_checked):
382
        if is_checked:
383
            self.sigStopODMRScan.emit()
384
            self.sigContinueODMRScan.emit()
385
            self._mw.action_run_stop.setEnabled(False)
386
387
            # during scan, enable the clear plot possibility.
388
            self._mw.clear_odmr_PushButton.setEnabled(True)
389
        else:
390
            self.sigStopODMRScan.emit()
391
            self._mw.action_run_stop.setEnabled(True)
392
            # Disable the clear functionality since that is not needed if no
393
            # scan is running:
394
            self._mw.clear_odmr_PushButton.setEnabled(False)
395
396
    def odmr_started(self):
397
        """ Switch the run/stop button to stop after receiving an odmsStarted
398
                    signal """
399
        self._mw.action_run_stop.setEnabled(True)
400
        self._mw.action_resume_odmr.setEnabled(False)
401
402
    def odmr_stopped(self):
403
        """ Switch the run/stop button to stop after receiving an odmr_stoped
404
            signal """
405
        self._mw.action_run_stop.setChecked(False)
406
        self._mw.action_resume_odmr.setChecked(False)
407
        self._mw.action_run_stop.setEnabled(True)
408
        self._mw.action_resume_odmr.setEnabled(True)
409
410
    def clear_odmr_plots_clicked(self):
411
        """ Clear the ODMR plots. """
412
        self.sigClearPlots.emit()
413
414
    def menu_settings(self):
415
        """ Open the settings menu """
416
        self._sd.exec_()
417
418
    def refresh_plot(self):
419
        """ Refresh the xy-plot image """
420
        self.odmr_image.setData(self._odmr_logic.ODMR_plot_x,
421
                                self._odmr_logic.ODMR_plot_y)
422
423
    def refresh_plot_fit(self):
424
        """ Refresh the xy fit plot image. """
425
426
        if not self._mw.fit_methods_ComboBox.currentText() == 'No Fit':
427
            self.odmr_fit_image.setData(x=self._odmr_logic.ODMR_fit_x,
428
                                        y=self._odmr_logic.ODMR_fit_y)
429
        else:
430
            if self.odmr_fit_image in self._mw.odmr_PlotWidget.listDataItems():
431
                self._mw.odmr_PlotWidget.removeItem(self.odmr_fit_image)
432
433
    def refresh_matrix(self):
434
        """ Refresh the xy-matrix image """
435
        odmr_image_data = self._odmr_logic.ODMR_plot_xy.transpose()
436
437
        cb_range = self.get_matrix_cb_range()
438
439
        # Now update image with new color scale, and update colorbar
440
        self.odmr_matrix_image.setImage(image=odmr_image_data,
441
                                        levels=(cb_range[0], cb_range[1])
442
                                        )
443
        self.refresh_odmr_colorbar()
444
445
    def update_matrix_axes(self):
446
        """ Adjust the x and y axes in the image according to the input. """
447
448
        self.odmr_matrix_image.setRect(
449
            QtCore.QRectF(
450
                self._odmr_logic.mw_start,
451
                0,
452
                self._odmr_logic.mw_stop - self._odmr_logic.mw_start,
453
                self._odmr_logic.number_of_lines
454
            ))
455
456
    def refresh_odmr_colorbar(self):
457
        """ Update the colorbar to a new scaling.
458
459
        Calls the refresh method from colorbar.
460
        """
461
        cb_range = self.get_matrix_cb_range()
462
        self.odmr_cb.refresh_colorbar(cb_range[0], cb_range[1])
463
464
        self._mw.odmr_cb_PlotWidget.update()  # TODO: Is this necessary?  It is not in refresh_xy_colorbar in confocal gui
465
466
    def get_matrix_cb_range(self):
467
        """ Determines the cb_min and cb_max values for the matrix plot
468
        """
469
        matrix_image = self.odmr_matrix_image.image
470
471
        # If "Manual" is checked or the image is empty (all zeros), then take manual cb range.
472
        if self._mw.odmr_cb_manual_RadioButton.isChecked() or np.max(matrix_image) == 0.0:
473
            cb_min = self._mw.odmr_cb_min_DoubleSpinBox.value()
474
            cb_max = self._mw.odmr_cb_max_DoubleSpinBox.value()
475
476
        # Otherwise, calculate cb range from percentiles.
477
        else:
478
            # Exclude any zeros (which are typically due to unfinished scan)
479
            matrix_image_nonzero = matrix_image[np.nonzero(matrix_image)]
480
481
            # Read centile range
482
            low_centile = self._mw.odmr_cb_low_percentile_DoubleSpinBox.value()
483
            high_centile = self._mw.odmr_cb_high_percentile_DoubleSpinBox.value()
484
485
            cb_min = np.percentile(matrix_image_nonzero, low_centile)
486
            cb_max = np.percentile(matrix_image_nonzero, high_centile)
487
488
        cb_range = [cb_min, cb_max]
489
        return cb_range
490
491
    def refresh_elapsedtime(self):
492
        """ Show current elapsed measurement time """
493
        self._mw.elapsed_time_DisplayWidget.display(int(self._odmr_logic.elapsed_time))
494
495 View Code Duplication
    def update_settings(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
496
        """ Write the new settings from the gui to the file. """
497
        self._odmr_logic.number_of_lines = self._sd.matrix_lines_SpinBox.value()
498
        self._odmr_logic.set_clock_frequency(self._sd.clock_frequency_DoubleSpinBox.value())
499
        self._odmr_logic.safeRawData = self._sd.save_raw_data_CheckBox.isChecked()
500
        for name, tab in self._sd.fit_tabs.items():
501
            self._odmr_logic.use_custom_params[name] = tab.updateFitSettings(
502
                self._odmr_logic.fit_models[name][1])
503
504
    def reject_settings(self):
505
        """ Keep the old settings and restores the old settings in the gui. """
506
        self._sd.matrix_lines_SpinBox.setValue(self._odmr_logic.number_of_lines)
507
        self._sd.clock_frequency_DoubleSpinBox.setValue(self._odmr_logic._clock_frequency)
508
        self._sd.save_raw_data_CheckBox.setChecked(self._odmr_logic.safeRawData)
509
        for name, tab in self._sd.fit_tabs.items():
510
            tab.keepFitSettings(
511
                self._odmr_logic.fit_models[name][1],
512
                self._odmr_logic.use_custom_params[name])
513
514
    def update_fit_variable(self, txt):
515
        """ Set current fit function """
516
        self._odmr_logic.current_fit_function = txt
517
518
    def update_fit(self):
519
        """ Do the configured fit and show it in the sum plot """
520
        x_data_fit, y_data_fit, fit_param, fit_result = self._odmr_logic.do_fit(fit_function=self._odmr_logic.current_fit_function)
521
        # The fit signal was already emitted in the logic, so there is no need
522
        # to set the fit data
523
524
        # check which Fit method is used and remove or add again the
525
        # odmr_fit_image, check also whether a odmr_fit_image already exists.
526
        if self._mw.fit_methods_ComboBox.currentText() == 'No Fit':
527
            if self.odmr_fit_image in self._mw.odmr_PlotWidget.listDataItems():
528
                self._mw.odmr_PlotWidget.removeItem(self.odmr_fit_image)
529
        else:
530
            if self.odmr_fit_image not in self._mw.odmr_PlotWidget.listDataItems():
531
                self._mw.odmr_PlotWidget.addItem(self.odmr_fit_image)
532
533
        self._mw.odmr_PlotWidget.getViewBox().updateAutoRange()
534
        self._mw.odmr_fit_results_DisplayWidget.clear()
535
536
        formated_results = units.create_formatted_output(fit_param)
537
538
        self._mw.odmr_fit_results_DisplayWidget.setPlainText(formated_results)
539
540
    def _format_param_dict(self, param_dict):
541
        """ Create from the passed param_dict a proper display of the parameters.
542
543
        @param dict param_dict: the dictionary with keys being the names of the
544
                                parameter and items being values/parameters.
545
546
        @return:
547
        """
548
        pass
549
550
    def mw_stop(self, txt):
551
        """ Stop frequency sweep and change to CW of off"""
552
        if txt == 'Off':
553
            self.sigMWOff.emit()
554
        if txt == 'CW':
555
            self.change_frequency()
556
            self.change_power()
557
            self.sigMWOn.emit()
558
559
560
    ############################################################################
561
    ##                          Change Methods                                ##
562
    ############################################################################
563
564
    def change_frequency(self):
565
        """ Change CW frequency of microwave source """
566
        frequency = self._mw.frequency_DoubleSpinBox.value()
567
        self.sigMWFreqChanged.emit(frequency)
568
569
    def change_start_freq(self):
570
        """ Change start frequency of frequency sweep """
571
        self._odmr_logic.mw_start = self._mw.start_freq_DoubleSpinBox.value()
572
573
    def change_step_freq(self):
574
        """ Change step size in which frequency is changed """
575
        self._odmr_logic.mw_step = self._mw.step_freq_DoubleSpinBox.value()
576
577
    def change_stop_freq(self):
578
        """ Change end of frequency sweep """
579
        self._odmr_logic.mw_stop = self._mw.stop_freq_DoubleSpinBox.value()
580
581
    def change_power(self):
582
        """ Change microwave power """
583
        power = self._mw.power_DoubleSpinBox.value()
584
        self.sigMWPowerChanged.emit(power)
585
586
    def change_runtime(self):
587
        """ Change time after which microwave sweep is stopped """
588
        self._odmr_logic.run_time = self._mw.runtime_DoubleSpinBox.value()
589
590
    def save_data(self):
591
        """ Save the sum plot, the scan marix plot and the scan data """
592
        filetag = self._mw.save_tag_LineEdit.text()
593
        cb_range = self.get_matrix_cb_range()
594
595
        # Percentile range is None, unless the percentile scaling is selected in GUI.
596
        pcile_range = None
597
        if self._mw.odmr_cb_centiles_RadioButton.isChecked():
598
            low_centile = self._mw.odmr_cb_low_percentile_DoubleSpinBox.value()
599
            high_centile = self._mw.odmr_cb_high_percentile_DoubleSpinBox.value()
600
            pcile_range = [low_centile, high_centile]
601
602
        self._odmr_logic.save_ODMR_Data(filetag, colorscale_range=cb_range, percentile_range=pcile_range)
603