Completed
Push — pulsed_with_queued_connections ( 175b78...ff3ac3 )
by
unknown
03:03 queued 24s
created

PulsedMeasurementGui._deactivate_analysis_ui()   B

Complexity

Conditions 1

Size

Total Lines 77

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
dl 0
loc 77
rs 8.9342
c 2
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
# -*- coding: utf-8 -*-
2
3
"""
4
This file contains the QuDi main GUI for pulsed measurements.
5
6
QuDi is free software: you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation, either version 3 of the License, or
9
(at your option) any later version.
10
11
QuDi is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
16
You should have received a copy of the GNU General Public License
17
along with QuDi. If not, see <http://www.gnu.org/licenses/>.
18
19
Copyright (c) the Qudi Developers. See the COPYRIGHT.txt file at the
20
top-level directory of this distribution and at <https://github.com/Ulm-IQO/qudi/>
21
"""
22
23
from qtpy import QtGui
24
from qtpy import QtCore
25
from qtpy import QtWidgets
26
from qtpy import uic
27
import numpy as np
28
import os
29
from collections import OrderedDict
30
import pyqtgraph as pg
31
import re
32
import inspect
33
import datetime
34
35
36
from gui.guibase import GUIBase
37
from gui.colordefs import QudiPalettePale as palette
38
from gui.colordefs import QudiPalette as palettedark
39
#from gui.pulsed.pulse_editor import PulseEditor
40
from core.util.mutex import Mutex
41
from core.util import units
42
from gui.pulsed.pulse_editors import BlockEditor, BlockOrganizer
43
from logic.sampling_functions import SamplingFunctions
44
45
46
#FIXME: Display the Pulse
47
#FIXME: save the length in sample points (bins)
48
#FIXME: adjust the length to the bins
49
#FIXME: Later that should be able to round up the values directly within
50
51
52
class PulsedMeasurementMainWindow(QtWidgets.QMainWindow):
53
    def __init__(self):
54
        # Get the path to the *.ui file
55
        this_dir = os.path.dirname(__file__)
56
        ui_file = os.path.join(this_dir, 'ui_pulsed_noeditor.ui')
57
58
        # Load it
59
        super(PulsedMeasurementMainWindow, self).__init__()
60
61
        uic.loadUi(ui_file, self)
62
        self.show()
63
64
65
class PulseAnalysisTab(QtWidgets.QWidget):
66
    def __init__(self):
67
        # Get the path to the *.ui file
68
        this_dir = os.path.dirname(__file__)
69
        ui_file = os.path.join(this_dir, 'ui_pulse_analysis.ui')
70
        # Load it
71
        super().__init__()
72
        uic.loadUi(ui_file, self)
73
74
75
class PulseGeneratorTab(QtWidgets.QWidget):
76
    def __init__(self):
77
        # Get the path to the *.ui file
78
        this_dir = os.path.dirname(__file__)
79
        ui_file = os.path.join(this_dir, 'ui_pulse_editor.ui')
80
        # Load it
81
        super().__init__()
82
        uic.loadUi(ui_file, self)
83
84
85
class PulseExtractionTab(QtWidgets.QWidget):
86
    def __init__(self):
87
        # Get the path to the *.ui file
88
        this_dir = os.path.dirname(__file__)
89
        ui_file = os.path.join(this_dir, 'ui_pulse_extraction.ui')
90
        # Load it
91
        super().__init__()
92
        uic.loadUi(ui_file, self)
93
94
95
class AnalysisSettingDialog(QtWidgets.QDialog):
96
    def __init__(self):
97
        # Get the path to the *.ui file
98
        this_dir = os.path.dirname(__file__)
99
        ui_file = os.path.join(this_dir, 'ui_pulsed_main_gui_settings_analysis.ui')
100
101
        # Load it
102
        super(AnalysisSettingDialog, self).__init__()
103
104
        uic.loadUi(ui_file, self)
105
106
107
class GeneratorSettingsDialog(QtWidgets.QDialog):
108
    def __init__(self):
109
        # Get the path to the *.ui file
110
        this_dir = os.path.dirname(__file__)
111
        ui_file = os.path.join(this_dir, 'ui_pulsed_main_gui_settings_block_gen.ui')
112
113
        # Load it
114
        super(GeneratorSettingsDialog, self).__init__()
115
116
        uic.loadUi(ui_file, self)
117
118
119
class PredefinedMethodsDialog(QtWidgets.QDialog):
120
    def __init__(self):
121
        # Get the path to the *.ui file
122
        this_dir = os.path.dirname(__file__)
123
        ui_file = os.path.join(this_dir, 'ui_predefined_methods.ui')
124
125
        # Load it
126
        super(PredefinedMethodsDialog, self).__init__()
127
128
        uic.loadUi(ui_file, self)
129
130
class PredefinedMethodsConfigDialog(QtWidgets.QDialog):
131
    def __init__(self):
132
        # Get the path to the *.ui file
133
        this_dir = os.path.dirname(__file__)
134
        ui_file = os.path.join(this_dir, 'ui_predefined_methods_config.ui')
135
136
        # Load it
137
        super(PredefinedMethodsConfigDialog, self).__init__()
138
139
        uic.loadUi(ui_file, self)
140
141
142
class PulsedMeasurementGui(GUIBase):
143
    """ This is the main GUI Class for pulsed measurements. """
144
145
    _modclass = 'PulsedMeasurementGui'
146
    _modtype = 'gui'
147
148
    ## declare connectors
149
    _in = {'pulsedmasterlogic': 'PulsedMasterLogic',
150
           'savelogic': 'SaveLogic'}
151
152
    def __init__(self, config, **kwargs):
153
        super().__init__(config=config, **kwargs)
154
155
        self.log.info('The following configuration was found.')
156
157
        # checking for the right configuration
158
        for key in config.keys():
159
            self.log.info('{}: {}'.format(key,config[key]))
160
161
        # that variable is for testing issues and can be deleted if not needed:
162
        self._write_chunkwise = False
163
164
    def on_activate(self, e=None):
165
        """ Initialize, connect and configure the pulsed measurement GUI.
166
167
        @param object e: Fysom.event object from Fysom class.
168
                         An object created by the state machine module Fysom,
169
                         which is connected to a specific event (have a look in
170
                         the Base Class). This object contains the passed event,
171
                         the state before the event happened and the destination
172
                         of the state which should be reached after the event
173
                         had happened.
174
175
        Establish general connectivity and activate the different tabs of the
176
        GUI.
177
        """
178
        self._pulsed_master_logic = self.get_in_connector('pulsedmasterlogic')
179
        self._save_logic = self.get_in_connector('savelogic')
180
181
        self._mw = PulsedMeasurementMainWindow()
182
        self._pa = PulseAnalysisTab()
183
        self._pg = PulseGeneratorTab()
184
        self._pe = PulseExtractionTab()
185
186
        self._mw.tabWidget.addTab(self._pa, 'Analysis')
187
        self._mw.tabWidget.addTab(self._pe, 'Pulse Extraction')
188
        self._mw.tabWidget.addTab(self._pg, 'Pulse Generator')
189
190
        self.setup_toolbar()
191
        self._activate_analysis_settings_ui(e)
192
        self._activate_analysis_ui(e)
193
        self.setup_extraction_ui()
194
195
        self._activate_generator_settings_ui(e)
196
        self._activate_pulse_generator_ui(e)
197
198
        self.show()
199
200
    def on_deactivate(self, e):
201
        """ Undo the Definition, configuration and initialisation of the pulsed
202
            measurement GUI.
203
204
        @param object e: Fysom.event object from Fysom class. A more detailed
205
                         explanation can be found in the method initUI.
206
207
        This deactivation disconnects all the graphic modules, which were
208
        connected in the initUI method.
209
        """
210
        self._deactivate_analysis_settings_ui(e)
211
        self._deactivate_analysis_ui(e)
212
213
        self._deactivate_generator_settings_ui(e)
214
        self._deactivate_pulse_generator_ui(e)
215
216
        self._mw.close()
217
218
    def show(self):
219
        """Make main window visible and put it above all other windows. """
220
        QtWidgets.QMainWindow.show(self._mw)
221
        self._mw.activateWindow()
222
        self._mw.raise_()
223
224
    ###########################################################################
225
    ###   Methods related to Settings for the 'Pulse Generator' tab:        ###
226
    ###########################################################################
227
    def _activate_generator_settings_ui(self, e):
228
        """ Initialize, connect and configure the pulse generator settings to be displayed in the
229
        editor.
230
231
        @param object e: Fysom.event object from Fysom class. A more detailed
232
                         explanation can be found in the method initUI.
233
        """
234
        self._gs = GeneratorSettingsDialog()
235
        self._gs.accepted.connect(self.apply_generator_settings)
236
        self._gs.rejected.connect(self.keep_former_generator_settings)
237
        self._gs.buttonBox.button(QtWidgets.QDialogButtonBox.Apply).clicked.connect(
238
            self.apply_generator_settings)
239
240
        # create the Predefined methods Dialog
241
        self._pm = PredefinedMethodsDialog()
242
        # here are all the names of the chosen predefined methods are saved.
243
        self._predefined_methods_list = []
244
        # create a config for the predefined methods:
245
        self._pm_cfg = PredefinedMethodsConfigDialog()
246
247
        # Add in the settings menu within the groupbox widget all the available math_functions,
248
        # based on the list from the Logic. Right now, the GUI objects are inserted the 'hard' way,
249
        # like it is done in the Qt-Designer.
250
        # FIXME: Make a nicer way of displaying the available functions, maybe with a Table!
251
        _encoding = QtWidgets.QApplication.UnicodeUTF8
252
        objectname = self._gs.objectName()
253
        for index, func_name in enumerate(list(SamplingFunctions().func_config)):
254
            name_label = 'func_' + str(index)
255
            setattr(self._gs, name_label, QtWidgets.QLabel(self._gs.groupBox))
256
            label = getattr(self._gs, name_label)
257
            label.setObjectName(name_label)
258
            self._gs.gridLayout_3.addWidget(label, index, 0, 1, 1)
259
            label.setText(QtWidgets.QApplication.translate(objectname, func_name, None, _encoding))
260
261
            name_checkbox = 'checkbox_' + str(index)
262
            setattr(self._gs, name_checkbox, QtWidgets.QCheckBox(self._gs.groupBox))
263
            checkbox = getattr(self._gs, name_checkbox)
264
            checkbox.setObjectName(name_checkbox)
265
            self._gs.gridLayout_3.addWidget(checkbox, index, 1, 1, 1)
266
            checkbox.setText(QtWidgets.QApplication.translate(objectname, '', None, _encoding))
267
        # make the first 4 Functions as default.
268
        # FIXME: the default functions, must be passed as a config
269
        for index in range(4):
270
            name_checkbox = 'checkbox_' + str(index)
271
            checkbox = getattr(self._gs, name_checkbox)
272
            checkbox.setCheckState(QtCore.Qt.Checked)
273
        return
274
275
    def _deactivate_generator_settings_ui(self, e):
276
        """ Disconnects the configuration of the Settings for the 'Pulse Generator' Tab.
277
278
        @param object e: Fysom.event object from Fysom class. A more detailed
279
                         explanation can be found in the method initUI.
280
        """
281
        self._gs.accepted.disconnect()
282
        self._gs.rejected.disconnect()
283
        self._gs.buttonBox.button(QtWidgets.QDialogButtonBox.Apply).clicked.disconnect()
284
        self._gs.close()
285
        return
286
287
    def show_generator_settings(self):
288
        """
289
        Opens the generator settings menu.
290
        """
291
        self._gs.exec_()
292
        return
293
294
    def apply_generator_settings(self):
295
        """
296
        Write new generator settings from the gui to the file.
297
        """
298
        new_config = SamplingFunctions().func_config
299
        for index, func_name in enumerate(list(SamplingFunctions().func_config)):
300
            name_checkbox = 'checkbox_' + str(index)
301
            checkbox = getattr(self._gs, name_checkbox)
302
            if not checkbox.isChecked():
303
                name_label = 'func_' + str(index)
304
                func = getattr(self._gs, name_label)
305
                del new_config[func.text()]
306
        if self.block_editor.function_config != new_config:
307
            self.block_editor.set_function_config(new_config)
308
        return
309
310
    def keep_former_generator_settings(self):
311
        """
312
        Keep the old generator settings and restores them in the gui.
313
        """
314
        old_config = self.block_editor.function_config
315
        for index, func_name in enumerate(list(SamplingFunctions().func_config)):
316
            name_checkbox = 'checkbox_' + str(index)
317
            checkbox = getattr(self._gs, name_checkbox)
318
            if func_name in old_config:
319
                checkbox.setChecked(True)
320
            else:
321
                checkbox.setChecked(False)
322
        return
323
324
    def show_predefined_methods(self):
325
        """ Opens the predefined methods Window."""
326
        self._pm.show()
327
        self._pm.raise_()
328
329
    def show_predefined_methods_config(self):
330
        """ Opens the Window for the config of predefined methods."""
331
        self._pm_cfg.show()
332
        self._pm_cfg.raise_()
333
    #
334
    # def keep_former_predefined_methods(self):
335
    #
336
    #     for method_name in self._predefined_methods_list:
337
    #         groupbox = self._get_ref_groupbox_predefined_methods(method_name)
338
    #         checkbox = self._get_ref_checkbox_predefined_methods_config(method_name)
339
    #
340
    #         checkbox.setChecked(groupbox.isVisible())
341
    #
342
    # def update_predefined_methods(self):
343
    #     for method_name in self._predefined_methods_list:
344
    #         groupbox = self._get_ref_groupbox_predefined_methods(method_name)
345
    #         checkbox = self._get_ref_checkbox_predefined_methods_config(method_name)
346
    #
347
    #         groupbox.setVisible(checkbox.isChecked())
