def set_property_bag(self, property_bag, show_hidden=False, display_hwobj=False): self.display_hwobj = display_hwobj self.clear() if self.property_bag is not None: for prop in self.property_bag: prop._editor = None self.property_bag = property_bag if self.property_bag is not None: i = 0 for prop in self.property_bag: prop._editor = weakref.ref(self) prop_name = prop.get_name() if not show_hidden and prop.hidden: continue if display_hwobj: if not prop_name.startswith("hwobj_"): continue else: prop_name = prop_name.replace("hwobj_", "") else: if prop_name.startswith("hwobj_"): continue self.setRowCount(i + 1) temp_table_item = QtImport.QTableWidgetItem(prop_name) temp_table_item.setFlags(QtImport.Qt.ItemIsEnabled) self.blockSignals(True) self.setItem(i, 0, temp_table_item) self.set_widget_from_property(i, prop) temp_table_item = QtImport.QTableWidgetItem(prop.comment) temp_table_item.setFlags(QtImport.Qt.ItemIsEnabled) self.setItem(i, 3, temp_table_item) self.blockSignals(False) validation_panel = ValidationTableItem(self) self.setCellWidget(i, 2, validation_panel) validation_panel.ok_button.clicked.connect( self.on_validate_click) validation_panel.cancel_button.clicked.connect( self.on_invalidate_click) validation_panel.reset_button.clicked.connect( self.on_reset_click) i += 1 self.setEnabled(i > 0) self.resizeColumnsToContents() self.setFixedHeight((self.rowCount() + 1) * (self.rowHeight(0) + 2)) # self.adjustSize() self.parent().adjustSize()
def test_focus_mode(self): if not hasattr(self.beamline_test_hwobj, "get_focus_mode"): self.test_focus_page.setEnabled(False) return active_mode, beam_size = self.beamline_test_hwobj.get_focus_mode() if active_mode is None: self.beamline_test_widget.focus_mode_label.setText( "<font color='red'>No focusing mode detected<font>") else: self.beamline_test_widget.focus_mode_label.setText( "<font color='black'>%s mode detected<font>" % active_mode) focus_modes = self.beamline_test_hwobj.get_focus_mode_names() focus_modes_table = self.beamline_test_widget.focus_modes_table focus_modes_combo = self.beamline_test_widget.focus_modes_combo if focus_modes: focus_modes_table.setColumnCount(len(focus_modes)) focus_modes_combo.clear() hor_labels = QtImport.QStringList(focus_modes) focus_modes_table.setHorizontalHeaderLabels(hor_labels) for col, mode in enumerate(focus_modes): focus_modes_combo.addItem(mode) if active_mode: focus_modes_combo.setCurrentIndex( focus_modes_combo.findText(active_mode)) else: focus_modes_combo.setCurrentIndex(-1) focus_motors_list = self.beamline_test_hwobj.get_focus_motors() if focus_motors_list: ver_labels = QtImport.QStringList() focus_modes_table.setRowCount(len(focus_motors_list)) for row, motor in enumerate(focus_motors_list): ver_labels.append(motor["motorName"]) for col, mode in enumerate(focus_modes): item_text = "%.3f/%.3f" % ( motor["focusingModes"][mode], motor["position"], ) res = mode in motor["focMode"] if res: temp_table_item = QtImport.QTableWidgetItem(item_text) temp_table_item.setBackground(Colors.LIGHT_GREEN) else: temp_table_item = QtImport.QTableWidgetItem(item_text) temp_table_item.setBackground(Colors.LIGHT_RED) focus_modes_table.setItem(row, col, temp_table_item) focus_modes_table.setVerticalHeaderLabels(ver_labels)
def init_view(self): self.chan_config = HWR.beamline.online_processing.ssx_setup.get_current_chip_config( ) self.chan_table.blockSignals(True) self.chan_table.setColumnCount(3) for index, header_text in enumerate(("Name", "Delay", "Length")): self.chan_table.setHorizontalHeaderItem( index, QtImport.QTableWidgetItem(header_text)) if index > 0: self.chan_table.resizeColumnToContents(index) self.chan_table.setRowCount(self.chan_config["num_channels"]) self.chan_seq = [None] * self.chan_config["num_channels"] self.chan_table.setFixedHeight(30 * (self.chan_config["num_channels"] + 1)) for index in range(self.chan_config["num_channels"]): combo = QtImport.QComboBox() combo.activated.connect(self.chan_seq_combo_activated) for chan_name in self.chan_config["channels"].keys(): combo.addItem(chan_name) combo.addItem("") combo.setCurrentIndex(-1) self.chan_table.setCellWidget(index, 0, combo) self.chan_combo_items.append(combo) for col in (1, 2): self.chan_table.setItem(index, col, QtImport.QTableWidgetItem("")) if index < len(self.chan_config["default_seq"]): def_chan_item_name = self.chan_config["default_seq"][index] combo.setCurrentIndex(combo.findText(def_chan_item_name)) self.chan_table.setItem( index, 1, QtImport.QTableWidgetItem( str(self.chan_config["channels"][def_chan_item_name] [0]))) self.chan_table.setItem( index, 2, QtImport.QTableWidgetItem( str(self.chan_config["channels"][def_chan_item_name] [1]))) self.chan_table.blockSignals(False) self.refresh_chan_sequence()
def create_dg_channels_list(self, num_exp): chip_config = self.ssx_control_hwobj.get_config() # set number of columns self.ssx_widget_layout.dg_channels_table.setColumnCount(num_exp) # add checkboxes if a new number of exposures is bigger than the old one dg_channels_list = [] if num_exp > chip_config["old_num_of_exp"]: for row in range(0, 4): checkbox_item = QtImport.QTableWidgetItem() checkbox_item.setFlags( QtImport.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled ) checkbox_item.setCheckState(QtImport.Qt.Unchecked) # add checkboxes to the list dg_channels_list.append(checkbox_item) self.ssx_widget_layout.dg_channels_table.setItem( row, num_exp - 1, checkbox_item ) # remove checkboxes from the list if a new number of exposures is bigger # than the old one if num_exp < chip_config["old_num_of_exp"]: for row in range(0, 4): del dg_channels_list[len(dg_channels_list) - 1] self.ssx_control_hwobj.set_dg_channels_list(dg_channels_list) # update old number of exposures self.ssx_control_hwobj.set_config_item("old_num_of_exp", num_exp)
def init_interface(self): """ Build up GUI """ tmp_dict = self.multipos_hwobj.get_positions() if tmp_dict: if not self.table_created: # create table items for first and only time self.ui_widgets_manager.beam_positions_table.setRowCount( len(tmp_dict)) for row in range(len(tmp_dict)): for col in range(3): tmp_item = QtImport.QTableWidgetItem() tmp_item.setFlags(tmp_item.flags() ^ QtImport.Qt.ItemIsEditable) self.ui_widgets_manager.beam_positions_table.setItem( row, col, tmp_item) self.table_created = True table = self.ui_widgets_manager.beam_positions_table for i, (position, position_dict) in enumerate(tmp_dict.items()): beam_pos_x = position_dict["beam_pos_x"] beam_pos_y = position_dict["beam_pos_y"] table.item(i, 0).setText(str(position)) table.item(i, 1).setText(str(beam_pos_x)) table.item(i, 2).setText(str(beam_pos_y))
def init_state_machine(self): self.cond_list = self.state_machine_hwobj.get_condition_list() self.states_list = self.state_machine_hwobj.get_state_list() self.trans_list = self.state_machine_hwobj.get_transition_list() self.cond_states_table.setRowCount(len(self.cond_list)) # conditions = [] # for key in self.cond_list.keys(): # conditions.append(self.cond_list[key]['name']) # self.cond_states_table.setVerticalHeaderLabels(self.cond_list.keys()) self.cond_states_table.setColumnCount(len(self.states_list)) self.cond_states_table.setHorizontalHeader( QtImport.RotatedHeaderView(self.cond_states_table) ) states_name_list = [] for index, state in enumerate(self.states_list): states_name_list.append("%d %s" % (index + 1, state["desc"])) self.cond_states_table.setHorizontalHeaderLabels(states_name_list) condition_name_list = [] for index, condition in enumerate(self.cond_list): condition_name_list.append("%d %s" % (index + 1, condition["desc"])) self.cond_states_table.setVerticalHeaderLabels(condition_name_list) self.cond_states_table.resizeColumnsToContents() for col in range(self.cond_states_table.columnCount()): for row in range(self.cond_states_table.rowCount()): temp_item = QtImport.QTableWidgetItem() self.cond_states_table.setItem(row, col, temp_item)
def populate_widget(self, item): dcg_queue_item = item.get_queue_entry() dcg_child_list = [] sw_list = [] if dcg_queue_item.interleave_sw_list: sw_list = dcg_queue_item.interleave_sw_list for child in dcg_queue_item.interleave_items: dcg_child_list.append(child["data_model"]) else: for children in dcg_queue_item.get_queue_entry_list(): if isinstance(children.get_view(), queue_item.DataCollectionQueueItem): dcg_child_list.append(children.get_data_model()) acq_par = (children.get_data_model().acquisitions[0]. acquisition_parameters) sw_list.append([ len(sw_list), 0, acq_par.first_image, acq_par.num_images, acq_par.osc_start, acq_par.osc_range * acq_par.num_images, ]) for sw in sw_list: color = Colors.get_random_numpy_color() sw.append(color) self.subwedge_table.setRowCount(0) for sw in sw_list: acq_par = dcg_child_list[ sw[0]].acquisitions[0].acquisition_parameters row = self.subwedge_table.rowCount() self.subwedge_table.setRowCount(row + 1) param_list = ( str(acq_par.osc_start), str(acq_par.osc_range), str(acq_par.num_images), str(acq_par.exp_time), str(acq_par.energy), str(acq_par.transmission), str(acq_par.resolution), ) # color = Colors.get_random_color() # sw.append(color) for col in range(7): self.subwedge_table.setItem( row, col, QtImport.QTableWidgetItem(param_list[col])) color = QtImport.QColor(int(sw[-1][0] * 255), int(sw[-1][0] * 255), int(sw[-1][0] * 255)) color.setAlpha(100) self.subwedge_table.item(row, col).setBackground(color) # QtGui.QColor(Colors.TASK_GROUP[sw[0]])) self.polar_scater_widget.draw_multiwedge_scater(sw_list)
def init_plate_view(self): """Initalizes plate info """ cell_width = 25 cell_height = 23 plate_info = HWR.beamline.plate_manipulator.get_plate_info() self.num_cols = plate_info.get("num_cols", 12) self.num_rows = plate_info.get("num_rows", 8) self.num_drops = plate_info.get("num_drops", 3) self.plate_navigator_table.setColumnCount(self.num_cols) self.plate_navigator_table.setRowCount(self.num_rows) for col in range(self.num_cols): temp_header_item = QtImport.QTableWidgetItem("%d" % (col + 1)) self.plate_navigator_table.setHorizontalHeaderItem( col, temp_header_item) self.plate_navigator_table.setColumnWidth(col, cell_width) for row in range(self.num_rows): temp_header_item = QtImport.QTableWidgetItem(chr(65 + row)) self.plate_navigator_table.setVerticalHeaderItem( row, temp_header_item) self.plate_navigator_table.setRowHeight(row, cell_height) for col in range(self.num_cols): for row in range(self.num_rows): temp_item = QtImport.QTableWidgetItem() self.plate_navigator_table.setItem(row, col, temp_item) table_width = cell_width * (self.num_cols + 1) table_height = (cell_height + 2) * (self.num_rows + 1) self.plate_navigator_table.setFixedWidth(table_width) self.plate_navigator_table.setFixedHeight(table_height) self.plate_navigator_cell.setFixedHeight(table_height) self.plate_navigator_cell.setFixedWidth(200) self.setFixedHeight(table_height + 2) self.navigation_graphicsscene.setSceneRect(0, 0, table_height, 200) self.navigation_item.set_size(200, table_height) self.navigation_item.set_num_drops_per_cell(plate_info['num_drops']) self.refresh_plate_location()
def update_table(self): header = self.ssx_widget_layout.interlacings_tableWidget.horizontalHeader() self.ssx_widget_layout.quarter_density_checkbox.setEnabled(True) self.ssx_widget_layout.meandering_checkbox.setEnabled(True) # gets the list of interlacings interlacings_list = self.ssx_control_hwobj.get_interlacings_list() # update interlacings_textEdit self.ssx_widget_layout.interlacings_text_edit.setText( str(len(interlacings_list)) ) # set number of rows and columns self.ssx_widget_layout.interlacings_tableWidget.setRowCount( len(interlacings_list) ) self.ssx_widget_layout.interlacings_tableWidget.setColumnCount(2) # resize columns respectively header.setResizeMode(QtImport.QHeaderView.Stretch) # headers names self.ssx_widget_layout.interlacings_tableWidget.setHorizontalHeaderLabels( QtImport.QString("interlace;est. delay (s)").split(";") ) # set non editable self.ssx_widget_layout.interlacings_tableWidget.setEditTriggers( QtImport.QAbstractItemView.NoEditTriggers ) # fill the table for element in range(0, len(interlacingsList)): self.ssx_widget_layout.interlacings_tableWidget.setItem( element, 0, QtImport.QTableWidgetItem(str(interlacingsList[element])) ) self.ssx_widget_layout.interlacings_tableWidget.setItem( element, 1, QtImport.QTableWidgetItem( str(round(interlacingsList[element] / scan_rate, 3)) ), )
def init_tables(self): """ Inits table with status info :return: """ self.status_str_desc = api.sample_changer.get_status_str_desc() self.index_dict = {} self.status_table.setRowCount(len(self.status_str_desc)) for row, key in enumerate(self.status_str_desc.keys()): temp_item = QtImport.QTableWidgetItem(key) self.status_table.setItem(row, 0, temp_item) temp_item = QtImport.QTableWidgetItem(self.status_str_desc[key]) self.status_table.setItem(row, 1, temp_item) temp_item = QtImport.QTableWidgetItem("") self.status_table.setItem(row, 2, temp_item) self.index_dict[key] = row self.status_table.resizeColumnToContents(0) self.status_table.resizeColumnToContents(1)
def refresh_plate_location(self): new_location = HWR.beamline.plate_manipulator.get_plate_location() self.plate_navigator_cell.setEnabled(True) if new_location: row = new_location[0] col = new_location[1] pos_x = new_location[2] pos_y = new_location[3] self.navigation_item.set_navigation_pos(pos_x, pos_y) self.plate_navigator_cell.update() if self.__current_location != new_location: empty_item = QtImport.QTableWidgetItem(QtImport.QIcon(), "") self.plate_navigator_table.setItem(self.__current_location[0], self.__current_location[1], empty_item) new_item = QtImport.QTableWidgetItem( Icons.load_icon("sample_axis"), "") self.plate_navigator_table.setItem(row, col, new_item) self.__current_location = new_location
def set_widget_from_property(self, row, prop): """Adds new property to the propery table :param row: selected row :type row: int :param prop: property :type prop: dict """ if prop.get_type() == "boolean": new_property_item = QtImport.QTableWidgetItem("") self.setItem(row, 1, new_property_item) if prop.get_user_value(): self.item(row, 1).setCheckState(QtImport.Qt.Checked) else: self.item(row, 1).setCheckState(QtImport.Qt.Unchecked) elif prop.get_type() == "combo": choices_list = [] choices = prop.get_choices() for choice in choices: choices_list.append(choice) new_property_item = ComboBoxTableItem(self, row, 1, choices_list) new_property_item.setCurrentIndex( new_property_item.findText(prop.get_user_value())) self.setCellWidget(row, 1, new_property_item) elif prop.get_type() == "file": new_property_item = FileTableItem(self, row, 1, prop.get_user_value(), prop.getFilter()) self.setCellWidget(row, 1, new_property_item) elif prop.get_type() == "color": new_property_item = ColorTableItem(self, row, 1, prop.get_user_value()) self.setCellWidget(row, 1, new_property_item) else: if prop.get_user_value() is None: temp_table_item = QtImport.QTableWidgetItem("") else: temp_table_item = QtImport.QTableWidgetItem( str(prop.get_user_value())) self.setItem(row, 1, temp_table_item) self.resizeColumnsToContents()
def fill_config_table(self): tmp_dict = self.multipos_hwobj.get_positions() if tmp_dict is not None: self.ui_widgets_manager.configuration_table.itemChanged.disconnect( self.configuration_table_item_changed) if not self.table_created: # create table items for first and only time self.ui_widgets_manager.configuration_table.setRowCount( len(tmp_dict)) for row in range(len(tmp_dict)): for col in range(7): tmp_item = QtImport.QTableWidgetItem() if col == 0: #zoom position name not editable tmp_item.setFlags(tmp_item.flags() ^ QtImport.Qt.ItemIsEditable) self.ui_widgets_manager.configuration_table.setItem( row, col, tmp_item) self.table_created = True table = self.ui_widgets_manager.configuration_table for i, (position, position_dict_elem) in enumerate(tmp_dict.items()): table.item(i, 0).setText(str(position)) table.item(i, 1).setText(str(position_dict_elem["beam_pos_x"])) table.item(i, 2).setText(str(position_dict_elem["beam_pos_y"])) if position_dict_elem["cal_x"] == 1: y_calib = "Not defined" else: y_calib = str(abs(int(position_dict_elem["cal_x"]))) if position_dict_elem["cal_y"] == 1: z_calib = "Not defined" else: z_calib = str(abs(int(position_dict_elem["cal_y"]))) table.item(i, 3).setText(y_calib) table.item(i, 4).setText(z_calib) table.item(i, 5).setText(str(position_dict_elem['light'])) table.item(i, 6).setText(str(position_dict_elem['zoom'])) self.ui_widgets_manager.configuration_table.itemChanged.connect( self.configuration_table_item_changed) self.ui_widgets_manager.configuration_table.horizontalHeader( ).setSectionResizeMode(QtImport.QHeaderView.ResizeToContents)
def change_point_number(self, new_int_value): """ Adapt """ self.points_for_aligment = new_int_value # restart the table and populate with items table = self.ui_widgets_manager.aligment_table table.clearContents() table.setRowCount(self.points_for_aligment) for row in range(table.rowCount()): table.setItem(row, 0, QtImport.QTableWidgetItem("")) table.setItem(row, 1, QtImport.QTableWidgetItem("")) table.setItem(row, 2, QtImport.QTableWidgetItem("")) if HWR.beamline.diffractometer is not None: HWR.beamline.diffractometer.set_centring_parameters( self.points_for_aligment, self.delta_phi )
def init_tables(self): client_info = self.exporter_client_hwobj.get_client_info() self.info_address_ledit.setText("%s:%d" % (client_info[0], client_info[1])) method_list = self.exporter_client_hwobj.get_method_list() self.method_table.setRowCount(len(method_list)) for index, method in enumerate(method_list): string_list = method.split(" ") temp_item = QtImport.QTableWidgetItem(string_list[0]) self.method_table.setItem(index, 0, temp_item) temp_item = QtImport.QTableWidgetItem(string_list[1]) self.method_table.setItem(index, 1, temp_item) property_list = self.exporter_client_hwobj.get_property_list() self.property_table.setRowCount(len(property_list)) for index, prop in enumerate(property_list): string_list = prop.split(" ") temp_item = QtImport.QTableWidgetItem(string_list[0]) self.property_table.setItem(index, 0, temp_item) temp_item = QtImport.QTableWidgetItem(string_list[1]) self.property_table.setItem(index, 1, temp_item) temp_item = QtImport.QTableWidgetItem(string_list[2]) self.property_table.setItem(index, 2, temp_item) temp_item = QtImport.QTableWidgetItem() self.property_table.setItem(index, 3, temp_item) self.refresh_property_values()
def set_best_pos(self): """Displays 10 (if exists) best positions """ self._best_pos_table.setRowCount( len(self.__results_raw.get("best_positions", []))) for row, best_pos in enumerate( self.__results_raw.get("best_positions", [])): self._best_pos_table.setItem( row, 0, QtImport.QTableWidgetItem("%d" % (best_pos.get("index") + 1))) self._best_pos_table.setItem( row, 1, QtImport.QTableWidgetItem("%.2f" % (best_pos.get("score")))) self._best_pos_table.setItem( row, 2, QtImport.QTableWidgetItem("%d" % (best_pos.get("spots_num")))) self._best_pos_table.setItem( row, 3, QtImport.QTableWidgetItem("%.2f" % (best_pos.get("spots_int_aver"))), ) self._best_pos_table.setItem( row, 4, QtImport.QTableWidgetItem("%.2f" % (best_pos.get("spots_resolution"))), ) self._best_pos_table.setItem( row, 5, QtImport.QTableWidgetItem(str(best_pos.get("filename")))) self._best_pos_table.setItem( row, 6, QtImport.QTableWidgetItem("%d" % (best_pos.get("col")))) self._best_pos_table.setItem( row, 7, QtImport.QTableWidgetItem("%d" % (best_pos.get("row")))) if best_pos["cpos"]: self._best_pos_table.setItem( row, 8, QtImport.QTableWidgetItem(str(best_pos["cpos"]))) self._best_pos_table.setSortingEnabled(True)
def property_changed(self, property_name, old_value, new_value): """Defines gui and connects to hwobj based on the user defined properties""" if property_name == "mnemonic": if self.crl_hwobj: self.disconnect(self.crl_hwobj, "crlModeChanged", self.crl_mode_changed) self.disconnect(self.crl_hwobj, "crlValueChanged", self.crl_value_changed) self.crl_hwobj = self.get_hardware_object(new_value) if self.crl_hwobj: crl_modes = self.crl_hwobj.get_modes() for crl_mode in crl_modes: self.mode_combo.addItem(crl_mode) self.connect(self.crl_hwobj, "crlModeChanged", self.crl_mode_changed) self.connect(self.crl_hwobj, "crlValueChanged", self.crl_value_changed) self.crl_hwobj.re_emit_values() elif property_name == "lenseCount": self.crl_value_table.setColumnCount(new_value) for col_index in range(new_value): temp_item = QtImport.QTableWidgetItem("") temp_item.setFlags(QtImport.Qt.ItemIsEnabled) temp_item.setBackground(Colors.LIGHT_GRAY) self.crl_value_table.setItem(0, col_index, temp_item) self.crl_value_table.setColumnWidth(col_index, 20) self.crl_value.append(0) self.crl_value_table.setFixedWidth(20 * new_value + 6) self.crl_lense_spinbox.setMaximum(new_value - 1) elif property_name == "caption": if new_value: self.main_gbox.setTitle(new_value) elif property_name == "style": self.crl_value_table.setVisible(new_value == "table") self.mode_combo.setEnabled(new_value == "table") self.set_according_to_energy_button.setEnabled( new_value == "table") self.crl_lense_spinbox.setVisible(new_value != "table") self.crl_lense_in_button.setVisible(new_value != "table") self.crl_lense_out_button.setVisible(new_value != "table") else: BaseWidget.property_changed(self, property_name, old_value, new_value)
def chip_selected(self): self.file_name = self.chip_files_listwidget.currentItem().text() self.fill_chip_data(self.file_name) # creates the corresponding color table self.ssx_widget_layout.color_table.setRowCount( self.template.num_comp_h_spinbox.value() ) self.ssx_widget_layout.color_table.setColumnCount( self.template.num_comp_v_spinbox.value() ) # fill the table with empty items for row in range(0, self.ssx_widget_layout.color_table.rowCount()): for col in range(0, self.ssx_widget_layout.color_table.columnCount()): self.ssx_widget_layout.color_table.setItem( row, col, QtImport.QTableWidgetItem() ) self.ssx_widget_layout.color_table.item(row, col).setBackground( Colors.GREEN )
def init_com_table(self): try: self.com_device_list = self.beamline_test_hwobj.get_device_list() except BaseException: self.com_device_list = None if self.com_device_list: row = 0 self.com_device_table.setRowCount(len(self.com_device_list)) for device in self.com_device_list: row += 1 for info_index, info in enumerate(device): temp_table_item = QtImport.QTableWidgetItem(info) self.com_device_table.setItem(row - 1, info_index, temp_table_item) # for col in range(self.com_device_table.columnCount()): # self.com_device_table.adjustColumn(col) # self.com_device_table.adjustSize() self.beamline_test_widget.progress_bar.setMaximum( len(self.com_device_list)) else: self.test_com_page.setEnabled(False)
def update_gui(self): tmp_dict = self.multipos_hwobj.get_positions() if tmp_dict: if not self.table_created: # create table items for first and only time self.ui_widgets_manager.calibration_table.setRowCount( len(tmp_dict)) for row in range(len(tmp_dict)): for col in range(3): tmp_item = QtImport.QTableWidgetItem() tmp_item.setFlags(tmp_item.flags() ^ QtImport.Qt.ItemIsEditable) self.ui_widgets_manager.calibration_table.setItem( row, col, tmp_item) self.table_created = True table = self.ui_widgets_manager.calibration_table for i, (position, position_dict) in enumerate(tmp_dict.items()): if position_dict["cal_x"] == 1: y_calib = "Not defined" else: y_calib = str(abs(int(position_dict["cal_x"]))) if position_dict["cal_y"] == 1: z_calib = "Not defined" else: z_calib = str(abs(int(position_dict["cal_y"]))) """ resolution are displayed in nanometer/pixel and saved in metre/pixel """ table.item(i, 0).setText(str(position)) table.item(i, 1).setText(y_calib) table.item(i, 2).setText(z_calib)
def init_gui(self): """ Inits gui :return: None """ self.image_tracking_cbox.setChecked(True) self.inverted_rows_cbox.setChecked( self.current_chip_config["inverted_rows"] ) self.grid_table.setColumnCount(self.current_chip_config["num_comp_h"]) self.grid_table.setRowCount(self.current_chip_config["num_comp_v"]) for col in range(self.current_chip_config["num_comp_h"]): temp_header_item = QtImport.QTableWidgetItem("%d" % (col + 1)) self.grid_table.setHorizontalHeaderItem(col, temp_header_item) self.grid_table.setColumnWidth(col, self["cell_size"]) for row in range(self.current_chip_config["num_comp_v"]): temp_header_item = QtImport.QTableWidgetItem(chr(65 + row)) self.grid_table.setVerticalHeaderItem(row, temp_header_item) self.grid_table.setRowHeight(row, self["cell_size"]) for col in range(self.current_chip_config["num_comp_h"]): for row in range(self.current_chip_config["num_comp_v"]): temp_item = QtImport.QTableWidgetItem() self.grid_table.setItem(row, col, temp_item) table_width = ( self["cell_size"] * (self.current_chip_config["num_comp_h"] + 1) + 4 ) table_height = ( self["cell_size"] * (self.current_chip_config["num_comp_v"] + 1) + 4 ) self.grid_table.setFixedWidth(table_width) self.grid_table.setFixedHeight(table_height) self.comp_table.setColumnCount(self.current_chip_config["num_crystal_h"]) self.comp_table.setRowCount(self.current_chip_config["num_crystal_v"]) for col in range(self.current_chip_config["num_crystal_h"]): temp_header_item = QtImport.QTableWidgetItem("%d" % (col + 1)) self.comp_table.setHorizontalHeaderItem(col, temp_header_item) self.comp_table.setColumnWidth(col, self["cell_size"]) for row in range(self.current_chip_config["num_crystal_v"]): temp_header_item = QtImport.QTableWidgetItem(chr(65 + row)) self.comp_table.setVerticalHeaderItem(row, temp_header_item) self.comp_table.setRowHeight(row, self["cell_size"]) for col in range(self.current_chip_config["num_crystal_h"]): for row in range(self.current_chip_config["num_crystal_v"]): temp_item = QtImport.QTableWidgetItem() self.comp_table.setItem(row, col, temp_item) table_width = ( self["cell_size"] * (self.current_chip_config["num_crystal_h"] + 1) + 7 ) table_height = ( self["cell_size"] * (self.current_chip_config["num_crystal_v"] + 1) + 7 ) self.comp_table.setFixedWidth(table_width + 10) self.comp_table.setFixedHeight(table_height) self.hit_map_plot.setFixedWidth(table_width) self.hit_map_plot.setFixedHeight(200) for score_type in self.score_type_list: self.hit_map_plot.add_curve( score_type, np.array([]), np.array([]), linestyle="None", label=score_type, color="m", marker="s", ) self.hit_map_plot.hide_all_curves() self.hit_map_plot.show_curve(self.score_type)
def __init__(self, *args): BaseWidget.__init__(self, *args) # Hardware objects ---------------------------------------------------- self.ssx_control_hwobj = None # Internal values ----------------------------------------------------- self.current_chip_config = None self.chip_file_dir = "" self.chip_filenames_list = [] self.shortlist_dir = "" # Properties ---------------------------------------------------------- # Properties to initialize hardware objects -------------------------- self.add_property("hwobj_ssx_control", "string", "") # Signals ------------------------------------------------------------ # Slots --------------------------------------------------------------- # Graphic elements ---------------------------------------------------- self.ssx_widget_layout = QtImport.load_ui_file("ssx_control_widget_layout.ui") # Layout -------------------------------------------------------------- _main_layout = QtImport.QVBoxLayout(self) _main_layout.addWidget(self.ssx_widget_layout) # SizePolicies -------------------------------------------------------- # Qt signal/slot connections ------------------------------------------ self.ssx_widget_layout.start_button.clicked.connect(self.start_experiment) self.ssx_widget_layout.chip_file_dir_browse_button.clicked.connect( self.get_chip_file_directory ) self.ssx_widget_layout.shortlist_dir_browse_button.clicked.connect( self.get_shortlist_directory ) self.ssx_widget_layout.save_chip_data_button.clicked.connect( self.save_chip_data ) self.ssx_widget_layout.create_shortlist_button.clicked.connect( self.create_short_list ) self.ssx_widget_layout.enable_all_button.clicked.connect(self.enable_all) self.ssx_widget_layout.disable_all_button.clicked.connect(self.disable_all) self.ssx_widget_layout.color_table.itemSelectionChanged.connect( self.change_cell_color ) self.ssx_widget_layout.quarter_density_checkbox.stateChanged.connect( self.quarter_density_enabled ) self.ssx_widget_layout.quarter_density_checkbox.setEnabled(False) self.ssx_widget_layout.meandering_checkbox.stateChanged.connect( self.meandering_enabled ) # Other --------------------------------------------------------------- self.ssx_widget_layout.crystal_h_pitch_spinbox.valueChanged.connect( self.crystal_h_pitch_changed ) self.ssx_widget_layout.crystal_v_pitch_spinbox.valueChanged.connect( self.crystal_v_pitch_changed ) self.ssx_widget_layout.comp_h_pitch_spinbox.valueChanged.connect( self.comp_h_pitch_changed ) self.ssx_widget_layout.comp_v_pitch_spinbox.valueChanged.connect( self.comp_v_pitch_changed ) self.ssx_widget_layout.num_crystal_h_spinbox.valueChanged.connect( self.num_crystal_h_changed ) self.ssx_widget_layout.num_crystal_v_spinbox.valueChanged.connect( self.num_crystal_v_changed ) self.ssx_widget_layout.num_comp_h_spinbox.valueChanged.connect( self.num_comp_h_changed ) self.ssx_widget_layout.num_comp_v_spinbox.valueChanged.connect( self.num_copm_v_changed ) self.ssx_widget_layout.meandering_checkbox.setEnabled(False) # connect exposures per feature self.ssx_widget_layout.exp_per_feature_spinbox.valueChanged[unicode].connect( self.set_exposures_per_feature ) # show names and one column at exposures per feature self.ssx_widget_layout.dg_channels_table.setRowCount(4) self.ssx_widget_layout.dg_channels_table.setColumnCount(1) # headers names self.ssx_widget_layout.dg_channels_table.setVerticalHeaderLabels( QtImport.QString("Detector;Excitation;Aux1;Aux2").split(";") ) # set first column of checkboxes dg_channels_list = [] for row in range(0, 4): checkbox_item = QtImport.QTableWidgetItem() checkbox_item.setFlags( QtImport.Qt.ItemIsUserCheckable | QtImport.Qt.ItemIsEnabled ) checkbox_item.setCheckState(QtImport.Qt.Unchecked) dg_channels_list.append(checkbox_item) self.ssx_widget_layout.dg_channels_table.setItem(row, 0, checkbox_item) # set a color table with 3 by 3 cells self.ssx_widget_layout.color_table.setRowCount(3) self.ssx_widget_layout.color_table.setColumnCount(3) # set min size of cells self.ssx_widget_layout.color_table.horizontalHeader().setDefaultSectionSize(25) self.ssx_widget_layout.color_table.verticalHeader().setDefaultSectionSize(25) # table is non editable self.ssx_widget_layout.color_table.setEditTriggers( QtImport.QAbstractItemView.NoEditTriggers ) # fill the table with empty items for row in range(0, 3): for column in range(0, 3): self.ssx_widget_layout.color_table.setItem( row, column, QtImport.QTableWidgetItem() ) self.ssx_widget_layout.color_table.item(row, column).setBackground( Colors.GREEN ) # connect scan rate self.ssx_widget_layout.scan_rate_ledit.textEdited.connect( self.scan_rate_text_changed )
def __init__(self, *args): """ Main init :param args: """ BaseWidget.__init__(self, *args) # Internal values ----------------------------------------------------- # Properties ---------------------------------------------------------- self.add_property("formatString", "formatString", "#.#") # Signals ------------------------------------------------------------ # Slots --------------------------------------------------------------- # Graphic elements ---------------------------------------------------- self.status_gbox = QtImport.QGroupBox("Status", self) self.mounted_sample_ledit = QtImport.QLineEdit("", self) self.sample_detected_ledit = QtImport.QLineEdit("", self) self.focus_mode_ledit = QtImport.QLineEdit("", self) self.puck_switches_gbox = QtImport.QGroupBox("Puck switches", self) self.puck_switches_table = QtImport.QTableWidget( self.puck_switches_gbox) self.central_puck_ledit = QtImport.QLineEdit("No center puck", self.puck_switches_gbox) self.control_gbox = QtImport.QGroupBox("Control", self) self.open_lid_button = QtImport.QPushButton("Open lid", self.control_gbox) self.close_lid_button = QtImport.QPushButton("Close lid", self.control_gbox) self.base_to_center_button = QtImport.QPushButton( "Base to center", self.control_gbox) self.center_to_base_button = QtImport.QPushButton( "Center to base", self.control_gbox) self.dry_gripper_button = QtImport.QPushButton("Dry gripper", self.control_gbox) self.status_list_gbox = QtImport.QGroupBox("Status list", self) self.status_table = QtImport.QTableWidget(self) # Layout -------------------------------------------------------------- _status_gbox_gridlayout = QtImport.QGridLayout(self.status_gbox) _status_gbox_gridlayout.addWidget( QtImport.QLabel("Mounted sample", self.status_list_gbox), 0, 0) _status_gbox_gridlayout.addWidget( QtImport.QLabel("Sample detected", self.status_list_gbox), 1, 0) _status_gbox_gridlayout.addWidget( QtImport.QLabel("Focus mode", self.status_list_gbox), 2, 0) _status_gbox_gridlayout.addWidget(self.mounted_sample_ledit, 0, 1) _status_gbox_gridlayout.addWidget(self.sample_detected_ledit, 1, 1) _status_gbox_gridlayout.addWidget(self.focus_mode_ledit, 2, 1) _status_gbox_gridlayout.setSpacing(2) _status_gbox_gridlayout.setContentsMargins(0, 0, 0, 0) _status_gbox_gridlayout.setColumnStretch(2, 10) _puck_switches_gbox_vlayout = QtImport.QHBoxLayout( self.puck_switches_gbox) _puck_switches_gbox_vlayout.addWidget(self.puck_switches_table) _puck_switches_gbox_vlayout.addWidget(self.central_puck_ledit) _puck_switches_gbox_vlayout.setSpacing(2) _puck_switches_gbox_vlayout.setContentsMargins(0, 0, 0, 0) _status_vbox_layout = QtImport.QVBoxLayout(self.status_list_gbox) _status_vbox_layout.addWidget(self.status_table) _status_vbox_layout.setSpacing(2) _status_vbox_layout.setContentsMargins(0, 0, 0, 0) _control_gbox_hlayout = QtImport.QHBoxLayout(self.control_gbox) _control_gbox_hlayout.addWidget(self.open_lid_button) _control_gbox_hlayout.addWidget(self.close_lid_button) _control_gbox_hlayout.addWidget(self.base_to_center_button) _control_gbox_hlayout.addWidget(self.center_to_base_button) _control_gbox_hlayout.addWidget(self.dry_gripper_button) _control_gbox_hlayout.setSpacing(2) _control_gbox_hlayout.setContentsMargins(0, 0, 0, 0) _main_vlayout = QtImport.QVBoxLayout(self) _main_vlayout.addWidget(self.status_gbox) _main_vlayout.addWidget(self.puck_switches_gbox) _main_vlayout.addWidget(self.control_gbox) _main_vlayout.addWidget(self.status_list_gbox) _main_vlayout.setSpacing(2) _main_vlayout.setContentsMargins(2, 2, 2, 2) # SizePolicies -------------------------------------------------------- # Qt signal/slot connections ------------------------------------------ self.open_lid_button.clicked.connect(open_lid_clicked) self.close_lid_button.clicked.connect(close_lid_clicked) self.base_to_center_button.clicked.connect(base_to_center_clicked) self.center_to_base_button.clicked.connect(center_to_base_clicked) self.dry_gripper_button.clicked.connect(dry_gripper_clicked) # Other --------------------------------------------------------------- self.mounted_sample_ledit.setFixedWidth(80) self.sample_detected_ledit.setFixedWidth(80) self.focus_mode_ledit.setFixedWidth(80) self.puck_switches_table.setRowCount(1) self.puck_switches_table.setColumnCount(PUCK_COUNT) self.puck_switches_table.verticalHeader().hide() self.puck_switches_table.horizontalHeader().hide() self.puck_switches_table.setRowHeight(0, 28) self.puck_switches_table.setFixedHeight(28) self.puck_switches_table.setShowGrid(True) self.puck_switches_table.setFixedWidth(33 * PUCK_COUNT + 4) for col_index in range(PUCK_COUNT): temp_item = QtImport.QTableWidgetItem(str(col_index + 1)) temp_item.setFlags(QtImport.Qt.ItemIsEnabled) temp_item.setBackground(Colors.WHITE) self.puck_switches_table.setItem(0, col_index, temp_item) self.puck_switches_table.setColumnWidth(col_index, 33) self.status_table.setColumnCount(3) self.status_table.setHorizontalHeaderLabels( ["Property", "Description", "Value"]) self.puck_switches_gbox.setSizePolicy(QtImport.QSizePolicy.Preferred, QtImport.QSizePolicy.Fixed) self.init_tables() self.connect(HWR.beamline.sample_changer, "statusListChanged", self.status_list_changed) self.connect(HWR.beamline.sample_changer, "infoDictChanged", self.info_dict_changed) HWR.beamline.sample_changer.re_emit_values()
def __init__(self, parent=None, name="dc_group_widget"): QtImport.QWidget.__init__(self, parent) if name is not None: self.setObjectName(name) # Properties ---------------------------------------------------------- # Signals ------------------------------------------------------------ # Slots --------------------------------------------------------------- # Hardware objects ---------------------------------------------------- # Internal variables -------------------------------------------------- self._data_collection = None self.add_dc_cb = None self._tree_view_item = None _subwedge_widget = QtImport.QGroupBox("Summary", self) self.polar_scater_widget = PolarScaterWidget() self.subwedge_table = QtImport.QTableWidget(_subwedge_widget) self.position_widget = QtImport.load_ui_file( "snapshot_widget_layout.ui") # Layout -------------------------------------------------------------- _subwedge_widget_vlayout = QtImport.QVBoxLayout(_subwedge_widget) _subwedge_widget_vlayout.addWidget(self.polar_scater_widget) _subwedge_widget_vlayout.addWidget(self.subwedge_table) _subwedge_widget_vlayout.setContentsMargins(0, 4, 0, 0) _subwedge_widget_vlayout.setSpacing(6) _subwedge_widget_vlayout.addStretch(0) _main_hlayout = QtImport.QHBoxLayout(self) _main_hlayout.addWidget(_subwedge_widget) _main_hlayout.setContentsMargins(0, 0, 0, 0) _main_hlayout.setSpacing(2) _main_hlayout.addStretch(0) # SizePolicies -------------------------------------------------------- # Qt signal/slot connections ------------------------------------------ # Other --------------------------------------------------------------- # self.polar_scater_widget.setFixedSize(600, 600) font = self.subwedge_table.font() font.setPointSize(8) self.subwedge_table.setFont(font) self.subwedge_table.setEditTriggers( QtImport.QAbstractItemView.NoEditTriggers) self.subwedge_table.setColumnCount(7) self.subwedge_table.horizontalHeader().setStretchLastSection(False) horizontal_headers = [ "Osc start", "Osc range", "Images", "Exposure time", "Energy", "Transmission", "Resolution", ] for index, header in enumerate(horizontal_headers): self.subwedge_table.setHorizontalHeaderItem( index, QtImport.QTableWidgetItem(header))
def __init__(self, parent=None, show_aligned_results=False): QtImport.QWidget.__init__(self, parent) self.setObjectName("hit_map_widget") # Properties ---------------------------------------------------------- # Signals ------------------------------------------------------------- # Slots --------------------------------------------------------------- # Internal values ----------------------------------------------------- self.__plot_type = "1D" self.__result_types = [] self.__results_raw = None self.__results_aligned = None self.__first_result = True self.__associated_grid = None self.__associated_data_collection = None self.__selected_col = 0 self.__selected_row = 0 self.__score_key = None self.__max_value = 0 self.__filter_min_value = 0 self.__best_pos_list = None self.__hit_map_max_size = [] self.__hitmap_clicked = False self.__enable_continues_image_display = False #self.__tooltip_text = None self.selected_image_serial = None # Graphic elements ---------------------------------------------------- self._hit_map_gbox = QtImport.QGroupBox("Hit map", self) self._hit_map_plot = PlotWidget(self._hit_map_gbox) self._hit_map_popup_menu = QtImport.QMenu(self._hit_map_gbox) hit_map_info_widget = QtImport.QWidget(self._hit_map_gbox) score_type_label = QtImport.QLabel("Result: ", hit_map_info_widget) self._score_type_cbox = QtImport.QComboBox(hit_map_info_widget) self._autoscale_button = QtImport.QPushButton("Auto scale", hit_map_info_widget) image_display_cbox = QtImport.QCheckBox("Display image in ADxV", hit_map_info_widget) self._image_info_label = QtImport.QLabel("Image: #, value #", hit_map_info_widget) self._hit_map_tools_widget = QtImport.QWidget(self._hit_map_gbox) _threshold_label = QtImport.QLabel("Threshold: ", self._hit_map_tools_widget) self._threshold_slider = QtImport.QSlider(QtImport.Qt.Horizontal, self._hit_map_tools_widget) self._relaunch_processing_button = QtImport.QPushButton( "Relaunch processing", self._hit_map_tools_widget) self._create_points_button = QtImport.QPushButton( "Create centring points", self._hit_map_tools_widget) self._summary_gbox = QtImport.QGroupBox("Summary", self) self._summary_textbrowser = QtImport.QTextBrowser(self._summary_gbox) self._best_pos_gbox = QtImport.QGroupBox("Best positions", self) self._best_pos_table = QtImport.QTableWidget(self._best_pos_gbox) self._best_pos_popup_menu = QtImport.QMenu(self._hit_map_gbox) self._best_pos_gbox.setHidden(True) # Layout -------------------------------------------------------------- _hit_map_info_hlayout = QtImport.QHBoxLayout(hit_map_info_widget) _hit_map_info_hlayout.addWidget(score_type_label) _hit_map_info_hlayout.addWidget(self._score_type_cbox) _hit_map_info_hlayout.addWidget(self._autoscale_button) _hit_map_info_hlayout.addWidget(image_display_cbox) _hit_map_info_hlayout.addStretch(0) _hit_map_info_hlayout.addWidget(self._image_info_label) _hit_map_info_hlayout.setSpacing(2) _hit_map_info_hlayout.setContentsMargins(0, 0, 0, 0) _hit_map_tools_hlayout = QtImport.QHBoxLayout( self._hit_map_tools_widget) _hit_map_tools_hlayout.addWidget(_threshold_label) _hit_map_tools_hlayout.addWidget(self._threshold_slider) _hit_map_tools_hlayout.addStretch(0) _hit_map_tools_hlayout.addWidget(self._relaunch_processing_button) _hit_map_tools_hlayout.addWidget(self._create_points_button) _hit_map_tools_hlayout.setSpacing(2) _hit_map_tools_hlayout.setContentsMargins(0, 0, 0, 0) _hit_map_gbox_vlayout = QtImport.QVBoxLayout(self._hit_map_gbox) _hit_map_gbox_vlayout.addWidget(self._hit_map_plot) _hit_map_gbox_vlayout.addWidget(hit_map_info_widget) _hit_map_gbox_vlayout.addWidget(self._hit_map_tools_widget) _hit_map_gbox_vlayout.setSpacing(2) _hit_map_gbox_vlayout.setContentsMargins(0, 0, 0, 0) _summary_gbox_vlayout = QtImport.QVBoxLayout(self._summary_gbox) _summary_gbox_vlayout.addWidget(self._summary_textbrowser) _summary_gbox_vlayout.setSpacing(2) _summary_gbox_vlayout.setContentsMargins(0, 0, 0, 0) _best_postition_gbox_vlayout = QtImport.QVBoxLayout( self._best_pos_gbox) _best_postition_gbox_vlayout.addWidget(self._best_pos_table) _best_postition_gbox_vlayout.setSpacing(2) _best_postition_gbox_vlayout.setContentsMargins(0, 0, 0, 0) _main_hlayout = QtImport.QVBoxLayout(self) _main_hlayout.addWidget(self._hit_map_gbox) _main_hlayout.addWidget(self._summary_gbox) _main_hlayout.addWidget(self._best_pos_gbox) _main_hlayout.setSpacing(2) _main_hlayout.setContentsMargins(2, 2, 2, 2) # SizePolicies -------------------------------------------------------- #self._image_info_label.setAlignment(QtImport.Qt.AlignLeft) #self._image_info_label.setSizePolicy( # QtImport.QSizePolicy.Expanding, QtImport.QSizePolicy.Fixed #) # Qt signals and slots ------------------------------------------------ image_display_cbox.stateChanged.connect( self.enable_image_display_state_changed) self._score_type_cbox.activated.connect(self.score_type_changed) self._threshold_slider.valueChanged.connect( self.filter_min_slider_changed) self._relaunch_processing_button.clicked.connect( self.relaunch_processing_clicked) self._create_points_button.clicked.connect(self.create_points_clicked) self._hit_map_plot.mouseMovedSignal.connect(self.mouse_moved) self._hit_map_plot.mouseClickedSignal.connect(self.mouse_clicked) self._hit_map_plot.mouseDoubleClickedSignal.connect( self.move_to_position_clicked) self._hit_map_plot.mouseLeftSignal.connect(self.mouse_left_plot) self._autoscale_button.clicked.connect(self.autoscale_pressed) # Other --------------------------------------------------------------- #self.__tooltip_text = ( # "Double click to move to the position. " + "Right click to open menu." #) #self._hit_map_plot.setToolTip(self.__tooltip_text) self._hit_map_popup_menu.addSeparator() self._hit_map_popup_menu.addAction("Move to position", self.move_to_position_clicked) self._hit_map_popup_menu.addAction("Create centring point", self.create_centring_point_clicked) self._hit_map_popup_menu.addAction("Create helical line", self.create_helical_line_clicked) self._hit_map_popup_menu.addAction( "Rotate 90 degrees and create helical line", self.rotate_and_create_helical_line_clicked, ) self._hit_map_popup_menu.addSeparator() self._hit_map_popup_menu.addAction("Open image in ADXV", self.display_image_clicked) self._hit_map_popup_menu.addSeparator() #self._hit_map_plot.contextMenuEvent = self.open_hit_map_popup_menu if HWR.beamline.online_processing is not None: self.__result_types = HWR.beamline.online_processing.get_result_types( ) for result in self.__result_types: self._score_type_cbox.addItem(result["descr"]) self._score_type_cbox.setMaximumWidth(200) self.__score_key = "spots_resolution" self._threshold_slider.setRange(0, 100) self._threshold_slider.setTickInterval(5) self._threshold_slider.setFixedWidth(200) self._threshold_slider.setTracking(False) #font = self._best_pos_table.font() #font.setPointSize(8) #self._best_pos_table.setFont(font) self._best_pos_table.setEditTriggers( QtImport.QAbstractItemView.NoEditTriggers) self._best_pos_table.setColumnCount(9) self._best_pos_table.setAlternatingRowColors(True) self._best_pos_table.setWordWrap(False) self._best_pos_table.horizontalHeader().setSortIndicatorShown(True) self._best_pos_table.setHorizontalHeaderItem( 0, QtImport.QTableWidgetItem("No.")) for index, result_type in enumerate(self.__result_types): self._best_pos_table.setHorizontalHeaderItem( index + 1, QtImport.QTableWidgetItem(result_type["descr"])) for index, header_text in enumerate( ("Path", "Col", "Row", "Motor positions")): self._best_pos_table.setHorizontalHeaderItem( 5 + index, QtImport.QTableWidgetItem(header_text)) self._best_pos_popup_menu.addAction("Move to position", self.move_to_best_position_clicked) self._best_pos_table.contextMenuEvent = self.open_best_pos_popup_menu screen_shape = QtImport.QDesktopWidget().screenGeometry() self.__hit_map_max_size = (screen_shape.width() / 2, screen_shape.height() / 2)