def createList(labelText, slot, changedSlot, validator=None): widget = QWidget() layout = QVBoxLayout() layout.setObjectName('listLayout') widget.setLayout(layout) hboxWidget = QWidget() hboxLayout = QHBoxLayout() hboxLayout.setObjectName('hboxLayout for tableWidget') hboxWidget.setLayout(hboxLayout) tableWidget = QTableWidget(0, 2) tableWidget.setAlternatingRowColors(True) widget.connect(tableWidget, SIGNAL('cellChanged(int, int)'), changedSlot) tableWidget.setHorizontalHeaderLabels(createQStringList([labelText, ''])) tableWidget.setColumnWidth(INPUT_IDX, contentColumnWidth) tableWidget.setColumnWidth(BUTTON_IDX, deleteButtonColumnWidth) hboxLayout.addWidget(tableWidget) add = QWidget() addLayout = QHBoxLayout() addLayout.setObjectName('addLayout') add.setLayout(addLayout) addLineEdit = createLineEdit(add, None, validator) addButton = createButton(translate('MainWindow', 'Add'), add, add, slot) add.connect(addLineEdit, SIGNAL('returnPressed()'), slot) for wid in addLineEdit, addButton: addLayout.addWidget(wid) for wid in add, hboxWidget: layout.addWidget(wid) return (widget, tableWidget, addLineEdit)
class InstalledWidget(QWidget): """ This widget show the installed plugins """ def __init__(self, parent, installed): QWidget.__init__(self, parent) self._parent = parent self._installed = installed vbox = QVBoxLayout(self) self._table = QTableWidget(1, 2) self._table.setSelectionMode(QTableWidget.SingleSelection) self._table.removeRow(0) vbox.addWidget(self._table) ui_tools.load_table(self._table, (self.tr('Name'), self.tr('Version')), _format_for_table(installed)) self._table.setColumnWidth(0, 500) self._table.setSortingEnabled(True) self._table.setAlternatingRowColors(True) btnUninstall = QPushButton(self.tr("Uninstall")) btnUninstall.setMaximumWidth(100) vbox.addWidget(btnUninstall) self.connect(btnUninstall, SIGNAL("clicked()"), self._uninstall_plugins) self.connect(self._table, SIGNAL("itemSelectionChanged()"), self._show_item_description) def _show_item_description(self): item = self._table.currentItem() if item is not None: data = list(item.data(Qt.UserRole)) self._parent.show_plugin_info(data) def remove_item(self, plugin_name): plugin = _get_plugin(plugin_name, self._installed) self._installed.remove(plugin) def add_table_items(self, plugs): self._installed += plugs data = _format_for_table(self._installed) ui_tools.load_table(self._table, (self.tr('Name'), self.tr('Version')), data) def _uninstall_plugins(self): data = _format_for_table(self._installed) plugins = ui_tools.remove_get_selected_items(self._table, data) self._parent.mark_as_available(plugins) def reset_table(self, installed): self._installed = installed while self._table.rowCount() > 0: self._table.removeRow(0) ui_tools.load_table(self._table, (self.tr('Name'), self.tr('Version')), self._installed)
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)
class UpdatesWidget(QWidget): """ This widget show the availables plugins to update """ def __init__(self, parent, updates): QWidget.__init__(self, parent) self._parent = parent self._updates = updates vbox = QVBoxLayout(self) self._table = QTableWidget(1, 2) self._table.removeRow(0) self._table.setSelectionMode(QTableWidget.SingleSelection) self._table.setColumnWidth(0, 500) self._table.setSortingEnabled(True) self._table.setAlternatingRowColors(True) vbox.addWidget(self._table) ui_tools.load_table(self._table, (self.tr('Name'), self.tr('Version')), _format_for_table(updates)) btnUpdate = QPushButton(self.tr("Update")) btnUpdate.setMaximumWidth(100) vbox.addWidget(btnUpdate) self.connect(btnUpdate, SIGNAL("clicked()"), self._update_plugins) self.connect(self._table, SIGNAL("itemSelectionChanged()"), self._show_item_description) def _show_item_description(self): item = self._table.currentItem() if item is not None: data = list(item.data(Qt.UserRole)) self._parent.show_plugin_info(data) def _update_plugins(self): data = _format_for_table(self._updates) plugins = ui_tools.remove_get_selected_items(self._table, data) #get the download link of each plugin for p_row in plugins: #search the plugin for p_dict in self._updates: if p_dict["name"] == p_row[0]: p_data = p_dict break #append the downlod link p_row.append(p_data["download"]) self._parent.update_plugin(plugins)
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 Main(plugin.Plugin): " Main Class " def initialize(self, *args, **kwargs): " Init Main Class " super(Main, self).initialize(*args, **kwargs) self.scriptPath, self.scriptArgs = "", [] self.profilerPath, self.tempPath = profilerPath, tempPath self.output = " ERROR: FAIL: No output ! " self.process = QProcess() self.process.finished.connect(self.on_process_finished) self.process.error.connect(self.on_process_error) self.tabWidget, self.stat = QTabWidget(), QWidget() self.tabWidget.tabCloseRequested.connect( lambda: self.tabWidget.setTabPosition(1) if self.tabWidget. tabPosition() == 0 else self.tabWidget.setTabPosition(0)) self.tabWidget.setStyleSheet('QTabBar{font-weight:bold;}') self.tabWidget.setMovable(True) self.tabWidget.setTabsClosable(True) self.vboxlayout1 = QVBoxLayout(self.stat) self.hboxlayout1 = QHBoxLayout() self.filterTableLabel = QLabel("<b>Type to Search : </b>", self.stat) self.hboxlayout1.addWidget(self.filterTableLabel) self.filterTableLineEdit = QLineEdit(self.stat) self.filterTableLineEdit.setPlaceholderText(' Type to Search . . . ') self.hboxlayout1.addWidget(self.filterTableLineEdit) self.filterHintTableLabel = QLabel(" ? ", self.stat) self.hboxlayout1.addWidget(self.filterHintTableLabel) self.vboxlayout1.addLayout(self.hboxlayout1) self.tableWidget = QTableWidget(self.stat) self.tableWidget.setAlternatingRowColors(True) self.tableWidget.setColumnCount(8) self.tableWidget.setRowCount(2) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(0, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(1, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(2, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(3, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(4, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(5, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(6, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(7, item) self.tableWidget.itemDoubleClicked.connect( self.on_tableWidget_itemDoubleClicked) self.vboxlayout1.addWidget(self.tableWidget) self.tabWidget.addTab(self.stat, " ? ") self.source = QWidget() self.gridlayout = QGridLayout(self.source) self.scintillaWarningLabel = QLabel( "QScintilla is not installed!. Falling back to basic text edit!.", self.source) self.gridlayout.addWidget(self.scintillaWarningLabel, 1, 0, 1, 2) self.sourceTreeWidget = QTreeWidget(self.source) self.sourceTreeWidget.setAlternatingRowColors(True) self.sourceTreeWidget.itemActivated.connect( self.on_sourceTreeWidget_itemActivated) self.sourceTreeWidget.itemClicked.connect( self.on_sourceTreeWidget_itemClicked) self.sourceTreeWidget.itemDoubleClicked.connect( self.on_sourceTreeWidget_itemClicked) self.gridlayout.addWidget(self.sourceTreeWidget, 0, 0, 1, 1) self.sourceTextEdit = QTextEdit(self.source) self.sourceTextEdit.setReadOnly(True) self.gridlayout.addWidget(self.sourceTextEdit, 0, 1, 1, 1) self.tabWidget.addTab(self.source, " ? ") self.result = QWidget() self.vlayout = QVBoxLayout(self.result) self.globalStatGroupBox = QGroupBox(self.result) self.hboxlayout = QHBoxLayout(self.globalStatGroupBox) self.totalTimeLcdNumber = QLCDNumber(self.globalStatGroupBox) self.totalTimeLcdNumber.setSegmentStyle(QLCDNumber.Filled) self.totalTimeLcdNumber.setNumDigits(7) self.totalTimeLcdNumber.display(1000000) self.totalTimeLcdNumber.setFrameShape(QFrame.StyledPanel) self.totalTimeLcdNumber.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.hboxlayout.addWidget(self.totalTimeLcdNumber) self.tTimeLabel = QLabel("<b>Total Time (Sec)</b>", self.globalStatGroupBox) self.tTimeLabel.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.hboxlayout.addWidget(self.tTimeLabel) self.numCallLcdNumber = QLCDNumber(self.globalStatGroupBox) self.numCallLcdNumber.setNumDigits(7) self.numCallLcdNumber.display(1000000) self.numCallLcdNumber.setSegmentStyle(QLCDNumber.Filled) self.numCallLcdNumber.setFrameShape(QFrame.StyledPanel) self.numCallLcdNumber.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.hboxlayout.addWidget(self.numCallLcdNumber) self.numCallLabel = QLabel("<b>Number of calls</b>", self.globalStatGroupBox) self.numCallLabel.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.hboxlayout.addWidget(self.numCallLabel) self.primCallLcdNumber = QLCDNumber(self.globalStatGroupBox) self.primCallLcdNumber.setSegmentStyle(QLCDNumber.Filled) self.primCallLcdNumber.setFrameShape(QFrame.StyledPanel) self.primCallLcdNumber.setNumDigits(7) self.primCallLcdNumber.display(1000000) self.primCallLcdNumber.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.hboxlayout.addWidget(self.primCallLcdNumber) self.primCallLabel = QLabel("<b>Primitive calls (%)</b>", self.globalStatGroupBox) self.primCallLabel.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.hboxlayout.addWidget(self.primCallLabel) self.vlayout.addWidget(self.globalStatGroupBox) try: from PyKDE4.kdeui import KRatingWidget self.rating = KRatingWidget(self.globalStatGroupBox) self.rating.setToolTip('Profiling Performance Rating') except ImportError: pass self.tabWidget.addTab(self.result, " Get Results ! ") self.resgraph = QWidget() self.vlayout2 = QVBoxLayout(self.result) self.graphz = QGroupBox(self.resgraph) self.hboxlayout2 = QHBoxLayout(self.graphz) try: from PyKDE4.kdeui import KLed KLed(self.graphz) except ImportError: pass self.hboxlayout2.addWidget( QLabel(''' Work in Progress :) Not Ready Yet''')) self.vlayout2.addWidget(self.graphz) self.tabWidget.addTab(self.resgraph, " Graphs and Charts ") self.pathz = QWidget() self.vlayout3 = QVBoxLayout(self.pathz) self.patz = QGroupBox(self.pathz) self.hboxlayout3 = QVBoxLayout(self.patz) self.profilepath = QLineEdit(profilerPath) self.getprofile = QPushButton(QIcon.fromTheme("document-open"), 'Open') self.getprofile.setToolTip( 'Dont touch if you dont know what are doing') self.getprofile.clicked.connect(lambda: self.profilepath.setText( str( QFileDialog.getOpenFileName( self.patz, ' Open the profile.py file ', path.expanduser("~"), ';;(profile.py)')))) self.hboxlayout3.addWidget( QLabel( '<center><b>Profile.py Python Library Full Path:</b></center>') ) self.hboxlayout3.addWidget(self.profilepath) self.hboxlayout3.addWidget(self.getprofile) self.argGroupBox = QGroupBox(self.pathz) self.hbxlayout = QHBoxLayout(self.argGroupBox) self.argLineEdit = QLineEdit(self.argGroupBox) self.argLineEdit.setToolTip( 'Not touch if you dont know what are doing') self.argLineEdit.setPlaceholderText( 'Dont touch if you dont know what are doing') self.hbxlayout.addWidget( QLabel('<b>Additional Profile Arguments:</b>')) self.hbxlayout.addWidget(self.argLineEdit) self.hboxlayout3.addWidget(self.argGroupBox) self.vlayout3.addWidget(self.patz) self.tabWidget.addTab(self.pathz, " Paths and Configs ") self.outp = QWidget() self.vlayout4 = QVBoxLayout(self.outp) self.outgro = QGroupBox(self.outp) self.outgro.setTitle(" MultiProcessing Output Logs ") self.hboxlayout4 = QVBoxLayout(self.outgro) self.outputlog = QTextEdit() self.outputlog.setText(''' I do not fear computers, I fear the lack of them. -Isaac Asimov ''') self.hboxlayout4.addWidget(self.outputlog) self.vlayout4.addWidget(self.outgro) self.tabWidget.addTab(self.outp, " Logs ") self.actionNew_profiling = QAction(QIcon.fromTheme("document-new"), 'New Profiling', self) self.actionLoad_profile = QAction(QIcon.fromTheme("document-open"), 'Open Profiling', self) self.actionClean = QAction(QIcon.fromTheme("edit-clear"), 'Clean', self) self.actionClean.triggered.connect(lambda: self.clearContent) self.actionAbout = QAction(QIcon.fromTheme("help-about"), 'About', self) self.actionAbout.triggered.connect(lambda: QMessageBox.about( self.dock, __doc__, ', '.join( (__doc__, __license__, __author__, __email__)))) self.actionSave_profile = QAction(QIcon.fromTheme("document-save"), 'Save Profiling', self) self.actionManual = QAction(QIcon.fromTheme("help-contents"), 'Help', self) self.actionManual.triggered.connect(lambda: open_new_tab( 'http://docs.python.org/library/profile.html')) self.tabWidget.setCurrentIndex(2) self.globalStatGroupBox.setTitle("Global Statistics") item = self.tableWidget.horizontalHeaderItem(0) item.setText("Number of Calls") item = self.tableWidget.horizontalHeaderItem(1) item.setText("Total Time") item = self.tableWidget.horizontalHeaderItem(2) item.setText("Per Call") item = self.tableWidget.horizontalHeaderItem(3) item.setText("Cumulative Time") item = self.tableWidget.horizontalHeaderItem(4) item.setText("Per Call") item = self.tableWidget.horizontalHeaderItem(5) item.setText("Filename") item = self.tableWidget.horizontalHeaderItem(6) item.setText("Line") item = self.tableWidget.horizontalHeaderItem(7) item.setText("Function") self.tabWidget.setTabText(self.tabWidget.indexOf(self.stat), "Statistics per Function") self.sourceTreeWidget.headerItem().setText(0, "Source files") self.tabWidget.setTabText(self.tabWidget.indexOf(self.source), "Sources Navigator") ####################################################################### self.scrollable, self.dock = QScrollArea(), QDockWidget() self.scrollable.setWidgetResizable(True) self.scrollable.setWidget(self.tabWidget) self.dock.setWindowTitle(__doc__) self.dock.setStyleSheet('QDockWidget::title{text-align: center;}') self.dock.setWidget(self.scrollable) QToolBar(self.dock).addActions( (self.actionNew_profiling, self.actionClean, self.actionSave_profile, self.actionLoad_profile, self.actionManual, self.actionAbout)) self.actionNew_profiling.triggered.connect( self.on_actionNew_profiling_triggered) self.actionLoad_profile.triggered.connect( self.on_actionLoad_profile_triggered) self.actionSave_profile.triggered.connect( self.on_actionSave_profile_triggered) self.locator.get_service('misc').add_widget( self.dock, QIcon.fromTheme("document-open-recent"), __doc__) if QSCI: # Scintilla source editor management self.scintillaWarningLabel.setText(' QScintilla is Ready ! ') layout = self.source.layout() layout.removeWidget(self.sourceTextEdit) self.sourceTextEdit = Qsci.QsciScintilla(self.source) layout.addWidget(self.sourceTextEdit, 0, 1) doc = self.sourceTextEdit doc.setLexer(Qsci.QsciLexerPython(self.sourceTextEdit)) doc.setReadOnly(True) doc.setEdgeMode(Qsci.QsciScintilla.EdgeLine) doc.setEdgeColumn(80) doc.setEdgeColor(QColor("#FF0000")) doc.setFolding(Qsci.QsciScintilla.BoxedTreeFoldStyle) doc.setBraceMatching(Qsci.QsciScintilla.SloppyBraceMatch) doc.setCaretLineVisible(True) doc.setMarginLineNumbers(1, True) doc.setMarginWidth(1, 25) doc.setTabWidth(4) doc.setEolMode(Qsci.QsciScintilla.EolUnix) self.marker = {} for color in COLORS: mnr = doc.markerDefine(Qsci.QsciScintilla.Background) doc.setMarkerBackgroundColor(color, mnr) self.marker[color] = mnr self.currentSourcePath = None # Connect table and tree filter edit signal to unique slot self.filterTableLineEdit.textEdited.connect( self.on_filterLineEdit_textEdited) # Timer to display filter hint message self.filterHintTimer = QTimer(self) self.filterHintTimer.setSingleShot(True) self.filterHintTimer.timeout.connect(self.on_filterHintTimer_timeout) # Timer to start search self.filterSearchTimer = QTimer(self) self.filterSearchTimer.setSingleShot(True) self.filterSearchTimer.timeout.connect( self.on_filterSearchTimer_timeout) self.tabLoaded = {} for i in range(10): self.tabLoaded[i] = False self.backgroundTreeMatchedItems = {} self.resizeWidgetToContent(self.tableWidget) def on_actionNew_profiling_triggered(self): self.clearContent() self.scriptPath = str( QFileDialog.getOpenFileName(self.dock, "Choose your script to profile", path.expanduser("~"), "Python (*.py *.pyw)")) commandLine = [ self.profilerPath, "-o", self.tempPath, self.scriptPath ] + self.scriptArgs commandLine = " ".join(commandLine) ##if self.termCheckBox.checkState() == Qt.Checked: #termList = ["xterm", "aterm"] #for term in termList: #termPath = which(term) #if termPath: #break #commandLine = """%s -e "%s ; echo 'Press ENTER Exit' ; read" """ \ #% (termPath, commandLine) self.process.start(commandLine) if not self.process.waitForStarted(): print((" ERROR: {} failed!".format(commandLine))) return def on_process_finished(self, exitStatus): ' whan the process end ' print((" INFO: OK: QProcess is %s" % self.process.exitCode())) self.output = self.process.readAll().data() if not self.output: self.output = " ERROR: FAIL: No output ! " self.outputlog.setText(self.output + str(self.process.exitCode())) if path.exists(self.tempPath): self.setStat(self.tempPath) remove(self.tempPath) else: self.outputlog.setText(" ERROR: QProcess FAIL: Profiling failed.") self.tabWidget.setCurrentIndex(2) def on_process_error(self, error): ' when the process fail, I hope you never see this ' print(" ERROR: QProcess FAIL: Profiler Dead, wheres your God now ? ") if error == QProcess.FailedToStart: self.outputlog.setText(" ERROR: FAIL: Profiler execution failed ") elif error == QProcess.Crashed: self.outputlog.setText(" ERROR: FAIL: Profiler execution crashed ") else: self.outputlog.setText(" ERROR: FAIL: Profiler unknown error ") def on_actionLoad_profile_triggered(self): """Load a previous profile sessions""" statPath = str( QFileDialog.getOpenFileName(self.dock, "Open profile dump", path.expanduser("~"), "Profile file (*)")) if statPath: self.clearContent() print(' INFO: OK: Loading profiling from ' + statPath) self.setStat(statPath) def on_actionSave_profile_triggered(self): """Save a profile sessions""" statPath = str( QFileDialog.getSaveFileName(self.dock, "Save profile dump", path.expanduser("~"), "Profile file (*)")) if statPath: #TODO: handle error case and give feelback to user print(' INFO: OK: Saving profiling to ' + statPath) self.stat.save(statPath) #=======================================================================# # Common parts # #=======================================================================# def on_tabWidget_currentChanged(self, index): """slot for tab change""" # Kill search and hint timer if running to avoid cross effect for timer in (self.filterHintTimer, self.filterSearchTimer): if timer.isActive(): timer.stop() if not self.stat: #No stat loaded, nothing to do return self.populateTable() self.populateSource() def on_filterLineEdit_textEdited(self, text): """slot for filter change (table or tree""" if self.filterSearchTimer.isActive(): # Already runnning, stop it self.filterSearchTimer.stop() # Start timer self.filterSearchTimer.start(300) def on_filterHintTimer_timeout(self): """Timeout to warn user about text length""" print("timeout") tab = self.tabWidget.currentIndex() if tab == TAB_FUNCTIONSTAT: label = self.filterHintTableLabel label.setText("Type > 2 characters to search") def on_filterSearchTimer_timeout(self): """timeout to start search""" tab = self.tabWidget.currentIndex() if tab == TAB_FUNCTIONSTAT: text = self.filterTableLineEdit.text() label = self.filterHintTableLabel edit = self.filterTableLineEdit widget = self.tableWidget else: print("Unknow tab for filterSearch timeout !") print(("do search for %s" % text)) if not len(text): # Empty keyword, just clean all if self.filterHintTimer.isActive(): self.filterHintTimer.stop() label.setText(" ? ") self.warnUSer(True, edit) self.clearSearch() return if len(text) < 2: # Don't filter if text is too short and tell it to user self.filterHintTimer.start(600) return else: if self.filterHintTimer.isActive(): self.filterHintTimer.stop() label.setText(" ? ") # Search self.clearSearch() matchedItems = [] if tab == TAB_FUNCTIONSTAT: # Find items matchedItems = widget.findItems(text, Qt.MatchContains) widget.setSortingEnabled(False) matchedRows = [item.row() for item in matchedItems] # Hide matched items header = widget.verticalHeader() for row in range(widget.rowCount()): if row not in matchedRows: header.hideSection(row) widget.setSortingEnabled(True) else: print(" Unknow tab for filterSearch timeout ! ") print(("got %s members" % len(matchedItems))) self.warnUSer(matchedItems, edit) self.resizeWidgetToContent(widget) def resizeWidgetToContent(self, widget): """Resize all columns according to content""" for i in range(widget.columnCount()): widget.resizeColumnToContents(i) def clearSearch(self): """Clean search result For table, show all items For tree, remove colored items""" tab = self.tabWidget.currentIndex() if tab == TAB_FUNCTIONSTAT: header = self.tableWidget.verticalHeader() if header.hiddenSectionCount(): for i in range(header.count()): if header.isSectionHidden(i): header.showSection(i) def clearContent(self): # Clear tabs self.tableWidget.clearContents() self.sourceTreeWidget.clear() # Reset LCD numbers for lcdNumber in (self.totalTimeLcdNumber, self.numCallLcdNumber, self.primCallLcdNumber): lcdNumber.display(1000000) # Reset stat self.pstat = None # Disable save as menu self.actionSave_profile.setEnabled(False) # Mark all tabs as unloaded for i in range(10): self.tabLoaded[i] = False def warnUSer(self, result, inputWidget): palette = inputWidget.palette() if result: palette.setColor(QPalette.Normal, QPalette.Base, QColor(255, 255, 255)) else: palette.setColor(QPalette.Normal, QPalette.Base, QColor(255, 136, 138)) inputWidget.setPalette(palette) inputWidget.update() def setStat(self, statPath): self.stat = Stat(path=statPath) # Global stat update self.totalTimeLcdNumber.display(self.stat.getTotalTime()) self.numCallLcdNumber.display(self.stat.getCallNumber()) self.primCallLcdNumber.display(self.stat.getPrimitiveCallRatio()) # Refresh current tab self.on_tabWidget_currentChanged(self.tabWidget.currentIndex()) # Activate save as menu self.actionSave_profile.setEnabled(True) try: self.rating.setMaxRating(10) self.rating.setRating( int(self.stat.getPrimitiveCallRatio()) / 10 - 1) except: pass #========================================================================# # Statistics table # #=======================================================================# def populateTable(self): row = 0 rowCount = self.stat.getStatNumber() progress = QProgressDialog("Populating statistics table...", "Abort", 0, 2 * rowCount) self.tableWidget.setSortingEnabled(False) self.tableWidget.setRowCount(rowCount) progress.setWindowModality(Qt.WindowModal) for (key, value) in self.stat.getStatItems(): #ncalls item = StatTableWidgetItem(str(value[0])) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_NCALLS, item) colorTableItem(item, self.stat.getCallNumber(), value[0]) #total time item = StatTableWidgetItem(str(value[2])) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_TTIME, item) colorTableItem(item, self.stat.getTotalTime(), value[2]) #per call (total time) if value[0] != 0: tPerCall = str(value[2] / value[0]) cPerCall = str(value[3] / value[0]) else: tPerCall = "" cPerCall = "" item = StatTableWidgetItem(tPerCall) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_TPERCALL, item) colorTableItem( item, 100.0 * self.stat.getTotalTime() / self.stat.getCallNumber(), tPerCall) #per call (cumulative time) item = StatTableWidgetItem(cPerCall) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_CPERCALL, item) colorTableItem( item, 100.0 * self.stat.getTotalTime() / self.stat.getCallNumber(), cPerCall) #cumulative time item = StatTableWidgetItem(str(value[3])) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_CTIME, item) colorTableItem(item, self.stat.getTotalTime(), value[3]) #Filename self.tableWidget.setItem(row, STAT_FILENAME, StatTableWidgetItem(str(key[0]))) #Line item = StatTableWidgetItem(str(key[1])) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_LINE, item) #Function name self.tableWidget.setItem(row, STAT_FUNCTION, StatTableWidgetItem(str(key[2]))) row += 1 # Store it in stat hash array self.stat.setStatLink(item, key, TAB_FUNCTIONSTAT) progress.setValue(row) if progress.wasCanceled(): return for i in range(self.tableWidget.rowCount()): progress.setValue(row + i) for j in range(self.tableWidget.columnCount()): item = self.tableWidget.item(i, j) if item: item.setFlags(Qt.ItemIsEnabled) self.tableWidget.setSortingEnabled(True) self.resizeWidgetToContent(self.tableWidget) progress.setValue(2 * rowCount) def on_tableWidget_itemDoubleClicked(self, item): matchedItems = [] filename = str(self.tableWidget.item(item.row(), STAT_FILENAME).text()) if not filename or filename.startswith("<"): # No source code associated, return immediatly return function = self.tableWidget.item(item.row(), STAT_FUNCTION).text() line = self.tableWidget.item(item.row(), STAT_LINE).text() self.on_tabWidget_currentChanged(TAB_SOURCE) # load source tab function = "%s (%s)" % (function, line) fathers = self.sourceTreeWidget.findItems(filename, Qt.MatchContains, SOURCE_FILENAME) print(("find %s father" % len(fathers))) for father in fathers: findItems(father, function, SOURCE_FILENAME, matchedItems) print(("find %s items" % len(matchedItems))) if matchedItems: self.tabWidget.setCurrentIndex(TAB_SOURCE) self.sourceTreeWidget.scrollToItem(matchedItems[0]) self.on_sourceTreeWidget_itemClicked(matchedItems[0], SOURCE_FILENAME) matchedItems[0].setSelected(True) else: print("oups, item found but cannot scroll to it !") #=======================================================================# # Source explorer # #=====================================================================# def populateSource(self): items = {} for stat in self.stat.getStatKeys(): source = stat[0] function = "%s (%s)" % (stat[2], stat[1]) if source in ("", "profile") or source.startswith("<"): continue # Create the function child child = QTreeWidgetItem([function]) # Store it in stat hash array self.stat.setStatLink(child, stat, TAB_SOURCE) if source in items: father = items[source] else: # Create the father father = QTreeWidgetItem([source]) items[source] = father father.addChild(child) self.sourceTreeWidget.setSortingEnabled(False) for value in list(items.values()): self.sourceTreeWidget.addTopLevelItem(value) self.sourceTreeWidget.setSortingEnabled(True) def on_sourceTreeWidget_itemActivated(self, item, column): self.on_sourceTreeWidget_itemClicked(item, column) def on_sourceTreeWidget_itemClicked(self, item, column): line = 0 parent = item.parent() if QSCI: doc = self.sourceTextEdit if parent: pathz = parent.text(column) result = match("(.*) \(([0-9]+)\)", item.text(column)) if result: try: function = str(result.group(1)) line = int(result.group(2)) except ValueError: # We got garbage... falling back to line 0 pass else: pathz = item.text(column) pathz = path.abspath(str(pathz)) if self.currentSourcePath != pathz: # Need to load source self.currentSourcePath == pathz try: if QSCI: doc.clear() doc.insert(file(pathz).read()) else: self.sourceTextEdit.setPlainText(file(pathz).read()) except IOError: QMessageBox.warning(self, "Error", "Source file could not be found", QMessageBox.Ok) return if QSCI: for function, line in [(i[2], i[1]) for i in self.stat.getStatKeys() if i[0] == pathz]: # expr, regexp, case sensitive, whole word, wrap, forward doc.findFirst("def", False, True, True, False, True, line, 0, True) end, foo = doc.getCursorPosition() time = self.stat.getStatTotalTime((pathz, line, function)) colorSource(doc, self.stat.getTotalTime(), time, line, end, self.marker) if QSCI: doc.ensureLineVisible(line)
class ImportDataDlg(QDialog): __isJy = False # 数据校验成功的标志 __mlist = [] # 定义一个列表用于保存从excel表中取出的数据 def __init__(self, iface, parent=None, impType=ImpDateType.SITEANDCELL): super(ImportDataDlg, self).__init__() self.iface = iface self.parent = parent self.impType = impType self.initView() def initView(self): if self.impType == ImpDateType.SERVINGCELL: self.setWindowTitle(u'相邻小区数据导入') else: self.setWindowTitle(u'基站和小区数据导入') self.setWindowIcon(QIcon('images/logo.png')) self.resize(620, 480) # 数据表格 self.tableWidget = QTableWidget(self) self.tableWidget.setAlternatingRowColors(True) self.tableWidget.setRowCount(7) # 设置当前Table不能编辑 self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers) # 初始化表格上下文菜单 self.initTableContextMenu() # 初始化表头 self.initTableHeader() # 导入出错列表 self.listWidget = QListWidget(self) # 按钮组 impBtn = QPushButton(u"导入EXCEL表", self) yzBtn = QPushButton(u"数据检验", self) impdateBtn = QPushButton(u"导入数据", self) btnVBox = QVBoxLayout() btnVBox.addWidget(impBtn) btnVBox.addWidget(yzBtn) btnVBox.addWidget(impdateBtn) # 错误列表与按钮组 hBox = QHBoxLayout() hBox.setMargin(20) hBox.addWidget(self.listWidget) hBox.addLayout(btnVBox) self.mbar = QStatusBar(self) self.mbar.showMessage(u'准备就绪...') self.maction = QToolBar(self) self.editAction = QAction(u'编辑', self.maction) self.editAction.setCheckable(True) self.combox = QComboBox(self) self.combox.addItems(HeadsConfig.ImpExcelName) self.maction.addWidget(self.combox) self.maction.addAction(self.editAction) vBox = QVBoxLayout() vBox.addWidget(self.maction) vBox.addWidget(self.tableWidget) vBox.addLayout(hBox) vBox.addWidget(self.mbar) vBox.setStretchFactor(self.tableWidget, 9) vBox.setStretchFactor(hBox, 5) vBox.setStretchFactor(self.mbar, 1) self.setLayout(vBox) QObject.connect(impBtn, SIGNAL('clicked()'), self.impClick) QObject.connect(yzBtn, SIGNAL('clicked()'), self.yzClick) QObject.connect(impdateBtn, SIGNAL('clicked()'), self.impdateClick) QObject.connect(self.editAction, SIGNAL('triggered()'), self.editClick) QObject.connect(self.combox, SIGNAL('currentIndexChanged(int)'), self.comboxChange) self.listWidget.doubleClicked.connect(self.mlistClicked) # self.connect(self.listWidget, SIGNAL("itemDoubleClicked (QListWidgetItem)"), self.mlistClicked) def initTableContextMenu(self): self.tableWidget.setContextMenuPolicy(Qt.CustomContextMenu) self.popMenu = QMenu(self.tableWidget) delAction = QAction(u'删除', self) # 删除 self.popMenu.addAction(delAction) # 设置表格可以双击修改数据 def setEditTriggers(self, isTrigger): if isTrigger: self.tableWidget.setEditTriggers(QAbstractItemView.DoubleClicked) else: self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers) # 提供给外部修改状态栏消息 def setStatusBarMsg(self, msg): self.mbar.showMessage(msg) # 选框改变时,清空当前表格的全部内容,包括表格头 def updateType(self, mtype): self.impType = mtype self.tableWidget.clear() # 清空表格所有内容 self.initTableHeader() # 初始化表格的每个Item def initTable(self, mlist): self.tableWidget.setRowCount(len(mlist)) for (i, v) in enumerate(mlist): for (j, item) in enumerate(v): if type(item) != str: item = unicode(item) if item == None: item = u"" tabItem = QTableWidgetItem(item) tabItem.setTextAlignment(Qt.AlignCenter) self.tableWidget.setItem(i, j, tabItem) # 初始化错误信息列表 def initListView(self, mlist): for iv in mlist: lisItm = QListWidgetItem(self.listWidget) lisItm.setTextColor(Qt.red) lisItm.setData(Qt.UserRole, iv) if isinstance(iv, basestring): # 如果错误信息是一行字符串 lisItm.setText(iv) else: lisItm.setText(u'第' + unicode(str(iv['row'] + 1)) + u'行,第' + unicode(str(iv['col'] + 1)) + u'列:' + iv['msg']) # 初始化Table的头 def initTableHeader(self): self.heads = [] if self.impType == ImpDateType.SITEANDCELL: # 获取当前项目图层的字段名 cell_layer = getLayerByName(u"小区", self.iface) for head in HeadsConfig.SiteANDCellHead: self.heads.append(head) if len(cell_layer.pendingFields()) > 55: for (index, field) in enumerate(cell_layer.pendingFields()): if index > 54: field_name = field.name().strip() self.heads.append(field_name) else: self.heads = HeadsConfig.ServingCellHead self.tableWidget.setColumnCount(len(self.heads)) # 设置表格的列数 for (i, h) in enumerate(self.heads): tabItem = QTableWidgetItem(h) self.tableWidget.setHorizontalHeaderItem(i, tabItem) # 自定义为Table添加Item def addTableItem(self, row, col, content): tabItem = QTableWidgetItem(content) self.tableWidget.setItem(row, col, tabItem) # 修改Item的内容 def editTableItem(self, row, col, content): tabItem = self.tableWidget.item(row, col) tabItem.setText(content) self.tableWidget.setItem(row, col, tabItem) # 从Excel表读取数据(导入Excel表) def impClick(self): fileName = QFileDialog.getOpenFileName(self, u'基站小区数据导入', '/', 'Excel Files (*.xls *.xlsx)') if fileName.strip() != "": self.setStatusBarMsg(u'选择完毕:' + fileName) importData = GetDataFromExcel(fileName, self.impType, self.heads) self.__mlist = [] self.__mlist.extend(importData.getData()) self.tableWidget.clearContents() self.listWidget.clear() self.initTable(self.__mlist) self.setStatusBarMsg(u'数据导入完成...') self.__isJy = False # 导入完数据后,说明需要重新验证数据的正确性 else: QMessageBox.information(self.parent, u"错误", u"请选中文件") # 数据验证按钮点击事件处理 def yzClick(self): if len(self.__mlist) > 0: self.erlist = [] # 定义一个列表用于保存数据验证错误的数据 # 清楚全部的Item if self.listWidget.count() > 0: self.listWidget.clear() # 根据tableWidget更新self.__mlist for (r, items) in enumerate(self.__mlist): for (v, item) in enumerate(self.__mlist[r]): if self.tableWidget.item(r, v).text() == u"": continue else: # 跟据self.__mlist[r][v]数据类型进行比对 if type(self.__mlist[r][v]) == int: if unicode(self.__mlist[r][v]) != ( self.tableWidget.item(r, v).text()): self.__mlist[r][v] = int( self.tableWidget.item(r, v).text()) elif type(self.__mlist[r][v]) == float: if unicode(self.__mlist[r][v]) != ( self.tableWidget.item(r, v).text()): self.__mlist[r][v] = float( self.tableWidget.item(r, v).text()) elif type(self.__mlist[r][v]) == str: if unicode(self.__mlist[r][v] ) != self.tableWidget.item(r, v).text(): self.__mlist[r][v] = str( self.tableWidget.item(r, v).text()) elif type(self.__mlist[r][v]) == unicode: if (self.__mlist[r][v]) != self.tableWidget.item( r, v).text(): self.__mlist[r][v] = self.tableWidget.item( r, v).text() else: print type(self.__mlist[r][v]) # 执行数据校验函数 self.erlist = checkDataByDataType(self.__mlist, self.impType) if len(self.erlist) > 0: self.initListView(self.erlist) QMessageBox.information(self.parent, u'数据校验', u'数据校验失败,请检查数据正确性后,再导入到地图中') self.__isJy = False else: QMessageBox.information(self.parent, u'数据校验', u'数据校验成功,没有错误数据') self.__isJy = True else: QMessageBox.warning(self.parent, u'数据校验', u'请先导入Excel数据后再操作!') # 导入数据到地图中 def impdateClick(self): if self.__isJy: # 如果数据校验成功 if self.impType == ImpDateType.SITEANDCELL: # 导入基站小区 importDataToLayer = ImportDataToLayer(self.iface, self.__mlist, self.parent) if importDataToLayer.importSiteAndCellData(): QMessageBox.information(self.parent, u"导入数据", u"导入数据成功!") else: QMessageBox.critical(self.parent, u"导入数据", u"导入数据失败!") else: # 导入相邻小区 importDataToLayer = ImportDataToLayer(self.iface, self.__mlist, self.parent) if importDataToLayer.importSCellData(): QMessageBox.information(self.parent, u"导入数据", u"导入数据成功!") else: QMessageBox.critical(self.parent, u"导入数据", u"导入数据失败!") else: QMessageBox.warning(self.parent, u'数据导入', u'请确保校验数据成功后,再导入到地图中') # 编辑Action点击事件 def editClick(self): self.setEditTriggers(self.editAction.isChecked()) # 错误列表双击事件处理 def mlistClicked(self, listItem): itemData = listItem.data(Qt.UserRole) self.tableWidget.setFocus() self.tableWidget.setCurrentCell(itemData['row'], itemData['col']) # 选框改变事件 def comboxChange(self, index): self.updateType(index) # 字段验证是否为空 def __validNull(self, name, col, row, itm, rowitm): if itm is None or itm == '': tmpMap = {} tmpMap['col'] = col tmpMap['row'] = row tmpMap['msg'] = unicode(name) + u'不能为空' tmpMap['item'] = rowitm return tmpMap else: return None # 导入数据线程开始信号 绑定函数 def impStart(self): self.setStatusBarMsg(u'准备导入...') # 导入数据线程发生异常信号 绑定函数 def impError(self, e, exception_string): self.setStatusBarMsg(u'发生错误:' + unicode(e)) QMessageBox.warning(self.parent, u'Excel数据导入', u'发生错误:' + unicode(e)) # 导入数据线程完成信号 绑定函数 def impFinish(self, mylist): self.__mlist = [] self.__mlist.extend(mylist) self.mthread.quit() self.mthread.wait() self.mthread.deleteLater() self.impDateThread.deleteLater() self.tableWidget.clearContents() self.listWidget.clear() self.initTable(self.__mlist) self.setStatusBarMsg(u'数据导入完成...') self.__isJy = False # 导入完数据后,说明需要重新验证数据的正确性 # 导入数据到地图线程发生异常信号 绑定函数 def impError1(self, e, exception_string): self.setStatusBarMsg(u"导入数据发生错误") QMessageBox.critical(self, u'数据导入', u"发生错误:" + unicode(e)) # 导入数据到地图线程完成信号 绑定函数 def impFinish1(self, mylist): self.threadImp.quit() self.threadImp.wait() self.threadImp.deleteLater() self.impFeatureThread.deleteLater() remsg = u'数据导入完成!' layer = None if self.impType == LayerType.SITE: # remsg = u'基站' + remsg layer = getLayerByName(u'基站', self.iface) elif self.impType == LayerType.CELL: # remsg = u'小区' + remsg layer = getLayerByName(u'小区', self.iface) else: remsg = u'相邻小区' + remsg layer = getLayerByName(u'相邻小区', self.iface) self.setStatusBarMsg(remsg) layer.updateExtents() # 更新地图数据 self.iface.actionDraw().trigger() QMessageBox.information(self, u'数据导入', remsg) merlist = [] for eritm in self.erlist: merlist.append(eritm['item']) self.tableWidget.clearContents() # 先清楚表格的内容,再将错误的行显示到表格中 self.initTable(merlist)
def process(self, node): for idx in xrange(0, self.tabs.count()): widget = self.tabs.widget(idx) del widget self.tabs.clear() self.node = node file = self.node.open() tags = EXIF.process_file(file) if len(tags) == 0: self.nometa.setSizePolicy(self.tabs.sizePolicy()) self.tabs.hide() self.nometa.show() else: self.tabs.show() self.nometa.hide() sortedTags = {} for tag in tags.keys(): if tag not in ('JPEGThumbnail', 'TIFFThumbnail', 'Filename', 'EXIF MakerNote'): spaceidx = tag.find(" ") ifd = tag[:spaceidx].strip() if ifd == "Image": ifd = "IFD 0 (Image)" if ifd == "Thumbnail": ifd = "IFD 1 (Thumbnail)" key = tag[spaceidx:].strip() try: val = str(tags[tag]) except: val = "cannot be decoded" if ifd not in sortedTags.keys(): sortedTags[ifd] = [] sortedTags[ifd].append((key, val)) for ifd in sortedTags.keys(): table = QTableWidget(len(sortedTags[ifd]), 2) table.setShowGrid(False) table.setAlternatingRowColors(True) table.verticalHeader().hide() table.horizontalHeader().setClickable(False) table.horizontalHeader().setStretchLastSection(True) table.setHorizontalHeaderLabels(["Tag", "Value"]) table.setSelectionBehavior(QAbstractItemView.SelectRows) self.tabs.addTab(table, ifd) row = 0 for res in sortedTags[ifd]: key = QTableWidgetItem(res[0]) key.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) val = QTableWidgetItem(res[1]) val.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) table.setItem(row, 0, key) table.setItem(row, 1, val) row += 1 if 'JPEGThumbnail' in tags.keys(): label = QLabel() img = QImage() img.loadFromData(tags['JPEGThumbnail']) label.setPixmap(QPixmap.fromImage(img)) label.setAlignment(Qt.AlignCenter) self.tabs.addTab(label, "Embedded Thumbnail") if 'TIFFThumbnail' in tags.keys(): label = QLabel() img = QImage() img.loadFromData(tags['TIFFThumbnail']) label.setPixmap(QPixmap.fromImage(img)) label.setAlignment(Qt.AlignCenter) self.tabs.addTab(label, "Embedded Thumbnail") file.close()
class AvailableWidget(QWidget): def __init__(self, parent, available): QWidget.__init__(self, parent) self._parent = parent self._available = available vbox = QVBoxLayout(self) self._table = QTableWidget(1, 2) self._table.setSelectionMode(QTableWidget.SingleSelection) self._table.removeRow(0) vbox.addWidget(self._table) ui_tools.load_table(self._table, (self.tr('Name'), self.tr('Version')), _format_for_table(available)) self._table.setColumnWidth(0, 500) self._table.setSortingEnabled(True) self._table.setAlternatingRowColors(True) hbox = QHBoxLayout() btnInstall = QPushButton(self.tr('Install')) btnInstall.setMaximumWidth(100) hbox.addWidget(btnInstall) hbox.addWidget(QLabel(self.tr("NINJA needs to be restarted for " "changes to take effect."))) vbox.addLayout(hbox) self.connect(btnInstall, SIGNAL("clicked()"), self._install_plugins) self.connect(self._table, SIGNAL("itemSelectionChanged()"), self._show_item_description) def _show_item_description(self): item = self._table.currentItem() if item is not None: data = list(item.data(Qt.UserRole)) self._parent.show_plugin_info(data) def _install_plugins(self): data = _format_for_table(self._available) plugins = ui_tools.remove_get_selected_items(self._table, data) #get the download link of each plugin for p_row in plugins: #search the plugin for p_dict in self._available: if p_dict["name"] == p_row[0]: p_data = p_dict break #append the downlod link p_row.append(p_data["download"]) #download self._parent.download_plugins(plugins) def remove_item(self, plugin_name): plugin = _get_plugin(plugin_name, self._available) self._available.remove(plugin) def _install_external(self): if self._link.text().isEmpty(): QMessageBox.information(self, self.tr("External Plugins"), self.tr("URL from Plugin missing...")) return plug = [ file_manager.get_module_name(str(self._link.text())), 'External Plugin', '1.0', str(self._link.text())] self.parent().download_plugins(plug) self._link.setText('') def add_table_items(self, plugs): self._available += plugs data = _format_for_table(self._available) ui_tools.load_table(self._table, (self.tr('Name'), self.tr('Version')), data)
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 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()
def process(self, node): for idx in xrange(0, self.tabs.count()): widget = self.tabs.widget(idx) del widget self.tabs.clear() self.node = node file = self.node.open() tags = EXIF.process_file(file) if len(tags) == 0: self.nometa.setSizePolicy(self.tabs.sizePolicy()) self.tabs.hide() self.nometa.show() else: self.tabs.show() self.nometa.hide() sortedTags = {} for tag in tags.keys(): if tag not in ('JPEGThumbnail', 'TIFFThumbnail', 'Filename', 'EXIF MakerNote'): spaceidx = tag.find(" ") ifd = tag[:spaceidx].strip() if ifd == "Image": ifd = "IFD 0 (Image)" if ifd == "Thumbnail": ifd = "IFD 1 (Thumbnail)" key = tag[spaceidx:].strip() try: val = str(tags[tag]) except: val = "cannot be decoded" if ifd not in sortedTags.keys(): sortedTags[ifd] = [] sortedTags[ifd].append((key, val)) for ifd in sortedTags.keys(): table = QTableWidget(len(sortedTags[ifd]), 2) table.setShowGrid(False) table.setAlternatingRowColors(True) table.verticalHeader().hide() table.horizontalHeader().setClickable(False) table.horizontalHeader().setStretchLastSection(True) table.setHorizontalHeaderLabels(["Tag", "Value"]) table.setSelectionBehavior(QAbstractItemView.SelectRows) self.tabs.addTab(table, ifd) row = 0 for res in sortedTags[ifd]: key = QTableWidgetItem(res[0]) key.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) val = QTableWidgetItem(res[1]) val.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) table.setItem(row, 0, key) table.setItem(row, 1, val) row += 1 if 'JPEGThumbnail' in tags.keys(): label = QLabel() img = QImage() img.loadFromData(tags['JPEGThumbnail']) label.setPixmap(QPixmap.fromImage(img)) label.setAlignment(Qt.AlignCenter) self.tabs.addTab(label, "Embedded Thumbnail") if 'TIFFThumbnail' in tags.keys(): label = QLabel() img = QImage() img.loadFromData(tags['TIFFThumbnail']) label.setPixmap(QPixmap.fromImage(img)) label.setAlignment(Qt.AlignCenter) self.tabs.addTab(label, "Embedded Thumbnail") file.close()
class edycja_proby(QDialog): def __init__(self, sample, defpol={}, defpol_order=[], parent=None): ''' defpol and defpol_order should contains the same values, it will not be checked in this class is it valid, pay attention to it''' super(edycja_proby, self).__init__(parent) # self.dane = globals()["daneW"][0] # self.defpol = globals()["daneW"][1] # globals()["daneW"] = [] self.sample = copy.deepcopy(sample) self.sample._edytowany = 'E' self.org_sample = sample self.newName = self.sample.KeyCode() self.setWindowTitle("Sample: " + self.sample.KeyCode()) self.resize(691, 749) self.setMinimumSize(QSize(691, 749)) # self.setMaximumSize(QSize(691, 749)) # Prepare headers self.defpol = defpol self.defpol_order = defpol_order self.prepareDefPol() self.selected = [] # list with index of selected ring in sample # ustawienie pol z danymi self.p_naglowek = QTableWidget() self.p_naglowek.setObjectName("p_naglowek") self.p_naglowek.setColumnCount(1) self.p_naglowek.setRowCount(len(self.headers)) self.p_naglowek.setHorizontalHeaderLabels(["Value"]) self.p_naglowek.setVerticalHeaderLabels(self.headers) self.p_naglowek.setAlternatingRowColors(True) self.p_naglowek.setSortingEnabled(False) self.p_dane = QTableWidget() self.p_dane.setObjectName("p_dane") self.p_dane.setColumnCount(10) self.p_dane.setHorizontalHeaderLabels( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]) self.dodaj = QPushButton("Add") self.usun = QPushButton("Delete") self.przerysuj = QPushButton("Redraw") self.podziel = QPushButton("Divide") self.polacz = QPushButton("Join") self.anuluj = QPushButton("Cancel") self.wykonaj = QPushButton("Update") self.vbl = QVBoxLayout() self.qmc = Qt4MplCanvas(self) self.ntb = NavigationToolbar(self.qmc, self) self.vbl.addWidget(self.qmc) self.vbl.addWidget(self.ntb) self.updateHeaderTable() self.wpisz_pomiary() self.przerysuj_wykres() # ustawiamy wyglad okna layout = QGridLayout() layout.addWidget(self.p_naglowek, 0, 0) layout1 = QGridLayout() layout1.addWidget(self.p_dane, 0, 0, 1, 5) layout1.addWidget(self.dodaj, 1, 0) layout1.addWidget(self.usun, 1, 1) layout1.addWidget(self.podziel, 1, 2) layout1.addWidget(self.polacz, 1, 3) layout1.addWidget(self.przerysuj, 1, 4) layout1.setRowMinimumHeight(1, 25) layout1.setRowStretch(0, 1) layout.addLayout(layout1, 0, 1) layout.addLayout(self.vbl, 1, 0, 1, 2) layout.addWidget(self.anuluj, 2, 0) layout.addWidget(self.wykonaj, 2, 1) layout.setColumnMinimumWidth(0, 290) layout.setColumnStretch(1, 1) layout.setRowStretch(0, 1) layout.setRowMinimumHeight(0, 350) self.setLayout(layout) # Sygnaly self.connect(self.anuluj, SIGNAL("clicked()"), self.schowaj) self.connect(self.wykonaj, SIGNAL("clicked()"), self.wykonaj_odczytanie) self.connect(self.dodaj, SIGNAL("clicked()"), self.dodaj_wartosc) self.connect(self.przerysuj, SIGNAL("clicked()"), self.przerysuj_wykres) self.connect(self.usun, SIGNAL("clicked()"), self.usun_wartosc) self.connect(self.podziel, SIGNAL("clicked()"), self.podziel_wartosc) self.connect(self.polacz, SIGNAL("clicked()"), self.polacz_wartosc) self.p_naglowek.cellChanged.connect(self.edytowana_kom_nagl) self.p_dane.itemSelectionChanged.connect(self.przerysuj_wykres) self.p_dane.cellChanged.connect(self.przerysuj_wykres) def prepareDefPol(self): """Prepare Headers for metadata, BEAWARE! measurements are delete on the end""" self.headers = [ 'KeyCode', 'DateBegin', 'DateEnd', 'Length', 'Gat', 'SapWoodRings', 'measurements', ] add_table = [] if len(self.defpol_order): add_table = self.defpol_order[:] elif len(self.defpol.keys()): add_table = sorted(list(self.defpol.keys())) else: add_table = sorted(self.sample.unikalneNaglowki()) for val in add_table: if val not in self.headers: self.headers.append(val) self.headers.remove('measurements') def updateHeaderTable(self): # Dodaj wartosci wierszow dla tabeli naglowka proby self.p_naglowek.blockSignals(True) for i, val in enumerate(self.headers): if self.sample.wypiszMetadana(val): komorka = QTableWidgetItem(str(self.sample.wypiszMetadana(val))) else: komorka = QTableWidgetItem('---') if val == 'Length': komorka.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.p_naglowek.setItem(i, 0, komorka) self.p_naglowek.blockSignals(False) def wykonaj_odczytanie(self): # spisz cala probe z edytowanych tabel i zapisz ja do zmiennej globalnej # daneW self.odczytaj_dane(origin='org') self.newName = self.org_sample.KeyCode() self.hide() def przerysuj_wykres(self): self.odczytaj_dane() self.updateHeaderTable() self.chartData = [ [], # X axis - years [], # Y axis - measurements ] self.chartData[1] = self.sample.wypiszPomiary() self.chartData[0] = range(1, self.sample.Length() + 1) self.qmc.axes.clear() # draw sample curve self.qmc.axes.plot(self.chartData[0], self.chartData[1]) # draw selected years Xpoints = [] Ypoints = [] self.selected = [] j = 0 for i in range(self.sample.Length()): if i == 11: j += 1 item = self.p_dane.item(j, i-(j*10)) if item.isSelected(): Xpoints.append(i+1) self.selected.append(i) Ypoints.append(int(item.text())) self.qmc.axes.plot(Xpoints, Ypoints, 'ro') # formatting of support lines self.qmc.axes.xaxis.set_major_locator(MultipleLocator(10)) self.qmc.axes.xaxis.set_minor_locator(MultipleLocator(2)) # Prepare axis dimensions Xmax = 40 if self.sample.Length() > 40: Xmax = self.sample.Length() + 2 Ymax = max(self.sample.wypiszPomiary()) + 30 self.qmc.axes.axis([0, Xmax, 0, Ymax]) self.qmc.axes.xaxis.grid( True, 'minor', linewidth=0.4, ls='-', color='0.20') self.qmc.axes.xaxis.grid( True, 'major', linewidth=1, ls='-', color='0.80') self.qmc.axes.tick_params(axis='both', which='major', labelsize=10) self.qmc.axes.set_axisbelow(True) # ustawienie obszaru wykresu self.qmc.axes.set_position([0.03, 0.05, 0.96, 0.94]) self.qmc.draw() def odczytaj_dane(self, origin='copy'): """update sample - read all metadata and measurements which could be altered by user. If origin of sample has to be modified use any string in origin """ if origin == 'copy': target = self.sample else: target = self.org_sample for i, head in enumerate(self.headers): ins = unicode(self.p_naglowek.item(i, 0).text()) if head not in ['Length'] and ins not in ['---', 0]: target.wpiszMetadana( head, ins ) rowNum = self.p_dane.rowCount() colNum = self.p_dane.columnCount() measurements = [] check = 'ok' redraw = 0 for w in range(rowNum): for k in range(colNum): item = self.p_dane.item(w, k) try: if int(item.text()) != 0 and str(item.text()).isdigit: measurements.append(int(item.text())) # if after notOk we find number there is something wrong # and we neef to reread measuremnts to tabel if check == 'notOk': redraw = 1 except: check = 'notOk' target.uaktualnijPom(measurements) if redraw == 1: self.wpisz_pomiary() def dodaj_wartosc(self): kk = 0 self.ile_wierszy = self.p_dane.rowCount() self.ile_kol = self.p_dane.columnCount() for wiersz in range(self.ile_wierszy): for kolumna in range(self.ile_kol): item = self.p_dane.item(wiersz, kolumna) if self.p_dane.isItemSelected(item) == True and kk == 0: kk = 1 text, ok = QInputDialog.getText( self, 'Value', 'inser value: ') if ok: measurements = self.sample.wypiszPomiary() measurements.insert((wiersz*10)+kolumna, int(text)) self.sample.uaktualnijPom(measurements) self.wpisz_pomiary() self.przerysuj_wykres() def usun_wartosc(self): sel = self.selected[:] sel.reverse() for s in sel: self.sample.usunOstatniPomiar(position=int(s)) self.wpisz_pomiary() self.przerysuj_wykres() def wpisz_pomiary(self): # przygotowanie labelek poziomych dla tablicy z pomiarami self.w = (len(self.sample.wypiszPomiary()))/10 if (len(self.sample.wypiszPomiary())) % 10 > 0: self.w += 1 i = 0 self.ww = [] while i < self.w: self.ww.append(str(i*10)) i += 1 self.p_dane.blockSignals(True) self.p_dane.clear() self.p_dane.setRowCount(self.w) self.p_dane.setVerticalHeaderLabels(self.ww) self.p_dane.setAlternatingRowColors(True) self.p_dane.setSortingEnabled(False) # Dodajemy wartosci pomiarow i = 0 j = 0 k = 0 measurements = self.sample.wypiszPomiary() while k < len(measurements): if j == 10: j = 0 i += 1 komorka = QTableWidgetItem(str(measurements[k])) self.p_dane.setItem(i, j, komorka) j += 1 k += 1 # uzupelniamy pozostale pola pustymi wartosciami while j % 10 != 0: komorka = QTableWidgetItem("") self.p_dane.setItem(i, j, komorka) j += 1 self.p_dane.resizeColumnsToContents() self.p_dane.blockSignals(False) def podziel_wartosc(self): if len(self.selected) != 1: pass else: measurements = self.sample.wypiszPomiary() val = measurements[self.selected[0]] self.divideWindow = okno_podzialu(val) self.divideWindow.exec_() measurements.pop(self.selected[0]) self.sample.uaktualnijPom(measurements) self.sample.dodajPomiar(self.divideWindow.val1, position=self.selected[0]) self.sample.dodajPomiar(self.divideWindow.val0, position=self.selected[0]) self.wpisz_pomiary() self.przerysuj_wykres() def polacz_wartosc(self): measurements = self.sample.wypiszPomiary() i = len(measurements) - 1 selectionRange = [] newMeasurements = [] while i > -1: if i in self.selected: selectionRange.append(measurements[i]) elif i not in self.selected: if len(selectionRange) > 0: newMeasurements.append(sum(selectionRange)) selectionRange = [] newMeasurements.append(measurements[i]) i -= 1 if len(selectionRange) > 0: newMeasurements.append(selectionRange) newMeasurements.reverse() self.sample.uaktualnijPom(newMeasurements) self.wpisz_pomiary() self.przerysuj_wykres() def schowaj(self): self.odczytaj_dane() self.hide() def edytowana_kom_nagl(self): # neccessary to maintain user specific date, otherwise it will be # shuflled row = self.p_naglowek.currentRow() self.p_naglowek.blockSignals(True) if self.headers[row] in ['DateBegin', 'DateEnd']: head_temp = self.headers[row] if head_temp == "DateBegin": self.sample.ustawDateBegin( int(self.p_naglowek.item(row, 0).text())) it = QTableWidgetItem(str(self.sample.DateEnd())) self.p_naglowek.setItem(self.headers.index("DateEnd"), 0, it) if head_temp == "DateEnd": self.sample.ustawDateEnd( int(self.p_naglowek.item(row, 0).text())) it = QTableWidgetItem(str(self.sample.DateBegin())) self.p_naglowek.setItem(self.headers.index("DateBegin"), 0, it) self.p_naglowek.blockSignals(False) self.przerysuj_wykres()
class OptimizateNewSiteUI(QDialog): def __init__(self, iface, parent=None): super(OptimizateNewSiteUI, self).__init__() self.iface = iface self.parent = parent self.initUI() # 初始化界面 def initUI(self): self.setWindowTitle(u'自动规划基站优化') self.setWindowIcon(QIcon('images/logo.png')) self.resize(600, 300) self.setWindowFlags(Qt.WindowMinMaxButtonsHint) self.initView() def initView(self): # 数据表格 self.tableWidget = QTableWidget(self) self.tableWidget.setAlternatingRowColors(True) self.tableWidget.setRowCount(7) # 设置当前Table不能编辑 self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers) # 初始化表格上下文菜单 self.initTableContextMenu() self.initTableHeader() # 定义按钮 impBtn = QPushButton(u"导入EXCEL表", self) self.connect(impBtn, SIGNAL('clicked()'), self.impData) startBtn = QPushButton(u"开始合并", self) self.connect(startBtn, SIGNAL('clicked()'), self.mergeJSite) #布局 hbox = QHBoxLayout() hbox.addWidget(impBtn) hbox.addWidget(startBtn) vbox = QVBoxLayout() vbox.addWidget(self.tableWidget) vbox.addLayout(hbox) self.setLayout(vbox) # 判断是否已有规划基站结果 layer = getLayerByName(u'规划基站结果', self.iface) if layer: data_list = [] for feature in layer.getFeatures(): temp_list = [] for value in feature.attributes(): temp_list.append(value) data_list.append(temp_list) del temp_list self.initTable(data_list) self.__mlist = data_list def initTableContextMenu(self): self.tableWidget.setContextMenuPolicy(Qt.CustomContextMenu) self.popMenu = QMenu(self.tableWidget) delAction = QAction(u'删除', self) # 删除 self.popMenu.addAction(delAction) # 初始化Table的头 def initTableHeader(self): self.heads = [] self.heads = MergeSiteHead self.tableWidget.setColumnCount(len(self.heads)) # 设置表格的列数 for (i, h) in enumerate(self.heads): tabItem = QTableWidgetItem(h) self.tableWidget.setHorizontalHeaderItem(i, tabItem) # 导入Excel表数据 def impData(self): fileName = QFileDialog.getOpenFileName(self, u'数据导入', '/', 'Excel Files (*.xls *.xlsx)') if fileName != None and fileName != '': self.impType = ExcelType.MERGESITE getDataFromExcel = GetDataFromExcel(fileName, self.impType) datas_list = getDataFromExcel.getData() self.impFinish(datas_list) # 导入数据完成绑定函数 def impFinish(self, mylist): self.__mlist = [] self.__mlist.extend(mylist) self.tableWidget.clearContents() self.initTable(self.__mlist) # 初始化表格的每个Item def initTable(self, mlist): self.tableWidget.setRowCount(len(mlist)) for (i, v) in enumerate(mlist): for (j, item) in enumerate(v): if type(item) != str: item = unicode(item) if item == None: item = '' tabItem = QTableWidgetItem(item) tabItem.setTextAlignment(Qt.AlignCenter) self.tableWidget.setItem(i, j, tabItem) # 开始运行 def mergeJSite(self): self.accept() merge = OptimizateNewSite(self.__mlist, self) merge.calculationResult.connect(self.calculationFinish) merge.run() def calculationFinish(self, merge_result): self.setResultLayer(merge_result) fileName = QFileDialog.getSaveFileName(self, u'合并结果导出到 ...', '/', 'Excel File(*.xls *.xlsx)') if fileName: self.sphead = [u'规划基站名称', u'经度', u'纬度', u'区域类型', u"平均距离"] for i in range(6): # 根据输入的参数增加表头 self.sphead.append(u'基站名称') self.sphead.append(u'距离') self.sphead.append(u'经度') self.sphead.append(u'纬度') layer = getLayerByName(u"基站合并结果", self.iface) if not layer: QMessageBox.critical(self, u"错误", u"找不到基站合并结果图层") exportData = ExportData(self.iface, self) if exportData.exportDataToExcel(layer, fileName): QMessageBox.information(self, u"成功", u"数据导出成功!") else: QMessageBox.critical(self, u"错误", u"数据导出失败!") else: self.close() # 生成规划基站结果图层 def setResultLayer(self, result_list): layerName = u'规划基站优化结果' layerType = QGis.WKBPoint project_dir = getProjectDir(self.iface) # 先判断是否已存在规划基站结果图层 result_layer = getLayerByName(layerName, self.iface) if result_layer: # 清空数据 delAllFeatures(result_layer) else: # 删除原有图层文件 deleteShapefile(project_dir, layerName) shapPath = os.path.join(project_dir, layerName + u".shp") # 生成图层 fileds = self.createFields() # 创建出Shap文件 # 数据源编码模式为GBK2312(否则中文字段会乱码) wr = QgsVectorFileWriter(shapPath, "GBK2312", fileds, layerType, None, "ESRI Shapefile") # 如果保存的时候没有错误 if wr.hasError() == QgsVectorFileWriter.NoError: pass else: print wr.hasError() raise Exception, wr.errorMessage() # 发生错误,抛出异常交给外面的方法处理异常 del wr # 使添加的字段生效 result_layer = QgsVectorLayer(shapPath, layerName, 'ogr') QgsMapLayerRegistry.instance().addMapLayer(result_layer) # 添加数据 features_list = [] for result in result_list: feature = createABasicPointFeature( QgsPoint(float(result[1]), float(result[2])), result) features_list.append(feature) importFeaturesToLayer(result_layer, features_list) def createFields(self): names = PLANNINGHead types = PLANNINGType2 lengs = PLANNINGLength precs = PLANNINGPrec fields = QgsFields() for (i, itm) in enumerate(names): cuType = types[i] mtype = 'String' if cuType == QVariant.Int: mtype = 'Integer' elif cuType == QVariant.Double: mtype = 'Real' field = QgsField(itm, cuType, mtype, lengs[i], precs[i]) fields.append(field) return fields def exportFinish(self, result): QMessageBox.information(self, u'新建基站结果', u'数据导出到Excel表完成,请查看') def exportError(self, e, erStr): QMessageBox.information(self, u'新建结果', u'生成基站时,发生错误,请重试+' + erStr)
class RLibraryBrowser(QDialog): def __init__(self, parent=None, paths=None): QDialog.__init__(self, parent) QShortcut(QKeySequence("Escape"), self, self.reject) self.setWindowTitle("manageR - Library Browser") self.resize(500, 500) port = robjects.r('tools:::httpdPort')[0] if not port > 0: robjects.r('tools::startDynamicHelp()') port = robjects.r('tools:::httpdPort')[0] robjects.r("""make.packages.html()""") host = "localhost" home = "/doc/html/packages.html" #splitter = QSplitter(self) #splitter.setOrientation(Qt.Vertical) #splitter.setFrameStyle(QFrame.StyledPanel|QFrame.Sunken) labels = QStringList(["Loaded", "Package", "Title", "Path"]) self.parent = parent self.home = home self.packageTable = QTableWidget(0, 4, self) self.htmlViewer = HtmlBrowser(self, host, port, home, paths) #splitter.addWidget(self.packageTable) #splitter.addWidget(self.htmlViewer) vbox = QVBoxLayout(self) #hbox.addWidget(splitter) vbox.addWidget(self.packageTable) vbox.addWidget(self.htmlViewer) self.packageTable.setHorizontalHeaderLabels(labels) self.packageTable.setShowGrid(True) self.packageTable.setSelectionBehavior(QAbstractItemView.SelectRows) self.packageTable.setSelectionMode(QAbstractItemView.SingleSelection) self.packageTable.setAlternatingRowColors(True) self.updatePackages() self.connect(self.packageTable, SIGNAL("itemChanged(QTableWidgetItem*)"), self.loadPackage) self.connect(self.packageTable, SIGNAL("itemDoubleClicked(QTableWidgetItem*)"), self.showPackage) def setSource(self, source): self.htmlViewer.setSource(source) def showPackage(self, item): row = item.row() tmp = self.packageTable.item(row, 1) package = tmp.text() home = QUrl(self.home) curr = QUrl("../../library/%s/html/00Index.html" % package) self.htmlViewer.setSource(home.resolved(curr)) def loadPackage(self, item): row = item.row() tmp = self.packageTable.item(row, 1) package = tmp.text() if item.checkState() == Qt.Checked: command = "library(%s)" % package else: command = "detach('package:%s')" % package robjects.r(command) #self.emit(SIGNAL(...(command) def updatePackages(self): library_ = robjects.r.get('library', mode='function') packages_ = robjects.r.get('.packages', mode='function') loaded = list(packages_()) packages = list(library_()[1]) length = len(packages) self.packageTable.clearContents() #self.table.setRowCount(length/3) packageList = [] for i in range(length/3): package = unicode(packages[i]) if not package in packageList: packageList.append(package) self.packageTable.setRowCount(len(packageList)) item = QTableWidgetItem("Loaded") item.setFlags( Qt.ItemIsUserCheckable|Qt.ItemIsEnabled|Qt.ItemIsSelectable) if package in loaded: item.setCheckState(Qt.Checked) else: item.setCheckState(Qt.Unchecked) self.packageTable.setItem(i, 0, item) item = QTableWidgetItem(unicode(packages[i])) item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsSelectable) self.packageTable.setItem(i, 1, item) item = QTableWidgetItem(unicode(packages[i+(2*(length/3))])) item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsSelectable) self.packageTable.setItem(i, 2, item) item = QTableWidgetItem(unicode(packages[i+(length/3)])) item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsSelectable) self.packageTable.setItem(i, 3, item) self.packageTable.resizeColumnsToContents()
class Main(plugin.Plugin): " Main Class " def initialize(self, *args, **kwargs): " Init Main Class " super(Main, self).initialize(*args, **kwargs) self.scriptPath, self.scriptArgs = "", [] self.profilerPath, self.tempPath = profilerPath, tempPath self.output = " ERROR: FAIL: No output ! " self.process = QProcess() self.process.finished.connect(self.on_process_finished) self.process.error.connect(self.on_process_error) self.tabWidget, self.stat = QTabWidget(), QWidget() self.tabWidget.tabCloseRequested.connect(lambda: self.tabWidget.setTabPosition(1) if self.tabWidget.tabPosition() == 0 else self.tabWidget.setTabPosition(0)) self.tabWidget.setStyleSheet('QTabBar{font-weight:bold;}') self.tabWidget.setMovable(True) self.tabWidget.setTabsClosable(True) self.vboxlayout1 = QVBoxLayout(self.stat) self.hboxlayout1 = QHBoxLayout() self.filterTableLabel = QLabel("<b>Type to Search : </b>", self.stat) self.hboxlayout1.addWidget(self.filterTableLabel) self.filterTableLineEdit = QLineEdit(self.stat) self.filterTableLineEdit.setPlaceholderText(' Type to Search . . . ') self.hboxlayout1.addWidget(self.filterTableLineEdit) self.filterHintTableLabel = QLabel(" ? ", self.stat) self.hboxlayout1.addWidget(self.filterHintTableLabel) self.vboxlayout1.addLayout(self.hboxlayout1) self.tableWidget = QTableWidget(self.stat) self.tableWidget.setAlternatingRowColors(True) self.tableWidget.setColumnCount(8) self.tableWidget.setRowCount(2) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(0, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(1, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(2, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(3, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(4, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(5, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(6, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(7, item) self.tableWidget.itemDoubleClicked.connect( self.on_tableWidget_itemDoubleClicked) self.vboxlayout1.addWidget(self.tableWidget) self.tabWidget.addTab(self.stat, " ? ") self.source = QWidget() self.gridlayout = QGridLayout(self.source) self.scintillaWarningLabel = QLabel( "QScintilla is not installed!. Falling back to basic text edit!.", self.source) self.gridlayout.addWidget(self.scintillaWarningLabel, 1, 0, 1, 2) self.sourceTreeWidget = QTreeWidget(self.source) self.sourceTreeWidget.setAlternatingRowColors(True) self.sourceTreeWidget.itemActivated.connect( self.on_sourceTreeWidget_itemActivated) self.sourceTreeWidget.itemClicked.connect( self.on_sourceTreeWidget_itemClicked) self.sourceTreeWidget.itemDoubleClicked.connect( self.on_sourceTreeWidget_itemClicked) self.gridlayout.addWidget(self.sourceTreeWidget, 0, 0, 1, 1) self.sourceTextEdit = QTextEdit(self.source) self.sourceTextEdit.setReadOnly(True) self.gridlayout.addWidget(self.sourceTextEdit, 0, 1, 1, 1) self.tabWidget.addTab(self.source, " ? ") self.result = QWidget() self.vlayout = QVBoxLayout(self.result) self.globalStatGroupBox = QGroupBox(self.result) self.hboxlayout = QHBoxLayout(self.globalStatGroupBox) self.totalTimeLcdNumber = QLCDNumber(self.globalStatGroupBox) self.totalTimeLcdNumber.setSegmentStyle(QLCDNumber.Filled) self.totalTimeLcdNumber.setNumDigits(7) self.totalTimeLcdNumber.display(1000000) self.totalTimeLcdNumber.setFrameShape(QFrame.StyledPanel) self.totalTimeLcdNumber.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.hboxlayout.addWidget(self.totalTimeLcdNumber) self.tTimeLabel = QLabel("<b>Total Time (Sec)</b>", self.globalStatGroupBox) self.tTimeLabel.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.hboxlayout.addWidget(self.tTimeLabel) self.numCallLcdNumber = QLCDNumber(self.globalStatGroupBox) self.numCallLcdNumber.setNumDigits(7) self.numCallLcdNumber.display(1000000) self.numCallLcdNumber.setSegmentStyle(QLCDNumber.Filled) self.numCallLcdNumber.setFrameShape(QFrame.StyledPanel) self.numCallLcdNumber.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.hboxlayout.addWidget(self.numCallLcdNumber) self.numCallLabel = QLabel("<b>Number of calls</b>", self.globalStatGroupBox) self.numCallLabel.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.hboxlayout.addWidget(self.numCallLabel) self.primCallLcdNumber = QLCDNumber(self.globalStatGroupBox) self.primCallLcdNumber.setSegmentStyle(QLCDNumber.Filled) self.primCallLcdNumber.setFrameShape(QFrame.StyledPanel) self.primCallLcdNumber.setNumDigits(7) self.primCallLcdNumber.display(1000000) self.primCallLcdNumber.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.hboxlayout.addWidget(self.primCallLcdNumber) self.primCallLabel = QLabel("<b>Primitive calls (%)</b>", self.globalStatGroupBox) self.primCallLabel.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.hboxlayout.addWidget(self.primCallLabel) self.vlayout.addWidget(self.globalStatGroupBox) try: from PyKDE4.kdeui import KRatingWidget self.rating = KRatingWidget(self.globalStatGroupBox) self.rating.setToolTip('Profiling Performance Rating') except ImportError: pass self.tabWidget.addTab(self.result, " Get Results ! ") self.resgraph = QWidget() self.vlayout2 = QVBoxLayout(self.result) self.graphz = QGroupBox(self.resgraph) self.hboxlayout2 = QHBoxLayout(self.graphz) try: from PyKDE4.kdeui import KLed KLed(self.graphz) except ImportError: pass self.hboxlayout2.addWidget(QLabel(''' Work in Progress :) Not Ready Yet''')) self.vlayout2.addWidget(self.graphz) self.tabWidget.addTab(self.resgraph, " Graphs and Charts ") self.pathz = QWidget() self.vlayout3 = QVBoxLayout(self.pathz) self.patz = QGroupBox(self.pathz) self.hboxlayout3 = QVBoxLayout(self.patz) self.profilepath = QLineEdit(profilerPath) self.getprofile = QPushButton(QIcon.fromTheme("document-open"), 'Open') self.getprofile.setToolTip('Dont touch if you dont know what are doing') self.getprofile.clicked.connect(lambda: self.profilepath.setText(str( QFileDialog.getOpenFileName(self.patz, ' Open the profile.py file ', path.expanduser("~"), ';;(profile.py)')))) self.hboxlayout3.addWidget(QLabel( '<center><b>Profile.py Python Library Full Path:</b></center>')) self.hboxlayout3.addWidget(self.profilepath) self.hboxlayout3.addWidget(self.getprofile) self.argGroupBox = QGroupBox(self.pathz) self.hbxlayout = QHBoxLayout(self.argGroupBox) self.argLineEdit = QLineEdit(self.argGroupBox) self.argLineEdit.setToolTip('Not touch if you dont know what are doing') self.argLineEdit.setPlaceholderText( 'Dont touch if you dont know what are doing') self.hbxlayout.addWidget(QLabel('<b>Additional Profile Arguments:</b>')) self.hbxlayout.addWidget(self.argLineEdit) self.hboxlayout3.addWidget(self.argGroupBox) self.vlayout3.addWidget(self.patz) self.tabWidget.addTab(self.pathz, " Paths and Configs ") self.outp = QWidget() self.vlayout4 = QVBoxLayout(self.outp) self.outgro = QGroupBox(self.outp) self.outgro.setTitle(" MultiProcessing Output Logs ") self.hboxlayout4 = QVBoxLayout(self.outgro) self.outputlog = QTextEdit() self.outputlog.setText(''' I do not fear computers, I fear the lack of them. -Isaac Asimov ''') self.hboxlayout4.addWidget(self.outputlog) self.vlayout4.addWidget(self.outgro) self.tabWidget.addTab(self.outp, " Logs ") self.actionNew_profiling = QAction(QIcon.fromTheme("document-new"), 'New Profiling', self) self.actionLoad_profile = QAction(QIcon.fromTheme("document-open"), 'Open Profiling', self) self.actionClean = QAction(QIcon.fromTheme("edit-clear"), 'Clean', self) self.actionClean.triggered.connect(lambda: self.clearContent) self.actionAbout = QAction(QIcon.fromTheme("help-about"), 'About', self) self.actionAbout.triggered.connect(lambda: QMessageBox.about(self.dock, __doc__, ', '.join((__doc__, __license__, __author__, __email__)))) self.actionSave_profile = QAction(QIcon.fromTheme("document-save"), 'Save Profiling', self) self.actionManual = QAction(QIcon.fromTheme("help-contents"), 'Help', self) self.actionManual.triggered.connect(lambda: open_new_tab('http://docs.python.org/library/profile.html')) self.tabWidget.setCurrentIndex(2) self.globalStatGroupBox.setTitle("Global Statistics") item = self.tableWidget.horizontalHeaderItem(0) item.setText("Number of Calls") item = self.tableWidget.horizontalHeaderItem(1) item.setText("Total Time") item = self.tableWidget.horizontalHeaderItem(2) item.setText("Per Call") item = self.tableWidget.horizontalHeaderItem(3) item.setText("Cumulative Time") item = self.tableWidget.horizontalHeaderItem(4) item.setText("Per Call") item = self.tableWidget.horizontalHeaderItem(5) item.setText("Filename") item = self.tableWidget.horizontalHeaderItem(6) item.setText("Line") item = self.tableWidget.horizontalHeaderItem(7) item.setText("Function") self.tabWidget.setTabText(self.tabWidget.indexOf(self.stat), "Statistics per Function") self.sourceTreeWidget.headerItem().setText(0, "Source files") self.tabWidget.setTabText(self.tabWidget.indexOf(self.source), "Sources Navigator") ####################################################################### self.scrollable, self.dock = QScrollArea(), QDockWidget() self.scrollable.setWidgetResizable(True) self.scrollable.setWidget(self.tabWidget) self.dock.setWindowTitle(__doc__) self.dock.setStyleSheet('QDockWidget::title{text-align: center;}') self.dock.setWidget(self.scrollable) QToolBar(self.dock).addActions((self.actionNew_profiling, self.actionClean, self.actionSave_profile, self.actionLoad_profile, self.actionManual, self.actionAbout)) self.actionNew_profiling.triggered.connect( self.on_actionNew_profiling_triggered) self.actionLoad_profile.triggered.connect( self.on_actionLoad_profile_triggered) self.actionSave_profile.triggered.connect( self.on_actionSave_profile_triggered) self.locator.get_service('misc').add_widget(self.dock, QIcon.fromTheme("document-open-recent"), __doc__) if QSCI: # Scintilla source editor management self.scintillaWarningLabel.setText(' QScintilla is Ready ! ') layout = self.source.layout() layout.removeWidget(self.sourceTextEdit) self.sourceTextEdit = Qsci.QsciScintilla(self.source) layout.addWidget(self.sourceTextEdit, 0, 1) doc = self.sourceTextEdit doc.setLexer(Qsci.QsciLexerPython(self.sourceTextEdit)) doc.setReadOnly(True) doc.setEdgeMode(Qsci.QsciScintilla.EdgeLine) doc.setEdgeColumn(80) doc.setEdgeColor(QColor("#FF0000")) doc.setFolding(Qsci.QsciScintilla.BoxedTreeFoldStyle) doc.setBraceMatching(Qsci.QsciScintilla.SloppyBraceMatch) doc.setCaretLineVisible(True) doc.setMarginLineNumbers(1, True) doc.setMarginWidth(1, 25) doc.setTabWidth(4) doc.setEolMode(Qsci.QsciScintilla.EolUnix) self.marker = {} for color in COLORS: mnr = doc.markerDefine(Qsci.QsciScintilla.Background) doc.setMarkerBackgroundColor(color, mnr) self.marker[color] = mnr self.currentSourcePath = None # Connect table and tree filter edit signal to unique slot self.filterTableLineEdit.textEdited.connect( self.on_filterLineEdit_textEdited) # Timer to display filter hint message self.filterHintTimer = QTimer(self) self.filterHintTimer.setSingleShot(True) self.filterHintTimer.timeout.connect(self.on_filterHintTimer_timeout) # Timer to start search self.filterSearchTimer = QTimer(self) self.filterSearchTimer.setSingleShot(True) self.filterSearchTimer.timeout.connect( self.on_filterSearchTimer_timeout) self.tabLoaded = {} for i in range(10): self.tabLoaded[i] = False self.backgroundTreeMatchedItems = {} self.resizeWidgetToContent(self.tableWidget) def on_actionNew_profiling_triggered(self): self.clearContent() self.scriptPath = str(QFileDialog.getOpenFileName(self.dock, "Choose your script to profile", path.expanduser("~"), "Python (*.py *.pyw)")) commandLine = [self.profilerPath, "-o", self.tempPath, self.scriptPath] + self.scriptArgs commandLine = " ".join(commandLine) ##if self.termCheckBox.checkState() == Qt.Checked: #termList = ["xterm", "aterm"] #for term in termList: #termPath = which(term) #if termPath: #break #commandLine = """%s -e "%s ; echo 'Press ENTER Exit' ; read" """ \ #% (termPath, commandLine) self.process.start(commandLine) if not self.process.waitForStarted(): print((" ERROR: {} failed!".format(commandLine))) return def on_process_finished(self, exitStatus): ' whan the process end ' print((" INFO: OK: QProcess is %s" % self.process.exitCode())) self.output = self.process.readAll().data() if not self.output: self.output = " ERROR: FAIL: No output ! " self.outputlog.setText(self.output + str(self.process.exitCode())) if path.exists(self.tempPath): self.setStat(self.tempPath) remove(self.tempPath) else: self.outputlog.setText(" ERROR: QProcess FAIL: Profiling failed.") self.tabWidget.setCurrentIndex(2) def on_process_error(self, error): ' when the process fail, I hope you never see this ' print(" ERROR: QProcess FAIL: Profiler Dead, wheres your God now ? ") if error == QProcess.FailedToStart: self.outputlog.setText(" ERROR: FAIL: Profiler execution failed ") elif error == QProcess.Crashed: self.outputlog.setText(" ERROR: FAIL: Profiler execution crashed ") else: self.outputlog.setText(" ERROR: FAIL: Profiler unknown error ") def on_actionLoad_profile_triggered(self): """Load a previous profile sessions""" statPath = str(QFileDialog.getOpenFileName(self.dock, "Open profile dump", path.expanduser("~"), "Profile file (*)")) if statPath: self.clearContent() print(' INFO: OK: Loading profiling from ' + statPath) self.setStat(statPath) def on_actionSave_profile_triggered(self): """Save a profile sessions""" statPath = str(QFileDialog.getSaveFileName(self.dock, "Save profile dump", path.expanduser("~"), "Profile file (*)")) if statPath: #TODO: handle error case and give feelback to user print(' INFO: OK: Saving profiling to ' + statPath) self.stat.save(statPath) #=======================================================================# # Common parts # #=======================================================================# def on_tabWidget_currentChanged(self, index): """slot for tab change""" # Kill search and hint timer if running to avoid cross effect for timer in (self.filterHintTimer, self.filterSearchTimer): if timer.isActive(): timer.stop() if not self.stat: #No stat loaded, nothing to do return self.populateTable() self.populateSource() def on_filterLineEdit_textEdited(self, text): """slot for filter change (table or tree""" if self.filterSearchTimer.isActive(): # Already runnning, stop it self.filterSearchTimer.stop() # Start timer self.filterSearchTimer.start(300) def on_filterHintTimer_timeout(self): """Timeout to warn user about text length""" print("timeout") tab = self.tabWidget.currentIndex() if tab == TAB_FUNCTIONSTAT: label = self.filterHintTableLabel label.setText("Type > 2 characters to search") def on_filterSearchTimer_timeout(self): """timeout to start search""" tab = self.tabWidget.currentIndex() if tab == TAB_FUNCTIONSTAT: text = self.filterTableLineEdit.text() label = self.filterHintTableLabel edit = self.filterTableLineEdit widget = self.tableWidget else: print("Unknow tab for filterSearch timeout !") print(("do search for %s" % text)) if not len(text): # Empty keyword, just clean all if self.filterHintTimer.isActive(): self.filterHintTimer.stop() label.setText(" ? ") self.warnUSer(True, edit) self.clearSearch() return if len(text) < 2: # Don't filter if text is too short and tell it to user self.filterHintTimer.start(600) return else: if self.filterHintTimer.isActive(): self.filterHintTimer.stop() label.setText(" ? ") # Search self.clearSearch() matchedItems = [] if tab == TAB_FUNCTIONSTAT: # Find items matchedItems = widget.findItems(text, Qt.MatchContains) widget.setSortingEnabled(False) matchedRows = [item.row() for item in matchedItems] # Hide matched items header = widget.verticalHeader() for row in range(widget.rowCount()): if row not in matchedRows: header.hideSection(row) widget.setSortingEnabled(True) else: print(" Unknow tab for filterSearch timeout ! ") print(("got %s members" % len(matchedItems))) self.warnUSer(matchedItems, edit) self.resizeWidgetToContent(widget) def resizeWidgetToContent(self, widget): """Resize all columns according to content""" for i in range(widget.columnCount()): widget.resizeColumnToContents(i) def clearSearch(self): """Clean search result For table, show all items For tree, remove colored items""" tab = self.tabWidget.currentIndex() if tab == TAB_FUNCTIONSTAT: header = self.tableWidget.verticalHeader() if header.hiddenSectionCount(): for i in range(header.count()): if header.isSectionHidden(i): header.showSection(i) def clearContent(self): # Clear tabs self.tableWidget.clearContents() self.sourceTreeWidget.clear() # Reset LCD numbers for lcdNumber in (self.totalTimeLcdNumber, self.numCallLcdNumber, self.primCallLcdNumber): lcdNumber.display(1000000) # Reset stat self.pstat = None # Disable save as menu self.actionSave_profile.setEnabled(False) # Mark all tabs as unloaded for i in range(10): self.tabLoaded[i] = False def warnUSer(self, result, inputWidget): palette = inputWidget.palette() if result: palette.setColor(QPalette.Normal, QPalette.Base, QColor(255, 255, 255)) else: palette.setColor(QPalette.Normal, QPalette.Base, QColor(255, 136, 138)) inputWidget.setPalette(palette) inputWidget.update() def setStat(self, statPath): self.stat = Stat(path=statPath) # Global stat update self.totalTimeLcdNumber.display(self.stat.getTotalTime()) self.numCallLcdNumber.display(self.stat.getCallNumber()) self.primCallLcdNumber.display(self.stat.getPrimitiveCallRatio()) # Refresh current tab self.on_tabWidget_currentChanged(self.tabWidget.currentIndex()) # Activate save as menu self.actionSave_profile.setEnabled(True) try: self.rating.setMaxRating(10) self.rating.setRating( int(self.stat.getPrimitiveCallRatio()) / 10 - 1) except: pass #========================================================================# # Statistics table # #=======================================================================# def populateTable(self): row = 0 rowCount = self.stat.getStatNumber() progress = QProgressDialog("Populating statistics table...", "Abort", 0, 2 * rowCount) self.tableWidget.setSortingEnabled(False) self.tableWidget.setRowCount(rowCount) progress.setWindowModality(Qt.WindowModal) for (key, value) in self.stat.getStatItems(): #ncalls item = StatTableWidgetItem(str(value[0])) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_NCALLS, item) colorTableItem(item, self.stat.getCallNumber(), value[0]) #total time item = StatTableWidgetItem(str(value[2])) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_TTIME, item) colorTableItem(item, self.stat.getTotalTime(), value[2]) #per call (total time) if value[0] != 0: tPerCall = str(value[2] / value[0]) cPerCall = str(value[3] / value[0]) else: tPerCall = "" cPerCall = "" item = StatTableWidgetItem(tPerCall) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_TPERCALL, item) colorTableItem(item, 100.0 * self.stat.getTotalTime() / self.stat.getCallNumber(), tPerCall) #per call (cumulative time) item = StatTableWidgetItem(cPerCall) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_CPERCALL, item) colorTableItem(item, 100.0 * self.stat.getTotalTime() / self.stat.getCallNumber(), cPerCall) #cumulative time item = StatTableWidgetItem(str(value[3])) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_CTIME, item) colorTableItem(item, self.stat.getTotalTime(), value[3]) #Filename self.tableWidget.setItem(row, STAT_FILENAME, StatTableWidgetItem(str(key[0]))) #Line item = StatTableWidgetItem(str(key[1])) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_LINE, item) #Function name self.tableWidget.setItem(row, STAT_FUNCTION, StatTableWidgetItem(str(key[2]))) row += 1 # Store it in stat hash array self.stat.setStatLink(item, key, TAB_FUNCTIONSTAT) progress.setValue(row) if progress.wasCanceled(): return for i in range(self.tableWidget.rowCount()): progress.setValue(row + i) for j in range(self.tableWidget.columnCount()): item = self.tableWidget.item(i, j) if item: item.setFlags(Qt.ItemIsEnabled) self.tableWidget.setSortingEnabled(True) self.resizeWidgetToContent(self.tableWidget) progress.setValue(2 * rowCount) def on_tableWidget_itemDoubleClicked(self, item): matchedItems = [] filename = str(self.tableWidget.item(item.row(), STAT_FILENAME).text()) if not filename or filename.startswith("<"): # No source code associated, return immediatly return function = self.tableWidget.item(item.row(), STAT_FUNCTION).text() line = self.tableWidget.item(item.row(), STAT_LINE).text() self.on_tabWidget_currentChanged(TAB_SOURCE) # load source tab function = "%s (%s)" % (function, line) fathers = self.sourceTreeWidget.findItems(filename, Qt.MatchContains, SOURCE_FILENAME) print(("find %s father" % len(fathers))) for father in fathers: findItems(father, function, SOURCE_FILENAME, matchedItems) print(("find %s items" % len(matchedItems))) if matchedItems: self.tabWidget.setCurrentIndex(TAB_SOURCE) self.sourceTreeWidget.scrollToItem(matchedItems[0]) self.on_sourceTreeWidget_itemClicked(matchedItems[0], SOURCE_FILENAME) matchedItems[0].setSelected(True) else: print("oups, item found but cannot scroll to it !") #=======================================================================# # Source explorer # #=====================================================================# def populateSource(self): items = {} for stat in self.stat.getStatKeys(): source = stat[0] function = "%s (%s)" % (stat[2], stat[1]) if source in ("", "profile") or source.startswith("<"): continue # Create the function child child = QTreeWidgetItem([function]) # Store it in stat hash array self.stat.setStatLink(child, stat, TAB_SOURCE) if source in items: father = items[source] else: # Create the father father = QTreeWidgetItem([source]) items[source] = father father.addChild(child) self.sourceTreeWidget.setSortingEnabled(False) for value in list(items.values()): self.sourceTreeWidget.addTopLevelItem(value) self.sourceTreeWidget.setSortingEnabled(True) def on_sourceTreeWidget_itemActivated(self, item, column): self.on_sourceTreeWidget_itemClicked(item, column) def on_sourceTreeWidget_itemClicked(self, item, column): line = 0 parent = item.parent() if QSCI: doc = self.sourceTextEdit if parent: pathz = parent.text(column) result = match("(.*) \(([0-9]+)\)", item.text(column)) if result: try: function = str(result.group(1)) line = int(result.group(2)) except ValueError: # We got garbage... falling back to line 0 pass else: pathz = item.text(column) pathz = path.abspath(str(pathz)) if self.currentSourcePath != pathz: # Need to load source self.currentSourcePath == pathz try: if QSCI: doc.clear() doc.insert(file(pathz).read()) else: self.sourceTextEdit.setPlainText(file(pathz).read()) except IOError: QMessageBox.warning(self, "Error", "Source file could not be found", QMessageBox.Ok) return if QSCI: for function, line in [(i[2], i[1] ) for i in self.stat.getStatKeys() if i[0] == pathz]: # expr, regexp, case sensitive, whole word, wrap, forward doc.findFirst("def", False, True, True, False, True, line, 0, True) end, foo = doc.getCursorPosition() time = self.stat.getStatTotalTime((pathz, line, function)) colorSource(doc, self.stat.getTotalTime(), time, line, end, self.marker) if QSCI: doc.ensureLineVisible(line)