348
349
    ###########################################################################
350
    ###   Methods related to Tab 'Pulse Generator' in the Pulsed Window:    ###
351
    ###########################################################################
352
    def _activate_pulse_generator_ui(self, e):
353
        """ Initialize, connect and configure the 'Pulse Generator' Tab.
354
355
        @param object e: Fysom.event object from Fysom class. A more detailed
356
                         explanation can be found in the method initUI.
357
        """
358
        # connect signals of input widgets
359
        self._pg.gen_sample_freq_DSpinBox.editingFinished.connect(self.generator_settings_changed, QtCore.Qt.QueuedConnection)
360
        self._pg.gen_laserchannel_ComboBox.currentIndexChanged.connect(self.generator_settings_changed, QtCore.Qt.QueuedConnection)
361
        self._pg.gen_activation_config_ComboBox.currentIndexChanged.connect(self.generator_settings_changed, QtCore.Qt.QueuedConnection)
362
        # connect signals of buttons
363
        self._pg.sample_ensemble_PushButton.clicked.connect(self.sample_ensemble_clicked)
364
        # self._pg.sample_sequence_PushButton.clicked.connect(self.sample_sequence_clicked)
365
        self._pg.sauplo_ensemble_PushButton.clicked.connect(self.sauplo_ensemble_clicked)
366
367
        self._pg.block_add_last_PushButton.clicked.connect(self.block_add_last_clicked)
368
        self._pg.block_del_last_PushButton.clicked.connect(self.block_del_last_clicked)
369
        self._pg.block_add_sel_PushButton.clicked.connect(self.block_add_sel_clicked)
370
        self._pg.block_del_sel_PushButton.clicked.connect(self.block_del_sel_clicked)
371
        self._pg.block_clear_PushButton.clicked.connect(self.block_clear_clicked)
372
        self._pg.organizer_add_last_PushButton.clicked.connect(self.organizer_add_last_clicked)
373
        self._pg.organizer_del_last_PushButton.clicked.connect(self.organizer_del_last_clicked)
374
        self._pg.organizer_add_sel_PushButton.clicked.connect(self.organizer_add_sel_clicked)
375
        self._pg.organizer_del_sel_PushButton.clicked.connect(self.organizer_del_sel_clicked)
376
        self._pg.organizer_clear_PushButton.clicked.connect(self.organizer_clear_clicked)
377
378
        self._pg.curr_block_generate_PushButton.clicked.connect(self.editor_generate_block_clicked)
379
        self._pg.curr_block_del_PushButton.clicked.connect(self.editor_delete_block_clicked)
380
        self._pg.curr_block_load_PushButton.clicked.connect(self.editor_load_block_clicked)
381
        self._pg.curr_ensemble_generate_PushButton.clicked.connect(self.editor_generate_ensemble_clicked)
382
        self._pg.curr_ensemble_del_PushButton.clicked.connect(self.editor_delete_ensemble_clicked)
383
        self._pg.curr_ensemble_load_PushButton.clicked.connect(self.editor_load_ensemble_clicked)
384
385
        # connect update signals from pulsed_master_logic
386
        self._pulsed_master_logic.sigBlockEnsembleSampled.connect(self.sample_ensemble_finished)
387
        # self._pulsed_master_logic.sigSequenceSampled.connect(self.sample_sequence_finished)
388
        self._pulsed_master_logic.sigSavedPulseBlocksUpdated.connect(self.update_block_dict)
389
        self._pulsed_master_logic.sigSavedBlockEnsemblesUpdated.connect(self.update_ensemble_dict)
390
        # self._pulsed_master_logic.sigSavedSequencesUpdated.connect(self.update_sequence_list)
391
        self._pulsed_master_logic.sigGeneratorSettingsUpdated.connect(self.update_generator_settings)
392
393
        self._pulsed_master_logic.sigCurrentPulseBlockUpdated.connect(self.load_block_in_editor)
394
        self._pulsed_master_logic.sigCurrentBlockEnsembleUpdated.connect(self.load_ensemble_in_editor)
395
        # self._pulsed_master_logic.sigCurrentSequenceUpdated.connect(self.)
396
397
        self.block_organizer = BlockOrganizer(self._pg.block_organizer_TableWidget)
398
        self.block_editor = BlockEditor(self._pg.block_editor_TableWidget)
399
400
        # connect the menu to the actions:
401
        self._mw.action_Settings_Block_Generation.triggered.connect(self.show_generator_settings)
402
        self._mw.action_Predefined_Methods_Config.triggered.connect(self.show_predefined_methods_config)
403
        self._mw.action_Show_Predefined_Methods.triggered.connect(self.show_predefined_methods)
404
405
        # Apply hardware constraints to input widgets
406
        self._gen_apply_hardware_constraints()
407
408
        # Fill initial values from logic into input widgets
409
        self._pulsed_master_logic.request_generator_init_values()
410
        return
411
412
    def _deactivate_pulse_generator_ui(self, e):
413
        """ Disconnects the configuration for 'Pulse Generator Tab.
414
415
        @param object e: Fysom.event object from Fysom class. A more detailed
416
                         explanation can be found in the method initUI.
417
        """
418
        # disconnect signals of input widgets
419
        self._pg.gen_sample_freq_DSpinBox.editingFinished.disconnect()
420
        self._pg.gen_laserchannel_ComboBox.currentIndexChanged.disconnect()
421
        self._pg.gen_activation_config_ComboBox.currentIndexChanged.disconnect()
422
        # disconnect signals of buttons
423
        self._pg.sample_ensemble_PushButton.clicked.disconnect()
424
        # self._pg.sample_sequence_PushButton.clicked.disconnect()
425
        self._pg.sauplo_ensemble_PushButton.clicked.disconnect()
426
        self._pg.block_add_last_PushButton.clicked.disconnect()
427
        self._pg.block_del_last_PushButton.clicked.disconnect()
428
        self._pg.block_add_sel_PushButton.clicked.disconnect()
429
        self._pg.block_del_sel_PushButton.clicked.disconnect()
430
        self._pg.block_clear_PushButton.clicked.disconnect()
431
        self._pg.organizer_add_last_PushButton.clicked.disconnect()
432
        self._pg.organizer_del_last_PushButton.clicked.disconnect()
433
        self._pg.organizer_add_sel_PushButton.clicked.disconnect()
434
        self._pg.organizer_del_sel_PushButton.clicked.disconnect()
435
        self._pg.organizer_clear_PushButton.clicked.disconnect()
436
        self._pg.curr_block_generate_PushButton.clicked.disconnect()
437
        self._pg.curr_block_del_PushButton.clicked.disconnect()
438
        self._pg.curr_block_load_PushButton.clicked.disconnect()
439
        self._pg.curr_ensemble_generate_PushButton.clicked.disconnect()
440
        self._pg.curr_ensemble_del_PushButton.clicked.disconnect()
441
        self._pg.curr_ensemble_load_PushButton.clicked.disconnect()
442
        # disconnect update signals from pulsed_master_logic
443
        self._pulsed_master_logic.sigBlockEnsembleSampled.disconnect()
444
        # self._pulsed_master_logic.sigSequenceSampled.disconnect()
445
        self._pulsed_master_logic.sigSavedPulseBlocksUpdated.disconnect()
446
        self._pulsed_master_logic.sigSavedBlockEnsemblesUpdated.disconnect()
447
        # self._pulsed_master_logic.sigSavedSequencesUpdated.disconnect()
448
        self._pulsed_master_logic.sigGeneratorSettingsUpdated.disconnect()
449
        # self._pulsed_master_logic.sigCurrentPulseBlockUpdated.disconnect()
450
        # self._pulsed_master_logic.sigCurrentBlockEnsembleUpdated.disconnect()
451
        # self._pulsed_master_logic.sigCurrentSequenceUpdated.disconnect()
452
        return
453
454
    def _gen_apply_hardware_constraints(self):
455
        """
456
        Retrieve the constraints from pulser hardware and apply these constraints to the pulse
457
        generator GUI elements.
458
        """
459
        # block signals
460
        self._pg.gen_activation_config_ComboBox.blockSignals(True)
461
        self._pg.gen_sample_freq_DSpinBox.blockSignals(True)
462
        # apply constraints
463
        pulser_constr, dummy = self._pulsed_master_logic.get_hardware_constraints()
464
        self._pg.gen_activation_config_ComboBox.addItems(list(pulser_constr['activation_config']))
465
        self._pg.gen_sample_freq_DSpinBox.setMinimum(pulser_constr['sample_rate']['min'])
466
        self._pg.gen_sample_freq_DSpinBox.setMaximum(pulser_constr['sample_rate']['max'])
467
        # unblock signals
468
        self._pg.gen_activation_config_ComboBox.blockSignals(False)
469
        self._pg.gen_sample_freq_DSpinBox.blockSignals(False)
470
        return
471
472
    def generator_settings_changed(self):
473
        """
474
475
        @return:
476
        """
477
        sample_rate = self._pg.gen_sample_freq_DSpinBox.value()
478
        laser_channel = self._pg.gen_laserchannel_ComboBox.currentText()
479
        activation_config_name = self._pg.gen_activation_config_ComboBox.currentText()
480
        amplitude_dict = self._pulsed_master_logic._generator_logic.amplitude_dict
481
482
        self._pulsed_master_logic.generator_settings_changed(activation_config_name, laser_channel,
483
                                                             sample_rate, amplitude_dict)
484
        return
485
486
    def update_generator_settings(self, activation_config_name, activation_config, sample_rate,
487
                                   amplitude_dict, laser_channel):
488
        """
489
490
        @param activation_config_name:
491
        @param activation_config:
492
        @param sample_rate:
493
        @param amplitude_dict:
494
        @param laser_channel:
495
        @return:
496
        """
497
        # block signals
498
        self._pg.gen_sample_freq_DSpinBox.blockSignals(True)
499
        self._pg.gen_laserchannel_ComboBox.blockSignals(True)
500
        self._pg.gen_activation_config_ComboBox.blockSignals(True)
501
        # activation config
502
        index = self._pg.gen_activation_config_ComboBox.findText(activation_config_name)
503
        self._pg.gen_activation_config_ComboBox.setCurrentIndex(index)
504
        display_str = ''
505
        for chnl in activation_config:
506
            display_str += chnl + ' | '
507
        display_str = display_str[:-3]
508
        self._pg.gen_activation_config_LineEdit.setText(display_str)
509
        self._pg.gen_analog_channels_SpinBox.setValue(
510
            len([chnl for chnl in activation_config if 'a_ch' in chnl]))
511
        self._pg.gen_digital_channels_SpinBox.setValue(
512
            len([chnl for chnl in activation_config if 'd_ch' in chnl]))
513
        # laser channel
514
        self._pg.gen_laserchannel_ComboBox.clear()
515
        self._pg.gen_laserchannel_ComboBox.addItems(activation_config)
516
        index = self._pg.gen_laserchannel_ComboBox.findText(laser_channel)
517
        self._pg.gen_laserchannel_ComboBox.setCurrentIndex(index)
518
        # sample rate
519
        self._pg.gen_sample_freq_DSpinBox.setValue(sample_rate)
520
        # set activation config in block editor
521
        if self.block_editor.activation_config != activation_config:
522
            self.block_editor.set_activation_config(activation_config)
523
        # unblock signals
524
        self._pg.gen_sample_freq_DSpinBox.blockSignals(False)
525
        self._pg.gen_laserchannel_ComboBox.blockSignals(False)
526
        self._pg.gen_activation_config_ComboBox.blockSignals(False)
527
        return
528
529
    def block_add_last_clicked(self):
530
        """
531
532
        @return:
533
        """
534
        self.block_editor.insert_rows(self._pg.block_editor_TableWidget.rowCount(), 1)
535
        return
536
537
    def block_del_last_clicked(self):
538
        """
539
540
        @return:
541
        """
542
        self.block_editor.delete_row(self._pg.block_editor_TableWidget.rowCount())
543
        return
544
545
    def block_add_sel_clicked(self):
546
        """
547
548
        @return:
549
        """
550
        index = self._pg.block_editor_TableWidget.currentRow()
551
        self.block_editor.insert_rows(index + 1, 1)
552
        return
553
554
    def block_del_sel_clicked(self):
555
        """
556
557
        @return:
558
        """
559
        index = self._pg.block_editor_TableWidget.currentRow()
560
        self.block_editor.delete_row(index)
561
        return
562
563
    def block_clear_clicked(self):
564
        """
565
566
        @return:
567
        """
568
        self.block_editor.clear_table()
569
        return
570
571
    def organizer_add_last_clicked(self):
572
        """
573
574
        @return:
575
        """
576
        self.block_organizer.insert_rows(self._pg.block_organizer_TableWidget.rowCount(), 1)
577
        return
578
579
    def organizer_del_last_clicked(self):
580
        """
581
582
        @return:
583
        """
584
        self.block_organizer.delete_row(self._pg.block_organizer_TableWidget.rowCount() - 1)
585
        return
586
587
    def organizer_add_sel_clicked(self):
588
        """
589
590
        @return:
591
        """
592
        index = self._pg.block_organizer_TableWidget.currentRow()
593
        self.block_organizer.insert_rows(index + 1, 1)
594
        return
595
596
    def organizer_del_sel_clicked(self):
597
        """
598
599
        @return:
600
        """
601
        index = self._pg.block_organizer_TableWidget.currentRow()
602
        self.block_organizer.delete_row(index)
603
        return
604
605
    def organizer_clear_clicked(self):
606
        """
607
608
        @return:
609
        """
610
        self.block_organizer.clear_table()
611
        return
612
613
    def editor_generate_block_clicked(self):
614
        name = self._pg.curr_block_name_LineEdit.text()
615
        if name == '':
616
            self.log.error('No name has been entered for the PulseBlock to be generated.')
617
            return
618
        block_object = self.block_editor.generate_block_object(name)
