| Total Complexity | 100 |
| Total Lines | 1234 |
| Duplicated Lines | 9.24 % |
| Changes | 1 | ||
| Bugs | 0 | Features | 0 |
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like MagnetGui often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | # -*- coding: utf-8 -*- |
||
| 65 | class MagnetGui(GUIBase): |
||
| 66 | """ Main GUI for the magnet. """ |
||
| 67 | |||
| 68 | _modclass = 'MagnetGui' |
||
| 69 | _modtype = 'gui' |
||
| 70 | |||
| 71 | ## declare connectors |
||
| 72 | _in = {'magnetlogic1': 'MagnetLogic', |
||
| 73 | 'savelogic': 'SaveLogic'} |
||
| 74 | |||
| 75 | def __init__(self, config, **kwargs): |
||
| 76 | super().__init__(config=config, **kwargs) |
||
| 77 | |||
| 78 | self.log.info('The following configuration was found.') |
||
| 79 | |||
| 80 | # checking for the right configuration |
||
| 81 | for key in config.keys(): |
||
| 82 | self.log.info('{0}: {1}'.format(key,config[key])) |
||
| 83 | |||
| 84 | self._continue_2d_fluorescence_alignment = False |
||
| 85 | |||
| 86 | |||
| 87 | def on_activate(self, e=None): |
||
| 88 | """ Definition and initialisation of the GUI. |
||
| 89 | |||
| 90 | @param object e: Fysom.event object from Fysom class. |
||
| 91 | An object created by the state machine module Fysom, |
||
| 92 | which is connected to a specific event (have a look in |
||
| 93 | the Base Class). This object contains the passed event, |
||
| 94 | the state before the event happened and the destination |
||
| 95 | of the state which should be reached after the event |
||
| 96 | had happened. |
||
| 97 | """ |
||
| 98 | self._magnet_logic = self.connector['in']['magnetlogic1']['object'] |
||
| 99 | self._save_logic = self.connector['in']['savelogic']['object'] |
||
| 100 | |||
| 101 | self._mw = MagnetMainWindow() |
||
| 102 | |||
| 103 | config = self.getConfiguration() |
||
| 104 | |||
| 105 | # create all the needed control elements. They will manage the |
||
| 106 | # connection with each other themselves. Note some buttons are also |
||
| 107 | # connected within these functions because they have to be placed at |
||
| 108 | # first in the GUI Layout, otherwise the signals will not react. |
||
| 109 | self._create_axis_pos_disp() |
||
| 110 | self._create_move_rel_control() |
||
| 111 | self._create_move_abs_control() |
||
| 112 | |||
| 113 | self._create_meas_type_RadioButtons() |
||
| 114 | |||
| 115 | # Configuring the dock widgets |
||
| 116 | # Use the class 'MagnetMainWindow' to create the GUI window |
||
| 117 | |||
| 118 | axis_list = list(self._magnet_logic.get_hardware_constraints()) |
||
| 119 | self._mw.align_2d_axes0_name_ComboBox.clear() |
||
| 120 | self._mw.align_2d_axes0_name_ComboBox.addItems(axis_list) |
||
| 121 | |||
| 122 | self._mw.align_2d_axes1_name_ComboBox.clear() |
||
| 123 | self._mw.align_2d_axes1_name_ComboBox.addItems(axis_list) |
||
| 124 | |||
| 125 | # Setup dock widgets |
||
| 126 | self._mw.centralwidget.hide() |
||
| 127 | self._mw.setDockNestingEnabled(True) |
||
| 128 | # self._mw.tabifyDockWidget(self._mw.curr_pos_DockWidget, self._mw.move_rel_DockWidget) |
||
| 129 | # self._mw.tabifyDockWidget(self._mw.curr_pos_DockWidget, self._mw.move_abs_DockWidget) |
||
| 130 | # self._mw.addDockWidget(QtCore.Qt.DockWidgetArea(1), self._mw.curr_pos_DockWidget) |
||
| 131 | # self._mw.addDockWidget(QtCore.Qt.DockWidgetArea(2), self._mw.move_rel_DockWidget) |
||
| 132 | # self._mw.addDockWidget(QtCore.Qt.DockWidgetArea(3), self._mw.move_abs_DockWidget) |
||
| 133 | self.set_default_view_main_window() |
||
| 134 | |||
| 135 | # After a movement command, the device should not block the program, at |
||
| 136 | # least on the hardware level. That meant that the dll (or whatever |
||
| 137 | # protocol is used to access the hardware) can receive a command during |
||
| 138 | # an ongoing action. That is of course controller specific, but in |
||
| 139 | # general should it should be possible (unless the controller was |
||
| 140 | # written by someone who has no clue what he is doing). Eventually with |
||
| 141 | # that you have the possibility of stopping an ongoing movement! |
||
| 142 | self._interactive_mode = True |
||
| 143 | self._activate_magnet_settings(e) |
||
| 144 | |||
| 145 | # connect the actions of the toolbar: |
||
| 146 | self._mw.magnet_settings_Action.triggered.connect(self.open_magnet_settings) |
||
| 147 | self._mw.default_view_Action.triggered.connect(self.set_default_view_main_window) |
||
| 148 | |||
| 149 | self.update_pos() |
||
| 150 | self._magnet_logic.sigPosChanged.connect(self.update_pos) |
||
| 151 | |||
| 152 | # Connect alignment GUI elements: |
||
| 153 | |||
| 154 | self._magnet_logic.sigMeasurementFinished.connect(self._change_display_to_stop_2d_alignment) |
||
| 155 | |||
| 156 | |||
| 157 | |||
| 158 | self._mw.align_2d_axes0_name_ComboBox.currentIndexChanged.connect(self._update_limits_axis0) |
||
| 159 | self._mw.align_2d_axes1_name_ComboBox.currentIndexChanged.connect(self._update_limits_axis1) |
||
| 160 | self._mw.align_2d_axis0_set_vel_CheckBox.stateChanged.connect(self._set_vel_display_axis0) |
||
| 161 | self._mw.align_2d_axis1_set_vel_CheckBox.stateChanged.connect(self._set_vel_display_axis1) |
||
| 162 | |||
| 163 | |||
| 164 | self._mw.alignment_2d_cb_min_centiles_DSpinBox.valueChanged.connect(self._update_2d_graph_data) |
||
| 165 | self._mw.alignment_2d_cb_max_centiles_DSpinBox.valueChanged.connect(self._update_2d_graph_data) |
||
| 166 | self._mw.alignment_2d_cb_low_centiles_DSpinBox.valueChanged.connect(self._update_2d_graph_data) |
||
| 167 | self._mw.alignment_2d_cb_high_centiles_DSpinBox.valueChanged.connect(self._update_2d_graph_data) |
||
| 168 | |||
| 169 | self._update_limits_axis0() |
||
| 170 | self._update_limits_axis1() |
||
| 171 | self._set_vel_display_axis0() |
||
| 172 | self._set_vel_display_axis1() |
||
| 173 | |||
| 174 | self._2d_alignment_ImageItem = pg.ImageItem(self._magnet_logic.get_2d_data_matrix()) |
||
| 175 | axis0, axis1 = self._magnet_logic.get_2d_axis_arrays() |
||
| 176 | self._2d_alignment_ImageItem.setRect(QtCore.QRectF(axis0[0], |
||
| 177 | axis1[0], |
||
| 178 | axis0[-1]-axis0[0], |
||
| 179 | axis1[-1]-axis1[0],)) |
||
| 180 | |||
| 181 | self._mw.alignment_2d_GraphicsView.addItem(self._2d_alignment_ImageItem) |
||
| 182 | |||
| 183 | # Get the colorscales at set LUT |
||
| 184 | my_colors = ColorScaleInferno() |
||
| 185 | |||
| 186 | self._2d_alignment_ImageItem.setLookupTable(my_colors.lut) |
||
| 187 | |||
| 188 | |||
| 189 | |||
| 190 | # Configuration of Colorbar: |
||
| 191 | self._2d_alignment_cb = ColorBar(my_colors.cmap_normed, 100, 0, 100000) |
||
| 192 | |||
| 193 | self._mw.alignment_2d_cb_GraphicsView.addItem(self._2d_alignment_cb) |
||
| 194 | self._mw.alignment_2d_cb_GraphicsView.hideAxis('bottom') |
||
| 195 | self._mw.alignment_2d_cb_GraphicsView.hideAxis('left') |
||
| 196 | |||
| 197 | self._mw.alignment_2d_cb_GraphicsView.addItem(self._2d_alignment_cb) |
||
| 198 | |||
| 199 | if 'alignment_2d_cb_GraphicsView_text' in self._statusVariables: |
||
| 200 | textlabel = self._statusVariables['alignment_2d_cb_GraphicsView_text'] |
||
| 201 | |||
| 202 | else: |
||
| 203 | textlabel = 'Fluorescence' |
||
| 204 | |||
| 205 | if 'alignment_2d_cb_GraphicsView_units' in self._statusVariables: |
||
| 206 | units = self._statusVariables['alignment_2d_cb_GraphicsView_units'] |
||
| 207 | else: |
||
| 208 | units = 'counts/s' |
||
| 209 | |||
| 210 | self._mw.alignment_2d_cb_GraphicsView.setLabel('right', textlabel, units=units) |
||
| 211 | |||
| 212 | #FIXME: save that in the logic |
||
| 213 | if 'align_2d_axes0_range_DSpinBox' in self._statusVariables: |
||
| 214 | self._mw.align_2d_axes0_range_DSpinBox.setValue(self._statusVariables['align_2d_axes0_range_DSpinBox']) |
||
| 215 | if 'align_2d_axes0_step_DSpinBox' in self._statusVariables: |
||
| 216 | self._mw.align_2d_axes0_step_DSpinBox.setValue(self._statusVariables['align_2d_axes0_step_DSpinBox']) |
||
| 217 | if 'align_2d_axes0_vel_DSpinBox' in self._statusVariables: |
||
| 218 | self._mw.align_2d_axes0_vel_DSpinBox.setValue(self._statusVariables['align_2d_axes0_vel_DSpinBox']) |
||
| 219 | if 'align_2d_axes1_range_DSpinBox' in self._statusVariables: |
||
| 220 | self._mw.align_2d_axes1_range_DSpinBox.setValue(self._statusVariables['align_2d_axes1_range_DSpinBox']) |
||
| 221 | if 'align_2d_axes1_step_DSpinBox' in self._statusVariables: |
||
| 222 | self._mw.align_2d_axes1_step_DSpinBox.setValue(self._statusVariables['align_2d_axes1_step_DSpinBox']) |
||
| 223 | if 'align_2d_axes1_vel_DSpinBox' in self._statusVariables: |
||
| 224 | self._mw.align_2d_axes1_vel_DSpinBox.setValue(self._statusVariables['align_2d_axes1_vel_DSpinBox']) |
||
| 225 | |||
| 226 | #FIXME: that should be actually set in the logic |
||
| 227 | if 'measurement_type' in self._statusVariables: |
||
| 228 | self.measurement_type = self._statusVariables['measurement_type'] |
||
| 229 | else: |
||
| 230 | self.measurement_type = 'fluorescence' |
||
| 231 | |||
| 232 | self._magnet_logic.sig2DAxisChanged.connect(self._update_2d_graph_axis) |
||
| 233 | self._magnet_logic.sig2DMatrixChanged.connect(self._update_2d_graph_data) |
||
| 234 | |||
| 235 | # Connect the buttons and inputs for the odmr colorbar |
||
| 236 | self._mw.alignment_2d_manual_RadioButton.clicked.connect(self._update_2d_graph_data) |
||
| 237 | self._mw.alignment_2d_centiles_RadioButton.clicked.connect(self._update_2d_graph_data) |
||
| 238 | |||
| 239 | self._update_2d_graph_data() |
||
| 240 | self._update_2d_graph_cb() |
||
| 241 | |||
| 242 | |||
| 243 | # Add save file tag input box |
||
| 244 | self._mw.alignment_2d_nametag_LineEdit = QtWidgets.QLineEdit(self._mw) |
||
| 245 | self._mw.alignment_2d_nametag_LineEdit.setMaximumWidth(200) |
||
| 246 | self._mw.alignment_2d_nametag_LineEdit.setToolTip('Enter a nametag which will be\n' |
||
| 247 | 'added to the filename.') |
||
| 248 | |||
| 249 | self._mw.save_ToolBar.addWidget(self._mw.alignment_2d_nametag_LineEdit) |
||
| 250 | self._mw.save_Action.triggered.connect(self.save_2d_plots_and_data) |
||
| 251 | |||
| 252 | self._mw.run_stop_2d_alignment_Action.triggered.connect(self.run_stop_2d_alignment) |
||
| 253 | self._mw.continue_2d_alignment_Action.triggered.connect(self.continue_stop_2d_alignment) |
||
| 254 | |||
| 255 | # connect the signals: |
||
| 256 | # -------------------- |
||
| 257 | |||
| 258 | # for fluorescence alignment: |
||
| 259 | self._mw.align_2d_fluorescence_optimize_CheckBox.stateChanged.connect(self.optimize_pos_changed) |
||
| 260 | |||
| 261 | |||
| 262 | # for odmr alignment: |
||
| 263 | self._mw.meas_type_fluorescence_RadioButton.toggled.connect(self.set_measurement_type) |
||
| 264 | self._mw.meas_type_odmr_RadioButton.toggled.connect(self.set_measurement_type) |
||
| 265 | self._mw.meas_type_nuclear_spin_RadioButton.toggled.connect(self.set_measurement_type) |
||
| 266 | self.set_measurement_type() |
||
| 267 | |||
| 268 | # for odmr alignment: |
||
| 269 | self._mw.align_2d_odmr_low_fit_func_ComboBox.clear() |
||
| 270 | self._mw.align_2d_odmr_low_fit_func_ComboBox.addItems(self._magnet_logic.odmr_2d_low_fitfunction_list) |
||
| 271 | self._mw.align_2d_odmr_low_fit_func_ComboBox.setCurrentIndex(1) |
||
| 272 | self._mw.align_2d_odmr_low_center_freq_DSpinBox.setValue(self._magnet_logic.odmr_2d_low_center_freq) |
||
| 273 | self._mw.align_2d_odmr_low_range_freq_DSpinBox.setValue(self._magnet_logic.odmr_2d_low_range_freq) |
||
| 274 | self._mw.align_2d_odmr_low_step_freq_DSpinBox.setValue(self._magnet_logic.odmr_2d_low_step_freq) |
||
| 275 | self._mw.align_2d_odmr_low_power_DSpinBox.setValue(self._magnet_logic.odmr_2d_low_power) |
||
| 276 | self._mw.align_2d_odmr_low_runtime_DSpinBox.setValue(self._magnet_logic.odmr_2d_low_runtime) |
||
| 277 | |||
| 278 | self._mw.align_2d_odmr_high_fit_func_ComboBox.clear() |
||
| 279 | self._mw.align_2d_odmr_high_fit_func_ComboBox.addItems(self._magnet_logic.odmr_2d_high_fitfunction_list) |
||
| 280 | self._mw.align_2d_odmr_high_fit_func_ComboBox.setCurrentIndex(1) |
||
| 281 | self._mw.align_2d_odmr_high_center_freq_DSpinBox.setValue(self._magnet_logic.odmr_2d_high_center_freq) |
||
| 282 | self._mw.align_2d_odmr_high_range_freq_DSpinBox.setValue(self._magnet_logic.odmr_2d_high_range_freq) |
||
| 283 | self._mw.align_2d_odmr_high_step_freq_DSpinBox.setValue(self._magnet_logic.odmr_2d_high_step_freq) |
||
| 284 | self._mw.align_2d_odmr_high_power_DSpinBox.setValue(self._magnet_logic.odmr_2d_high_power) |
||
| 285 | self._mw.align_2d_odmr_high_runtime_DSpinBox.setValue(self._magnet_logic.odmr_2d_high_runtime) |
||
| 286 | |||
| 287 | self._mw.align_2d_odmr_save_after_measure_CheckBox.setChecked(self._magnet_logic.odmr_2d_save_after_measure) |
||
| 288 | |||
| 289 | self._mw.odmr_2d_single_trans_CheckBox.stateChanged.connect(self._odmr_single_trans_alignment_changed) |
||
| 290 | |||
| 291 | # peak shift for odmr: |
||
| 292 | self._mw.align_2d_axes0_shift_DSpinBox.setValue(self._magnet_logic.odmr_2d_peak_axis0_move_ratio/1e12) |
||
| 293 | self._mw.align_2d_axes1_shift_DSpinBox.setValue(self._magnet_logic.odmr_2d_peak_axis1_move_ratio/1e12) |
||
| 294 | |||
| 295 | |||
| 296 | |||
| 297 | # for single shot alignment of a nuclear spin: |
||
| 298 | self._mw.align_2d_nuclear_rabi_periode_DSpinBox.setValue(self._magnet_logic.nuclear_2d_rabi_periode) |
||
| 299 | self._mw.align_2d_nuclear_mw_freq_DSpinBox.setValue(self._magnet_logic.nuclear_2d_mw_freq) |
||
| 300 | self._mw.align_2d_nuclear_mw_channel_SpinBox.setValue(self._magnet_logic.nuclear_2d_mw_channel) |
||
| 301 | self._mw.align_2d_nuclear_mw_power_DSpinBox.setValue(self._magnet_logic.nuclear_2d_mw_power) |
||
| 302 | self._mw.align_2d_nuclear_laser_time_DSpinBox.setValue(self._magnet_logic.nuclear_2d_laser_time) |
||
| 303 | self._mw.align_2d_nuclear_laser_channel_SpinBox.setValue(self._magnet_logic.nuclear_2d_laser_channel) |
||
| 304 | self._mw.align_2d_nuclear_detect_channel_SpinBox.setValue(self._magnet_logic.nuclear_2d_detect_channel) |
||
| 305 | self._mw.align_2d_nuclear_idle_time_DSpinBox.setValue(self._magnet_logic.nuclear_2d_idle_time) |
||
| 306 | self._mw.align_2d_nuclear_reps_within_ssr_SpinBox.setValue(self._magnet_logic.nuclear_2d_reps_within_ssr) |
||
| 307 | self._mw.align_2d_nuclear_num_of_ssr_SpinBox.setValue(self._magnet_logic.nuclear_2d_num_ssr) |
||
| 308 | |||
| 309 | def _activate_magnet_settings(self, e): |
||
| 310 | """ Activate magnet settings. |
||
| 311 | |||
| 312 | @param object e: Fysom.event object from Fysom class. A more detailed |
||
| 313 | explanation can be found in the method initUI. |
||
| 314 | """ |
||
| 315 | self._ms = MagnetSettingsWindow() |
||
| 316 | # default config is normal_mode |
||
| 317 | self._ms.normal_mode_checkBox.setChecked(True) |
||
| 318 | self._ms.z_mode_checkBox.setChecked(False) |
||
| 319 | # make sure the buttons are exclusively checked |
||
| 320 | self._ms.normal_mode_checkBox.stateChanged.connect(self.trig_wrapper_normal_mode) |
||
| 321 | self._ms.z_mode_checkBox.stateChanged.connect(self.trig_wrapper_z_mode) |
||
| 322 | |||
| 323 | #self._ms.z_mode_checkBox.stateChanged.connect(self._ms.normal_mode_checkBox.toggle) |
||
| 324 | self._ms.accepted.connect(self.update_magnet_settings) |
||
| 325 | self._ms.rejected.connect(self.keep_former_magnet_settings) |
||
| 326 | self._ms.ButtonBox.button(QtWidgets.QDialogButtonBox.Apply).clicked.connect(self.update_magnet_settings) |
||
| 327 | |||
| 328 | self.keep_former_magnet_settings() |
||
| 329 | |||
| 330 | def trig_wrapper_normal_mode(self): |
||
| 331 | if not self._ms.normal_mode_checkBox.isChecked() and not self._ms.z_mode_checkBox.isChecked(): |
||
| 332 | self._ms.z_mode_checkBox.toggle() |
||
| 333 | elif self._ms.normal_mode_checkBox.isChecked() and self._ms.z_mode_checkBox.isChecked(): |
||
| 334 | self._ms.z_mode_checkBox.toggle() |
||
| 335 | |||
| 336 | def trig_wrapper_z_mode(self): |
||
| 337 | if not self._ms.normal_mode_checkBox.isChecked() and not self._ms.z_mode_checkBox.isChecked(): |
||
| 338 | self._ms.normal_mode_checkBox.toggle() |
||
| 339 | elif self._ms.normal_mode_checkBox.isChecked() and self._ms.z_mode_checkBox.isChecked(): |
||
| 340 | self._ms.normal_mode_checkBox.toggle() |
||
| 341 | |||
| 342 | |||
| 343 | def on_deactivate(self, e=None): |
||
| 344 | """ Deactivate the module properly. |
||
| 345 | |||
| 346 | @param object e: Fysom.event object from Fysom class. A more detailed |
||
| 347 | explanation can be found in the method initUI. |
||
| 348 | """ |
||
| 349 | self._statusVariables['measurement_type'] = self.measurement_type |
||
| 350 | self._statusVariables['alignment_2d_cb_GraphicsView_text'] = self._mw.alignment_2d_cb_GraphicsView.plotItem.axes['right']['item'].labelText |
||
| 351 | self._statusVariables['alignment_2d_cb_GraphicsView_units'] = self._mw.alignment_2d_cb_GraphicsView.plotItem.axes['right']['item'].labelUnits |
||
| 352 | |||
| 353 | #FIXME: save that in the logic |
||
| 354 | self._statusVariables['align_2d_axes0_range_DSpinBox'] = self._mw.align_2d_axes0_range_DSpinBox.value() |
||
| 355 | self._statusVariables['align_2d_axes0_step_DSpinBox'] = self._mw.align_2d_axes0_step_DSpinBox.value() |
||
| 356 | self._statusVariables['align_2d_axes0_vel_DSpinBox'] = self._mw.align_2d_axes0_vel_DSpinBox.value() |
||
| 357 | self._statusVariables['align_2d_axes1_range_DSpinBox'] = self._mw.align_2d_axes1_range_DSpinBox.value() |
||
| 358 | self._statusVariables['align_2d_axes1_step_DSpinBox'] = self._mw.align_2d_axes1_step_DSpinBox.value() |
||
| 359 | self._statusVariables['align_2d_axes1_vel_DSpinBox'] = self._mw.align_2d_axes1_vel_DSpinBox.value() |
||
| 360 | |||
| 361 | self._mw.close() |
||
| 362 | |||
| 363 | def show(self): |
||
| 364 | """Make window visible and put it above all other windows. """ |
||
| 365 | QtWidgets.QMainWindow.show(self._mw) |
||
| 366 | self._mw.activateWindow() |
||
| 367 | self._mw.raise_() |
||
| 368 | |||
| 369 | |||
| 370 | def set_default_view_main_window(self): |
||
| 371 | """ Establish the default dock Widget configuration. """ |
||
| 372 | |||
| 373 | # connect all widgets to the main Window |
||
| 374 | self._mw.curr_pos_DockWidget.setFloating(False) |
||
| 375 | self._mw.move_rel_DockWidget.setFloating(False) |
||
| 376 | self._mw.move_abs_DockWidget.setFloating(False) |
||
| 377 | self._mw.alignment_DockWidget.setFloating(False) |
||
| 378 | |||
| 379 | # QtCore.Qt.LeftDockWidgetArea 0x1 |
||
| 380 | # QtCore.Qt.RightDockWidgetArea 0x2 |
||
| 381 | # QtCore.Qt.TopDockWidgetArea 0x4 |
||
| 382 | # QtCore.Qt.BottomDockWidgetArea 0x8 |
||
| 383 | # QtCore.Qt.AllDockWidgetAreas DockWidgetArea_Mask |
||
| 384 | # QtCore.Qt.NoDockWidgetArea 0 |
||
| 385 | |||
| 386 | # align the widget |
||
| 387 | self._mw.addDockWidget(QtCore.Qt.DockWidgetArea(1), |
||
| 388 | self._mw.curr_pos_DockWidget) |
||
| 389 | self._mw.addDockWidget(QtCore.Qt.DockWidgetArea(1), |
||
| 390 | self._mw.move_rel_DockWidget) |
||
| 391 | self._mw.addDockWidget(QtCore.Qt.DockWidgetArea(1), |
||
| 392 | self._mw.move_abs_DockWidget) |
||
| 393 | |||
| 394 | self._mw.addDockWidget(QtCore.Qt.DockWidgetArea(2), |
||
| 395 | self._mw.alignment_DockWidget) |
||
| 396 | |||
| 397 | def open_magnet_settings(self): |
||
| 398 | """ This method opens the settings menu. """ |
||
| 399 | self._ms.exec_() |
||
| 400 | |||
| 401 | def update_magnet_settings(self): |
||
| 402 | """ Apply the set configuration in the Settings Window. """ |
||
| 403 | |||
| 404 | if self._ms.interactive_mode_CheckBox.isChecked(): |
||
| 405 | self._interactive_mode = True |
||
| 406 | else: |
||
| 407 | self._interactive_mode = False |
||
| 408 | |||
| 409 | if self._ms.interactive_mode_CheckBox.isChecked(): |
||
| 410 | self._interactive_mode = True |
||
| 411 | else: |
||
| 412 | self._interactive_mode = False |
||
| 413 | if self._ms.z_mode_checkBox.isChecked(): |
||
| 414 | self._z_mode = True |
||
| 415 | self._magnet_logic._magnet_device.mode = 'z_mode' |
||
| 416 | else: |
||
| 417 | self._z_mode = False |
||
| 418 | self._magnet_logic._magnet_device.mode = 'normal_mode' |
||
| 419 | |||
| 420 | if self._ms.normal_mode_checkBox.isChecked(): |
||
| 421 | self._normal_mode = True |
||
| 422 | self._magnet_logic._magnet_device.mode = 'normal_mode' |
||
| 423 | else: |
||
| 424 | self._normal_mode = False |
||
| 425 | self._magnet_logic._magnet_device.mode = 'z_mode' |
||
| 426 | |||
| 427 | def keep_former_magnet_settings(self): |
||
| 428 | |||
| 429 | self._ms.interactive_mode_CheckBox.setChecked(self._interactive_mode) |
||
| 430 | |||
| 431 | def _create_meas_type_RadioButtons(self): |
||
| 432 | """ Create the measurement Buttons for the desired measurements: |
||
| 433 | |||
| 434 | @return: |
||
| 435 | """ |
||
| 436 | |||
| 437 | self._mw.alignment_2d_ButtonGroup = QtWidgets.QButtonGroup(self._mw) |
||
| 438 | |||
| 439 | self._mw.meas_type_fluorescence_RadioButton = QtWidgets.QRadioButton(parent=self._mw) |
||
| 440 | self._mw.alignment_2d_ButtonGroup.addButton(self._mw.meas_type_fluorescence_RadioButton) |
||
| 441 | self._mw.alignment_2d_ToolBar.addWidget(self._mw.meas_type_fluorescence_RadioButton) |
||
| 442 | self._mw.meas_type_fluorescence_RadioButton.setText('Fluorescence') |
||
| 443 | |||
| 444 | self._mw.meas_type_odmr_RadioButton = QtWidgets.QRadioButton(parent=self._mw) |
||
| 445 | self._mw.alignment_2d_ButtonGroup.addButton(self._mw.meas_type_odmr_RadioButton) |
||
| 446 | self._mw.alignment_2d_ToolBar.addWidget(self._mw.meas_type_odmr_RadioButton) |
||
| 447 | self._mw.meas_type_odmr_RadioButton.setText('ODMR') |
||
| 448 | |||
| 449 | self._mw.meas_type_nuclear_spin_RadioButton = QtWidgets.QRadioButton(parent=self._mw) |
||
| 450 | self._mw.alignment_2d_ButtonGroup.addButton(self._mw.meas_type_nuclear_spin_RadioButton) |
||
| 451 | self._mw.alignment_2d_ToolBar.addWidget(self._mw.meas_type_nuclear_spin_RadioButton) |
||
| 452 | self._mw.meas_type_nuclear_spin_RadioButton.setText('Nuclear Spin') |
||
| 453 | |||
| 454 | self._mw.meas_type_fluorescence_RadioButton.setChecked(True) |
||
| 455 | |||
| 456 | |||
| 457 | def _create_axis_pos_disp(self): |
||
| 458 | """ Create the axis position display. |
||
| 459 | |||
| 460 | The generic variable name for a created QLable is: |
||
| 461 | curr_pos_axis{0}_Label |
||
| 462 | The generic variable name for a created ScienDSpinBox is: |
||
| 463 | curr_pos_axis{0}_ScienDSpinBox |
||
| 464 | where in {0} the name of the axis will be inserted. |
||
| 465 | |||
| 466 | DO NOT CALL THESE VARIABLES DIRECTLY! USE THE DEDICATED METHOD INSTEAD! |
||
| 467 | Use the method get_ref_curr_pos_ScienDSpinBox with the appropriated |
||
| 468 | label, otherwise you will break the generality. |
||
| 469 | """ |
||
| 470 | |||
| 471 | constraints = self._magnet_logic.get_hardware_constraints() |
||
| 472 | |||
| 473 | # set the parameters in the curr_pos_DockWidget: |
||
| 474 | for index, axis_label in enumerate(constraints): |
||
| 475 | |||
| 476 | # Set the QLabel according to the grid |
||
| 477 | # this is the name prototype for the label of current position display |
||
| 478 | label_var_name = 'curr_pos_axis{0}_Label'.format(axis_label) |
||
| 479 | setattr(self._mw, label_var_name, QtWidgets.QLabel(self._mw.curr_pos_DockWidgetContents)) |
||
| 480 | label_var = getattr(self._mw, label_var_name) |
||
| 481 | label_var.setObjectName(label_var_name) |
||
| 482 | label_var.setText('{0}'.format(axis_label)) |
||
| 483 | self._mw.curr_pos_GridLayout.addWidget(label_var, index, 0, 1, 1) |
||
| 484 | |||
| 485 | # Set the ScienDSpinBox according to the grid |
||
| 486 | # this is the name prototype for the current position display |
||
| 487 | dspinbox_ref_name = 'curr_pos_axis{0}_ScienDSpinBox'.format(axis_label) |
||
| 488 | |||
| 489 | setattr(self._mw, dspinbox_ref_name, ScienDSpinBox(parent=self._mw.curr_pos_DockWidgetContents)) |
||
| 490 | dspinbox_ref = getattr(self._mw, dspinbox_ref_name) |
||
| 491 | dspinbox_ref.setObjectName(dspinbox_ref_name) |
||
| 492 | dspinbox_ref.setReadOnly(True) |
||
| 493 | dspinbox_ref.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons) |
||
| 494 | dspinbox_ref.setMaximum(np.inf) |
||
| 495 | dspinbox_ref.setMinimum(-np.inf) |
||
| 496 | |||
| 497 | # in the ScienDSpinBox the decimals are actually the number of |
||
| 498 | # significant digits, therefore set them here by default: |
||
| 499 | dspinbox_ref.setDecimals(5) |
||
| 500 | dspinbox_ref.setOpts(minStep=constraints[axis_label]['pos_step']) |
||
| 501 | dspinbox_ref.setSingleStep(0.001) |
||
| 502 | dspinbox_ref.setSuffix(constraints[axis_label]['unit']) |
||
| 503 | |||
| 504 | self._mw.curr_pos_GridLayout.addWidget(dspinbox_ref, index, 1, 1, 1) |
||
| 505 | |||
| 506 | extension = len(constraints) |
||
| 507 | self._mw.curr_pos_GridLayout.addWidget(self._mw.curr_pos_get_pos_PushButton, 0, 2, extension, 1) |
||
| 508 | self._mw.curr_pos_GridLayout.addWidget(self._mw.curr_pos_stop_PushButton, 0, 3, extension, 1) |
||
| 509 | self._mw.curr_pos_get_pos_PushButton.clicked.connect(self.update_pos) |
||
| 510 | self._mw.curr_pos_stop_PushButton.clicked.connect(self.stop_movement) |
||
| 511 | |||
| 512 | def _create_move_rel_control(self): |
||
| 513 | """ Create all the gui elements to control a relative movement. |
||
| 514 | |||
| 515 | The generic variable name for a created QLable is: |
||
| 516 | move_rel_axis_{0}_Label |
||
| 517 | The generic variable name for a created ScienDSpinBox is: |
||
| 518 | move_rel_axis_{0}_ScienDSpinBox |
||
| 519 | The generic variable name for a created QPushButton in negative dir is: |
||
| 520 | move_rel_axis_{0}_m_PushButton |
||
| 521 | The generic variable name for a created QPushButton in positive dir is: |
||
| 522 | move_rel_axis_{0}_p_PushButton |
||
| 523 | |||
| 524 | DO NOT CALL THESE VARIABLES DIRECTLY! USE THE DEDICATED METHOD INSTEAD! |
||
| 525 | Use the method get_ref_move_rel_ScienDSpinBox with the appropriated |
||
| 526 | label, otherwise you will break the generality. |
||
| 527 | """ |
||
| 528 | |||
| 529 | constraints = self._magnet_logic.get_hardware_constraints() |
||
| 530 | |||
| 531 | # set the axis_labels in the curr_pos_DockWidget: |
||
| 532 | for index, axis_label in enumerate(constraints): |
||
| 533 | |||
| 534 | label_var_name = 'move_rel_axis_{0}_Label'.format(axis_label) |
||
| 535 | setattr(self._mw, label_var_name, QtWidgets.QLabel(self._mw.move_rel_DockWidgetContents)) |
||
| 536 | label_var = getattr(self._mw, label_var_name) # get the reference |
||
| 537 | label_var.setObjectName(label_var_name) # set axis_label for the label |
||
| 538 | label_var.setText('{0}'.format(axis_label)) |
||
| 539 | # add the label to the grid: |
||
| 540 | self._mw.move_rel_GridLayout.addWidget(label_var, index, 0, 1, 1) |
||
| 541 | |||
| 542 | # Set the ScienDSpinBox according to the grid |
||
| 543 | # this is the name prototype for the relative movement display |
||
| 544 | dspinbox_ref_name = 'move_rel_axis_{0}_ScienDSpinBox'.format(axis_label) |
||
| 545 | setattr(self._mw, dspinbox_ref_name, ScienDSpinBox(parent=self._mw.move_rel_DockWidgetContents)) |
||
| 546 | dspinbox_ref = getattr(self._mw, dspinbox_ref_name) |
||
| 547 | dspinbox_ref.setObjectName(dspinbox_ref_name) |
||
| 548 | # dspinbox_ref.setButtonSymbols(QtGui.QAbstractSpinBox.NoButtons) |
||
| 549 | |||
| 550 | dspinbox_ref.setMaximum(constraints[axis_label]['pos_max']) |
||
| 551 | dspinbox_ref.setMinimum(constraints[axis_label]['pos_min']) |
||
| 552 | |||
| 553 | # in the ScienDSpinBox the decimals are actually the number of |
||
| 554 | # significant digits, therefore set them here by default: |
||
| 555 | dspinbox_ref.setDecimals(5) |
||
| 556 | dspinbox_ref.setOpts(minStep=constraints[axis_label]['pos_step']) |
||
| 557 | dspinbox_ref.setSingleStep(0.001) |
||
| 558 | dspinbox_ref.setSuffix(constraints[axis_label]['unit']) |
||
| 559 | |||
| 560 | self._mw.move_rel_GridLayout.addWidget(dspinbox_ref, index, 1, 1, 1) |
||
| 561 | |||
| 562 | |||
| 563 | # this is the name prototype for the relative movement minus button |
||
| 564 | func_name = 'move_rel_axis_{0}_m'.format(axis_label) |
||
| 565 | # create a method and assign it as attribute: |
||
| 566 | setattr(self, func_name, self._function_builder_move_rel(func_name,axis_label,-1) ) |
||
| 567 | move_rel_m_ref = getattr(self, func_name) # get the reference |
||
| 568 | |||
| 569 | # the change of the PushButton is connected to the previous method. |
||
| 570 | button_var_name = 'move_rel_axis_{0}_m_PushButton'.format(axis_label) |
||
| 571 | setattr(self._mw, button_var_name, QtWidgets.QPushButton(self._mw.move_rel_DockWidgetContents)) |
||
| 572 | button_var = getattr(self._mw, button_var_name) |
||
| 573 | button_var.setObjectName(button_var_name) |
||
| 574 | button_var.setText('-') |
||
| 575 | button_var.clicked.connect(move_rel_m_ref, type=QtCore.Qt.QueuedConnection) |
||
| 576 | self._mw.move_rel_GridLayout.addWidget(button_var, index, 2, 1, 1) |
||
| 577 | |||
| 578 | # this is the name prototype for the relative movement plus button |
||
| 579 | func_name = 'move_rel_axis_{0}_p'.format(axis_label) |
||
| 580 | setattr(self, func_name, self._function_builder_move_rel(func_name,axis_label,1) ) |
||
| 581 | move_rel_p_ref = getattr(self, func_name) |
||
| 582 | |||
| 583 | # the change of the PushButton is connected to the previous method. |
||
| 584 | button_var_name = 'move_rel_axis_{0}_p_PushButton'.format(axis_label) |
||
| 585 | setattr(self._mw, button_var_name, QtWidgets.QPushButton(self._mw.move_rel_DockWidgetContents)) |
||
| 586 | button_var = getattr(self._mw, button_var_name) |
||
| 587 | button_var.setObjectName(button_var_name) |
||
| 588 | button_var.setText('+') |
||
| 589 | button_var.clicked.connect(move_rel_p_ref, type=QtCore.Qt.QueuedConnection) |
||
| 590 | self._mw.move_rel_GridLayout.addWidget(button_var, index, 3, 1, 1) |
||
| 591 | |||
| 592 | def _create_move_abs_control(self): |
||
| 593 | """ Create all the GUI elements to control a relative movement. |
||
| 594 | |||
| 595 | The generic variable name for a created QLable is: |
||
| 596 | move_abs_axis_{0}_Label |
||
| 597 | The generic variable name for a created QLable is: |
||
| 598 | move_abs_axis_{0}_Slider |
||
| 599 | The generic variable name for a created ScienDSpinBox is: |
||
| 600 | move_abs_axis_{0}_ScienDSpinBox |
||
| 601 | The generic variable name for a created QPushButton for move is: |
||
| 602 | move_abs_PushButton |
||
| 603 | |||
| 604 | These methods should not be called: |
||
| 605 | The generic variable name for a update method for the ScienDSpinBox: |
||
| 606 | _update_move_abs_{0}_dspinbox |
||
| 607 | The generic variable name for a update method for the QSlider: |
||
| 608 | _update_move_abs_{0}_slider |
||
| 609 | |||
| 610 | DO NOT CALL THESE VARIABLES DIRECTLY! USE THE DEDICATED METHOD INSTEAD! |
||
| 611 | Use the method get_ref_move_abs_ScienDSpinBox with the appropriated |
||
| 612 | label, otherwise you will break the generality. |
||
| 613 | """ |
||
| 614 | |||
| 615 | constraints = self._magnet_logic.get_hardware_constraints() |
||
| 616 | |||
| 617 | for index, axis_label in enumerate(constraints): |
||
| 618 | |||
| 619 | label_var_name = 'move_abs_axis_{0}_Label'.format(axis_label) |
||
| 620 | setattr(self._mw, label_var_name, QtWidgets.QLabel(self._mw.move_abs_DockWidgetContents)) |
||
| 621 | label_var = getattr(self._mw, label_var_name) # get the reference |
||
| 622 | # set axis_label for the label: |
||
| 623 | label_var.setObjectName(label_var_name) |
||
| 624 | label_var.setText(axis_label) |
||
| 625 | |||
| 626 | # make the steps of the splider as a multiple of 10 |
||
| 627 | # smallest_step_slider = 10**int(np.log10(constraints[axis_label]['pos_step']) -1) |
||
| 628 | smallest_step_slider = constraints[axis_label]['pos_step'] |
||
| 629 | |||
| 630 | # add the label to the grid: |
||
| 631 | self._mw.move_abs_GridLayout.addWidget(label_var, index, 0, 1, 1) |
||
| 632 | |||
| 633 | # Set the ScienDSpinBox according to the grid |
||
| 634 | # this is the name prototype for the relative movement display |
||
| 635 | slider_obj_name = 'move_abs_axis_{0}_Slider'.format(axis_label) |
||
| 636 | setattr(self._mw, slider_obj_name, QtWidgets.QSlider(self._mw.move_abs_DockWidgetContents)) |
||
| 637 | slider_obj = getattr(self._mw, slider_obj_name) |
||
| 638 | slider_obj.setObjectName(slider_obj_name) |
||
| 639 | slider_obj.setOrientation(QtCore.Qt.Horizontal) |
||
| 640 | # dspinbox_ref.setButtonSymbols(QtGui.QAbstractSpinBox.NoButtons) |
||
| 641 | |||
| 642 | max_val = abs(constraints[axis_label]['pos_max'] - constraints[axis_label]['pos_min']) |
||
| 643 | |||
| 644 | # set the step size of the slider to a fixed resolution, that |
||
| 645 | # prevents really ugly rounding error behaviours in display. |
||
| 646 | # Set precision to nanometer scale, which is actually never reached. |
||
| 647 | max_steps = int(max_val/smallest_step_slider) |
||
| 648 | |||
| 649 | |||
| 650 | slider_obj.setMaximum(max_steps) |
||
| 651 | slider_obj.setMinimum(0) |
||
| 652 | #TODO: set the decimals also from the constraints! |
||
| 653 | # slider_obj.setDecimals(3) |
||
| 654 | slider_obj.setSingleStep(1) |
||
| 655 | # slider_obj.setEnabled(False) |
||
| 656 | |||
| 657 | self._mw.move_abs_GridLayout.addWidget(slider_obj, index, 1, 1, 1) |
||
| 658 | |||
| 659 | # Set the ScienDSpinBox according to the grid |
||
| 660 | # this is the name prototype for the relative movement display |
||
| 661 | dspinbox_ref_name = 'move_abs_axis_{0}_ScienDSpinBox'.format(axis_label) |
||
| 662 | setattr(self._mw, dspinbox_ref_name, ScienDSpinBox(parent=self._mw.move_abs_DockWidgetContents)) |
||
| 663 | dspinbox_ref = getattr(self._mw, dspinbox_ref_name) |
||
| 664 | dspinbox_ref.setObjectName(dspinbox_ref_name) |
||
| 665 | # dspinbox_ref.setButtonSymbols(QtGui.QAbstractSpinBox.NoButtons) |
||
| 666 | |||
| 667 | dspinbox_ref.setMaximum(constraints[axis_label]['pos_max']) |
||
| 668 | dspinbox_ref.setMinimum(constraints[axis_label]['pos_min']) |
||
| 669 | |||
| 670 | # in the ScienDSpinBox the decimals are actually the number of |
||
| 671 | # significant digits, therefore set them here by default: |
||
| 672 | dspinbox_ref.setDecimals(5) |
||
| 673 | dspinbox_ref.setOpts(minStep=constraints[axis_label]['pos_step']) |
||
| 674 | dspinbox_ref.setSingleStep(0.001) |
||
| 675 | dspinbox_ref.setSuffix(constraints[axis_label]['unit']) |
||
| 676 | |||
| 677 | # set the horizontal size to 100 pixel: |
||
| 678 | dspinbox_ref.setMaximumSize(QtCore.QSize(80, 16777215)) |
||
| 679 | |||
| 680 | self._mw.move_abs_GridLayout.addWidget(dspinbox_ref, index, 2, 1, 1) |
||
| 681 | |||
| 682 | # build a function to change the dspinbox value and connect a |
||
| 683 | # slidermove event to it: |
||
| 684 | func_name = '_update_move_abs_{0}_dspinbox'.format(axis_label) |
||
| 685 | setattr(self, func_name, self._function_builder_update_viewbox(func_name, axis_label, dspinbox_ref)) |
||
| 686 | update_func_dspinbox_ref = getattr(self, func_name) |
||
| 687 | slider_obj.valueChanged.connect(update_func_dspinbox_ref) |
||
| 688 | |||
| 689 | # build a function to change the slider value and connect a |
||
| 690 | # spinbox value change event to it: |
||
| 691 | func_name = '_update_move_abs_{0}_slider'.format(axis_label) |
||
| 692 | setattr(self, func_name, self._function_builder_update_slider(func_name, axis_label, slider_obj)) |
||
| 693 | update_func_slider_ref = getattr(self, func_name) |
||
| 694 | # dspinbox_ref.valueChanged.connect(update_func_slider_ref) |
||
| 695 | |||
| 696 | # the editingFinished idea has to be implemented properly at first: |
||
| 697 | dspinbox_ref.editingFinished.connect(update_func_slider_ref) |
||
| 698 | |||
| 699 | extension = len(constraints) |
||
| 700 | self._mw.move_abs_GridLayout.addWidget(self._mw.move_abs_PushButton, 0, 3, extension, 1) |
||
| 701 | self._mw.move_abs_PushButton.clicked.connect(self.move_abs) |
||
| 702 | |||
| 703 | def _function_builder_move_rel(self, func_name, axis_label, direction): |
||
| 704 | """ Create a function/method, which gots executed for pressing move_rel. |
||
| 705 | |||
| 706 | @param str func_name: name how the function should be called. |
||
| 707 | @param str axis_label: label of the axis you want to create a control |
||
| 708 | function for. |
||
| 709 | @param int direction: either 1 or -1 depending on the relative movement. |
||
| 710 | @return: function with name func_name |
||
| 711 | |||
| 712 | A routine to construct a method on the fly and attach it as attribute |
||
| 713 | to the object, so that it can be used or so that other signals can be |
||
| 714 | connected to it. That means the return value is already fixed for a |
||
| 715 | function name. |
||
| 716 | """ |
||
| 717 | |||
| 718 | def func_dummy_name(): |
||
| 719 | self.move_rel(axis_label, direction) |
||
| 720 | |||
| 721 | func_dummy_name.__name__ = func_name |
||
| 722 | return func_dummy_name |
||
| 723 | |||
| 724 | # create the signals for the push buttons and connect them to the move |
||
| 725 | # rel method in the Logic |
||
| 726 | |||
| 727 | def _function_builder_update_viewbox(self, func_name, axis_label, |
||
| 728 | ref_dspinbox): |
||
| 729 | """ Create a function/method, which gots executed for pressing move_rel. |
||
| 730 | |||
| 731 | @param str func_name: name how the function should be called. |
||
| 732 | @param str axis_label: label of the axis you want to create a control |
||
| 733 | function for. |
||
| 734 | @param object ref_dspinbox: a reference to the dspinbox object, which |
||
| 735 | will actually apply the changed within the |
||
| 736 | created method. |
||
| 737 | |||
| 738 | @return: function with name func_name |
||
| 739 | |||
| 740 | A routine to construct a method on the fly and attach it as attribute |
||
| 741 | to the object, so that it can be used or so that other signals can be |
||
| 742 | connected to it. The connection of a signal to this method must appear |
||
| 743 | outside of the present function. |
||
| 744 | """ |
||
| 745 | |||
| 746 | def func_dummy_name(slider_val): |
||
| 747 | """ |
||
| 748 | @param int slider_val: The current value of the slider, will be an |
||
| 749 | integer value between |
||
| 750 | [0,(pos_max - pos_min)/pos_step] |
||
| 751 | of the corresponding axis label. |
||
| 752 | Now convert this value back to a viewbox |
||
| 753 | value like: |
||
| 754 | pos_min + slider_step*pos_step |
||
| 755 | """ |
||
| 756 | |||
| 757 | constraints = self._magnet_logic.get_hardware_constraints() |
||
| 758 | # set the resolution of the slider to nanometer precision, that is |
||
| 759 | # better for the display behaviour. In the end, that will just make |
||
| 760 | # everything smoother but not actually affect the displayed number: |
||
| 761 | |||
| 762 | # max_step_slider = 10**int(np.log10(constraints[axis_label]['pos_step']) -1) |
||
| 763 | max_step_slider = constraints[axis_label]['pos_step'] |
||
| 764 | |||
| 765 | actual_pos = (constraints[axis_label]['pos_min'] + slider_val * max_step_slider) |
||
| 766 | ref_dspinbox.setValue(actual_pos) |
||
| 767 | |||
| 768 | func_dummy_name.__name__ = func_name |
||
| 769 | return func_dummy_name |
||
| 770 | |||
| 771 | def _function_builder_update_slider(self, func_name, axis_label, ref_slider): |
||
| 772 | """ Create a function/method, which gots executed for pressing move_rel. |
||
| 773 | |||
| 774 | Create a function/method, which gots executed for pressing move_rel. |
||
| 775 | |||
| 776 | @param str func_name: name how the function should be called. |
||
| 777 | @param str axis_label: label of the axis you want to create a control |
||
| 778 | function for. |
||
| 779 | @param object ref_slider: a reference to the slider object, which |
||
| 780 | will actually apply the changed within the |
||
| 781 | created method. |
||
| 782 | |||
| 783 | @return: function with name func_name |
||
| 784 | |||
| 785 | A routine to construct a method on the fly and attach it as attribute |
||
| 786 | to the object, so that it can be used or so that other signals can be |
||
| 787 | connected to it. The connection of a signal to this method must appear |
||
| 788 | outside of the present function. |
||
| 789 | """ |
||
| 790 | |||
| 791 | def func_dummy_name(): |
||
| 792 | """ |
||
| 793 | @param int slider_step: The current value of the slider, will be an |
||
| 794 | integer value between |
||
| 795 | [0,(pos_max - pos_min)/pos_step] |
||
| 796 | of the corresponding axis label. |
||
| 797 | Now convert this value back to a viewbox |
||
| 798 | value like: |
||
| 799 | pos_min + slider_step*pos_step |
||
| 800 | """ |
||
| 801 | |||
| 802 | dspinbox_obj = self.get_ref_move_abs_ScienDSpinBox(axis_label) |
||
| 803 | viewbox_val = dspinbox_obj.value() |
||
| 804 | |||
| 805 | constraints = self._magnet_logic.get_hardware_constraints() |
||
| 806 | # set the resolution of the slider to nanometer precision, that is |
||
| 807 | # better for the display behaviour. In the end, that will just make |
||
| 808 | # everything smoother but not actually affect the displayed number: |
||
| 809 | |||
| 810 | # max_step_slider = 10**int(np.log10(constraints[axis_label]['pos_step']) -1) |
||
| 811 | max_step_slider = constraints[axis_label]['pos_step'] |
||
| 812 | |||
| 813 | slider_val = abs(viewbox_val - constraints[axis_label]['pos_min'])/max_step_slider |
||
| 814 | ref_slider.setValue(slider_val) |
||
| 815 | |||
| 816 | func_dummy_name.__name__ = func_name |
||
| 817 | return func_dummy_name |
||
| 818 | |||
| 819 | # create the signals for the push buttons and connect them to the move |
||
| 820 | # rel method in the Logic |
||
| 821 | |||
| 822 | def move_rel(self, axis_label, direction): |
||
| 823 | """ Move relative by the axis with given label an direction. |
||
| 824 | |||
| 825 | @param str axis_label: tells which axis should move. |
||
| 826 | @param int direction: either 1 or -1 depending on the relative movement. |
||
| 827 | |||
| 828 | That method get called from methods, which are created on the fly at |
||
| 829 | runtime during the activation of that module (basically from the |
||
| 830 | methods with the generic name move_rel_axis_{0}_p or |
||
| 831 | move_rel_axis_{0}_m with the appropriate label). |
||
| 832 | """ |
||
| 833 | constraints = self._magnet_logic.get_hardware_constraints() |
||
| 834 | dspinbox = self.get_ref_move_rel_ScienDSpinBox(axis_label) |
||
| 835 | |||
| 836 | movement = dspinbox.value() * direction |
||
| 837 | |||
| 838 | self._magnet_logic.move_rel({axis_label: movement}) |
||
| 839 | # if self._interactive_mode: |
||
| 840 | # self.update_pos() |
||
| 841 | |||
| 842 | def move_abs(self, param_dict=None): |
||
| 843 | """ Perform an absolute movement. |
||
| 844 | |||
| 845 | @param param_dict: with {<axis_label>:<position>}, can of course |
||
| 846 | contain many entries of the same kind. |
||
| 847 | |||
| 848 | Basically all the axis can be controlled at the same time. |
||
| 849 | """ |
||
| 850 | |||
| 851 | if (param_dict is not None) and (type(param_dict) is not bool): |
||
| 852 | self._magnet_logic.move_abs(param_dict) |
||
| 853 | else: |
||
| 854 | constraints = self._magnet_logic.get_hardware_constraints() |
||
| 855 | |||
| 856 | # create the move_abs dict |
||
| 857 | move_abs = {} |
||
| 858 | for label in constraints: |
||
| 859 | move_abs[label] = self.get_ref_move_abs_ScienDSpinBox(label).value() |
||
| 860 | |||
| 861 | self._magnet_logic.move_abs(move_abs) |
||
| 862 | |||
| 863 | # if self._interactive_mode: |
||
| 864 | # self.update_pos() |
||
| 865 | |||
| 866 | |||
| 867 | def get_ref_curr_pos_ScienDSpinBox(self, label): |
||
| 868 | """ Get the reference to the double spin box for the passed label. """ |
||
| 869 | |||
| 870 | dspinbox_name = 'curr_pos_axis{0}_ScienDSpinBox'.format(label) |
||
| 871 | dspinbox_ref = getattr(self._mw, dspinbox_name) |
||
| 872 | return dspinbox_ref |
||
| 873 | |||
| 874 | def get_ref_move_rel_ScienDSpinBox(self, label): |
||
| 875 | """ Get the reference to the double spin box for the passed label. """ |
||
| 876 | |||
| 877 | dspinbox_name = 'move_rel_axis_{0}_ScienDSpinBox'.format(label) |
||
| 878 | dspinbox_ref = getattr(self._mw, dspinbox_name) |
||
| 879 | return dspinbox_ref |
||
| 880 | |||
| 881 | def get_ref_move_abs_ScienDSpinBox(self, label): |
||
| 882 | """ Get the reference to the double spin box for the passed label. """ |
||
| 883 | |||
| 884 | dspinbox_name = 'move_abs_axis_{0}_ScienDSpinBox'.format(label) |
||
| 885 | dspinbox_ref = getattr(self._mw, dspinbox_name) |
||
| 886 | return dspinbox_ref |
||
| 887 | |||
| 888 | def get_ref_move_abs_Slider(self, label): |
||
| 889 | """ Get the reference to the slider for the passed label. """ |
||
| 890 | |||
| 891 | slider_name = 'move_abs_axis_{0}_Slider'.format(label) |
||
| 892 | slider_ref = getattr(self._mw, slider_name) |
||
| 893 | return slider_ref |
||
| 894 | |||
| 895 | def optimize_pos_changed(self): |
||
| 896 | """ Set whether postition should be optimized at each point. """ |
||
| 897 | |||
| 898 | state = self._mw.align_2d_fluorescence_optimize_CheckBox.isChecked() |
||
| 899 | self._magnet_logic.set_optimize_pos(state) |
||
| 900 | |||
| 901 | def stop_movement(self): |
||
| 902 | """ Invokes an immediate stop of the hardware. |
||
| 903 | |||
| 904 | MAKE SURE THAT THE HARDWARE CAN BE CALLED DURING AN ACTION! |
||
| 905 | If the parameter _interactive_mode is set to False no stop can be done |
||
| 906 | since the device would anyway not respond to a method call. |
||
| 907 | """ |
||
| 908 | |||
| 909 | if self._interactive_mode: |
||
| 910 | self._magnet_logic.stop_movement() |
||
| 911 | else: |
||
| 912 | self.log.warning('Movement cannot be stopped during a movement ' |
||
| 913 | 'anyway! Set the interactive mode to True in the Magnet ' |
||
| 914 | 'Settings! Otherwise this method is useless.') |
||
| 915 | |||
| 916 | def update_pos(self, param_list=None): |
||
| 917 | """ Update the current position. |
||
| 918 | |||
| 919 | @param list param_list: optional, if specific positions needed to be |
||
| 920 | updated. |
||
| 921 | |||
| 922 | If no value is passed, the current position is retrieved from the |
||
| 923 | logic and the display is changed. |
||
| 924 | """ |
||
| 925 | constraints = self._magnet_logic.get_hardware_constraints() |
||
| 926 | curr_pos = self._magnet_logic.get_pos() |
||
| 927 | |||
| 928 | if (param_list is not None) and (type(param_list) is not bool): |
||
| 929 | param_list = list(param_list) |
||
| 930 | # param_list =list(param_list) # convert for safety to a list |
||
| 931 | curr_pos = self._magnet_logic.get_pos(param_list) |
||
| 932 | |||
| 933 | for axis_label in curr_pos: |
||
| 934 | # update the values of the current position viewboxes: |
||
| 935 | dspinbox_pos_ref = self.get_ref_curr_pos_ScienDSpinBox(axis_label) |
||
| 936 | |||
| 937 | dspinbox_pos_ref.setValue(curr_pos[axis_label]) |
||
| 938 | |||
| 939 | # update the values also of the absolute movement display: |
||
| 940 | dspinbox_move_abs_ref = self.get_ref_move_abs_ScienDSpinBox(axis_label) |
||
| 941 | dspinbox_move_abs_ref.setValue(curr_pos[axis_label]) |
||
| 942 | |||
| 943 | |||
| 944 | def run_stop_2d_alignment(self, is_checked): |
||
| 945 | """ Manage what happens if 2d magnet scan is started/stopped |
||
| 946 | |||
| 947 | @param bool is_checked: state if the current scan, True = started, |
||
| 948 | False = stopped |
||
| 949 | """ |
||
| 950 | |||
| 951 | if is_checked: |
||
| 952 | self.start_2d_alignment_clicked() |
||
| 953 | |||
| 954 | else: |
||
| 955 | self.abort_2d_alignment_clicked() |
||
| 956 | |||
| 957 | def _change_display_to_stop_2d_alignment(self): |
||
| 958 | """ Changes every display component back to the stopped state. """ |
||
| 959 | |||
| 960 | self._mw.run_stop_2d_alignment_Action.blockSignals(True) |
||
| 961 | self._mw.run_stop_2d_alignment_Action.setChecked(False) |
||
| 962 | |||
| 963 | self._mw.continue_2d_alignment_Action.blockSignals(True) |
||
| 964 | self._mw.continue_2d_alignment_Action.setChecked(False) |
||
| 965 | |||
| 966 | self._mw.run_stop_2d_alignment_Action.blockSignals(False) |
||
| 967 | self._mw.continue_2d_alignment_Action.blockSignals(False) |
||
| 968 | |||
| 969 | def start_2d_alignment_clicked(self): |
||
| 970 | """ Start the 2d alignment. """ |
||
| 971 | |||
| 972 | if self.measurement_type == '2d_fluorescence': |
||
| 973 | self._magnet_logic.curr_alignment_method = self.measurement_type |
||
| 974 | |||
| 975 | self._magnet_logic.fluorescence_integration_time = self._mw.align_2d_fluorescence_integrationtime_DSpinBox.value() |
||
| 976 | |||
| 977 | self._mw.alignment_2d_cb_GraphicsView.setLabel('right', 'Fluorescence', units='c/s') |
||
| 978 | |||
| 979 | elif self.measurement_type == '2d_odmr': |
||
| 980 | self._magnet_logic.curr_alignment_method = self.measurement_type |
||
| 981 | |||
| 982 | self._magnet_logic.odmr_2d_low_center_freq = self._mw.align_2d_odmr_low_center_freq_DSpinBox.value() |
||
| 983 | self._magnet_logic.odmr_2d_low_range_freq = self._mw.align_2d_odmr_low_range_freq_DSpinBox.value() |
||
| 984 | self._magnet_logic.odmr_2d_low_step_freq = self._mw.align_2d_odmr_low_step_freq_DSpinBox.value() |
||
| 985 | self._magnet_logic.odmr_2d_low_power = self._mw.align_2d_odmr_low_power_DSpinBox.value() |
||
| 986 | self._magnet_logic.odmr_2d_low_runtime = self._mw.align_2d_odmr_low_runtime_DSpinBox.value() |
||
| 987 | self._magnet_logic.odmr_2d_low_fitfunction = self._mw.align_2d_odmr_low_fit_func_ComboBox.currentText() |
||
| 988 | |||
| 989 | self._magnet_logic.odmr_2d_high_center_freq = self._mw.align_2d_odmr_high_center_freq_DSpinBox.value() |
||
| 990 | self._magnet_logic.odmr_2d_high_range_freq = self._mw.align_2d_odmr_high_range_freq_DSpinBox.value() |
||
| 991 | self._magnet_logic.odmr_2d_high_step_freq = self._mw.align_2d_odmr_high_step_freq_DSpinBox.value() |
||
| 992 | self._magnet_logic.odmr_2d_high_power = self._mw.align_2d_odmr_high_power_DSpinBox.value() |
||
| 993 | self._magnet_logic.odmr_2d_high_runtime = self._mw.align_2d_odmr_high_runtime_DSpinBox.value() |
||
| 994 | self._magnet_logic.odmr_2d_high_fitfunction = self._mw.align_2d_odmr_high_fit_func_ComboBox.currentText() |
||
| 995 | |||
| 996 | self._magnet_logic.odmr_2d_peak_axis0_move_ratio = self._mw.align_2d_axes0_shift_DSpinBox.value()*1e12 |
||
| 997 | self._magnet_logic.odmr_2d_peak_axis1_move_ratio = self._mw.align_2d_axes1_shift_DSpinBox.value()*1e12 |
||
| 998 | |||
| 999 | self._magnet_logic.odmr_2d_single_trans = self._mw.odmr_2d_single_trans_CheckBox.isChecked() |
||
| 1000 | |||
| 1001 | if self._mw.odmr_2d_single_trans_CheckBox.isChecked(): |
||
| 1002 | self._mw.alignment_2d_cb_GraphicsView.setLabel('right', 'ODMR transition contrast', units='%') |
||
| 1003 | else: |
||
| 1004 | self._mw.alignment_2d_cb_GraphicsView.setLabel('right', 'Half ODMR splitting', units='Hz') |
||
| 1005 | |||
| 1006 | elif self.measurement_type == '2d_nuclear': |
||
| 1007 | self._magnet_logic.curr_alignment_method = self.measurement_type |
||
| 1008 | |||
| 1009 | # ODMR stuff: |
||
| 1010 | self._magnet_logic.odmr_2d_low_center_freq = self._mw.align_2d_odmr_low_center_freq_DSpinBox.value()*1e6 |
||
| 1011 | self._magnet_logic.odmr_2d_low_step_freq = self._mw.align_2d_odmr_low_step_freq_DSpinBox.value()*1e6 |
||
| 1012 | self._magnet_logic.odmr_2d_low_range_freq = self._mw.align_2d_odmr_low_range_freq_DSpinBox.value()*1e6 |
||
| 1013 | self._magnet_logic.odmr_2d_low_power = self._mw.align_2d_odmr_low_power_DSpinBox.value() |
||
| 1014 | self._magnet_logic.odmr_2d_low_runtime = self._mw.align_2d_odmr_low_runtime_DSpinBox.value() |
||
| 1015 | self._magnet_logic.odmr_2d_low_fitfunction = self._mw.align_2d_odmr_low_fit_func_ComboBox.currentText() |
||
| 1016 | |||
| 1017 | self._magnet_logic.odmr_2d_peak_axis0_move_ratio = self._mw.align_2d_axes0_shift_DSpinBox.value()*1e12 |
||
| 1018 | self._magnet_logic.odmr_2d_peak_axis1_move_ratio = self._mw.align_2d_axes1_shift_DSpinBox.value()*1e12 |
||
| 1019 | |||
| 1020 | self._magnet_logic.odmr_2d_single_trans = self._mw.odmr_2d_single_trans_CheckBox.isChecked() |
||
| 1021 | |||
| 1022 | # nuclear ops: |
||
| 1023 | self._magnet_logic.nuclear_2d_rabi_periode = self._mw.align_2d_nuclear_rabi_periode_DSpinBox.value()*1e-9 |
||
| 1024 | self._magnet_logic.nuclear_2d_mw_freq = self._mw.align_2d_nuclear_mw_freq_DSpinBox.value()*1e6 |
||
| 1025 | self._magnet_logic.nuclear_2d_mw_channel = self._mw.align_2d_nuclear_mw_channel_SpinBox.value() |
||
| 1026 | self._magnet_logic.nuclear_2d_mw_power = self._mw.align_2d_nuclear_mw_power_DSpinBox.value() |
||
| 1027 | self._magnet_logic.nuclear_2d_laser_time = self._mw.align_2d_nuclear_laser_time_DSpinBox.value() |
||
| 1028 | self._magnet_logic.nuclear_2d_laser_channel = self._mw.align_2d_nuclear_laser_channel_SpinBox.value() |
||
| 1029 | self._magnet_logic.nuclear_2d_detect_channel = self._mw.align_2d_nuclear_detect_channel_SpinBox.value() |
||
| 1030 | self._magnet_logic.nuclear_2d_idle_time = self._mw.align_2d_nuclear_idle_time_DSpinBox.value() |
||
| 1031 | self._magnet_logic.nuclear_2d_reps_within_ssr = self._mw.align_2d_nuclear_reps_within_ssr_SpinBox.value() |
||
| 1032 | self._magnet_logic.nuclear_2d_num_ssr = self._mw.align_2d_nuclear_num_of_ssr_SpinBox.value() |
||
| 1033 | |||
| 1034 | self._mw.alignment_2d_cb_GraphicsView.setLabel('right', 'Single shot readout fidelity', units='%') |
||
| 1035 | |||
| 1036 | |||
| 1037 | constraints = self._magnet_logic.get_hardware_constraints() |
||
| 1038 | |||
| 1039 | axis0_name = self._mw.align_2d_axes0_name_ComboBox.currentText() |
||
| 1040 | axis0_range = self._mw.align_2d_axes0_range_DSpinBox.value() |
||
| 1041 | axis0_step = self._mw.align_2d_axes0_step_DSpinBox.value() |
||
| 1042 | |||
| 1043 | axis1_name = self._mw.align_2d_axes1_name_ComboBox.currentText() |
||
| 1044 | axis1_range = self._mw.align_2d_axes1_range_DSpinBox.value() |
||
| 1045 | axis1_step = self._mw.align_2d_axes1_step_DSpinBox.value() |
||
| 1046 | |||
| 1047 | if axis0_name == axis1_name: |
||
| 1048 | self.log.error('Fluorescence Alignment cannot be started since the ' |
||
| 1049 | 'same axis with name "{0}" was chosen for axis0 and ' |
||
| 1050 | 'axis1!\n' |
||
| 1051 | 'Alignment will not be started. Change the ' |
||
| 1052 | 'settings!'.format(axis0_name)) |
||
| 1053 | return |
||
| 1054 | |||
| 1055 | if self._mw.align_2d_axis0_set_vel_CheckBox.isChecked(): |
||
| 1056 | axis0_vel = self._mw.align_2d_axes0_vel_DSpinBox.value() |
||
| 1057 | else: |
||
| 1058 | axis0_vel = None |
||
| 1059 | View Code Duplication | ||
|
|
|||
| 1060 | if self._mw.align_2d_axis1_set_vel_CheckBox.isChecked(): |
||
| 1061 | axis1_vel = self._mw.align_2d_axes1_vel_DSpinBox.value() |
||
| 1062 | else: |
||
| 1063 | axis1_vel = None |
||
| 1064 | |||
| 1065 | self._magnet_logic.start_2d_alignment(axis0_name=axis0_name, axis0_range=axis0_range, |
||
| 1066 | axis0_step=axis0_step, axis1_name=axis1_name, |
||
| 1067 | axis1_range=axis1_range,axis1_step=axis1_step, |
||
| 1068 | axis0_vel=axis0_vel, axis1_vel=axis1_vel, |
||
| 1069 | continue_meas=self._continue_2d_fluorescence_alignment) |
||
| 1070 | |||
| 1071 | self._continue_2d_fluorescence_alignment = False |
||
| 1072 | |||
| 1073 | def continue_stop_2d_alignment(self, is_checked): |
||
| 1074 | """ Manage what happens if 2d magnet scan is continued/stopped |
||
| 1075 | |||
| 1076 | @param bool is_checked: state if the current scan, True = continue, |
||
| 1077 | False = stopped |
||
| 1078 | """ |
||
| 1079 | |||
| 1080 | if is_checked: |
||
| 1081 | self.continue_2d_alignment_clicked() |
||
| 1082 | else: |
||
| 1083 | self.abort_2d_alignment_clicked() |
||
| 1084 | |||
| 1085 | |||
| 1086 | def continue_2d_alignment_clicked(self): |
||
| 1087 | |||
| 1088 | View Code Duplication | self._continue_2d_fluorescence_alignment = True |
|
| 1089 | self.start_2d_alignment_clicked() |
||
| 1090 | |||
| 1091 | |||
| 1092 | def abort_2d_alignment_clicked(self): |
||
| 1093 | """ Stops the current Fluorescence alignment. """ |
||
| 1094 | |||
| 1095 | self._change_display_to_stop_2d_alignment() |
||
| 1096 | self._magnet_logic.stop_alignment() |
||
| 1097 | |||
| 1098 | def _update_limits_axis0(self): |
||
| 1099 | """ Whenever a new axis name was chosen in axis0 config, the limits of the |
||
| 1100 | viewboxes will be adjusted. |
||
| 1101 | """ |
||
| 1102 | |||
| 1103 | constraints = self._magnet_logic.get_hardware_constraints() |
||
| 1104 | axis0_name = self._mw.align_2d_axes0_name_ComboBox.currentText() |
||
| 1105 | |||
| 1106 | # set the range constraints: |
||
| 1107 | self._mw.align_2d_axes0_range_DSpinBox.setMinimum(0) |
||
| 1108 | self._mw.align_2d_axes0_range_DSpinBox.setMaximum(constraints[axis0_name]['pos_max']) |
||
| 1109 | self._mw.align_2d_axes0_range_DSpinBox.setSingleStep(constraints[axis0_name]['pos_step']) |
||
| 1110 | # self._mw.align_2d_axes0_range_DSpinBox.setDecimals(5) |
||
| 1111 | self._mw.align_2d_axes0_range_DSpinBox.setSuffix(constraints[axis0_name]['unit']) |
||
| 1112 | |||
| 1113 | # set the step constraints: |
||
| 1114 | self._mw.align_2d_axes0_step_DSpinBox.setMinimum(0) |
||
| 1115 | self._mw.align_2d_axes0_step_DSpinBox.setMaximum(constraints[axis0_name]['pos_max']) |
||
| 1116 | self._mw.align_2d_axes0_step_DSpinBox.setSingleStep(constraints[axis0_name]['pos_step']) |
||
| 1117 | # self._mw.align_2d_axes0_step_DSpinBox.setDecimals(5) |
||
| 1118 | self._mw.align_2d_axes0_step_DSpinBox.setSuffix(constraints[axis0_name]['unit']) |
||
| 1119 | |||
| 1120 | # set the velocity constraints: |
||
| 1121 | self._mw.align_2d_axes0_vel_DSpinBox.setMinimum(constraints[axis0_name]['vel_min']) |
||
| 1122 | self._mw.align_2d_axes0_vel_DSpinBox.setMaximum(constraints[axis0_name]['vel_max']) |
||
| 1123 | self._mw.align_2d_axes0_vel_DSpinBox.setSingleStep(constraints[axis0_name]['vel_step']) |
||
| 1124 | # self._mw.align_2d_axes0_vel_DSpinBox.setDecimals(5) |
||
| 1125 | self._mw.align_2d_axes0_vel_DSpinBox.setSuffix(constraints[axis0_name]['unit']+'/s') |
||
| 1126 | |||
| 1127 | def _update_limits_axis1(self): |
||
| 1128 | """ Whenever a new axis name was chosen in axis0 config, the limits of the |
||
| 1129 | viewboxes will be adjusted. |
||
| 1130 | """ |
||
| 1131 | |||
| 1132 | constraints = self._magnet_logic.get_hardware_constraints() |
||
| 1133 | axis1_name = self._mw.align_2d_axes1_name_ComboBox.currentText() |
||
| 1134 | |||
| 1135 | self._mw.align_2d_axes1_range_DSpinBox.setMinimum(0) |
||
| 1136 | self._mw.align_2d_axes1_range_DSpinBox.setMaximum(constraints[axis1_name]['pos_max']) |
||
| 1137 | self._mw.align_2d_axes1_range_DSpinBox.setSingleStep(constraints[axis1_name]['pos_step']) |
||
| 1138 | # self._mw.align_2d_axes1_range_DSpinBox.setDecimals(5) |
||
| 1139 | self._mw.align_2d_axes1_range_DSpinBox.setSuffix(constraints[axis1_name]['unit']) |
||
| 1140 | |||
| 1141 | self._mw.align_2d_axes1_step_DSpinBox.setMinimum(0) |
||
| 1142 | self._mw.align_2d_axes1_step_DSpinBox.setMaximum(constraints[axis1_name]['pos_max']) |
||
| 1143 | self._mw.align_2d_axes1_step_DSpinBox.setSingleStep(constraints[axis1_name]['pos_step']) |
||
| 1144 | # self._mw.align_2d_axes1_step_DSpinBox.setDecimals(5) |
||
| 1145 | self._mw.align_2d_axes1_step_DSpinBox.setSuffix(constraints[axis1_name]['unit']) |
||
| 1146 | |||
| 1147 | self._mw.align_2d_axes1_vel_DSpinBox.setMinimum(constraints[axis1_name]['vel_min']) |
||
| 1148 | self._mw.align_2d_axes1_vel_DSpinBox.setMaximum(constraints[axis1_name]['vel_max']) |
||
| 1149 | self._mw.align_2d_axes1_vel_DSpinBox.setSingleStep(constraints[axis1_name]['vel_step']) |
||
| 1150 | # self._mw.align_2d_axes1_vel_DSpinBox.setDecimals(5) |
||
| 1151 | self._mw.align_2d_axes1_vel_DSpinBox.setSuffix(constraints[axis1_name]['unit']+'/s') |
||
| 1152 | |||
| 1153 | def _set_vel_display_axis0(self): |
||
| 1154 | """ Set the visibility of the velocity display for axis 0. """ |
||
| 1155 | |||
| 1156 | if self._mw.align_2d_axis0_set_vel_CheckBox.isChecked(): |
||
| 1157 | self._mw.align_2d_axes0_vel_DSpinBox.setVisible(True) |
||
| 1158 | else: |
||
| 1159 | View Code Duplication | self._mw.align_2d_axes0_vel_DSpinBox.setVisible(False) |
|
| 1160 | |||
| 1161 | def _set_vel_display_axis1(self): |
||
| 1162 | """ Set the visibility of the velocity display for axis 1. """ |
||
| 1163 | |||
| 1164 | if self._mw.align_2d_axis1_set_vel_CheckBox.isChecked(): |
||
| 1165 | self._mw.align_2d_axes1_vel_DSpinBox.setVisible(True) |
||
| 1166 | else: |
||
| 1167 | self._mw.align_2d_axes1_vel_DSpinBox.setVisible(False) |
||
| 1168 | |||
| 1169 | def _update_2d_graph_axis(self): |
||
| 1170 | |||
| 1171 | constraints = self._magnet_logic.get_hardware_constraints() |
||
| 1172 | |||
| 1173 | axis0_name = self._mw.align_2d_axes0_name_ComboBox.currentText() |
||
| 1174 | axis0_unit = constraints[axis0_name]['unit'] |
||
| 1175 | axis1_name = self._mw.align_2d_axes1_name_ComboBox.currentText() |
||
| 1176 | axis1_unit = constraints[axis1_name]['unit'] |
||
| 1177 | |||
| 1178 | axis0_array, axis1_array = self._magnet_logic.get_2d_axis_arrays() |
||
| 1179 | |||
| 1180 | self._2d_alignment_ImageItem.setRect(QtCore.QRectF(axis0_array[0], |
||
| 1181 | axis1_array[0], |
||
| 1182 | axis0_array[-1]-axis0_array[0], |
||
| 1183 | axis1_array[-1]-axis1_array[0],)) |
||
| 1184 | |||
| 1185 | self._mw.alignment_2d_GraphicsView.setLabel('bottom', 'Absolute Position, Axis0: ' + axis0_name, units=axis0_unit) |
||
| 1186 | self._mw.alignment_2d_GraphicsView.setLabel('left', 'Absolute Position, Axis1: '+ axis1_name, units=axis1_unit) |
||
| 1187 | |||
| 1188 | View Code Duplication | def _update_2d_graph_cb(self): |
|
| 1189 | """ Update the colorbar to a new scaling. |
||
| 1190 | |||
| 1191 | That function alters the color scaling of the colorbar next to the main |
||
| 1192 | picture. |
||
| 1193 | """ |
||
| 1194 | |||
| 1195 | # If "Centiles" is checked, adjust colour scaling automatically to |
||
| 1196 | # centiles. Otherwise, take user-defined values. |
||
| 1197 | |||
| 1198 | if self._mw.alignment_2d_centiles_RadioButton.isChecked(): |
||
| 1199 | |||
| 1200 | low_centile = self._mw.alignment_2d_cb_low_centiles_DSpinBox.value() |
||
| 1201 | high_centile = self._mw.alignment_2d_cb_high_centiles_DSpinBox.value() |
||
| 1202 | |||
| 1203 | if np.isclose(low_centile, 0.0): |
||
| 1204 | low_centile = 0.0 |
||
| 1205 | |||
| 1206 | # mask the array such that the arrays will be |
||
| 1207 | masked_image = np.ma.masked_equal(self._2d_alignment_ImageItem.image, 0.0) |
||
| 1208 | |||
| 1209 | if len(masked_image.compressed()) == 0: |
||
| 1210 | cb_min = np.percentile(self._2d_alignment_ImageItem.image, low_centile) |
||
| 1211 | cb_max = np.percentile(self._2d_alignment_ImageItem.image, high_centile) |
||
| 1212 | else: |
||
| 1213 | cb_min = np.percentile(masked_image.compressed(), low_centile) |
||
| 1214 | cb_max = np.percentile(masked_image.compressed(), high_centile) |
||
| 1215 | |||
| 1216 | else: |
||
| 1217 | cb_min = self._mw.alignment_2d_cb_min_centiles_DSpinBox.value() |
||
| 1218 | cb_max = self._mw.alignment_2d_cb_max_centiles_DSpinBox.value() |
||
| 1219 | |||
| 1220 | self._2d_alignment_cb.refresh_colorbar(cb_min, cb_max) |
||
| 1221 | self._mw.alignment_2d_cb_GraphicsView.update() |
||
| 1222 | View Code Duplication | ||
| 1223 | def _update_2d_graph_data(self): |
||
| 1224 | """ Refresh the 2D-matrix image. """ |
||
| 1225 | matrix_data = self._magnet_logic.get_2d_data_matrix() |
||
| 1226 | |||
| 1227 | if self._mw.alignment_2d_centiles_RadioButton.isChecked(): |
||
| 1228 | |||
| 1229 | low_centile = self._mw.alignment_2d_cb_low_centiles_DSpinBox.value() |
||
| 1230 | high_centile = self._mw.alignment_2d_cb_high_centiles_DSpinBox.value() |
||
| 1231 | |||
| 1232 | if np.isclose(low_centile, 0.0): |
||
| 1233 | low_centile = 0.0 |
||
| 1234 | |||
| 1235 | # mask the array in order to mark the values which are zeros with |
||
| 1236 | # True, the rest with False: |
||
| 1237 | masked_image = np.ma.masked_equal(matrix_data, 0.0) |
||
| 1238 | |||
| 1239 | # compress the 2D masked array to a 1D array where the zero values |
||
| 1240 | # are excluded: |
||
| 1241 | if len(masked_image.compressed()) == 0: |
||
| 1242 | cb_min = np.percentile(self._2d_alignment_ImageItem.image, low_centile) |
||
| 1243 | cb_max = np.percentile(self._2d_alignment_ImageItem.image, high_centile) |
||
| 1244 | else: |
||
| 1245 | cb_min = np.percentile(masked_image.compressed(), low_centile) |
||
| 1246 | cb_max = np.percentile(masked_image.compressed(), high_centile) |
||
| 1247 | else: |
||
| 1248 | cb_min = self._mw.alignment_2d_cb_min_centiles_DSpinBox.value() |
||
| 1249 | cb_max = self._mw.alignment_2d_cb_max_centiles_DSpinBox.value() |
||
| 1250 | |||
| 1251 | |||
| 1252 | self._2d_alignment_ImageItem.setImage(image=matrix_data, |
||
| 1253 | levels=(cb_min, cb_max)) |
||
| 1254 | self._update_2d_graph_axis() |
||
| 1255 | |||
| 1256 | self._update_2d_graph_cb() |
||
| 1257 | |||
| 1258 | # get data from logic |
||
| 1259 | |||
| 1260 | |||
| 1261 | def save_2d_plots_and_data(self): |
||
| 1262 | """ Save the sum plot, the scan marix plot and the scan data """ |
||
| 1263 | timestamp = datetime.datetime.now() |
||
| 1264 | filetag = self._mw.alignment_2d_nametag_LineEdit.text() |
||
| 1265 | filepath = self._save_logic.get_path_for_module(module_name='Magnet') |
||
| 1266 | |||
| 1267 | if len(filetag) > 0: |
||
| 1268 | filename = os.path.join(filepath, '{0}_{1}_Magnet'.format(timestamp.strftime('%Y%m%d-%H%M-%S'), filetag)) |
||
| 1269 | else: |
||
| 1270 | filename = os.path.join(filepath, '{0}_Magnet'.format(timestamp.strftime('%Y%m%d-%H%M-%S'),)) |
||
| 1271 | |||
| 1272 | exporter_graph = pyqtgraph.exporters.SVGExporter(self._mw.alignment_2d_GraphicsView.plotItem.scene()) |
||
| 1273 | #exporter_graph = pg.exporters.ImageExporter(self._mw.odmr_PlotWidget.plotItem) |
||
| 1274 | exporter_graph.export(filename + '.svg') |
||
| 1275 | |||
| 1276 | # self._save_logic. |
||
| 1277 | self._magnet_logic.save_2d_data(filetag, timestamp) |
||
| 1278 | |||
| 1279 | def set_measurement_type(self): |
||
| 1280 | """ According to the selected Radiobox a measurement type will be chosen.""" |
||
| 1281 | |||
| 1282 | #FIXME: the measurement type should actually be set and saved in the logic |
||
| 1283 | |||
| 1284 | if self._mw.meas_type_fluorescence_RadioButton.isChecked(): |
||
| 1285 | self.measurement_type = '2d_fluorescence' |
||
| 1286 | elif self._mw.meas_type_odmr_RadioButton.isChecked(): |
||
| 1287 | self.measurement_type = '2d_odmr' |
||
| 1288 | elif self._mw.meas_type_nuclear_spin_RadioButton.isChecked(): |
||
| 1289 | self.measurement_type = '2d_nuclear' |
||
| 1290 | else: |
||
| 1291 | self.log.error('No measurement type specified in Magnet GUI!') |
||
| 1292 | def _odmr_single_trans_alignment_changed(self): |
||
| 1293 | """ Adjust the GUI display if only one ODMR transition is used. """ |
||
| 1294 | |||
| 1295 | if self._mw.odmr_2d_single_trans_CheckBox.isChecked(): |
||
| 1296 | self._mw.odmr_2d_high_trans_GroupBox.setVisible(False) |
||
| 1297 | else: |
||
| 1298 | self._mw.odmr_2d_high_trans_GroupBox.setVisible(True) |
||
| 1299 |