def add_new_table(self, rel, name): import itertools table = QTableWidget() table.setRowCount(0) table.setColumnCount(0) data = itertools.chain([rel.fields], rel.content) for row_data in data: row = table.rowCount() table.setColumnCount(len(row_data)) for col, text in enumerate(row_data): item = QTableWidgetItem() item.setText(text) if row == 0: table.setHorizontalHeaderItem(col, item) else: table.setItem(row - 1, col, item) table.insertRow(row) table.removeRow(table.rowCount() - 1) self.stacked.addWidget(table) self.stacked.setCurrentIndex(self.stacked.count() - 1) lateral = Pireal.get_service("lateral") lateral.add_item_list([name])
class AccountManagerDialog(QDialog): def __init__(self, emails, types, parent): self.emails, self.types = emails, types QDialog.__init__(self, parent) self.resize(560, 350) self.gridLayout = QGridLayout(self) self.tableWidget = QTableWidget(0, 2, self) self.tableWidget.setAlternatingRowColors(True) self.tableWidget.setSelectionBehavior(1) # Rows self.tableWidget.setSelectionMode(1) # Single self.tableWidget.horizontalHeader().setResizeMode(0, 1) # 1 = Stretch self.tableWidget.setHorizontalHeaderLabels(['Email', 'Type']) self.addBtn = QPushButton('+', self) self.removeBtn = QPushButton('-', self) self.closeBtn = QPushButton('Close', self) self.spacer = QWidget(self) self.spacer.setSizePolicy(1 | 2 | 4, 1 | 4) self.gridLayout.addWidget(self.tableWidget, 0, 0, 1, 4) self.gridLayout.addWidget(self.addBtn, 1, 0, 1, 1) self.gridLayout.addWidget(self.removeBtn, 1, 1, 1, 1) self.gridLayout.addWidget(self.spacer, 1, 2, 1, 1) self.gridLayout.addWidget(self.closeBtn, 1, 3, 1, 1) self.addBtn.clicked.connect(self.addAccount) self.removeBtn.clicked.connect(self.removeAccount) self.closeBtn.clicked.connect(self.accept) for i in range(len(self.emails)): self.tableWidget.insertRow(i) self.tableWidget.setItem(i, 0, QTableWidgetItem(emails[i])) self.tableWidget.setItem(i, 1, QTableWidgetItem(types[i])) def addAccount(self): dialog = AddAccountDialog(self) if dialog.exec_() != QDialog.Accepted: return email = unicode(dialog.emailEdit.text()) passwd = unicode(dialog.passwordEdit.text()) ac_type = unicode(dialog.typeCombo.currentText()) self.tableWidget.insertRow(0) self.tableWidget.setItem(0, 0, QTableWidgetItem(email)) self.tableWidget.setItem(0, 1, QTableWidgetItem(ac_type)) self.emails.insert(0, email) self.types.insert(0, ac_type) kr = Keyring() kr.setPassword(email, passwd) def removeAccount(self): row = self.tableWidget.selectionModel().selectedRows()[0].row() email = self.tableWidget.item(row, 0).text() kr = Keyring() kr.deletePassword(email) self.tableWidget.removeRow(row) self.emails.pop(row) self.types.pop(row)
def load_relation(self, filenames=[]): """ Load relation from file """ import csv from PyQt4.QtGui import QTableWidgetItem, QTableWidget from src.core import relation if not filenames: native_dialog = QFileDialog.DontUseNativeDialog directory = os.path.expanduser("~") ffilter = settings.RFILES.split(';;')[-1] filenames = QFileDialog.getOpenFileNames(self, self.tr("Abrir Archivo"), directory, ffilter, native_dialog) if not filenames: return lateral = Pireal.get_service("lateral") for filename in filenames: rel = relation.Relation(filename) relation_name = os.path.splitext(os.path.basename(filename))[0] self.table_widget.relations[relation_name] = rel table = QTableWidget() with open(filename, newline='') as f: table.setRowCount(0) table.setColumnCount(0) csv_reader = csv.reader(f) for row_data in csv_reader: row = table.rowCount() table.setColumnCount(len(row_data)) for column, data in enumerate(row_data): item = QTableWidgetItem() item.setText(data) if row == 0: table.setHorizontalHeaderItem(column, item) else: table.setItem(row - 1, column, item) table.insertRow(row) table.removeRow(table.rowCount() - 1) self.table_widget.stacked.addWidget(table) #FIXME: names names = [os.path.splitext(os.path.basename(i))[0] for i in filenames] lateral.add_item_list(names) lateral.show()
class OWdabam_height_profile(OWWidget): name = "DABAM Height Profile" id = "dabam_height_profile" description = "Calculation of mirror surface error profile" icon = "icons/dabam.png" author = "Luca Rebuffi" maintainer_email = "[email protected]; [email protected]" priority = 6 category = "" keywords = ["dabam_height_profile"] outputs = [{"name": "PreProcessor_Data", "type": ShadowPreProcessorData, "doc": "PreProcessor Data", "id": "PreProcessor_Data"}] want_main_area = 1 want_control_area = 1 MAX_WIDTH = 1320 MAX_HEIGHT = 700 IMAGE_WIDTH = 860 IMAGE_HEIGHT = 645 CONTROL_AREA_WIDTH = 405 TABS_AREA_HEIGHT = 618 xx = None yy = None zz = None entry_number = Setting(1) shape=Setting(0) slope_error_from = Setting(0.0) slope_error_to = Setting(1.5) dimension_y_from = Setting(0.0) dimension_y_to = Setting(200.0) use_undetrended = Setting(0) step_x = Setting(1.0) dimension_x = Setting(10.0) center_y = Setting(1) modify_y = Setting(0) new_length = Setting(200.0) filler_value = Setting(0.0) scale_factor_y = Setting(1.0) renormalize_y = Setting(1) error_type_y = Setting(0) rms_y = Setting(0.9) dabam_profile_index = Setting(1) heigth_profile_file_name = Setting('mirror.dat') tab=[] def __init__(self): super().__init__() self.runaction = widget.OWAction("Calculate Height Profile", self) self.runaction.triggered.connect(self.calculate_heigth_profile_ni) self.addAction(self.runaction) self.runaction = widget.OWAction("Generate Height Profile File", self) self.runaction.triggered.connect(self.generate_heigth_profile_file_ni) self.addAction(self.runaction) geom = QApplication.desktop().availableGeometry() self.setGeometry(QRect(round(geom.width() * 0.05), round(geom.height() * 0.05), round(min(geom.width() * 0.98, self.MAX_WIDTH)), round(min(geom.height() * 0.95, self.MAX_HEIGHT)))) self.setMaximumHeight(self.geometry().height()) self.setMaximumWidth(self.geometry().width()) # DABAM INITIALIZATION self.server = dabam.dabam() self.server.set_input_silent(True) gui.separator(self.controlArea) button_box = oasysgui.widgetBox(self.controlArea, "", addSpace=False, orientation="horizontal") button = gui.button(button_box, self, "Calculate Height\nProfile", callback=self.calculate_heigth_profile) button.setFixedHeight(45) button = gui.button(button_box, self, "Generate Height\nProfile File", callback=self.generate_heigth_profile_file) font = QFont(button.font()) font.setBold(True) button.setFont(font) palette = QPalette(button.palette()) # make a copy of the palette palette.setColor(QPalette.ButtonText, QColor('Dark Blue')) button.setPalette(palette) # assign new palette button.setFixedHeight(45) button.setFixedWidth(150) button = gui.button(button_box, self, "Reset Fields", callback=self.call_reset_settings) font = QFont(button.font()) font.setItalic(True) button.setFont(font) palette = QPalette(button.palette()) # make a copy of the palette palette.setColor(QPalette.ButtonText, QColor('Dark Red')) button.setPalette(palette) # assign new palette button.setFixedHeight(45) gui.separator(self.controlArea) tabs_setting = gui.tabWidget(self.controlArea) tabs_setting.setFixedHeight(self.TABS_AREA_HEIGHT) tabs_setting.setFixedWidth(self.CONTROL_AREA_WIDTH-5) tab_input = oasysgui.createTabPage(tabs_setting, "DABAM Search Setting") tab_gener = oasysgui.createTabPage(tabs_setting, "DABAM Generation Setting") tab_out = oasysgui.createTabPage(tabs_setting, "Output") manual_box = oasysgui.widgetBox(tab_input, "Manual Entry", addSpace=True, orientation="vertical") oasysgui.lineEdit(manual_box, self, "entry_number", "Entry Number", labelWidth=300, valueType=int, orientation="horizontal") gui.separator(manual_box) button = gui.button(manual_box, self, "Retrieve Profile", callback=self.retrieve_profile) button.setFixedHeight(35) button.setFixedWidth(self.CONTROL_AREA_WIDTH-35) input_box = oasysgui.widgetBox(tab_input, "Search Parameters", addSpace=True, orientation="vertical") gui.comboBox(input_box, self, "shape", label="Mirror Shape", labelWidth=300, items=["All", "Plane", "Cylindrical", "Elliptical", "Toroidal", "Spherical"], sendSelectedValue=False, orientation="horizontal") gui.separator(input_box) input_box_1 = oasysgui.widgetBox(input_box, "", addSpace=True, orientation="horizontal") oasysgui.lineEdit(input_box_1, self, "slope_error_from", "Slope Error From (" + u"\u03BC" + "rad)", labelWidth=150, valueType=float, orientation="horizontal") oasysgui.lineEdit(input_box_1, self, "slope_error_to", "To (" + u"\u03BC" + "rad)", labelWidth=60, valueType=float, orientation="horizontal") input_box_2 = oasysgui.widgetBox(input_box, "", addSpace=True, orientation="horizontal") self.le_dimension_y_from = oasysgui.lineEdit(input_box_2, self, "dimension_y_from", "Mirror Length From", labelWidth=150, valueType=float, orientation="horizontal") self.le_dimension_y_to = oasysgui.lineEdit(input_box_2, self, "dimension_y_to", "To", labelWidth=60, valueType=float, orientation="horizontal") table_box = oasysgui.widgetBox(tab_input, "Search Results", addSpace=True, orientation="vertical", height=290) self.overlay_search = Overlay(table_box, self.search_profiles) self.overlay_search.hide() button = gui.button(input_box, self, "Search", callback=self.overlay_search.show) button.setFixedHeight(35) button.setFixedWidth(self.CONTROL_AREA_WIDTH-35) gui.comboBox(table_box, self, "use_undetrended", label="Use Undetrended Profile", labelWidth=300, items=["No", "Yes"], callback=self.table_item_clicked, sendSelectedValue=False, orientation="horizontal") gui.separator(table_box) self.scrollarea = QScrollArea() self.scrollarea.setMinimumWidth(self.CONTROL_AREA_WIDTH-35) table_box.layout().addWidget(self.scrollarea, alignment=Qt.AlignHCenter) self.table = QTableWidget(1, 5) self.table.setAlternatingRowColors(True) self.table.horizontalHeader().setResizeMode(QHeaderView.Fixed) self.table.verticalHeader().setVisible(False) self.table.setColumnWidth(0, 40) self.table.setColumnWidth(1, 70) self.table.setColumnWidth(2, 70) self.table.setColumnWidth(3, 85) self.table.setColumnWidth(4, 80) self.table.resizeRowsToContents() self.table.setSelectionBehavior(QAbstractItemView.SelectRows) self.table.itemClicked.connect(self.table_item_clicked) self.scrollarea.setWidget(self.table) self.scrollarea.setWidgetResizable(1) output_profile_box = oasysgui.widgetBox(tab_gener, "Surface Generation Parameters", addSpace=True, orientation="vertical", height=270) self.le_dimension_x = oasysgui.lineEdit(output_profile_box, self, "dimension_x", "Width", labelWidth=300, valueType=float, orientation="horizontal") self.le_step_x = oasysgui.lineEdit(output_profile_box, self, "step_x", "Step Width", labelWidth=300, valueType=float, orientation="horizontal") gui.comboBox(output_profile_box, self, "center_y", label="Center Profile in the middle of O.E.", labelWidth=300, items=["No", "Yes"], sendSelectedValue=False, orientation="horizontal") gui.comboBox(output_profile_box, self, "modify_y", label="Modify Length?", labelWidth=240, items=["No", "Rescale to new length", "Fit to new length (fill or cut)"], callback=self.set_ModifyY, sendSelectedValue=False, orientation="horizontal") self.modify_box_1 = oasysgui.widgetBox(output_profile_box, "", addSpace=False, orientation="vertical", height=50) self.modify_box_2 = oasysgui.widgetBox(output_profile_box, "", addSpace=False, orientation="vertical", height=50) oasysgui.lineEdit(self.modify_box_2, self, "scale_factor_y", "Scale Factor", labelWidth=300, valueType=float, orientation="horizontal") self.modify_box_3 = oasysgui.widgetBox(output_profile_box, "", addSpace=False, orientation="vertical", height=50) self.le_new_length = oasysgui.lineEdit(self.modify_box_3, self, "new_length", "New Length", labelWidth=300, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.modify_box_3, self, "filler_value", "Filler Value (if new length > profile length) [nm]", labelWidth=300, valueType=float, orientation="horizontal") self.set_ModifyY() gui.comboBox(output_profile_box, self, "renormalize_y", label="Renormalize Length Profile to different RMS", labelWidth=300, items=["No", "Yes"], callback=self.set_RenormalizeY, sendSelectedValue=False, orientation="horizontal") self.output_profile_box_1 = oasysgui.widgetBox(output_profile_box, "", addSpace=True, orientation="vertical") gui.comboBox(self.output_profile_box_1, self, "error_type_y", label="Normalization to", labelWidth=270, items=["Figure Error (nm)", "Slope Error (" + u"\u03BC" + "rad)"], sendSelectedValue=False, orientation="horizontal") oasysgui.lineEdit(self.output_profile_box_1, self, "rms_y", "Rms Value", labelWidth=300, valueType=float, orientation="horizontal") self.set_RenormalizeY() output_box = oasysgui.widgetBox(tab_gener, "Outputs", addSpace=True, orientation="vertical") select_file_box = oasysgui.widgetBox(output_box, "", addSpace=True, orientation="horizontal") self.le_heigth_profile_file_name = oasysgui.lineEdit(select_file_box, self, "heigth_profile_file_name", "Output File Name", labelWidth=120, valueType=str, orientation="horizontal") gui.button(select_file_box, self, "...", callback=self.selectFile) self.shadow_output = QTextEdit() self.shadow_output.setReadOnly(True) out_box = oasysgui.widgetBox(tab_out, "System Output", addSpace=True, orientation="horizontal", height=500) out_box.layout().addWidget(self.shadow_output) gui.rubber(self.controlArea) self.initializeTabs() gui.rubber(self.mainArea) self.overlay_search.raise_() def resizeEvent(self, event): self.overlay_search.resize(self.CONTROL_AREA_WIDTH - 15, 290) event.accept() def after_change_workspace_units(self): self.si_to_user_units = 1e2 / self.workspace_units_to_cm self.horHeaders = ["Entry", "Shape", "Length\n[" + self.workspace_units_label + "]", "Heights St.Dev.\n[nm]", "Slopes St.Dev.\n[" + u"\u03BC" + "rad]"] self.table.setHorizontalHeaderLabels(self.horHeaders) self.plot_canvas[0].setGraphXLabel("Y [" + self.workspace_units_label + "]") self.plot_canvas[1].setGraphXLabel("Y [" + self.workspace_units_label + "]") self.axis.set_xlabel("X [" + self.workspace_units_label + "]") self.axis.set_ylabel("Y [" + self.workspace_units_label + "]") label = self.le_dimension_y_from.parent().layout().itemAt(0).widget() label.setText(label.text() + " [" + self.workspace_units_label + "]") label = self.le_dimension_y_to.parent().layout().itemAt(0).widget() label.setText(label.text() + " [" + self.workspace_units_label + "]") label = self.le_dimension_x.parent().layout().itemAt(0).widget() label.setText(label.text() + " [" + self.workspace_units_label + "]") label = self.le_step_x.parent().layout().itemAt(0).widget() label.setText(label.text() + " [" + self.workspace_units_label + "]") label = self.le_new_length.parent().layout().itemAt(0).widget() label.setText(label.text() + " [" + self.workspace_units_label + "]") def initializeTabs(self): self.tabs = gui.tabWidget(self.mainArea) self.tab = [gui.createTabPage(self.tabs, "Info"), gui.createTabPage(self.tabs, "Heights Profile"), gui.createTabPage(self.tabs, "Slopes Profile"), gui.createTabPage(self.tabs, "PSD Heights"), gui.createTabPage(self.tabs, "CSD Heights"), gui.createTabPage(self.tabs, "ACF"), gui.createTabPage(self.tabs, "Generated 2D Profile"), ] for tab in self.tab: tab.setFixedHeight(self.IMAGE_HEIGHT) tab.setFixedWidth(self.IMAGE_WIDTH) self.plot_canvas = [None, None, None, None, None, None] self.plot_canvas[0] = PlotWindow(roi=False, control=False, position=True, plugins=False) self.plot_canvas[0].setDefaultPlotLines(True) self.plot_canvas[0].setActiveCurveColor(color='darkblue') self.plot_canvas[0].setGraphYLabel("Z [nm]") self.plot_canvas[0].setGraphTitle("Heights Profile") self.plot_canvas[0].setDrawModeEnabled(True, 'rectangle') self.plot_canvas[0].setZoomModeEnabled(True) self.plot_canvas[1] = PlotWindow(roi=False, control=False, position=True, plugins=False) self.plot_canvas[1].setDefaultPlotLines(True) self.plot_canvas[1].setActiveCurveColor(color='darkblue') self.plot_canvas[1].setGraphYLabel("Zp [$\mu$rad]") self.plot_canvas[1].setGraphTitle("Slopes Profile") self.plot_canvas[1].setDrawModeEnabled(True, 'rectangle') self.plot_canvas[1].setZoomModeEnabled(True) self.plot_canvas[2] = PlotWindow(roi=False, control=False, position=True, plugins=False) self.plot_canvas[2].setDefaultPlotLines(True) self.plot_canvas[2].setActiveCurveColor(color='darkblue') self.plot_canvas[2].setGraphXLabel("f [m^-1]") self.plot_canvas[2].setGraphYLabel("PSD [m^3]") self.plot_canvas[2].setGraphTitle("Power Spectral Density of Heights Profile") self.plot_canvas[2].setDrawModeEnabled(True, 'rectangle') self.plot_canvas[2].setZoomModeEnabled(True) self.plot_canvas[2].setXAxisLogarithmic(True) self.plot_canvas[2].setYAxisLogarithmic(True) self.plot_canvas[3] = PlotWindow(roi=False, control=False, position=True, plugins=False) self.plot_canvas[3].setDefaultPlotLines(True) self.plot_canvas[3].setActiveCurveColor(color='darkblue') self.plot_canvas[3].setGraphXLabel("f [m^-1]") self.plot_canvas[3].setGraphYLabel("CSD [m^3]") self.plot_canvas[3].setGraphTitle("Cumulative Spectral Density of Heights Profile") self.plot_canvas[3].setDrawModeEnabled(True, 'rectangle') self.plot_canvas[3].setZoomModeEnabled(True) self.plot_canvas[3].setXAxisLogarithmic(True) self.plot_canvas[4] = PlotWindow(roi=False, control=False, position=True, plugins=False) self.plot_canvas[4].setDefaultPlotLines(True) self.plot_canvas[4].setActiveCurveColor(color='darkblue') self.plot_canvas[4].setGraphXLabel("Length [m]") self.plot_canvas[4].setGraphYLabel("ACF") self.plot_canvas[4].setGraphTitle("Autocovariance Function of Heights Profile") self.plot_canvas[4].setDrawModeEnabled(True, 'rectangle') self.plot_canvas[4].setZoomModeEnabled(True) self.figure = Figure(figsize=(self.IMAGE_HEIGHT, self.IMAGE_HEIGHT)) # QUADRATA! self.figure.patch.set_facecolor('white') self.axis = self.figure.add_subplot(111, projection='3d') self.axis.set_zlabel("Z [nm]") self.plot_canvas[5] = FigureCanvasQTAgg(self.figure) self.profileInfo = QTextEdit() self.profileInfo.setReadOnly(True) self.profileInfo.setMinimumHeight(self.IMAGE_HEIGHT-5) self.profileInfo.setMaximumHeight(self.IMAGE_HEIGHT-5) self.profileInfo.setMinimumWidth(310) self.profileInfo.setMaximumWidth(310) profile_box = oasysgui.widgetBox(self.tab[0], "", addSpace=True, orientation="horizontal", height = self.IMAGE_HEIGHT, width=320) profile_box.layout().addWidget(self.profileInfo) for index in range(0, 6): self.tab[index+1].layout().addWidget(self.plot_canvas[index]) self.tabs.setCurrentIndex(1) def plot_dabam_graph(self, plot_canvas_index, curve_name, x_values, y_values, xtitle, ytitle, color='blue', replace=True): self.plot_canvas[plot_canvas_index].addCurve(x_values, y_values, curve_name, symbol='', color=color, replace=replace) #'+', '^', ',' self.plot_canvas[plot_canvas_index].setGraphXLabel(xtitle) self.plot_canvas[plot_canvas_index].setGraphYLabel(ytitle) self.plot_canvas[plot_canvas_index].replot() def set_ModifyY(self): self.modify_box_1.setVisible(self.modify_y == 0) self.modify_box_2.setVisible(self.modify_y == 1) self.modify_box_3.setVisible(self.modify_y == 2) def set_RenormalizeY(self): self.output_profile_box_1.setVisible(self.renormalize_y==1) def table_item_clicked(self): if self.table.selectionModel().hasSelection(): if not self.table.rowCount() == 0: if not self.table.item(0, 0) is None: row = self.table.selectionModel().selectedRows()[0].row() self.entry_number = int(self.table.item(row, 0).text()) self.retrieve_profile() def retrieve_profile(self): try: if self.entry_number is None or self.entry_number <= 0: raise Exception("Entry number should be a strictly positive integer number") self.server.load(self.entry_number) self.profileInfo.setText(self.server.info_profiles()) self.plot_canvas[0].setGraphTitle( "Heights Profile. St.Dev.=%.3f nm" % (self.server.stdev_profile_heights() * 1e9)) self.plot_canvas[1].setGraphTitle( "Slopes Profile. St.Dev.=%.3f $\mu$rad" % (self.server.stdev_profile_slopes() * 1e6)) if self.use_undetrended == 0: self.plot_dabam_graph(0, "heights_profile", self.si_to_user_units * self.server.y, 1e9 * self.server.zHeights, "Y [" + self.workspace_units_label + "]", "Z [nm]") self.plot_dabam_graph(1, "slopes_profile", self.si_to_user_units * self.server.y, 1e6 * self.server.zSlopes, "Y [" + self.workspace_units_label + "]", "Zp [$\mu$rad]") else: self.plot_dabam_graph(0, "heights_profile", self.si_to_user_units * self.server.y, 1e9 * self.server.zHeightsUndetrended, "Y [" + self.workspace_units_label + "]", "Z [nm]") self.plot_dabam_graph(1, "slopes_profile", self.si_to_user_units * self.server.y, 1e6 * self.server.zSlopesUndetrended, "Y [" + self.workspace_units_label + "]", "Zp [$\mu$rad]") y = self.server.f ** (self.server.powerlaw["hgt_pendent"]) * 10 ** self.server.powerlaw["hgt_shift"] i0 = self.server.powerlaw["index_from"] i1 = self.server.powerlaw["index_to"] beta = -self.server.powerlaw["hgt_pendent"] self.plot_canvas[2].setGraphTitle( "Power Spectral Density of Heights Profile (beta=%.2f,Df=%.2f)" % (beta, (5 - beta) / 2)) self.plot_dabam_graph(2, "psd_heights_2", self.server.f, self.server.psdHeights, "f [m^-1]", "PSD [m^3]") self.plot_dabam_graph(2, "psd_heights_1", self.server.f, y, "f [m^-1]", "PSD [m^3]", color='green', replace=False) self.plot_dabam_graph(2, "psd_heights_3", self.server.f[i0:i1], y[i0:i1], "f [m^-1]", "PSD [m^3]", color='red', replace=False) self.plot_dabam_graph(3, "csd", self.server.f, self.server.csd_heights(), "f [m^-1]", "CSD [m^3]") c1, c2, c3 = dabam.autocorrelationfunction(self.server.y, self.server.zHeights) self.plot_canvas[4].setGraphTitle( "Autocovariance Function of Heights Profile.\nAutocorrelation Length (ACF=0.5)=%.3f m" % (c3)) self.plot_dabam_graph(4, "acf", c1[0:-1], c2, "Length [m]", "Heights Autocovariance") # surface error removal if not self.zz is None and not self.yy is None and not self.xx is None: self.xx = None self.yy = None self.zz = None self.axis.set_title("") self.axis.clear() self.plot_canvas[5].draw() if (self.tabs.currentIndex()==6): self.tabs.setCurrentIndex(1) except Exception as exception: QMessageBox.critical(self, "Error", exception.args[0], QMessageBox.Ok) #raise exception def search_profiles(self): try: self.table.itemClicked.disconnect(self.table_item_clicked) self.table.clear() row_count = self.table.rowCount() for n in range(0, row_count): self.table.removeRow(0) self.table.setHorizontalHeaderLabels(self.horHeaders) profiles = dabam.dabam_summary_dictionary(surface=self.get_dabam_shape(), slp_err_from=self.slope_error_from*1e-6, slp_err_to=self.slope_error_to*1e-6, length_from=self.dimension_y_from / self.si_to_user_units, length_to=self.dimension_y_to / self.si_to_user_units) for index in range(0, len(profiles)): self.table.insertRow(0) for index in range(0, len(profiles)): table_item = QTableWidgetItem(str(profiles[index]["entry"])) table_item.setTextAlignment(Qt.AlignCenter) self.table.setItem(index, 0, table_item) table_item = QTableWidgetItem(str(profiles[index]["surface"])) table_item.setTextAlignment(Qt.AlignLeft) self.table.setItem(index, 1, table_item) table_item = QTableWidgetItem(str(numpy.round(profiles[index]["length"]*self.si_to_user_units, 3))) table_item.setTextAlignment(Qt.AlignRight) self.table.setItem(index, 2, table_item) table_item = QTableWidgetItem(str(numpy.round(profiles[index]["hgt_err"]*1e9, 3))) table_item.setTextAlignment(Qt.AlignRight) self.table.setItem(index, 3, table_item) table_item = QTableWidgetItem(str(numpy.round(profiles[index]["slp_err"]*1e6, 3))) table_item.setTextAlignment(Qt.AlignRight) self.table.setItem(index, 4, table_item) self.table.setHorizontalHeaderLabels(self.horHeaders) self.table.resizeRowsToContents() self.table.setSelectionBehavior(QAbstractItemView.SelectRows) self.table.itemClicked.connect(self.table_item_clicked) self.overlay_search.hide() except Exception as exception: self.overlay_search.hide() QMessageBox.critical(self, "Error", exception.args[0], QMessageBox.Ok) def get_dabam_shape(self): if self.shape == 0: return None elif self.shape == 1: return "plane" elif self.shape == 2: return "cylindrical" elif self.shape == 3: return "elliptical" elif self.shape == 4: return "toroidal" elif self.shape == 5: return "spherical" def calculate_heigth_profile_ni(self): self.calculate_heigth_profile(not_interactive_mode=True) def calculate_heigth_profile(self, not_interactive_mode=False): try: if self.server.y is None: raise Exception("No Profile Selected") sys.stdout = EmittingStream(textWritten=self.writeStdOut) self.check_fields() combination = "EF" if self.modify_y == 2: profile_1D_y_x_temp = self.si_to_user_units * self.server.y if self.use_undetrended == 0: profile_1D_y_y_temp = self.si_to_user_units * self.server.zHeights else: profile_1D_y_y_temp = self.si_to_user_units * self.server.zHeightsUndetrended first_coord = profile_1D_y_x_temp[0] second_coord = profile_1D_y_x_temp[1] last_coord = profile_1D_y_x_temp[-1] step = numpy.abs(second_coord - first_coord) length = numpy.abs(last_coord - first_coord) n_points_old = len(profile_1D_y_x_temp) if self.new_length > length: difference = self.new_length - length n_added_points = int(difference/step) if difference % step == 0: n_added_points += 1 if n_added_points % 2 != 0: n_added_points += 1 profile_1D_y_x = numpy.arange(n_added_points + n_points_old) * step profile_1D_y_y = numpy.ones(n_added_points + n_points_old) * self.filler_value * 1e-9 * self.si_to_user_units profile_1D_y_y[int(n_added_points/2) : n_points_old + int(n_added_points/2)] = profile_1D_y_y_temp elif self.new_length < length: difference = length - self.new_length n_removed_points = int(difference/step) if difference % step == 0: n_removed_points -= 1 if n_removed_points % 2 != 0: n_removed_points -= 1 if n_removed_points >= 2: profile_1D_y_x = profile_1D_y_x_temp[0 : (n_points_old - n_removed_points)] profile_1D_y_y = profile_1D_y_y_temp[(int(n_removed_points/2) - 1) : (n_points_old - int(n_removed_points/2) - 1)] else: profile_1D_y_x = profile_1D_y_x_temp profile_1D_y_y = profile_1D_y_y_temp else: profile_1D_y_x = profile_1D_y_x_temp profile_1D_y_y = profile_1D_y_y_temp else: if self.modify_y == 0: profile_1D_y_x = self.si_to_user_units * self.server.y elif self.modify_y == 1: profile_1D_y_x = self.si_to_user_units * self.server.y * self.scale_factor_y if self.use_undetrended == 0: profile_1D_y_y = self.si_to_user_units * self.server.zHeights else: profile_1D_y_y = self.si_to_user_units * self.server.zHeightsUndetrended if self.center_y: first_coord = profile_1D_y_x[0] last_coord = profile_1D_y_x[-1] length = numpy.abs(last_coord - first_coord) profile_1D_y_x_temp = numpy.linspace(-length/2, length/2, len(profile_1D_y_x)) profile_1D_y_x = profile_1D_y_x_temp if self.renormalize_y == 0: rms_y = None else: if self.error_type_y == profiles_simulation.FIGURE_ERROR: rms_y = self.si_to_user_units * self.rms_y * 1e-9 # from nm to user units else: rms_y = self.rms_y * 1e-6 # from urad to rad xx, yy, zz = profiles_simulation.simulate_profile_2D(combination = combination, error_type_l = self.error_type_y, rms_l = rms_y, x_l = profile_1D_y_x, y_l = profile_1D_y_y, mirror_width = self.dimension_x, step_w = self.step_x, rms_w = 0.0) self.xx = xx self.yy = yy self.zz = zz # in user units self.axis.clear() x_to_plot, y_to_plot = numpy.meshgrid(xx, yy) z_to_plot = zz * 1e9 / self.si_to_user_units #nm self.axis.plot_surface(x_to_plot, y_to_plot, z_to_plot, rstride=1, cstride=1, cmap=cm.autumn, linewidth=0.5, antialiased=True) sloperms = profiles_simulation.slopes(zz.T, xx, yy, return_only_rms=1) title = ' Slope error rms in X direction: %f $\mu$rad' % (sloperms[0]*1e6) + '\n' + \ ' Slope error rms in Y direction: %f $\mu$rad' % (sloperms[1]*1e6) self.axis.set_xlabel("X [" + self.workspace_units_label + "]") self.axis.set_ylabel("Y [" + self.workspace_units_label + "]") self.axis.set_zlabel("Z [nm]") self.axis.set_title(title) self.axis.mouse_init() if not not_interactive_mode: try: self.plot_canvas[5].draw() except: pass self.tabs.setCurrentIndex(6) QMessageBox.information(self, "QMessageBox.information()", "Height Profile calculated: if the result is satisfactory,\nclick \'Generate Height Profile File\' to complete the operation ", QMessageBox.Ok) except Exception as exception: QMessageBox.critical(self, "Error", exception.args[0], QMessageBox.Ok) #raise exception def generate_heigth_profile_file_ni(self): self.generate_heigth_profile_file(not_interactive_mode=True) def generate_heigth_profile_file(self, not_interactive_mode=False): if not self.zz is None and not self.yy is None and not self.xx is None: try: congruence.checkDir(self.heigth_profile_file_name) sys.stdout = EmittingStream(textWritten=self.writeStdOut) ST.write_shadow_surface(self.zz, self.xx, self.yy, outFile=congruence.checkFileName(self.heigth_profile_file_name)) if not not_interactive_mode: QMessageBox.information(self, "QMessageBox.information()", "Height Profile file " + self.heigth_profile_file_name + " written on disk", QMessageBox.Ok) if self.modify_y == 0: dimension_y = self.si_to_user_units * (self.server.y[-1] - self.server.y[0]) if self.modify_y == 1: dimension_y = self.si_to_user_units * (self.server.y[-1] - self.server.y[0]) * self.scale_factor_y elif self.modify_y == 2: dimension_y = self.new_length self.send("PreProcessor_Data", ShadowPreProcessorData(error_profile_data_file=self.heigth_profile_file_name, error_profile_x_dim=self.dimension_x, error_profile_y_dim=dimension_y)) except Exception as exception: QMessageBox.critical(self, "Error", exception.args[0], QMessageBox.Ok) def call_reset_settings(self): if ConfirmDialog.confirmed(parent=self, message="Confirm Reset of the Fields?"): try: self.resetSettings() except: pass def check_fields(self): self.dimension_x = congruence.checkStrictlyPositiveNumber(self.dimension_x, "Dimension X") self.step_x = congruence.checkStrictlyPositiveNumber(self.step_x, "Step X") if self.step_x > self.dimension_x/2: raise Exception("Step Width should be smaller than or equal to Width/2") if self.modify_y == 1: self.scale_factor_y = congruence.checkStrictlyPositiveNumber(self.scale_factor_y, "Scale Factor") elif self.modify_y == 2: self.new_length = congruence.checkStrictlyPositiveNumber(self.new_length, "New Length") if self.renormalize_y == 1: self.rms_y = congruence.checkPositiveNumber(self.rms_y, "Rms Y") congruence.checkDir(self.heigth_profile_file_name) def writeStdOut(self, text): cursor = self.shadow_output.textCursor() cursor.movePosition(QTextCursor.End) cursor.insertText(text) self.shadow_output.setTextCursor(cursor) self.shadow_output.ensureCursorVisible() def selectFile(self): self.le_heigth_profile_file_name.setText(oasysgui.selectFileFromDialog(self, self.heigth_profile_file_name, "Select Output File", file_extension_filter="Data Files (*.dat)"))
class AccessFrontend(ScrollArea): COMPONENT = 'access' LABEL = tr('Access to services') REQUIREMENTS = ('access',) STYLE_ALLOW = "color: white; background-color: white; border: none;" STYLE_DISALLOW = "color: lightGray; background-color: lightGray; border: none;" ICON = ':/icons/Acl.png' def __init__(self, client, parent): ScrollArea.__init__(self) self.client = client self.mainwindow = parent self._modified = False self.__disabled = False self.net_object = QNetObject.getInitializedInstance(self.client) if EDENWALL: self.vpn_object = QOpenVpnObject.getInstance() self.setupWidgets() self.getConfigs() self.getNetworks() # vpn_config is used to check if the VPN config changed or not self.vpn_config = self.getVPNConfig() self.fillTable() self.net_object.registerCallbacks(self.validateNetCfg, self.updateWithNetCfg) if EDENWALL: self.vpn_object.registerCallbacks(self.validateVpnCfg, self.updateWithVpnCfg) self.mainwindow.addToInfoArea(tr("Access interface enabled")) @staticmethod def get_calls(): """ services called at startup (self.mainwindow.init_call) """ return (('access', 'getConfig'),) def getVPNConfig(self): if not EDENWALL: return None vpn = self.vpn_object.getCfg() if not vpn: return None return (vpn.enabled, vpn.protocol, vpn.port, vpn.client_network) def setupWidgets(self): layout = QVBoxLayout(self) self.setLayout(layout) self.icon = QIcon() ALLOW = QPixmap(":/icons-20/status_on.png") self.icon.addPixmap(ALLOW, QIcon.Normal, QIcon.On) DISALLOW = QPixmap(":/icons-20/status_off.png") self.icon.addPixmap(DISALLOW, QIcon.Normal, QIcon.Off) title = QLabel(u"<H1>%s</H1>" % tr("Access to services")) layout.addWidget(title) self.table = QTableWidget() self.table.setSelectionMode(QAbstractItemView.NoSelection) layout.addWidget(self.table) def isModified(self): return self._modified def isValid(self): if self.__disabled: return True valid, errmsg = self.access_cfg.isValidWithMsg() if not valid: self.error_message = errmsg return valid def setModified(self, modif=True): if self.__disabled: self._modified = False return self._modified = modif if modif: self.mainwindow.setModified(self, True) def resetConf(self): if self.__disabled: return self.getConfigs() self.getNetworks() self.fillTable() def __disable(self, reason): if self.__disabled: return self.__disabled = True self.mainwindow.addToInfoArea( tr("The Access to services interface is disabled."), COLOR_ERROR) self.mainwindow.addToInfoArea(reason, COLOR_ERROR) self.close() raise NuConfModuleDisabled(reason) def getConfigs(self): if self.__disabled: return try: data = self.mainwindow.init_call('access', 'getConfig') except RpcdError: self.__disable(tr("Could not get Access to services configuration.")) return if data is None: self.access_cfg = AccessConf.defaultConf() else: self.access_cfg = AccessConf.deserialize(data) def _getNetworks(self, netcfg): return [(interface.system_name, network) for interface, network in netcfg.iterKnownNetworks()] def getNetworks(self): if self.__disabled: return netcfg = QNetObject.getInstance().netcfg if netcfg is None: self.networks = () self.mainwindow.addToInfoArea( tr("The access interface could not load the network configuration"), COLOR_ERROR ) return # list of (interface, network) where interface (str) is the system # name, and network (IPy.IP object) is the network address # (eg. IP('192.168.0.0/24') self.networks = self._getNetworks(netcfg) self.networks += list(self.access_cfg.custom_networks) self.networks.sort() def fillTable(self): if self.__disabled: self.table.clear() return services = list(self.access_cfg.permissions) self.table.clear() # (interface (str), network (IPy), ip version (int)) => row (int) # Don't use (interface, network) because of a bug in IPy < 0.70: # IP('0.0.0.0/0') and IP('::/0') are considered as equal self.net_to_row = {} component_to_name = ComponentToName() self.table.setSortingEnabled(False) self.table.setRowCount(len(self.networks)) self.setVerticalHeaders() self.table.setColumnCount(len(services)) self.table.setHorizontalHeaderLabels([component_to_name.display_name(service) for service in services]) self.table.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents) for irow, interface_network in enumerate(self.networks): self.setRow(interface_network, irow) for icol, service in enumerate(self.access_cfg.permissions): allow = interface_network in self.access_cfg.permissions[service] self.createService(irow, icol, service, interface_network, allow) def getRow(self, interface_network, pop=False): interface, network = interface_network key = (interface, network, network.version()) if pop: return self.net_to_row.pop(key) else: return self.net_to_row[key] def setRow(self, interface_network, row): interface, network = interface_network key = (interface, network, network.version()) self.net_to_row[key] = row def setVerticalHeaders(self): labels = [self.netLabel(interface, network) for interface, network in self.networks] self.table.setVerticalHeaderLabels(labels) def saveConf(self, message): data = self.access_cfg.serialize(downgrade=True) self.client.call("access", 'setConfig', message, data) self.setModified(False) def changeService(self, col, service, interface_network): row = self.getRow(interface_network) self.setModified(True) button = self.table.cellWidget(row, col) if button.isChecked(): self.access_cfg.permissions[service].add(interface_network) button.setStyleSheet(self.STYLE_ALLOW) else: try: self.access_cfg.permissions[service].remove(interface_network) except KeyError: pass button.setStyleSheet(self.STYLE_DISALLOW) def appendNetwork(self, interface_network, close_all_ports=False): row = self.table.rowCount() self.table.insertRow(row) self.networks.append(interface_network) self.setRow(interface_network, row) interface, network = interface_network for icol, service in enumerate(self.access_cfg.permissions): if (not close_all_ports) \ and (service in OPEN_BY_DEFAULT) \ and (network not in CLOSED_NETWORKS): allow = True self.access_cfg.permissions[service].add(interface_network) else: allow = interface_network in self.access_cfg.permissions[service] self.createService(row, icol, service, interface_network, allow) def removeNetwork(self, interface_network): index = self.getRow(interface_network, pop=True) self.table.removeRow(index) network = self.networks[index] for service, networks in self.access_cfg.permissions.iteritems(): try: networks.remove(network) except KeyError: pass del self.networks[index] for key, row in self.net_to_row.iteritems(): if row > index: self.net_to_row[key] -= 1 # callback used to update the table on network modification def updateWithNetCfg(self, deleted_nets, added_nets): if not(deleted_nets or added_nets): return # delete for key in deleted_nets: self.removeNetwork(key) # add new for interface_network in added_nets: self.appendNetwork(interface_network, close_all_ports=True) # modify and update self.setVerticalHeaders() self.setModified(True) def createService(self, row, col, service, interface_network, allow): button = QPushButton(self.icon, u'') button.setCheckable(True) button.setFlat(True) button.setAutoFillBackground(True) if allow: style = self.STYLE_ALLOW else: style = self.STYLE_DISALLOW button.setStyleSheet(style) button.setFocusPolicy(Qt.NoFocus) self.mainwindow.writeAccessNeeded(button) self.connect(button, SIGNAL('clicked()'), partial(self.changeService, col, service, interface_network)) self.table.setCellWidget(row, col, button) # with PyQt 4.4.2, table.setCellWidget(button) changes # the button's state (bug fixed in PyQt 4.4.4) button.setChecked(allow) # callback used when the networks are modified def validateNetCfg(self): netcfg = QNetObject.getInstance().netcfg previous_nets = set(self.networks) - set(self.access_cfg.custom_networks) new_networks = self._getNetworks(netcfg) new_networks = set(new_networks) not_in_both = previous_nets ^ new_networks deleted_nets = not_in_both & previous_nets added_nets = not_in_both & new_networks return True, deleted_nets, added_nets def validateVpnCfg(self): """ always accept modifications """ return True, self.getVPNConfig() def updateWithVpnCfg(self, new_config): if self.vpn_config == new_config: return # anything changed, access has to reapply the new config self.setModified() self.vpn_config = new_config # get old/new key config = self.vpn_object.getCfg() if self.access_cfg.custom_networks: old_key = self.access_cfg.custom_networks[0] else: old_key = None if config.enabled: network = config.client_network try: network = IP(network) except ValueError: # ignore invalid network: vpn check will raise an error return new_key = (OPENVPN_INTERFACE, network) else: new_key = None # no change? exit if old_key == new_key: return # create/delete vpn custom network if old_key: self.removeNetwork(old_key) if new_key: self.access_cfg.custom_networks = [new_key] self.appendNetwork(new_key) else: self.access_cfg.custom_networks = [] self.setVerticalHeaders() def netLabel(self, interface, network): """ return label for network """ interface_label = interface network_label = str(network) network = IP(network) netcfg = QNetObject.getInstance().netcfg try: interface = netcfg.getInterfaceBySystemName(interface) interface_label = interface.user_label network = netcfg.getNet(network) network_label = network.displayName() except NoMatch: pass return tr("%s: %s") % (interface_label, network_label)
class PvTunerDlg(QDialog): COL = 6 COL_ELEMENT = 0 COL_FIELD = 1 COL_PV = 2 COL_STEPSIZE = 3 COL_READBACK = 4 COL_SETPOINT = 5 FMT_READBACK = "%.4e" def __init__(self, parent=None): super(PvTunerDlg, self).__init__(parent) self.setAttribute(Qt.WA_DeleteOnClose) #self.inputBox = QLineEdit("PL2G2C01A.x") #self.inputBox = QLineEdit("CXH2G6C01B.x") self.inputBox = QLineEdit("PL2G2C01A") addPvBtn = QPushButton("add") self.table = QTableWidget(0, PvTunerDlg.COL) self.table.setHorizontalHeaderLabels(["Element", "Field", "PV", "Stepsize", "Readback", "setpoint"]) #self.table.horizontalHeader().setStretchLastSection(True) #self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) buttonBox = QDialogButtonBox(QDialogButtonBox.Ok) box = QGridLayout() box.addWidget(self.inputBox, 0, 0) box.addWidget(addPvBtn, 0, 1) box.addWidget(self.table, 1, 0, 1, 2) box.addWidget(buttonBox, 2, 0) self.setLayout(box) self.pvs_rb = [] self.pvs_rb_val_flat = [] self.pvs_sp = [] self.pvmoni = [] self.spinbox = [] self.connect(addPvBtn, SIGNAL("clicked()"), self.addPv) self.connect(buttonBox, SIGNAL("accepted()"), self.accept) #self.connect(self.table, SIGNAL("cellChanged"), self.updatePv) self.connect(buttonBox.button(QDialogButtonBox.Ok), SIGNAL("clicked()"), self.close) self.connect(self.table, SIGNAL("cellClicked(int, int)"), self._cell_clicked) def _cell_clicked(self, row, column): #print row, column if column in [self.COL_PV, self.COL_STEPSIZE]: item = self.table.item(row, column) if not item: return item.setFlags(item.flags() | Qt.ItemIsEditable) def _appendRecord(self, name): vec = name.split('.') if len(vec) > 2: QMessageBox.critical(None, "ERROR", "format is wrong") return if len(vec) == 1: elem, field = vec[0], 'value' elif len(vec) == 2: elem, field = vec elemobj = hla.getElements(elem) if elemobj: # pvsrb is a list pvsrb = elemobj.pv(field=field, handle='readback') self.pvs_rb.append(pvsrb) pvssp = elemobj.pv(field=field, handle='setpoint') self.pvs_sp.append(pvssp) else: QMessageBox.critical(None, "ERROR", "element %s not found" % elem) return # expand one row m, n = self.table.rowCount(), self.table.columnCount() self.table.insertRow(m) # add cells item = QTableWidgetItem(elem) item.setFlags(item.flags() & (~Qt.ItemIsEditable)) self.table.setItem(m, self.COL_ELEMENT, item) item = QTableWidgetItem(field) item.setFlags(item.flags() & (~Qt.ItemIsEditable)) self.table.setItem(m, self.COL_FIELD, item) item = QTableWidgetItem(', '.join(pvsrb)) #item.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) self.table.setItem(m, self.COL_PV, item) readval = ['%.4e' % v for v in caget(pvsrb)] item = QTableWidgetItem(', '.join(readval)) item.setFlags(item.flags() & (~Qt.ItemIsEditable)) self.table.setItem(m, self.COL_READBACK, item) # set the stepsize of PV stepsize = 0.00001 if pvssp: item = QTableWidgetItem('%f' % stepsize) item.setFlags(item.flags() & (~Qt.ItemIsEditable)) self.table.setItem(m, self.COL_STEPSIZE, item) self.spinbox.append(QDoubleSpinBox(self.table)) self.spinbox[-1].setRange(-100, 100) #self.spinbox[-1].setValue(float(10.0)) self.spinbox[-1].setSingleStep(stepsize) self.spinbox[-1].setDecimals(10) self.spinbox[-1].valueChanged.connect(self._writePv) self.table.setCellWidget(m, self.COL_SETPOINT, self.spinbox[-1]) sp = float(caget(pvssp)[0]) #print "setpoint:", pvssp, sp, type(sp) self.spinbox[-1].setValue(-1e-5) #print "connected", self.spinbox[-1].value() else: item = self.table.item(m, self.COL_STEPSIZE) if item: item.setFlags(item.flags() & (~Qt.ItemIsEditable)) item = self.table.item(m, self.COL_SETPOINT) if item: item.setFlags(item.flags() & (~Qt.ItemIsEditable)) self.spinbox.append(None) self.table.resizeColumnsToContents() def addPv(self): self._appendRecord(str(self.inputBox.text())) self._updateMonitors() def minimalSizeHint(self): return QSize(800, 600) def _writePv(self, v): """ """ c = QObject.sender(self) i = self.spinbox.index(c) #print i, c.text(), "changed" #print self.pvs_sp[i], v caput(self.pvs_sp[i], v) def _updateMonitors(self): """ prepare the PV list for camonitor """ #print "Updating monitors" pvs = [] self.pvs_rb_val = [] for i in range(self.table.rowCount()): for j in range(len(self.pvs_rb[i])): self.pvs_rb_val.append([i, 0.0]) pvs.extend(self.pvs_rb[i]) for p in self.pvmoni: p.close() self.pvmoni = camonitor(pvs, self._updatePvValues) #print self.pvmoni #print pvs #print self.pvs_rb_val def _updatePvValues(self, val, idx): #print idx, val s = [] for i, v in enumerate(self.pvs_rb_val): if v[0] == self.pvs_rb_val[idx][0]: s.append(self.FMT_READBACK % val) #print s item = self.table.item(self.pvs_rb_val[idx][0], self.COL_READBACK) item.setText(','.join(s)) def closePvMonitors(self): #print "Closing PV Monitors" for p in self.pvmoni: p.close() pass def closeEvent(self, event): self.closePvMonitors() event.accept() def close(self): self.closePvMonitors() return True
class Ventana(QWidget): def __init__(self): super(Ventana, self).__init__() self.algoritmos = {"FCFS":FCFS, "SJF":SJF, "SRTF":SRTF, "Prioridad":Prioridad, "Round Robin":RoundRobin, "Colas multiples retroalimentadas":MulticolasRetro} self.iniciar = QPushButton("INICIAR") self.bloquear = QPushButton("BLOQUEAR") self.tablaGantt = QTableWidget(5, 0) self.tablaDatos = QTableWidget(0, 9) self.temporizador = QTimer(self) self.contenedor = None self.cant = 0 self.terminados = 0 self.fila = 0 self.columna = 0 self.bloqueo = False self._inicializar() def _inicializar(self): self.setWindowTitle("Algoritmos de planificacion ") #------------------------------------# # ELEMENTOS DEL PANEL SUPERIOR # #------------------------------------# tituloS = QLabel("DIAGRAMA DE GANTT") tituloS.adjustSize() fila1 = QHBoxLayout() fila2 = QHBoxLayout() fila1.addWidget(tituloS) fila2.addWidget(self.tablaGantt) cajaSuperior = QVBoxLayout() cajaSuperior.addLayout(fila1) cajaSuperior.addLayout(fila2) #------------------------------------# # ELEMENTOS DEL PANEL INFERIOR # #------------------------------------# tituloI = QLabel("DATOS DE LOS PROCESOS") tituloI.adjustSize() fila3 = QHBoxLayout() fila4 = QHBoxLayout() fila5 = QHBoxLayout() fila3.addWidget(tituloI) fila4.addWidget(self.tablaDatos) fila5.addWidget(self.iniciar) fila5.addWidget(self.bloquear) cajaInferior = QVBoxLayout() cajaInferior.addLayout(fila3) cajaInferior.addLayout(fila4) cajaInferior.addLayout(fila5) #------------------------------------# #agregar el segundo nivel de layout al panel panelSuperior = QFrame(self) panelSuperior.setFrameShape(QFrame.StyledPanel) panelSuperior.setLayout(cajaSuperior) #agregar el segundo nivel de layout al panel panelInferior = QFrame(self) panelInferior.setFrameShape(QFrame.StyledPanel) panelInferior.setLayout(cajaInferior) #agregar el panel al separador separador = QSplitter(Qt.Vertical) separador.addWidget(panelSuperior) separador.addWidget(panelInferior) #agregar el separador al primer layout caja = QVBoxLayout(self) caja.addWidget(separador) #agregar el layout a la ventana self.setLayout(caja) self.setFixedSize(1200, 900) self._configurar() self.show() def _configurar(self): self.iniciar.clicked.connect(self._comenzar) self.bloquear.clicked.connect(self._bloquear) self.bloquear.setEnabled(False) self.temporizador.timeout.connect(self._actualizar) self.tablaGantt.setEditTriggers(QAbstractItemView.NoEditTriggers) self.tablaGantt.setDragDropOverwriteMode(False) self.tablaDatos.setEditTriggers(QAbstractItemView.NoEditTriggers) self.tablaDatos.setDragDropOverwriteMode(False) datos = ["PROCESO", "LLEGADA", "RAFAGA", "PRIORIDAD", "EDAD", "COMIENZO", "FINALIZACION", "RETORNO", "ESPERA"] self.tablaDatos.setHorizontalHeaderLabels(QStringList(datos)) def _comenzar(self): ok = 0 eleccion, ok1 = QInputDialog.getItem(self, "Algoritmos", "Seleccione un algoritmo", self.algoritmos.keys()) if ok1: self.contenedor = self.algoritmos[str(eleccion)]() self.cant, ok = QInputDialog.getInt(self, "Duracion", "Indique la duracion de la simulacion", min=0, max=60) if ok and ok1: self.setWindowTitle(self.windowTitle() + " --" +str(eleccion)) self.temporizador.start(1000) self.iniciar.setEnabled(False) self.bloquear.setEnabled(True) self._inicializarDatos() def _bloquear(self): self.bloqueo = True def _actualizar(self): momento = round(clock()) if momento < self.cant: proceso = self.contenedor.agregarProcesos(momento) if proceso: if proceso.listo(): self._actualizarDatosNuevo(proceso) self.tablaGantt.insertRow(self.fila) self.fila += 1 estados = [p.estado for p in self.contenedor.procesos] if self.contenedor.procesos and ("listo" in estados or "ejecutando" in estados): proceso = self.contenedor.administrarProcesos(momento, self.bloqueo) if self.bloqueo: self.bloqueo = False if proceso or proceso==0: if self.contenedor[proceso].terminado() and not self.contenedor[proceso].actualizado: self._actualizarDatosFinalizado(self.contenedor[proceso], proceso) self.contenedor[proceso].actualizado = True self.terminados += 1 self._actualizarGantt() if isinstance(self.contenedor, Prioridad): self._actualizarDatosDinamicos() else: msj = QMessageBox.information(self, "Terminado", "El proceso de simulacion ha terminado") self.temporizador.stop() del msj def _actualizarGantt(self): self.tablaGantt.insertColumn(self.columna) for i in range(len(self.contenedor)): item = QTableWidgetItem() if self.contenedor[i].ejecutando(): if isinstance(self.contenedor, MulticolasRetro): if self.contenedor[i].prioridad == 1: item.setBackgroundColor(QColor(0,128,0)) elif self.contenedor[i].prioridad == 2: item.setBackgroundColor(QColor(0,255,0)) elif self.contenedor[i].prioridad == 3: item.setBackgroundColor(QColor(128,255,128)) else: item.setBackgroundColor(Qt.green) elif self.contenedor[i].listo(): if isinstance(self.contenedor, MulticolasRetro): if self.contenedor[i].prioridad == 1: item.setBackgroundColor(QColor(128,0,0)) elif self.contenedor[i].prioridad == 2: item.setBackgroundColor(QColor(255,0,0)) elif self.contenedor[i].prioridad == 3: item.setBackgroundColor(QColor(255,128,128)) else: item.setBackgroundColor(Qt.red) elif self.contenedor[i].bloqueado(): item.setBackgroundColor(Qt.blue) self.tablaGantt.setItem(i, self.columna, item) self.columna += 1 self.tablaGantt.resizeColumnsToContents() def _actualizarDatosNuevo(self, proceso): self.tablaDatos.insertRow(self.fila) self.tablaDatos.setItem(self.fila, 0, QTableWidgetItem(str(proceso.nombre))) self.tablaDatos.setItem(self.fila, 1, QTableWidgetItem(str(proceso.llegada))) self.tablaDatos.setItem(self.fila, 2, QTableWidgetItem(str(proceso.rafaga))) if isinstance(self.contenedor, Prioridad): self.tablaDatos.setItem(self.fila, 3, QTableWidgetItem(str(proceso.prioridad))) self.tablaDatos.setItem(self.fila, 4, QTableWidgetItem(str(proceso.edad))) self.tablaDatos.resizeColumnsToContents() def _actualizarDatosDinamicos(self): for i in range(len(self.contenedor)): self.tablaDatos.setItem(i, 3, QTableWidgetItem(str(self.contenedor[i].prioridad))) self.tablaDatos.setItem(i, 4, QTableWidgetItem(str(self.contenedor[i].edad))) def _actualizarDatosFinalizado(self, proceso, i): self.tablaDatos.setItem(i, 5, QTableWidgetItem(str(proceso.comienzo))) self.tablaDatos.setItem(i, 6, QTableWidgetItem(str(proceso.finalizacion))) self.tablaDatos.setItem(i, 7, QTableWidgetItem(str(proceso.finalizacion - proceso.llegada))) self.tablaDatos.setItem(i, 8, QTableWidgetItem(str(proceso.comienzo - proceso.llegada))) def _inicializarDatos(self): for i in range(len(self.contenedor)): self.tablaDatos.insertRow(self.fila) self.tablaDatos.setItem(self.fila, 0, QTableWidgetItem(str(self.contenedor[i].nombre))) self.tablaDatos.setItem(self.fila, 1, QTableWidgetItem(str(self.contenedor[i].llegada))) self.tablaDatos.setItem(self.fila, 2, QTableWidgetItem(str(self.contenedor[i].rafaga))) if isinstance(self.contenedor, Prioridad): self.tablaDatos.setItem(self.fila, 3, QTableWidgetItem(str(self.contenedor[i].prioridad))) self.tablaDatos.setItem(self.fila, 4, QTableWidgetItem(str(self.contenedor[i].edad))) self.fila += 1 self.tablaDatos.resizeColumnsToContents()
class CameraWindow(PyDialog): def __init__(self, data, win_parent=None): """ +--------+ | Camera | +--------+---------------+ | Camera Name | | +-------------------+ | | | | | | | | | | | | | | | | | | | | | | +-------------------+ | | | | Name xxx Save | | Delete Set | | | | Apply OK Cancel | +--------+---------------+ """ PyDialog.__init__(self, data, win_parent) self.setWindowTitle('Camera Views') #self.setWindowIcon(view_icon) self._default_name = 'Camera' self.out_data['clicked_ok'] = False self.cameras = deepcopy(data['cameras']) self.names = sorted(self.cameras.keys()) self.name = QLabel("Name:") self.name_edit = QLineEdit(str(self._default_name)) self.delete_button = QPushButton("Delete") self.set_button = QPushButton("Set") self.save_button = QPushButton("Save") # closing self.apply_button = QPushButton("Apply") #self.ok_button = QPushButton("OK") self.close_button = QPushButton("Close") self.cancel_button = QPushButton("Cancel") self.table = QTableWidget() names_text = [] for iname, name in enumerate(self.names): name_text = QTableWidgetItem(str(name)) names_text.append(name_text) self.create_layout(names_text) self.set_connections() def create_layout(self, names_text): nrows = len(self.names) table = self.table table.setRowCount(nrows) table.setColumnCount(1) headers = [QString('Camera Name')] table.setHorizontalHeaderLabels(headers) header = table.horizontalHeader() header.setStretchLastSection(True) for iname, name_text in enumerate(names_text): # row, col, value table.setItem(iname, 0, name_text) table.resizeRowsToContents() ok_cancel_box = QHBoxLayout() ok_cancel_box.addWidget(self.apply_button) #ok_cancel_box.addWidget(self.ok_button) ok_cancel_box.addWidget(self.close_button) ok_cancel_box.addWidget(self.cancel_button) grid = QGridLayout() irow = 0 grid.addWidget(self.name, irow, 0) grid.addWidget(self.name_edit, irow, 1) grid.addWidget(self.save_button, irow, 2) irow += 1 grid.addWidget(self.delete_button, irow, 0) grid.addWidget(self.set_button, irow, 1) irow += 1 vbox = QVBoxLayout() vbox.addWidget(self.table) vbox.addLayout(grid) vbox.addStretch() vbox.addLayout(ok_cancel_box) self.setLayout(vbox) def set_connections(self): if qt_version == 4: self.connect(self.set_button, QtCore.SIGNAL('clicked()'), self.on_set) self.connect(self.save_button, QtCore.SIGNAL('clicked()'), self.on_save) self.connect(self.delete_button, QtCore.SIGNAL('clicked()'), self.on_delete) self.connect(self.apply_button, QtCore.SIGNAL('clicked()'), self.on_apply) #self.connect(self.ok_button, QtCore.SIGNAL('clicked()'), self.on_ok) self.connect(self.close_button, QtCore.SIGNAL('clicked()'), self.on_close) self.connect(self.cancel_button, QtCore.SIGNAL('clicked()'), self.on_cancel) else: self.set_button.clicked.connect(self.on_set) self.save_button.clicked.connect(self.on_save) self.delete_button.clicked.connect(self.on_delete) self.apply_button.clicked.connect(self.on_apply) self.close_button.clicked.connect(self.on_close) self.cancel_button.clicked.connect(self.on_cancel) def on_set(self): objs = self.table.selectedIndexes() if len(objs) == 1: obj = objs[0] irow = obj.row() name = self.names[irow] #print('name =', name) self.set_camera(name) return True return False def on_save(self): name = str(self.name_edit.text()).strip() if name in self.cameras: return irow = self.nrows if len(name): self.table.insertRow(irow) name_text = QTableWidgetItem(str(name)) self.table.setItem(irow, 0, name_text) self.name_edit.setText('') self.save_camera(name) def set_camera(self, name): camera_data = self.cameras[name] if self.win_parent is None: return self.win_parent.on_set_camera_data(camera_data) def save_camera(self, name): self.names.append(name) if self.win_parent is None: self.cameras[name] = None return self.cameras[name] = self.win_parent.get_camera_data() #@property #def camera(self): @property def nrows(self): return self.table.rowCount() def on_delete(self): irows = [] for obj in self.table.selectedIndexes(): irow = obj.row() irows.append(irow) irows.sort() for irow in reversed(irows): self.table.removeRow(irow) #print('delete', self.names) name = self.names.pop(irow) del self.cameras[name] #print(' removing irow=%s name=%r' % (irow, name)) def closeEvent(self, event): event.accept() @staticmethod def check_name(cell): text = str(cell.text()).strip() if len(text): cell.setStyleSheet("QLineEdit{background: white;}") return text, True else: cell.setStyleSheet("QLineEdit{background: red;}") return None, False #def on_validate(self): #name_value, flag0 = self.check_name(self.name_edit) #if flag0: #self.out_data['cameras'] = self.cameras #self.out_data['clicked_ok'] = True #return True #return False def on_apply(self): passed = self.on_set() #if passed: # self.win_parent.create_plane(self.out_data) return passed def on_close(self): self.out_data['clicked_ok'] = True self.out_data['cameras'] = self.cameras self.close() def on_ok(self): passed = self.on_apply() if passed: name = str(self.name_edit.text()).strip() self.out_data['name'] = name self.out_data['cameras'] = self.cameras self.out_data['clicked_ok'] = True self.close() #self.destroy() def on_cancel(self): self.close()
class TableCatalogOTF(QObject): runCatalog = pyqtSignal(str) def __init__(self): def initGui(): self.tableWidget.setWindowTitle("Catalog OTF") self.tableWidget.setSortingEnabled(False) msgtrans = QCoreApplication.translate("CatalogOTF", "Layer,Total") headers = msgtrans.split(',') self.tableWidget.setColumnCount(len(headers)) self.tableWidget.setHorizontalHeaderLabels(headers) self.tableWidget.resizeColumnsToContents() super(TableCatalogOTF, self).__init__() self.tableWidget = QTableWidget() initGui() def _getRowLayerID(self, layerID): for row in range(self.tableWidget.rowCount()): if layerID == self.tableWidget.cellWidget(row, 0).objectName(): return row return -1 def _changedText(self, layerID, name, column): row = self._getRowLayerID(layerID) if row != -1: wgt = self.tableWidget.cellWidget( row, column) if column == 0 else self.tableWidget.item( row, column) wgt.setText(name) wgt.setToolTip(name) self.tableWidget.resizeColumnsToContents() @pyqtSlot() def _onRunCatalog(self): btn = self.sender() icon = QIcon(joinPath(dirname(__file__), 'cancel_red.svg')) btn.setIcon(icon) layerID = btn.objectName() self.runCatalog.emit(layerID) @pyqtSlot() def _onSelectionChanged(self): layer = self.sender() row = self._getRowLayerID(layer.id()) if row != -1: wgt = self.tableWidget.cellWidget(row, 0) nameIcon = 'check_green.svg' if layer.selectedFeatureCount( ) == 0 else 'check_yellow.svg' icon = QIcon(joinPath(dirname(__file__), nameIcon)) wgt.setIcon(icon) @pyqtSlot("QgsVectorLayer") def insertRow(self, layer): row = self.tableWidget.rowCount() self.tableWidget.insertRow(row) column = 0 # Layer layerName = layer.name() nameIcon = 'check_green.svg' if layer.selectedFeatureCount( ) == 0 else 'check_yellow.svg' icon = QIcon(joinPath(dirname(__file__), nameIcon)) btn = QPushButton(icon, layerName, self.tableWidget) btn.setObjectName(layer.id()) btn.setToolTip(layerName) btn.clicked.connect(self._onRunCatalog) layer.selectionChanged.connect(self._onSelectionChanged) self.tableWidget.setCellWidget(row, column, btn) column = 1 # Total msgtrans = QCoreApplication.translate("CatalogOTF", "None") item = QTableWidgetItem(msgtrans) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.tableWidget.setItem(row, column, item) self.tableWidget.resizeColumnsToContents() @pyqtSlot(str) def removeRow(self, layerID): row = self._getRowLayerID(layerID) if row != -1: self.tableWidget.removeRow(row) @pyqtSlot(str, str) def changedNameLayer(self, layerID, name): self._changedText(layerID, name, 0) @pyqtSlot(str, str) def changedTotal(self, layerID, value): self._changedText(layerID, value, 1) @pyqtSlot(str, bool) def changedIconRun(self, layerID, selected): row = self._getRowLayerID(layerID) if row != -1: btn = self.tableWidget.cellWidget(row, 0) nameIcon = 'check_green.svg' if not selected else 'check_yellow.svg' icon = QIcon(joinPath(dirname(__file__), nameIcon)) btn.setIcon(icon) btn.setEnabled(True) @pyqtSlot(str) def killed(self, layerID): row = self._getRowLayerID(layerID) if row != -1: btn = self.tableWidget.cellWidget(row, 0) btn.setEnabled(False) def widget(self): return self.tableWidget
class OWxsh_waviness(widget.OWWidget): name = "xsh_waviness" id = "orange.widgets.preprocessor.xsh_waviness" description = "xoppy application to compute..." icon = "icons/waviness.png" author = "Luca Rebuffi" maintainer_email = "[email protected]; [email protected]" priority = 10 category = "" keywords = ["xoppy", "xsh_waviness"] outputs = [{"name": "PreProcessor_Data", "type": ShadowPreProcessorData, "doc": "PreProcessor Data", "id": "PreProcessor_Data"}] want_main_area = 1 want_control_area = 1 WIDGET_WIDTH = 1100 WIDGET_HEIGHT = 650 xx = None yy = None zz = None number_of_points_x = Setting(10) number_of_points_y = Setting(100) dimension_x = Setting(20.1) dimension_y = Setting(113.1) estimated_slope_error = Setting(0.9) montecarlo_seed = Setting(2387427) waviness_file_name = Setting('waviness.dat') harmonic_maximum_index = Setting(60) data = Setting({'c': ['0.3', '0.1', '0.1', '0.0', '0.0', '0.0', '0.3', '0.0', '0.0', '0.3', '0.0', '0.0', '0.5', '0.0', '0.0', '0.2', '0.2', '0.2', '0.9', '0.0', '0.0', '0.0', '0.0', '0.0', '0.4', '0.0', '0.0', '0.4', '0.0', '0.0', '0.0', '0.6', '0.6', '0.0', '0.4', '0.4', '0.0', '0.4', '0.4', '0.1', '0.4', '0.4', '0.1', '0.2', '0.2', '0.0', '0.2', '0.2', '0.0', '0.3', '0.3', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0'], 'y': ['0.0', '-0.1', '-0.1', '0.0', '0.0', '0.0', '0.03', '0.0', '0.0', '0.2', '0.0', '0.0', '0.2', '0.0', '0.0', '0.1', '0.1', '0.1', '0.1', '0.0', '0.0', '0.0', '0.0', '0.0', '0.01', '0.0', '0.0', '0.03', '0.0', '0.0', '0.0', '0.02', '0.02', '0.0', '0.1', '0.1', '0.0', '0.1', '0.1', '0.0', '0.1', '0.1', '0.0', '0.0', '0.0', '0.0', '0.3', '0.3', '0.0', '0.2', '0.2', '0.0', '0.2', '0.2', '0.0', '0.2', '0.2', '0.0', '0.0', '0.0', '0.0'], 'g': ['0.0', '0.3', '0.3', '0.0', '0.0', '0.0', '0.05', '0.0', '0.0', '0.05', '0.0', '0.0', '0.1', '0.0', '0.0', '0.05', '0.05', '0.05', '0.2', '0.0', '0.0', '0.0', '0.0', '0.0', '0.1', '0.0', '0.0', '0.1', '0.0', '0.0', '0.0', '0.2', '0.2', '0.0', '0.1', '0.1', '0.0', '0.1', '0.1', '0.0', '0.1', '0.1', '0.0', '0.0', '0.0', '0.0', '0.1', '0.1', '0.0', '0.2', '0.2', '0.0', '0.1', '0.1', '0.0', '0.1', '0.1', '0.0', '0.0', '0.0', '0.0']}) def __init__(self): super().__init__() geom = QApplication.desktop().availableGeometry() self.setGeometry(QRect(round(geom.width() * 0.05), round(geom.height() * 0.05), round(min(geom.width() * 0.98, self.WIDGET_WIDTH)), round(min(geom.height() * 0.95, self.WIDGET_HEIGHT)))) gen_box = ShadowGui.widgetBox(self.controlArea, "Waviness Parameters", addSpace=True, orientation="horizontal", width=500) tabs_setting = gui.tabWidget(gen_box) tab_input = ShadowGui.createTabPage(tabs_setting, "Input Parameter") tab_harmonics = ShadowGui.createTabPage(tabs_setting, "Harmonics") tab_out = ShadowGui.createTabPage(tabs_setting, "Output") self.input_box = ShadowGui.widgetBox(tab_input, "Inputs", addSpace=True, orientation="vertical", width=470) gui.button(self.input_box, self, "Load xsh_waviness input file ...", callback=self.load_inp_file) gui.separator(self.input_box) ShadowGui.lineEdit(self.input_box, self, "number_of_points_x", "Number of Points (<201) X (width)", labelWidth=300, valueType=int, orientation="horizontal") ShadowGui.lineEdit(self.input_box, self, "number_of_points_y", " Y (length)", labelWidth=300, valueType=int, orientation="horizontal") gui.separator(self.input_box) ShadowGui.lineEdit(self.input_box, self, "dimension_x", "Dimensions [cm] X (width)", labelWidth=300, valueType=float, orientation="horizontal") ShadowGui.lineEdit(self.input_box, self, "dimension_y", " Y (length)", labelWidth=300, valueType=float, orientation="horizontal") gui.separator(self.input_box) ShadowGui.lineEdit(self.input_box, self, "estimated_slope_error", "Estimated slope error [arcsec]", labelWidth=300, valueType=float, orientation="horizontal") ShadowGui.lineEdit(self.input_box, self, "montecarlo_seed", "Monte Carlo initial seed", labelWidth=300, valueType=int, orientation="horizontal") self.output_box = ShadowGui.widgetBox(tab_input, "Outputs", addSpace=True, orientation="vertical", width=470) self.select_file_box = ShadowGui.widgetBox(self.output_box, "", addSpace=True, orientation="horizontal") gui.separator(self.output_box) gui.button(self.output_box, self, "Write xsh_waviness input file (optional) ...", callback=self.write_inp_file) ShadowGui.lineEdit(self.select_file_box, self, "waviness_file_name", "Output File Name", labelWidth=120, valueType=str, orientation="horizontal") self.harmonics_box = ShadowGui.widgetBox(tab_harmonics, "Harmonics", addSpace=True, orientation="vertical", width=470, height=690) ShadowGui.lineEdit(self.harmonics_box, self, "harmonic_maximum_index", "Harmonic Maximum Index", labelWidth=300, valueType=int, orientation="horizontal", callback=self.set_harmonics) gui.separator(self.harmonics_box) self.scrollarea = QScrollArea() self.scrollarea.setMaximumWidth(400) self.harmonics_box.layout().addWidget(self.scrollarea, alignment=Qt.AlignHCenter) self.shadow_output = QTextEdit() self.shadow_output.setReadOnly(True) out_box = ShadowGui.widgetBox(tab_out, "System Output", addSpace=True, orientation="horizontal", height=600) out_box.layout().addWidget(self.shadow_output) button_box = ShadowGui.widgetBox(self.controlArea, "", addSpace=False, orientation="horizontal") button = gui.button(button_box, self, "Calculate Waviness", callback=self.calculate_waviness) button.setFixedHeight(45) button.setFixedWidth(170) button = gui.button(button_box, self, "Generate Waviness File", callback=self.generate_waviness_file) font = QFont(button.font()) font.setBold(True) button.setFont(font) palette = QPalette(button.palette()) # make a copy of the palette palette.setColor(QPalette.ButtonText, QColor('Dark Blue')) button.setPalette(palette) # assign new palette button.setFixedHeight(45) button.setFixedWidth(200) button = gui.button(button_box, self, "Reset Fields", callback=self.call_reset_settings) font = QFont(button.font()) font.setItalic(True) button.setFont(font) palette = QPalette(button.palette()) # make a copy of the palette palette.setColor(QPalette.ButtonText, QColor('Dark Red')) button.setPalette(palette) # assign new palette button.setFixedHeight(45) button.setFixedWidth(120) gui.rubber(self.controlArea) self.figure = Figure(figsize=(600, 600)) self.figure.patch.set_facecolor('white') self.axis = self.figure.add_subplot(111, projection='3d') self.axis.set_xlabel("X (cm)") self.axis.set_ylabel("Y (cm)") self.axis.set_zlabel("Z (µm)") self.figure_canvas = FigureCanvasQTAgg(self.figure) self.mainArea.layout().addWidget(self.figure_canvas) gui.rubber(self.mainArea) def restoreWidgetPosition(self): super().restoreWidgetPosition() self.table = QTableWidget(self.harmonic_maximum_index + 1, 3) self.table.setAlternatingRowColors(True) self.table.horizontalHeader().setResizeMode(QHeaderView.Fixed) for i in range(0, 3): self.table.setColumnWidth(i, 70) horHeaders = [] verHeaders = [] for n, key in enumerate(sorted(self.data.keys())): horHeaders.append(key) for m, item in enumerate(self.data[key]): table_item = QTableWidgetItem(str(item)) table_item.setTextAlignment(Qt.AlignRight) self.table.setItem(m, n, table_item) verHeaders.append(str(m)) self.table.setHorizontalHeaderLabels(horHeaders) self.table.setVerticalHeaderLabels(verHeaders) self.table.resizeRowsToContents() self.table.itemChanged.connect(self.table_item_changed) self.scrollarea.setWidget(self.table) self.scrollarea.setWidgetResizable(1) gui.rubber(self.controlArea) def reload_harmonics_table(self): horHeaders = [] verHeaders = [] self.table.itemChanged.disconnect(self.table_item_changed) self.table.clear() row_count = self.table.rowCount() for n in range(0, row_count): self.table.removeRow(0) for index in range(0, self.harmonic_maximum_index + 1): self.table.insertRow(0) for n, key in enumerate(sorted(self.data.keys())): horHeaders.append(key) for m, item in enumerate(self.data[key]): table_item = QTableWidgetItem(str(item)) table_item.setTextAlignment(Qt.AlignRight) self.table.setItem(m, n, table_item) verHeaders.append(str(m)) self.table.setHorizontalHeaderLabels(horHeaders) self.table.setVerticalHeaderLabels(verHeaders) self.table.resizeRowsToContents() for i in range(0, 3): self.table.setColumnWidth(i, 70) self.table.itemChanged.connect(self.table_item_changed) def table_item_changed(self): dict = {} message = "" error_row_index = -1 error_column_index = -1 previous_value = "" try: row_count = self.harmonic_maximum_index + 1 for column_index in range(0, self.table.columnCount()): column_name = self.table.horizontalHeaderItem(column_index).data(0) row_content = [] for row_index in range(0, row_count): if not self.table.item(row_index, column_index) is None: message = "Value at row " + str( row_index) + " and column \'" + column_name + "\' is not numeric" error_row_index = row_index error_column_index = column_index previous_value = self.data[column_name][row_index] value = float(self.table.item(row_index, column_index).data(0)) # to raise exception row_content.append(str(value)) dict[column_name] = row_content self.data = dict except ValueError: QMessageBox.critical(self, "QMessageBox.critical()", message + "\nValue is reset to previous value", QMessageBox.Ok) table_item = QTableWidgetItem(previous_value) table_item.setTextAlignment(Qt.AlignRight) self.table.setItem(error_row_index, error_column_index, table_item) self.table.setCurrentCell(error_row_index, error_column_index) except Exception as exception: QMessageBox.critical(self, "QMessageBox.critical()", exception.args[0], QMessageBox.Ok) def set_harmonics(self): if self.harmonic_maximum_index < 0: QMessageBox.critical(self, "QMessageBox.critical()", "Harmonic Maximum Index should be a positive integer number", QMessageBox.Ok) else: row_count = len(self.data["c"]) if self.harmonic_maximum_index + 1 > row_count: for n, key in enumerate(sorted(self.data.keys())): for m in range(row_count, self.harmonic_maximum_index + 1): self.data[key].append('0.0') else: for n, key in enumerate(sorted(self.data.keys())): self.data[key] = copy.deepcopy(self.data[key][0: self.harmonic_maximum_index + 1]) self.reload_harmonics_table() def load_inp_file(self): file_name = QFileDialog.getOpenFileName(self, "Select a input file for XSH_WAVINESS", ".", "*.inp") if not file_name is None: sys.stdout = EmittingStream(textWritten=self.writeStdOut) if not file_name.strip() == "": dict = ST.waviness_read(file=file_name) self.number_of_points_x = dict["npointx"] self.number_of_points_y = dict["npointy"] self.dimension_y = dict["xlength"] self.dimension_x = dict["width"] self.estimated_slope_error = dict["slp"] self.montecarlo_seed = dict["iseed"] self.waviness_file_name = dict["file"].strip('\n\r').strip() self.harmonic_maximum_index = dict["nharmonics"] self.data["c"] = self.to_str_array(dict["c"]) self.data["y"] = self.to_str_array(dict["y"]) self.data["g"] = self.to_str_array(dict["g"]) self.reload_harmonics_table() def write_inp_file(self): try: sys.stdout = EmittingStream(textWritten=self.writeStdOut) self.check_fields() file_name = self.waviness_file_name.strip().split(sep=".dat")[0] + ".inp" dict = {} dict["npointx"] = self.number_of_points_x dict["npointy"] = self.number_of_points_y dict["xlength"] = self.dimension_y dict["width"] = self.dimension_x dict["slp"] = self.estimated_slope_error dict["iseed"] = self.montecarlo_seed dict["file"] = self.waviness_file_name.strip('\n\r') dict["nharmonics"] = self.harmonic_maximum_index dict["c"] = self.to_float_array(self.data["c"]) dict["y"] = self.to_float_array(self.data["y"]) dict["g"] = self.to_float_array(self.data["g"]) ST.waviness_write(dict, file=file_name) QMessageBox.information(self, "QMessageBox.information()", "File \'" + file_name + "\' written to disk", QMessageBox.Ok) except Exception as exception: QMessageBox.critical(self, "QMessageBox.critical()", exception.args[0], QMessageBox.Ok) def calculate_waviness(self): try: sys.stdout = EmittingStream(textWritten=self.writeStdOut) self.check_fields() xx, yy, zz = ST.waviness_calc(npointx=self.number_of_points_x, npointy=self.number_of_points_y, width=self.dimension_x, xlength=self.dimension_y, slp=self.estimated_slope_error, nharmonics=self.harmonic_maximum_index, iseed=self.montecarlo_seed, c=self.to_float_array(self.data["c"]), y=self.to_float_array(self.data["y"]), g=self.to_float_array(self.data["g"])) self.xx = xx self.yy = yy self.zz = zz self.axis.clear() x_to_plot, y_to_plot = numpy.meshgrid(xx, yy) z_to_plot = [] for y_index in range(0, len(yy)): z_array = [] for x_index in range(0, len(xx)): z_array.append(1e4 * float(zz[x_index][y_index])) # to micron z_to_plot.append(z_array) z_to_plot = numpy.array(z_to_plot) self.axis.plot_surface(x_to_plot, y_to_plot, z_to_plot, rstride=1, cstride=1, cmap=cm.autumn, linewidth=0.5, antialiased=True) slope, sloperms = ST.slopes(zz, xx, yy) title = ' Slope error rms in X direction: %f arcsec' % (sloperms[0]) + '\n' + \ ' : %f urad' % (sloperms[2]) + '\n' + \ ' Slope error rms in Y direction: %f arcsec' % (sloperms[1]) + '\n' + \ ' : %f urad' % (sloperms[3]) self.axis.set_xlabel("X (cm)") self.axis.set_ylabel("Y (cm)") self.axis.set_zlabel("Z (µm)") self.axis.set_title(title) self.axis.mouse_init() self.figure_canvas.draw() QMessageBox.information(self, "QMessageBox.information()", "Waviness calculated: if the result is satisfactory,\nclick \'Generate Waviness File\' to complete the operation ", QMessageBox.Ok) except Exception as exception: QMessageBox.critical(self, "QMessageBox.critical()", exception.args[0], QMessageBox.Ok) def generate_waviness_file(self): if not self.zz is None and not self.yy is None and not self.xx is None: if not self.waviness_file_name is None: self.waviness_file_name = self.waviness_file_name.strip() if self.waviness_file_name == "": raise Exception("Output File Name missing") else: raise Exception("Output File Name missing") sys.stdout = EmittingStream(textWritten=self.writeStdOut) ST.write_shadow_surface(self.zz.T, self.xx, self.yy, outFile=self.waviness_file_name) QMessageBox.information(self, "QMessageBox.information()", "Waviness file " + self.waviness_file_name + " written on disk", QMessageBox.Ok) self.send("PreProcessor_Data", ShadowPreProcessorData(waviness_data_file=self.waviness_file_name)) def call_reset_settings(self): if ConfirmDialog.confirmed(parent=self, message="Confirm Reset of the Fields?"): try: self.resetSettings() self.reload_harmonics_table() except: pass def check_fields(self): self.number_of_points_x = ShadowGui.checkStrictlyPositiveNumber(self.number_of_points_x, "Number of Points X") self.number_of_points_y = ShadowGui.checkStrictlyPositiveNumber(self.number_of_points_y, "Number of Points Y") self.dimension_x = ShadowGui.checkStrictlyPositiveNumber(self.dimension_x, "Dimension X") self.dimension_y = ShadowGui.checkStrictlyPositiveNumber(self.dimension_y, "Dimension Y") self.estimated_slope_error = ShadowGui.checkPositiveNumber(self.estimated_slope_error, "Estimated slope error") self.montecarlo_seed = ShadowGui.checkPositiveNumber(self.montecarlo_seed, "Monte Carlo initial seed") self.harmonic_maximum_index = ShadowGui.checkPositiveNumber(self.harmonic_maximum_index, "Harmonic Maximum Index") if not self.waviness_file_name is None: self.waviness_file_name = self.waviness_file_name.strip() if self.waviness_file_name == "": raise Exception("Output File Name missing") else: raise Exception("Output File Name missing") def to_float_array(self, string_array): float_array = [] for index in range(len(string_array)): float_array.append(float(string_array[index])) return float_array def to_str_array(self, float_array): string_array = [] for index in range(len(float_array)): string_array.append(str(float_array[index])) return string_array def writeStdOut(self, text): cursor = self.shadow_output.textCursor() cursor.movePosition(QTextCursor.End) cursor.insertText(text) self.shadow_output.setTextCursor(cursor) self.shadow_output.ensureCursorVisible()
class GroupsPostView(QDialog): """ +------------------------+ | Groups : Post/Delete | +------------------------+ | | | check1 Name1 | | check2 Name2 | | check3 Name3 | | | | SetAsMain | | Apply OK Close | +------------------------+ """ def __init__(self, data, win_parent=None): self.win_parent = win_parent #Init the base class groups = data['groups'] inames = data['inames'] self.imain = data['imain'] self.names = [group.name for group in groups] self.white = (255, 255, 255) self.light_grey = (211, 211, 211) self.inames = inames self.shown_set = data['shown'] self.deleted_groups = set([]) #self.inames = argsort(self.names) #print('inames =', inames) anames = array(self.names) for iname, name in enumerate(anames[self.inames]): print('name[%s] = %r' % (iname, name)) # ignore these... #self._default_name = data['name'] #self._default_coords = data['coords'] #self._default_elements = data['elements'] #self._default_color = data['color'] #self.coords_pound = data['coords_pound'] #self.elements_pound = data['elements_pound'] #self._default_is_discrete = data['is_discrete'] self.out_data = data QDialog.__init__(self, win_parent) #self.setupUi(self) self.setWindowTitle('Groups: Post/View') self.create_widgets() self.create_layout() self.set_connections() #self.show() def create_widgets(self): # main/delete/supergroup self.set_as_main_button = QPushButton("Set As Main") self.create_super_group_button = QPushButton("Create Super Group") self.delete_groups_button = QPushButton("Delete Groups") self.revert_groups_button = QPushButton("Revert Groups") self.show_groups_button = QPushButton("Show Groups") self.hide_groups_button = QPushButton("Hide Groups") # closing self.apply_button = QPushButton("Apply") self.ok_button = QPushButton("OK") self.cancel_button = QPushButton("Cancel") #table self.table = QTableWidget() self.checks = [] self.names_text = [] bold = QtGui.QFont() bold.setBold(True) bold.setItalic(True) bold.setWeight(75) anames = array(self.names) for iname, name in enumerate(anames[self.inames]): check = QTableWidgetItem() check.setCheckState(False) # TODO: create right click menu ??? name_text = QTableWidgetItem(str(name)) if iname == self.imain: name_text.setFont(bold) self.shown_set.add(iname) check.setCheckState(2) name_text.setBackground(QtGui.QColor(*self.light_grey)) elif iname in self.shown_set: name_text.setBackground(QtGui.QColor(*self.light_grey)) self.checks.append(check) self.names_text.append(name_text) def create_layout(self): nrows = len(self.names) table = self.table table.setRowCount(nrows) table.setColumnCount(2) headers = [QString('Operate On'), QString('Name')] table.setHorizontalHeaderLabels(headers) header = table.horizontalHeader() header.setStretchLastSection(True) #table.setAlternatingRowColors(True) #header = table.verticalHeader() #header.setStretchLastSection(True) #table.resize(400, 250) #heighti = table.rowHeight(0) #total_height = nrows * heighti #table.setMaximumHeight(total_height) #table.resize(total_height, None) #for iname, name in enumerate(self.names[self.inames]): #print('name[%s] = %r' % (iname, name)) for iname in self.inames: check = self.checks[iname] name_text = self.names_text[iname] # row, col, value table.setItem(iname, 0, check) table.setItem(iname, 1, name_text) table.resizeRowsToContents() #table.horizontalHeaderItem(1).setTextAlignment(QtCore.AlignHCenter) #= QVBoxLayout() ok_cancel_box = QHBoxLayout() ok_cancel_box.addWidget(self.apply_button) ok_cancel_box.addWidget(self.ok_button) ok_cancel_box.addWidget(self.cancel_button) vbox = QVBoxLayout() vbox.addWidget(table) vbox.addWidget(self.set_as_main_button) #vbox.addWidget(self.create_super_group_button) vbox.addStretch() vbox.addWidget(self.show_groups_button) vbox.addWidget(self.hide_groups_button) vbox.addStretch() vbox.addWidget(self.delete_groups_button) vbox.addWidget(self.revert_groups_button) vbox.addStretch() vbox.addStretch() vbox.addLayout(ok_cancel_box) self.setLayout(vbox) def set_connections(self): if qt_version == 4: self.connect(self.set_as_main_button, QtCore.SIGNAL('clicked()'), self.on_set_as_main) self.connect(self.delete_groups_button, QtCore.SIGNAL('clicked()'), self.on_delete_groups) self.connect(self.revert_groups_button, QtCore.SIGNAL('clicked()'), self.on_revert_groups) self.connect(self.show_groups_button, QtCore.SIGNAL('clicked()'), self.on_show_groups) self.connect(self.hide_groups_button, QtCore.SIGNAL('clicked()'), self.on_hide_groups) self.connect(self.create_super_group_button, QtCore.SIGNAL('clicked()'), self.on_create_super_group) self.connect(self.apply_button, QtCore.SIGNAL('clicked()'), self.on_apply) self.connect(self.ok_button, QtCore.SIGNAL('clicked()'), self.on_ok) self.connect(self.cancel_button, QtCore.SIGNAL('clicked()'), self.on_cancel) else: self.set_as_main_button.clicked.connect(self.on_set_as_main) self.delete_groups_button.clicked.connect(self.on_delete_groups) self.revert_groups_button.clicked.connect(self.on_revert_groups) self.show_groups_button.clicked.connect(self.on_show_groups) self.hide_groups_button.clicked.connect(self.on_hide_groups) self.create_super_group_button.clicked.connect(self.on_create_super_group) self.apply_button.clicked.connect(self.on_apply) self.ok_button.clicked.connect(self.on_ok) self.cancel_button.clicked.connect(self.on_cancel) def closeEvent(self, event): event.accept() @property def nrows(self): return self.table.rowCount() def on_hide_groups(self): self._set_highlight(self.white) def on_show_groups(self): self._set_highlight(self.light_grey) def _set_highlight(self, color): for irow in range(self.nrows): check = self.checks[irow] is_checked = check.checkState() # 0 - unchecked # 1 - partially checked (invalid) # 2 - checked if is_checked: name_text = self.names_text[irow] name_text.setBackground(QtGui.QColor(*color)) def on_delete_groups(self): for irow in range(self.nrows): check = self.checks[irow] is_checked = check.checkState() # 0 - unchecked # 1 - partially checked (invalid) # 2 - checked if irow == 0 and is_checked: # TODO: change this to a log print('error deleting group ALL...change this to a log') #self.window_parent.log return if is_checked: self.table.hideRow(irow) self.deleted_groups.add(irow) check.setCheckState(0) if self.imain > 0 and self.shown_set == set([0]): bold = QtGui.QFont() bold.setBold(True) bold.setItalic(True) self.imain = 0 irow = 0 check = self.checks[irow] name_text = self.names_texts[irow] name_text.setFont(bold) name_text.setBackground(QtGui.QColor(*self.light_grey)) def on_revert_groups(self): for irow in range(self.nrows): self.table.showRow(irow) self.deleted_groups = set([]) def on_create_super_group(self): inames = [iname for iname, check in enumerate(self.checks) if bool(check.checkState())] if not len(inames): # TODO: add logging print('nothing is checked...') return if inames[0] == 0: # TODO: add logging print("cannot include 'ALL' in supergroup...") return name = 'SuperGroup' # popup gui and get a name irow = self.table.rowCount() self.table.insertRow(irow) check = QTableWidgetItem() check.setCheckState(False) name_text = QTableWidgetItem(str(name)) self.names.extend(name) self.names_text.append(name_text) self.checks.append(check) self.table.setItem(irow, 0, check) self.table.setItem(irow, 1, name_text) def on_set_as_main(self): bold = QtGui.QFont() bold.setBold(True) bold.setItalic(True) normal = QtGui.QFont() normal.setBold(False) normal.setItalic(False) imain = None imain_set = False for irow in range(self.nrows): check = self.checks[irow] name_text = self.names_text[irow] is_checked = check.checkState() # 0 - unchecked # 1 - partially checked (invalid) # 2 - checked if is_checked and not imain_set: # TODO: change this to a log #self.window_parent.log imain_set = True imain = irow name_text.setFont(bold) name_text.setBackground(QtGui.QColor(*self.light_grey)) self.shown_set.add(irow) elif irow == self.imain: name_text.setFont(normal) if irow == 0: name_text.setBackground(QtGui.QColor(*self.white)) if irow in self.shown_set: self.shown_set.remove(irow) elif imain == 0: name_text.setBackground(QtGui.QColor(*self.white)) self.shown_set.remove(imain) self.imain = imain def get_main_group(self): return self.imain def get_shown_group(self): return self.shown_set def get_deleted_groups(self): return self.deleted_groups def on_validate(self): flag0 = flag1 = flag2 = True main_group_id = self.get_main_group() shown_groups_ids = self.get_shown_group() deleted_group_ids = self.get_deleted_groups() if flag0 and flag1 and flag2: self.out_data['imain'] = main_group_id self.out_data['shown'] = shown_groups_ids self.out_data['remove'] = deleted_group_ids self.out_data['clicked_ok'] = True return True return False def on_apply(self): passed = self.on_validate() if passed: self.win_parent.on_post_group(self.out_data) def on_ok(self): passed = self.on_validate() if passed: self.close() #self.destroy() def on_cancel(self): self.close()
class FilesUIManager(QWidget): def __init__(self, winged, pref): QWidget.__init__(self) self.winged = winged self.pref = pref self._vbox = QVBoxLayout(self) self._hbox = QHBoxLayout() self._table = QTableWidget(1, 3) self._table.setHorizontalHeaderLabels(['Access', 'File Name', 'Size']) self._table.setSelectionBehavior(QAbstractItemView.SelectRows) self._table.verticalHeader().hide() self._table.removeRow(0) self._table.setColumnWidth(0, 80) self._table.setColumnWidth(1, 480) self._hbox.addWidget(self._table) self._btnDownload = QPushButton(QIcon(config.images['download']), '') self._btnDownload.setToolTip('Download') self._btnFacebook = QPushButton(QIcon(config.images['facebook']), '') self._btnFacebook.setToolTip('Share on Facebook') self._btnTwitter = QPushButton(QIcon(config.images['twitter']), '') self._btnTwitter.setToolTip('Share on Twitter') self._btnLink = QPushButton(QIcon(config.images['link']), '') self._btnLink.setToolTip('Copy Link') self.connect(self._btnDownload, SIGNAL("clicked()"), self._save) self.connect(self._btnFacebook, SIGNAL("clicked()"), self._facebook) self.connect(self._btnTwitter, SIGNAL("clicked()"), self._twitter) self.connect(self._btnLink, SIGNAL("clicked()"), self._copy_link) def _save(self): file_ = self._files[self._table.currentRow()] if file_['accesibility'] == '2': if self.pref.get('ask', True): folderName = str(QFileDialog.getExistingDirectory(self, 'Save File in...')) else: folderName = self.pref.get('folder', '') if folderName != '': self.winged.save_file(file_, folderName) else: QMessageBox.information(self, 'Download Fail', 'You can only download public files\nwith WingedBox-Client.') def _facebook(self): file_ = self._files[self._table.currentRow()] self.winged.thread.api.facebook(file_) def _twitter(self): file_ = self._files[self._table.currentRow()] self.winged.thread.api.twitter(file_) def _copy_link(self): clipboard = QApplication.clipboard() file = self._files[self._table.currentRow()] clipboard.setText('http://wingedbox.com/downloads/' + file['id'] + "-" + file['file-name']) def find(self, text): items = self._table.findItems(text, Qt.MatchContains) rows = [i.row() for i in items] rowsCount = range(self._table.rowCount()) rowsCount.reverse() for i in rowsCount: if i not in rows: self._table.removeRow(i) def load_table(self, files): self._files = files r = 0 for file in files: self._table.insertRow(r) if len(file['name']) > 0: item = QTableWidgetItem(file['name']) else: item = QTableWidgetItem(file['file-name']) item.setFlags( Qt.ItemIsSelectable | Qt.ItemIsEnabled ) self._table.setItem(r, 1, item) item = QTableWidgetItem(str(file['file-size'] / 1024) + ' kb') item.setFlags( Qt.ItemIsSelectable | Qt.ItemIsEnabled ) self._table.setItem(r, 2, item) imageFile = config.type.get(file['type'], config.typeBlank) access = config.access[file['accesibility']] item = QTableWidgetItem(QIcon(imageFile), access[3]) item.setBackgroundColor(QColor(access[0], access[1], access[2])) item.setFlags( Qt.ItemIsSelectable | Qt.ItemIsEnabled ) self._table.setItem(r, 0, item) r += 1 self._table.resizeRowsToContents() self._table.resizeColumnsToContents() self._table.horizontalHeader().setStretchLastSection(True)
class DataItemWidget(QWidget): __EXTRA_COLUMN_WIDTH = 20 def __init__(self, me_cls, data): QWidget.__init__(self) self.__me_cls = me_cls self.__setup_ui() self.__data = data self.__init_data() self.__connect_slot() def __setup_ui(self): v_layout = QVBoxLayout() self.__tool_widget = ToolWidget() self.__tool_widget.setMaximumHeight(40) self.__data_table_widget = QTableWidget() self.__data_table_widget.horizontalHeader().setStretchLastSection(True) self.__data_table_widget.horizontalHeader().setResizeMode( 0, QHeaderView.Fixed) v_layout.setSpacing(0) v_layout.setContentsMargins(0, 0, 0, 0) v_layout.addWidget(self.__tool_widget, 0) v_layout.addWidget(self.__data_table_widget, 1) self.setLayout(v_layout) def __connect_slot(self): pass #self.connect(self.__tool_widget,SIGNAL('refresh_btn_clicked()'), self ,SLOT('__on_refresh_signal()')) def __init_data(self): self.__data_table_widget.clearContents() # init header #self.__colume_names = yt_connection.get_table_colume_names(self.__table_name) self.__colume_names = [x.field.name for x in self.__me_cls.attributes] #self.__colume_names.insert(0,'entity_id') #print self.__colume_names self.__data_table_widget.setColumnCount(len(self.__colume_names)) head_list = QStringList() for colume in self.__colume_names: head_list << colume self.__data_table_widget.setHorizontalHeaderLabels(head_list) # default the header column both sides are coverd, these codes add __EXTRA_COLUMN_WIDTH to the header column width # and reise column width in function self.__adjust_table_colume() self.__data_table_widget.horizontalHeader().setResizeMode( QHeaderView.ResizeToContents) self.__record_colume_header_width() self.__data_table_widget.horizontalHeader().setResizeMode( QHeaderView.Interactive) self.__record_colume_header_width() show_data = [] for entity_id, value in self.__data.items(): item = value.obj_data.copy() item['managed_entity_id'] = entity_id show_data.append(item) self.__update_table(show_data) # init data # data = yt_connection.get_table_data(self.__table_name) # # self.__update_table(data) self.__adjust_table_colume() def __record_colume_header_width(self): count = self.__data_table_widget.columnCount() self.__column_widths = [] for i in range(count): self.__column_widths.append( self.__data_table_widget.columnWidth(i) + self.__EXTRA_COLUMN_WIDTH) ''' data like this [ {u'direction': 'to-lport', u'name': '[]', u'priority': '100', u'log': 'true', u'action': 'drop', u'external_ids': '{"neutron:lport"="5fb77332-2035-4f72-8e57-7415b02489c9"}', u'match': '"outport==\\"inside-vm2\\""', u'severity': '[]', 'uuid': '2890a832-1c83-4b8e-8b40-2928817012cc'} ] ''' def __update_table(self, data): self.__data_table_widget.clearContents() row_num = 0 for row in data: self.__data_table_widget.insertRow(row_num) colume_num = 0 for colume in self.__colume_names: if row.has_key(colume): item_str = str(row[colume]) else: item_str = 'None' table_wid_item = QTableWidgetItem(item_str) table_wid_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) self.__data_table_widget.setItem(row_num, colume_num, table_wid_item) colume_num += 1 row_num += 1 def __clear_table_data(self): row_count = self.__data_table_widget.rowCount() rev = [i for i in range(row_count)] rev.reverse() for i in rev: self.__data_table_widget.removeRow(i) def __adjust_table_colume(self): self.__data_table_widget.resizeColumnsToContents() count = self.__data_table_widget.columnCount() for i in range(count): col_wid = self.__data_table_widget.columnWidth(i) if col_wid < self.__column_widths[i]: self.__data_table_widget.setColumnWidth( i, self.__column_widths[i])
class NewRelationDialog(QDialog): def __init__(self, parent=None): QDialog.__init__(self, parent) self.setWindowTitle(self.tr("Nueva Relación")) vbox = QVBoxLayout(self) hbox = QHBoxLayout() self._line_relation_name = QLineEdit() hbox.addWidget(QLabel(self.tr("Nombre:"))) hbox.addWidget(self._line_relation_name) vbox.addLayout(hbox) vbox.addWidget(QLabel( self.tr("La primera fila corresponde a los campos"))) hbox = QHBoxLayout() btn_add_column = QPushButton(self.tr("Agregar Columna")) hbox.addWidget(btn_add_column) btn_add_tuple = QPushButton(self.tr("Agregar Tupla")) hbox.addWidget(btn_add_tuple) btn_remove_column = QPushButton(self.tr("Eliminar Columna")) hbox.addWidget(btn_remove_column) btn_remove_tuple = QPushButton(self.tr("Eliminar Tupla")) hbox.addWidget(btn_remove_tuple) vbox.addLayout(hbox) self._table = QTableWidget() vbox.addWidget(self._table) self._table.setRowCount(1) self._table.setColumnCount(2) self._table.setItem(0, 0, QTableWidgetItem("Campo 1")) self._table.setItem(0, 1, QTableWidgetItem("Campo 2")) hbox = QHBoxLayout() hbox.addItem(QSpacerItem(1, 0, QSizePolicy.Expanding)) btn_ok = QPushButton(self.tr("Aceptar")) hbox.addWidget(btn_ok) btn_cancel = QPushButton(self.tr("Cancelar")) hbox.addWidget(btn_cancel) vbox.addLayout(hbox) # Connections self.connect(btn_add_column, SIGNAL("clicked()"), self.__add_column) self.connect(btn_remove_column, SIGNAL("clicked()"), self.__remove_column) self.connect(btn_add_tuple, SIGNAL("clicked()"), self.__add_tuple) self.connect(btn_remove_tuple, SIGNAL("clicked()"), self.__remove_tuple) self.connect(btn_ok, SIGNAL("clicked()"), self.__create_table) self.connect(btn_cancel, SIGNAL("clicked()"), self.close) def __add_column(self): columns = self._table.columnCount() self._table.insertColumn(columns) def __remove_column(self): current = self._table.currentColumn() self._table.removeColumn(current) def __add_tuple(self): tuples = self._table.rowCount() self._table.insertRow(tuples) def __remove_tuple(self): current = self._table.currentRow() self._table.removeRow(current) def __create_table(self): name = self._line_relation_name.text() rows = self._table.rowCount() columns = self._table.columnCount() rel = relation.Relation() fields = [self._table.item(0, i).text() for i in range(columns)] rel.fields = fields data = {} for row in range(1, rows): reg = [] for column in range(columns): reg.append(self._table.item(row, column).text()) data[row, column] = self._table.item(row, column).text() rel.insert(reg) table_widget = Pireal.get_service("container").table_widget table_widget.add_table(rows - 1, columns, name, data) #table_widget.relations[name] = rel self.close()
class daq_window(QMainWindow): """Window to control and visualise DAQ measurements. Set up the desired channels with a given sampling rate. Start an acquisition after a trigger. Display the acquired data on a trace, and accumulated data on a graph. Arguments: n -- run number for synchronisation rate -- max sample rate in samples / second dt -- desired acquisition period in seconds config_file -- path to file storing default settings port -- the port number to open for TCP connections """ def __init__(self, n=0, rate=250, dt=500, config_file='monitor\\daqconfig.dat', port=8622): super().__init__() self.types = OrderedDict([('n', int), ('config_file', str), ('trace_file', str), ('graph_file', str), ('save_dir', str), ('Sample Rate (kS/s)',float), ('Duration (ms)', float), ('Trigger Channel', str), ('Trigger Level (V)', float), ('Trigger Edge', str), ('channels',channel_stats)]) self.stats = OrderedDict([('n', n), ('config_file', config_file), ('trace_file', 'DAQtrace.csv'), ('graph_file', 'DAQgraph.csv'),('save_dir', '.'), ('Sample Rate (kS/s)', rate), ('Duration (ms)', dt), ('Trigger Channel', 'Dev2/ai1'), # /Dev2/PFI0 ('Trigger Level (V)', 1.0), ('Trigger Edge', 'rising'), ('channels', channel_stats("[['Dev2/ai0', '0', '1.0', '0.0', '5', '1', '1']]"))]) self.trigger_toggle = True # whether to trigger acquisition or just take a measurement self.slave = worker(rate*1e3, dt/1e3, self.stats['Trigger Channel'], self.stats['Trigger Level (V)'], self.stats['Trigger Edge'], list(self.stats['channels'].keys()), [ch['range'] for ch in self.stats['channels'].values()]) # this controls the DAQ self.dc = daqCollection(param=[], channels=list(self.stats['channels'].keys())) self.init_UI() self.load_config(config_file) # load default settings self.n_samples = int(self.stats['Duration (ms)'] * self.stats['Sample Rate (kS/s)']) # number of samples per acquisition self.last_path = './' self.x = [] # run numbers for graphing collections of acquired data self.y = [] # average voltages in slice of acquired trace self.slave.acquired.connect(self.update_graph) # take average of slices self.slave.acquired.connect(self.update_trace) # plot new data when it arrives self.tcp = PyClient(port=port) remove_slot(self.tcp.dxnum, self.set_n, True) remove_slot(self.tcp.textin, self.respond, True) self.tcp.start() def init_UI(self): """Produce the widgets and buttons.""" self.centre_widget = QWidget() self.tabs = QTabWidget() # make tabs for each main display self.centre_widget.layout = QVBoxLayout() self.centre_widget.layout.addWidget(self.tabs) self.centre_widget.setLayout(self.centre_widget.layout) self.setCentralWidget(self.centre_widget) # change font size font = QFont() font.setPixelSize(18) #### menubar at top gives options #### menubar = self.menuBar() # file menubar allows you to save/load data file_menu = menubar.addMenu('File') for label, function in [['Load Config', self.load_config], ['Save Config', self.save_config], ['Load Trace', self.load_trace], ['Save Trace', self.save_trace], ['Save Graph', self.save_graph]]: action = QAction(label, self) action.triggered.connect(function) file_menu.addAction(action) #### tab for settings #### settings_tab = QWidget() settings_grid = QGridLayout() settings_tab.setLayout(settings_grid) self.tabs.addTab(settings_tab, "Settings") self.settings = QTableWidget(1, 6) self.settings.setHorizontalHeaderLabels(['Duration (ms)', 'Sample Rate (kS/s)', 'Trigger Channel', 'Trigger Level (V)', 'Trigger Edge', 'Use Trigger?']) settings_grid.addWidget(self.settings, 0,0, 1,1) defaults = [str(self.stats['Duration (ms)']), str(self.stats['Sample Rate (kS/s)']), self.stats['Trigger Channel'], str(self.stats['Trigger Level (V)']), self.stats['Trigger Edge'], '1'] validators = [double_validator, double_validator, None, double_validator, None, bool_validator] for i in range(6): table_item = QLineEdit(defaults[i]) # user can edit text to change the setting if defaults[i] == 'Sample Rate (kS/s)': table_item.setEnabled(False) table_item.setValidator(validators[i]) # validator limits the values that can be entered self.settings.setCellWidget(0,i, table_item) self.settings.resizeColumnToContents(1) self.settings.setFixedHeight(70) # make it take up less space self.settings.cellWidget(0,0).textChanged.connect(self.check_slice_duration) # start/stop: start waiting for a trigger or taking an acquisition self.toggle = QPushButton('Start', self) self.toggle.setCheckable(True) self.toggle.clicked.connect(self.activate) settings_grid.addWidget(self.toggle, 1,0, 1,1) # channels self.channels = QTableWidget(8, 7) # make table self.channels.setHorizontalHeaderLabels(['Channel', 'Label', 'Scale (X/V)', 'Offset (V)', 'Range', 'Acquire?', 'Plot?']) settings_grid.addWidget(self.channels, 2,0, 1,1) validators = [None, double_validator, double_validator, None, bool_validator, bool_validator] for i in range(8): chan = 'Dev2/ai'+str(i) # name of virtual channel table_item = QLabel(chan) self.channels.setCellWidget(i,0, table_item) if chan in self.stats['channels']: # load values from previous defaults = self.stats['channels'][chan] else: # default values when none are loaded defaults = channel_stats("[dummy, "+str(i)+", 1.0, 0.0, 5.0, 0, 0]")['dummy'] for j, key in zip([0,1,2,4,5], ['label', 'scale', 'offset', 'acquire', 'plot']): table_item = QLineEdit(str(defaults[key])) if 'acquire' in key: table_item.textChanged.connect(self.check_slice_channels) elif 'plot' in key: table_item.textChanged.connect(self.set_acquire) table_item.setValidator(validators[j]) self.channels.setCellWidget(i,j+1, table_item) vrange = QComboBox() # only allow certain values for voltage range vrange.text = vrange.currentText # overload function so it's same as QLabel vrange.addItems(['%.1f'%x for x in self.slave.vrs]) try: vrange.setCurrentIndex(self.slave.vrs.index(defaults['range'])) except Exception as e: logger.error('Invalid channel voltage range\n'+str(e)) self.channels.setCellWidget(i,4, vrange) #### Plot for most recently acquired trace #### trace_tab = QWidget() trace_grid = QGridLayout() trace_tab.setLayout(trace_grid) self.tabs.addTab(trace_tab, "Trace") # button activates horizontal line self.hline_toggle = QPushButton('Horizontal line', self, checkable=True) self.hline_toggle.clicked.connect(self.add_horizontal) trace_grid.addWidget(self.hline_toggle, 0,0, 1,1) self.hline_label = QLabel() trace_grid.addWidget(self.hline_label, 0,1, 1,1) fadeline_button = QPushButton('Persist', self) fadeline_button.clicked.connect(self.set_fadelines) trace_grid.addWidget(fadeline_button, 0,2, 1,1) # plot the trace self.trace_canvas = pg.PlotWidget() self.trace_legend = self.trace_canvas.addLegend() self.trace_canvas.getAxis('bottom').tickFont = font self.trace_canvas.getAxis('left').tickFont = font self.trace_canvas.setLabel('bottom', 'Time', 's', **{'font-size':'18pt'}) self.trace_canvas.setLabel('left', 'Voltage', 'V', **{'font-size':'18pt'}) self.lines = [] # handles for lines plotting the last measurement self.fadelines = [] # handles for previous measurement lines for i in range(8): chan = self.channels.cellWidget(i,1).text() self.lines.append(self.trace_canvas.plot([1], name=chan, pen=pg.mkPen(pg.intColor(i), width=3))) self.lines[i].hide() self.fadelines.append(self.trace_canvas.plot([1], pen=pg.mkPen(pg.intColor(i, alpha=50), width=2))) self.fadelines[i].hide() self.hline = pg.InfiniteLine(1., angle=0, pen='k', movable=True) self.trace_canvas.addItem(self.hline) self.hline.sigPositionChanged.connect(self.update_hline) self.hline.hide() trace_grid.addWidget(self.trace_canvas, 1,0, 1,3) #### Settings for slices of the trace accumulating into the graph #### slice_tab = QWidget() slice_grid = QGridLayout() slice_tab.setLayout(slice_grid) self.tabs.addTab(slice_tab, "Slice") # Buttons to add/remove slices and reset graph for i, (label, func) in enumerate([['Add slice', self.add_slice], ['Remove slice', self.del_slice], ['Reset graph', self.reset_graph]]): button = QPushButton(label, self) button.clicked.connect(func) slice_grid.addWidget(button, 0,i, 1,1) # parameters for slices self.slices = QTableWidget(0, 4) # make table self.slices.setHorizontalHeaderLabels(['Slice name', 'Start (ms)', 'End (ms)', 'Channels']) slice_grid.addWidget(self.slices, 1,0, 1,3) #### Plot for graph of accumulated data #### graph_tab = QWidget() graph_grid = QGridLayout() graph_tab.setLayout(graph_grid) self.tabs.addTab(graph_tab, "Graph") self.mean_graph = pg.PlotWidget() # for plotting means self.stdv_graph = pg.PlotWidget() # for plotting standard deviations self.graph_legends = [] for i, g in enumerate([self.mean_graph, self.stdv_graph]): g.getAxis('bottom').tickFont = font g.getAxis('bottom').setFont(font) g.getAxis('left').tickFont = font g.getAxis('left').setFont(font) graph_grid.addWidget(g, i,0, 1,1) self.reset_lines() # make a line for every slice channel self.stdv_graph.setLabel('bottom', 'Shot', '', **{'font-size':'18pt'}) self.stdv_graph.setLabel('left', 'Standard Deviation', 'V', **{'font-size':'18pt'}) self.mean_graph.setLabel('left', 'Mean', 'V', **{'font-size':'18pt'}) #### tab for TCP message settings #### tcp_tab = QWidget() tcp_grid = QGridLayout() tcp_tab.setLayout(tcp_grid) self.tabs.addTab(tcp_tab, "Sync") label = QLabel('Run number: ') tcp_grid.addWidget(label, 0,0, 1,1) self.n_edit = QLineEdit(str(self.stats['n'])) self.n_edit.setValidator(int_validator) self.n_edit.textEdited[str].connect(self.set_n) tcp_grid.addWidget(self.n_edit, 0,1, 1,1) label = QLabel('Save directory: ') tcp_grid.addWidget(label, 1,0, 1,1) self.save_edit = QLineEdit(self.stats['save_dir']) self.save_edit.textEdited[str].connect(self.set_save_dir) tcp_grid.addWidget(self.save_edit, 1,1, 1,1) label = QLabel('Trace file name: ') tcp_grid.addWidget(label, 2,0, 1,1) self.trace_edit = QLineEdit(self.stats['trace_file']) self.trace_edit.textEdited[str].connect(self.set_trace_file) tcp_grid.addWidget(self.trace_edit, 2,1, 1,1) label = QLabel('Graph file name: ') tcp_grid.addWidget(label, 3,0, 1,1) self.graph_edit = QLineEdit(self.stats['graph_file']) self.graph_edit.textEdited[str].connect(self.set_graph_file) tcp_grid.addWidget(self.graph_edit, 3,1, 1,1) reset = QPushButton('Reset TCP client', self) reset.clicked.connect(self.reset_client) tcp_grid.addWidget(reset, 4,0, 1,1) #### Title and icon #### self.setWindowTitle('- NI DAQ Controller -') self.setWindowIcon(QIcon('docs/daqicon.png')) self.setGeometry(200, 200, 800, 600) #### user input functions #### def set_acquire(self): """If the user chooses to plot, set the same channel to acquire.""" for i in range(self.channels.rowCount()): if BOOL(self.channels.cellWidget(i,6).text()): # plot self.channels.cellWidget(i,5).setText('1') # only plot if acquiring def check_settings(self): """Coerce the settings into allowed values.""" statstr = "[[" # dictionary of channel names and properties for i in range(self.channels.rowCount()): self.trace_legend.items[i][1].setText(self.channels.cellWidget(i,1).text()) # label if BOOL(self.channels.cellWidget(i,5).text()): # acquire statstr += ', '.join([self.channels.cellWidget(i,j).text() for j in range(self.channels.columnCount())]) + '],[' self.stats['channels'] = channel_stats(statstr[:-2] + ']') self.dc.channels = self.stats['channels'].keys() # acquisition settings self.stats['Duration (ms)'] = float(self.settings.cellWidget(0,0).text()) # check that the requested rate is valid rate = float(self.settings.cellWidget(0,1).text()) if len(self.stats['channels']) > 1 and rate > 245 / len(self.stats['channels']): rate = 245 / len(self.stats['channels']) elif len(self.stats['channels']) < 2 and rate > 250: rate = 250 self.stats['Sample Rate (kS/s)'] = rate self.settings.cellWidget(0,1).setText('%.2f'%(rate)) self.n_samples = int(self.stats['Duration (ms)'] * self.stats['Sample Rate (kS/s)']) # check the trigger channel is valid trig_chan = self.settings.cellWidget(0,2).text() if 'Dev2/PFI' in trig_chan or 'Dev2/ai' in trig_chan: self.stats['Trigger Channel'] = trig_chan else: self.stats['Trigger Channel'] = 'Dev2/ai0' self.settings.cellWidget(0,2).setText(str(self.stats['Trigger Channel'])) self.stats['Trigger Level (V)'] = float(self.settings.cellWidget(0,3).text()) self.stats['Trigger Edge'] = self.settings.cellWidget(0,4).text() self.trigger_toggle = BOOL(self.settings.cellWidget(0,5).text()) def set_table(self): """Display the acquisition and channel settings in the table.""" x = self.stats.copy() # prevent it getting overwritten for i in range(5): self.settings.cellWidget(0,i).setText(str(x[ self.settings.horizontalHeaderItem(i).text()])) for i in range(8): ch = self.channels.cellWidget(i,0).text() if ch in x['channels']: for j, key in zip([0,1,2,4,5], ['label', 'scale', 'offset', 'acquire', 'plot']): self.channels.cellWidget(i,j+1).setText(str(x['channels'][ch][key])) self.channels.cellWidget(i,4).setCurrentText('%.1f'%x['channels'][ch]['range']) else: self.channels.cellWidget(i,5).setText('0') # don't acquire self.channels.cellWidget(i,6).setText('0') # don't plot #### slice settings functions #### def add_slice(self, param=[]): """Add a row to the slice table and append it to the daqCollection instance for analysis. param -- [name, start (ms), end (ms), channels]""" try: name, start, end, channels = param except TypeError: name = 'Slice' + str(self.slices.rowCount()) start = 0 end = self.stats['Duration (ms)'] channels = list(self.stats['channels'].keys()) i = self.slices.rowCount() # index to add row at self.slices.insertRow(i) # add row to table validator = QDoubleValidator(0.,float(self.stats['Duration (ms)']),3) for j, text in enumerate([name, str(start), str(end)]): item = QLineEdit(text) item.pos = (i, j) if j > 0: item.setValidator(validator) item.textChanged.connect(self.update_slices) self.slices.setCellWidget(i, j, item) chanbox = QListWidget(self) chanbox.setSelectionMode(3) # extended selection, allows multiple selection chanbox.itemSelectionChanged.connect(self.update_slices) chanbox.pos = (i, 3) chanbox.text = chanbox.objectName chanlist = list(self.stats['channels'].keys()) chanbox.addItems(chanlist) self.slices.setCellWidget(i, j+1, chanbox) self.slices.resizeRowToContents(i) # add to the dc list of slices t = np.linspace(0, self.stats['Duration (ms)']/1000, self.n_samples) self.dc.add_slice(name, np.argmin(np.abs(t-start)), np.argmin(np.abs(t-end)), OrderedDict([(chan, chanlist.index(chan)) for chan in channels])) self.reset_lines() def del_slice(self, toggle=True): """Remove the slice at the selected row of the slice table.""" index = self.slices.currentRow() self.slices.removeRow(index) if index >= 0: self.dc.slices.pop(index) def check_slice_duration(self, newtxt): """If the acquisition duration is changed, make sure the slices can't use times beyond this.""" self.check_settings() # update DAQ acquisition settings first for i in range(self.slices.rowCount()): for j in [1,2]: # force slice to be within max duration validator = QDoubleValidator(0.,float(self.stats['Duration (ms)']),3) self.slices.cellWidget(i, j).setValidator(validator) def check_slice_channels(self, newtxt): """If the channels that can be used for the acquisition are changed, change the list widgets in the slice settings to match.""" self.check_settings() # update DAQ acquisition settings first for i in range(self.slices.rowCount()): w = self.slices.cellWidget(i, 3) # widget shorthand selected = [w.row(x) for x in w.selectedItems()] # make record of selected channels w.clear() w.addItems(list(self.stats['channels'].keys())) for r in selected: try: w.setCurrentRow(r, QItemSelectionModel.SelectCurrent) except Exception as e: pass def update_slices(self, newtxt=''): """Use the current item from the table to update the parameter for the slices.""" try: w = self.sender() i, j = w.pos t = np.linspace(0, self.stats['Duration (ms)'], self.n_samples) x = self.dc.slices[i] # shorthand if j == 0: # name x.name = w.text() elif j == 1: # start (ms) x.i0 = np.argmin(np.abs(t-float(w.text()))) elif j == 2: # end (ms) x.i1 = np.argmin(np.abs(t-float(w.text()))) elif j == 3: x.channels = OrderedDict([(x.text(), w.row(x)) for x in w.selectedItems()]) x.stats = OrderedDict([(chan, OrderedDict([ ('mean',[]), ('stdv',[])])) for chan in x.channels.keys()]) self.reset_lines() self.reset_graph() x.inds = slice(x.i0, x.i1+1) x.size = x.i1 - x.i0 except IndexError as e: pass # logger.error("Couldn't update slice.\n"+str(e)) #### TCP functions #### def set_n(self, num): """Receive the new run number to update to""" self.stats['n'] = int(num) self.n_edit.setText(str(num)) def set_save_dir(self, directory): """Set the directory to save results to""" self.stats['save_dir'] = directory self.save_edit.setText(directory) def set_trace_file(self, fname): """Set the default name for trace files when they're saved.""" self.stats['trace_file'] = fname self.trace_edit.setText(fname) def set_graph_file(self, fname): """Set the default name for graph files when they're saved.""" self.stats['graph_file'] = fname self.graph_edit.setText(fname) def reset_client(self, toggle=True): """Stop the TCP client thread then restart it.""" self.tcp.stop = True for i in range(100): # wait til it's stopped if not self.tcp.isRunning(): break else: time.sleep(0.001) self.tcp.start() # restart def respond(self, msg=''): """Interpret a TCP message. For setting properties, the syntax is: value=property. E.g. 'Z:\Tweezer=save_dir'.""" if 'save_dir' in msg: self.set_save_dir(msg.split('=')[0]) elif 'trace_file' in msg: self.set_trace_file(msg.split('=')[0]) elif 'graph_file' in msg: self.set_graph_file(msg.split('=')[0]) elif 'start' in msg and not self.toggle.isChecked(): self.toggle.setChecked(True) self.activate() elif 'stop' in msg and self.toggle.isChecked(): self.toggle.setChecked(False) self.activate() elif 'save trace' in msg: self.save_trace(os.path.join(self.stats['save_dir'], self.stats['trace_file'])) elif 'save graph' in msg: self.save_graph(os.path.join(self.stats['save_dir'], self.stats['graph_file'])) elif 'set fadelines' in msg: self.set_fadelines() #### acquisition functions #### def activate(self, toggle=0): """Prime the DAQ task for acquisition if it isn't already running. Otherwise, stop the task running.""" if self.toggle.isChecked(): self.check_settings() self.slave = worker(self.stats['Sample Rate (kS/s)']*1e3, self.stats['Duration (ms)']/1e3, self.stats['Trigger Channel'], self.stats['Trigger Level (V)'], self.stats['Trigger Edge'], list(self.stats['channels'].keys()), [ch['range'] for ch in self.stats['channels'].values()]) remove_slot(self.slave.acquired, self.update_trace, True) remove_slot(self.slave.acquired, self.update_graph, True) if self.trigger_toggle: # remove_slot(self.slave.finished, self.activate, True) self.slave.start() self.toggle.setText('Stop') else: self.toggle.setChecked(False) self.slave.analogue_acquisition() else: # remove_slot(self.slave.finished, self.activate, False) self.slave.stop = True self.slave.quit() self.toggle.setText('Start') #### plotting functions #### def update_trace(self, data): """Plot the supplied data with labels on the trace canvas.""" t = np.linspace(0, self.stats['Duration (ms)']/1000, self.n_samples) i = 0 # index to keep track of which channels have been plotted for j in range(8): ch = self.channels.cellWidget(j,0).text() l = self.lines[j] # shorthand if ch in self.stats['channels'] and self.stats['channels'][ch]['plot']: try: l.setData(t, data[i]) except Exception as e: logger.error('DAQ trace could not be plotted.\n'+str(e)) self.fadelines[j].show() l.show() self.trace_legend.items[j][0].show() self.trace_legend.items[j][1].show() i += 1 else: l.hide() self.fadelines[j].hide() self.trace_legend.items[j][0].hide() self.trace_legend.items[j][1].hide() self.trace_legend.resize(0,0) def set_fadelines(self): """Take the data from the current lines and sets it to the fadelines.""" for j in range(8): ch = self.channels.cellWidget(j,0).text() l = self.lines[j] # shorthand if ch in self.stats['channels'] and self.stats['channels'][ch]['plot']: try: self.fadelines[j].setData(l.xData, l.yData) except Exception as e: logger.error('DAQ trace could not be plotted.\n'+str(e)) self.fadelines[j].show() else: self.fadelines[j].hide() def reset_lines(self): """Clear the mean and stdv graphs, reset the legends, then make new lines for each of the slice channels.""" for legend in self.graph_legends: # reset the legends try: legend.scene().removeItem(legend) except AttributeError: pass for g in [self.mean_graph, self.stdv_graph]: g.clear() g.lines = OrderedDict([]) self.graph_legends.append(g.addLegend()) i = 0 for s in self.dc.slices: for chan, val in s.stats.items(): g.lines[s.name+'/'+chan] = g.plot([1], name=s.name+'/'+chan, pen=None, symbol='o', symbolPen=pg.mkPen(pg.intColor(i)), symbolBrush=pg.intColor(i)) i += 1 def reset_graph(self): """Reset the collection of slice data, then replot the graph.""" self.dc.reset_arrays() self.update_graph() def update_graph(self, data=[]): """Extract averages from slices of the data. Replot the stored data accumulated from averages in slices of the measurements.""" if np.size(data): self.dc.process(data, self.stats['n']) for s in self.dc.slices: for chan, val in s.stats.items(): self.mean_graph.lines[s.name+'/'+chan].setData(self.dc.runs, val['mean']) self.stdv_graph.lines[s.name+'/'+chan].setData(self.dc.runs, val['stdv']) def add_horizontal(self, toggle=True): """Display a horizontal line on the trace""" if toggle: self.hline.show() else: self.hline.hide() self.hline_label.setText('') def update_hline(self): """Display the value of the horizontal line in the label""" self.hline_label.setText(str(self.hline.value())) #### save/load functions #### def try_browse(self, title='Select a File', file_type='all (*)', open_func=QFileDialog.getOpenFileName, default_path=''): """Open a file dialog and retrieve a file name from the browser. title: String to display at the top of the file browser window default_path: directory to open first file_type: types of files that can be selected open_func: the function to use to open the file browser""" default_path = default_path if default_path else os.path.dirname(self.last_path) try: if 'PyQt4' in sys.modules: file_name = open_func(self, title, default_path, file_type) elif 'PyQt5' in sys.modules: file_name, _ = open_func(self, title, default_path, file_type) if type(file_name) == str: self.last_path = file_name return file_name except OSError: return '' # probably user cancelled def save_config(self, file_name='daqconfig.dat'): """Save the current acquisition settings to the config file.""" self.stats['config_file'] = file_name if file_name else self.try_browse( 'Save Config File', 'dat (*.dat);;all (*)', QFileDialog.getSaveFileName) try: with open(self.stats['config_file'], 'w+') as f: for key, val in self.stats.items(): if key == 'channels': f.write(key+'='+channel_str(val)+'\n') else: f.write(key+'='+str(val)+'\n') logger.info('DAQ config saved to '+self.stats['config_file']) except Exception as e: logger.error('DAQ settings could not be saved to config file.\n'+str(e)) def load_config(self, file_name='daqconfig.dat'): """Load the acquisition settings from the config file.""" self.stats['config_file'] = file_name if file_name else self.try_browse(file_type='dat (*.dat);;all (*)') try: with open(self.stats['config_file'], 'r') as f: for line in f: if len(line.split('=')) == 2: key, val = line.replace('\n','').split('=') # there should only be one = per line try: self.stats[key] = self.types[key](val) except KeyError as e: logger.warning('Failed to load DAQ default config line: '+line+'\n'+str(e)) self.set_table() # make sure the updates are displayed self.set_n(self.stats['n']) self.set_save_dir(self.stats['save_dir']) self.set_trace_file(self.stats['trace_file']) self.set_graph_file(self.stats['graph_file']) self.dc.channels = list(self.stats['channels'].keys()) logger.info('DAQ config loaded from '+self.stats['config_file']) except FileNotFoundError as e: logger.warning('DAQ settings could not find the config file.\n'+str(e)) def save_trace(self, file_name=''): """Save the data currently displayed on the trace to a csv file.""" file_name = file_name if file_name else self.try_browse( 'Save File', 'csv (*.csv);;all (*)', QFileDialog.getSaveFileName) if file_name: # metadata header = ', '.join(list(self.stats.keys())) + '\n' header += ', '.join(list(map(str, self.stats.values()))[:-1] ) + ', ' + channel_str(self.stats['channels']) + '\n' # determine which channels are in the plot header += 'Time (s)' data = [] for key, d in self.stats['channels'].items(): if d['plot']: header += ', ' + key # column headings if len(data) == 0: # time (s) data.append(self.lines[int(key[-1])].xData) data.append(self.lines[int(key[-1])].yData) # voltage # data converted to the correct type out_arr = np.array(data).T try: np.savetxt(file_name, out_arr, fmt='%s', delimiter=',', header=header) logger.info('DAQ trace saved to '+file_name) except (PermissionError, FileNotFoundError) as e: logger.error('DAQ controller denied permission to save file: \n'+str(e)) def load_trace(self, file_name=''): """Load data for the current trace from a csv file.""" file_name = file_name if file_name else self.try_browse(file_type='csv(*.csv);;all (*)') if file_name: head = [[],[],[]] # get metadata with open(file_name, 'r') as f: for i in range(3): row = f.readline() if row[:2] == '# ': head[i] = row[2:].replace('\n','').split(', ') # apply the acquisition settings from the file labels = [self.settings.horizontalHeaderItem(i).text() for i in range(self.settings.columnCount())] for i in range(len(head[0])): try: j = labels.index(head[0][i]) self.settings.cellWidget(0,j).setText(head[1][i]) except ValueError: pass self.stats['channels'] = channel_stats(', '.join(head[1][7:])) for i in range(8): # whether to plot or not ch = self.channels.cellWidget(i,0).text() if ch in head[2]: self.channels.cellWidget(i,6).setText('1') self.channels.cellWidget(i,1).setText(self.stats['channels'][ch]['label']) else: self.channels.cellWidget(i,6).setText('0') self.check_settings() # plot the data data = np.genfromtxt(file_name, delimiter=',', dtype=float) if np.size(data) < 2: return 0 # insufficient data to load self.update_trace(data.T[1:]) def save_graph(self, file_name=''): """Save the data accumulated from several runs that's displayed in the graph into a csv file.""" file_name = file_name if file_name else self.try_browse( 'Save File', 'csv (*.csv);;all (*)', QFileDialog.getSaveFileName) if file_name: self.dc.save(file_name, list(self.stats.keys()), list(map(str, self.stats.values()))[:-1] + [channel_str(self.stats['channels'])]) logger.info('DAQ graph saved to '+file_name) def closeEvent(self, event): """Before closing, try to save the config settings to file.""" statstr = "[[" # dictionary of channel names and properties for i in range(self.channels.rowCount()): statstr += ', '.join([self.channels.cellWidget(i,j).text() for j in range(self.channels.columnCount())]) + '],[' self.stats['channels'] = channel_stats(statstr[:-2] + ']') # add all channels to stats self.save_config(self.stats['config_file']) event.accept()
class CameraWindow(PyDialog): def __init__(self, data, win_parent=None): """ +--------+ | Camera | +--------+---------------+ | Camera Name | | +-------------------+ | | | | | | | | | | | | | | | | | | | | | | +-------------------+ | | | | Name xxx Save | | Delete Set | | | | Apply OK Cancel | +--------+---------------+ """ PyDialog.__init__(self, data, win_parent) self.setWindowTitle('Camera Views') #self.setWindowIcon(view_icon) self._default_name = 'Camera' self.out_data['clicked_ok'] = False self.cameras = deepcopy(data['cameras']) self.names = sorted(self.cameras.keys()) self.name = QLabel("Name:") self.name_edit = QLineEdit(str(self._default_name)) self.delete_button = QPushButton("Delete") self.set_button = QPushButton("Set") self.save_button = QPushButton("Save") # closing self.apply_button = QPushButton("Apply") #self.ok_button = QPushButton("OK") self.close_button = QPushButton("Close") self.cancel_button = QPushButton("Cancel") self.table = QTableWidget() names_text = [] for iname, name in enumerate(self.names): name_text = QTableWidgetItem(str(name)) names_text.append(name_text) self.create_layout(names_text) self.set_connections() def create_layout(self, names_text): nrows = len(self.names) table = self.table table.setRowCount(nrows) table.setColumnCount(1) headers = [QString('Camera Name')] table.setHorizontalHeaderLabels(headers) header = table.horizontalHeader() header.setStretchLastSection(True) for iname, name_text in enumerate(names_text): # row, col, value table.setItem(iname, 0, name_text) table.resizeRowsToContents() ok_cancel_box = QHBoxLayout() ok_cancel_box.addWidget(self.apply_button) #ok_cancel_box.addWidget(self.ok_button) ok_cancel_box.addWidget(self.close_button) ok_cancel_box.addWidget(self.cancel_button) grid = QGridLayout() irow = 0 grid.addWidget(self.name, irow, 0) grid.addWidget(self.name_edit, irow, 1) grid.addWidget(self.save_button, irow, 2) irow += 1 grid.addWidget(self.delete_button, irow, 0) grid.addWidget(self.set_button, irow, 1) irow += 1 vbox = QVBoxLayout() vbox.addWidget(self.table) vbox.addLayout(grid) vbox.addStretch() vbox.addLayout(ok_cancel_box) self.setLayout(vbox) def set_connections(self): #if qt_version == 4: #self.connect(self.ok_button, QtCore.SIGNAL('clicked()'), self.on_ok) self.set_button.clicked.connect(self.on_set) self.save_button.clicked.connect(self.on_save) self.delete_button.clicked.connect(self.on_delete) self.apply_button.clicked.connect(self.on_apply) self.close_button.clicked.connect(self.on_close) self.cancel_button.clicked.connect(self.on_cancel) def on_set(self): objs = self.table.selectedIndexes() if len(objs) == 1: obj = objs[0] irow = obj.row() name = self.names[irow] self.set_camera(name) return True return False def on_save(self): name = str(self.name_edit.text()).strip() if name in self.cameras: return irow = self.nrows if len(name): self.table.insertRow(irow) name_text = QTableWidgetItem(str(name)) self.table.setItem(irow, 0, name_text) self.name_edit.setText('') self.save_camera(name) def set_camera(self, name): camera_data = self.cameras[name] if self.win_parent is None: return self.win_parent.on_set_camera_data(camera_data) def save_camera(self, name): self.names.append(name) if self.win_parent is None: self.cameras[name] = None return self.cameras[name] = self.win_parent.get_camera_data() #@property #def camera(self): @property def nrows(self): return self.table.rowCount() def on_delete(self): irows = [] for obj in self.table.selectedIndexes(): irow = obj.row() irows.append(irow) irows.sort() for irow in reversed(irows): self.table.removeRow(irow) #print('delete', self.names) name = self.names.pop(irow) del self.cameras[name] #print(' removing irow=%s name=%r' % (irow, name)) def closeEvent(self, event): event.accept() @staticmethod def check_name(cell): text = str(cell.text()).strip() if len(text): cell.setStyleSheet("QLineEdit{background: white;}") return text, True else: cell.setStyleSheet("QLineEdit{background: red;}") return None, False #def on_validate(self): #name_value, flag0 = self.check_name(self.name_edit) #if flag0: #self.out_data['cameras'] = self.cameras #self.out_data['clicked_ok'] = True #return True #return False def on_apply(self): passed = self.on_set() #if passed: # self.win_parent.create_plane(self.out_data) return passed def on_close(self): self.out_data['clicked_ok'] = True self.out_data['cameras'] = self.cameras self.close() def on_ok(self): passed = self.on_apply() if passed: name = str(self.name_edit.text()).strip() self.out_data['name'] = name self.out_data['cameras'] = self.cameras self.out_data['clicked_ok'] = True self.close() #self.destroy() def on_cancel(self): self.close()
class TemplateWindow(QMainWindow): def __init__(self, params_pipe, number_pipe, templates_pipe, spikes_pipe, probe_path=None, screen_resolution=None): QMainWindow.__init__(self) # Receive parameters. params = params_pipe[0].recv() self.probe = load_probe(probe_path) self._nb_samples = params['nb_samples'] self._sampling_rate = params['sampling_rate'] self._display_list = [] self._params = { 'nb_samples': self._nb_samples, 'sampling_rate': self._sampling_rate, 'time': { 'min': 10.0, # ms 'max': 100.0, # ms 'init': 100.0, # ms }, 'voltage': { 'min': -200, # µV 'max': 20e+1, # µV 'init': 50.0, # µV }, 'templates': self._display_list } self._canvas_mea = MEACanvas(probe_path=probe_path, params=self._params) self._canvas_template = TemplateCanvas(probe_path=probe_path, params=self._params) self._canvas_rate = RateCanvas(probe_path=probe_path, params=self._params) self._canvas_isi = ISICanvas(probe_path=probe_path, params=self._params) self.cells = Cells({}) self._nb_buffer = 0 # TODO ISI self.isi_bin_width, self.isi_x_max = 2, 25.0 canvas_template_widget = self._canvas_template.native canvas_mea = self._canvas_mea.native canvas_rate = self._canvas_rate.native canvas_isi = self._canvas_isi.native # Create controls widgets. label_time = QLabel() label_time.setText(u"time") label_time_unit = QLabel() label_time_unit.setText(u"ms") self._dsp_time = QDoubleSpinBox() self._dsp_time.setMinimum(self._params['time']['min']) self._dsp_time.setMaximum(self._params['time']['max']) self._dsp_time.setValue(self._params['time']['init']) self._dsp_time.valueChanged.connect(self._on_time_changed) label_voltage = QLabel() label_voltage.setText(u"voltage") label_voltage_unit = QLabel() label_voltage_unit.setText(u"µV") self._dsp_voltage = QDoubleSpinBox() self._dsp_voltage.setMinimum(self._params['voltage']['min']) self._dsp_voltage.setMaximum(self._params['voltage']['max']) self._dsp_voltage.setValue(self._params['voltage']['init']) self._dsp_voltage.valueChanged.connect(self._on_voltage_changed) label_binsize = QLabel() label_binsize.setText(u"Bin size") label_binsize_unit = QLabel() label_binsize_unit.setText(u"second") self._dsp_binsize = QDoubleSpinBox() self._dsp_binsize.setRange(0.1, 10) self._dsp_binsize.setSingleStep(0.1) self.bin_size = 1 self._dsp_binsize.setValue(self.bin_size) self._dsp_binsize.valueChanged.connect(self._on_binsize_changed) label_zoomrates = QLabel() label_zoomrates.setText(u'Zoom rates') self._zoom_rates = QDoubleSpinBox() self._zoom_rates.setRange(1, 50) self._zoom_rates.setSingleStep(0.1) self._zoom_rates.setValue(1) self._zoom_rates.valueChanged.connect(self._on_zoomrates_changed) label_time_window = QLabel() label_time_window.setText(u'Time window rates') label_time_window_unit = QLabel() label_time_window_unit.setText(u'second') self._dsp_tw_rate = QDoubleSpinBox() self._dsp_tw_rate.setRange(1, 50) self._dsp_tw_rate.setSingleStep(self.bin_size) self._dsp_tw_rate.setValue(50 * self.bin_size) self._dsp_tw_rate.valueChanged.connect(self._on_time_window_changed) label_tw_from_start = QLabel() label_tw_from_start.setText('Time scale from start') self._tw_from_start = QCheckBox() self._tw_from_start.setChecked(True) self._selection_templates = QTableWidget() self._selection_templates.setSelectionMode( QAbstractItemView.ExtendedSelection ) self._selection_templates.setColumnCount(3) self._selection_templates.setVerticalHeaderLabels(['Nb template', 'Channel', 'Amplitude']) self._selection_templates.insertRow(0) self._selection_templates.setItem(0, 0, QTableWidgetItem('Nb template')) self._selection_templates.setItem(0, 1, QTableWidgetItem('Channel')) self._selection_templates.setItem(0, 2, QTableWidgetItem('Amplitude')) # self._selection_channels.setGeometry(QtCore.QRect(10, 10, 211, 291)) # for i in range(self.nb_templates): # numRows = self.tableWidget.rowCount() # self.tableWidget.insertRow(numRows) # item = QTableWidgetItem("Template %i" % i) # self._selection_templates.addItem(item) # self._selection_templates.item(i).setSelected(False) spacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) # Create controls grid. grid = QGridLayout() # # Add time row. grid.addWidget(label_time, 0, 0) grid.addWidget(self._dsp_time, 0, 1) grid.addWidget(label_time_unit, 0, 2) # # Add voltage row. grid.addWidget(label_voltage, 1, 0) grid.addWidget(self._dsp_voltage, 1, 1) grid.addWidget(label_voltage_unit, 1, 2) # # Add binsize row. grid.addWidget(label_binsize, 2, 0) grid.addWidget(self._dsp_binsize, 2, 1) grid.addWidget(label_binsize_unit, 2, 2) # # Add zoom rate grid.addWidget(label_zoomrates, 3, 0) grid.addWidget(self._zoom_rates, 3, 1) # Add a double checkbox for time window grid.addWidget(label_time_window, 4, 0) grid.addWidget(self._dsp_tw_rate, 4, 1) grid.addWidget(label_time_window_unit, 4, 2) ## Add checkbox to display the rates from start grid.addWidget(label_tw_from_start, 5, 0) grid.addWidget(self._tw_from_start, 5, 1) # # Add spacer. grid.addItem(spacer) # # Create info group. controls_group = QGroupBox() controls_group.setLayout(grid) # Create info grid. templates_grid = QGridLayout() # # Add Channel selection # grid.addWidget(label_selection, 3, 0) templates_grid.addWidget(self._selection_templates, 0, 1) def add_template(): items = self._selection_templates.selectedItems() self._display_list = [] for i in range(len(items)): self._display_list.append(i) self._on_templates_changed() # self._selection_templates.itemClicked.connect(add_template) # Template selection signals self._selection_templates.itemSelectionChanged.connect(lambda: self.selected_templates( self.nb_templates)) # Checkbox to display all the rates self._tw_from_start.stateChanged.connect(self.time_window_rate_full) # self._selection_templates.itemPressed(0, 1).connect(self.sort_template()) # # Add spacer. templates_grid.addItem(spacer) # Create controls group. templates_group = QGroupBox() templates_group.setLayout(templates_grid) # # Create controls dock. templates_dock = QDockWidget() templates_dock.setWidget(templates_group) templates_dock.setWindowTitle("Channels selection") # # Create controls dock. control_dock = QDockWidget() control_dock.setWidget(controls_group) control_dock.setWindowTitle("Controls") # Create info widgets. label_time = QLabel() label_time.setText(u"time") self._label_time_value = QLineEdit() self._label_time_value.setText(u"0") self._label_time_value.setReadOnly(True) self._label_time_value.setAlignment(Qt.AlignRight) label_time_unit = QLabel() label_time_unit.setText(u"s") info_buffer_label = QLabel() info_buffer_label.setText(u"buffer") self._info_buffer_value_label = QLineEdit() self._info_buffer_value_label.setText(u"0") self._info_buffer_value_label.setReadOnly(True) self._info_buffer_value_label.setAlignment(Qt.AlignRight) info_buffer_unit_label = QLabel() info_buffer_unit_label.setText(u"") info_probe_label = QLabel() info_probe_label.setText(u"probe") info_probe_value_label = QLineEdit() info_probe_value_label.setText(u"{}".format(probe_path)) info_probe_value_label.setReadOnly(True) # TODO place the following info in another grid? info_probe_unit_label = QLabel() info_probe_unit_label.setText(u"") info_spacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) # Create info grid. info_grid = QGridLayout() # # Time row. info_grid.addWidget(label_time, 0, 0) info_grid.addWidget(self._label_time_value, 0, 1) info_grid.addWidget(label_time_unit, 0, 2) # # Buffer row. info_grid.addWidget(info_buffer_label, 1, 0) info_grid.addWidget(self._info_buffer_value_label, 1, 1) info_grid.addWidget(info_buffer_unit_label, 1, 2) # # Probe row. info_grid.addWidget(info_probe_label, 2, 0) info_grid.addWidget(info_probe_value_label, 2, 1) info_grid.addWidget(info_probe_unit_label, 2, 2) # # Spacer. info_grid.addItem(info_spacer) # Create info group. info_group = QGroupBox() info_group.setLayout(info_grid) # Create info dock. info_dock = QDockWidget() info_dock.setWidget(info_group) info_dock.setWindowTitle("Info") # Create thread. thread = Thread(number_pipe, templates_pipe, spikes_pipe) thread.number_signal.connect(self._number_callback) thread.reception_signal.connect(self._reception_callback) thread.start() # Add dockable windows. self.addDockWidget(Qt.LeftDockWidgetArea, control_dock) self.addDockWidget(Qt.LeftDockWidgetArea, info_dock) self.addDockWidget(Qt.LeftDockWidgetArea, templates_dock) # Add Grid Layout for canvas canvas_grid = QGridLayout() group_canv_temp = QDockWidget() group_canv_temp.setWidget(canvas_template_widget) group_canv_mea = QDockWidget() group_canv_mea.setWidget(canvas_mea) group_canv_rate = QDockWidget() group_canv_rate.setWidget(canvas_rate) group_canv_isi = QDockWidget() group_canv_isi.setWidget(canvas_isi) canvas_grid.addWidget(group_canv_temp, 0, 0) canvas_grid.addWidget(group_canv_mea, 0, 1) canvas_grid.addWidget(group_canv_rate, 1, 1) canvas_grid.addWidget(group_canv_isi, 1, 0) canvas_group = QGroupBox() canvas_group.setLayout(canvas_grid) # Set central widget. self.setCentralWidget(canvas_group) # Set window size. if screen_resolution is not None: screen_width = screen_resolution.width() screen_height = screen_resolution.height() self.resize(screen_width, screen_height) # Set window title. self.setWindowTitle("SpyKING Circus ORT - Read 'n' Qt display") print(" ") # TODO remove? @property def nb_templates(self): return len(self.cells) def _number_callback(self, number): self._nb_buffer = float(number) text = u"{}".format(number) self._info_buffer_value_label.setText(text) text = u"{:8.3f}".format(self._nb_buffer * float(self._nb_samples) / self._sampling_rate) self._label_time_value.setText(text) return def _reception_callback(self, templates, spikes): bar = None if templates is not None: bar = [] for i in range(len(templates)): mask = spikes['templates'] == i template = load_template_from_dict(templates[i], self.probe) new_cell = Cell(template, Train([]), Amplitude([], [])) self.cells.append(new_cell) self._selection_templates.insertRow(self.nb_templates) bar += [template.center_of_mass(self.probe)] channel = template.channel amplitude = template.peak_amplitude() # self._selection_templates.setItem(self.nb_templates, 0, QTableWidgetItem("Template %d" %self.nb_templates)) # self._selection_templates.setItem(self.nb_templates, 1, QTableWidgetItem(str(bar))) self._selection_templates.setItem(self.nb_templates, 0, QTableWidgetItem(str(self.nb_templates))) self._selection_templates.setItem(self.nb_templates, 1, QTableWidgetItem(str(channel))) self._selection_templates.setItem(self.nb_templates, 2, QTableWidgetItem(str(amplitude))) # item = QListWidgetItem("Template %i" % self.nb_templates) # self._selection_templates.addItem(item) # self._selection_templates.item(i).setSelected(False) # self.nb_templates += 1 # print(bar.shape, bar) if spikes is not None: self.cells.add_spikes(spikes['spike_times'], spikes['amplitudes'], spikes['templates']) self.cells.set_t_max(self._nb_samples * self._nb_buffer / self._sampling_rate) to_display = self.cells.rate(self.bin_size) self._canvas_template.on_reception(templates, self.nb_templates) self._canvas_mea.on_reception_bary(bar, self.nb_templates) # TODO Cells rate self._canvas_rate.on_reception_rates(self.cells.rate(self.bin_size)) # TODO : ISI If we want to display the ISI also # isi = self.cells.interspike_interval_histogram(self.isi_bin_width, self.isi_x_max=25.0) isi = self.cells.interspike_interval_histogram(self.isi_bin_width, self.isi_x_max) self._canvas_isi.on_reception_isi(isi) return def _on_time_changed(self): time = self._dsp_time.value() self._canvas_template.set_time(time) self._dsp_tw_rate.setRange(1, int(time)) return def _on_binsize_changed(self): time = self._dsp_binsize.value() self.bin_size = time self._dsp_tw_rate.setSingleStep(self.bin_size) return def _on_zoomrates_changed(self): zoom_value = self._zoom_rates.value() self._canvas_rate.zoom_rates(zoom_value) return def _on_voltage_changed(self): voltage = self._dsp_voltage.value() self._canvas_template.set_voltage(voltage) return def _on_peaks_display(self): value = self._display_peaks.isChecked() self._canvas_template.show_peaks(value) return def _on_templates_changed(self): self._canvas_template.set_templates(self._display_list) return def selected_templates(self, max_templates): list_templates = [] list_channels = [] for i in range(max_templates + 1): if i != 0 and \ self._selection_templates.item(i, 0).isSelected() and \ self._selection_templates.item(i, 1).isSelected() and \ self._selection_templates.item(i, 2).isSelected(): list_templates.append(i - 1) list_channels.append(int(self._selection_templates.item(i, 1).text())) self._canvas_template.selected_templates(list_templates) self._canvas_mea.selected_channels(list_channels) self._canvas_mea.selected_templates(list_templates) self._canvas_rate.selected_cells(list_templates) self._canvas_isi.selected_cells(list_templates) return def time_window_rate_full(self): value = self._tw_from_start.isChecked() self._canvas_rate.time_window_full(value) return def _on_time_window_changed(self): tw_value = self._dsp_tw_rate.value() self._canvas_rate.time_window_value(tw_value, self.bin_size) return
class PatternsTable(QWidget): def __init__(self): QWidget.__init__(self) self.grid = QGridLayout() self.setLayout(self.grid) self.patternArea() self.patternTable() def createPattern(self, name, x): label = name.lower() + "Label" type = name.lower() + "Type" entry = name.lower() + "Entry" setattr(self, label, QLabel(name)) setattr(self, entry, QLineEdit()) setattr(self, type, QComboBox()) labelobj = getattr(self, label) typeobj = getattr(self, type) entryobj = getattr(self, entry) typeobj.addItem("Hexadecimal") typeobj.addItem("String") self.grid.addWidget(labelobj, x, 0) self.grid.addWidget(entryobj, x, 1) self.grid.addWidget(typeobj, x, 2) def patternArea(self): self.filetypeLabel = QLabel("File type") self.filetype = QLineEdit() self.alignedLabel = QLabel("block aligned") self.aligned = QCheckBox() self.windowLabel = QLabel("Window size") self.window = QSpinBox() self.window.setSuffix(" bytes") self.window.setRange(0, 2500000) self.window.setSingleStep(100) self.addEntry = QPushButton("add") self.connect(self.addEntry, SIGNAL("clicked()"), self.insertPattern) self.grid.addWidget(self.filetypeLabel, 0, 0) self.grid.addWidget(self.filetype, 0, 1, 1, 2) self.createPattern("Header", 2) self.createPattern("Footer", 3) self.grid.addWidget(self.windowLabel, 4, 0) self.grid.addWidget(self.window, 4, 1) self.grid.addWidget(self.alignedLabel, 5, 0) self.grid.addWidget(self.aligned, 5, 1) self.grid.addWidget(self.addEntry, 6, 1) def patternTable(self): self.patterns = QTableWidget() self.patterns.setShowGrid(False) self.patterns.setColumnCount(5) self.patterns.setHorizontalHeaderLabels(["Filetype", "Header", "Footer", "Window", "Block aligned"]) self.patterns.horizontalHeader().setStretchLastSection(True) self.connect(self.patterns.verticalHeader(), SIGNAL("sectionClicked(int)"), self.patterns.removeRow) self.grid.addWidget(self.patterns, 7, 0, 1, 3) def warning(self, msg): msgBox = QMessageBox(self) msgBox.setText(msg) msgBox.setIcon(QMessageBox.Warning) msgBox.exec_() def validate(self, **kwargs): msg = "" if len(kwargs["type"]) == 0: msg = "Type must be defined" else: for i in kwargs["type"]: if i not in string.letters: msg = "Type's characters must be in the following set\n\n" + string.letters break rowCount = self.patterns.rowCount() for row in range(0, rowCount): if str(self.patterns.item(row, 0).text()) == kwargs["type"]: msg = "Type <" + kwargs["type"] + " > already defined" if msg != "": self.warning(msg) return False if kwargs["headerType"] == "Hexadecimal" and not self.isHex(kwargs["header"]): msg = "Header must be an even number of chars" self.warning(msg) return False if len(kwargs["header"]) == 0: msg = "Header must be provided" self.warning(msg) return False if kwargs["footerType"] == "Hexadecimal" and not self.isHex(kwargs["footer"]): msg = "Footer must be an even number of chars" self.warning(msg) return False if kwargs["window"] <= 0: msg = "Window size must be greater than 0" self.warning(msg) return False return True def insertPattern(self): filetype = str(self.filetype.text()) header = str(self.headerEntry.text()) headerType = str(self.headerType.currentText()) footer = str(self.footerEntry.text()) footerType = str(self.footerType.currentText()) window = self.window.text() aligned = self.aligned.isChecked() #Validate most of provided items kwargs = {"type": filetype, "header": header, "headerType": headerType, "footer": footer, "footerType": footerType, "window": int(window.replace(" bytes", ""))} if not self.validate(**kwargs): return filetypeItem = QTableWidgetItem(filetype) headerItem = QTableWidgetItem(header + " (" + headerType[0:3] + ")") footerItem = QTableWidgetItem(footer + " (" + footerType[0:3] + ")") windowItem = QTableWidgetItem(window) alignedItem = QTableWidgetItem(str(aligned)) self.patterns.insertRow(self.patterns.rowCount()) vertHeader = QTableWidgetItem(QIcon(":closetab.png"), "") row = self.patterns.rowCount() - 1 self.patterns.setVerticalHeaderItem(row, vertHeader) self.patterns.setItem(row, 0, filetypeItem) self.patterns.setItem(row, 1, headerItem) self.patterns.setItem(row, 2, footerItem) self.patterns.setItem(row, 3, windowItem) self.patterns.setItem(row, 4, alignedItem) self.patterns.resizeRowToContents(row) def isHex(self, hstr): HEXCHAR = "0123456789abcdefABCDEF" if len(hstr) % 2 != 0: return False even = False for i in range(len(hstr)): if hstr[i] not in HEXCHAR: return False return True def toHex(self, str): HEXCHAR = "0123456789abcdefABCDEF" hexStr = "" evenhex = "" for i in range(len(str)): if str[i] in HEXCHAR: if len(evenhex) == 1: hexStr += chr(int(evenhex+str[i], 16)) evenhex = "" else: evenhex = str[i] else: raise ValueError, "argument 'str' contains not valid characters" if len(evenhex) != 0: raise ValueError, "argument 'str' must be an even number of char" return hexStr def textToPattern(self, text): idx = text.find("(") pattern = "" if idx != -1: type = text[idx+1:idx+4] pattern = text[0:idx-1] if type == "Hex": pattern = self.toHex(pattern) return pattern def selectedItems(self): selected = {} rowCount = self.patterns.rowCount() for row in range(0, rowCount): filetype = str(self.patterns.item(row, 0).text()) selected[filetype] = [] pattern = [] pattern.append(self.textToPattern(str(self.patterns.item(row, 1).text()))) pattern.append(self.textToPattern(str(self.patterns.item(row, 2).text()))) pattern.append(int(self.patterns.item(row, 3).text().replace(" bytes", ""))) selected[filetype].append([pattern]) if self.patterns.item(row, 4).text() == "True": selected[filetype].append(True) else: selected[filetype].append(False) return selected
class WellMarkerDialog(QDialog): def __init__(self, well): super(WellMarkerDialog, self).__init__() self.well = well self.setupUi() self.initUI() self.button_box.accepted.connect(self.save_markers) self.button_box.rejected.connect(self.close) self.add_Button.clicked.connect(self.add_row) self.del_Button.clicked.connect(self.del_row) self.export_Button.clicked.connect(self.export_markers) self.import_Button.clicked.connect(self.import_markers) def setupUi(self): self.resize(568, 411) self.setWindowIcon(QIcon(':/icon/layer_icon')) self.setWindowTitle("Edit Markers") self.gridLayout = QGridLayout(self) # table widget self.tableWidget = QTableWidget(self) self.tableWidget.setColumnCount(4) self.tableWidget.setRowCount(0) self.tableWidget.setHorizontalHeaderItem(0, QTableWidgetItem("Name")) self.tableWidget.setHorizontalHeaderItem(1, QTableWidgetItem("TVD (m)")) self.tableWidget.setHorizontalHeaderItem(2, QTableWidgetItem("TVDSS (m)")) self.tableWidget.setHorizontalHeaderItem(3, QTableWidgetItem("Color")) self.gridLayout.addWidget(self.tableWidget, 0, 0, 1, 1) # button box self.button_box = QDialogButtonBox(self) self.export_Button = self.button_box.addButton( "Export", QDialogButtonBox.ResetRole) self.import_Button = self.button_box.addButton( "Import", QDialogButtonBox.ResetRole) self.add_Button = self.button_box.addButton("Add", QDialogButtonBox.ResetRole) self.del_Button = self.button_box.addButton("Del", QDialogButtonBox.ResetRole) self.button_box.setStandardButtons(QDialogButtonBox.Save | QDialogButtonBox.Cancel) self.gridLayout.addWidget(self.button_box, 1, 0, 1, 1) def initUI(self): self.populate_marker_table() def populate_marker_table(self): try: markers_dict = self.well.params["horizon"] for mark in markers_dict.keys(): self.tableWidget.insertRow(0) self.tableWidget.setItem(0, 0, QTableWidgetItem(mark)) self.tableWidget.setItem( 0, 1, QTableWidgetItem(str(markers_dict[mark]))) self.tableWidget.setItem( 0, 2, QTableWidgetItem(str(markers_dict[mark]))) self.tableWidget.sortItems(0, Qt.AscendingOrder) except KeyError: pass def add_row(self): self.tableWidget.insertRow(self.tableWidget.rowCount()) def del_row(self): self.tableWidget.removeRow(self.tableWidget.currentRow()) def save_markers(self): l_names = [str(self.tableWidget.item(irow, 0).text()) \ for irow in range(self.tableWidget.rowCount())] l_md = [float(self.tableWidget.item(irow, 1).text()) \ for irow in range(self.tableWidget.rowCount())] new_dict = OrderedDict([(a, b) for a, b in zip(l_names, l_md)]) if self.well.params['horizon'] != new_dict: respond = QMessageBox.question( self, "Save Markers", "Sure to save changes?", QMessageBox.Save | QMessageBox.Cancel) if respond == QMessageBox.Save: self.well.params['horizon'] = new_dict self.well.save_params() self.close() def export_markers(self): file_path = str(QFileDialog.getSaveFileName(self, "Save Markers")) l_names = [str(self.tableWidget.item(irow, 0).text()) \ for irow in range(self.tableWidget.rowCount())] l_md = [float(self.tableWidget.item(irow, 1).text()) \ for irow in range(self.tableWidget.rowCount())] df = pd.DataFrame({"name": l_names, "MD(m)": l_md}) df.to_csv(file_path, sep='\t', columns=["name", "MD(m)"], index=False) QMessageBox.information(self, "Export Markers", "Succeed!") def import_markers(self): read_csv_dialog = ReadCsvDialog() read_csv_dialog.setWindowIcon(QIcon(':/icon/layer_icon')) read_csv_dialog.setWindowTitle("Open Markers File") read_csv_dialog.label.setText("Read Makers from File") read_csv_dialog.exec_()
class KeywordTable(HelpedWidget): """Shows a table of key/value pairs. The data structure expected and sent to the getter and setter is a dictionary of values.""" def __init__(self, model, table_label="", help_link=""): HelpedWidget.__init__(self, table_label, help_link) self.table = QTableWidget(self) self.table.setColumnCount(2) self.setColumnHeaders() self.table.verticalHeader().setHidden(True) self.table.setColumnWidth(0, 150) self.table.horizontalHeader().setStretchLastSection(True) self.table.setMinimumHeight(110) self.table.setSelectionMode(QAbstractItemView.SingleSelection) self.table.setSelectionBehavior(QAbstractItemView.SelectRows) self.addWidget(self.table) self.addWidget(AddRemoveWidget(self.addItem, self.removeItem)) self.connect(self.table, SIGNAL('cellChanged(int,int)'), self.tableChanged) assert isinstance(model, DictionaryModelMixin) self.model = model model.observable().attach(DictionaryModelMixin.DICTIONARY_CHANGED_EVENT, self.modelChanged) self.modelChanged() def setColumnHeaders(self, keyword_name="Keyword", value_name="Value"): self.headers = [keyword_name, value_name] self.table.setHorizontalHeaderLabels(self.headers) def addItem(self): """Called by the add button to insert a new keyword""" title = "New %s" % self.headers[0] description = "Enter new %s:" % self.headers[0] (new_keyword, ok) = QInputDialog.getText(self, title, description, QLineEdit.Normal) if ok: new_keyword = str(new_keyword).strip() self.model.addKey(new_keyword) def removeItem(self): """Called by the remove button to remove a selected keyword""" current_row = self.table.currentRow() if current_row >= 0: do_delete = QMessageBox.question(self, "Delete row?", "Are you sure you want to delete the key/value pair?", QMessageBox.Yes | QMessageBox.No ) if do_delete: key_item = self.table.item(current_row, 0) if key_item is not None: key = str(key_item.text()).strip() self.model.removeKey(key) def tableChanged(self, row, column): """Called whenever the contents of a cell changes.""" key_item = self.table.item(row, 0) if key_item is not None: key = str(key_item.text()).strip() value_item = self.table.item(row, 1) if value_item is not None: value = str(value_item.text()).strip() self.model.setValueForKey(key, value) def modelChanged(self): """Retrieves data from the model and inserts it into the table.""" values = self.model.getDictionary() blocked = self.table.blockSignals(True) for row in reversed(range(self.table.rowCount())): self.table.removeRow(row) row = 0 for key in values: key_item = QTableWidgetItem(str(key)) key_item.setFlags(key_item.flags() ^ Qt.ItemIsEditable) value_item = QTableWidgetItem(str(values[key])) self.table.insertRow(row) self.table.setItem(row, 0, key_item) self.table.setItem(row, 1, value_item) row += 1 self.table.blockSignals(blocked)
class LabelAssistDialog(QDialog): """ A simple UI for showing bookmarks and navigating to them. FIXME: For now, this window is tied to a particular lane. If your project has more than one lane, then each one will have it's own bookmark window, which is kinda dumb. """ def __init__(self, parent, topLevelOperatorView): super(LabelAssistDialog, self).__init__(parent) # Create thread router to populate table on main thread self.threadRouter = ThreadRouter(self) # Set object classification operator view self.topLevelOperatorView = topLevelOperatorView self.setWindowTitle("Label Assist") self.setMinimumWidth(500) self.setMinimumHeight(700) layout = QGridLayout() layout.setContentsMargins(10, 10, 10, 10) # Show variable importance table rows = 0 columns = 4 self.table = QTableWidget(rows, columns) self.table.setHorizontalHeaderLabels( ['Frame', 'Max Area', 'Min Area', 'Labels']) self.table.verticalHeader().setVisible(False) # Select full row on-click and call capture double click self.table.setSelectionBehavior(QTableView.SelectRows) self.table.doubleClicked.connect(self._captureDoubleClick) layout.addWidget(self.table, 1, 0, 3, 2) # Create progress bar self.progressBar = QProgressBar() self.progressBar.setMinimum(0) self.progressBar.setMaximum(0) self.progressBar.hide() layout.addWidget(self.progressBar, 4, 0, 1, 2) # Create button to populate table self.computeButton = QPushButton('Compute object info') self.computeButton.clicked.connect(self._triggerTableUpdate) layout.addWidget(self.computeButton, 5, 0) # Create close button closeButton = QPushButton('Close') closeButton.clicked.connect(self.close) layout.addWidget(closeButton, 5, 1) # Set dialog layout self.setLayout(layout) def _triggerTableUpdate(self): # Check that object area is included in selected features featureNames = self.topLevelOperatorView.SelectedFeatures.value if 'Standard Object Features' not in featureNames or 'Count' not in featureNames[ 'Standard Object Features']: box = QMessageBox( QMessageBox.Warning, 'Warning', 'Object area is not a selected feature. Please select this feature on: \"Standard Object Features > Shape > Size in pixels\"', QMessageBox.NoButton, self) box.show() return # Clear table self.table.clearContents() self.table.setRowCount(0) self.table.setSortingEnabled(False) self.progressBar.show() self.computeButton.setEnabled(False) # Compute object features and number of labels per frame def compute_features(): features = self.topLevelOperatorView.ObjectFeatures([]).wait() labels = self.topLevelOperatorView.LabelInputs([]).wait() return features, labels req = Request(compute_features) req.notify_finished(self._populateTable) req.submit() @threadRouted def _populateTable(self, features_and_labels): features, labels = features_and_labels self.progressBar.hide() self.computeButton.setEnabled(True) for frame, objectFeatures in features.iteritems(): # Insert row rowNum = self.table.rowCount() self.table.insertRow(self.table.rowCount()) # Get max and min object areas areas = objectFeatures['Standard Object Features']['Count'] maxObjArea = numpy.max(areas[numpy.nonzero(areas)]) minObjArea = numpy.min(areas[numpy.nonzero(areas)]) # Get number of labeled objects labelNum = numpy.count_nonzero(labels[frame]) # Load fram number item = QTableWidgetItem(str(frame)) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.table.setItem(rowNum, 0, item) # Load max object areas item = QTableWidgetItemWithFloatSorting( str("{: .02f}".format(maxObjArea))) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.table.setItem(rowNum, 1, item) # Load min object areas item = QTableWidgetItemWithFloatSorting( str("{: .02f}".format(minObjArea))) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.table.setItem(rowNum, 2, item) # Load label numbers item = QTableWidgetItemWithFloatSorting( str("{: .01f}".format(labelNum))) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.table.setItem(rowNum, 3, item) # Resize column size to fit dialog size self.table.horizontalHeader().setResizeMode(QHeaderView.Stretch) # Sort by max object area self.table.setSortingEnabled(True) self.table.sortByColumn(1) def _captureDoubleClick(self): # Navigate to selected frame index = self.table.selectedIndexes()[0] frameStr = self.table.model().data(index).toString() if frameStr: frameNum = int(frameStr) self.parent().editor.posModel.time = frameNum
class PatternsTable(QWidget): def __init__(self): QWidget.__init__(self) self.grid = QGridLayout() self.setLayout(self.grid) self.patternArea() self.patternTable() def createPattern(self, name, x): label = name.lower() + "Label" type = name.lower() + "Type" entry = name.lower() + "Entry" setattr(self, label, QLabel(name)) setattr(self, entry, QLineEdit()) setattr(self, type, QComboBox()) labelobj = getattr(self, label) typeobj = getattr(self, type) entryobj = getattr(self, entry) typeobj.addItem("Hexadecimal") typeobj.addItem("String") self.grid.addWidget(labelobj, x, 0) self.grid.addWidget(entryobj, x, 1) self.grid.addWidget(typeobj, x, 2) def patternArea(self): self.filetypeLabel = QLabel("File type") self.filetype = QLineEdit() self.alignedLabel = QLabel("block aligned") self.aligned = QCheckBox() self.windowLabel = QLabel("Window size") self.window = QSpinBox() self.window.setSuffix(" bytes") self.window.setRange(0, 2500000) self.window.setSingleStep(100) self.addEntry = QPushButton("add") self.connect(self.addEntry, SIGNAL("clicked()"), self.insertPattern) self.grid.addWidget(self.filetypeLabel, 0, 0) self.grid.addWidget(self.filetype, 0, 1, 1, 2) self.createPattern("Header", 2) self.createPattern("Footer", 3) self.grid.addWidget(self.windowLabel, 4, 0) self.grid.addWidget(self.window, 4, 1) self.grid.addWidget(self.alignedLabel, 5, 0) self.grid.addWidget(self.aligned, 5, 1) self.grid.addWidget(self.addEntry, 6, 1) def patternTable(self): self.patterns = QTableWidget() self.patterns.setShowGrid(False) self.patterns.setColumnCount(5) self.patterns.setHorizontalHeaderLabels(["Filetype", "Header", "Footer", "Window", "Block aligned"]) self.patterns.horizontalHeader().setStretchLastSection(True) self.connect(self.patterns.verticalHeader(), SIGNAL("sectionClicked(int)"), self.patterns.removeRow) self.grid.addWidget(self.patterns, 7, 0, 1, 3) def warning(self, msg): msgBox = QMessageBox(self) msgBox.setText(msg) msgBox.setIcon(QMessageBox.Warning) msgBox.exec_() def validate(self, **kwargs): msg = "" if len(kwargs["type"]) == 0: msg = "Type must be defined" else: for i in kwargs["type"]: if i not in string.letters: msg = "Type's characters must be in the following set\n\n" + string.letters break rowCount = self.patterns.rowCount() for row in range(0, rowCount): if str(self.patterns.item(row, 0).text()) == kwargs["type"]: msg = "Type <" + kwargs["type"] + " > already defined" if msg != "": self.warning(msg) return False if kwargs["headerType"] == "Hexadecimal" and not self.isHex(kwargs["header"]): msg = "Header must be an even number of chars" self.warning(msg) return False if len(kwargs["header"]) == 0: msg = "Header must be provided" self.warning(msg) return False if kwargs["footerType"] == "Hexadecimal" and not self.isHex(kwargs["header"]): msg = "Footer must be an even number of chars" self.warning(msg) return False if kwargs["window"] <= 0: msg = "Window size must be greater than 0" self.warning(msg) return False return True def insertPattern(self): filetype = str(self.filetype.text()) header = str(self.headerEntry.text()) headerType = str(self.headerType.currentText()) footer = str(self.footerEntry.text()) footerType = str(self.footerType.currentText()) window = self.window.text() aligned = self.aligned.isChecked() #Validate most of provided items kwargs = {"type": filetype, "header": header, "headerType": headerType, "footer": footer, "footerType": footerType, "window": int(window.replace(" bytes", ""))} if not self.validate(**kwargs): return filetypeItem = QTableWidgetItem(filetype) headerItem = QTableWidgetItem(header + " (" + headerType[0:3] + ")") footerItem = QTableWidgetItem(footer + " (" + footerType[0:3] + ")") windowItem = QTableWidgetItem(window) alignedItem = QTableWidgetItem(str(aligned)) self.patterns.insertRow(self.patterns.rowCount()) vertHeader = QTableWidgetItem(QIcon(":closetab.png"), "") row = self.patterns.rowCount() - 1 self.patterns.setVerticalHeaderItem(row, vertHeader) self.patterns.setItem(row, 0, filetypeItem) self.patterns.setItem(row, 1, headerItem) self.patterns.setItem(row, 2, footerItem) self.patterns.setItem(row, 3, windowItem) self.patterns.setItem(row, 4, alignedItem) self.patterns.resizeRowToContents(row) def isHex(self, str): HEXCHAR = "0123456789abcdefABCDEF" hexStr = "" even = False for i in range(len(str)): if str[i] in HEXCHAR: if even == True: even = False else: even = True else: return False if even: return False return True def toHex(self, str): HEXCHAR = "0123456789abcdefABCDEF" hexStr = "" evenhex = "" for i in range(len(str)): if str[i] in HEXCHAR: if len(evenhex) == 1: hexStr += chr(int(evenhex+str[i], 16)) evenhex = "" else: evenhex = str[i] else: raise ValueError, "argument 'str' contains not valid characters" if len(evenhex) != 0: raise ValueError, "argument 'str' must be an even number of char" return hexStr def textToPattern(self, text): idx = text.find("(") pattern = "" if idx != -1: type = text[idx+1:idx+4] pattern = text[0:idx-1] if type == "Hex": pattern = self.toHex(pattern) return pattern def selectedItems(self): selected = {} rowCount = self.patterns.rowCount() for row in range(0, rowCount): filetype = str(self.patterns.item(row, 0).text()) selected[filetype] = [] pattern = [] pattern.append(self.textToPattern(str(self.patterns.item(row, 1).text()))) pattern.append(self.textToPattern(str(self.patterns.item(row, 2).text()))) pattern.append(int(self.patterns.item(row, 3).text().replace(" bytes", ""))) selected[filetype].append([pattern]) if self.patterns.item(row, 4).text() == "True": selected[filetype].append(True) else: selected[filetype].append(False) return selected
class GraphDialog(QDialog): edit_patterns = 0 edit_curves = 1 titles = {edit_patterns: 'Pattern editor', edit_curves: 'Curve editor'} labels = {edit_patterns: 'Patterns', edit_curves: 'Curves'} def __init__(self, dockwidget, parent, params, edit_type): QDialog.__init__(self, parent) main_lay = QVBoxLayout(self) self.dockwidget = dockwidget self.params = params self.edit_type = edit_type self.x_label = '' self.y_label = '' self.setMinimumWidth(600) self.setMinimumHeight(400) self.setWindowTitle(self.titles[edit_type]) # TODO: softcode self.setWindowModality(QtCore.Qt.ApplicationModal) self.current = None self.current_saved = False # File self.lbl_file = QLabel('File:') self.fra_file = QFrame() self.fra_file.setContentsMargins(0, 0, 0, 0) fra_file_lay = QHBoxLayout(self.fra_file) if edit_type == self.edit_patterns: self.txt_file = QLineEdit(self.params.patterns_file) elif edit_type == self.edit_curves: self.txt_file = QLineEdit(self.params.curves_file) self.txt_file.setReadOnly(True) self.txt_file.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) self.txt_file.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) fra_file_lay.addWidget(self.txt_file) self.btn_file = QPushButton('Change') # TODO: softcode self.btn_file.clicked.connect(self.import_file) fra_file_lay.addWidget(self.btn_file) fra_file_lay.setContentsMargins(0, 0, 0, 0) self.lbl_list = QLabel(self.labels[edit_type]) self.lst_list = QListWidget() self.lst_list.currentItemChanged.connect(self.list_item_changed) # Form self.fra_form = QFrame() fra_form1_lay = QFormLayout(self.fra_form) fra_form1_lay.setContentsMargins(0, 0, 0, 0) fra_form1_lay.addRow(self.lbl_list, self.lst_list) # Buttons self.fra_buttons = QFrame() fra_buttons_lay = QHBoxLayout(self.fra_buttons) fra_buttons_lay.setContentsMargins(0, 0, 0, 0) if self.edit_type == self.edit_patterns: ele_name = 'pattern' elif self.edit_type == self.edit_curves: ele_name = 'curve' self.btn_new = QPushButton('New ' + ele_name) # TODO: softcode self.btn_new.clicked.connect(self.new_element) fra_buttons_lay.addWidget(self.btn_new) self.btn_import = QPushButton('Import ' + ele_name + 's') # TODO: softcode self.btn_import.clicked.connect(self.import_file) fra_buttons_lay.addWidget(self.btn_import) self.btn_save = QPushButton('Save current ' + ele_name) # TODO: softcode self.btn_save.clicked.connect(self.save) fra_buttons_lay.addWidget(self.btn_save) self.btn_del = QPushButton('Delete current ' + ele_name) # TODO: softcode self.btn_del.clicked.connect(self.del_item) fra_buttons_lay.addWidget(self.btn_del) # ID self.lbl_id = QLabel('ID:') self.txt_id = QLineEdit() self.txt_id.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.MinimumExpanding) self.lbl_desc = QLabel('Desc.:') self.txt_desc = QLineEdit() self.fra_id = QFrame() fra_id_lay = QHBoxLayout(self.fra_id) fra_id_lay.addWidget(self.lbl_id) fra_id_lay.addWidget(self.txt_id) fra_id_lay.addWidget(self.lbl_desc) fra_id_lay.addWidget(self.txt_desc) # Table form self.table = QTableWidget(self) self.rows_nr = 24 self.cols_nr = 2 self.table.setRowCount(self.rows_nr) self.table.setColumnCount(self.cols_nr) self.table.verticalHeader().setVisible(False) # Initialize empty table self.clear_table() self.table.itemChanged.connect(self.data_changed) self.fra_table = QFrame() fra_table_lay = QVBoxLayout(self.fra_table) fra_table_lay.setContentsMargins(0, 0, 0, 0) if edit_type == self.edit_curves: self.fra_pump_type = QFrame() fra_pump_type_lay = QFormLayout(self.fra_pump_type) self.lbl_pump_type = QLabel('Curve type:') # TODO: softcode self.cbo_pump_type = QComboBox() for key, name in Curve.type_names.iteritems(): self.cbo_pump_type.addItem(name, key) fra_pump_type_lay.addRow(self.lbl_pump_type, self.cbo_pump_type) fra_table_lay.addWidget(self.fra_pump_type) self.cbo_pump_type.activated.connect(self.cbo_pump_type_activated) fra_table_lay.addWidget(self.table) self.btn_add_row = QPushButton('Add row') self.btn_add_row.clicked.connect(self.add_row) fra_table_lay.addWidget(self.btn_add_row) # Graph canvas self.fra_graph = QFrame() self.static_canvas = StaticMplCanvas(self.fra_graph, width=5, height=4, dpi=100) fra_graph_lay = QVBoxLayout(self.fra_graph) fra_graph_lay.addWidget(self.static_canvas) # Top frame self.fra_top = QFrame() fra_top_lay = QVBoxLayout(self.fra_top) fra_top_lay.addWidget(self.fra_form) fra_top_lay.addWidget(self.fra_id) fra_top_lay.addWidget(self.fra_buttons) # Bottom frame self.fra_bottom = QFrame() fra_bottom_lay = QHBoxLayout(self.fra_bottom) fra_bottom_lay.addWidget(self.fra_table) fra_bottom_lay.addWidget(self.fra_graph) # Main main_lay.addWidget(self.fra_top) main_lay.addWidget(self.fra_bottom) # Get existing patterns/curves self.need_to_update_graph = False if self.edit_type == self.edit_patterns: for pattern_id, pattern in self.params.patterns.iteritems(): self.lst_list.addItem(pattern.id) elif self.edit_type == self.edit_curves: for curve_id, curve in self.params.curves.iteritems(): self.lst_list.addItem(curve.id) if self.lst_list.count() > 0: self.lst_list.setCurrentRow(0) self.txt_id.setEnabled(True) self.txt_desc.setEnabled(True) self.btn_save.setEnabled(True) self.btn_del.setEnabled(True) self.table.setEnabled(True) self.table.setEditTriggers(QAbstractItemView.AllEditTriggers) else: self.txt_id.setEnabled(False) self.txt_desc.setEnabled(False) self.btn_save.setEnabled(False) self.btn_del.setEnabled(False) self.table.setEnabled(False) self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) self.new_dialog = None self.need_to_update_graph = True def cbo_pump_type_activated(self): self.update_table_headers() self.update_graph() def add_row(self): row_pos = self.table.rowCount() self.table.insertRow(row_pos) col = 0 item = QTableWidgetItem(str(row_pos)) if self.edit_type == self.edit_patterns: self.table.setItem(row_pos, col, item) item.setFlags(QtCore.Qt.ItemIsSelectable) def setVisible(self, bool): QDialog.setVisible(self, bool) self.update_table_headers() self.update_graph() def list_item_changed(self): p_index = self.lst_list.currentRow() flags = Qt.ItemFlags() flags != Qt.ItemIsEnabled # Clear table self.clear_table() self.need_to_update_graph = False if p_index >= 0: self.table.setRowCount(0) if self.edit_type == self.edit_patterns: self.current = self.params.patterns[ self.lst_list.currentItem().text()] for v in range(len(self.current.values)): row_pos = self.table.rowCount() self.table.insertRow(row_pos) item = QTableWidgetItem(str(v)) item.setFlags(flags) self.table.setItem(v, 0, item) self.table.setItem( v, 1, QTableWidgetItem(str(self.current.values[v]))) elif self.edit_type == self.edit_curves: self.current = self.params.curves[ self.lst_list.currentItem().text()] for v in range(len(self.current.xs)): row_pos = self.table.rowCount() self.table.insertRow(row_pos) self.table.setItem( v, 0, QTableWidgetItem(str(self.current.xs[v]))) self.table.setItem( v, 1, QTableWidgetItem(str(self.current.ys[v]))) curve_type = self.current.type self.cbo_pump_type.setCurrentIndex(curve_type) # Update GUI self.txt_id.setText(self.current.id) self.txt_desc.setText(self.current.desc) self.update_table_headers() # Update graph self.need_to_update_graph = True self.update_graph() else: # No curves self.txt_id.setText('') self.txt_desc.setText('') # Update table and chart self.need_to_update_graph = False for v in range(self.table.columnCount()): self.table.setItem(v, 1, QTableWidgetItem('')) self.need_to_update_graph = True self.update_graph() def import_file(self): config_file = ConfigFile(Parameters.config_file_path) directory = None if self.edit_type == GraphDialog.edit_curves: directory = self.params.last_curves_dir elif self.edit_type == GraphDialog.edit_patterns: directory = self.params.last_patterns_dir if directory is None: directory = self.params.last_project_dir file_path = QFileDialog.getOpenFileName(self, 'Select file', directory, 'Files (*.txt *.inp)') if file_path is None or file_path == '': return else: if self.edit_type == GraphDialog.edit_patterns: # Save patterns file path in configuration file config_file.set_patterns_file_path(file_path) Parameters.patterns_file = file_path elif self.edit_type == GraphDialog.edit_curves: # Save curve file path in configuration file config_file.set_curves_file_path(file_path) Parameters.curves_file = file_path self.read(file_path) def read(self, file_path): self.lst_list.clear() if self.edit_type == self.edit_patterns: InpFile.read_patterns(self.params, file_path) for pattern_id, pattern in self.params.patterns.iteritems(): # desc = ' (' + pattern.desc + ')' if pattern.desc is not None else '' self.lst_list.addItem(pattern.id) self.params.patterns[pattern.id] = pattern elif self.edit_type == self.edit_curves: InpFile.read_curves(self.params, file_path) for curve_id, curve in self.params.curves.iteritems(): # desc = ' (' + curve.desc + ')' if curve.desc is not None else '' self.lst_list.addItem(curve.id) self.params.curves[curve.id] = curve if self.lst_list.count() > 0: self.lst_list.setCurrentRow(0) def new_element(self): old_ids = [] if self.edit_type == self.edit_patterns: for pattern in self.params.patterns.itervalues(): old_ids.append(pattern.id) elif self.edit_type == self.edit_curves: for curve in self.params.curves.itervalues(): old_ids.append(curve.id) self.new_dialog = NewIdDialog(self, old_ids) self.new_dialog.exec_() new_id = self.new_dialog.get_newid() description = self.new_dialog.get_description() if new_id is None or description is None: return if self.edit_type == self.edit_patterns: new_pattern = Pattern(new_id, description) self.params.patterns[new_pattern.id] = new_pattern self.lst_list.addItem(new_pattern.id) elif self.edit_type == self.edit_curves: curve_type = self.cbo_pump_type.itemData( self.cbo_pump_type.currentIndex()) new_curve = Curve(new_id, curve_type, desc=description) self.params.curves[new_curve.id] = new_curve self.lst_list.addItem(new_curve.id) self.lst_list.setCurrentRow(self.lst_list.count() - 1) self.txt_id.setText(new_id) self.txt_desc.setText(description) # Clear table self.clear_table() self.static_canvas.axes.clear() self.txt_id.setEnabled(True) self.txt_desc.setEnabled(True) self.btn_save.setEnabled(True) self.btn_del.setEnabled(True) self.table.setEnabled(True) self.table.setEditTriggers(QAbstractItemView.AllEditTriggers) def save(self): self.need_to_update_graph = False # Check for ID if not self.txt_id.text(): QMessageBox.warning( self, Parameters.plug_in_name, u'Please specify the ID.', # TODO: softcode QMessageBox.Ok) return if self.edit_type == GraphDialog.edit_patterns: values = [] for row in range(self.table.rowCount()): item = self.table.item(row, 1) if item is not None and item.text() != '': values.append(self.from_item_to_val(item)) else: values.append('0') pattern = Pattern(self.txt_id.text(), self.txt_desc.text(), values) old_patterns = self.params.patterns old_patterns[pattern.id] = pattern self.params.patterns = old_patterns self.lst_list.currentItem().setText(pattern.id) elif self.edit_type == GraphDialog.edit_curves: # Check for ID unique xs = [] ys = [] for row in range(self.table.rowCount()): item_x = self.table.item(row, 0) item_y = self.table.item(row, 1) if item_x.text() != '' and item_y.text() != '': xs.append(self.from_item_to_val(item_x)) ys.append(self.from_item_to_val(item_y)) curve_type = self.cbo_pump_type.itemData( self.cbo_pump_type.currentIndex()) curve = Curve(self.txt_id.text(), curve_type, self.txt_desc.text()) for v in range(len(xs)): curve.append_xy(xs[v], ys[v]) old_curves = self.params.curves old_curves[curve.id] = curve self.params.curves = old_curves self.lst_list.currentItem().setText(curve.id) # Update GUI self.dockwidget.update_curves_combo() # self.read() self.need_to_update_graph = True def clear_table(self): self.need_to_update_graph = False for r in range(self.table.rowCount()): self.table.setItem(r, 0, QTableWidgetItem(None)) self.table.setItem(r, 1, QTableWidgetItem(None)) for row in range(self.rows_nr): for col in range(self.cols_nr): if self.edit_type == self.edit_patterns: if col == 0: item = QTableWidgetItem(str(row)) self.table.setItem(row, col, item) item.setFlags(QtCore.Qt.ItemIsSelectable) # elif col == 1 and row == 0: # item = QTableWidgetItem(str(1)) # self.table.setItem(row, col, item) # item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) # elif self.edit_type == self.edit_curves: # if row == 0: # item = QTableWidgetItem(str(0)) # self.table.setItem(row, 0, item) # item = QTableWidgetItem(str(1)) # self.table.setItem(row, 1, item) # item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) self.need_to_update_graph = True def del_item(self): selected_row = self.lst_list.currentRow() name = self.lst_list.currentItem().text() if selected_row < 0: return self.lst_list.takeItem(selected_row) if self.lst_list.count() == 0: self.txt_id.setEnabled(False) self.txt_desc.setEnabled(False) self.btn_save.setEnabled(False) self.btn_del.setEnabled(False) self.table.setEnabled(False) self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) if self.edit_type == GraphDialog.edit_curves: del self.params.curves[name] # Update GUI self.dockwidget.update_curves_combo() elif self.edit_type == GraphDialog.edit_patterns: del self.params.patterns[name] # Update GUI self.dockwidget.update_patterns_combo() def data_changed(self): if self.need_to_update_graph: self.update_graph() def update_table_headers(self): if self.edit_type == self.edit_patterns: self.x_label = 'Time period' self.y_label = 'Multiplier' elif self.edit_type == self.edit_curves: cbo_data = self.cbo_pump_type.itemData( self.cbo_pump_type.currentIndex()) if cbo_data == Curve.type_efficiency: self.x_label = 'Flow ' + '[' + self.params.options.flow_units + ']' self.y_label = 'Efficiency ' + '[' + self.params.options.units_deltaz[ self.params.options.units] + ']' if cbo_data == Curve.type_headloss: self.x_label = 'Flow ' + '[' + self.params.options.flow_units + ']' self.y_label = 'Headloss ' + '[' + self.params.options.units_deltaz[ self.params.options.units] + ']' if cbo_data == Curve.type_pump: self.x_label = 'Flow ' + '[' + self.params.options.flow_units + ']' self.y_label = 'Head ' + '[' + self.params.options.units_deltaz[ self.params.options.units] + ']' if cbo_data == Curve.type_volume: self.x_label = 'Height ' + '[' + self.params.options.flow_units + ']' self.y_label = 'Volume ' + '[' + self.params.options.units_deltaz[ self.params.options.units] + ']' self.table.setHorizontalHeaderLabels([self.x_label, self.y_label]) # TODO: softcode def update_graph(self): if not self.need_to_update_graph: return xs = [] ys = [] for row in range(self.table.rowCount()): item = self.table.item(row, 0) x = self.from_item_to_val(item) item = self.table.item(row, 1) y = self.from_item_to_val(item) if x is not None: xs.append(float(x)) if y is not None: ys.append(float(y)) if len(xs) == 0 or len(ys) == 0: self.static_canvas.clear() return xys_t = zip(xs, ys) xys_t.sort() xys = zip(*xys_t) xs = xys[0] ys = xys[1] if self.edit_type == self.edit_patterns: y_axis_label = 'Mult. avg.: ' + '{0:.2f}'.format( (numpy.average(ys))) self.static_canvas.draw_bars_graph( ys, time_period=self.params.times.pattern_timestep, y_axes_label=y_axis_label) elif self.edit_type == self.edit_curves: # Account for different types of curves cbo_data = self.cbo_pump_type.itemData( self.cbo_pump_type.currentIndex()) series_length = min(len(xs), len(ys)) # Need to account for different types of curves if cbo_data == Curve.type_efficiency or cbo_data == Curve.type_headloss or cbo_data == Curve.type_volume: self.static_canvas.draw_line_graph(xs[:series_length], ys[:series_length], self.x_label, self.y_label) elif cbo_data == Curve.type_pump: if series_length == 1 or series_length == 3: if series_length == 1: # 3 curve points curve_xs = [0, xs[0], xs[0] * 2] curve_ys = [ys[0] * 1.33, ys[0], 0] # y = a * x^2 + b * x + c elif series_length == 3: # 3 curve points curve_xs = [xs[0], xs[1], xs[2]] curve_ys = [ys[0], ys[1], ys[2]] (a, b, c) = numpy.polyfit(curve_xs, curve_ys, 2) # Create a few interpolated values interp_xs = [] interp_ys = [] n_vals = 30 for v in range(n_vals + 1): x = (curve_xs[2] - curve_xs[0]) / n_vals * v interp_xs.append(x) y = a * x**2 + b * x + c interp_ys.append(y) self.static_canvas.draw_line_graph(interp_xs, interp_ys, self.x_label, self.y_label) else: self.static_canvas.draw_line_graph(xs[:series_length], ys[:series_length], self.x_label, self.y_label) def from_item_to_val(self, item): if item is None: value = None else: value = item.text() try: value = float(value) value = max(value, 0) except: value = None return value
class ActionEditorDialog(QWidget): # Redefine the tr() function for this class. def tr(self, text): return qApp.translate("ActionEditorDialog", text) def __init__(self, actions, parent=None): super(ActionEditorDialog, self).__init__(parent) self.actions = actions help = QLabel(translate("Shortcut Settings", '<b>Double click a cell in the Shortcut Column' \ ' to <br />modify the key sequence.</b>')) self.actionTable = QTableWidget(self) self.actionTable.setSelectionBehavior(QTableWidget.SelectRows) self.actionTable.setEditTriggers(QTableWidget.DoubleClicked) self.actionTable.setColumnCount(2) self.actionTable.setHorizontalHeaderLabels( [translate("Shortcut Settings", "Description"), translate("Shortcut Settings", "Shortcut")] ) self.actionTable.horizontalHeader().setStretchLastSection(True) self.actionTable.verticalHeader().hide() self.actionTable.setItemDelegate(ActionEditorDelegate(self)) self.connect(self.actionTable, SIGNAL("cellChanged(int, int)"), self.validateAction) row = 0 for action in self.actions: if action.text().isEmpty(): continue self.actionTable.insertRow(self.actionTable.rowCount()) item = QTableWidgetItem() item.setText(action.text()) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) self.actionTable.setItem(row, 0, item) item = QTableWidgetItem() item.setText(action.shortcut().toString()) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsEditable | Qt.ItemIsSelectable) item.oldShortcutText = item.text() self.actionTable.setItem(row, 1, item) row += 1 self.actionTable.resizeColumnsToContents() mainLayout = QVBoxLayout() mainLayout.addWidget(help) mainLayout.setMargin(8) mainLayout.setSpacing(8) mainLayout.addWidget(self.actionTable) self.setLayout(mainLayout) self._model = self.actionTable.model() self._model.edited = False self.actionTable.model().edited = False self.setWindowTitle(translate("Shortcut Settings", "Edit Shortcuts")) def applySettings(self, control=None): if not self._model.edited: return row = 0 for action in self.actions: if not action.text().isEmpty(): action.setText(self.actionTable.item(row, 0).text()) action.setShortcut(QKeySequence(self.actionTable.item(row, 1).text())) row += 1 self.saveSettings(self.actions) self._model.edited = False def _loadSettings(self, actions): cparser = PuddleConfig(os.path.join(CONFIGDIR, 'user_shortcuts')) for action in actions: shortcut = cparser.get('shortcuts', unicode(action.text()), '') if shortcut: action.setShortcut(QKeySequence(shortcut)) _loadSettings = classmethod(_loadSettings) def saveSettings(self, actions): cparser = PuddleConfig(os.path.join(CONFIGDIR, 'user_shortcuts')) for action in actions: shortcut = unicode(action.shortcut().toString()) cparser.set('shortcuts', unicode(action.text()), shortcut) saveSettings = classmethod(saveSettings) def validateAction(self, row, column): if column != 1: return item = self.actionTable.item(row, column) shortcutText = QKeySequence(item.text()).toString() thisRow = self.actionTable.row(item) if not shortcutText.isEmpty(): for row in range(self.actionTable.rowCount()): if row == thisRow: continue other = self.actionTable.item(row, 1) if other.text() == shortcutText: other.setText(item.oldShortcutText) break item.setText(shortcutText) item.oldShortcutText = shortcutText self.actionTable.resizeColumnToContents(1)
def make_widget(main, show=True): id = main.persistant['id'] table = QTableWidget() table.controller = ROITableController(table, main) table.setGeometry(QRect(20, 33, 496, 296)) table.setWindowTitle('ceilingfaan - ROI Table - Work in progress') analysis = s.query(Analysis).order_by(Analysis.date.desc()).all() table.setRowCount(len(analysis)) table.setColumnCount(4) table.setHorizontalHeaderLabels( QString('CONTROL,DATE,MOUSE,FILENAME').split(',')) current_analysis = None on_render = table.controller.on('render') on_import = table.controller.on('import') for nrow, entity in enumerate(analysis): if entity.id == id: print 'Found matching analysis data', id, 'at nrow:', nrow current_analysis = entity current_nrow = nrow continue for ncol, attr in enumerate('date mouse_id filename'.split()): field = getattr(entity, attr) item = QTableWidgetItem(str(field)) item.setFlags(Qt.ItemIsEnabled) table.setItem(nrow, ncol + 1, item) render_btn = QPushButton('Render', checkable=True) render_btn.setStyleSheet('font-size: 9px; background-color: skyblue;') import_btn = QPushButton('Import') import_btn.setStyleSheet('font-size: 9px;') btn_layout = QHBoxLayout() btn_layout.setContentsMargins(5, 0, 5, 0) btn_layout.addWidget(render_btn) btn_layout.addWidget(import_btn) btn_widget = QWidget() btn_widget.nrow = nrow btn_widget.analysis_id = entity.id btn_widget.ext_roi_set = None btn_widget.setLayout(btn_layout) table.setCellWidget(nrow, 0, btn_widget) render_btn.clicked.connect(on_render) import_btn.clicked.connect(on_import) if current_analysis: table.removeRow(current_nrow) table.insertRow(0) item = QTableWidgetItem('Current Analysis') item.setFlags(Qt.ItemIsEnabled) item.setTextAlignment(Qt.AlignCenter) table.setItem(0, 0, item) for ncol, attr in enumerate('date mouse_id filename'.split()): field = getattr(current_analysis, attr) item = QTableWidgetItem(str(field)) item.setFlags(Qt.ItemIsEnabled) table.setItem(0, ncol + 1, item) # debug.enter() table.setSelectionBehavior(QTableWidget.SelectRows) table.setSelectionMode(QTableWidget.NoSelection) table.resizeColumnsToContents() table.horizontalHeader().setStretchLastSection(True) if show: table.show() return table
class ElemCompDialog(QtGui.QDialog): def __init__(self,mz, mass,xp,parent=None): QtGui.QDialog.__init__(self, parent) settings = QSettings() size = settings.value("MainWindow/Size",QVariant(QSize(1024,650))).toSize() self.resize(size) self.setWindowTitle('Elenmental Composition') self.xp=xp self.mass=mass self.mz=mz print mz self.initControls() # self.initPlots() def initControls(self): self.plot1 = Qwt.QwtPlot(self) self.plot1.setCanvasBackground(Qt.white) self.plot2 = Qwt.QwtPlot(self) self.plot2.setCanvasBackground(Qt.white) self.list = QTreeWidget() self.list.setColumnCount(11) self.list.setColumnWidth(0,80) self.list.setColumnWidth(1,80) self.list.setColumnWidth(2,60) self.list.setColumnWidth(3,60) self.list.setColumnWidth(4,60) self.list.setColumnWidth(5,150) self.list.setColumnWidth(7,30) self.list.setColumnWidth(8,30) self.list.setColumnWidth(9,30) self.list.setColumnWidth(10,30) self.list.setHeaderLabels(['Mass','Calc.Mass','mDa','PPM','DBE','Formula','Fit Conf %','C','H','N','O']) self.list.setSortingEnabled(True) self.table = QTableWidget(1,11) self.table.setColumnWidth(0,80) self.table.setColumnWidth(1,80) self.table.setColumnWidth(2,60) self.table.setColumnWidth(3,60) self.table.setColumnWidth(4,60) self.table.setColumnWidth(5,150) self.table.setColumnWidth(7,30) self.table.setColumnWidth(8,30) self.table.setColumnWidth(9,30) self.table.setColumnWidth(10,30) self.table.setHorizontalHeaderLabels(['Mass','Calc.Mass','mDa','PPM','DBE','Formula','Fit Conf %','C','H','N','O']) self.table.setEditTriggers(QTableWidget.NoEditTriggers) self.table.setSelectionBehavior(QTableWidget.SelectRows) self.table.setSelectionMode(QTableWidget.SingleSelection) self.table.setAlternatingRowColors(True) print self.connect(self.table, SIGNAL("itemActivated(QTableWidgetItem*)"), self.tableClicked) # self.connect(self.library_list, SIGNAL("itemSelectionChanged()"), self.libraryListClicked) up_hbox=QVBoxLayout() up_hbox.addWidget(self.table) down_hbox = QVBoxLayout() down_hbox.addWidget(self.plot1) down_hbox.addWidget(self.plot2) hbox = QVBoxLayout() hbox.addLayout(up_hbox, 3.5) hbox.addLayout(down_hbox, 3.5) self.setLayout(hbox) self.cal_mass() def tableClicked(self,item): self.C=self.table.item(item.row(),7).text() self.H=self.table.item(item.row(),8).text() self.N=self.table.item(item.row(),9).text() self.O=self.table.item(item.row(),10).text() self.cal_isotopic() self.initPlots() def initPlots(self): self.plot1.clear() # self.plot1.setTitle("Observed Isotope Distribution") # self.plot1.setAxisTitle(Qwt.QwtPlot.xBottom, 'Raman shift (cm-1)') # self.plot1.setAxisTitle(Qwt.QwtPlot.yLeft, 'Intensity') # grid = Qwt.QwtPlotGrid() pen = QPen(Qt.DotLine) pen.setColor(Qt.black) pen.setWidth(0) # grid.setPen(pen) # grid.attach(self.plot1) self.mass1=self.mass/self.massy*100 self.plot1.setAxisScale(self.plot1.xBottom,self.x_min,self.x_max) self.plot1.setAxisScale(self.plot1.yLeft,0,1.1*100) color = QColor('black') curve = Qwt.QwtPlotCurve("test1") pen = QPen(color) pen.setWidth(1) curve.setPen(pen) curve.setData(self.mass_x,self.mass_y) curve.setStyle(Qwt.QwtPlotCurve.Sticks) curve.attach(self.plot1) self.plot1.replot() self.plot2.clear() # self.plot2.setTitle("Theoretical Isotope Distribution") # self.plot2.setAxisTitle(Qwt.QwtPlot.xBottom, 'Raman shift (cm-1)') # self.plot2.setAxisTitle(Qwt.QwtPlot.yLeft, 'Intensity') # grid = Qwt.QwtPlotGrid() pen = QPen(Qt.DotLine) pen.setColor(Qt.blue) self.plot2.setAxisScale(self.plot1.xBottom,self.x_min,self.x_max) self.plot2.setAxisScale(self.plot1.yLeft,0,1.1*100) color = QColor('blue') curve = Qwt.QwtPlotCurve("test1") pen = QPen(color) pen.setWidth(1) curve.setPen(pen) # self.axis= np.arange(len(self.mass)) curve.setData(self.x,self.y) curve.setStyle(Qwt.QwtPlotCurve.Sticks) curve.attach(self.plot2) pen.setWidth(0) # grid.setPen(pen) # grid.attach(self.plot2) self.plot2.replot() def cal_mass(self): # charge=0.0 tol = 10.0 # electron=0.000549 measured_mass=np.round(self.xp) limit_lo = measured_mass - (tol/1000.0) limit_hi = measured_mass + (tol/1000.0) mass=[] mass.append((12.000000000,2.0,"C")) #mass.append((78.9183376,-1.0,"Br")) #mass.append((34.96885271,-1.0,"Cl")) #mass.append((31.97207069,0.0,"S")) #mass.append((30.97376151,1.0,"P")) #mass.append((27.9769265327,2.0,"Si")) #mass.append((22.98976967,-1.0,"Na")) #mass.append((18.99840320,-1.0,"F")) mass.append((15.9949146221,0.0,"O")) mass.append((14.0030740052,1.0,"N")) mass.append((1.0078250321,-1.0,"H")) print range(1,10) print mass[0][0] print mass[1][0] print mass[2][0] calc_mass=[] for i in range(1,int(floor(measured_mass/mass[0][0]))+1): for j in range(0,int(floor((measured_mass-mass[0][0]*i)/mass[1][0]))+1): for k in range(0,int(floor((measured_mass-mass[0][0]*i-mass[1][0]*j)/mass[2][0]))+1): # rr=(measured_mass-mass[0][0]*i-mass[1][0]*j-mass[2][0]*k)/mass[3][0] # rrr=round((measured_mass-mass[0][0]*i-mass[1][0]*j-mass[2][0]*k)/mass[3][0]) # rrrr=int(round((measured_mass-mass[0][0]*i-mass[1][0]*j-mass[2][0]*k)/mass[3][0])) # print "rr:%s"%rr+" rrr:%s"%rrr+" rrrr:%s"%rrrr r=int(round((measured_mass-mass[0][0]*i-mass[1][0]*j-mass[2][0]*k)/mass[3][0])) calmass=mass[0][0]*i+mass[1][0]*j+mass[2][0]*k+mass[3][0]*r if (mass[0][1]*i+mass[2][1]*k+mass[3][1]*r)>=-1 and calmass>limit_lo and calmass<limit_hi: calc_mass.append((calmass,i,j,k,r)) print len(calc_mass) for ii in range(0,len(calc_mass)): mda=(measured_mass-calc_mass[ii][0])*1000 ppm=(measured_mass-calc_mass[ii][0])/measured_mass*1000000 DBE=(calc_mass[ii][1]*2+calc_mass[ii][3]-calc_mass[ii][4]+2)/2.0 self.calmass="%.4f"%calc_mass[ii][0] self.mda="%.1f"%mda self.ppm="%.1f"%ppm self.DBE="%.1f"%DBE self.C="%s"%calc_mass[ii][1] self.H="%s"%calc_mass[ii][4] self.N="%s"%calc_mass[ii][3] self.O="%s"%calc_mass[ii][2] self.Formula="C%2s"%self.C+" H%2s"%self.H+" N%2s"%self.N+" O%2s"%self.O mass=str(self.xp) # if not(ii==0): # mass="" self.cal_isotopic() self.initPlots() self.conf="%.1f"%self.mass_diff self.table.insertRow(ii) self.table.setRowHeight(ii,20) self.table.setItem(ii, 0,QTableWidgetItem(mass)) self.table.setItem(ii, 1,QTableWidgetItem(self.calmass)) self.table.setItem(ii, 2,QTableWidgetItem(self.mda)) self.table.setItem(ii, 3,QTableWidgetItem(self.ppm)) self.table.setItem(ii, 4,QTableWidgetItem(self.DBE)) self.table.setItem(ii, 5,QTableWidgetItem(self.Formula)) self.table.setItem(ii, 6,QTableWidgetItem(self.conf)) self.table.setItem(ii, 7,QTableWidgetItem(self.C)) self.table.setItem(ii, 8,QTableWidgetItem(self.H)) self.table.setItem(ii, 9,QTableWidgetItem(self.N)) self.table.setItem(ii, 10,QTableWidgetItem(self.O)) item=QTreeWidgetItem([mass,str(self.calmass),str(self.mda),str(self.ppm),str(self.DBE),self.Formula,str(self.conf),str(self.C),str(self.H),str(self.N),str(self.O)]) self.list.addTopLevelItem(item) self.table.removeRow(len(calc_mass)) self.table.setSortingEnabled(True) # self.table.sortByColumn(1,Qt.DescendingOrder) def next2pow(self): return 2**int(np.ceil(np.log(float(self.xx))/np.log(2.0))) def cal_isotopic(self): MAX_ELEMENTS=5+1 # add 1 due to mass correction 'element' MAX_ISOTOPES=4 # maxiumum # of isotopes for one element CUTOFF=1e-4 # relative intensity cutoff for plotting WINDOW_SIZE = 500 #WINDOW_SIZE=input('Window size (in Da) ---> '); #RESOLUTION=input('Resolution (in Da) ----> '); % mass unit used in vectors RESOLUTION = 1 if RESOLUTION < 0.00001:# % minimal mass step allowed RESOLUTION = 0.00001 elif RESOLUTION > 0.5: # maximal mass step allowed RESOLUTION = 0.5 R=0.00001/RESOLUTION# % R is used to scale nuclide masses (see below) WINDOW_SIZE=WINDOW_SIZE/RESOLUTION; self.xx=WINDOW_SIZE # convert window size to new mass units WINDOW_SIZE=self.next2pow(); # fast radix-2 fast-Fourier transform algorithm if WINDOW_SIZE < np.round(496708*R)+1: WINDOW_SIZE = self.next2pow(np.round(496708*R)+1) # just to make sure window is big enough #H378 C254 N65 O75 S6 M=np.array([int(self.H),int(self.C),int(self.N),int(self.O),0,0]) #% empiric formula, e.g. bovine insulin # isotopic abundances stored in matrix A (one row for each element) A=np.zeros((MAX_ELEMENTS,MAX_ISOTOPES,2)); A[0][0,:] = [100783,0.9998443]# % 1H A[0][1,:] = [201410,0.0001557]# % 2H A[1][0,:] = [100000,0.98889]# % 12C A[1][1,:] = [200336,0.01111]# % 13C A[2][0,:] = [100307,0.99634]# % 14N A[2][1,:] = [200011,0.00366]# % 15N A[3][0,:] = [99492,0.997628]# % 16O A[3][1,:] = [199913,0.000372]# % 17O A[3][2,:] = [299916,0.002000]# % 18O A[4][0,:] = [97207,0.95018]# % 32S A[4][1,:] = [197146,0.00750]# % 33S A[4][2,:] = [296787,0.04215]# % 34S A[4][3,:] = [496708,0.00017]# % 36S A[5][0,:] = [100000,1.00000]# % for shifting mass so that Mmi is # % near left limit of window Mmi=np.array([np.round(100783*R), np.round(100000*R),\ np.round(100307*R),np.round(99492*R), np.round(97207*R), 0])*M# % (Virtual) monoisotopic mass in new units Mmi = Mmi.sum() #% mass shift so Mmi is in left limit of window: FOLDED=np.floor(Mmi/(WINDOW_SIZE-1))+1# % folded FOLDED times (always one folding due to shift below) #% shift distribution to 1 Da from lower window limit: M[MAX_ELEMENTS-1]=np.ceil(((WINDOW_SIZE-1)-np.mod(Mmi,WINDOW_SIZE-1)+np.round(100000*R))*RESOLUTION) MASS_REMOVED=np.array([0,11,13,15,31,-1])*M#% correction for 'virtual' elements and mass shift begin=WINDOW_SIZE*RESOLUTION+MASS_REMOVED.sum() end=2*(WINDOW_SIZE-1)*RESOLUTION+MASS_REMOVED.sum() ptA=np.ones(WINDOW_SIZE); t_fft=0 t_mult=0 for i in xrange(MAX_ELEMENTS): tA=np.zeros(WINDOW_SIZE) for j in xrange(MAX_ISOTOPES): if A[i][j,0] != 0: #removed +1 after R)+1 --we're using python tA[np.round(A[i][j,0]*R)]=A[i][j,1]#; % put isotopic distribution in tA t0 = time.clock() tA=F.fft(tA) # FFT along elements isotopic distribution O(nlogn) t_fft = time.clock()-t0 t0 = time.clock() tA=tA**M[i]# % O(n) ################# ptA = ptA*tA# % O(n)#this is where it is messing UP ################# t1 = time.clock() t_mult=t1-t0 t0=time.clock() ptA=F.ifft(ptA).real#; % O(nlogn) t0=time.clock() MA=np.linspace(begin,end,WINDOW_SIZE-1) ind=np.where(ptA>CUTOFF)[0] self.x = MA[ind] self.y = ptA[ind] self.x_min=int(np.min(self.x)-(np.max(self.x)-np.min(self.x))) self.x_max=int(np.min(self.x)+(np.max(self.x)-np.min(self.x))) self.mass_y=np.ones(len(self.x)) mass_diff=np.ones(len(self.x)) mzInd= np.logical_and((self.mz>=self.x_min),(self.mz<=self.x_max)) self.mass_y=self.mass[mzInd] self.mass_x=self.mz[mzInd] # for i in range(len(self.x)): # self.mass_y[i]=self.mass[int(self.x[i])] self.massy=np.max(self.mass_y) print self.massy self.mass_y=self.mass_y/max(self.mass_y)*100 self.y=self.y/max(self.y)*100 # k=(self.mass_y*self.y).sum()/(self.mass_y*self.mass_y).sum() # self.fit=((k*self.mass_y-self.y)*(k*self.mass_y-self.y)).sum()/(self.y*self.y).sum() for i in range(len(self.y)): mass_diff[i]=np.abs(self.mass_y[i]-self.y[i])/(self.mass_y[i]+self.y[i]) self.mass_diff=(1-mass_diff.sum()/len(mass_diff))*100
class UpdateDialog(QDialog): def __init__(self, update_script): super(UpdateDialog, self).__init__(None, Qt.Window) self.updates_to_run = [] self.setWindowTitle("emzed updates") self.setWindowModality(Qt.WindowModal) self.setMinimumWidth(600) self.update_script = update_script self.setup_widgets() self.setup_layout() self.connect_signals() wd = QApplication.desktop().width() hd = QApplication.desktop().height() w = self.size().width() h = self.size().height() self.move((wd - w) / 2, (hd - h) / 2) def showEvent(self, evt): self.setCursor(Qt.WaitCursor) class WorkerThread(QThread): def run(self, script=self.update_script, parent=self): try: for method, args in script(parent.add_info_line, parent.add_update_info): self.emit(SIGNAL("execute_method(PyQt_PyObject, PyQt_PyObject)"), method, args) except: import traceback tb = traceback.format_exc() self.emit(SIGNAL("execute_method(PyQt_PyObject, PyQt_PyObject)"), parent.add_info_line, (tb,)) self.emit(SIGNAL("update_query_finished()")) self.t = WorkerThread() self.connect(self.t, SIGNAL("update_query_finished()"), self.start_to_interact) self.connect( self.t, SIGNAL("execute_method(PyQt_PyObject,PyQt_PyObject)"), self.execute_method) try: self.t.start() finally: self.setCursor(Qt.ArrowCursor) def execute_method(self, meth, args): meth(*args) def start_to_interact(self): self.ok_button.setEnabled(True) def setup_widgets(self): self.label_info = QLabel("updates from exchange folder:") self.info = QTextEdit(self) self.info.setReadOnly(1) self.label_updates = QLabel("updates from internet:") self.updates = QTableWidget(0, 3) self.updates.setHorizontalHeaderLabels(["updater", "info", "try updatde ?"]) self.updates.verticalHeader().hide() self.updates.horizontalHeader().setResizeMode(0, QHeaderView.Stretch) self.updates.horizontalHeader().setResizeMode(1, QHeaderView.Stretch) self.ok_button = QPushButton("OK") self.ok_button.setEnabled(False) def setup_layout(self): layout = QVBoxLayout() self.setLayout(layout) layout.addWidget(self.label_info) layout.addWidget(self.info) layout.addWidget(self.label_updates) layout.addWidget(self.updates) button_layout = QHBoxLayout() button_layout.addStretch() button_layout.addWidget(self.ok_button) layout.addLayout(button_layout) def connect_signals(self): self.connect(self.ok_button, SIGNAL("pressed()"), self.accept) def ok_button_pressed(self): self.info.append("hi") self.add_update_info("updater", "info") def _item(self, content, is_checkable): item = QTableWidgetItem(content) if is_checkable: item.setCheckState(Qt.Unchecked) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsSelectable) return item def add_update_info(self, updater_id, info, with_checkbox=True): i = self.updates.rowCount() self.updates.insertRow(i) self.updates.setItem(i, 0, self._item(updater_id, False)) self.updates.setItem(i, 1, self._item(info, False)) if True or with_checkbox: self.updates.setItem(i, 2, self._item("", True)) def add_info_line(self, txt): self.info.append(txt) def get_updates_to_run(self): return self.updates_to_run def accept(self): for i in range(self.updates.rowCount()): updater_id = str(self.updates.item(i, 0).text()) item = self.updates.item(i, 2) if item is not None: # some cells in column are empty checked = self.updates.item(i, 2).checkState() == Qt.Checked if checked: self.updates_to_run.append(updater_id) super(UpdateDialog, self).accept()
class GroupsPostView(QDialog): """ +------------------------+ | Groups : Post/Delete | +------------------------+ | | | check1 Name1 | | check2 Name2 | | check3 Name3 | | | | SetAsMain | | Apply OK Close | +------------------------+ """ def __init__(self, data, win_parent=None): self.win_parent = win_parent #Init the base class groups = data['groups'] inames = data['inames'] self.imain = data['imain'] self.names = [group.name for group in groups] self.white = (255, 255, 255) self.light_grey = (211, 211, 211) self.inames = inames self.shown_set = data['shown'] self.deleted_groups = set([]) #self.inames = argsort(self.names) #print('inames =', inames) anames = array(self.names) for iname, name in enumerate(anames[self.inames]): print('name[%s] = %r' % (iname, name)) # ignore these... #self._default_name = data['name'] #self._default_coords = data['coords'] #self._default_elements = data['elements'] #self._default_color = data['color'] #self.coords_pound = data['coords_pound'] #self.elements_pound = data['elements_pound'] #self._default_is_discrete = data['is_discrete'] self.out_data = data QDialog.__init__(self, win_parent) #self.setupUi(self) self.setWindowTitle('Groups: Post/View') self.create_widgets() self.create_layout() self.set_connections() #self.show() def create_widgets(self): # main/delete/supergroup self.set_as_main_button = QPushButton("Set As Main") self.create_super_group_button = QPushButton("Create Super Group") self.delete_groups_button = QPushButton("Delete Groups") self.revert_groups_button = QPushButton("Revert Groups") self.show_groups_button = QPushButton("Show Groups") self.hide_groups_button = QPushButton("Hide Groups") # closing self.apply_button = QPushButton("Apply") self.ok_button = QPushButton("OK") self.cancel_button = QPushButton("Cancel") #table self.table = QTableWidget() self.checks = [] self.names_text = [] bold = QtGui.QFont() bold.setBold(True) bold.setItalic(True) bold.setWeight(75) anames = array(self.names) for iname, name in enumerate(anames[self.inames]): check = QTableWidgetItem() check.setCheckState(False) # TODO: create right click menu ??? name_text = QTableWidgetItem(str(name)) if iname == self.imain: name_text.setFont(bold) self.shown_set.add(iname) check.setCheckState(2) name_text.setBackground(QtGui.QColor(*self.light_grey)) elif iname in self.shown_set: name_text.setBackground(QtGui.QColor(*self.light_grey)) self.checks.append(check) self.names_text.append(name_text) def create_layout(self): nrows = len(self.names) table = self.table table.setRowCount(nrows) table.setColumnCount(2) headers = [QString('Operate On'), QString('Name')] table.setHorizontalHeaderLabels(headers) header = table.horizontalHeader() header.setStretchLastSection(True) #table.setAlternatingRowColors(True) #header = table.verticalHeader() #header.setStretchLastSection(True) #table.resize(400, 250) #heighti = table.rowHeight(0) #total_height = nrows * heighti #table.setMaximumHeight(total_height) #table.resize(total_height, None) #for iname, name in enumerate(self.names[self.inames]): #print('name[%s] = %r' % (iname, name)) for iname in self.inames: check = self.checks[iname] name_text = self.names_text[iname] # row, col, value table.setItem(iname, 0, check) table.setItem(iname, 1, name_text) table.resizeRowsToContents() #table.horizontalHeaderItem(1).setTextAlignment(QtCore.AlignHCenter) #= QVBoxLayout() ok_cancel_box = QHBoxLayout() ok_cancel_box.addWidget(self.apply_button) ok_cancel_box.addWidget(self.ok_button) ok_cancel_box.addWidget(self.cancel_button) vbox = QVBoxLayout() vbox.addWidget(table) vbox.addWidget(self.set_as_main_button) #vbox.addWidget(self.create_super_group_button) vbox.addStretch() vbox.addWidget(self.show_groups_button) vbox.addWidget(self.hide_groups_button) vbox.addStretch() vbox.addWidget(self.delete_groups_button) vbox.addWidget(self.revert_groups_button) vbox.addStretch() vbox.addStretch() vbox.addLayout(ok_cancel_box) self.setLayout(vbox) def set_connections(self): if qt_version == 4: self.connect(self.set_as_main_button, QtCore.SIGNAL('clicked()'), self.on_set_as_main) self.connect(self.delete_groups_button, QtCore.SIGNAL('clicked()'), self.on_delete_groups) self.connect(self.revert_groups_button, QtCore.SIGNAL('clicked()'), self.on_revert_groups) self.connect(self.show_groups_button, QtCore.SIGNAL('clicked()'), self.on_show_groups) self.connect(self.hide_groups_button, QtCore.SIGNAL('clicked()'), self.on_hide_groups) self.connect(self.create_super_group_button, QtCore.SIGNAL('clicked()'), self.on_create_super_group) self.connect(self.apply_button, QtCore.SIGNAL('clicked()'), self.on_apply) self.connect(self.ok_button, QtCore.SIGNAL('clicked()'), self.on_ok) self.connect(self.cancel_button, QtCore.SIGNAL('clicked()'), self.on_cancel) else: self.set_as_main_button.clicked.connect(self.on_set_as_main) self.delete_groups_button.clicked.connect(self.on_delete_groups) self.revert_groups_button.clicked.connect(self.on_revert_groups) self.show_groups_button.clicked.connect(self.on_show_groups) self.hide_groups_button.clicked.connect(self.on_hide_groups) self.create_super_group_button.clicked.connect( self.on_create_super_group) self.apply_button.clicked.connect(self.on_apply) self.ok_button.clicked.connect(self.on_ok) self.cancel_button.clicked.connect(self.on_cancel) def closeEvent(self, event): event.accept() @property def nrows(self): return self.table.rowCount() def on_hide_groups(self): self._set_highlight(self.white) def on_show_groups(self): self._set_highlight(self.light_grey) def _set_highlight(self, color): for irow in range(self.nrows): check = self.checks[irow] is_checked = check.checkState() # 0 - unchecked # 1 - partially checked (invalid) # 2 - checked if is_checked: name_text = self.names_text[irow] name_text.setBackground(QtGui.QColor(*color)) def on_delete_groups(self): for irow in range(self.nrows): check = self.checks[irow] is_checked = check.checkState() # 0 - unchecked # 1 - partially checked (invalid) # 2 - checked if irow == 0 and is_checked: # TODO: change this to a log print('error deleting group ALL...change this to a log') #self.window_parent.log return if is_checked: self.table.hideRow(irow) self.deleted_groups.add(irow) check.setCheckState(0) if self.imain > 0 and self.shown_set == set([0]): bold = QtGui.QFont() bold.setBold(True) bold.setItalic(True) self.imain = 0 irow = 0 check = self.checks[irow] name_text = self.names_texts[irow] name_text.setFont(bold) name_text.setBackground(QtGui.QColor(*self.light_grey)) def on_revert_groups(self): for irow in range(self.nrows): self.table.showRow(irow) self.deleted_groups = set([]) def on_create_super_group(self): inames = [ iname for iname, check in enumerate(self.checks) if bool(check.checkState()) ] if not len(inames): # TODO: add logging print('nothing is checked...') return if inames[0] == 0: # TODO: add logging print("cannot include 'ALL' in supergroup...") return name = 'SuperGroup' # popup gui and get a name irow = self.table.rowCount() self.table.insertRow(irow) check = QTableWidgetItem() check.setCheckState(False) name_text = QTableWidgetItem(str(name)) self.names.extend(name) self.names_text.append(name_text) self.checks.append(check) self.table.setItem(irow, 0, check) self.table.setItem(irow, 1, name_text) def on_set_as_main(self): bold = QtGui.QFont() bold.setBold(True) bold.setItalic(True) normal = QtGui.QFont() normal.setBold(False) normal.setItalic(False) imain = None imain_set = False for irow in range(self.nrows): check = self.checks[irow] name_text = self.names_text[irow] is_checked = check.checkState() # 0 - unchecked # 1 - partially checked (invalid) # 2 - checked if is_checked and not imain_set: # TODO: change this to a log #self.window_parent.log imain_set = True imain = irow name_text.setFont(bold) name_text.setBackground(QtGui.QColor(*self.light_grey)) self.shown_set.add(irow) elif irow == self.imain: name_text.setFont(normal) if irow == 0: name_text.setBackground(QtGui.QColor(*self.white)) if irow in self.shown_set: self.shown_set.remove(irow) elif imain == 0: name_text.setBackground(QtGui.QColor(*self.white)) self.shown_set.remove(imain) self.imain = imain def get_main_group(self): return self.imain def get_shown_group(self): return self.shown_set def get_deleted_groups(self): return self.deleted_groups def on_validate(self): flag0 = flag1 = flag2 = True main_group_id = self.get_main_group() shown_groups_ids = self.get_shown_group() deleted_group_ids = self.get_deleted_groups() if flag0 and flag1 and flag2: self.out_data['imain'] = main_group_id self.out_data['shown'] = shown_groups_ids self.out_data['remove'] = deleted_group_ids self.out_data['clicked_ok'] = True return True return False def on_apply(self): passed = self.on_validate() if passed: self.win_parent.on_post_group(self.out_data) def on_ok(self): passed = self.on_validate() if passed: self.close() #self.destroy() def on_cancel(self): self.close()
class NewRelationDialog(QDialog): def __init__(self, parent=None): QDialog.__init__(self, parent) self.setWindowTitle(self.tr("Nueva Relación")) vbox = QVBoxLayout(self) hbox = QHBoxLayout() self._line_relation_name = QLineEdit() hbox.addWidget(QLabel(self.tr("Nombre:"))) hbox.addWidget(self._line_relation_name) vbox.addLayout(hbox) vbox.addWidget(QLabel( self.tr("La primera fila corresponde a los campos"))) hbox = QHBoxLayout() btn_add_column = QPushButton(self.tr("Agregar Columna")) hbox.addWidget(btn_add_column) btn_add_tuple = QPushButton(self.tr("Agregar Tupla")) hbox.addWidget(btn_add_tuple) btn_remove_column = QPushButton(self.tr("Eliminar Columna")) hbox.addWidget(btn_remove_column) btn_remove_tuple = QPushButton(self.tr("Eliminar Tupla")) hbox.addWidget(btn_remove_tuple) vbox.addLayout(hbox) self._table = QTableWidget() vbox.addWidget(self._table) self._table.setRowCount(1) self._table.setColumnCount(2) self._table.setItem(0, 0, QTableWidgetItem("Campo 1")) self._table.setItem(0, 1, QTableWidgetItem("Campo 2")) hbox = QHBoxLayout() hbox.addItem(QSpacerItem(1, 0, QSizePolicy.Expanding)) btn_ok = QPushButton(self.tr("Aceptar")) hbox.addWidget(btn_ok) btn_cancel = QPushButton(self.tr("Cancelar")) hbox.addWidget(btn_cancel) vbox.addLayout(hbox) # Connections self.connect(btn_add_column, SIGNAL("clicked()"), self.__add_column) self.connect(btn_remove_column, SIGNAL("clicked()"), self.__remove_column) self.connect(btn_add_tuple, SIGNAL("clicked()"), self.__add_tuple) self.connect(btn_remove_tuple, SIGNAL("clicked()"), self.__remove_tuple) self.connect(btn_ok, SIGNAL("clicked()"), self.__create_table) self.connect(btn_cancel, SIGNAL("clicked()"), self.close) def __add_column(self): columns = self._table.columnCount() self._table.insertColumn(columns) def __remove_column(self): current = self._table.currentColumn() self._table.removeColumn(current) def __add_tuple(self): tuples = self._table.rowCount() self._table.insertRow(tuples) def __remove_tuple(self): current = self._table.currentRow() self._table.removeRow(current) def __create_table(self): # Name of relation name = self._line_relation_name.text() if not name.strip(): QMessageBox.critical(self, self.tr("Error"), self.tr("Nombre de relación no especificado")) return rows = self._table.rowCount() columns = self._table.columnCount() rel = relation.Relation() # Header of relation fields = [] for i in range(columns): text = self._table.item(0, i).text() if not text.strip(): QMessageBox.critical(self, self.tr("Error"), self.tr("Nombre de campo inválido")) return fields.append(text) rel.fields = fields # Data data = {} for row in range(1, rows): reg = [] for column in range(columns): item = self._table.item(row, column) if item is None or not item.text().strip(): QMessageBox.critical(self, self.tr("Campo vacío"), self.tr("El campo {0}:{1} está " "vacío").format(row + 1, column + 1)) return reg.append(self._table.item(row, column).text()) data[row, column] = self._table.item(row, column).text() rel.insert(reg) # Add table and relation table_widget = Pireal.get_service("container").table_widget table_widget.add_table(rows - 1, columns, name, data, fields) table_widget.relations[name] = rel self.close()
class UpdateDialog(QDialog): def __init__(self, update_script): super(UpdateDialog, self).__init__(None, Qt.Window) self.updates_to_run = [] self.setWindowTitle("emzed updates") self.setWindowModality(Qt.WindowModal) self.setMinimumWidth(600) self.update_script = update_script self.setup_widgets() self.setup_layout() self.connect_signals() wd = QApplication.desktop().width() hd = QApplication.desktop().height() w = self.size().width() h = self.size().height() self.move((wd - w) / 2, (hd - h) / 2) def showEvent(self, evt): self.setCursor(Qt.WaitCursor) class WorkerThread(QThread): def run(self, script=self.update_script, parent=self): try: for method, args in script(parent.add_info_line, parent.add_update_info): self.emit(SIGNAL("execute_method(PyQt_PyObject, PyQt_PyObject)"), method, args) except: import traceback tb = traceback.format_exc() self.emit(SIGNAL("execute_method(PyQt_PyObject, PyQt_PyObject)"), parent.add_info_line, (tb,)) self.emit(SIGNAL("update_query_finished()")) self.t = WorkerThread() self.connect(self.t, SIGNAL("update_query_finished()"), self.start_to_interact) self.connect( self.t, SIGNAL("execute_method(PyQt_PyObject,PyQt_PyObject)"), self.execute_method) try: self.t.start() finally: self.setCursor(Qt.ArrowCursor) def execute_method(self, meth, args): meth(*args) def start_to_interact(self): self.ok_button.setEnabled(True) def setup_widgets(self): self.label_info = QLabel("updates from exchange folder:") self.info = QTextEdit(self) self.info.setReadOnly(1) self.label_updates = QLabel("updates from internet:") self.updates = QTableWidget(0, 3) self.updates.setHorizontalHeaderLabels(["updater", "info", "try updatde ?"]) self.updates.verticalHeader().hide() self.updates.horizontalHeader().setResizeMode(0, QHeaderView.Stretch) self.updates.horizontalHeader().setResizeMode(1, QHeaderView.Stretch) self.ok_button = QPushButton("OK") self.ok_button.setEnabled(False) def setup_layout(self): layout = QVBoxLayout() self.setLayout(layout) layout.addWidget(self.label_info) layout.addWidget(self.info) layout.addWidget(self.label_updates) layout.addWidget(self.updates) button_layout = QHBoxLayout() button_layout.addStretch() button_layout.addWidget(self.ok_button) layout.addLayout(button_layout) def connect_signals(self): self.connect(self.ok_button, SIGNAL("pressed()"), self.accept) def ok_button_pressed(self): self.info.append("hi") self.add_update_info("updater", "info") def _item(self, content, is_checkable): item = QTableWidgetItem(str(content)) if is_checkable: item.setCheckState(Qt.Unchecked) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsSelectable) return item def add_update_info(self, updater_id, info, with_checkbox=True): i = self.updates.rowCount() self.updates.insertRow(i) self.updates.setItem(i, 0, self._item(updater_id, False)) self.updates.setItem(i, 1, self._item(info, False)) if True or with_checkbox: self.updates.setItem(i, 2, self._item("", True)) def add_info_line(self, txt): self.info.append(txt) def get_updates_to_run(self): return self.updates_to_run def accept(self): for i in range(self.updates.rowCount()): updater_id = str(self.updates.item(i, 0).text()) item = self.updates.item(i, 2) if item is not None: # some cells in column are empty checked = self.updates.item(i, 2).checkState() == Qt.Checked if checked: self.updates_to_run.append(updater_id) super(UpdateDialog, self).accept()
class LabelAssistDialog(QDialog): """ A simple UI for showing bookmarks and navigating to them. FIXME: For now, this window is tied to a particular lane. If your project has more than one lane, then each one will have it's own bookmark window, which is kinda dumb. """ def __init__(self, parent, topLevelOperatorView): super(LabelAssistDialog, self).__init__(parent) # Create thread router to populate table on main thread self.threadRouter = ThreadRouter(self) # Set object classification operator view self.topLevelOperatorView = topLevelOperatorView self.setWindowTitle("Label Assist") self.setMinimumWidth(500) self.setMinimumHeight(700) layout = QGridLayout() layout.setContentsMargins(10, 10, 10, 10) # Show variable importance table rows = 0 columns = 4 self.table = QTableWidget(rows, columns) self.table.setHorizontalHeaderLabels(['Frame', 'Max Area', 'Min Area', 'Labels']) self.table.verticalHeader().setVisible(False) # Select full row on-click and call capture double click self.table.setSelectionBehavior(QTableView.SelectRows); self.table.doubleClicked.connect(self._captureDoubleClick) layout.addWidget(self.table, 1, 0, 3, 2) # Create progress bar self.progressBar = QProgressBar() self.progressBar.setMinimum(0) self.progressBar.setMaximum(0) self.progressBar.hide() layout.addWidget(self.progressBar, 4, 0, 1, 2) # Create button to populate table self.computeButton = QPushButton('Compute object info') self.computeButton.clicked.connect(self._triggerTableUpdate) layout.addWidget(self.computeButton, 5, 0) # Create close button closeButton = QPushButton('Close') closeButton.clicked.connect(self.close) layout.addWidget(closeButton, 5, 1) # Set dialog layout self.setLayout(layout) def _triggerTableUpdate(self): # Check that object area is included in selected features featureNames = self.topLevelOperatorView.SelectedFeatures.value if 'Standard Object Features' not in featureNames or 'Count' not in featureNames['Standard Object Features']: box = QMessageBox(QMessageBox.Warning, 'Warning', 'Object area is not a selected feature. Please select this feature on: \"Standard Object Features > Shape > Size in pixels\"', QMessageBox.NoButton, self) box.show() return # Clear table self.table.clearContents() self.table.setRowCount(0) self.table.setSortingEnabled(False) self.progressBar.show() self.computeButton.setEnabled(False) def compute_features_for_frame(tIndex, t, features): # Compute features and labels (called in parallel from request pool) roi = [slice(None) for i in range(len(self.topLevelOperatorView.LabelImages.meta.shape))] roi[tIndex] = slice(t, t+1) roi = tuple(roi) frame = self.topLevelOperatorView.SegmentationImages(roi).wait() frame = frame.squeeze().astype(numpy.uint32, copy=False) # Dirty trick: We don't care what we're passing here for the 'image' parameter, # but vigra insists that we pass *something*, so we'll cast the label image as float32. features[t] = vigra.analysis.extractRegionFeatures(frame.view(numpy.float32), frame, ['Count'], ignoreLabel=0) tIndex = self.topLevelOperatorView.SegmentationImages.meta.axistags.index('t') tMax = self.topLevelOperatorView.SegmentationImages.meta.shape[tIndex] features = {} labels = {} def compute_all_features(): # Compute features in parallel pool = RequestPool() for t in range(tMax): pool.add( Request( partial(compute_features_for_frame, tIndex, t, features) ) ) pool.wait() # Compute labels labels = self.topLevelOperatorView.LabelInputs([]).wait() req = Request(compute_all_features) req.notify_finished( partial(self._populateTable, features, labels) ) req.submit() @threadRouted def _populateTable(self, features, labels, *args): self.progressBar.hide() self.computeButton.setEnabled(True) for time, feature in features.iteritems(): # Insert row rowNum = self.table.rowCount() self.table.insertRow(self.table.rowCount()) # Get max and min object areas areas = feature['Count']#objectFeatures['Standard Object Features']['Count'] maxObjArea = numpy.max(areas[numpy.nonzero(areas)]) minObjArea = numpy.min(areas[numpy.nonzero(areas)]) # Get number of labeled objects labelNum = numpy.count_nonzero(labels[time]) # Load fram number item = QTableWidgetItem(str(time)) item.setFlags( Qt.ItemIsSelectable | Qt.ItemIsEnabled ) self.table.setItem(rowNum, 0, item) # Load max object areas item = QTableWidgetItemWithFloatSorting(str("{: .02f}".format(maxObjArea))) item.setFlags( Qt.ItemIsSelectable | Qt.ItemIsEnabled ) self.table.setItem(rowNum, 1, item) # Load min object areas item = QTableWidgetItemWithFloatSorting(str("{: .02f}".format(minObjArea))) item.setFlags( Qt.ItemIsSelectable | Qt.ItemIsEnabled ) self.table.setItem(rowNum, 2, item) # Load label numbers item = QTableWidgetItemWithFloatSorting(str("{: .01f}".format(labelNum))) item.setFlags( Qt.ItemIsSelectable | Qt.ItemIsEnabled ) self.table.setItem(rowNum, 3, item) # Resize column size to fit dialog size self.table.horizontalHeader().setResizeMode(QHeaderView.Stretch) # Sort by max object area self.table.setSortingEnabled(True) self.table.sortByColumn(1) def _captureDoubleClick(self): # Navigate to selected frame index = self.table.selectedIndexes()[0] frameStr = self.table.model().data(index).toString() if frameStr: frameNum = int(frameStr) self.parent().editor.posModel.time = frameNum
class MainWindow(QtGui.QMainWindow): def __init__(self, parent=None): logging.info(u'创建主窗口...') QtGui.QMainWindow.__init__(self, parent) tabs = QtGui.QTabWidget(self) tab2 = QtGui.QWidget() tab3 = QtGui.QWidget() self.console = MyConsole(parent=self) # tab2 - self.console self.console.setMinimumSize(1500, 800) scroll = QtGui.QScrollArea() scroll.setWidget(self.console) scroll.setAutoFillBackground(True) scroll.setWidgetResizable(True) vbox = QtGui.QVBoxLayout() vbox.addWidget(scroll) tab2.setLayout(vbox) # tab3 - self.viewEntry = QTableWidget(0, 12) self.viewEntry.setHorizontalHeaderLabels( [u'期数', u'时间', u'冠军', u'亚军', u'第三名', u'第四名', u'第五名', u'第六名', u'第七名', u'第八名', u'第九名', u'第十名']) self.viewEntry.horizontalHeader().setStretchLastSection(True) self.viewEntry.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch) vbox3 = QtGui.QVBoxLayout() vbox3.addWidget(self.viewEntry) tab3.setLayout(vbox3) tabs.addTab(tab2, u"控制台") tabs.addTab(tab3, u"开奖结果") tabs.resize(1500, 800) self.resize(1500, 800) self.tabs = tabs self.tab2 = tab2 self.tab3 = tab3 self.scroll = scroll # 禁止最大化 self.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint) from myutil.tool.Overlay import Overlay self.setCentralWidget(self.tabs) self.overlay = Overlay(self.centralWidget()) self.overlay.hide() self.show() @pyqtSlot(str) def mySetWindowTitle(self, title): self.setWindowTitle(title) @pyqtSlot(str, list) def completeHistoryResultData(self, timesnow, open_balls): logging.info(u"【主窗口-历史数据展板-填充之】") for i in range(len(open_balls)): newItem = QTableWidgetItem(str(open_balls[i])) self.viewEntry.setItem(0, 2 + i, newItem) logging.info(u"【主窗口-历史数据展板-填充完毕】") @pyqtSlot(str, list) def appendHistoryResultData(self, timesnow, open_balls): logging.info(u"【主窗口-历史数据展板-追加】") time_str = MyTool.getCurrentTimeStr() self.viewEntry.insertRow(0) # 期数 newItem = QTableWidgetItem(str(int(timesnow) - 1)) self.viewEntry.setItem(0, 0, newItem) # 时间 newItem = QTableWidgetItem(time_str) self.viewEntry.setItem(0, 1, newItem) for i in range(len(open_balls)): newItem = QTableWidgetItem(str(open_balls[i])) self.viewEntry.setItem(0, 2 + i, newItem) logging.info(u"【主窗口-历史数据展板-追加完毕】") @pyqtSlot(list) def updateHistoryResultData(self, data_list): logging.info(u"【主窗口-历史数据展板-大更新】################START HistoryResultData################") # 先清空... self.viewEntry.clearContents() self.viewEntry.setRowCount(0) for period in data_list: # 添加一行 row = self.viewEntry.rowCount() self.viewEntry.insertRow(row) # 期数 newItem = QTableWidgetItem(period[0]) self.viewEntry.setItem(row, 0, newItem) # 时间 newItem = QTableWidgetItem(str(period[1])) self.viewEntry.setItem(row, 1, newItem) if self.console.play_mode in [common.PLAYMODE_PK10, common.PLAYMODE_XYFT]: for i in range(10): newItem = QTableWidgetItem(str(period[2 + i])) self.viewEntry.setItem(row, 2 + i, newItem) else: for i in range(5): newItem = QTableWidgetItem(str(period[2 + i])) self.viewEntry.setItem(row, 2 + i, newItem) logging.info(u"【主窗口-历史数据展板-大更新】################END HistoryResultData################") def closeEvent(self, event): reply = QtGui.QMessageBox.question(self, u'退出', u"您确定离开吗?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) if reply == QtGui.QMessageBox.Yes: # 关闭http连接... from common.common import req_session req_session.close() event.accept() else: event.ignore() def resizeEvent(self, event): self.overlay.resize(event.size()) event.accept()
class PvTunerDlg(QDialog): COL = 6 COL_ELEMENT = 0 COL_FIELD = 1 COL_PV = 2 COL_STEPSIZE = 3 COL_READBACK = 4 COL_SETPOINT = 5 FMT_READBACK = "%.4e" def __init__(self, parent=None): super(PvTunerDlg, self).__init__(parent) self.setAttribute(Qt.WA_DeleteOnClose) #self.inputBox = QLineEdit("PL2G2C01A.x") #self.inputBox = QLineEdit("CXH2G6C01B.x") self.inputBox = QLineEdit("PL2G2C01A") addPvBtn = QPushButton("add") self.table = QTableWidget(0, PvTunerDlg.COL) self.table.setHorizontalHeaderLabels( ["Element", "Field", "PV", "Stepsize", "Readback", "setpoint"]) #self.table.horizontalHeader().setStretchLastSection(True) #self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) buttonBox = QDialogButtonBox(QDialogButtonBox.Ok) box = QGridLayout() box.addWidget(self.inputBox, 0, 0) box.addWidget(addPvBtn, 0, 1) box.addWidget(self.table, 1, 0, 1, 2) box.addWidget(buttonBox, 2, 0) self.setLayout(box) self.pvs_rb = [] self.pvs_rb_val_flat = [] self.pvs_sp = [] self.pvmoni = [] self.spinbox = [] self.connect(addPvBtn, SIGNAL("clicked()"), self.addPv) self.connect(buttonBox, SIGNAL("accepted()"), self.accept) #self.connect(self.table, SIGNAL("cellChanged"), self.updatePv) self.connect(buttonBox.button(QDialogButtonBox.Ok), SIGNAL("clicked()"), self.close) self.connect(self.table, SIGNAL("cellClicked(int, int)"), self._cell_clicked) def _cell_clicked(self, row, column): #print row, column if column in [self.COL_PV, self.COL_STEPSIZE]: item = self.table.item(row, column) if not item: return item.setFlags(item.flags() | Qt.ItemIsEditable) def _appendRecord(self, name): vec = name.split('.') if len(vec) > 2: QMessageBox.critical(None, "ERROR", "format is wrong") return if len(vec) == 1: elem, field = vec[0], 'value' elif len(vec) == 2: elem, field = vec elemobj = hla.getElements(elem) if elemobj: # pvsrb is a list pvsrb = elemobj.pv(field=field, handle='readback') self.pvs_rb.append(pvsrb) pvssp = elemobj.pv(field=field, handle='setpoint') self.pvs_sp.append(pvssp) else: QMessageBox.critical(None, "ERROR", "element %s not found" % elem) return # expand one row m, n = self.table.rowCount(), self.table.columnCount() self.table.insertRow(m) # add cells item = QTableWidgetItem(elem) item.setFlags(item.flags() & (~Qt.ItemIsEditable)) self.table.setItem(m, self.COL_ELEMENT, item) item = QTableWidgetItem(field) item.setFlags(item.flags() & (~Qt.ItemIsEditable)) self.table.setItem(m, self.COL_FIELD, item) item = QTableWidgetItem(', '.join(pvsrb)) #item.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) self.table.setItem(m, self.COL_PV, item) readval = ['%.4e' % v for v in caget(pvsrb)] item = QTableWidgetItem(', '.join(readval)) item.setFlags(item.flags() & (~Qt.ItemIsEditable)) self.table.setItem(m, self.COL_READBACK, item) # set the stepsize of PV stepsize = 0.00001 if pvssp: item = QTableWidgetItem('%f' % stepsize) item.setFlags(item.flags() & (~Qt.ItemIsEditable)) self.table.setItem(m, self.COL_STEPSIZE, item) self.spinbox.append(QDoubleSpinBox(self.table)) self.spinbox[-1].setRange(-100, 100) #self.spinbox[-1].setValue(float(10.0)) self.spinbox[-1].setSingleStep(stepsize) self.spinbox[-1].setDecimals(10) self.spinbox[-1].valueChanged.connect(self._writePv) self.table.setCellWidget(m, self.COL_SETPOINT, self.spinbox[-1]) sp = float(caget(pvssp)[0]) #print "setpoint:", pvssp, sp, type(sp) self.spinbox[-1].setValue(-1e-5) #print "connected", self.spinbox[-1].value() else: item = self.table.item(m, self.COL_STEPSIZE) if item: item.setFlags(item.flags() & (~Qt.ItemIsEditable)) item = self.table.item(m, self.COL_SETPOINT) if item: item.setFlags(item.flags() & (~Qt.ItemIsEditable)) self.spinbox.append(None) self.table.resizeColumnsToContents() def addPv(self): self._appendRecord(str(self.inputBox.text())) self._updateMonitors() def minimalSizeHint(self): return QSize(800, 600) def _writePv(self, v): """ """ c = QObject.sender(self) i = self.spinbox.index(c) #print i, c.text(), "changed" #print self.pvs_sp[i], v caput(self.pvs_sp[i], v) def _updateMonitors(self): """ prepare the PV list for camonitor """ #print "Updating monitors" pvs = [] self.pvs_rb_val = [] for i in range(self.table.rowCount()): for j in range(len(self.pvs_rb[i])): self.pvs_rb_val.append([i, 0.0]) pvs.extend(self.pvs_rb[i]) for p in self.pvmoni: p.close() self.pvmoni = camonitor(pvs, self._updatePvValues) #print self.pvmoni #print pvs #print self.pvs_rb_val def _updatePvValues(self, val, idx): #print idx, val s = [] for i, v in enumerate(self.pvs_rb_val): if v[0] == self.pvs_rb_val[idx][0]: s.append(self.FMT_READBACK % val) #print s item = self.table.item(self.pvs_rb_val[idx][0], self.COL_READBACK) item.setText(','.join(s)) def closePvMonitors(self): #print "Closing PV Monitors" for p in self.pvmoni: p.close() pass def closeEvent(self, event): self.closePvMonitors() event.accept() def close(self): self.closePvMonitors() return True
class ProfileDlg(QDialog): def __init__(self): QDialog.__init__(self) self.__setup_ui() self.__connect_slot() self.__settings = QSettings('__cyt', '__yt_ovs') #print self.__settings.fileName() set_str = to_python_str(self.__settings.value('__profile_record', '').toString()) set_str = set_str if set_str is not '' else "[]" self.__record_list = json.loads(set_str)#[{'ip':'1.1.1.1','port':6641,'schema':'xxxx'},{...}] self.__list_to_table_item() self.click_ip = '' self.click_port = 0 self.click_schema = '' def __setup_ui(self): self.setMaximumSize(500, 400) self.setMinimumSize(500, 400) v_layout = QVBoxLayout() #init table widget self.__profile_table = QTableWidget() self.__profile_table.setColumnCount(3) header_list = QStringList() header_list << 'ip' << 'port' << 'schema' self.__profile_table.setHorizontalHeaderLabels(header_list) self.__profile_table.horizontalHeader().setResizeMode(QHeaderView.Stretch) self.__profile_table.setSelectionBehavior(QAbstractItemView.SelectRows) #init tool widget self.__tool_wid = QWidget() h_layout = QHBoxLayout() h_layout.setContentsMargins(0,0,0,0) self.__puls_btn = QPushButton() self.__puls_btn.setIcon(QIcon(ICON_IDR + 'arrow_plus.png')) self.__puls_btn.setIconSize(QSize(15, 15)) self.__puls_btn.setMaximumSize(20, 20) self.__minus_btn = QPushButton() self.__minus_btn.setIcon(QIcon(ICON_IDR + 'arrow_minus.png')) self.__minus_btn.setIconSize(QSize(15, 15)) self.__minus_btn.setMaximumSize(20, 20) h_layout.addWidget(self.__puls_btn,0) h_layout.addWidget(self.__minus_btn,0) h_layout.addStretch(1) self.__tool_wid.setLayout(h_layout) #v layout v_layout.addWidget(self.__profile_table,1) v_layout.addWidget(self.__tool_wid,0) v_layout.setSpacing(1) self.setLayout(v_layout) def __connect_slot(self): self.connect(self.__puls_btn, SIGNAL('clicked()'), self, SLOT('__on_plus_btn()')) self.connect(self.__minus_btn, SIGNAL('clicked()'), self, SLOT('__on_minus_btn()')) self.connect(self.__profile_table, SIGNAL('cellDoubleClicked (int,int)'), self, SLOT('__on_profile_double_click(int,int)')) def __add_record(self, ip, port, schema): count = self.__profile_table.rowCount() self.__profile_table.insertRow(count) ip_item = QTableWidgetItem(ip) ip_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) item_font = ip_item.font() item_font.setPointSizeF(12) ip_item.setFont(item_font) port_item = QTableWidgetItem(port) port_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) port_item.setFont(item_font) schema_item = QTableWidgetItem(schema) schema_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) schema_item.setFont(item_font) self.__profile_table.setItem(count, 0, ip_item) self.__profile_table.setItem(count, 1, port_item) self.__profile_table.setItem(count, 2, schema_item) def __clear_table_data(self): row_count = self.__profile_table.rowCount() rev = [i for i in range(row_count)] rev.reverse() for i in rev: self.__profile_table.removeRow(i) def __list_to_table_item(self): self.__clear_table_data() for record in self.__record_list: self.__add_record(record['ip'], str(record['port']), record['schema']) #print record def __table_item_to_list(self): row_count = self.__profile_table.rowCount() self.__record_list = [] for i in range(row_count): record = {} ip = to_python_str( self.__profile_table.item(i, 0).text() ) port = int( self.__profile_table.item(i, 1).text() ) schema = to_python_str(self.__profile_table.item(i, 2).text()) record["ip"] = ip record["port"] = port record["schema"] = schema self.__record_list.append(record) print self.__record_list def __check_existed(self, ip, port, schema): has_code = con_has_code(ip, port, schema) for record in self.__record_list: exist_code = con_has_code(record["ip"], record["port"], record["schema"]) if exist_code == has_code: return True return False def __record_to_settings(self): self.__settings.setValue('__profile_record', json.dumps(self.__record_list)) @pyqtSlot() def __on_plus_btn(self): new_dlg = NewConnectionDlg() if new_dlg.exec_(): # add to table_widget if self.__check_existed(new_dlg.host, new_dlg.port, new_dlg.schema): return self.__add_record(new_dlg.host, str(new_dlg.port), new_dlg.schema) self.__table_item_to_list() self.__record_to_settings() @pyqtSlot() def __on_minus_btn(self): select_row = self.__profile_table.currentRow() self.__profile_table.removeRow(select_row) self.__table_item_to_list() self.__record_to_settings() @pyqtSlot('int','int') def __on_profile_double_click(self, row, column): ip_item = self.__profile_table.item(row, 0) port_item = self.__profile_table.item(row, 1) schema_item = self.__profile_table.item(row, 2) self.click_ip = to_python_str(ip_item.text()) self.click_port = int(port_item.text()) self.click_schema = to_python_str(schema_item.text()) self.accept()