619
        self._pulsed_master_logic.save_pulse_block(name, block_object)
620
        return
621
622
    def editor_delete_block_clicked(self):
623
        name = self._pg.saved_blocks_ComboBox.currentText()
624
        self._pulsed_master_logic.delete_pulse_block(name)
625
        return
626
627
    def editor_load_block_clicked(self):
628
        name = self._pg.saved_blocks_ComboBox.currentText()
629
        self._pulsed_master_logic.load_pulse_block(name)
630
        return
631
632
    def editor_generate_ensemble_clicked(self):
633
        name = self._pg.curr_ensemble_name_LineEdit.text()
634
        if name == '':
635
            self.log.error('No name has been entered for the PulseBlockEnsemble to be generated.')
636
            return
637
        rotating_frame = self._pg.curr_ensemble_rot_frame_CheckBox.isChecked()
638
        ensemble_object = self.block_organizer.generate_ensemble_object(name, rotating_frame)
639
        self._pulsed_master_logic.save_block_ensemble(name, ensemble_object)
640
        return
641
642
    def editor_delete_ensemble_clicked(self):
643
        name = self._pg.saved_ensembles_ComboBox.currentText()
644
        self._pulsed_master_logic.delete_block_ensemble(name)
645
        return
646
647
    def editor_load_ensemble_clicked(self):
648
        name = self._pg.saved_ensembles_ComboBox.currentText()
649
        self._pulsed_master_logic.load_block_ensemble(name)
650
        return
651
652
    def load_block_in_editor(self, block_obj):
653
        self.block_editor.load_pulse_block(block_obj)
654
        return
655
656
    def load_ensemble_in_editor(self, ensemble_obj):
657
        self.block_organizer.load_pulse_block_ensemble(ensemble_obj)
658
        return
659
660
    def update_block_dict(self, block_dict):
661
        """
662
663
        @param block_dict:
664
        @return:
665
        """
666
        self.block_organizer.set_block_dict(block_dict)
667
        self._pg.saved_blocks_ComboBox.blockSignals(True)
668
        self._pg.saved_blocks_ComboBox.clear()
669
        self._pg.saved_blocks_ComboBox.addItems(list(block_dict))
670
        self._pg.saved_blocks_ComboBox.blockSignals(False)
671
        return
672
673
    def update_ensemble_dict(self, ensemble_dict):
674
        """
675
676
        @param ensemble_dict:
677
        @return:
678
        """
679
        # block signals
680
        self._pg.gen_ensemble_ComboBox.blockSignals(True)
681
        self._pg.saved_ensembles_ComboBox.blockSignals(True)
682
        # update gen_sequence_ComboBox items
683
        self._pg.gen_ensemble_ComboBox.clear()
684
        self._pg.gen_ensemble_ComboBox.addItems(list(ensemble_dict))
685
        self._pg.saved_ensembles_ComboBox.clear()
686
        self._pg.saved_ensembles_ComboBox.addItems(list(ensemble_dict))
687
        # unblock signals
688
        self._pg.gen_ensemble_ComboBox.blockSignals(False)
689
        self._pg.saved_ensembles_ComboBox.blockSignals(False)
690
        return
691
692
    # def update_sequence_list(self, sequence_list):
693
    #     """
694
    #
695
    #     @param sequence_list:
696
    #     @return:
697
    #     """
698
    #     # block signals
699
    #     self._pg.gen_sequence_ComboBox.blockSignals(True)
700
    #     # update gen_sequence_ComboBox items
701
    #     self._pg.gen_sequence_ComboBox.clear()
702
    #     self._pg.gen_sequence_ComboBox.addItems(sequence_list)
703
    #     # unblock signals
704
    #     self._pg.gen_sequence_ComboBox.blockSignals(False)
705
    #     return
706
707
    def sample_ensemble_clicked(self):
708
        """
709
        This method is called when the user clicks on "sample"
710
        """
711
        # Get the ensemble name from the ComboBox
712
        ensemble_name = self._pg.gen_ensemble_ComboBox.currentText()
713
        # disable button
714
        self._pg.sample_ensemble_PushButton.setEnabled(False)
715
        # Sample the ensemble via logic module
716
        self._pulsed_master_logic.sample_block_ensemble(ensemble_name, True, self._write_chunkwise)
717
        return
718
719
    def sample_ensemble_finished(self, ensemble_name):
720
        """
721
722
        @return:
723
        """
724
        # enable button
725
        self._pg.sample_ensemble_PushButton.setEnabled(True)
726
        return
727
728
    def sauplo_ensemble_clicked(self):
729
        """
730
731
        @return:
732
        """
733
        # Get the ensemble name from the ComboBox
734
        ensemble_name = self._pg.gen_ensemble_ComboBox.currentText()
735
        # disable button
736
        self._pg.sample_ensemble_PushButton.setEnabled(False)
737
        self._pg.upload_ensemble_PushButton.setEnabled(False)
738
        self._pg.load_ensemble_PushButton.setEnabled(False)
739
        # Sample the ensemble via logic module
740
        self._pulsed_master_logic.sample_block_ensemble(ensemble_name, True, self._write_chunkwise, True)
741
        return
742
743
    # def sample_sequence_clicked(self):
744
    #     """
745
    #     This method is called when the user clicks on "sample"
746
    #     """
747
    #     # Get the sequence name from the ComboBox
748
    #     sequence_name = self._pg.gen_sequence_ComboBox.currentText()
749
    #     # Sample the sequence via logic module
750
    #     self._pulsed_master_logic.sample_sequence(sequence_name, True, self._write_chunkwise)
751
    #     # disable button
752
    #     self._pg.sample_sequence_PushButton.setEnabled(False)
753
    #     return
754
755
    # def sample_sequence_finished(self, sequence_name):
756
    #     """
757
    #
758
    #     @return:
759
    #     """
760
    #     # enable button
761
    #     self._pg.sample_sequence_PushButton.setEnabled(True)
762
    #     return
763
764
    ###########################################################################
765
    ###        Methods related to Settings for the 'Analysis' Tab:          ###
766
    ###########################################################################
767
    #FIXME: Implement the setting for 'Analysis' tab.
768
    def _activate_analysis_settings_ui(self, e):
769
        """ Initialize, connect and configure the Settings of 'Analysis' Tab.
770
771
        @param object e: Fysom.event object from Fysom class. A more detailed
772
                         explanation can be found in the method initUI.
773
        """
774
        self._as = AnalysisSettingDialog()
775
        self._as.accepted.connect(self.update_analysis_settings)
776
        self._as.rejected.connect(self.keep_former_analysis_settings)
777
        self._as.buttonBox.button(QtWidgets.QDialogButtonBox.Apply).clicked.connect(self.update_analysis_settings)
778
779
        if 'ana_param_x_axis_name_LineEdit' in self._statusVariables:
780
            self._as.ana_param_x_axis_name_LineEdit.setText(self._statusVariables['ana_param_x_axis_name_LineEdit'])
781
        if 'ana_param_x_axis_unit_LineEdit' in self._statusVariables:
782
            self._as.ana_param_x_axis_unit_LineEdit.setText(self._statusVariables['ana_param_x_axis_unit_LineEdit'])
783
        if 'ana_param_y_axis_name_LineEdit' in self._statusVariables:
784
            self._as.ana_param_y_axis_name_LineEdit.setText(self._statusVariables['ana_param_y_axis_name_LineEdit'])
785
        if 'ana_param_y_axis_unit_LineEdit' in self._statusVariables:
786
            self._as.ana_param_y_axis_unit_LineEdit.setText(self._statusVariables['ana_param_y_axis_unit_LineEdit'])
787
        if 'ana_param_second_plot_x_axis_name_LineEdit' in self._statusVariables:
788
            self._as.ana_param_second_plot_x_axis_name_LineEdit.setText(self._statusVariables['ana_param_second_plot_x_axis_name_LineEdit'])
789
        if 'ana_param_second_plot_x_axis_unit_LineEdit' in self._statusVariables:
790
            self._as.ana_param_second_plot_x_axis_unit_LineEdit.setText(self._statusVariables['ana_param_second_plot_x_axis_unit_LineEdit'])
791
        if 'ana_param_second_plot_y_axis_name_LineEdit' in self._statusVariables:
792
            self._as.ana_param_second_plot_y_axis_name_LineEdit.setText(self._statusVariables['ana_param_second_plot_y_axis_name_LineEdit'])
793
        if 'ana_param_second_plot_y_axis_unit_LineEdit' in self._statusVariables:
794
            self._as.ana_param_second_plot_y_axis_unit_LineEdit.setText(self._statusVariables['ana_param_second_plot_y_axis_unit_LineEdit'])
795
        self.update_analysis_settings()
796
        return
797
798
799
    def _deactivate_analysis_settings_ui(self, e):
800
        """ Disconnects the configuration of the Settings for 'Analysis' Tab.
801
802
        @param object e: Fysom.event object from Fysom class. A more detailed
803
                         explanation can be found in the method initUI.
804
        """
805
        self._statusVariables['ana_param_x_axis_name_LineEdit'] = self._as.ana_param_x_axis_name_LineEdit.text()
806
        self._statusVariables['ana_param_x_axis_unit_LineEdit'] = self._as.ana_param_x_axis_unit_LineEdit.text()
807
        self._statusVariables['ana_param_y_axis_name_LineEdit'] = self._as.ana_param_y_axis_name_LineEdit.text()
808
        self._statusVariables['ana_param_y_axis_unit_LineEdit'] = self._as.ana_param_y_axis_unit_LineEdit.text()
809
        self._statusVariables['ana_param_second_plot_x_axis_name_LineEdit'] = self._as.ana_param_second_plot_x_axis_name_LineEdit.text()
810
        self._statusVariables['ana_param_second_plot_x_axis_unit_LineEdit'] = self._as.ana_param_second_plot_x_axis_unit_LineEdit.text()
811
        self._statusVariables['ana_param_second_plot_y_axis_name_LineEdit'] = self._as.ana_param_second_plot_y_axis_name_LineEdit.text()
812
        self._statusVariables['ana_param_second_plot_y_axis_unit_LineEdit'] = self._as.ana_param_second_plot_y_axis_unit_LineEdit.text()
813
        return
814
815
816
    def update_analysis_settings(self):
817
        """ Apply the new settings """
818
        self._pa.pulse_analysis_PlotWidget.setLabel(
819
            axis='bottom',
820
            text=self._as.ana_param_x_axis_name_LineEdit.text(),
821
            units=self._as.ana_param_x_axis_unit_LineEdit.text())
822
        self._pa.pulse_analysis_PlotWidget.setLabel(
823
            axis='left',
824
            text=self._as.ana_param_y_axis_name_LineEdit.text(),
825
            units=self._as.ana_param_y_axis_unit_LineEdit.text())
826
        self._pa.pulse_analysis_second_PlotWidget.setLabel(
827
            axis='bottom',
828
            text=self._as.ana_param_second_plot_x_axis_name_LineEdit.text(),
829
            units=self._as.ana_param_second_plot_x_axis_unit_LineEdit.text())
830
        self._pa.pulse_analysis_second_PlotWidget.setLabel(
831
            axis='left',
832
            text=self._as.ana_param_second_plot_y_axis_name_LineEdit.text(),
833
            units=self._as.ana_param_second_plot_y_axis_unit_LineEdit.text())
834
        return
835
836
    def keep_former_analysis_settings(self):
837
        """ Keep the old settings """
838
        #FIXME: Implement the behaviour
839
        pass
840
841
    def show_analysis_settings(self):
842
        """ Open the Analysis Settings Window. """
843
        self._as.exec_()
844
        return
845
846
    ###########################################################################
847
    ###     Methods related to the Tab 'Analysis' in the Pulsed Window:     ###
848
    ###########################################################################
849
    def setup_toolbar(self):
850
        # create all the needed control widgets on the fly and connect their
851
        # actions to each other:
852
        self._mw.pulser_on_off_PushButton = QtWidgets.QPushButton()
853
        self._mw.pulser_on_off_PushButton.setText('Pulser ON')
854
        self._mw.pulser_on_off_PushButton.setToolTip('Switch the device on and off.')
855
        self._mw.pulser_on_off_PushButton.setCheckable(True)
856
        self._mw.control_ToolBar.addWidget(self._mw.pulser_on_off_PushButton)
857
858
        self._mw.clear_device_PushButton = QtWidgets.QPushButton(self._mw)
859
        self._mw.clear_device_PushButton.setText('Clear Pulser')
860
        self._mw.clear_device_PushButton.setToolTip(
861
            'Clear the Pulser Device Memory\nfrom all loaded files.')
862
        self._mw.control_ToolBar.addWidget(self._mw.clear_device_PushButton)
863
864
        self._mw.current_loaded_asset_Label = QtWidgets.QLabel(self._mw)
865
        sizepolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred,
866
                                           QtWidgets.QSizePolicy.Fixed)
867
        sizepolicy.setHorizontalStretch(0)
868
        sizepolicy.setVerticalStretch(0)
869
        sizepolicy.setHeightForWidth(
870
            self._mw.current_loaded_asset_Label.sizePolicy().hasHeightForWidth())
871
        self._mw.current_loaded_asset_Label.setSizePolicy(sizepolicy)
872
        self._mw.current_loaded_asset_Label.setText('  No Asset Loaded')
873
        self._mw.current_loaded_asset_Label.setToolTip('Display the currently loaded asset.')
874
        self._mw.control_ToolBar.addWidget(self._mw.current_loaded_asset_Label)
875
876
        self._mw.save_tag_LineEdit = QtWidgets.QLineEdit()
877
        self._mw.save_tag_LineEdit.setMaximumWidth(200)
878
        self._mw.save_ToolBar.addWidget(self._mw.save_tag_LineEdit)
879
880
    def setup_extraction_ui(self):
881
        self.lasertrace_image = pg.PlotDataItem(np.array(range(10)), np.zeros(10), pen=palette.c1)
882
        self._pe.laserpulses_PlotWidget.addItem(self.lasertrace_image)
883
        self._pe.laserpulses_PlotWidget.addItem(self.sig_start_line)
884
        self._pe.laserpulses_PlotWidget.addItem(self.sig_end_line)
885
        self._pe.laserpulses_PlotWidget.addItem(self.ref_start_line)
886
        self._pe.laserpulses_PlotWidget.addItem(self.ref_end_line)
887
        self._pe.laserpulses_PlotWidget.setLabel('bottom', 'bins')
888
889
    def _activate_analysis_ui(self, e):
890
        """ Initialize, connect and configure the 'Analysis' Tab.
891
892
        @param object e: Fysom.event object from Fysom class. A more detailed
893
                         explanation can be found in the method initUI.
894
        """
895
        # FIXME: Implement second plot
896
        self._pa.second_plot_GroupBox.setVisible(False)
897
        # Configure the main pulse analysis display:
898
        self.signal_image = pg.PlotDataItem(np.array(range(10)), np.zeros(10), pen=palette.c1)
899
        self._pa.pulse_analysis_PlotWidget.addItem(self.signal_image)
900
        self.signal_image2 = pg.PlotDataItem(pen=palette.c3)
901
        self._pa.pulse_analysis_PlotWidget.addItem(self.signal_image2)
902
        self._pa.pulse_analysis_PlotWidget.showGrid(x=True, y=True, alpha=0.8)
903
904
        # Configure the fit of the data in the main pulse analysis display:
905
        self.fit_image = pg.PlotDataItem(pen=palette.c2)
906
        self._pa.pulse_analysis_PlotWidget.addItem(self.fit_image)
907
        self._pa.fit_param_fit_func_ComboBox.clear()
908
        self._pa.fit_param_fit_func_ComboBox.addItems(self._pulsed_master_logic.get_fit_functions())
909
910
        # Configure the errorbars of the data in the main pulse analysis display:
911
        self.signal_image_error_bars = pg.ErrorBarItem(
912
            x=np.array(range(10)),
913
            y=np.zeros(10),
914
            top=0.,
915
            bottom=0.,
916
            pen=palette.c1)
917
        self.signal_image_error_bars2 = pg.ErrorBarItem(
918
            x=np.array(range(10)),
919
            y=np.zeros(10),
920
            top=0.,
921
            bottom=0.,
922
            pen=palette.c3)
923
924
        # Configure the second pulse analysis display:
925
        self.second_plot_image = pg.PlotDataItem(np.array(range(10)), np.zeros(10), pen=palette.c1)
926
        self._pa.pulse_analysis_second_PlotWidget.addItem(self.second_plot_image)
927
        self._pa.pulse_analysis_second_PlotWidget.showGrid(x=True, y=True, alpha=0.8)
928
929
        # Configure the lasertrace plot display:
930
        self.sig_start_line = pg.InfiniteLine(pos=0, pen=QtGui.QPen(palette.c3), movable=True)
931
        self.sig_start_line.setHoverPen(QtGui.QPen(palette.c2))
932
        self.sig_end_line = pg.InfiniteLine(pos=0, pen=QtGui.QPen(palette.c3), movable=True)
933
        self.sig_end_line.setHoverPen(QtGui.QPen(palette.c2))
934
        self.ref_start_line = pg.InfiniteLine(pos=0, pen=QtGui.QPen(palettedark.c4), movable=True)
935
        self.ref_start_line.setHoverPen(QtGui.QPen(palette.c4))
936
        self.ref_end_line = pg.InfiniteLine(pos=0, pen=QtGui.QPen(palettedark.c4), movable=True)
937
        self.ref_end_line.setHoverPen(QtGui.QPen(palette.c4))
938
        # Configure the measuring error display:
939
        self.measuring_error_image = pg.PlotDataItem(
940
            np.array(range(10)),
941
            np.zeros(10),
942
            pen=palette.c1)
943
        self.measuring_error_image2 = pg.PlotDataItem(
944
            np.array(range(10)),
945
            np.zeros(10),
946
            pen=palette.c3)
947
        self._pe.measuring_error_PlotWidget.addItem(self.measuring_error_image)
948
        self._pe.measuring_error_PlotWidget.addItem(self.measuring_error_image2)
949
        self._pe.measuring_error_PlotWidget.setLabel('left', 'measuring error', units='a.u.')
950
        self._pe.measuring_error_PlotWidget.setLabel('bottom', 'tau', units='ns')
951
952
953
        # set boundaries
954
        self._pe.slider_conv_std_dev.setRange(1, 200)
955
        self._pe.conv_std_dev.setRange(1, 200)
956
957
        # ---------------------------------------------------------------------
958
        #                         Connect signals
959
        # ---------------------------------------------------------------------
960
        # connect update signals from logic
961
        self._pulsed_master_logic.sigSignalDataUpdated.connect(self.signal_data_updated)
962
        self._pulsed_master_logic.sigLaserDataUpdated.connect(self.laser_data_updated)
963
        self._pulsed_master_logic.sigLaserToShowUpdated.connect(self.laser_to_show_updated)
964
        self._pulsed_master_logic.sigElapsedTimeUpdated.connect(self.elapsed_time_updated)
965
        self._pulsed_master_logic.sigFitUpdated.connect(self.fit_data_updated)
966
        self._pulsed_master_logic.sigMeasurementStatusUpdated.connect(self.measurement_status_updated)
967
        self._pulsed_master_logic.sigPulserRunningUpdated.connect(self.pulser_running_updated)
968
        self._pulsed_master_logic.sigFastCounterSettingsUpdated.connect(self.fast_counter_settings_updated)
969
        self._pulsed_master_logic.sigMeasurementSequenceSettingsUpdated.connect(self.measurement_sequence_settings_updated)
970
        self._pulsed_master_logic.sigPulserSettingsUpdated.connect(self.pulse_generator_settings_updated)
971
        self._pulsed_master_logic.sigUploadedAssetsUpdated.connect(self.update_uploaded_assets)
972
        self._pulsed_master_logic.sigLoadedAssetUpdated.connect(self.update_loaded_asset)
973
        self._pulsed_master_logic.sigExtMicrowaveSettingsUpdated.connect(self.microwave_settings_updated)
974
        self._pulsed_master_logic.sigExtMicrowaveRunningUpdated.connect(self.microwave_running_updated)
975
        self._pulsed_master_logic.sigTimerIntervalUpdated.connect(self.measurement_timer_updated)
976
        self._pulsed_master_logic.sigAnalysisWindowsUpdated.connect(self.analysis_windows_updated)
977
        self._pulsed_master_logic.sigAnalysisMethodUpdated.connect(self.analysis_method_updated)
978
979
        # connect button click signals
980
        self._pg.upload_ensemble_PushButton.clicked.connect(self.upload_ensemble_clicked)
981
        self._pg.load_ensemble_PushButton.clicked.connect(self.load_ensemble_clicked)
982
        # self._pg.upload_sequence_PushButton.clicked.connect(self.upload_sequence_clicked)
983
        # self._pg.load_sequence_PushButton.clicked.connect(self.load_sequence_clicked)
984
        self._mw.pulser_on_off_PushButton.clicked.connect(self.pulser_on_off_clicked)
985
        self._mw.clear_device_PushButton.clicked.connect(self.clear_pulser_clicked)
986
        self._pa.fit_param_PushButton.clicked.connect(self.fit_clicked)
987
988
        # connect action trigger signals
989
        self._mw.action_run_stop.triggered.connect(self.measurement_run_stop_clicked)
990
        self._mw.action_continue_pause.triggered.connect(self.measurement_continue_pause_clicked)
991
        self._mw.action_pull_data.triggered.connect(self.pull_data_clicked)
992
        self._mw.action_save.triggered.connect(self.save_clicked)
993
        self._mw.action_Settings_Analysis.triggered.connect(self.show_analysis_settings)
994
995
        # connect checkbox click signals
996
        self._pa.ext_control_use_mw_CheckBox.stateChanged.connect(self.ext_mw_params_changed)
997
        self._pa.ana_param_x_axis_defined_CheckBox.stateChanged.connect(self.toggle_laser_xaxis_editor)
998
        self._pa.ana_param_laserpulse_defined_CheckBox.stateChanged.connect(self.toggle_laser_xaxis_editor)
999
        self._pa.ana_param_alternating_CheckBox.stateChanged.connect(self.measurement_sequence_settings_changed)
1000
        self._pa.ana_param_ignore_first_CheckBox.stateChanged.connect(self.measurement_sequence_settings_changed)
1001
        self._pa.ana_param_ignore_last_CheckBox.stateChanged.connect(self.measurement_sequence_settings_changed)
1002
        self._pe.laserpulses_display_raw_CheckBox.stateChanged.connect(self.laser_to_show_changed)
1003
        self._pa.ana_param_errorbars_CheckBox.stateChanged.connect(self.toggle_error_bars)
1004
        self._pa.pulser_use_interleave_CheckBox.stateChanged.connect(self.pulse_generator_settings_changed)
1005
1006
        # connect spinbox changed signals
1007
        self._pa.ana_param_num_laser_pulse_SpinBox.editingFinished.connect(self.measurement_sequence_settings_changed)
1008
        self._pa.ana_param_record_length_SpinBox.editingFinished.connect(self.fast_counter_settings_changed)
1009
        self._pa.time_param_ana_periode_DoubleSpinBox.editingFinished.connect(self.measurement_timer_changed)
1010
        self._pa.ext_control_mw_freq_DoubleSpinBox.editingFinished.connect(self.ext_mw_params_changed)
1011
        self._pa.ext_control_mw_power_DoubleSpinBox.editingFinished.connect(self.ext_mw_params_changed)
1012
        self._pa.pulser_sample_freq_DSpinBox.editingFinished.connect(self.pulse_generator_settings_changed)
1013
        self._pa.ana_param_x_axis_start_ScienDSpinBox.editingFinished.connect(self.measurement_sequence_settings_changed)
1014
        self._pa.ana_param_x_axis_inc_ScienDSpinBox.editingFinished.connect(self.measurement_sequence_settings_changed)
1015
        self._pe.extract_param_ana_window_start_SpinBox.editingFinished.connect(self.analysis_windows_changed)
1016
        self._pe.extract_param_ana_window_width_SpinBox.editingFinished.connect(self.analysis_windows_changed)
1017
        self._pe.extract_param_ref_window_start_SpinBox.editingFinished.connect(self.analysis_windows_changed)
1018
        self._pe.extract_param_ref_window_width_SpinBox.editingFinished.connect(self.analysis_windows_changed)
1019
        self._pe.conv_std_dev.valueChanged.connect(self.conv_std_dev_changed)
1020
1021
        # connect combobox changed signals
1022
        self._pa.ana_param_fc_bins_ComboBox.currentIndexChanged.connect(self.fast_counter_settings_changed)
1023
        #self._pa.second_plot_ComboBox.currentIndexChanged.connect(self.change_second_plot)
1024
        self._pa.pulser_activation_config_ComboBox.currentIndexChanged.connect(self.pulse_generator_settings_changed)
1025
        self._pe.laserpulses_ComboBox.currentIndexChanged.connect(self.laser_to_show_changed)
1026
1027
        # connect other widgets changed signals
1028
        self.sig_start_line.sigPositionChanged.connect(self.analysis_windows_line_changed)
1029
        self.sig_end_line.sigPositionChanged.connect(self.analysis_windows_line_changed)
1030
        self.ref_start_line.sigPositionChanged.connect(self.analysis_windows_line_changed)
1031
        self.ref_end_line.sigPositionChanged.connect(self.analysis_windows_line_changed)
1032
        self._pe.slider_conv_std_dev.sliderReleased.connect(self.slider_conv_std_dev_changed)
1033
1034
        # apply hardware constraints
1035
        self._analysis_apply_hardware_constraints()
1036
1037
        # initialize values
1038
        self._pulsed_master_logic.request_measurement_init_values()
1039
        return
1040
1041
    def _deactivate_analysis_ui(self, e):
1042
        """ Disconnects the configuration for 'Analysis' Tab.
1043
1044
       @param object e: Fysom.event object from Fysom class. A more detailed
1045
                         explanation can be found in the method initUI.
1046
        """
1047
        self.measurement_run_stop_clicked(False)
1048
1049
        self._statusVariables['ana_param_x_axis_defined_CheckBox'] = self._pa.ana_param_x_axis_defined_CheckBox.isChecked()
1050
        self._statusVariables['ana_param_laserpulse_defined_CheckBox'] = self._pa.ana_param_laserpulse_defined_CheckBox.isChecked()
1051
        self._statusVariables['ana_param_ignore_first_CheckBox'] = self._pa.ana_param_ignore_first_CheckBox.isChecked()
1052
        self._statusVariables['ana_param_ignore_last_CheckBox'] = self._pa.ana_param_ignore_last_CheckBox.isChecked()
1053
        self._statusVariables['ana_param_errorbars_CheckBox'] = self._pa.ana_param_errorbars_CheckBox.isChecked()
1054
        self._statusVariables['second_plot_ComboBox_text'] = self._pa.second_plot_ComboBox.currentText()
1055
1056
        # disconnect signals
1057
        self._pulsed_master_logic.sigSignalDataUpdated.disconnect()
1058
        self._pulsed_master_logic.sigLaserDataUpdated.disconnect()
1059
        self._pulsed_master_logic.sigLaserToShowUpdated.disconnect()
1060
        self._pulsed_master_logic.sigElapsedTimeUpdated.disconnect()
1061
        self._pulsed_master_logic.sigFitUpdated.disconnect()
1062
        self._pulsed_master_logic.sigMeasurementStatusUpdated.disconnect()
1063
        self._pulsed_master_logic.sigPulserRunningUpdated.disconnect()
1064
        self._pulsed_master_logic.sigFastCounterSettingsUpdated.disconnect()
1065
        self._pulsed_master_logic.sigMeasurementSequenceSettingsUpdated.disconnect()
1066
        self._pulsed_master_logic.sigPulserSettingsUpdated.disconnect()
1067
        self._pulsed_master_logic.sigUploadedAssetsUpdated.disconnect()
1068
        self._pulsed_master_logic.sigLoadedAssetUpdated.disconnect()
1069
        self._pulsed_master_logic.sigExtMicrowaveSettingsUpdated.disconnect()
1070
        self._pulsed_master_logic.sigExtMicrowaveRunningUpdated.disconnect()
1071
        self._pulsed_master_logic.sigTimerIntervalUpdated.disconnect()
1072
        self._pulsed_master_logic.sigAnalysisWindowsUpdated.disconnect()
1073
        self._pulsed_master_logic.sigAnalysisMethodUpdated.disconnect()
1074
        self._pg.upload_ensemble_PushButton.clicked.disconnect()
1075
        self._pg.load_ensemble_PushButton.clicked.disconnect()
1076
        # self._pg.upload_sequence_PushButton.clicked.disconnect()
1077
        # self._pg.load_sequence_PushButton.clicked.disconnect()
1078
        self._mw.pulser_on_off_PushButton.clicked.disconnect()
1079
        self._mw.clear_device_PushButton.clicked.disconnect()
1080
        self._pa.fit_param_PushButton.clicked.disconnect()
1081
        self._mw.action_run_stop.triggered.disconnect()
1082
        self._mw.action_continue_pause.triggered.disconnect()
1083
        self._mw.action_pull_data.triggered.disconnect()
1084
        self._mw.action_save.triggered.disconnect()
1085
        self._mw.action_Settings_Analysis.triggered.disconnect()
1086
        self._pa.ext_control_use_mw_CheckBox.stateChanged.disconnect()
1087
        self._pa.ana_param_x_axis_defined_CheckBox.stateChanged.disconnect()
1088
        self._pa.ana_param_laserpulse_defined_CheckBox.stateChanged.disconnect()
1089
        self._pa.ana_param_alternating_CheckBox.stateChanged.disconnect()
1090
        self._pa.ana_param_ignore_first_CheckBox.stateChanged.disconnect()
1091
        self._pa.ana_param_ignore_last_CheckBox.stateChanged.disconnect()
1092
        self._pe.laserpulses_display_raw_CheckBox.stateChanged.disconnect()
1093
        self._pa.ana_param_errorbars_CheckBox.stateChanged.disconnect()
1094
        self._pa.pulser_use_interleave_CheckBox.stateChanged.disconnect()
1095
        self._pa.ana_param_num_laser_pulse_SpinBox.editingFinished.disconnect()
1096
        self._pa.ana_param_record_length_SpinBox.editingFinished.disconnect()
1097
        self._pa.time_param_ana_periode_DoubleSpinBox.editingFinished.disconnect()
1098
        self._pa.ext_control_mw_freq_DoubleSpinBox.editingFinished.disconnect()
1099
        self._pa.ext_control_mw_power_DoubleSpinBox.editingFinished.disconnect()
1100
        self._pa.pulser_sample_freq_DSpinBox.editingFinished.disconnect()
1101
        self._pa.ana_param_x_axis_start_ScienDSpinBox.editingFinished.disconnect()
1102
        self._pa.ana_param_x_axis_inc_ScienDSpinBox.editingFinished.disconnect()
1103
        self._pe.extract_param_ana_window_start_SpinBox.editingFinished.disconnect()
1104
        self._pe.extract_param_ana_window_width_SpinBox.editingFinished.disconnect()
1105
        self._pe.extract_param_ref_window_start_SpinBox.editingFinished.disconnect()
1106
        self._pe.extract_param_ref_window_width_SpinBox.editingFinished.disconnect()
1107
        self._pe.conv_std_dev.valueChanged.disconnect()
1108
        self._pa.ana_param_fc_bins_ComboBox.currentIndexChanged.disconnect()
1109
        #self._pa.second_plot_ComboBox.currentIndexChanged.disconnect()
1110
        self._pa.pulser_activation_config_ComboBox.currentIndexChanged.disconnect()
1111
        self._pe.laserpulses_ComboBox.currentIndexChanged.disconnect()
1112
        self.sig_start_line.sigPositionChanged.disconnect()
1113
        self.sig_end_line.sigPositionChanged.disconnect()
1114
        self.ref_start_line.sigPositionChanged.disconnect()
1115
        self.ref_end_line.sigPositionChanged.disconnect()
1116
        self._pe.slider_conv_std_dev.sliderReleased.disconnect()
1117
        return
1118
1119
    def _analysis_apply_hardware_constraints(self):
1120
        """
1121
        Retrieve the constraints from pulser and fast counter hardware and apply these constraints
1122
        to the analysis tab GUI elements.
1123
        """
1124
        # block signals
1125
        self._pa.pulser_activation_config_ComboBox.blockSignals(True)
1126
        self._pa.ana_param_fc_bins_ComboBox.blockSignals(True)
1127
        # apply constraints
1128
        pulser_constr, fastcounter_constr = self._pulsed_master_logic.get_hardware_constraints()
1129
        sample_min = pulser_constr['sample_rate']['min']
1130
        sample_max = pulser_constr['sample_rate']['max']
1131
        sample_step = pulser_constr['sample_rate']['step']
1132
        self._pa.pulser_sample_freq_DSpinBox.setMinimum(sample_min)
1133
        self._pa.pulser_sample_freq_DSpinBox.setMaximum(sample_max)
1134
        self._pa.pulser_sample_freq_DSpinBox.setSingleStep(sample_step)
1135
        self._pa.pulser_activation_config_ComboBox.clear()
1136
        self._pa.pulser_activation_config_ComboBox.addItems(list(pulser_constr['activation_config']))
1137
        self._pa.ana_param_fc_bins_ComboBox.clear()
1138
        for binwidth in fastcounter_constr['hardware_binwidth_list']:
1139
            self._pa.ana_param_fc_bins_ComboBox.addItem(str(binwidth))
1140
        # unblock signals
1141
        self._pa.pulser_activation_config_ComboBox.blockSignals(False)
1142
        self._pa.ana_param_fc_bins_ComboBox.blockSignals(False)
1143
        return
1144
1145
    def measurement_run_stop_clicked(self, isChecked):
1146
        """ Manages what happens if pulsed measurement is started or stopped.
1147
1148
        @param bool isChecked: start scan if that is possible
1149
        """
1150
        if isChecked:
1151
            self._pulsed_master_logic.start_measurement()
1152
        else:
1153
            self._pulsed_master_logic.stop_measurement()
1154
        return
1155
1156
    #ToDo: I think that is not really working yet. Yeap, true....
1157
    def measurement_continue_pause_clicked(self, isChecked):
1158
        """ Continues and pauses the measurement. """
1159
        if isChecked:
1160
            self._pulsed_master_logic.pause_measurement()
1161
        else:
1162
            self._pulsed_master_logic.continue_measurement()
1163
        return
1164
1165
    def measurement_status_updated(self, is_running, is_paused):
1166
        """
1167
1168
        @param is_running:
1169
        @param is_paused:
1170
        @return:
1171
        """
1172
        # block signals
1173
        self._mw.action_run_stop.blockSignals(True)
1174
        self._mw.action_continue_pause.blockSignals(True)
1175
1176
        # Enable/Disable widgets
1177
        if is_running:
1178
            self._pa.ext_control_use_mw_CheckBox.setEnabled(False)
1179
            self._pa.ext_control_mw_freq_DoubleSpinBox.setEnabled(False)
1180
            self._pa.ext_control_mw_power_DoubleSpinBox.setEnabled(False)
1181
            self._pa.pulser_sample_freq_DSpinBox.setEnabled(False)
1182
            self._pa.pulser_activation_config_ComboBox.setEnabled(False)
1183
            self._pa.ana_param_fc_bins_ComboBox.setEnabled(False)
1184
            self._pa.ana_param_laserpulse_defined_CheckBox.setEnabled(False)
1185
            self._pa.ana_param_num_laser_pulse_SpinBox.setEnabled(False)
1186
            self._pa.ana_param_record_length_SpinBox.setEnabled(False)
1187
            self._pa.ana_param_ignore_first_CheckBox.setEnabled(False)
1188
            self._pa.ana_param_ignore_last_CheckBox.setEnabled(False)
1189
            self._pa.ana_param_alternating_CheckBox.setEnabled(False)
1190
            self._pa.ana_param_x_axis_defined_CheckBox.setEnabled(False)
1191
            self._pa.ana_param_x_axis_start_ScienDSpinBox.setEnabled(False)
1192
            self._pa.ana_param_x_axis_inc_ScienDSpinBox.setEnabled(False)
1193
            self._pg.load_ensemble_PushButton.setEnabled(False)
1194
            # self._pg.load_sequence_PushButton.setEnabled(False)
1195
            self._mw.pulser_on_off_PushButton.setEnabled(False)
1196
            self._mw.action_continue_pause.setEnabled(True)
1197
            self._mw.action_pull_data.setEnabled(True)
1198
            if not self._mw.action_run_stop.isChecked():
1199
                self._mw.action_run_stop.toggle()
1200
        else:
1201
            self._pa.ext_control_use_mw_CheckBox.setEnabled(True)
1202
            self._pa.ext_control_mw_freq_DoubleSpinBox.setEnabled(True)
1203
            self._pa.ext_control_mw_power_DoubleSpinBox.setEnabled(True)
1204
            self._pa.pulser_sample_freq_DSpinBox.setEnabled(True)
1205
            self._pa.pulser_activation_config_ComboBox.setEnabled(True)
1206
            self._pa.ana_param_fc_bins_ComboBox.setEnabled(True)
1207
            self._pa.ana_param_laserpulse_defined_CheckBox.setEnabled(True)
1208
            self._pa.ana_param_num_laser_pulse_SpinBox.setEnabled(True)
1209
            self._pa.ana_param_record_length_SpinBox.setEnabled(True)
1210
            self._pa.ana_param_ignore_first_CheckBox.setEnabled(True)
1211
            self._pa.ana_param_ignore_last_CheckBox.setEnabled(True)
1212
            self._pa.ana_param_alternating_CheckBox.setEnabled(True)
1213
            self._pa.ana_param_x_axis_defined_CheckBox.setEnabled(True)
1214
            self._pa.ana_param_x_axis_start_ScienDSpinBox.setEnabled(True)
1215
            self._pa.ana_param_x_axis_inc_ScienDSpinBox.setEnabled(True)
1216
            self._pg.load_ensemble_PushButton.setEnabled(True)
1217
            # self._pg.load_sequence_PushButton.setEnabled(True)
1218
            self._mw.pulser_on_off_PushButton.setEnabled(True)
1219
            self._mw.action_continue_pause.setEnabled(False)
1220
            self._mw.action_pull_data.setEnabled(False)
1221
            if self._mw.action_run_stop.isChecked():
1222
                self._mw.action_run_stop.toggle()
1223
        if is_paused:
1224
            if not self._mw.action_continue_pause.isChecked():
1225
                self._mw.action_continue_pause.toggle()
1226
        else:
1227
            if self._mw.action_continue_pause.isChecked():
1228
                self._mw.action_continue_pause.toggle()
1229
        # unblock signals
1230
        self._mw.action_run_stop.blockSignals(False)
1231
        self._mw.action_continue_pause.blockSignals(False)
1232
        return
1233
1234
    def pull_data_clicked(self):
1235
        """ Pulls and analysis the data when the 'action_pull_data'-button is clicked. """
1236
        self._pulsed_master_logic.manually_pull_data()
1237
        return
1238
1239
    def signal_data_updated(self, x_data, y_signal_data, y2_signal_data, y_error_data, y2_error_data):
1240
        """
1241
1242
        @param x_data:
1243
        @param y_signal_data:
1244
        @param y2_signal_data:
1245
        @param y_error_data:
1246
        @param y2_error_data:
1247
        @return:
1248
        """
1249
        show_error_bars = self._pa.ana_param_errorbars_CheckBox.isChecked()
1250
        is_alternating = self._pa.ana_param_alternating_CheckBox.isChecked()
1251
        if show_error_bars:
1252
            beamwidth = np.inf
1253
            for i in range(len(x_data) - 1):
1254
                width = x_data[i + 1] - x_data[i]
1255
                width = width / 3
1256
                if width <= beamwidth:
1257
                    beamwidth = width
1258
            # create ErrorBarItems
1259
            self.signal_image_error_bars.setData(x=x_data, y=y_signal_data, top=y_error_data,
1260
                                                 bottom=y_error_data, beam=beamwidth)
1261
            if is_alternating:
1262
                self.signal_image_error_bars2.setData(x=x_data, y=y2_signal_data, top=y2_error_data,
1263
                                                      bottom=y2_error_data, beam=beamwidth)
1264
            if not self.signal_image_error_bars in self._pa.pulse_analysis_PlotWidget.items():
1265
                self._pa.pulse_analysis_PlotWidget.addItem(self.signal_image_error_bars)
1266
                if is_alternating:
1267
                    self._pa.pulse_analysis_PlotWidget.addItem(self.signal_image_error_bars2)
1268
        else:
1269
            if self.signal_image_error_bars in self._pa.pulse_analysis_PlotWidget.items():
1270
                self._pa.pulse_analysis_PlotWidget.removeItem(self.signal_image_error_bars)
1271
                if is_alternating:
1272
                    self._pa.pulse_analysis_PlotWidget.addItem(self.signal_image_error_bars2)
1273
1274
        # dealing with the actual signal
1275
        self.signal_image.setData(x=x_data, y=y_signal_data)
1276
        if is_alternating:
1277
            self.signal_image2.setData(x=x_data, y=y2_signal_data)
1278
1279
        # dealing with the error plot
1280
        self.measuring_error_image.setData(x=x_data, y=y_error_data)
1281
        if is_alternating:
1282
            self.measuring_error_image2.setData(x=x_data, y=y2_error_data)
1283
        return
1284
1285
    # FIXME: Implement that
1286
    def save_clicked(self):
1287
        """Saves the current data"""
1288
        self._mw.action_save.setEnabled(False)
1289
        save_tag = self._mw.save_tag_LineEdit.text()
1290
        self._pulsed_master_logic.save_measurement_data(save_tag)
1291
        self._mw.action_save.setEnabled(True)
1292
        return
1293
1294
    def fit_clicked(self):
1295
        """Fits the current data"""
1296
        current_fit_function = self._pa.fit_param_fit_func_ComboBox.currentText()
1297
        self._pulsed_master_logic.do_fit(current_fit_function)
1298
        return
1299
1300
    def fit_data_updated(self, fit_function, fit_data_x, fit_data_y, param_dict, result_dict):
1301
        """
1302
1303
        @param fit_function:
1304
        @param fit_data_x:
1305
        @param fit_data_y:
1306
        @param param_dict:
1307
        @param result_dict:
1308
        @return:
1309
        """
1310
        # block signals
1311
        self._pa.fit_param_fit_func_ComboBox.blockSignals(True)
1312
        # set widgets
1313
        self._pa.fit_param_results_TextBrowser.clear()
1314
        fit_text = units.create_formatted_output(param_dict)
1315
        self._pa.fit_param_results_TextBrowser.setPlainText(fit_text)
1316
        self.fit_image.setData(x=fit_data_x, y=fit_data_y)
1317
        if fit_function == 'No Fit' and self.fit_image in self._pa.pulse_analysis_PlotWidget.items():
1318
            self._pa.pulse_analysis_PlotWidget.removeItem(self.fit_image)
1319
        elif fit_function != 'No Fit' and self.fit_image not in self._pa.pulse_analysis_PlotWidget.items():
1320
            self._pa.pulse_analysis_PlotWidget.addItem(self.fit_image)
1321
        if self._pa.fit_param_fit_func_ComboBox.currentText() != fit_function:
1322
            index = self._pa.fit_param_fit_func_ComboBox.findText(fit_function)
1323
            if index >= 0:
1324
                self._pa.fit_param_fit_func_ComboBox.setCurrentIndex(index)
1325
        # unblock signals
1326
        self._pa.fit_param_fit_func_ComboBox.blockSignals(False)
1327
        return
1328
1329
    def elapsed_time_updated(self, elapsed_time, elapsed_time_str):
1330
        """
1331
        Refreshes the elapsed time and sweeps of the measurement.
1332
1333
        @param elapsed_time:
1334
        @param elapsed_time_str:
1335
        @return:
1336
        """
1337
        # block signals
1338
        self._pa.time_param_elapsed_time_LineEdit.blockSignals(True)
1339
        # Set widgets
1340
        self._pa.time_param_elapsed_time_LineEdit.setText(elapsed_time_str)
1341
        # unblock signals
1342
        self._pa.time_param_elapsed_time_LineEdit.blockSignals(True)
1343
        return
1344
1345
    def ext_mw_params_changed(self):
1346
        """ Shows or hides input widgets which are necessary if an external mw is turned on"""
1347
        use_ext_microwave = self._pa.ext_control_use_mw_CheckBox.isChecked()
1348
        microwave_freq = self._pa.ext_control_mw_freq_DoubleSpinBox.value()
1349
        microwave_power = self._pa.ext_control_mw_power_DoubleSpinBox.value()
1350 View Code Duplication
        if use_ext_microwave:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1351
            self._pa.ext_control_mw_freq_Label.setEnabled(True)
1352
            self._pa.ext_control_mw_freq_DoubleSpinBox.setEnabled(True)
1353
            self._pa.ext_control_mw_power_Label.setEnabled(True)
1354
            self._pa.ext_control_mw_power_DoubleSpinBox.setEnabled(True)
1355
1356
            self._pa.ext_control_mw_freq_Label.setVisible(True)
1357
            self._pa.ext_control_mw_freq_DoubleSpinBox.setVisible(True)
1358
            self._pa.ext_control_mw_power_Label.setVisible(True)
1359
            self._pa.ext_control_mw_power_DoubleSpinBox.setVisible(True)
1360
        else:
1361
            self._pa.ext_control_mw_freq_Label.setEnabled(False)
1362
            self._pa.ext_control_mw_freq_DoubleSpinBox.setEnabled(False)
1363
            self._pa.ext_control_mw_power_Label.setEnabled(False)
1364
            self._pa.ext_control_mw_power_DoubleSpinBox.setEnabled(False)
1365
1366
            self._pa.ext_control_mw_freq_Label.setVisible(False)
1367
            self._pa.ext_control_mw_freq_DoubleSpinBox.setVisible(False)
1368
            self._pa.ext_control_mw_power_Label.setVisible(False)
1369
            self._pa.ext_control_mw_power_DoubleSpinBox.setVisible(False)
1370
1371
        self._pulsed_master_logic.ext_microwave_settings_changed(microwave_freq, microwave_power,
1372
                                                                 use_ext_microwave)
1373
        return
1374
1375
    def microwave_settings_updated(self, frequency, power, use_ext_microwave):
1376
        """
1377
1378
        @param frequency:
1379
        @param power:
1380
        @param use_ext_microwave:
1381
        @return:
1382
        """
1383
        # block signals
1384
        self._pa.ext_control_mw_freq_DoubleSpinBox.blockSignals(True)
1385
        self._pa.ext_control_mw_power_DoubleSpinBox.blockSignals(True)
1386
        self._pa.ext_control_use_mw_CheckBox.blockSignals(True)
1387
        # set widgets
1388
        self._pa.ext_control_mw_freq_DoubleSpinBox.setValue(frequency)
1389
        self._pa.ext_control_mw_power_DoubleSpinBox.setValue(power)
1390
        self._pa.ext_control_use_mw_CheckBox.setChecked(use_ext_microwave)
1391
        # set visibility
1392 View Code Duplication
        if use_ext_microwave:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1393
            self._pa.ext_control_mw_freq_Label.setEnabled(True)
1394
            self._pa.ext_control_mw_freq_DoubleSpinBox.setEnabled(True)
1395
            self._pa.ext_control_mw_power_Label.setEnabled(True)
1396
            self._pa.ext_control_mw_power_DoubleSpinBox.setEnabled(True)
1397
1398
            self._pa.ext_control_mw_freq_Label.setVisible(True)
1399
            self._pa.ext_control_mw_freq_DoubleSpinBox.setVisible(True)
1400
            self._pa.ext_control_mw_power_Label.setVisible(True)
1401
            self._pa.ext_control_mw_power_DoubleSpinBox.setVisible(True)
1402
        else:
1403
            self._pa.ext_control_mw_freq_Label.setEnabled(False)
1404
            self._pa.ext_control_mw_freq_DoubleSpinBox.setEnabled(False)
1405
            self._pa.ext_control_mw_power_Label.setEnabled(False)
1406
            self._pa.ext_control_mw_power_DoubleSpinBox.setEnabled(False)
1407
1408
            self._pa.ext_control_mw_freq_Label.setVisible(False)
1409
            self._pa.ext_control_mw_freq_DoubleSpinBox.setVisible(False)
1410
            self._pa.ext_control_mw_power_Label.setVisible(False)
1411
            self._pa.ext_control_mw_power_DoubleSpinBox.setVisible(False)
1412
        # unblock signals
1413
        self._pa.ext_control_mw_freq_DoubleSpinBox.blockSignals(False)
1414
        self._pa.ext_control_mw_power_DoubleSpinBox.blockSignals(False)
1415
        self._pa.ext_control_use_mw_CheckBox.blockSignals(False)
1416
        return
1417
1418
    def microwave_running_updated(self, is_running):
1419
        """
1420
1421
        @return:
1422
        """
1423
        pass
1424
1425
    def pulse_generator_settings_changed(self):
1426
        """
1427
1428
        @return:
1429
        """
1430
        # FIXME: Properly implement amplitude and interleave
1431
        sample_rate_hz = self._pa.pulser_sample_freq_DSpinBox.value()
1432
        activation_config_name = self._pa.pulser_activation_config_ComboBox.currentText()
1433
        analogue_amplitude, dummy = self._pulsed_master_logic._measurement_logic._pulse_generator_device.get_analog_level()
1434
        interleave_on = self._pa.pulser_use_interleave_CheckBox.isChecked()
1435
        self._pulsed_master_logic.pulse_generator_settings_changed(sample_rate_hz,
1436
                                                                   activation_config_name,
1437
                                                                   analogue_amplitude,
1438
                                                                   interleave_on)
1439
        return
1440
1441
    def pulse_generator_settings_updated(self, sample_rate_hz, activation_config_name,
1442
                                         activation_config, analogue_amplitude, interleave_on):
1443
        """
1444
1445
        @param sample_rate_hz:
1446
        @param activation_config_name:
1447
        @param analogue_amplitude:
1448
        @param interleave_on:
1449
        @return:
1450
        """
1451
        # block signals
1452
        self._pa.pulser_sample_freq_DSpinBox.blockSignals(True)
1453
        self._pa.pulser_activation_config_ComboBox.blockSignals(True)
1454
        self._pa.pulser_activation_config_LineEdit.blockSignals(True)
1455
        self._pa.pulser_use_interleave_CheckBox.blockSignals(True)
1456
        # Set widgets
1457
        # FIXME: Properly implement amplitude and interleave
1458
        self._pa.pulser_sample_freq_DSpinBox.setValue(sample_rate_hz)
1459
        index = self._pa.pulser_activation_config_ComboBox.findText(activation_config_name)
1460
        self._pa.pulser_activation_config_ComboBox.setCurrentIndex(index)
1461
        config_display_str = ''
1462
        for channel in activation_config:
1463
            config_display_str += channel + ' | '
1464
        config_display_str = config_display_str[:-3]
1465
        self._pa.pulser_activation_config_LineEdit.setText(config_display_str)
1466
        self._pa.pulser_use_interleave_CheckBox.setChecked(interleave_on)
1467
        # unblock signals
1468
        self._pa.pulser_sample_freq_DSpinBox.blockSignals(False)
1469
        self._pa.pulser_activation_config_ComboBox.blockSignals(False)
1470
        self._pa.pulser_activation_config_LineEdit.blockSignals(False)
1471
        self._pa.pulser_use_interleave_CheckBox.blockSignals(False)
1472
        return
1473
1474
    def fast_counter_settings_changed(self):
1475
        """
1476
1477
        @return:
1478
        """
1479
        record_length_s = self._pa.ana_param_record_length_SpinBox.value()
1480
        bin_width_s = float(self._pa.ana_param_fc_bins_ComboBox.currentText())
1481
        self._pulsed_master_logic.fast_counter_settings_changed(bin_width_s, record_length_s)
1482
        return
1483
1484
    def fast_counter_settings_updated(self, bin_width_s, record_length_s):
1485
        """
1486
1487
        @param bin_width_s:
1488
        @param record_length_s:
1489
        @return:
1490
        """
1491
        # block signals
1492
        self._pa.ana_param_record_length_SpinBox.blockSignals(True)
1493
        self._pa.ana_param_fc_bins_ComboBox.blockSignals(True)
1494
        # set widgets
1495
        self._pa.ana_param_record_length_SpinBox.setValue(record_length_s)
1496
        index = self._pa.ana_param_fc_bins_ComboBox.findText(str(bin_width_s))
1497
        self._pa.ana_param_fc_bins_ComboBox.setCurrentIndex(index)
1498
        # unblock signals
1499
        self._pa.ana_param_record_length_SpinBox.blockSignals(False)
1500
        self._pa.ana_param_fc_bins_ComboBox.blockSignals(False)
1501
        return
1502
1503
    def measurement_sequence_settings_changed(self):
1504
        """
1505
1506
        @return:
1507
        """
1508
        laser_ignore_list = []
1509
        if self._pa.ana_param_ignore_first_CheckBox.isChecked():
1510
            laser_ignore_list.append(0)
1511
        if self._pa.ana_param_ignore_last_CheckBox.isChecked():
1512
            laser_ignore_list.append(-1)
1513
        alternating = self._pa.ana_param_alternating_CheckBox.isChecked()
1514
        num_of_lasers = self._pa.ana_param_num_laser_pulse_SpinBox.value()
1515
        xaxis_start = self._pa.ana_param_x_axis_start_ScienDSpinBox.value()
1516
        xaxis_incr = self._pa.ana_param_x_axis_inc_ScienDSpinBox.value()
1517
        laser_trigger_delay = self._as.ana_param_lasertrigger_delay_ScienDSpinBox.value()
1518
        # FIXME: properly implement sequence_length_s
1519
        sequence_length_s = self._pulsed_master_logic._measurement_logic.sequence_length_s
1520
        num_of_ticks = num_of_lasers - len(laser_ignore_list)
1521
        if alternating:
1522
            num_of_ticks //= 2
1523
        measurement_ticks = np.arange(xaxis_start,
1524
                                      xaxis_start + (xaxis_incr * num_of_ticks) - (xaxis_incr / 2),
1525
                                      xaxis_incr)
1526
1527
        self._pulsed_master_logic.measurement_sequence_settings_changed(measurement_ticks,
1528
                                                                        num_of_lasers,
1529
                                                                        sequence_length_s,
1530
                                                                        laser_ignore_list,
1531
                                                                        alternating,
1532
                                                                        laser_trigger_delay)
1533
        return
1534
1535
    def measurement_sequence_settings_updated(self, measurement_ticks, number_of_lasers,
1536
                                              sequence_length_s, laser_ignore_list, alternating,
1537
                                              laser_trigger_delay):
1538
        """
1539
1540
        @param measurement_ticks:
1541
        @param number_of_lasers:
1542
        @param sequence_length_s:
1543
        @param laser_ignore_list:
1544
        @param alternating:
1545
        @param laser_trigger_delay:
1546
        @return:
1547
        """
1548
        # block signals
1549
        self._pa.ana_param_ignore_first_CheckBox.blockSignals(True)
1550
        self._pa.ana_param_ignore_last_CheckBox.blockSignals(True)
1551
        self._pa.ana_param_alternating_CheckBox.blockSignals(True)
1552
        self._pa.ana_param_num_laser_pulse_SpinBox.blockSignals(True)
1553
        self._pa.ana_param_x_axis_start_ScienDSpinBox.blockSignals(True)
1554
        self._pa.ana_param_x_axis_inc_ScienDSpinBox.blockSignals(True)
1555
        self._as.ana_param_lasertrigger_delay_ScienDSpinBox.blockSignals(True)
1556
        self._pe.laserpulses_ComboBox.blockSignals(True)
1557
        # set widgets
1558
        self._pa.ana_param_ignore_first_CheckBox.setChecked(0 in laser_ignore_list)
1559
        self._pa.ana_param_ignore_last_CheckBox.setChecked(-1 in laser_ignore_list)
1560
        self._pa.ana_param_alternating_CheckBox.setChecked(alternating)
1561
        self._pa.ana_param_num_laser_pulse_SpinBox.setValue(number_of_lasers)
1562
        self._as.ana_param_lasertrigger_delay_ScienDSpinBox.setValue(laser_trigger_delay)
1563
        self._pa.ana_param_x_axis_start_ScienDSpinBox.setValue(measurement_ticks[0])
1564
        self._pa.ana_param_x_axis_inc_ScienDSpinBox.setValue(
1565
            (measurement_ticks[-1] - measurement_ticks[0]) / (len(measurement_ticks)-1))
1566
        self._pe.laserpulses_ComboBox.addItems([str(i) for i in range(number_of_lasers+1)])
1567
        # change plots accordingly
1568
        if alternating:
1569
            if self.signal_image2 not in self._pa.pulse_analysis_PlotWidget.items():
1570
                self._pa.pulse_analysis_PlotWidget.addItem(self.signal_image2)
1571
            if self.signal_image_error_bars in self._pa.pulse_analysis_PlotWidget.items() and self.signal_image_error_bars2 not in self._pa.pulse_analysis_PlotWidget.items():
1572
                self._pa.pulse_analysis_PlotWidget.addItem(self.signal_image_error_bars2)
1573
            if self.measuring_error_image2 not in self._pe.measuring_error_PlotWidget.items():
1574
                self._pe.measuring_error_PlotWidget.addItem(self.measuring_error_image2)
1575
        else:
1576
            if self.signal_image2 in self._pa.pulse_analysis_PlotWidget.items():
1577
                self._pa.pulse_analysis_PlotWidget.removeItem(self.signal_image2)
1578
            if self.signal_image_error_bars2 in self._pa.pulse_analysis_PlotWidget.items():
1579
                self._pa.pulse_analysis_PlotWidget.removeItem(self.signal_image_error_bars2)
1580
            if self.measuring_error_image2 in self._pe.measuring_error_PlotWidget.items():
1581
                self._pe.measuring_error_PlotWidget.removeItem(self.measuring_error_image2)
1582
        # unblock signals
1583
        self._pa.ana_param_ignore_first_CheckBox.blockSignals(False)
1584
        self._pa.ana_param_ignore_last_CheckBox.blockSignals(False)
1585
        self._pa.ana_param_alternating_CheckBox.blockSignals(False)
1586
        self._pa.ana_param_num_laser_pulse_SpinBox.blockSignals(False)
1587
        self._pa.ana_param_x_axis_start_ScienDSpinBox.blockSignals(False)
1588
        self._pa.ana_param_x_axis_inc_ScienDSpinBox.blockSignals(False)
1589
        self._as.ana_param_lasertrigger_delay_ScienDSpinBox.blockSignals(False)
1590
        self._pe.laserpulses_ComboBox.blockSignals(False)
1591
        return
1592
1593
    def toggle_laser_xaxis_editor(self):
1594
        """ Shows or hides input widgets which are necessary if the x axis id defined or not."""
1595
        if self._pa.ana_param_x_axis_defined_CheckBox.isChecked():
1596
            self._pa.ana_param_x_axis_start_Label.setVisible(True)
1597
            self._pa.ana_param_x_axis_start_ScienDSpinBox.setVisible(True)
1598
            self._pa.ana_param_x_axis_inc_Label.setVisible(True)
1599
            self._pa.ana_param_x_axis_inc_ScienDSpinBox.setVisible(True)
1600
            self._pa.ana_param_x_axis_start_ScienDSpinBox.setEnabled(True)
1601
            self._pa.ana_param_x_axis_inc_ScienDSpinBox.setEnabled(True)
1602
        else:
1603
            self._pa.ana_param_x_axis_start_Label.setVisible(False)
1604
            self._pa.ana_param_x_axis_start_ScienDSpinBox.setVisible(False)
1605
            self._pa.ana_param_x_axis_inc_Label.setVisible(False)
1606
            self._pa.ana_param_x_axis_inc_ScienDSpinBox.setVisible(False)
1607
            self._pa.ana_param_x_axis_start_ScienDSpinBox.setEnabled(False)
1608
            self._pa.ana_param_x_axis_inc_ScienDSpinBox.setEnabled(False)
1609
1610
        if self._pa.ana_param_laserpulse_defined_CheckBox.isChecked():
1611
            self._pa.ana_param_num_laserpulses_Label.setVisible(True)
1612
            self._pa.ana_param_num_laser_pulse_SpinBox.setVisible(True)
1613
            self._pa.ana_param_record_length_Label.setVisible(True)
1614
            self._pa.ana_param_record_length_SpinBox.setVisible(True)
1615
            self._pa.ana_param_num_laser_pulse_SpinBox.setEnabled(True)
1616
            self._pa.ana_param_record_length_SpinBox.setEnabled(True)
1617
        else:
1618
            self._pa.ana_param_num_laserpulses_Label.setVisible(False)
1619
            self._pa.ana_param_num_laser_pulse_SpinBox.setVisible(False)
1620
            self._pa.ana_param_record_length_Label.setVisible(False)
1621
            self._pa.ana_param_record_length_SpinBox.setVisible(False)
1622
            self._pa.ana_param_num_laser_pulse_SpinBox.setEnabled(False)
1623
            self._pa.ana_param_record_length_SpinBox.setEnabled(False)
1624
        return
1625
1626
    def toggle_error_bars(self):
1627
        """
1628
1629
        @return:
1630
        """
1631
        show_bars = self._pa.ana_param_errorbars_CheckBox.isChecked()
1632
        is_alternating = self.signal_image2 in self._pa.pulse_analysis_PlotWidget.items()
1633
        if show_bars:
1634
            if self.signal_image_error_bars not in self._pa.pulse_analysis_PlotWidget.items():
1635
                self._pa.pulse_analysis_PlotWidget.addItem(self.signal_image_error_bars)
1636
            if is_alternating and self.signal_image_error_bars2 not in self._pa.pulse_analysis_PlotWidget.items():
1637
                self._pa.pulse_analysis_PlotWidget.addItem(self.signal_image_error_bars2)
1638
        else:
1639
            if self.signal_image_error_bars in self._pa.pulse_analysis_PlotWidget.items():
1640
                self._pa.pulse_analysis_PlotWidget.removeItem(self.signal_image_error_bars)
1641
            if is_alternating and self.signal_image_error_bars2 in self._pa.pulse_analysis_PlotWidget.items():
1642
                self._pa.pulse_analysis_PlotWidget.removeItem(self.signal_image_error_bars2)
1643
        return
1644
1645
    # def change_second_plot(self):
1646
    #     """ This method handles the second plot"""
1647
    #     if self._mw.second_plot_ComboBox.currentText()=='None':
1648
    #         self._mw.second_plot_GroupBox.setVisible(False)
1649
    #     else:
1650
    #         self._mw.second_plot_GroupBox.setVisible(True)
1651
    #
1652
    #         # Here FFT is seperated from the other option. The reason for that
1653
    #         # is preventing of code doubling
1654
    #         if self._mw.second_plot_ComboBox.currentText() == 'FFT':
1655
    #             fft_x, fft_y = self._pulsed_meas_logic.compute_fft()
1656
    #             self.second_plot_image.setData(fft_x, fft_y)
1657
    #             self._mw.pulse_analysis_second_PlotWidget.setLogMode(x=False, y=False)
1658
    #
1659
    #             self._mw.pulse_analysis_second_PlotWidget.setLabel(axis='bottom',
1660
    #                                                                text=self._as.ana_param_second_plot_x_axis_name_LineEdit.text(),
1661
    #                                                                units=self._as.ana_param_second_plot_x_axis_unit_LineEdit.text())
1662
    #             self._mw.pulse_analysis_second_PlotWidget.setLabel(axis='left',
1663
    #                                                                text=self._as.ana_param_second_plot_y_axis_name_LineEdit.text(),
1664
    #                                                                units=self._as.ana_param_second_plot_y_axis_unit_LineEdit.text())
1665
    #
1666
    #         else:
1667
    #             #FIXME: Is not working when there is a 0 in the values, therefore ignoring the first measurment point
1668
    #             self.second_plot_image.setData(self._pulsed_meas_logic.signal_plot_x[1:], self._pulsed_meas_logic.signal_plot_y[1:])
1669
    #
1670
    #             if self._as.ana_param_second_plot_x_axis_name_LineEdit.text()== '':
1671
    #                 self._mw.pulse_analysis_second_PlotWidget.setLabel(axis='left',
1672
    #                                                                    text=self._as.ana_param_y_axis_name_LineEdit.text(),
1673
    #                                                                    units=self._as.ana_param_y_axis_unit_LineEdit.text())
1674
    #                 self._mw.pulse_analysis_second_PlotWidget.setLabel(axis='bottom',
1675
    #                                                                    text=self._as.ana_param_x_axis_name_LineEdit.text(),
1676
    #                                                                    units=self._as.ana_param_x_axis_unit_LineEdit.text())
1677
    #
1678
    #             else:
1679
    #                 self._mw.pulse_analysis_second_PlotWidget.setLabel(axis='bottom',
1680
    #                                                                    text=self._as.ana_param_second_plot_x_axis_name_LineEdit.text(),
1681
    #                                                                    units=self._as.ana_param_second_plot_x_axis_unit_LineEdit.text())
1682
    #                 self._mw.pulse_analysis_second_PlotWidget.setLabel(axis='left',
1683
    #                                                                    text=self._as.ana_param_second_plot_y_axis_name_LineEdit.text(),
1684
    #                                                                    units=self._as.ana_param_second_plot_y_axis_unit_LineEdit.text())
1685
    #
1686
    #             if self._mw.second_plot_ComboBox.currentText() == 'unchanged data':
1687
    #                 self._mw.pulse_analysis_second_PlotWidget.setLogMode(x=False, y=False)
1688
    #
1689
    #             elif self._mw.second_plot_ComboBox.currentText() == 'Log(x)':
1690
    #                 self._mw.pulse_analysis_second_PlotWidget.setLogMode(x=True, y=False)
1691
    #
1692
    #             elif self._mw.second_plot_ComboBox.currentText() == 'Log(y)':
1693
    #                 self._mw.pulse_analysis_second_PlotWidget.setLogMode(x=False,y=True)
1694
    #
1695
    #             elif self._mw.second_plot_ComboBox.currentText() == 'Log(x)&Log(y)':
1696
    #                 self._mw.pulse_analysis_second_PlotWidget.setLogMode(x=True, y=True)
1697
1698
    def measurement_timer_changed(self):
1699
        """ This method handles the analysis timing"""
1700
        timer_interval = self._pa.time_param_ana_periode_DoubleSpinBox.value()
1701
        self._pulsed_master_logic.analysis_interval_changed(timer_interval)
1702
        return
1703
1704
    def measurement_timer_updated(self, timer_interval_s):
1705
        """
1706
1707
        @param timer_interval_s:
1708
        @return:
1709
        """
1710
        # block signals
1711
        self._pa.time_param_ana_periode_DoubleSpinBox.blockSignals(True)
1712
        # set widget
1713
        self._pa.time_param_ana_periode_DoubleSpinBox.setValue(timer_interval_s)
1714
        # unblock signals
1715
        self._pa.time_param_ana_periode_DoubleSpinBox.blockSignals(False)
1716
        return
1717
1718
    def conv_std_dev_changed(self):
1719
        """
1720
        Uodate new value of standard deviation of gaussian filter
1721
        """
1722
        # block signals
1723
        self._pe.slider_conv_std_dev.blockSignals(True)
1724
        # set widgets
1725
        std_dev = self._pe.conv_std_dev.value()
1726
        self._pe.slider_conv_std_dev.setValue(std_dev)
1727
        # unblock signals
1728
        self._pe.slider_conv_std_dev.blockSignals(False)
1729
1730
        self._pulsed_master_logic.analysis_method_changed(std_dev)
1731
        return
1732
1733
    def slider_conv_std_dev_changed(self):
1734
        """
1735
        Uodate new value of standard deviation of gaussian filter
1736
        from slider
1737
        """
1738
        # block signals
1739
        self._pe.conv_std_dev.blockSignals(True)
1740
        # set widgets
1741
        std_dev = self._pe.slider_conv_std_dev.value()
1742
        self._pe.conv_std_dev.setValue(std_dev)
1743
        # unblock signals
1744
        self._pe.conv_std_dev.blockSignals(False)
1745
1746
        self._pulsed_master_logic.analysis_method_changed(std_dev)
1747
        return
1748
1749
    def analysis_method_updated(self, gaussfilt_std_dev):
1750
        """
1751
1752
        @param gaussfilt_std_dev:
1753
        @return:
1754
        """
1755
        # block signals
1756
        self._pe.slider_conv_std_dev.blockSignals(True)
1757
        self._pe.conv_std_dev.blockSignals(True)
1758
        # set widgets
1759
        self._pe.slider_conv_std_dev.setValue(gaussfilt_std_dev)
1760
        self._pe.conv_std_dev.setValue(gaussfilt_std_dev)
1761
        # unblock signals
1762
        self._pe.slider_conv_std_dev.blockSignals(False)
1763
        self._pe.conv_std_dev.blockSignals(False)
1764
        return
1765
1766
    def analysis_windows_changed(self):
1767
        """
1768
1769
        @return:
1770
        """
1771
        # block signals
1772
        self.sig_start_line.blockSignals(True)
1773
        self.sig_end_line.blockSignals(True)
1774
        self.ref_start_line.blockSignals(True)
1775
        self.ref_end_line.blockSignals(True)
1776
        # get data
1777
        sig_start = self._pe.extract_param_ana_window_start_SpinBox.value()
1778
        sig_length = self._pe.extract_param_ana_window_width_SpinBox.value()
1779
        ref_start = self._pe.extract_param_ref_window_start_SpinBox.value()
1780
        ref_length = self._pe.extract_param_ref_window_width_SpinBox.value()
1781
        # update plots
1782
        self.sig_start_line.setValue(sig_start)
1783
        self.sig_end_line.setValue(sig_start + sig_length)
1784
        self.ref_start_line.setValue(ref_start)
1785
        self.ref_end_line.setValue(ref_start + ref_length)
1786
        # unblock signals
1787
        self.sig_start_line.blockSignals(False)
1788
        self.sig_end_line.blockSignals(False)
1789
        self.ref_start_line.blockSignals(False)
1790
        self.ref_end_line.blockSignals(False)
1791
1792
        self._pulsed_master_logic.analysis_windows_changed(sig_start, sig_length, ref_start,
1793
                                                           ref_length)
1794
        return
1795
1796
    def analysis_windows_line_changed(self):
1797
        """
1798
1799
        @return:
1800
        """
1801
        # block signals
1802
        self._pe.extract_param_ana_window_start_SpinBox.blockSignals(True)
1803
        self._pe.extract_param_ana_window_width_SpinBox.blockSignals(True)
1804
        self._pe.extract_param_ref_window_start_SpinBox.blockSignals(True)
1805
        self._pe.extract_param_ref_window_width_SpinBox.blockSignals(True)
1806
        # get data
1807
        sig_start = self.sig_start_line.value()
1808
        sig_length = self.sig_end_line.value() - sig_start
1809
        ref_start = self.ref_start_line.value()
1810
        ref_length = self.ref_end_line.value() - ref_start
1811
        # set widgets
1812
        self._pe.extract_param_ana_window_start_SpinBox.setValue(sig_start)
1813
        self._pe.extract_param_ana_window_width_SpinBox.setValue(sig_length)
1814
        self._pe.extract_param_ref_window_start_SpinBox.setValue(ref_start)
1815
        self._pe.extract_param_ref_window_width_SpinBox.setValue(ref_length)
1816
        # unblock signals
1817
        self._pe.extract_param_ana_window_start_SpinBox.blockSignals(False)
1818
        self._pe.extract_param_ana_window_width_SpinBox.blockSignals(False)
1819
        self._pe.extract_param_ref_window_start_SpinBox.blockSignals(False)
1820
        self._pe.extract_param_ref_window_width_SpinBox.blockSignals(False)
1821
        return
1822
1823
    def analysis_windows_updated(self, sig_start, sig_length, ref_start, ref_length):
1824
        """
1825
1826
        @param sig_start:
1827
        @param sig_length:
1828
        @param ref_start:
1829
        @param ref_length:
1830
        @return:
1831
        """
1832
        # block signals
1833
        self._pe.extract_param_ana_window_start_SpinBox.blockSignals(True)
1834
        self._pe.extract_param_ana_window_width_SpinBox.blockSignals(True)
1835
        self._pe.extract_param_ref_window_start_SpinBox.blockSignals(True)
1836
        self._pe.extract_param_ref_window_width_SpinBox.blockSignals(True)
1837
        # set widgets
1838
        self._pe.extract_param_ana_window_start_SpinBox.setValue(sig_start)
1839
        self._pe.extract_param_ana_window_width_SpinBox.setValue(sig_length)
1840
        self._pe.extract_param_ref_window_start_SpinBox.setValue(ref_start)
1841
        self._pe.extract_param_ref_window_width_SpinBox.setValue(ref_length)
1842
        # update plots
1843
        self.sig_start_line.setValue(sig_start)
1844
        self.sig_end_line.setValue(sig_start + sig_length)
1845
        self.ref_start_line.setValue(ref_start)
1846
        self.ref_end_line.setValue(ref_start + ref_length)
1847
        # unblock signals
1848
        self._pe.extract_param_ana_window_start_SpinBox.blockSignals(False)
1849
        self._pe.extract_param_ana_window_width_SpinBox.blockSignals(False)
1850
        self._pe.extract_param_ref_window_start_SpinBox.blockSignals(False)
1851
        self._pe.extract_param_ref_window_width_SpinBox.blockSignals(False)
1852
        return
1853
1854
    def laser_to_show_changed(self):
1855
        """
1856
1857
        @return:
1858
        """
1859
        current_laser = self._pe.laserpulses_ComboBox.currentText()
1860
        show_raw_data = self._pe.laserpulses_display_raw_CheckBox.isChecked()
1861
        if current_laser == 'sum':
1862
            show_laser_index = 0
1863
        else:
1864
            show_laser_index = int(current_laser)
1865
1866
        self._pulsed_master_logic.laser_to_show_changed(show_laser_index, show_raw_data)
1867
        return
1868
1869
    def laser_to_show_updated(self, laser_index, show_raw_data):
1870
        """
1871
1872
        @param laser_index:
1873
        @param show_raw_data:
1874
        @return:
1875
        """
1876
        # block signals
1877
        self._pe.laserpulses_ComboBox.blockSignals(True)
1878
        self._pe.laserpulses_display_raw_CheckBox.blockSignals(True)
1879
        # set widgets
1880
        self._pe.laserpulses_ComboBox.setCurrentIndex(laser_index)
1881
        self._pe.laserpulses_display_raw_CheckBox.setChecked(show_raw_data)
1882
        # unblock signals
1883
        self._pe.laserpulses_ComboBox.blockSignals(False)
1884
        self._pe.laserpulses_display_raw_CheckBox.blockSignals(False)
1885
        return
1886
1887
    def laser_data_updated(self, x_data, y_data):
1888
        """
1889
1890
        @param x_data:
1891
        @param y_data:
1892
        @return:
1893
        """
1894
        self.lasertrace_image.setData(x=x_data, y=y_data)
1895
        return
1896
1897
1898
1899
    ###########################################################################
1900
    ###         Methods related to the Tab 'Sequence Generator':            ###
1901
    ###########################################################################
1902
    def pulser_on_off_clicked(self, checked):
1903
        """ Manually switch the pulser output on/off. """
1904
        checked = self._mw.pulser_on_off_PushButton.isChecked()
1905
        if checked:
1906
            self._mw.pulser_on_off_PushButton.setText('Pulser OFF')
1907
            self._pulsed_master_logic.toggle_pulse_generator(True)
1908
        else:
1909
            self._mw.pulser_on_off_PushButton.setText('Pulser ON')
1910
            self._pulsed_master_logic.toggle_pulse_generator(False)
1911
        return
1912
1913
    def pulser_running_updated(self, is_running):
1914
        """
1915
1916
        @param is_running:
1917
        @return:
1918
        """
1919
        # block signals
1920
        self._mw.pulser_on_off_PushButton.blockSignals(True)
1921
        # set widgets
1922
        if is_running:
1923
            self._mw.pulser_on_off_PushButton.setText('Pulser OFF')
1924
            if not self._mw.pulser_on_off_PushButton.isChecked():
1925
                self._mw.pulser_on_off_PushButton.toggle()
1926
        else:
1927
            self._mw.pulser_on_off_PushButton.setText('Pulser ON')
1928
            if self._mw.pulser_on_off_PushButton.isChecked():
1929
                self._mw.pulser_on_off_PushButton.toggle()
1930
        # unblock signals
1931
        self._mw.pulser_on_off_PushButton.blockSignals(False)
1932
        return
1933
1934
    def clear_pulser_clicked(self):
1935
        """ Delete all loaded files in the device's current memory. """
1936
        self._pulsed_master_logic.clear_pulse_generator()
1937
        return
1938
1939
    def upload_ensemble_clicked(self):
1940
        """
1941
1942
        @return:
1943
        """
1944
        # Get the ensemble name from the ComboBox
1945
        ensemble_name = self._pg.gen_ensemble_ComboBox.currentText()
1946
        # Upload the ensemble via logic module
1947
        self._pulsed_master_logic.upload_asset(ensemble_name)
1948
        # disable button
1949
        self._pg.upload_ensemble_PushButton.setEnabled(False)
1950
        self._pg.load_ensemble_PushButton.setEnabled(False)
1951
        return
1952
1953
    # def upload_sequence_clicked(self):
1954
    #     """
1955
    #
1956
    #     @return:
1957
    #     """
1958
    #     # Get the sequence name from the ComboBox
1959
    #     seq_name = self._pg.gen_sequence_ComboBox.currentText()
1960
    #     # Upload the asset via logic module
1961
    #     self._pulsed_master_logic.upload_asset(seq_name)
1962
    #     # disable button
1963
    #     self._pg.upload_sequence_PushButton.setEnabled(False)
1964
    #     self._pg.load_sequence_PushButton.setEnabled(False)
1965
    #     return
1966
1967
    def update_uploaded_assets(self, asset_names_list):
1968
        """
1969
1970
        @param asset_names_list:
1971
        @return:
1972
        """
1973
        # enable buttons
1974
        # self._pg.upload_sequence_PushButton.setEnabled(True)
1975
        self._pg.upload_ensemble_PushButton.setEnabled(True)
1976
        self._pg.load_ensemble_PushButton.setEnabled(True)
1977
        # self._pg.load_sequence_PushButton.setEnabled(True)
1978
        return
1979
1980
    def load_ensemble_clicked(self):
1981
        """
1982
1983
        @return:
1984
        """
1985
        # Get the asset name to be uploaded from the ComboBox
1986
        asset_name = self._pg.gen_ensemble_ComboBox.currentText()
1987
        # Load asset into channles via logic module
1988
        self._pulsed_master_logic.load_asset_into_channels(asset_name, {}, False)
1989
        # disable button
1990
        self._pg.load_ensemble_PushButton.setEnabled(False)
1991
        return
1992
1993
    # def load_sequence_clicked(self):
1994
    #     """
1995
    #
1996
    #     @return:
1997
    #     """
1998
    #     # Get the asset name to be uploaded from the ComboBox
1999
    #     asset_name = self._pg.gen_sequence_ComboBox.currentText()
2000
    #     # Load asset into channles via logic module
2001
    #     self._pulsed_master_logic.load_asset_into_channels(asset_name, {}, False)
2002
    #     # disable button
2003
    #     self._pg.load_sequence_PushButton.setEnabled(False)
2004
    #     return
2005
2006
    def update_loaded_asset(self, asset_name, asset_type):
2007
        """ Check the current loaded asset from the logic and update the display. """
2008
        label = self._mw.current_loaded_asset_Label
2009
        if asset_name is None:
2010
            label.setText(asset_type)
2011
        elif asset_type == 'PulseBlockEnsemble' or asset_type == 'PulseSequence':
2012
            label.setText('  {0} ({1})'.format(asset_name, asset_type))
2013
        else:
2014
            label.setText('  Unknown asset type')
2015
        # enable buttons
2016
        if asset_type == 'PulseBlockEnsemble':
2017
            self._pg.load_ensemble_PushButton.setEnabled(True)
2018
        elif asset_type == 'PulseSequence':
2019
            self._pg.load_sequence_PushButton.setEnabled(True)
2020
        return
2021
2022
2023
    # def save_plots(self):
2024
    #     """ Save plot from analysis graph as a picture. """
2025
    #     timestamp = datetime.datetime.now()
2026
    #     filetag = self._mw.save_tag_LineEdit.text()
2027
    #     filepath = self._save_logic.get_path_for_module(module_name='PulsedMeasurement')
2028
    #     if len(filetag) > 0:
2029
    #         filename = os.path.join(filepath, '{}_{}_pulsed'.format(timestamp.strftime('%Y%m%d-%H%M-%S'), filetag))
2030
    #     else:
2031
    #         filename = os.path.join(filepath, '{}_pulsed'.format(timestamp.strftime('%Y%m%d-%H%M-%S')))
2032
    #
2033
    #     # print(type(self._mw.second_plot_ComboBox.currentText()), self._mw.second_plot_ComboBox.currentText())
2034
    #     # pulse plot
2035
    #     # exporter = pg.exporters.SVGExporter(self._pa.pulse_analysis_PlotWidget.plotItem.scene())
2036
    #     # exporter.export(filename+'.svg')
2037
    #     #
2038
    #     # # auxiliary plot
2039
    #     # if 'None' not in self._mw.second_plot_ComboBox.currentText():
2040
    #     #     exporter_aux = pg.exporters.SVGExporter(self._mw.pulse_analysis_second_PlotWidget.plotItem.scene())
2041
    #     #     exporter_aux.export(filename + '_aux' + '.svg')
2042
    #
2043
    #     self._pulsed_meas_logic._save_data(filetag, timestamp)
2044
2045
2046
2047