def __init__(self, fname=None, data=None, comment='#', skiprows=0, delimiter=' ', expressions={}, autoupdate=False, parent=None, matplotlib=False, plotIndex=None, colors=None): QDialog.__init__(self, parent=parent) loadUi('UI_Forms/Data_Dialog.ui', self) self.colcycler = cycle(['r', 'g', 'b', 'c', 'm', 'y', 'w']) self.plotWidget = PlotWidget(parent=self, matplotlib=matplotlib) self.plotTab = self.tabWidget.addTab(self.plotWidget, 'Plots') self.tabWidget.setCurrentIndex(0) self.show() self.fileWatcher = QFileSystemWatcher() self.fileWatcher.fileChanged.connect(self.fileUpdated) self.cwd = None self.plotNum = 0 self.xlabel = [] self.ylabel = [] self.oldPlotIndex = {} self.oldColors = {} self.dataAltered = False self.expressions = expressions if data is not None: self.data = data self.autoUpdateCheckBox.setEnabled(False) elif fname is not None: self.data = self.readData(fname, comment=comment, skiprows=skiprows, delimiter=delimiter) else: self.data = None self.autoUpdateCheckBox.setEnabled(False) self.saveDataPushButton.setEnabled(False) self.addRowPushButton.setEnabled(False) self.removeRowsPushButton.setEnabled(False) self.removeColumnPushButton.setEnabled(False) if self.data is not None: self.setMeta2Table() self.setData2Table() if plotIndex is None: self.addPlots(color=None) else: self.addMultiPlots(plotIndex=plotIndex, colors=colors) self.init_signals() self.okPushButton.setAutoDefault(False) self.make_default() self.setWindowTitle('Data Dialog') self.acceptData = True
def create_UI(self): """ Creates the widget user interface """ loadUi('UI_Forms/Data_Reduction_Client.ui',self) self.poniFileLineEdit.setText(str(self.poniFile)) self.maskFileLineEdit.setText(str(self.maskFile)) self.darkFileLineEdit.setText(str(self.darkFile)) self.extractedBaseFolderLineEdit.setText(self.extractedBaseFolder) self.radialPointsLineEdit.setText(str(self.npt)) self.openDataPushButton.clicked.connect(self.openDataFiles) self.reducePushButton.clicked.connect(self.reduce_multiple) self.openDarkPushButton.clicked.connect(self.openDarkFile) self.openPoniPushButton.clicked.connect(lambda x: self.openPoniFile(file=None)) self.calibratePushButton.clicked.connect(self.calibrate) self.maskFileLineEdit.returnPressed.connect(self.maskFileChanged) self.openMaskPushButton.clicked.connect(lambda x: self.openMaskFile(file=None)) self.createMaskPushButton.clicked.connect(self.createMask) self.extractedFolderPushButton.clicked.connect(self.openFolder) self.extractedFolderLineEdit.textChanged.connect(self.extractedFolderChanged) self.polCorrComboBox.currentIndexChanged.connect(self.polarizationChanged) self.polarizationChanged() self.radialPointsLineEdit.returnPressed.connect(self.nptChanged) self.azimuthalRangeLineEdit.returnPressed.connect(self.azimuthalRangeChanged) self.azimuthalRangeChanged() #self.statusLabel.setStyleSheet("color:rgba(0,1,0,0)") self.imageWidget=Image_Widget(zeros((100,100))) self.cakedImageWidget=Image_Widget(zeros((100,100))) imgNumberLabel=QLabel('Image number') self.imgNumberSpinBox=QSpinBox() self.imgNumberSpinBox.setSingleStep(1) self.imageWidget.imageLayout.addWidget(imgNumberLabel,row=2,col=1) self.imageWidget.imageLayout.addWidget(self.imgNumberSpinBox,row=2,col=2) self.imageView=self.imageWidget.imageView.getView() self.plotWidget=PlotWidget() self.plotWidget.setXLabel('Q, Å<sup>-1</sup>',fontsize=5) self.plotWidget.setYLabel('Intensity',fontsize=5) self.tabWidget.addTab(self.plotWidget,'Reduced 1D-data') self.tabWidget.addTab(self.imageWidget,'Masked 2D-data') self.tabWidget.addTab(self.cakedImageWidget,'Reduced Caked Data') self.serverAddress=self.serverAddressLineEdit.text() self.startClientPushButton.clicked.connect(self.startClient) self.stopClientPushButton.clicked.connect(self.stopClient) self.serverAddressLineEdit.returnPressed.connect(self.serverAddressChanged) self.startServerPushButton.clicked.connect(self.startServer) self.stopServerPushButton.clicked.connect(self.stopServer)
def __init__(self): self.app = wx.App(False) wx.Frame.__init__(self, None, title="Nocturnal hypoglycemia prediction", size=(1100, 800)) panel = wx.Panel(self) menu = wx.Menu() about = menu.Append(wx.ID_ABOUT, "&About", "Information about this program") self.Bind(wx.EVT_MENU, lambda x: self.OnAbout(), about) menuBar = wx.MenuBar() menuBar.Append(menu, "&Help") self.SetMenuBar(menuBar) label = wx.StaticText(panel, label="Train dataset path:", pos=(10, 10)) self.m_train_dataset_path_edit = wx.TextCtrl(panel, pos=(10, 30), size=(800, 20)) self.m_train_dataset_path_edit.SetValue(u"D:\GDrive\Диплом 2\DataPreparation\output1\\fixed_dataset+_train.xlsx") label = wx.StaticText(panel, label="Test dataset path:", pos=(10, 60)) self.m_test_dataset_path_edit = wx.TextCtrl(panel, pos=(10, 80), size=(800, 20)) self.m_test_dataset_path_edit.SetValue(u"D:\GDrive\Диплом 2\DataPreparation\output1\\fixed_dataset+_validate_known.xlsx") label = wx.StaticText(panel, label="Choose method:", pos=(10, 110)) self.m_predictor_combobox = wx.ComboBox(panel, pos=(10, 130), size=wx.DefaultSize, choices=['stub RNN', 'stub RNN+demographic'], style=wx.CB_READONLY) self.m_test_button = wx.Button(panel, label="Test", pos=(10, 160), size=wx.DefaultSize) self.m_train_button = wx.Button(panel, label="Train", pos=(110, 160), size=wx.DefaultSize) label = wx.StaticText(panel, label="Prediction log:", pos=(10, 200)) self.m_log = wx.TextCtrl(panel, pos=(10, 220), size=(360, 480), style=wx.TE_MULTILINE | wx.CB_READONLY) self.plot = PlotWidget(panel, pos=(400, 220), size=(10, 20))
def build_screen(self, tree): self.remove_widget(self.loading) box_layout = BoxLayout(orientation="horizontal") splitter = Splitter(sizable_from="right") plot_widget = PlotWidget(tree.root) splitter.add_widget(FilesTreeWidget(tree, plot_widget.draw)) box_layout.add_widget(splitter) box_layout.add_widget(plot_widget) self.add_widget(box_layout)
def show_bar_plot(fig): """This static method show figure of the plot in anew windows """ new_window = Toplevel(root) PlotWidget(new_window, fig) # sets the title of the # Toplevel widget new_window.title("Bar Plot") # sets the geometry of toplevel new_window.geometry("300x300")
def createPlotWidget(self): self._mplFigure = Figure((8.0, 5.0), dpi=100) self._mplCanvas = FigureCanvasQTAgg(self._mplFigure) self._mplCanvas.installEventFilter(self._eventHandler) self._mplCanvas.mpl_connect('pick_event', self.onPick) self._mplAxes = self._mplFigure.add_subplot(1, 1, 1) self._plotWidget = PlotWidget() self._toobarMPL = NavigationToolbar2QT(self._mplCanvas, None) for act in self._toobarMPL.actions(): actionName = str(act.text()).strip() self._mplNavigationActions[actionName] = act self._plotWidget.setCentralWidget(self._mplCanvas) self._toolbar = self._plotWidget.toolBar self.populateToolbar() self._popupMenu = QtGui.QMenu() self._popupMenu.addAction(self._actionLegend) # Connect evenement for the graphic scene self._mplCanvas.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self._mplCanvas.customContextMenuRequested.connect(self.onContextMenu) self._mplCanvas.mpl_connect('scroll_event', self.onScroll) self._mplCanvas.mpl_connect('button_press_event', self.onMousePress)
def __init__(self): super().__init__() # widgets self.video_window=VideoWindow(PixelPermm = 314) self.fps=None #fps for saving self.xplot = PlotWidget('X displacement', label = 'X',color ='r') self.yplot = PlotWidget('Y displacement', label = 'Y',color ='g') self.zplot = PlotWidget('Z displacement', label = 'Z',color =(50, 100, 255)) self.plot3D_widget = plot3D_widget() self.AnalysisWidget = AnalysisWidget() # controller self.video_saver=VideoSaver() self.isImageSaver=False #True: image_saver will be chose in place of video saver self.csv_reader=CSV_Reader(flip_z = False) #---------------------------------------------------------------------- # Toggle Comment/Uncomment to turn Z-plot ON and OFF #---------------------------------------------------------------------- # VERTICAL LAYOUT ON THE LEFT v_left_layout=QtGui.QVBoxLayout() v_left_layout.addWidget(self.video_window) v_right_layout = QtGui.QVBoxLayout() v_right_layout.addWidget(self.plot3D_widget) # Comment/Uncomment below to remove the image analysis widget v_right_layout.addWidget(self.AnalysisWidget) # v_right_layout=QtGui.QVBoxLayout() # v_right_layout.addWidget(self.xplot) # v_right_layout.addWidget(self.yplot) # v_right_layout.addWidget(self.zplot) # v_right_layout.setStretchFactor(self.xplot,1) # v_right_layout.setStretchFactor(self.yplot,1) # v_right_layout.setStretchFactor(self.zplot,1) h_layout = QtGui.QHBoxLayout() h_layout.addLayout(v_left_layout) # h_layout.addLayout(v_right_layout) h_layout.addLayout(v_right_layout) # h_layout.addLayout(v_layout) # h_layout.addLayout(plot3D_layout) h_layout.setStretchFactor(v_left_layout,1) # h_layout.setStretchFactor(v_right_layout,1) h_layout.setStretchFactor(v_right_layout,1) # Final action # self.setLayout(v_layout) self.setLayout(h_layout)
def __init__(self, parent): super(QWidget, self).__init__(parent) self.layout = QGridLayout(self) # Initialize tab screen self.tabs = QTabWidget() self.tab1 = SettingsWidget(parent) self.tab2 = PlotWidget(parent) # Add tabs self.tabs.addTab(self.tab1, "") self.tabs.addTab(self.tab2, "") # Add tabs to widget self.layout.addWidget(self.tabs) self.setLayout(self.layout) self.initUI()
def __init__(self): filename = "MainWindow.glade" builder = gtk.Builder() builder.add_from_file(filename) builder.connect_signals(self) self.window = builder.get_object("mainWindow") self.window.connect("destroy", self.onDeleteWindow) self.window.show_all() self.functionsVbox = builder.get_object("functionsVbox") self.addFunctionButton = builder.get_object("addFuncitonButton") self.viewParamsStatusBar = builder.get_object('viewParamsLabel') self.errorsStatusBar = builder.get_object('errorsLabel') self.eventbox1 = builder.get_object("eventbox1") self.plotWidget = PlotWidget() self.plotWidget.connect('view_updated', self.update_plotview_status_bar) self.plotWidget.update_view_info() self.plotWidget.show() self.eventbox1.add(self.plotWidget)
def createPlotWidget(self): self._mplFigure = Figure((8.0,5.0), dpi=100) self._mplCanvas = FigureCanvasQTAgg(self._mplFigure) self._mplCanvas.installEventFilter(self._eventHandler) self._mplCanvas.mpl_connect('pick_event', self.onPick) self._mplAxes = self._mplFigure.add_subplot(1, 1, 1) self._plotWidget = PlotWidget() self._toobarMPL = NavigationToolbar2QT(self._mplCanvas, None) for act in self._toobarMPL.actions(): actionName = str(act.text()).strip() self._mplNavigationActions[actionName] = act self._plotWidget.setCentralWidget(self._mplCanvas) self._toolbar = self._plotWidget.toolBar self.populateToolbar() self._popupMenu = QtGui.QMenu() self._popupMenu.addAction(self._actionLegend) # Connect evenement for the graphic scene self._mplCanvas.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self._mplCanvas.customContextMenuRequested.connect(self.onContextMenu) self._mplCanvas.mpl_connect('scroll_event', self.onScroll) self._mplCanvas.mpl_connect('button_press_event', self.onMousePress)
def setupUi(self, Form): Form.setObjectName("Form") Form.resize(726, 588) self.verticalLayout = QtGui.QVBoxLayout(Form) self.verticalLayout.setSpacing(0) self.verticalLayout.setMargin(0) self.verticalLayout.setObjectName("verticalLayout") self.splitter = QtGui.QSplitter(Form) self.splitter.setOrientation(QtCore.Qt.Vertical) self.splitter.setObjectName("splitter") self.layoutWidget = QtGui.QWidget(self.splitter) self.layoutWidget.setObjectName("layoutWidget") self.gridLayout = QtGui.QGridLayout(self.layoutWidget) self.gridLayout.setMargin(0) self.gridLayout.setSpacing(0) self.gridLayout.setObjectName("gridLayout") self.graphicsView = GraphicsView(self.layoutWidget) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(10) sizePolicy.setVerticalStretch(10) sizePolicy.setHeightForWidth(self.graphicsView.sizePolicy().hasHeightForWidth()) self.graphicsView.setSizePolicy(sizePolicy) self.graphicsView.setObjectName("graphicsView") self.gridLayout.addWidget(self.graphicsView, 1, 0, 3, 1) self.roiBtn = QtGui.QPushButton(self.layoutWidget) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(1) sizePolicy.setHeightForWidth(self.roiBtn.sizePolicy().hasHeightForWidth()) self.roiBtn.setSizePolicy(sizePolicy) self.roiBtn.setMaximumSize(QtCore.QSize(30, 16777215)) self.roiBtn.setCheckable(True) self.roiBtn.setObjectName("roiBtn") self.gridLayout.addWidget(self.roiBtn, 3, 3, 1, 1) self.gradientWidget = GradientWidget(self.layoutWidget) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(100) sizePolicy.setHeightForWidth(self.gradientWidget.sizePolicy().hasHeightForWidth()) self.gradientWidget.setSizePolicy(sizePolicy) self.gradientWidget.setObjectName("gradientWidget") self.gridLayout.addWidget(self.gradientWidget, 1, 3, 1, 1) self.normBtn = QtGui.QPushButton(self.layoutWidget) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(1) sizePolicy.setHeightForWidth(self.normBtn.sizePolicy().hasHeightForWidth()) self.normBtn.setSizePolicy(sizePolicy) self.normBtn.setMaximumSize(QtCore.QSize(30, 16777215)) self.normBtn.setCheckable(True) self.normBtn.setObjectName("normBtn") self.gridLayout.addWidget(self.normBtn, 2, 3, 1, 1) self.normGroup = QtGui.QGroupBox(self.layoutWidget) self.normGroup.setObjectName("normGroup") self.gridLayout_2 = QtGui.QGridLayout(self.normGroup) self.gridLayout_2.setMargin(0) self.gridLayout_2.setSpacing(0) self.gridLayout_2.setObjectName("gridLayout_2") self.normSubtractRadio = QtGui.QRadioButton(self.normGroup) self.normSubtractRadio.setObjectName("normSubtractRadio") self.gridLayout_2.addWidget(self.normSubtractRadio, 0, 2, 1, 1) self.normDivideRadio = QtGui.QRadioButton(self.normGroup) self.normDivideRadio.setChecked(False) self.normDivideRadio.setObjectName("normDivideRadio") self.gridLayout_2.addWidget(self.normDivideRadio, 0, 1, 1, 1) self.label_5 = QtGui.QLabel(self.normGroup) font = QtGui.QFont() font.setWeight(75) font.setBold(True) self.label_5.setFont(font) self.label_5.setObjectName("label_5") self.gridLayout_2.addWidget(self.label_5, 0, 0, 1, 1) self.label_3 = QtGui.QLabel(self.normGroup) font = QtGui.QFont() font.setWeight(75) font.setBold(True) self.label_3.setFont(font) self.label_3.setObjectName("label_3") self.gridLayout_2.addWidget(self.label_3, 1, 0, 1, 1) self.label_4 = QtGui.QLabel(self.normGroup) font = QtGui.QFont() font.setWeight(75) font.setBold(True) self.label_4.setFont(font) self.label_4.setObjectName("label_4") self.gridLayout_2.addWidget(self.label_4, 2, 0, 1, 1) self.normROICheck = QtGui.QCheckBox(self.normGroup) self.normROICheck.setObjectName("normROICheck") self.gridLayout_2.addWidget(self.normROICheck, 1, 1, 1, 1) self.normXBlurSpin = QtGui.QDoubleSpinBox(self.normGroup) self.normXBlurSpin.setObjectName("normXBlurSpin") self.gridLayout_2.addWidget(self.normXBlurSpin, 2, 2, 1, 1) self.label_8 = QtGui.QLabel(self.normGroup) self.label_8.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.label_8.setObjectName("label_8") self.gridLayout_2.addWidget(self.label_8, 2, 1, 1, 1) self.label_9 = QtGui.QLabel(self.normGroup) self.label_9.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.label_9.setObjectName("label_9") self.gridLayout_2.addWidget(self.label_9, 2, 3, 1, 1) self.normYBlurSpin = QtGui.QDoubleSpinBox(self.normGroup) self.normYBlurSpin.setObjectName("normYBlurSpin") self.gridLayout_2.addWidget(self.normYBlurSpin, 2, 4, 1, 1) self.label_10 = QtGui.QLabel(self.normGroup) self.label_10.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.label_10.setObjectName("label_10") self.gridLayout_2.addWidget(self.label_10, 2, 5, 1, 1) self.normOffRadio = QtGui.QRadioButton(self.normGroup) self.normOffRadio.setChecked(True) self.normOffRadio.setObjectName("normOffRadio") self.gridLayout_2.addWidget(self.normOffRadio, 0, 3, 1, 1) self.normTimeRangeCheck = QtGui.QCheckBox(self.normGroup) self.normTimeRangeCheck.setObjectName("normTimeRangeCheck") self.gridLayout_2.addWidget(self.normTimeRangeCheck, 1, 3, 1, 1) self.normFrameCheck = QtGui.QCheckBox(self.normGroup) self.normFrameCheck.setObjectName("normFrameCheck") self.gridLayout_2.addWidget(self.normFrameCheck, 1, 2, 1, 1) self.normTBlurSpin = QtGui.QDoubleSpinBox(self.normGroup) self.normTBlurSpin.setObjectName("normTBlurSpin") self.gridLayout_2.addWidget(self.normTBlurSpin, 2, 6, 1, 1) self.gridLayout.addWidget(self.normGroup, 0, 0, 1, 4) self.roiPlot = PlotWidget(self.splitter) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.roiPlot.sizePolicy().hasHeightForWidth()) self.roiPlot.setSizePolicy(sizePolicy) self.roiPlot.setMinimumSize(QtCore.QSize(0, 40)) self.roiPlot.setObjectName("roiPlot") self.verticalLayout.addWidget(self.splitter) self.retranslateUi(Form) QtCore.QMetaObject.connectSlotsByName(Form)
class Data_Reducer(QWidget): """ This widget is developed to reduce on the fly 2D SAXS data to azimuthally averaged 1D SAXS data """ def __init__(self,poniFile=None,dataFile=None, darkFile=None, maskFile=None,extractedFolder='/tmp', npt=1000, transmission_corr=True, azimuthRange=(-180.0,180.0), parent=None): """ poniFile is the calibration file obtained after Q-calibration """ QWidget.__init__(self,parent) self.layout=QGridLayout(self) self.setup_dict=json.load(open('./SetupData/reducer_setup.txt','r')) if poniFile is not None: self.poniFile=poniFile else: self.poniFile=self.setup_dict['poniFile'] if maskFile is not None: self.maskFile=maskFile else: self.maskFile=self.setup_dict['maskFile'] self.dataFile=dataFile if darkFile is None: self.dark_corrected=False self.darkFile='' else: self.darkFile=darkFile self.dark_corrected=True self.curDir=os.getcwd() self.extractedFolder=extractedFolder self.npt=npt self.set_externally=False self.transmission_corr=transmission_corr #ai=AIWidget() #self.layout.addWidget(ai) self.azimuthRange=azimuthRange self.create_UI() if os.path.exists(self.poniFile): self.openPoniFile(file=self.poniFile) if os.path.exists(self.maskFile): self.openMaskFile(file=self.maskFile) def create_UI(self): """ Creates the widget user interface """ row=0 col=0 dataFileLabel=QLabel('Data file') self.layout.addWidget(dataFileLabel,row,col) col+=1 self.dataFileLineEdit=QLineEdit(self.dataFile) self.layout.addWidget(self.dataFileLineEdit,row,col,1,2) col+=2 self.openDataPushButton=QPushButton('Select') self.openDataPushButton.clicked.connect(self.openDataFiles) self.layout.addWidget(self.openDataPushButton,row,col) col+=1 self.reducePushButton=QPushButton('Reduce data') self.reducePushButton.clicked.connect(self.reduce_multiple) self.layout.addWidget(self.reducePushButton,row,col,1,1) row+=1 col=0 darkFileLabel=QLabel('Dark file') self.layout.addWidget(darkFileLabel,row,col) col+=1 self.darkFileLineEdit=QLineEdit(self.darkFile) self.layout.addWidget(self.darkFileLineEdit,row,col,1,2) col+=2 self.openDarkPushButton=QPushButton('Select') self.openDarkPushButton.clicked.connect(self.openDarkFile) self.layout.addWidget(self.openDarkPushButton,row,col) col+=1 self.darkCheckBox=QCheckBox('Dark Correction') self.layout.addWidget(self.darkCheckBox,row,col) row+=1 col=0 poniFileLabel=QLabel('Calibration file') self.layout.addWidget(poniFileLabel,row,col) col+=1 self.poniFileLineEdit=QLineEdit(self.poniFile) self.layout.addWidget(self.poniFileLineEdit,row,col,1,2) col+=2 self.openPoniPushButton=QPushButton('Select') self.openPoniPushButton.clicked.connect(lambda x: self.openPoniFile(file=None)) self.layout.addWidget(self.openPoniPushButton,row,col) col+=1 self.calibratePushButton=QPushButton('Calibrate') self.calibratePushButton.clicked.connect(self.calibrate) self.layout.addWidget(self.calibratePushButton,row,col) row+=1 col=0 maskFileLabel=QLabel('Mask file') self.layout.addWidget(maskFileLabel,row,col) col+=1 self.maskFileLineEdit=QLineEdit(self.maskFile) self.maskFileLineEdit.returnPressed.connect(self.maskFileChanged) self.layout.addWidget(self.maskFileLineEdit,row,col,1,2) col+=2 self.openMaskPushButton=QPushButton('Select') self.openMaskPushButton.clicked.connect(lambda x: self.openMaskFile(file=None)) self.layout.addWidget(self.openMaskPushButton,row,col) col+=1 self.createMaskPushButton=QPushButton('Create mask') self.createMaskPushButton.clicked.connect(self.createMask) self.layout.addWidget(self.createMaskPushButton,row,col) row+=1 col=0 extractedFolderLabel=QLabel('Extracted folder') self.layout.addWidget(extractedFolderLabel,row,col) col+=1 self.extractedFolderLineEdit=QLineEdit() self.layout.addWidget(self.extractedFolderLineEdit,row,col,1,2) col+=2 self.extractedFolderPushButton=QPushButton('Select') self.extractedFolderPushButton.clicked.connect(self.openFolder) self.layout.addWidget(self.extractedFolderPushButton,row,col) row+=1 col=0 radialPointsLabel=QLabel('Radial Points') self.layout.addWidget(radialPointsLabel,row,col) col+=1 self.radialPointsLineEdit=QLineEdit(str(self.npt)) self.radialPointsLineEdit.returnPressed.connect(self.nptChanged) self.layout.addWidget(self.radialPointsLineEdit,row,col) col+=1 azimuthRangeLabel=QLabel('Azimuthal Range (min:max)') self.layout.addWidget(azimuthRangeLabel,row,col) col+=1 self.azimuthRangeLineEdit=QLineEdit('%.2f:%.2f'%(self.azimuthRange[0],self.azimuthRange[1])) self.azimuthRangeLineEdit.returnPressed.connect(self.azimuthRangeChanged) self.layout.addWidget(self.azimuthRangeLineEdit,row,col) col+=1 self.transCorrCheckBox=QCheckBox('Transmission Correction') self.transCorrCheckBox.setTristate(False) self.transCorrCheckBox.setChecked(self.transmission_corr) self.layout.addWidget(self.transCorrCheckBox) row+=1 col=0 progressLabel=QLabel('Status') self.layout.addWidget(progressLabel,row,col,1,1) col+=1 self.progressBar=QProgressBar() self.layout.addWidget(self.progressBar,row,col,1,1) col+=1 self.statusLabel=QLabel('Idle') self.layout.addWidget(self.statusLabel,row,col,1,1) col+=1 normLabel=QLabel('Normalized by') self.normComboBox=QComboBox() self.normComboBox.addItems(['BSDiode','Image sum','Monitor']) self.layout.addWidget(normLabel,row,col,1,1) col+=1 self.layout.addWidget(self.normComboBox,row,col,1,1) row+=1 col=0 self.tabWidget=QTabWidget(self) self.layout.addWidget(self.tabWidget,row,col,20,5) self.imageWidget=Image_Widget(zeros((100,100))) imgNumberLabel=QLabel('Image number') self.imgNumberSpinBox=QSpinBox() self.imgNumberSpinBox.setSingleStep(1) self.imageWidget.imageLayout.addWidget(imgNumberLabel,row=2,col=1) self.imageWidget.imageLayout.addWidget(self.imgNumberSpinBox,row=2,col=2) self.imageView=self.imageWidget.imageView.getView() self.plotWidget=PlotWidget() self.plotWidget.setXLabel('Q, Å<sup>-1</sup>',fontsize=5) self.plotWidget.setYLabel('Intensity',fontsize=5) self.tabWidget.addTab(self.plotWidget,'Reduced 1D-data') self.tabWidget.addTab(self.imageWidget,'Masked 2D-data') def createMask(self): """ Opens a mask-widget to create mask file """ fname=str(QFileDialog.getOpenFileName(self,'Select an image file', directory=self.curDir,filter='Image file (*.edf *.tif)')[0]) if fname is not None or fname!='': img=fb.open(fname).data self.maskWidget=MaskWidget(img) self.maskWidget.saveMaskPushButton.clicked.disconnect() self.maskWidget.saveMaskPushButton.clicked.connect(self.save_mask) self.maskWidget.show() else: QMessageBox.warning(self,'File error','Please import a data file first for creating the mask',QMessageBox.Ok) def maskFileChanged(self): """ Changes the mask file """ maskFile=str(self.maskFileLineEdit.text()) if str(maskFile)=='': self.maskFile=None elif os.path.exists(maskFile): self.maskFile=maskFile else: self.maskFile=None def save_mask(self): """ Saves the entire mask combining all the shape ROIs """ fname=str(QFileDialog.getSaveFileName(filter='Mask Files (*.msk)')[0]) name,extn=os.path.splitext(fname) if extn=='': fname=name+'.msk' elif extn!='.msk': QMessageBox.warning(self,'File extension error','Please donot provide file extension other than ".msk". Thank you!') return else: tmpfile=fb.edfimage.EdfImage(data=self.maskWidget.full_mask_data.T,header=None) tmpfile.save(fname) self.maskFile=fname self.maskFileLineEdit.setText(self.maskFile) def calibrate(self): """ Opens a calibartion widget to create calibration file """ fname=str(QFileDialog.getOpenFileName(self,'Select calibration image',directory=self.curDir, filter='Calibration image (*.edf *.tif)')[0]) if fname is not None: img=fb.open(fname).data pixel1=79.0 pixel2=79.0 self.calWidget=CalibrationWidget(img,pixel1,pixel2) self.calWidget.saveCalibrationPushButton.clicked.disconnect() self.calWidget.saveCalibrationPushButton.clicked.connect(self.save_calibration) self.calWidget.show() else: QMessageBox.warning(self,'File error','Please import a data file first for creating the calibration file',QMessageBox.Ok) def save_calibration(self): fname=str(QFileDialog.getSaveFileName(self,'Calibration file',directory=self.curDir,filter='Clibration files (*.poni)')[0]) tfname=os.path.splitext(fname)[0]+'.poni' self.calWidget.applyPyFAI() self.calWidget.geo.save(tfname) self.poniFile=tfname self.poniFileLineEdit.setText(self.poniFile) def openPoniFile(self,file=None): """ Select and imports the calibration file """ if file is None: self.poniFile=QFileDialog.getOpenFileName(self,'Select calibration file',directory=self.curDir,filter='Calibration file (*.poni)')[0] self.poniFileLineEdit.setText(self.poniFile) else: self.poniFile=file if os.path.exists(self.poniFile): self.setup_dict['poniFile']=self.poniFile json.dump(self.setup_dict,open('./SetupData/reducer_setup.txt','w')) fh=open(self.poniFile,'r') lines=fh.readlines() self.calib_data={} for line in lines: if line[0]!='#': key,val=line.split(': ') self.calib_data[key]=float(val) self.dist=self.calib_data['Distance'] self.pixel1=self.calib_data['PixelSize1'] self.pixel2=self.calib_data['PixelSize2'] self.poni1=self.calib_data['Poni1'] self.poni2=self.calib_data['Poni2'] self.rot1=self.calib_data['Rot1'] self.rot2=self.calib_data['Rot2'] self.rot3=self.calib_data['Rot3'] self.wavelength=self.calib_data['Wavelength'] self.ai=AzimuthalIntegrator(dist=self.dist,poni1=self.poni1,poni2=self.poni2,pixel1=self.pixel1,pixel2=self.pixel2,rot1=self.rot1,rot2=self.rot2,rot3=self.rot3,wavelength=self.wavelength) #pos=[self.poni2/self.pixel2,self.poni1/self.pixel1] #self.roi=cake(pos,movable=False) #self.roi.sigRegionChangeStarted.connect(self.endAngleChanged) #self.imageView.addItem(self.roi) else: QMessageBox.warning(self,'File error','The calibration file '+self.poniFile+' doesnot exists.',QMessageBox.Ok) def endAngleChanged(self,evt): print(evt.pos()) def nptChanged(self): """ Changes the number of radial points """ try: self.npt=int(self.radialPointsLineEdit.text()) except: QMessageBox.warning(self,'Value error', 'Please input positive integers only.',QMessageBox.Ok) def azimuthRangeChanged(self): """ Changes the azimuth angular range """ try: self.azimuthRange=tuple(map(float, self.azimuthRangeLineEdit.text().split(':'))) except: QMessageBox.warning(self,'Value error','Please input min:max angles in floating point numbers',QMessageBox.Ok) def openDataFile(self): """ Select and imports one data file """ dataFile=QFileDialog.getOpenFileName(self,'Select data file',directory=self.curDir,filter='Data file (*.edf *.tif)')[0] if dataFile!='': self.dataFile=dataFile self.curDir=os.path.dirname(self.dataFile) self.dataFileLineEdit.setText(self.dataFile) self.data2d=fb.open(self.dataFile).data if self.darkFile is not None: self.applyDark() if self.maskFile is not None: self.applyMask() self.imageWidget.setImage(self.data2d,transpose=True) self.tabWidget.setCurrentWidget(self.imageWidget) if not self.set_externally: self.extractedFolder=os.path.join(self.curDir,'extracted_pyFAI') if not os.path.exists(self.extractedFolder): os.makedirs(self.extractedFolder) def openDataFiles(self): """ Selects and imports multiple data files """ self.dataFiles=QFileDialog.getOpenFileNames(self,'Select data files', directory=self.curDir,filter='Data files (*.edf *.tif)')[0] if len(self.dataFiles)!=0: self.imgNumberSpinBox.valueChanged.connect(self.imageChanged) self.imgNumberSpinBox.setMinimum(0) self.imgNumberSpinBox.setMaximum(len(self.dataFiles)-1) self.dataFileLineEdit.setText(str(self.dataFiles)) self.curDir=os.path.dirname(self.dataFiles[0]) self.extractedFolder=os.path.join(self.curDir,'extracted_pyFAI') if not os.path.exists(self.extractedFolder): os.makedirs(self.extractedFolder) self.extractedFolderLineEdit.setText(self.extractedFolder) self.imgNumberSpinBox.setValue(0) self.imageChanged() def imageChanged(self): self.data2d=fb.open(self.dataFiles[self.imgNumberSpinBox.value()]).data if self.darkFile is not None: self.applyDark() if self.maskFile is not None: self.applyMask() self.imageWidget.setImage(self.data2d,transpose=True) def applyDark(self): if not self.dark_corrected and self.darkFile!='': self.dark2d=fb.open(self.darkFile).data self.data2d=self.data2d-self.dark2d self.dark_corrected=True def applyMask(self): self.mask2d=fb.open(self.maskFile).data self.data2d=self.data2d*(1+self.mask2d)/2.0 self.mask_applied=True def openDarkFile(self): """ Select and imports the dark file """ self.darkFile=QFileDialog.getOpenFileName(self,'Select dark file',directory=self.curDir,filter='Dark file (*.edf)')[0] if self.darkFile!='': self.dark_corrected=False self.darkFileLineEdit.setText(self.darkFile) if self.dataFile is not None: self.data2d=fb.open(self.dataFile).data self.applyDark() def openMaskFile(self,file=None): """ Select and imports the Mask file """ if file is None: self.maskFile=QFileDialog.getOpenFileName(self,'Select mask file',directory=self.curDir,filter='Mask file (*.msk)')[0] else: self.maskFile=file if self.maskFile!='': self.mask_applied=False if os.path.exists(self.maskFile): self.curDir=os.path.dirname(self.maskFile) self.maskFileLineEdit.setText(self.maskFile) self.setup_dict['maskFile']=self.maskFile self.setup_dict['poniFile']=self.poniFile json.dump(self.setup_dict,open('./SetupData/reducer_setup.txt','w')) else: self.openMaskFile(file=None) if self.dataFile is not None: self.applyMask() else: self.maskFile=None self.maskFileLineEdit.clear() def openFolder(self): """ Select the folder to save the reduce data """ self.extractedFolder=QFileDialog.getExistingDirectory(self,'Select extracted directory',directory=self.curDir) if self.extractedFolder!='': self.extractedFolderLineEdit.setText(self.extractedFolder) self.set_externally=True def reduceData(self): """ Reduces the 2d data to 1d data """ print('Iloveu', self.darkFile) if (self.dataFile is not None) and (os.path.exists(self.dataFile)): if (self.poniFile is not None) and (os.path.exists(self.poniFile)): # self.statusLabel.setText('Busy') # self.progressBar.setRange(0, 0) imageData=fb.open(self.dataFile) #self.data2d=imageData.data #if self.maskFile is not None: # self.applyMask() #self.imageWidget.setImage(self.data2d,transpose=True) #self.tabWidget.setCurrentWidget(self.imageWidget) self.header=imageData.header try: self.ai.set_wavelength(float(self.header['Wavelength'])*1e-10) except: self.ai.set_wavelength(self.wavelength) print('Iloveu',self.darkFile) if os.path.exists(self.dataFile.split('.')[0]+'_dark.edf') and self.darkCheckBox.isChecked(): self.darkFile=self.dataFile.split('.')[0]+'_dark.edf' dark=fb.open(self.darkFile) self.darkFileLineEdit.setText(self.darkFile) imageDark=dark.data self.header['BSDiode_corr']=max([1.0,(float(imageData.header['BSDiode'])-float(dark.header['BSDiode']))]) self.header['Monitor_corr']=max([1.0,(float(imageData.header['Monitor'])-float(dark.header['Monitor']))]) print("Dark File read from existing dark files") elif self.darkFile is not None and self.darkFile!='' and self.darkCheckBox.isChecked(): dark=fb.open(self.darkFile) imageDark=dark.data self.header['BSDiode_corr']=max([1.0,(float(imageData.header['BSDiode'])-float(dark.header['BSDiode']))]) self.header['Monitor_corr']=max([1.0,(float(imageData.header['Monitor'])-float(dark.header['Monitor']))]) print("Dark File from memory subtracted") else: imageDark=None try: self.header['BSDiode_corr']=float(imageData.header['BSDiode']) self.header['Monitor_corr']=float(imageData.header['Monitor']) except: self.transCorrCheckBox.setCheckState(Qt.Unchecked) print("No dark correction done") if self.transCorrCheckBox.isChecked(): if str(self.normComboBox.currentText())=='BSDiode': norm_factor=self.header['BSDiode_corr']#/float(self.header['count_time']) elif str(self.normComboBox.currentText())=='Monitor': norm_factor=self.header['Monitor_corr'] else: norm_factor=sum(imageData.data) else: norm_factor=1.0 if self.maskFile is not None: imageMask=fb.open(self.maskFile).data else: imageMask=None print(self.maskFile) # QApplication.processEvents() #print(self.azimuthRange) self.q,self.I,self.Ierr=self.ai.integrate1d(imageData.data,self.npt,error_model='poisson',mask=imageMask,dark=imageDark,unit='q_A^-1',normalization_factor=norm_factor,azimuth_range=self.azimuthRange) self.plotWidget.add_data(self.q,self.I,yerr=self.Ierr,name='Reduced data') self.plotWidget.setTitle(self.dataFile,fontsize=2) # self.progressBar.setRange(0,100) # self.progressBar.setValue(100) # self.statusLabel.setText('Idle') # QApplication.processEvents() self.saveData() self.tabWidget.setCurrentWidget(self.plotWidget) else: QMessageBox.warning(self,'Calibration File Error','Data reduction failed because either no calibration file provided or the provided file or path do not exists',QMessageBox.Ok) else: QMessageBox.warning(self,'Data File Error','No data file provided', QMessageBox.Ok) def reduce_multiple(self): """ Reduce multiple files """ #try: i=0 self.progressBar.setRange(0,len(self.dataFiles)) self.progressBar.setValue(i) self.statusLabel.setText('Busy') for file in self.dataFiles: self.dataFile=file QApplication.processEvents() self.reduceData() i=i+1 self.progressBar.setValue(i) QApplication.processEvents() self.statusLabel.setText('Idle') #except: # QMessageBox.warning(self,'File error','No data files to reduce',QMessageBox.Ok) def saveData(self): """ saves the extracted data into a file """ if not os.path.exists(self.extractedFolder): os.makedirs(self.extractedFolder) filename=os.path.join(self.extractedFolder,os.path.splitext(os.path.basename(self.dataFile))[0]+'.txt') headers='File extracted on '+time.asctime()+'\n' headers='Files used for extraction are:\n' headers+='Data file: '+self.dataFile+'\n' if self.darkFile is not None: headers+='Dark file: '+self.darkFile+'\n' else: headers+='Dark file: None\n' headers+='Poni file: '+self.poniFile+'\n' if self.maskFile is not None: headers+='mask file: '+self.maskFile+'\n' else: headers+='mask file: None\n' for key in self.header.keys(): headers+=key+'='+str(self.header[key])+'\n' headers+='Q (A^-1)\t\tIntensity\t\tIntensity_err' data=vstack((self.q,self.I,self.Ierr)).T savetxt(filename,data,header=headers,comments='#')
def create_UI(self): """ Creates the widget user interface """ row=0 col=0 dataFileLabel=QLabel('Data file') self.layout.addWidget(dataFileLabel,row,col) col+=1 self.dataFileLineEdit=QLineEdit(self.dataFile) self.layout.addWidget(self.dataFileLineEdit,row,col,1,2) col+=2 self.openDataPushButton=QPushButton('Select') self.openDataPushButton.clicked.connect(self.openDataFiles) self.layout.addWidget(self.openDataPushButton,row,col) col+=1 self.reducePushButton=QPushButton('Reduce data') self.reducePushButton.clicked.connect(self.reduce_multiple) self.layout.addWidget(self.reducePushButton,row,col,1,1) row+=1 col=0 darkFileLabel=QLabel('Dark file') self.layout.addWidget(darkFileLabel,row,col) col+=1 self.darkFileLineEdit=QLineEdit(self.darkFile) self.layout.addWidget(self.darkFileLineEdit,row,col,1,2) col+=2 self.openDarkPushButton=QPushButton('Select') self.openDarkPushButton.clicked.connect(self.openDarkFile) self.layout.addWidget(self.openDarkPushButton,row,col) col+=1 self.darkCheckBox=QCheckBox('Dark Correction') self.layout.addWidget(self.darkCheckBox,row,col) row+=1 col=0 poniFileLabel=QLabel('Calibration file') self.layout.addWidget(poniFileLabel,row,col) col+=1 self.poniFileLineEdit=QLineEdit(self.poniFile) self.layout.addWidget(self.poniFileLineEdit,row,col,1,2) col+=2 self.openPoniPushButton=QPushButton('Select') self.openPoniPushButton.clicked.connect(lambda x: self.openPoniFile(file=None)) self.layout.addWidget(self.openPoniPushButton,row,col) col+=1 self.calibratePushButton=QPushButton('Calibrate') self.calibratePushButton.clicked.connect(self.calibrate) self.layout.addWidget(self.calibratePushButton,row,col) row+=1 col=0 maskFileLabel=QLabel('Mask file') self.layout.addWidget(maskFileLabel,row,col) col+=1 self.maskFileLineEdit=QLineEdit(self.maskFile) self.maskFileLineEdit.returnPressed.connect(self.maskFileChanged) self.layout.addWidget(self.maskFileLineEdit,row,col,1,2) col+=2 self.openMaskPushButton=QPushButton('Select') self.openMaskPushButton.clicked.connect(lambda x: self.openMaskFile(file=None)) self.layout.addWidget(self.openMaskPushButton,row,col) col+=1 self.createMaskPushButton=QPushButton('Create mask') self.createMaskPushButton.clicked.connect(self.createMask) self.layout.addWidget(self.createMaskPushButton,row,col) row+=1 col=0 extractedFolderLabel=QLabel('Extracted folder') self.layout.addWidget(extractedFolderLabel,row,col) col+=1 self.extractedFolderLineEdit=QLineEdit() self.layout.addWidget(self.extractedFolderLineEdit,row,col,1,2) col+=2 self.extractedFolderPushButton=QPushButton('Select') self.extractedFolderPushButton.clicked.connect(self.openFolder) self.layout.addWidget(self.extractedFolderPushButton,row,col) row+=1 col=0 radialPointsLabel=QLabel('Radial Points') self.layout.addWidget(radialPointsLabel,row,col) col+=1 self.radialPointsLineEdit=QLineEdit(str(self.npt)) self.radialPointsLineEdit.returnPressed.connect(self.nptChanged) self.layout.addWidget(self.radialPointsLineEdit,row,col) col+=1 azimuthRangeLabel=QLabel('Azimuthal Range (min:max)') self.layout.addWidget(azimuthRangeLabel,row,col) col+=1 self.azimuthRangeLineEdit=QLineEdit('%.2f:%.2f'%(self.azimuthRange[0],self.azimuthRange[1])) self.azimuthRangeLineEdit.returnPressed.connect(self.azimuthRangeChanged) self.layout.addWidget(self.azimuthRangeLineEdit,row,col) col+=1 self.transCorrCheckBox=QCheckBox('Transmission Correction') self.transCorrCheckBox.setTristate(False) self.transCorrCheckBox.setChecked(self.transmission_corr) self.layout.addWidget(self.transCorrCheckBox) row+=1 col=0 progressLabel=QLabel('Status') self.layout.addWidget(progressLabel,row,col,1,1) col+=1 self.progressBar=QProgressBar() self.layout.addWidget(self.progressBar,row,col,1,1) col+=1 self.statusLabel=QLabel('Idle') self.layout.addWidget(self.statusLabel,row,col,1,1) col+=1 normLabel=QLabel('Normalized by') self.normComboBox=QComboBox() self.normComboBox.addItems(['BSDiode','Image sum','Monitor']) self.layout.addWidget(normLabel,row,col,1,1) col+=1 self.layout.addWidget(self.normComboBox,row,col,1,1) row+=1 col=0 self.tabWidget=QTabWidget(self) self.layout.addWidget(self.tabWidget,row,col,20,5) self.imageWidget=Image_Widget(zeros((100,100))) imgNumberLabel=QLabel('Image number') self.imgNumberSpinBox=QSpinBox() self.imgNumberSpinBox.setSingleStep(1) self.imageWidget.imageLayout.addWidget(imgNumberLabel,row=2,col=1) self.imageWidget.imageLayout.addWidget(self.imgNumberSpinBox,row=2,col=2) self.imageView=self.imageWidget.imageView.getView() self.plotWidget=PlotWidget() self.plotWidget.setXLabel('Q, Å<sup>-1</sup>',fontsize=5) self.plotWidget.setYLabel('Intensity',fontsize=5) self.tabWidget.addTab(self.plotWidget,'Reduced 1D-data') self.tabWidget.addTab(self.imageWidget,'Masked 2D-data')
def __init__(self, sensor): QtWidgets.QMainWindow.__init__(self) # super doesn't seem to work here self.setWindowTitle("MUGIC Plot") self.window_widget = QtWidgets.QWidget() self.main_layout = QtWidgets.QVBoxLayout() self.window_widget.setLayout(self.main_layout) self.setCentralWidget(self.window_widget) self.setMinimumSize(1500, 500) self.stream = sensor.stream # Create the plot widget to use as the central widget self.plot_widget = PlotWidget(sensor) self.main_layout.addWidget(self.plot_widget) # Create the control panel self.control_widget = QtWidgets.QWidget(self) self.control_layout = QtWidgets.QHBoxLayout() self.main_layout.addWidget(self.control_widget) self.control_widget.setLayout(self.control_layout) self.toggle_button = QtWidgets.QPushButton() self.toggle_button.setText("Start Recording") self.toggle_button.clicked.connect(self.toggle_recording) self.control_layout.addWidget(self.toggle_button) reset_button = QtWidgets.QPushButton() reset_button.setText("Reset") reset_button.clicked.connect(self.reset_recording) self.control_layout.addWidget(reset_button) export_button = QtWidgets.QPushButton() export_button.setText("Export") export_button.clicked.connect(self.export_csv) self.control_layout.addWidget(export_button) # Create the menu bar menu_bar = self.menuBar() file_menu = menu_bar.addMenu("File") run_menu = menu_bar.addMenu("Run") toggle_option = QtGui.QAction("Toggle recording", self) toggle_option.setShortcut("Ctrl+R") toggle_option.setStatusTip("Start/stop plotting data") toggle_option.triggered.connect(self.toggle_recording) run_menu.addAction(toggle_option) toggle_option = QtGui.QAction("Reset plots", self) toggle_option.setShortcut("Ctrl+Backspace") toggle_option.setStatusTip("Clear plotting data") toggle_option.triggered.connect(self.reset_recording) run_menu.addAction(toggle_option) export_option = QtGui.QAction("Export data...", self) export_option.setShortcut("Ctrl+S") export_option.setStatusTip("Export accumulated raw and processed data") export_option.triggered.connect(self.export_csv) file_menu.addAction(export_option) # Create the output console self.console = QtGui.QTextEdit() self.console.moveCursor(QtGui.QTextCursor.Start) self.console.ensureCursorVisible() self.main_layout.addWidget(self.console) # Hook up stdout to the console sys.stdout = TextStream() sys.stdout.signal.connect(self.update_text) # Start the plot loop self.timer = QtCore.QTimer() self.timer.timeout.connect(self.plot_widget.update) self.timer.start(10)
class XAnoS_Reducer(QWidget): """ This widget is developed to reduce on the fly 2D SAXS data to azimuthally averaged 1D SAXS data """ def __init__(self,poniFile=None,dataFile=None, darkFile=None, maskFile=None,extractedFolder='/tmp', npt=1000, azimuthalRange=(-180.0,180.0), parent=None): """ poniFile is the calibration file obtained after Q-calibration """ QWidget.__init__(self,parent) self.setup_dict=json.load(open('./SetupData/reducer_setup.txt','r')) if poniFile is not None: self.poniFile=poniFile else: self.poniFile=self.setup_dict['poniFile'] if maskFile is not None: self.maskFile=maskFile else: self.maskFile=self.setup_dict['maskFile'] self.dataFile=dataFile if darkFile is None: self.dark_corrected=False self.darkFile='' else: self.darkFile=darkFile self.dark_corrected=True self.curDir=os.getcwd() self.extractedBaseFolder=extractedFolder self.npt=npt self.set_externally=False #ai=AIWidget() #self.layout.addWidget(ai) self.azimuthalRange=azimuthalRange self.create_UI() if os.path.exists(self.poniFile): self.openPoniFile(file=self.poniFile) if os.path.exists(self.maskFile): self.openMaskFile(file=self.maskFile) self.clientRunning=False def create_UI(self): """ Creates the widget user interface """ loadUi('UI_Forms/Data_Reduction_Client.ui',self) self.poniFileLineEdit.setText(str(self.poniFile)) self.maskFileLineEdit.setText(str(self.maskFile)) self.darkFileLineEdit.setText(str(self.darkFile)) self.extractedBaseFolderLineEdit.setText(self.extractedBaseFolder) self.radialPointsLineEdit.setText(str(self.npt)) self.openDataPushButton.clicked.connect(self.openDataFiles) self.reducePushButton.clicked.connect(self.reduce_multiple) self.openDarkPushButton.clicked.connect(self.openDarkFile) self.openPoniPushButton.clicked.connect(lambda x: self.openPoniFile(file=None)) self.calibratePushButton.clicked.connect(self.calibrate) self.maskFileLineEdit.returnPressed.connect(self.maskFileChanged) self.openMaskPushButton.clicked.connect(lambda x: self.openMaskFile(file=None)) self.createMaskPushButton.clicked.connect(self.createMask) self.extractedFolderPushButton.clicked.connect(self.openFolder) self.extractedFolderLineEdit.textChanged.connect(self.extractedFolderChanged) self.polCorrComboBox.currentIndexChanged.connect(self.polarizationChanged) self.polarizationChanged() self.radialPointsLineEdit.returnPressed.connect(self.nptChanged) self.azimuthalRangeLineEdit.returnPressed.connect(self.azimuthalRangeChanged) self.azimuthalRangeChanged() #self.statusLabel.setStyleSheet("color:rgba(0,1,0,0)") self.imageWidget=Image_Widget(zeros((100,100))) self.cakedImageWidget=Image_Widget(zeros((100,100))) imgNumberLabel=QLabel('Image number') self.imgNumberSpinBox=QSpinBox() self.imgNumberSpinBox.setSingleStep(1) self.imageWidget.imageLayout.addWidget(imgNumberLabel,row=2,col=1) self.imageWidget.imageLayout.addWidget(self.imgNumberSpinBox,row=2,col=2) self.imageView=self.imageWidget.imageView.getView() self.plotWidget=PlotWidget() self.plotWidget.setXLabel('Q, Å<sup>-1</sup>',fontsize=5) self.plotWidget.setYLabel('Intensity',fontsize=5) self.tabWidget.addTab(self.plotWidget,'Reduced 1D-data') self.tabWidget.addTab(self.imageWidget,'Masked 2D-data') self.tabWidget.addTab(self.cakedImageWidget,'Reduced Caked Data') self.serverAddress=self.serverAddressLineEdit.text() self.startClientPushButton.clicked.connect(self.startClient) self.stopClientPushButton.clicked.connect(self.stopClient) self.serverAddressLineEdit.returnPressed.connect(self.serverAddressChanged) self.startServerPushButton.clicked.connect(self.startServer) self.stopServerPushButton.clicked.connect(self.stopServer) def startServer(self): serverAddr=self.serverAddressLineEdit.text() dataDir=QFileDialog.getExistingDirectory(self,'Select data folder',options=QFileDialog.ShowDirsOnly) self.serverStatusLabel.setText('<font color="Red">Transmitting</font>') QApplication.processEvents() self.serverThread=QThread() self.zeromq_server=ZeroMQ_Server(serverAddr,dataDir) self.zeromq_server.moveToThread(self.serverThread) self.serverThread.started.connect(self.zeromq_server.loop) self.zeromq_server.messageEmitted.connect(self.updateServerMessage) self.zeromq_server.folderFinished.connect(self.serverDone) QTimer.singleShot(0,self.serverThread.start) def updateServerMessage(self,mesg): #self.serverStatusLabel.setText('<font color="Red">Transmitting</font>') self.serverMessageLabel.setText('Server sends: %s'%mesg) QApplication.processEvents() def serverDone(self): self.serverStatusLabel.setText('<font color="Green">Idle</font>') self.zeromq_server.socket.unbind(self.zeromq_server.socket.last_endpoint) self.serverThread.quit() self.serverThread.wait() self.serverThread.deleteLater() self.zeromq_server.deleteLater() def stopServer(self): try: self.zeromq_server.running=False self.serverStatusLabel.setText('<font color="Green">Idle</font>') self.zeromq_server.socket.unbind(self.zeromq_server.socket.last_endpoint) self.serverThread.quit() self.serverThread.wait() self.serverThread.deleteLater() self.zeromq_server.deleteLater() except: QMessageBox.warning(self,'Server Error','Start the server before stopping it') def enableClient(self,enable=True): self.startClientPushButton.setEnabled(enable) self.stopClientPushButton.setEnabled(enable) def enableServer(self,enable=True): self.startServerPushButton.setEnabled(enable) self.stopServerPushButton.setEnabled(enable) def startClient(self): if self.clientRunning: self.stopClient() else: self.clientFree=True self.clientRunning=True self.files=[] self.listenerThread = QThread() addr=self.clientAddressLineEdit.text() self.zeromq_listener = ZeroMQ_Listener(addr) self.zeromq_listener.moveToThread(self.listenerThread) self.listenerThread.started.connect(self.zeromq_listener.loop) self.zeromq_listener.messageReceived.connect(self.signal_received) QTimer.singleShot(0, self.listenerThread.start) QTimer.singleShot(0,self.clientReduce) self.clientStatusLabel.setText('<font color="red">Connected</font>') def stopClient(self): try: self.clientRunning=False self.clientFree=False self.zeromq_listener.messageReceived.disconnect() self.zeromq_listener.running=False self.listenerThread.quit() self.listenerThread.wait() self.listenerThread.deleteLater() self.zeromq_listener.deleteLater() self.clientStatusLabel.setText('<font color="green">Idle</font>') except: QMessageBox.warning(self,'Client Error', 'Please start the client first before closing.',QMessageBox.Ok) def serverAddressChanged(self): if self.clientRunning: self.startClient() def signal_received(self, message): self.clientMessageLabel.setText('Client receives: %s'%message) if 'dark.edf' not in message: self.files.append(message) def clientReduce(self): while self.clientFree: QApplication.processEvents() if len(self.files)>0: message=self.files[0] self.dataFiles=[message] self.dataFileLineEdit.setText(str(self.dataFiles)) self.extractedBaseFolder=os.path.dirname(message) self.extractedFolder=os.path.join(self.extractedBaseFolder,self.extractedFolderLineEdit.text()) if not os.path.exists(self.extractedFolder): os.makedirs(self.extractedFolder) self.extractedBaseFolderLineEdit.setText(self.extractedBaseFolder) self.set_externally=True self.reduce_multiple() self.set_externally=False self.files.pop(0) def closeEvent(self, event): if self.clientRunning: self.stopClient() event.accept() def polarizationChanged(self): if self.polCorrComboBox.currentText()=='Horizontal': self.polarization_factor=1 elif self.polCorrComboBox.currentText()=='Vertical': self.polarization_factor=-1 elif self.polCorrComboBox.currentText()=='Circular': self.polarization_factor=0 else: self.polarization_factor=None def createMask(self): """ Opens a mask-widget to create mask file """ fname=str(QFileDialog.getOpenFileName(self,'Select an image file', directory=self.curDir,filter='Image file (*.edf *.tif)')[0]) if fname is not None or fname!='': img=fb.open(fname).data self.maskWidget=MaskWidget(img) self.maskWidget.saveMaskPushButton.clicked.disconnect() self.maskWidget.saveMaskPushButton.clicked.connect(self.save_mask) self.maskWidget.show() else: QMessageBox.warning(self,'File error','Please import a data file first for creating the mask',QMessageBox.Ok) def maskFileChanged(self): """ Changes the mask file """ maskFile=str(self.maskFileLineEdit.text()) if str(maskFile)=='': self.maskFile=None elif os.path.exists(maskFile): self.maskFile=maskFile else: self.maskFile=None def save_mask(self): """ Saves the entire mask combining all the shape ROIs """ fname=str(QFileDialog.getSaveFileName(filter='Mask Files (*.msk)')[0]) name,extn=os.path.splitext(fname) if extn=='': fname=name+'.msk' elif extn!='.msk': QMessageBox.warning(self,'File extension error','Please donot provide file extension other than ".msk". Thank you!') return else: tmpfile=fb.edfimage.EdfImage(data=self.maskWidget.full_mask_data.T,header=None) tmpfile.save(fname) self.maskFile=fname self.maskFileLineEdit.setText(self.maskFile) def calibrate(self): """ Opens a calibartion widget to create calibration file """ fname=str(QFileDialog.getOpenFileName(self,'Select calibration image',directory=self.curDir, filter='Calibration image (*.edf *.tif)')[0]) if fname is not None: img=fb.open(fname).data if self.maskFile is not None: try: mask=fb.open(self.maskFile).data except: QMessageBox.warning(self,'Mask File Error','Cannot open %s.\n No masking will be done.'%self.maskFile) mask=None else: mask=None pixel1=79.0 pixel2=79.0 self.calWidget=CalibrationWidget(img,pixel1,pixel2,mask=mask) self.calWidget.saveCalibrationPushButton.clicked.disconnect() self.calWidget.saveCalibrationPushButton.clicked.connect(self.save_calibration) self.calWidget.show() else: QMessageBox.warning(self,'File error','Please import a data file first for creating the calibration file',QMessageBox.Ok) def save_calibration(self): fname=str(QFileDialog.getSaveFileName(self,'Calibration file',directory=self.curDir,filter='Clibration files (*.poni)')[0]) tfname=os.path.splitext(fname)[0]+'.poni' self.calWidget.applyPyFAI() self.calWidget.geo.save(tfname) self.poniFile=tfname self.poniFileLineEdit.setText(self.poniFile) self.openPoniFile(file=self.poniFile) def openPoniFile(self,file=None): """ Select and imports the calibration file """ if file is None: self.poniFile=QFileDialog.getOpenFileName(self,'Select calibration file',directory=self.curDir,filter='Calibration file (*.poni)')[0] self.poniFileLineEdit.setText(self.poniFile) else: self.poniFile=file if os.path.exists(self.poniFile): self.setup_dict['poniFile']=self.poniFile json.dump(self.setup_dict,open('./SetupData/reducer_setup.txt','w')) fh=open(self.poniFile,'r') lines=fh.readlines() self.calib_data={} for line in lines: if line[0]!='#': key,val=line.split(': ') self.calib_data[key]=float(val) self.dist=self.calib_data['Distance'] self.pixel1=self.calib_data['PixelSize1'] self.pixel2=self.calib_data['PixelSize2'] self.poni1=self.calib_data['Poni1'] self.poni2=self.calib_data['Poni2'] self.rot1=self.calib_data['Rot1'] self.rot2=self.calib_data['Rot2'] self.rot3=self.calib_data['Rot3'] self.wavelength=self.calib_data['Wavelength'] self.ai=AzimuthalIntegrator(dist=self.dist,poni1=self.poni1,poni2=self.poni2,pixel1=self.pixel1,pixel2=self.pixel2,rot1=self.rot1,rot2=self.rot2,rot3=self.rot3,wavelength=self.wavelength) #pos=[self.poni2/self.pixel2,self.poni1/self.pixel1] #self.roi=cake(pos,movable=False) #self.roi.sigRegionChangeStarted.connect(self.endAngleChanged) #self.imageView.addItem(self.roi) else: QMessageBox.warning(self,'File error','The calibration file '+self.poniFile+' doesnot exists.',QMessageBox.Ok) def endAngleChanged(self,evt): print(evt.pos()) def nptChanged(self): """ Changes the number of radial points """ try: self.npt=int(self.radialPointsLineEdit.text()) except: QMessageBox.warning(self,'Value error', 'Please input positive integers only.',QMessageBox.Ok) def azimuthalRangeChanged(self): """ Changes the azimuth angular range """ try: self.azimuthalRange=tuple(map(float, self.azimuthalRangeLineEdit.text().split(':'))) except: QMessageBox.warning(self,'Value error','Please input min:max angles in floating point numbers',QMessageBox.Ok) def openDataFile(self): """ Select and imports one data file """ dataFile=QFileDialog.getOpenFileName(self,'Select data file',directory=self.curDir,filter='Data file (*.edf *.tif)')[0] if dataFile!='': self.dataFile=dataFile self.curDir=os.path.dirname(self.dataFile) self.dataFileLineEdit.setText(self.dataFile) self.data2d=fb.open(self.dataFile).data if self.darkFile is not None: self.applyDark() if self.maskFile is not None: self.applyMask() self.imageWidget.setImage(self.data2d,transpose=True) self.tabWidget.setCurrentWidget(self.imageWidget) if not self.set_externally: self.extractedFolder=os.path.join(self.curDir,self.extractedFolderLineEdit.text()) if not os.path.exists(self.extractedFolder): os.makedirs(self.extractedFolder) def openDataFiles(self): """ Selects and imports multiple data files """ self.dataFiles=QFileDialog.getOpenFileNames(self,'Select data files', directory=self.curDir,filter='Data files (*.edf *.tif)')[0] if len(self.dataFiles)!=0: self.imgNumberSpinBox.valueChanged.connect(self.imageChanged) self.imgNumberSpinBox.setMinimum(0) self.imgNumberSpinBox.setMaximum(len(self.dataFiles)-1) self.dataFileLineEdit.setText(str(self.dataFiles)) self.curDir=os.path.dirname(self.dataFiles[0]) self.extractedBaseFolder=self.curDir self.extractedFolder=os.path.abspath(os.path.join(self.extractedBaseFolder,self.extractedFolderLineEdit.text())) if not os.path.exists(self.extractedFolder): os.makedirs(self.extractedFolder) self.extractedBaseFolderLineEdit.setText(self.extractedBaseFolder) self.imgNumberSpinBox.setValue(0) self.imageChanged() def imageChanged(self): self.data2d=fb.open(self.dataFiles[self.imgNumberSpinBox.value()]).data if self.darkFile is not None: self.applyDark() if self.maskFile is not None: self.applyMask() self.imageWidget.setImage(self.data2d,transpose=True) def applyDark(self): if not self.dark_corrected and self.darkFile!='': self.dark2d=fb.open(self.darkFile).data self.data2d=self.data2d-self.dark2d self.dark_corrected=True def applyMask(self): self.mask2d=fb.open(self.maskFile).data self.data2d=self.data2d*(1+self.mask2d)/2.0 self.mask_applied=True def openDarkFile(self): """ Select and imports the dark file """ self.darkFile=QFileDialog.getOpenFileName(self,'Select dark file',directory=self.curDir,filter='Dark file (*.edf)')[0] if self.darkFile!='': self.dark_corrected=False self.darkFileLineEdit.setText(self.darkFile) if self.dataFile is not None: self.data2d=fb.open(self.dataFile).data self.applyDark() def openMaskFile(self,file=None): """ Select and imports the Mask file """ if file is None: self.maskFile=QFileDialog.getOpenFileName(self,'Select mask file',directory=self.curDir,filter='Mask file (*.msk)')[0] else: self.maskFile=file if self.maskFile!='': self.mask_applied=False if os.path.exists(self.maskFile): self.curDir=os.path.dirname(self.maskFile) self.maskFileLineEdit.setText(self.maskFile) self.setup_dict['maskFile']=self.maskFile self.setup_dict['poniFile']=self.poniFile json.dump(self.setup_dict,open('./SetupData/reducer_setup.txt','w')) else: self.openMaskFile(file=None) if self.dataFile is not None: self.applyMask() else: self.maskFile=None self.maskFileLineEdit.clear() def openFolder(self): """ Select the folder to save the reduce data """ oldfolder=self.extractedBaseFolder.text() folder=QFileDialog.getExistingDirectory(self,'Select extracted directory',directory=self.curDir) if folder!='': self.extractedBaseFolder=folder self.extractedBaseFolderLineEdit.setText(folder) self.extractedFolder=os.path.join(folder,self.extractedFolderLineEdit.text()) self.set_externally=True else: self.extractedBaseFolder=oldfolder self.extractedBaseFolderLineEdit.setText(oldfolder) self.extractedFolder = os.path.join(oldfolder, self.extractedFolderLineEdit.text()) self.set_externally = True def extractedFolderChanged(self,txt): self.extractedFolder=os.path.join(self.extractedBaseFolder,txt) self.set_externally=True def reduceData(self): """ Reduces the 2d data to 1d data """ if (self.dataFile is not None) and (os.path.exists(self.dataFile)): if (self.poniFile is not None) and (os.path.exists(self.poniFile)): # self.statusLabel.setText('Busy') # self.progressBar.setRange(0, 0) imageData=fb.open(self.dataFile) #self.data2d=imageData.data #if self.maskFile is not None: # self.applyMask() #self.imageWidget.setImage(self.data2d,transpose=True) #self.tabWidget.setCurrentWidget(self.imageWidget) self.header=imageData.header try: self.ai.set_wavelength(float(self.header['Wavelength'])*1e-10) except: self.ai.set_wavelength(self.wavelength) #print(self.darkFile) if os.path.exists(self.dataFile.split('.')[0]+'_dark.edf') and self.darkCheckBox.isChecked(): self.darkFile=self.dataFile.split('.')[0]+'_dark.edf' dark=fb.open(self.darkFile) self.darkFileLineEdit.setText(self.darkFile) imageDark=dark.data self.header['BSDiode_corr']=max([1.0,(float(imageData.header['BSDiode'])-float(dark.header['BSDiode']))]) self.header['Monitor_corr']=max([1.0,(float(imageData.header['Monitor'])-float(dark.header['Monitor']))]) print("Dark File read from existing dark files") elif self.darkFile is not None and self.darkFile!='' and self.darkCheckBox.isChecked(): dark=fb.open(self.darkFile) imageDark=dark.data self.header['BSDiode_corr']=max([1.0,(float(imageData.header['BSDiode'])-float(dark.header['BSDiode']))]) self.header['Monitor_corr']=max([1.0,(float(imageData.header['Monitor'])-float(dark.header['Monitor']))]) print("Dark File from memory subtracted") else: imageDark=None try: self.header['BSDiode_corr']=float(imageData.header['BSDiode']) self.header['Monitor_corr']=float(imageData.header['Monitor']) self.header['Transmission'] = float(imageData.header['Transmission']) except: self.normComboBox.setCurrentText('None') print("No dark correction done") if str(self.normComboBox.currentText())=='BSDiode': norm_factor=self.header['BSDiode_corr']#/self.header['Monitor_corr']#float(self.header[ # 'count_time']) elif str(self.normComboBox.currentText())=='TransDiode': norm_factor=self.header['Transmission']*self.header['Monitor_corr'] elif str(self.normComboBox.currentText())=='Monitor': norm_factor=self.header['Monitor_corr'] elif str(self.normComboBox.currentText())=='Image Sum': norm_factor=sum(imageData.data) else: norm_factor=1.0 if self.maskFile is not None: imageMask=fb.open(self.maskFile).data else: imageMask=None # QApplication.processEvents() #print(self.azimuthalRange) self.q,self.I,self.Ierr=self.ai.integrate1d(imageData.data,self.npt,error_model='poisson',mask=imageMask,dark=imageDark,unit='q_A^-1',normalization_factor=norm_factor,azimuth_range=self.azimuthalRange,polarization_factor=self.polarization_factor) self.plotWidget.add_data(self.q,self.I,yerr=self.Ierr,name='Reduced data') if not self.set_externally: cakedI,qr,phir=self.ai.integrate2d(imageData.data,self.npt,mask=imageMask,dark=imageDark,unit='q_A^-1',normalization_factor=norm_factor,polarization_factor=self.polarization_factor) self.cakedImageWidget.setImage(cakedI,xmin=qr[0],xmax=qr[-1],ymin=phir[0],ymax=phir[-1],transpose=True,xlabel='Q ', ylabel='phi ',unit=['Å<sup>-1</sup>','degree']) self.cakedImageWidget.imageView.view.setAspectLocked(False) try: self.azimuthalRegion.setRegion(self.azimuthalRange) except: self.azimuthalRegion=pg.LinearRegionItem(values=self.azimuthalRange,orientation=pg.LinearRegionItem.Horizontal,movable=True,bounds=[-180,180]) self.cakedImageWidget.imageView.getView().addItem(self.azimuthalRegion) self.azimuthalRegion.sigRegionChanged.connect(self.azimuthalRegionChanged) self.plotWidget.setTitle(self.dataFile,fontsize=3) # self.progressBar.setRange(0,100) # self.progressBar.setValue(100) # self.statusLabel.setText('Idle') # QApplication.processEvents() self.saveData() #self.tabWidget.setCurrentWidget(self.plotWidget) else: QMessageBox.warning(self,'Calibration File Error','Data reduction failed because either no calibration file provided or the provided file or path do not exists',QMessageBox.Ok) else: QMessageBox.warning(self,'Data File Error','No data file provided', QMessageBox.Ok) def azimuthalRegionChanged(self): minp,maxp=self.azimuthalRegion.getRegion() self.azimuthalRangeLineEdit.setText('%.1f:%.1f'%(minp,maxp)) self.azimuthalRange=[minp,maxp] self.set_externally=True def reduce_multiple(self): """ Reduce multiple files """ try: i=0 self.progressBar.setRange(0,len(self.dataFiles)) self.progressBar.setValue(i) self.statusLabel.setText('<font color="red">Busy</font>') for file in self.dataFiles: self.dataFile=file QApplication.processEvents() self.reduceData() i=i+1 self.progressBar.setValue(i) QApplication.processEvents() self.statusLabel.setText('<font color="green">Idle</font>') self.progressBar.setValue(0) except: QMessageBox.warning(self,'File error','No data files to reduce',QMessageBox.Ok) def saveData(self): """ saves the extracted data into a file """ if not os.path.exists(self.extractedFolder): os.makedirs(self.extractedFolder) filename=os.path.join(self.extractedFolder,os.path.splitext(os.path.basename(self.dataFile))[0]+'.txt') headers='File extracted on '+time.asctime()+'\n' headers='Files used for extraction are:\n' headers+='Data file: '+self.dataFile+'\n' if self.darkFile is not None: headers+='Dark file: '+self.darkFile+'\n' else: headers+='Dark file: None\n' headers+='Poni file: '+self.poniFile+'\n' if self.maskFile is not None: headers+='mask file: '+self.maskFile+'\n' else: headers+='mask file: None\n' for key in self.header.keys(): headers+=key+'='+str(self.header[key])+'\n' headers+="col_names=['Q (inv Angs)','Int','Int_err']\n" headers+='Q (inv Angs)\tInt\tInt_err' data=vstack((self.q,self.I,self.Ierr)).T savetxt(filename,data,header=headers,comments='#')
class View(wx.Frame): def __init__(self): self.app = wx.App(False) wx.Frame.__init__(self, None, title="Nocturnal hypoglycemia prediction", size=(1100, 800)) panel = wx.Panel(self) menu = wx.Menu() about = menu.Append(wx.ID_ABOUT, "&About", "Information about this program") self.Bind(wx.EVT_MENU, lambda x: self.OnAbout(), about) menuBar = wx.MenuBar() menuBar.Append(menu, "&Help") self.SetMenuBar(menuBar) label = wx.StaticText(panel, label="Train dataset path:", pos=(10, 10)) self.m_train_dataset_path_edit = wx.TextCtrl(panel, pos=(10, 30), size=(800, 20)) self.m_train_dataset_path_edit.SetValue(u"D:\GDrive\Диплом 2\DataPreparation\output1\\fixed_dataset+_train.xlsx") label = wx.StaticText(panel, label="Test dataset path:", pos=(10, 60)) self.m_test_dataset_path_edit = wx.TextCtrl(panel, pos=(10, 80), size=(800, 20)) self.m_test_dataset_path_edit.SetValue(u"D:\GDrive\Диплом 2\DataPreparation\output1\\fixed_dataset+_validate_known.xlsx") label = wx.StaticText(panel, label="Choose method:", pos=(10, 110)) self.m_predictor_combobox = wx.ComboBox(panel, pos=(10, 130), size=wx.DefaultSize, choices=['stub RNN', 'stub RNN+demographic'], style=wx.CB_READONLY) self.m_test_button = wx.Button(panel, label="Test", pos=(10, 160), size=wx.DefaultSize) self.m_train_button = wx.Button(panel, label="Train", pos=(110, 160), size=wx.DefaultSize) label = wx.StaticText(panel, label="Prediction log:", pos=(10, 200)) self.m_log = wx.TextCtrl(panel, pos=(10, 220), size=(360, 480), style=wx.TE_MULTILINE | wx.CB_READONLY) self.plot = PlotWidget(panel, pos=(400, 220), size=(10, 20)) def OnAbout(self): dlg = View.AboutBox() dlg.ShowModal() dlg.Destroy() # Custom bindings def SetOnTestAction(self, on_test_action): self.Bind(wx.EVT_BUTTON, lambda x: on_test_action(), self.m_test_button) def SetOnTrainAction(self, on_train_action): self.Bind(wx.EVT_BUTTON, lambda x: on_train_action(), self.m_train_button) # Custom functions def UpdateMethodList(self, i_method_list): self.m_predictor_combobox.Clear() for method in i_method_list: self.m_predictor_combobox.Append(method) self.m_predictor_combobox.SetSize((200, -1)) def GetSelectedMethodName(self): return self.m_predictor_combobox.GetValue() def GetTrainDataPath(self): return self.m_train_dataset_path_edit.GetValue() def GetTestDataPath(self): return self.m_test_dataset_path_edit.GetValue() def PrintToLog(self, i_text): self.m_log.AppendText('[' + datetime.now().strftime('%Y-%m-%d %H:%M:%S') + '] ' + i_text + '\n') def PlotGraph(self, x_arr, y_arr, col): self.plot.draw(x_arr, y_arr, col) def ClearGraph(self): self.plot.clear() class AboutBox(wx.Dialog): aboutText = "\nThis application is a part of Master's Thesis \"Prediction of nocturnal hypoglycemia in patients with typr 1 diabetes using mrthods based on decision tree and methods based on neural networks\"\n" \ "\nAuthors: Dmytro Yurchenko and Serhii Sakharov\n" \ "\nKyiv Polytechnic Institute, Department of Applied Math, 2016" def __init__(self): wx.Dialog.__init__(self, None, -1, "About Nocturnal hypoglycemia prediction", style=wx.DEFAULT_DIALOG_STYLE|wx.THICK_FRAME|wx.RESIZE_BORDER|wx.TAB_TRAVERSAL) hwin = wx.StaticText(self, label=View.AboutBox.aboutText, size=(400,200)) self.CentreOnParent(wx.BOTH) self.SetFocus() # Run (all settings must be done before this function run) def Run(self): self.Show(True) self.app.MainLoop()
def _buildUI(self): self.setWindowTitle("MOOI: Multi-Objective Optimization Interface") self.resize(840, 480) self.statusBar().setSizeGripEnabled(False) self.statusBar().showMessage("Loading initial data...") # Plot widget self.plot = PlotWidget() self.plot.setMinimumSize(320, 480) self.plot.setAlignment(Qt.AlignCenter) self.plot.setContextMenuPolicy(Qt.ActionsContextMenu) self.setCentralWidget(self.plot) # Function widget self.functionWidget = QListWidget() self.functionWidget.itemSelectionChanged.connect(self.solutionSelected) rightDock = QDockWidget("Functions", self) rightDock.setObjectName("Functions") rightDock.setWidget(self.functionWidget) rightDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.addDockWidget(Qt.RightDockWidgetArea, rightDock) # Control widget self.showSolutionsRadio = QRadioButton("Functions") self.showSolutionsRadio.setChecked(True) self.showSolutionsRadio.toggled.connect(self._showSolution) self.showVariablesRadio = QRadioButton("Variables") radioWidget = QWidget() radioLayout = QHBoxLayout() radioLayout.addWidget(self.showSolutionsRadio) radioLayout.addWidget(self.showVariablesRadio) radioWidget.setLayout(radioLayout) self.generationLabel = QLabel("Run: 1") self.generationSlider = QSlider(Qt.Horizontal) self.generationSlider.setTickPosition(QSlider.TicksBothSides) self.generationSlider.setTracking(True) self.generationSlider.setMinimum(1) self.generationSlider.setMaximum(1) self.generationSlider.setTickInterval(1) self.generationSlider.valueChanged.connect(self._showSolution) self.solutionSelector = QWidget() self.solutionSelector.setLayout(QVBoxLayout()) addSolutionButton = QPushButton("Add") addSolutionButton.clicked.connect(self.addImplementation) removeSolutionButton = QPushButton("Remove unselected") removeSolutionButton.clicked.connect(self.removeResult) solutionSelectorButtons = QWidget() solutionSelectorButtons.setLayout(QHBoxLayout()) solutionSelectorButtons.layout().addWidget(addSolutionButton) solutionSelectorButtons.layout().addWidget(removeSolutionButton) self.solutionSelectorWidget = QWidget() self.solutionSelectorWidget.setLayout(QVBoxLayout()) self.solutionSelectorWidget.layout().addWidget(solutionSelectorButtons) self.solutionSelectorWidget.layout().addWidget(self.solutionSelector) exportButton = QPushButton("Export image") exportButton.clicked.connect(self.exportImage) exportAllButton = QPushButton("Export all images") exportAllButton.clicked.connect(self.exportAllImages) computeMetricsButton = QPushButton("Compute metrics") computeMetricsButton.clicked.connect(self.computeMetricsAsync) refreshButton = QPushButton("Refresh") refreshButton.clicked.connect(self.updateUI) controlLayout = QVBoxLayout() controlLayout.addWidget(radioWidget) controlLayout.addWidget(self.generationLabel) controlLayout.addWidget(self.generationSlider) controlLayout.addWidget(self.solutionSelectorWidget) controlLayout.addStretch() controlLayout.addWidget(computeMetricsButton) controlLayout.addWidget(refreshButton) controlLayout.addWidget(exportButton) controlLayout.addWidget(exportAllButton) controlWidget = QWidget() controlWidget.setLayout(controlLayout) leftDock = QDockWidget("Control", self) leftDock.setObjectName("Control") leftDock.setWidget(controlWidget) leftDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.addDockWidget(Qt.LeftDockWidgetArea, leftDock) # Metric widget self.metrics = MetricsPanel(self.analyzer) bottomDock = QDockWidget("Metrics", self) bottomDock.setObjectName("Metrics") bottomDock.setWidget(self.metrics) bottomDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.addDockWidget(Qt.BottomDockWidgetArea, bottomDock) # Actions exitAction = QAction("&Exit", self) exitAction.setShortcut("Ctrl+Q") exitAction.setStatusTip("Exit application") exitAction.triggered.connect(qApp.quit) copyAction = QAction("&Copy", self) copyAction.setShortcut("Ctrl+C") copyAction.setStatusTip("Copy metrics") copyAction.triggered.connect(self.metrics.copyMetrics) aboutAction = QAction("&About", self) aboutAction.setStatusTip("About MOOI") aboutAction.triggered.connect(self.helpAbout) # Menus menubar = self.menuBar() fileMenu = menubar.addMenu("&File") fileMenu.addAction(copyAction) fileMenu.addAction(aboutAction) fileMenu.addSeparator() fileMenu.addAction(exitAction)
class MainWindow(QMainWindow): __PREF_GEOM__ = "UI/Geometry" __PREF_STATE__ = "UI/State" __PREF_DIR__ = "Config/Directories" __PREF_SAVE__ = "Config/SaveDirectory" __PREF_SAVE_ALL__ = "Config/SaveAllDirectory" def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.analyzer = Analyzer() self.currentSolution = None self._buildUI() self._loadSettings() QTimer.singleShot(0, self._loadInitialData) def _buildUI(self): self.setWindowTitle("MOOI: Multi-Objective Optimization Interface") self.resize(840, 480) self.statusBar().setSizeGripEnabled(False) self.statusBar().showMessage("Loading initial data...") # Plot widget self.plot = PlotWidget() self.plot.setMinimumSize(320, 480) self.plot.setAlignment(Qt.AlignCenter) self.plot.setContextMenuPolicy(Qt.ActionsContextMenu) self.setCentralWidget(self.plot) # Function widget self.functionWidget = QListWidget() self.functionWidget.itemSelectionChanged.connect(self.solutionSelected) rightDock = QDockWidget("Functions", self) rightDock.setObjectName("Functions") rightDock.setWidget(self.functionWidget) rightDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.addDockWidget(Qt.RightDockWidgetArea, rightDock) # Control widget self.showSolutionsRadio = QRadioButton("Functions") self.showSolutionsRadio.setChecked(True) self.showSolutionsRadio.toggled.connect(self._showSolution) self.showVariablesRadio = QRadioButton("Variables") radioWidget = QWidget() radioLayout = QHBoxLayout() radioLayout.addWidget(self.showSolutionsRadio) radioLayout.addWidget(self.showVariablesRadio) radioWidget.setLayout(radioLayout) self.generationLabel = QLabel("Run: 1") self.generationSlider = QSlider(Qt.Horizontal) self.generationSlider.setTickPosition(QSlider.TicksBothSides) self.generationSlider.setTracking(True) self.generationSlider.setMinimum(1) self.generationSlider.setMaximum(1) self.generationSlider.setTickInterval(1) self.generationSlider.valueChanged.connect(self._showSolution) self.solutionSelector = QWidget() self.solutionSelector.setLayout(QVBoxLayout()) addSolutionButton = QPushButton("Add") addSolutionButton.clicked.connect(self.addImplementation) removeSolutionButton = QPushButton("Remove unselected") removeSolutionButton.clicked.connect(self.removeResult) solutionSelectorButtons = QWidget() solutionSelectorButtons.setLayout(QHBoxLayout()) solutionSelectorButtons.layout().addWidget(addSolutionButton) solutionSelectorButtons.layout().addWidget(removeSolutionButton) self.solutionSelectorWidget = QWidget() self.solutionSelectorWidget.setLayout(QVBoxLayout()) self.solutionSelectorWidget.layout().addWidget(solutionSelectorButtons) self.solutionSelectorWidget.layout().addWidget(self.solutionSelector) exportButton = QPushButton("Export image") exportButton.clicked.connect(self.exportImage) exportAllButton = QPushButton("Export all images") exportAllButton.clicked.connect(self.exportAllImages) computeMetricsButton = QPushButton("Compute metrics") computeMetricsButton.clicked.connect(self.computeMetricsAsync) refreshButton = QPushButton("Refresh") refreshButton.clicked.connect(self.updateUI) controlLayout = QVBoxLayout() controlLayout.addWidget(radioWidget) controlLayout.addWidget(self.generationLabel) controlLayout.addWidget(self.generationSlider) controlLayout.addWidget(self.solutionSelectorWidget) controlLayout.addStretch() controlLayout.addWidget(computeMetricsButton) controlLayout.addWidget(refreshButton) controlLayout.addWidget(exportButton) controlLayout.addWidget(exportAllButton) controlWidget = QWidget() controlWidget.setLayout(controlLayout) leftDock = QDockWidget("Control", self) leftDock.setObjectName("Control") leftDock.setWidget(controlWidget) leftDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.addDockWidget(Qt.LeftDockWidgetArea, leftDock) # Metric widget self.metrics = MetricsPanel(self.analyzer) bottomDock = QDockWidget("Metrics", self) bottomDock.setObjectName("Metrics") bottomDock.setWidget(self.metrics) bottomDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.addDockWidget(Qt.BottomDockWidgetArea, bottomDock) # Actions exitAction = QAction('&Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(qApp.quit) copyAction = QAction("&Copy", self) copyAction.setShortcut("Ctrl+C") copyAction.setStatusTip('Copy metrics') copyAction.triggered.connect(self.metrics.copyMetrics) aboutAction = QAction("&About", self) aboutAction.setStatusTip('About MOOI') aboutAction.triggered.connect(self.helpAbout) # Menus menubar = self.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(copyAction) fileMenu.addAction(aboutAction) fileMenu.addSeparator() fileMenu.addAction(exitAction) def _loadSettings(self): settings = QSettings() self.restoreState( settings.value(MainWindow.__PREF_STATE__).toByteArray()) self.restoreGeometry( settings.value(MainWindow.__PREF_GEOM__).toByteArray()) paretoDirectory = __RESOURCES_DIR__ + Analyzer.__PARETO__ self.analyzer.setPareto(paretoDirectory) currentDirs = settings.value(MainWindow.__PREF_DIR__) if currentDirs is not None: self.analyzer.setResultDirectories( [directory.toString() for directory in currentDirs.toList()]) self._updateSolutionSelection() def exportImage(self): settings = QSettings() filename = settings.value(MainWindow.__PREF_SAVE__) if filename is None: filename = os.path.dirname(__file__) else: filename = os.path.abspath( os.path.join(str(filename.toString()), os.path.pardir)) + "/" filename += "%s_%s.png" % (self.currentSolution.functionName, "fun" if self.isFunctionSpaceSelected() else "var") filename = QFileDialog.getSaveFileName(self, "Export image as", filename, ("PNG image (*.png)")) if filename is None or filename == "": return settings.setValue(MainWindow.__PREF_SAVE__, QVariant(filename)) self._exportCurrentImage(filename) self.statusBar().showMessage("Image saved!", 5000) def isFunctionSpaceSelected(self): return self.showSolutionsRadio.isChecked() def _exportCurrentImage(self, filename=None): generation = self.generationSlider.value() self.generationLabel.setText("Run: %d" % generation) tmp = filename is None if tmp: prefix = "mooi_%s_" % self.currentSolution.functionName filename = tempfile.mkstemp(prefix=prefix, suffix=".png", text=False)[1] resultNames = self._getSelectedResultNames() self.analyzer.exportToImage(self.currentSolution, [generation-1]*len(resultNames), self.isFunctionSpaceSelected(), \ resultNames, str(filename)) if tmp: self.plot.setPlotPixmap(filename) try: os.remove(filename) except: print >> sys.stderr, "Couldn't delete temporal file: %s" % filename def _getSelectedResultNames(self): resultNames = [] for i in xrange(self.analyzer.nResults): implementationItem = self.solutionSelector.layout().itemAt( i).widget() if implementationItem.isChecked(): resultNames.append(str(implementationItem.text())) return resultNames def exportAllImages(self): settings = QSettings() directory = settings.value(MainWindow.__PREF_SAVE_ALL__).toString() directory = QFileDialog.getExistingDirectory( self, "Select a directory to export to", directory) if directory is None or not os.path.exists(directory): return self.analyzer.exportAllImages(directory, self._getSelectedResultNames()) settings.setValue(MainWindow.__PREF_SAVEL_ALL__, QVariant(directory)) self.statusBar().showMessage("Images saved!", 5000) def computeMetricsAsync(self): self.statusBar().showMessage("Computing metrics...") QTimer.singleShot(0, self.computeMetrics) def computeMetrics(self): self._computeMetrics(self.currentSolution.functionName) self.statusBar().showMessage("Metrics computed!", 5000) def _computeMetrics(self, functionName): pareto = self.analyzer.getFunctionPareto(functionName) solutions = self.analyzer.getFunctionResults( functionName, self._getSelectedResultNames()) self.metrics.updateMetrics(pareto, solutions, functionName) def helpAbout(self): QMessageBox.about( self, "About Image Changer", """<b>Multi-Objective Optimization Interface</b> v%s <p>Copyright © 2011-2012 %s All rights reserved. <p>This application can be used to perform simple optimization analysis. <p><a href='%s'>%s</a> <p>Python %s - Qt %s - PyQt %s on %s""" % (__VERSION__, __AUTHOR__, __WEBSITE__, __WEBSITE__, platform.python_version(), QT_VERSION_STR, PYQT_VERSION_STR, platform.system())) def addImplementation(self): if self.analyzer.nResults == 0: directory = "" else: directory = os.path.abspath( os.path.join(str(self.analyzer.resultDirectories[-1]), os.path.pardir)) directory = QFileDialog.getExistingDirectory( self, "Select a directory to scan", directory, QFileDialog.ShowDirsOnly) if not os.path.exists( directory) or directory in self.analyzer.resultDirectories: return self.analyzer.addResultDirectory(directory) self.addSolutionForSelection(self.analyzer.getResultName(directory)) settings = QSettings() settings.setValue(MainWindow.__PREF_DIR__, QVariant(self.analyzer.resultDirectories)) def removeResult(self): layout = self.solutionSelector.layout() for i in xrange(layout.count() - 1, -1, -1): item = layout.itemAt(i) if not item.widget().isChecked( ): # and self.analyzer.resultNames[i] != Analyzer.__PARETO__: item.widget().setVisible(False) layout.removeItem(item) self.analyzer.removeResultDirectory( self.analyzer.resultDirectories[i]) layout.update() settings = QSettings() settings.setValue(MainWindow.__PREF_DIR__, QVariant(self.analyzer.resultDirectories)) def solutionSelected(self): selection = self.functionWidget.currentItem() if selection is None: return self.showSolution(str(selection.text())) def showSolution(self, functionName): self.currentSolution = self.analyzer.getResultsForFunction( functionName) self.metrics.clear() self._showSolution() def addSolutionForSelection(self, name): solution = QCheckBox(name) solution.setChecked(True) solution.stateChanged.connect(self._showSolution) self.solutionSelector.layout().addWidget(solution) self.solutionSelector.layout().update() def _updateSolutionSelection(self): self.clearWidget(self.solutionSelector) for directory in self.analyzer.resultDirectories: self.addSolutionForSelection( self.analyzer.getResultName(directory)) def _showSolution(self): sol = self.currentSolution if sol is None: return if len(sol.variableImplementation ) == 0 and self.showVariablesRadio.isEnabled(): self.showVariablesRadio.setEnabled(False) if self.showVariablesRadio.isChecked(): self.showSolutionsRadio.setChecked(True) else: self.showVariablesRadio.setEnabled(True) if len(sol.functionImplementation ) == 0 and self.showSolutionsRadio.isEnabled(): self.showSolutionsRadio.setEnabled(False) if self.showSolutionsRadio.isChecked(): self.showVariablesRadio.setChecked(True) else: self.showSolutionsRadio.setEnabled(True) if self.showSolutionsRadio.isChecked(): self.generationSlider.setMaximum( max([ sol.getFunctionSolution(impl).count() for impl in sol.functionImplementation ])) else: self.generationSlider.setMaximum( max([ sol.getVariableSolution(impl).count() for impl in sol.variableImplementation ])) self._exportCurrentImage() def clearWidget(self, widget): layout = widget.layout() for i in xrange(layout.count() - 1, -1, -1): layout.removeItem(layout.itemAt(i)) def updateUI(self): self.statusBar().showMessage("Updating solutions...") selectedRow = self.functionWidget.currentRow() self.functionWidget.clear() names = [] + self.analyzer.getFunctionNames() names.sort() for name in names: item = QListWidgetItem() item.setText(name) self.functionWidget.addItem(item) if self.functionWidget.count() > 0: self.functionWidget.setCurrentRow( selectedRow if selectedRow >= 0 and selectedRow < self.functionWidget.count() else 0) self.statusBar().showMessage("Updated!", 5000) def _loadInitialData(self): self.updateUI() self.statusBar().showMessage("Ready!", 5000) def closeEvent(self, event): self.statusBar().showMessage("Closing...") settings = QSettings() settings.setValue(MainWindow.__PREF_GEOM__, self.saveGeometry()) settings.setValue(MainWindow.__PREF_STATE__, self.saveState()) self.plot.clear()
def setupUi(self, MainWindow): MainWindow.setObjectName(_fromUtf8("MainWindow")) MainWindow.resize(1029, 526) self.centralwidget = QtGui.QWidget(MainWindow) self.centralwidget.setObjectName(_fromUtf8("centralwidget")) self.gridLayout_2 = QtGui.QGridLayout(self.centralwidget) self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2")) self.gridLayout = QtGui.QGridLayout() self.gridLayout.setObjectName(_fromUtf8("gridLayout")) self.PlotWidget = PlotWidget(self.centralwidget) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.PlotWidget.sizePolicy().hasHeightForWidth()) self.PlotWidget.setSizePolicy(sizePolicy) self.PlotWidget.setAutoFillBackground(False) self.PlotWidget.setObjectName(_fromUtf8("PlotWidget")) self.gridLayout.addWidget(self.PlotWidget, 0, 0, 3, 1) self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtGui.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 1029, 30)) self.menubar.setObjectName(_fromUtf8("menubar")) self.menuFile = QtGui.QMenu(self.menubar) self.menuFile.setObjectName(_fromUtf8("menuFile")) self.menuHelp = QtGui.QMenu(self.menubar) self.menuHelp.setObjectName(_fromUtf8("menuHelp")) self.menuView = QtGui.QMenu(self.menubar) self.menuView.setObjectName(_fromUtf8("menuView")) self.menuPaper_format = QtGui.QMenu(self.menuView) self.menuPaper_format.setObjectName(_fromUtf8("menuPaper_format")) self.menuAnnotation_Toolbar = QtGui.QMenu(self.menuView) self.menuAnnotation_Toolbar.setObjectName( _fromUtf8("menuAnnotation_Toolbar")) self.menuTools = QtGui.QMenu(self.menubar) self.menuTools.setObjectName(_fromUtf8("menuTools")) MainWindow.setMenuBar(self.menubar) self.statusbar = QtGui.QStatusBar(MainWindow) self.statusbar.setObjectName(_fromUtf8("statusbar")) MainWindow.setStatusBar(self.statusbar) self.dockClinInfo = QtGui.QDockWidget(MainWindow) self.dockClinInfo.setObjectName(_fromUtf8("dockClinInfo")) self.dockClinInfoContents = QtGui.QWidget() self.dockClinInfoContents.setObjectName( _fromUtf8("dockClinInfoContents")) self.dockClinInfo.setWidget(self.dockClinInfoContents) MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.dockClinInfo) self.dockDataBrowser = QtGui.QDockWidget(MainWindow) self.dockDataBrowser.setObjectName(_fromUtf8("dockDataBrowser")) self.dockWidgetContents = QtGui.QWidget() self.dockWidgetContents.setObjectName(_fromUtf8("dockWidgetContents")) self.dockDataBrowser.setWidget(self.dockWidgetContents) MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(1), self.dockDataBrowser) self.toolBar = QtGui.QToolBar(MainWindow) self.toolBar.setEnabled(True) font = QtGui.QFont() font.setPointSize(8) self.toolBar.setFont(font) self.toolBar.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) self.toolBar.setMovable(True) self.toolBar.setAllowedAreas(QtCore.Qt.AllToolBarAreas) self.toolBar.setIconSize(QtCore.QSize(22, 22)) self.toolBar.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon) self.toolBar.setFloatable(False) self.toolBar.setObjectName(_fromUtf8("toolBar")) MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar) self.actionOpen = QtGui.QAction(MainWindow) icon = QtGui.QIcon() icon.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/document-open-3.png")), QtGui.QIcon.Normal, QtGui.QIcon.On) self.actionOpen.setIcon(icon) self.actionOpen.setStatusTip(_fromUtf8("")) self.actionOpen.setObjectName(_fromUtf8("actionOpen")) self.actionClose = QtGui.QAction(MainWindow) icon1 = QtGui.QIcon() icon1.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/document-close-3.png")), QtGui.QIcon.Normal, QtGui.QIcon.On) self.actionClose.setIcon(icon1) self.actionClose.setObjectName(_fromUtf8("actionClose")) self.actionQuit = QtGui.QAction(MainWindow) icon2 = QtGui.QIcon() icon2.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/application-exit-4.png")), QtGui.QIcon.Normal, QtGui.QIcon.On) self.actionQuit.setIcon(icon2) self.actionQuit.setObjectName(_fromUtf8("actionQuit")) self.actionAbout = QtGui.QAction(MainWindow) self.actionAbout.setObjectName(_fromUtf8("actionAbout")) self.actionConvert_files = QtGui.QAction(MainWindow) self.actionConvert_files.setObjectName( _fromUtf8("actionConvert_files")) self.actionOpen_folder = QtGui.QAction(MainWindow) self.actionOpen_folder.setObjectName(_fromUtf8("actionOpen_folder")) self.actionAttribute_selection = QtGui.QAction(MainWindow) self.actionAttribute_selection.setObjectName( _fromUtf8("actionAttribute_selection")) self.actionDownload_CTU_UHB_data = QtGui.QAction(MainWindow) self.actionDownload_CTU_UHB_data.setObjectName( _fromUtf8("actionDownload_CTU_UHB_data")) self.actionData_browser = QtGui.QAction(MainWindow) self.actionData_browser.setCheckable(True) self.actionData_browser.setObjectName(_fromUtf8("actionData_browser")) self.actionExport_to_PDF = QtGui.QAction(MainWindow) self.actionExport_to_PDF.setEnabled(True) icon3 = QtGui.QIcon() icon3.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/pdf_icon2.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionExport_to_PDF.setIcon(icon3) self.actionExport_to_PDF.setObjectName( _fromUtf8("actionExport_to_PDF")) self.actionEU = QtGui.QAction(MainWindow) self.actionEU.setCheckable(True) self.actionEU.setObjectName(_fromUtf8("actionEU")) self.actionUS = QtGui.QAction(MainWindow) self.actionUS.setCheckable(True) self.actionUS.setObjectName(_fromUtf8("actionUS")) self.actionSet_Clear_Baseline = QtGui.QAction(MainWindow) self.actionSet_Clear_Baseline.setObjectName( _fromUtf8("actionSet_Clear_Baseline")) self.actionBasal = QtGui.QAction(MainWindow) self.actionBasal.setCheckable(True) icon4 = QtGui.QIcon() icon4.addPixmap(QtGui.QPixmap(_fromUtf8(":/actions/icons/basal.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionBasal.setIcon(icon4) self.actionBasal.setObjectName(_fromUtf8("actionBasal")) self.actionBaseline = QtGui.QAction(MainWindow) self.actionBaseline.setCheckable(True) icon5 = QtGui.QIcon() icon5.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/baseline.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionBaseline.setIcon(icon5) self.actionBaseline.setObjectName(_fromUtf8("actionBaseline")) self.actionRecovery = QtGui.QAction(MainWindow) self.actionRecovery.setCheckable(True) icon6 = QtGui.QIcon() icon6.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/recovery.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionRecovery.setIcon(icon6) self.actionRecovery.setObjectName(_fromUtf8("actionRecovery")) self.actionCursor = QtGui.QAction(MainWindow) self.actionCursor.setCheckable(True) icon7 = QtGui.QIcon() icon7.addPixmap(QtGui.QPixmap(_fromUtf8(":/actions/icons/cursor.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionCursor.setIcon(icon7) self.actionCursor.setObjectName(_fromUtf8("actionCursor")) self.actionNote = QtGui.QAction(MainWindow) self.actionNote.setCheckable(True) icon8 = QtGui.QIcon() icon8.addPixmap(QtGui.QPixmap(_fromUtf8(":/actions/icons/note.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionNote.setIcon(icon8) self.actionNote.setObjectName(_fromUtf8("actionNote")) self.actionSave = QtGui.QAction(MainWindow) self.actionSave.setEnabled(False) icon9 = QtGui.QIcon() icon9.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/save_icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionSave.setIcon(icon9) self.actionSave.setObjectName(_fromUtf8("actionSave")) self.actionDelete = QtGui.QAction(MainWindow) self.actionDelete.setEnabled(True) icon10 = QtGui.QIcon() icon10.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/recycle_bin.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionDelete.setIcon(icon10) self.actionDelete.setObjectName(_fromUtf8("actionDelete")) self.actionSent_annotations = QtGui.QAction(MainWindow) self.actionSent_annotations.setObjectName( _fromUtf8("actionSent_annotations")) self.actionNo_recovery = QtGui.QAction(MainWindow) self.actionNo_recovery.setCheckable(True) icon11 = QtGui.QIcon() icon11.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/no_recovery.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionNo_recovery.setIcon(icon11) self.actionNo_recovery.setObjectName(_fromUtf8("actionNo_recovery")) self.actionEllipse = QtGui.QAction(MainWindow) self.actionEllipse.setCheckable(True) icon12 = QtGui.QIcon() icon12.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/ellipse-icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionEllipse.setIcon(icon12) self.actionEllipse.setObjectName(_fromUtf8("actionEllipse")) self.actionExcessive_UA = QtGui.QAction(MainWindow) self.actionExcessive_UA.setCheckable(True) icon13 = QtGui.QIcon() icon13.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/excessive_ua.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionExcessive_UA.setIcon(icon13) self.actionExcessive_UA.setObjectName(_fromUtf8("actionExcessive_UA")) self.actionAnnToolbarVisible = QtGui.QAction(MainWindow) self.actionAnnToolbarVisible.setCheckable(True) self.actionAnnToolbarVisible.setObjectName( _fromUtf8("actionAnnToolbarVisible")) self.actionAnnToolbarAlign_right = QtGui.QAction(MainWindow) self.actionAnnToolbarAlign_right.setCheckable(True) self.actionAnnToolbarAlign_right.setObjectName( _fromUtf8("actionAnnToolbarAlign_right")) self.actionClinical_information = QtGui.QAction(MainWindow) self.actionClinical_information.setCheckable(True) self.actionClinical_information.setObjectName( _fromUtf8("actionClinical_information")) self.actionEllipseNote = QtGui.QAction(MainWindow) self.actionEllipseNote.setCheckable(True) icon14 = QtGui.QIcon() icon14.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/ellipse-note-icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionEllipseNote.setIcon(icon14) self.actionEllipseNote.setObjectName(_fromUtf8("actionEllipseNote")) self.actionFloating_Baseline = QtGui.QAction(MainWindow) self.actionFloating_Baseline.setCheckable(True) icon15 = QtGui.QIcon() icon15.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/floating_baseline.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionFloating_Baseline.setIcon(icon15) self.actionFloating_Baseline.setObjectName( _fromUtf8("actionFloating_Baseline")) self.actionAcceleration = QtGui.QAction(MainWindow) self.actionAcceleration.setCheckable(True) icon16 = QtGui.QIcon() icon16.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/acceleration.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionAcceleration.setIcon(icon16) self.actionAcceleration.setObjectName(_fromUtf8("actionAcceleration")) self.actionDeceleration = QtGui.QAction(MainWindow) self.actionDeceleration.setCheckable(True) icon17 = QtGui.QIcon() icon17.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/deceleration.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionDeceleration.setIcon(icon17) self.actionDeceleration.setObjectName(_fromUtf8("actionDeceleration")) self.actionUA = QtGui.QAction(MainWindow) self.actionUA.setCheckable(True) icon18 = QtGui.QIcon() icon18.addPixmap( QtGui.QPixmap( _fromUtf8(":/actions/icons/uterine_contraction.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionUA.setIcon(icon18) self.actionUA.setObjectName(_fromUtf8("actionUA")) self.actionCaliper = QtGui.QAction(MainWindow) self.actionCaliper.setCheckable(True) icon19 = QtGui.QIcon() icon19.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/caliper.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionCaliper.setIcon(icon19) self.actionCaliper.setObjectName(_fromUtf8("actionCaliper")) self.actionCaliperFHR = QtGui.QAction(MainWindow) self.actionCaliperFHR.setCheckable(True) self.actionCaliperFHR.setObjectName(_fromUtf8("actionCaliperFHR")) self.actionCaliperTOCO = QtGui.QAction(MainWindow) self.actionCaliperTOCO.setCheckable(True) self.actionCaliperTOCO.setObjectName(_fromUtf8("actionCaliperTOCO")) self.actionFIGO_acc_dec = QtGui.QAction(MainWindow) self.actionFIGO_acc_dec.setObjectName(_fromUtf8("actionFIGO_acc_dec")) self.actionFIGO_UA = QtGui.QAction(MainWindow) self.actionFIGO_UA.setObjectName(_fromUtf8("actionFIGO_UA")) self.actionCaliperReset = QtGui.QAction(MainWindow) self.actionCaliperReset.setObjectName(_fromUtf8("actionCaliperReset")) self.actionAnnShowHide = QtGui.QAction(MainWindow) icon20 = QtGui.QIcon() icon20.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/ann_visibility.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionAnnShowHide.setIcon(icon20) self.actionAnnShowHide.setObjectName(_fromUtf8("actionAnnShowHide")) self.actionDebug_CalibSignal = QtGui.QAction(MainWindow) self.actionDebug_CalibSignal.setObjectName( _fromUtf8("actionDebug_CalibSignal")) self.actionEvaluationNote = QtGui.QAction(MainWindow) self.actionEvaluationNote.setCheckable(True) icon21 = QtGui.QIcon() icon21.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/assessment.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionEvaluationNote.setIcon(icon21) self.actionEvaluationNote.setObjectName( _fromUtf8("actionEvaluationNote")) self.menuFile.addAction(self.actionOpen) self.menuFile.addAction(self.actionOpen_folder) self.menuFile.addAction(self.actionExport_to_PDF) self.menuFile.addAction(self.actionQuit) self.menuHelp.addAction(self.actionAbout) self.menuPaper_format.addAction(self.actionEU) self.menuPaper_format.addAction(self.actionUS) self.menuAnnotation_Toolbar.addAction(self.actionAnnToolbarVisible) self.menuAnnotation_Toolbar.addAction(self.actionAnnToolbarAlign_right) self.menuView.addAction(self.actionClinical_information) self.menuView.addAction(self.actionData_browser) self.menuView.addAction(self.menuPaper_format.menuAction()) self.menuView.addAction(self.menuAnnotation_Toolbar.menuAction()) self.menuTools.addAction(self.actionAttribute_selection) self.menuTools.addAction(self.actionConvert_files) self.menuTools.addAction(self.actionDownload_CTU_UHB_data) self.menuTools.addAction(self.actionSent_annotations) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuView.menuAction()) self.menubar.addAction(self.menuTools.menuAction()) self.menubar.addAction(self.menuHelp.menuAction()) self.toolBar.addAction(self.actionCursor) self.toolBar.addAction(self.actionBasal) self.toolBar.addAction(self.actionBaseline) self.toolBar.addAction(self.actionRecovery) self.toolBar.addAction(self.actionNo_recovery) self.toolBar.addAction(self.actionExcessive_UA) self.toolBar.addAction(self.actionEllipseNote) self.toolBar.addAction(self.actionNote) self.toolBar.addAction(self.actionEvaluationNote) self.toolBar.addSeparator() self.toolBar.addAction(self.actionCaliper) self.toolBar.addAction(self.actionSave) self.toolBar.addAction(self.actionDelete) self.toolBar.addSeparator() self.toolBar.addAction(self.actionFloating_Baseline) self.toolBar.addAction(self.actionAcceleration) self.toolBar.addAction(self.actionDeceleration) self.toolBar.addAction(self.actionUA) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow)
class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName(_fromUtf8("MainWindow")) MainWindow.resize(1029, 526) self.centralwidget = QtGui.QWidget(MainWindow) self.centralwidget.setObjectName(_fromUtf8("centralwidget")) self.gridLayout_2 = QtGui.QGridLayout(self.centralwidget) self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2")) self.gridLayout = QtGui.QGridLayout() self.gridLayout.setObjectName(_fromUtf8("gridLayout")) self.PlotWidget = PlotWidget(self.centralwidget) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.PlotWidget.sizePolicy().hasHeightForWidth()) self.PlotWidget.setSizePolicy(sizePolicy) self.PlotWidget.setAutoFillBackground(False) self.PlotWidget.setObjectName(_fromUtf8("PlotWidget")) self.gridLayout.addWidget(self.PlotWidget, 0, 0, 3, 1) self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtGui.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 1029, 30)) self.menubar.setObjectName(_fromUtf8("menubar")) self.menuFile = QtGui.QMenu(self.menubar) self.menuFile.setObjectName(_fromUtf8("menuFile")) self.menuHelp = QtGui.QMenu(self.menubar) self.menuHelp.setObjectName(_fromUtf8("menuHelp")) self.menuView = QtGui.QMenu(self.menubar) self.menuView.setObjectName(_fromUtf8("menuView")) self.menuPaper_format = QtGui.QMenu(self.menuView) self.menuPaper_format.setObjectName(_fromUtf8("menuPaper_format")) self.menuAnnotation_Toolbar = QtGui.QMenu(self.menuView) self.menuAnnotation_Toolbar.setObjectName( _fromUtf8("menuAnnotation_Toolbar")) self.menuTools = QtGui.QMenu(self.menubar) self.menuTools.setObjectName(_fromUtf8("menuTools")) MainWindow.setMenuBar(self.menubar) self.statusbar = QtGui.QStatusBar(MainWindow) self.statusbar.setObjectName(_fromUtf8("statusbar")) MainWindow.setStatusBar(self.statusbar) self.dockClinInfo = QtGui.QDockWidget(MainWindow) self.dockClinInfo.setObjectName(_fromUtf8("dockClinInfo")) self.dockClinInfoContents = QtGui.QWidget() self.dockClinInfoContents.setObjectName( _fromUtf8("dockClinInfoContents")) self.dockClinInfo.setWidget(self.dockClinInfoContents) MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.dockClinInfo) self.dockDataBrowser = QtGui.QDockWidget(MainWindow) self.dockDataBrowser.setObjectName(_fromUtf8("dockDataBrowser")) self.dockWidgetContents = QtGui.QWidget() self.dockWidgetContents.setObjectName(_fromUtf8("dockWidgetContents")) self.dockDataBrowser.setWidget(self.dockWidgetContents) MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(1), self.dockDataBrowser) self.toolBar = QtGui.QToolBar(MainWindow) self.toolBar.setEnabled(True) font = QtGui.QFont() font.setPointSize(8) self.toolBar.setFont(font) self.toolBar.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) self.toolBar.setMovable(True) self.toolBar.setAllowedAreas(QtCore.Qt.AllToolBarAreas) self.toolBar.setIconSize(QtCore.QSize(22, 22)) self.toolBar.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon) self.toolBar.setFloatable(False) self.toolBar.setObjectName(_fromUtf8("toolBar")) MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar) self.actionOpen = QtGui.QAction(MainWindow) icon = QtGui.QIcon() icon.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/document-open-3.png")), QtGui.QIcon.Normal, QtGui.QIcon.On) self.actionOpen.setIcon(icon) self.actionOpen.setStatusTip(_fromUtf8("")) self.actionOpen.setObjectName(_fromUtf8("actionOpen")) self.actionClose = QtGui.QAction(MainWindow) icon1 = QtGui.QIcon() icon1.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/document-close-3.png")), QtGui.QIcon.Normal, QtGui.QIcon.On) self.actionClose.setIcon(icon1) self.actionClose.setObjectName(_fromUtf8("actionClose")) self.actionQuit = QtGui.QAction(MainWindow) icon2 = QtGui.QIcon() icon2.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/application-exit-4.png")), QtGui.QIcon.Normal, QtGui.QIcon.On) self.actionQuit.setIcon(icon2) self.actionQuit.setObjectName(_fromUtf8("actionQuit")) self.actionAbout = QtGui.QAction(MainWindow) self.actionAbout.setObjectName(_fromUtf8("actionAbout")) self.actionConvert_files = QtGui.QAction(MainWindow) self.actionConvert_files.setObjectName( _fromUtf8("actionConvert_files")) self.actionOpen_folder = QtGui.QAction(MainWindow) self.actionOpen_folder.setObjectName(_fromUtf8("actionOpen_folder")) self.actionAttribute_selection = QtGui.QAction(MainWindow) self.actionAttribute_selection.setObjectName( _fromUtf8("actionAttribute_selection")) self.actionDownload_CTU_UHB_data = QtGui.QAction(MainWindow) self.actionDownload_CTU_UHB_data.setObjectName( _fromUtf8("actionDownload_CTU_UHB_data")) self.actionData_browser = QtGui.QAction(MainWindow) self.actionData_browser.setCheckable(True) self.actionData_browser.setObjectName(_fromUtf8("actionData_browser")) self.actionExport_to_PDF = QtGui.QAction(MainWindow) self.actionExport_to_PDF.setEnabled(True) icon3 = QtGui.QIcon() icon3.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/pdf_icon2.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionExport_to_PDF.setIcon(icon3) self.actionExport_to_PDF.setObjectName( _fromUtf8("actionExport_to_PDF")) self.actionEU = QtGui.QAction(MainWindow) self.actionEU.setCheckable(True) self.actionEU.setObjectName(_fromUtf8("actionEU")) self.actionUS = QtGui.QAction(MainWindow) self.actionUS.setCheckable(True) self.actionUS.setObjectName(_fromUtf8("actionUS")) self.actionSet_Clear_Baseline = QtGui.QAction(MainWindow) self.actionSet_Clear_Baseline.setObjectName( _fromUtf8("actionSet_Clear_Baseline")) self.actionBasal = QtGui.QAction(MainWindow) self.actionBasal.setCheckable(True) icon4 = QtGui.QIcon() icon4.addPixmap(QtGui.QPixmap(_fromUtf8(":/actions/icons/basal.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionBasal.setIcon(icon4) self.actionBasal.setObjectName(_fromUtf8("actionBasal")) self.actionBaseline = QtGui.QAction(MainWindow) self.actionBaseline.setCheckable(True) icon5 = QtGui.QIcon() icon5.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/baseline.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionBaseline.setIcon(icon5) self.actionBaseline.setObjectName(_fromUtf8("actionBaseline")) self.actionRecovery = QtGui.QAction(MainWindow) self.actionRecovery.setCheckable(True) icon6 = QtGui.QIcon() icon6.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/recovery.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionRecovery.setIcon(icon6) self.actionRecovery.setObjectName(_fromUtf8("actionRecovery")) self.actionCursor = QtGui.QAction(MainWindow) self.actionCursor.setCheckable(True) icon7 = QtGui.QIcon() icon7.addPixmap(QtGui.QPixmap(_fromUtf8(":/actions/icons/cursor.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionCursor.setIcon(icon7) self.actionCursor.setObjectName(_fromUtf8("actionCursor")) self.actionNote = QtGui.QAction(MainWindow) self.actionNote.setCheckable(True) icon8 = QtGui.QIcon() icon8.addPixmap(QtGui.QPixmap(_fromUtf8(":/actions/icons/note.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionNote.setIcon(icon8) self.actionNote.setObjectName(_fromUtf8("actionNote")) self.actionSave = QtGui.QAction(MainWindow) self.actionSave.setEnabled(False) icon9 = QtGui.QIcon() icon9.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/save_icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionSave.setIcon(icon9) self.actionSave.setObjectName(_fromUtf8("actionSave")) self.actionDelete = QtGui.QAction(MainWindow) self.actionDelete.setEnabled(True) icon10 = QtGui.QIcon() icon10.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/recycle_bin.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionDelete.setIcon(icon10) self.actionDelete.setObjectName(_fromUtf8("actionDelete")) self.actionSent_annotations = QtGui.QAction(MainWindow) self.actionSent_annotations.setObjectName( _fromUtf8("actionSent_annotations")) self.actionNo_recovery = QtGui.QAction(MainWindow) self.actionNo_recovery.setCheckable(True) icon11 = QtGui.QIcon() icon11.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/no_recovery.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionNo_recovery.setIcon(icon11) self.actionNo_recovery.setObjectName(_fromUtf8("actionNo_recovery")) self.actionEllipse = QtGui.QAction(MainWindow) self.actionEllipse.setCheckable(True) icon12 = QtGui.QIcon() icon12.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/ellipse-icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionEllipse.setIcon(icon12) self.actionEllipse.setObjectName(_fromUtf8("actionEllipse")) self.actionExcessive_UA = QtGui.QAction(MainWindow) self.actionExcessive_UA.setCheckable(True) icon13 = QtGui.QIcon() icon13.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/excessive_ua.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionExcessive_UA.setIcon(icon13) self.actionExcessive_UA.setObjectName(_fromUtf8("actionExcessive_UA")) self.actionAnnToolbarVisible = QtGui.QAction(MainWindow) self.actionAnnToolbarVisible.setCheckable(True) self.actionAnnToolbarVisible.setObjectName( _fromUtf8("actionAnnToolbarVisible")) self.actionAnnToolbarAlign_right = QtGui.QAction(MainWindow) self.actionAnnToolbarAlign_right.setCheckable(True) self.actionAnnToolbarAlign_right.setObjectName( _fromUtf8("actionAnnToolbarAlign_right")) self.actionClinical_information = QtGui.QAction(MainWindow) self.actionClinical_information.setCheckable(True) self.actionClinical_information.setObjectName( _fromUtf8("actionClinical_information")) self.actionEllipseNote = QtGui.QAction(MainWindow) self.actionEllipseNote.setCheckable(True) icon14 = QtGui.QIcon() icon14.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/ellipse-note-icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionEllipseNote.setIcon(icon14) self.actionEllipseNote.setObjectName(_fromUtf8("actionEllipseNote")) self.actionFloating_Baseline = QtGui.QAction(MainWindow) self.actionFloating_Baseline.setCheckable(True) icon15 = QtGui.QIcon() icon15.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/floating_baseline.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionFloating_Baseline.setIcon(icon15) self.actionFloating_Baseline.setObjectName( _fromUtf8("actionFloating_Baseline")) self.actionAcceleration = QtGui.QAction(MainWindow) self.actionAcceleration.setCheckable(True) icon16 = QtGui.QIcon() icon16.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/acceleration.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionAcceleration.setIcon(icon16) self.actionAcceleration.setObjectName(_fromUtf8("actionAcceleration")) self.actionDeceleration = QtGui.QAction(MainWindow) self.actionDeceleration.setCheckable(True) icon17 = QtGui.QIcon() icon17.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/deceleration.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionDeceleration.setIcon(icon17) self.actionDeceleration.setObjectName(_fromUtf8("actionDeceleration")) self.actionUA = QtGui.QAction(MainWindow) self.actionUA.setCheckable(True) icon18 = QtGui.QIcon() icon18.addPixmap( QtGui.QPixmap( _fromUtf8(":/actions/icons/uterine_contraction.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionUA.setIcon(icon18) self.actionUA.setObjectName(_fromUtf8("actionUA")) self.actionCaliper = QtGui.QAction(MainWindow) self.actionCaliper.setCheckable(True) icon19 = QtGui.QIcon() icon19.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/caliper.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionCaliper.setIcon(icon19) self.actionCaliper.setObjectName(_fromUtf8("actionCaliper")) self.actionCaliperFHR = QtGui.QAction(MainWindow) self.actionCaliperFHR.setCheckable(True) self.actionCaliperFHR.setObjectName(_fromUtf8("actionCaliperFHR")) self.actionCaliperTOCO = QtGui.QAction(MainWindow) self.actionCaliperTOCO.setCheckable(True) self.actionCaliperTOCO.setObjectName(_fromUtf8("actionCaliperTOCO")) self.actionFIGO_acc_dec = QtGui.QAction(MainWindow) self.actionFIGO_acc_dec.setObjectName(_fromUtf8("actionFIGO_acc_dec")) self.actionFIGO_UA = QtGui.QAction(MainWindow) self.actionFIGO_UA.setObjectName(_fromUtf8("actionFIGO_UA")) self.actionCaliperReset = QtGui.QAction(MainWindow) self.actionCaliperReset.setObjectName(_fromUtf8("actionCaliperReset")) self.actionAnnShowHide = QtGui.QAction(MainWindow) icon20 = QtGui.QIcon() icon20.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/ann_visibility.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionAnnShowHide.setIcon(icon20) self.actionAnnShowHide.setObjectName(_fromUtf8("actionAnnShowHide")) self.actionDebug_CalibSignal = QtGui.QAction(MainWindow) self.actionDebug_CalibSignal.setObjectName( _fromUtf8("actionDebug_CalibSignal")) self.actionEvaluationNote = QtGui.QAction(MainWindow) self.actionEvaluationNote.setCheckable(True) icon21 = QtGui.QIcon() icon21.addPixmap( QtGui.QPixmap(_fromUtf8(":/actions/icons/assessment.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionEvaluationNote.setIcon(icon21) self.actionEvaluationNote.setObjectName( _fromUtf8("actionEvaluationNote")) self.menuFile.addAction(self.actionOpen) self.menuFile.addAction(self.actionOpen_folder) self.menuFile.addAction(self.actionExport_to_PDF) self.menuFile.addAction(self.actionQuit) self.menuHelp.addAction(self.actionAbout) self.menuPaper_format.addAction(self.actionEU) self.menuPaper_format.addAction(self.actionUS) self.menuAnnotation_Toolbar.addAction(self.actionAnnToolbarVisible) self.menuAnnotation_Toolbar.addAction(self.actionAnnToolbarAlign_right) self.menuView.addAction(self.actionClinical_information) self.menuView.addAction(self.actionData_browser) self.menuView.addAction(self.menuPaper_format.menuAction()) self.menuView.addAction(self.menuAnnotation_Toolbar.menuAction()) self.menuTools.addAction(self.actionAttribute_selection) self.menuTools.addAction(self.actionConvert_files) self.menuTools.addAction(self.actionDownload_CTU_UHB_data) self.menuTools.addAction(self.actionSent_annotations) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuView.menuAction()) self.menubar.addAction(self.menuTools.menuAction()) self.menubar.addAction(self.menuHelp.menuAction()) self.toolBar.addAction(self.actionCursor) self.toolBar.addAction(self.actionBasal) self.toolBar.addAction(self.actionBaseline) self.toolBar.addAction(self.actionRecovery) self.toolBar.addAction(self.actionNo_recovery) self.toolBar.addAction(self.actionExcessive_UA) self.toolBar.addAction(self.actionEllipseNote) self.toolBar.addAction(self.actionNote) self.toolBar.addAction(self.actionEvaluationNote) self.toolBar.addSeparator() self.toolBar.addAction(self.actionCaliper) self.toolBar.addAction(self.actionSave) self.toolBar.addAction(self.actionDelete) self.toolBar.addSeparator() self.toolBar.addAction(self.actionFloating_Baseline) self.toolBar.addAction(self.actionAcceleration) self.toolBar.addAction(self.actionDeceleration) self.toolBar.addAction(self.actionUA) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): MainWindow.setWindowTitle( _translate("MainWindow", "CTGViewerLite", None)) self.menuFile.setTitle(_translate("MainWindow", "File", None)) self.menuHelp.setTitle(_translate("MainWindow", "Help", None)) self.menuView.setTitle(_translate("MainWindow", "View", None)) self.menuPaper_format.setTitle( _translate("MainWindow", "Paper format", None)) self.menuAnnotation_Toolbar.setTitle( _translate("MainWindow", "Annotation Toolbar", None)) self.menuTools.setTitle(_translate("MainWindow", "Tools", None)) self.dockClinInfo.setWindowTitle( _translate("MainWindow", "Clinical information", None)) self.dockDataBrowser.setWindowTitle( _translate("MainWindow", "Data browser", None)) self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar", None)) self.actionOpen.setText(_translate("MainWindow", "&Open file", None)) self.actionOpen.setIconText(_translate("MainWindow", "Open file", None)) self.actionOpen.setShortcut(_translate("MainWindow", "Ctrl+O", None)) self.actionClose.setText(_translate("MainWindow", "&Close", None)) self.actionClose.setShortcut(_translate("MainWindow", "Ctrl+W", None)) self.actionQuit.setText(_translate("MainWindow", "&Quit", None)) self.actionQuit.setToolTip(_translate("MainWindow", "Quit", None)) self.actionQuit.setShortcut(_translate("MainWindow", "Ctrl+Q", None)) self.actionAbout.setText(_translate("MainWindow", "About", None)) self.actionConvert_files.setText( _translate("MainWindow", "Convert files", None)) self.actionOpen_folder.setText( _translate("MainWindow", "Open folder", None)) self.actionOpen_folder.setShortcut( _translate("MainWindow", "Ctrl+Alt+O", None)) self.actionAttribute_selection.setText( _translate("MainWindow", "Attribute selection", None)) self.actionDownload_CTU_UHB_data.setText( _translate("MainWindow", "Download CTU-UHB data", None)) self.actionData_browser.setText( _translate("MainWindow", "Data browser", None)) self.actionExport_to_PDF.setText( _translate("MainWindow", "Export to PDF", None)) self.actionExport_to_PDF.setShortcut( _translate("MainWindow", "Ctrl+Shift+E", None)) self.actionEU.setText( _translate("MainWindow", "EU (1cm/min, 20bpm/cm)", None)) self.actionEU.setToolTip( _translate("MainWindow", "EU (1cm/min., 20bpm/cm)", None)) self.actionUS.setText( _translate("MainWindow", "US (3cm/min, 30bpm/cm)", None)) self.actionUS.setToolTip( _translate("MainWindow", "US (3cm/min., 30bpm/cm)", None)) self.actionSet_Clear_Baseline.setText( _translate("MainWindow", "Set/Clear Baseline", None)) self.actionSet_Clear_Baseline.setShortcut( _translate("MainWindow", "Ctrl+B", None)) self.actionBasal.setText(_translate("MainWindow", "basal", None)) self.actionBasal.setIconText(_translate("MainWindow", "Basal", None)) self.actionBasal.setToolTip( _translate("MainWindow", "Draw basal heart rate line", None)) self.actionBaseline.setText(_translate("MainWindow", "baseline", None)) self.actionBaseline.setIconText( _translate("MainWindow", "Baseline", None)) self.actionBaseline.setToolTip( _translate("MainWindow", "Draw a baseline (B)", None)) self.actionBaseline.setShortcut(_translate("MainWindow", "B", None)) self.actionRecovery.setText(_translate("MainWindow", "recovery", None)) self.actionRecovery.setIconText( _translate("MainWindow", "Recovery", None)) self.actionRecovery.setToolTip( _translate("MainWindow", "Recovery (R)", None)) self.actionRecovery.setShortcut(_translate("MainWindow", "R", None)) self.actionCursor.setText(_translate("MainWindow", "select", None)) self.actionCursor.setIconText(_translate("MainWindow", "Select", None)) self.actionCursor.setToolTip( _translate("MainWindow", "Select and move (S)", None)) self.actionCursor.setShortcut(_translate("MainWindow", "S", None)) self.actionNote.setText(_translate("MainWindow", "note", None)) self.actionNote.setIconText(_translate("MainWindow", "Note", None)) self.actionNote.setToolTip(_translate("MainWindow", "Add note", None)) self.actionSave.setText(_translate("MainWindow", "save", None)) self.actionSave.setIconText(_translate("MainWindow", "Save", None)) self.actionSave.setToolTip( _translate("MainWindow", "Save all changes", None)) self.actionSave.setShortcut(_translate("MainWindow", "Ctrl+S", None)) self.actionDelete.setText(_translate("MainWindow", "Delete", None)) self.actionDelete.setIconText( _translate("MainWindow", "Delete All", None)) self.actionDelete.setToolTip( _translate("MainWindow", "Delete all annotations", None)) self.actionSent_annotations.setText( _translate("MainWindow", "Sent annotations", None)) self.actionNo_recovery.setText( _translate("MainWindow", "No recovery", None)) self.actionEllipse.setText(_translate("MainWindow", "Mark", None)) self.actionEllipse.setToolTip( _translate("MainWindow", "Draw mark (ellipse)", None)) self.actionExcessive_UA.setText( _translate("MainWindow", "Excessive UA", None)) self.actionExcessive_UA.setToolTip( _translate("MainWindow", "Excessive uterine contractions", None)) self.actionAnnToolbarVisible.setText( _translate("MainWindow", "Show/hide", None)) self.actionAnnToolbarVisible.setToolTip( _translate("MainWindow", "Show/hide annotation toolbar and annotations", None)) self.actionAnnToolbarAlign_right.setText( _translate("MainWindow", "Align right", None)) self.actionClinical_information.setText( _translate("MainWindow", "Clinical information", None)) self.actionEllipseNote.setText(_translate("MainWindow", "Mark ", None)) self.actionEllipseNote.setToolTip( _translate("MainWindow", "Mark with note", None)) self.actionFloating_Baseline.setText( _translate("MainWindow", "Float. Baseline", None)) self.actionFloating_Baseline.setToolTip( _translate("MainWindow", "Add Floating Baseline (F)", None)) self.actionFloating_Baseline.setShortcut( _translate("MainWindow", "F", None)) self.actionAcceleration.setText(_translate("MainWindow", "Accel", None)) self.actionAcceleration.setToolTip( _translate("MainWindow", "Add acceleration (A)", None)) self.actionAcceleration.setShortcut(_translate("MainWindow", "A", None)) self.actionDeceleration.setText(_translate("MainWindow", "Decel", None)) self.actionDeceleration.setToolTip( _translate("MainWindow", "Add deceleration (D)", None)) self.actionDeceleration.setShortcut(_translate("MainWindow", "D", None)) self.actionUA.setText(_translate("MainWindow", "UA", None)) self.actionUA.setToolTip( _translate("MainWindow", "Add uterine contraction (U)", None)) self.actionUA.setShortcut(_translate("MainWindow", "U", None)) self.actionCaliper.setText(_translate("MainWindow", "Caliper", None)) self.actionCaliper.setToolTip( _translate("MainWindow", "Caliper (C)", None)) self.actionCaliper.setShortcut(_translate("MainWindow", "C", None)) self.actionCaliperFHR.setText(_translate("MainWindow", "FHR", None)) self.actionCaliperFHR.setToolTip( _translate("MainWindow", "Enable caliper FHR", None)) self.actionCaliperTOCO.setText(_translate("MainWindow", "TOCO", None)) self.actionCaliperTOCO.setToolTip( _translate("MainWindow", "Enable caliper TOCO", None)) self.actionFIGO_acc_dec.setText( _translate("MainWindow", "FIGO acc/dec", None)) self.actionFIGO_acc_dec.setToolTip( _translate("MainWindow", "FIGO requirements for acc/dec", None)) self.actionFIGO_UA.setText(_translate("MainWindow", "FIGO UA", None)) self.actionFIGO_UA.setToolTip( _translate("MainWindow", "Requirements for uterine contractions", None)) self.actionCaliperReset.setText( _translate("MainWindow", "Reset caliper", None)) self.actionCaliperReset.setToolTip( _translate("MainWindow", "Reset caliper settings", None)) self.actionAnnShowHide.setText( _translate("MainWindow", "Show/hide", None)) self.actionAnnShowHide.setToolTip( _translate("MainWindow", "Show/hide annotations", None)) self.actionDebug_CalibSignal.setText( _translate("MainWindow", "Plot calibration signal", None)) self.actionDebug_CalibSignal.setToolTip( _translate("MainWindow", "Plot calibration signal", None)) self.actionEvaluationNote.setText( _translate("MainWindow", "Evaluation", None)) self.actionEvaluationNote.setToolTip( _translate( "MainWindow", "Evaluation (Initial CTG, level of concern, intervention, pH)", None)) self.actionEvaluationNote.setShortcut( _translate("MainWindow", "E", None))
class CentralWidget(QtWidgets.QWidget): def __init__(self): super().__init__() # widgets self.video_window=VideoWindow(PixelPermm = 314) self.fps=None #fps for saving self.xplot = PlotWidget('X displacement', label = 'X',color ='r') self.yplot = PlotWidget('Y displacement', label = 'Y',color ='g') self.zplot = PlotWidget('Z displacement', label = 'Z',color =(50, 100, 255)) self.plot3D_widget = plot3D_widget() self.AnalysisWidget = AnalysisWidget() # controller self.video_saver=VideoSaver() self.isImageSaver=False #True: image_saver will be chose in place of video saver self.csv_reader=CSV_Reader(flip_z = False) #---------------------------------------------------------------------- # Toggle Comment/Uncomment to turn Z-plot ON and OFF #---------------------------------------------------------------------- # VERTICAL LAYOUT ON THE LEFT v_left_layout=QtGui.QVBoxLayout() v_left_layout.addWidget(self.video_window) v_right_layout = QtGui.QVBoxLayout() v_right_layout.addWidget(self.plot3D_widget) # Comment/Uncomment below to remove the image analysis widget v_right_layout.addWidget(self.AnalysisWidget) # v_right_layout=QtGui.QVBoxLayout() # v_right_layout.addWidget(self.xplot) # v_right_layout.addWidget(self.yplot) # v_right_layout.addWidget(self.zplot) # v_right_layout.setStretchFactor(self.xplot,1) # v_right_layout.setStretchFactor(self.yplot,1) # v_right_layout.setStretchFactor(self.zplot,1) h_layout = QtGui.QHBoxLayout() h_layout.addLayout(v_left_layout) # h_layout.addLayout(v_right_layout) h_layout.addLayout(v_right_layout) # h_layout.addLayout(v_layout) # h_layout.addLayout(plot3D_layout) h_layout.setStretchFactor(v_left_layout,1) # h_layout.setStretchFactor(v_right_layout,1) h_layout.setStretchFactor(v_right_layout,1) # Final action # self.setLayout(v_layout) self.setLayout(h_layout) def update_recording_fps(self,fps): self.fps=np.round(fps,2) def record_change(self,isRecording): self.isRecording=isRecording if isRecording: options_recording = options_Recording() options_recording.recording_instructions.connect(self.create_video) options_recording.exec_() else: self.terminate_video() def create_video(self,recording_instructions): self.folder_path=recording_instructions.folder_path print(self.folder_path) self.quality=recording_instructions.quality print(self.quality) self.isImageSaver=recording_instructions.isImageSaver print(self.isImageSaver) if self.isImageSaver: self.image_saver.start(self.folder_path,self.fps) else: self.video_saver.start(self.folder_path,self.fps) def add_frame(self,img, image_name): #img is the trigger for adding a new image print('try add frame') plotx=self.xplot.export_plot(self.quality) ploty=self.yplot.export_plot(self.quality) plotz=self.zplot.export_plot(self.quality) print('try 2') plot3d=self.plot3D_widget.plot3D.export_plot(self.quality) print('koik') if self.isImageSaver: self.image_saver.register(image_name, img,plotx,ploty,plotz,plot3d) else: self.video_saver.register(img,plotx,ploty,plotz,plot3d) print('images added') def add_name(self,imgName): if self.isImageSaver: self.image_saver.register_name(imgName) def terminate_video(self): if self.isImageSaver: self.image_saver.wait() #all element in the queue should be processed self.image_saver.stop() #release the video else: self.image_saver.wait() #all element in the queue should be processed self.video_saver.stop() #release the video def connect_all(self): self.csv_reader.Time_data.connect(self.xplot.update_Time) self.csv_reader.Time_data.connect(self.yplot.update_Time) self.csv_reader.Time_data.connect(self.zplot.update_Time) self.csv_reader.Xobj_data.connect(self.xplot.update_plot) self.csv_reader.Yobj_data.connect(self.yplot.update_plot) self.csv_reader.Zobj_data.connect(self.zplot.update_plot) self.csv_reader.fps_data.connect(self.update_recording_fps) self.csv_reader.Time_data.connect(self.plot3D_widget.plot3D.update_Time) self.csv_reader.Xobj_data.connect(self.plot3D_widget.plot3D.update_X) self.csv_reader.Yobj_data.connect(self.plot3D_widget.plot3D.update_Y) self.csv_reader.Zobj_data.connect(self.plot3D_widget.plot3D.update_Z) self.csv_reader.ImageTime_data.connect(self.video_window.initialize_image_time) self.csv_reader.ObjLoc_data.connect(self.video_window.initialize_obj_centroids) self.csv_reader.ImageNames_data.connect(self.video_window.initialize_image_names) # Added Image Index as another connection # self.csv_reader.ImageIndex_data.connect(self.video_window.initialize_image_index) self.video_window.update_plot.connect(self.xplot.update_cursor) self.video_window.update_plot.connect(self.yplot.update_cursor) self.video_window.update_plot.connect(self.zplot.update_cursor) self.video_window.update_3Dplot.connect(self.plot3D_widget.plot3D.move_marker) self.video_window.record_signal.connect(self.record_change) self.video_window.image_to_record.connect(self.add_frame) self.video_window.imageName.connect(self.add_name) # Image analysis widget connections self.AnalysisWidget.show_roi.connect(self.video_window.toggle_ROI_show) self.video_window.roi_pos_signal.connect(self.AnalysisWidget.update_pos_display) self.video_window.roi_size_signal.connect(self.AnalysisWidget.update_size_display) # metadata self.csv_reader.pixelpermm_data.connect(self.video_window.update_pixelsize)
class Data_Dialog(QDialog): def __init__(self, fname=None, data=None, comment='#', skiprows=0, delimiter=' ', expressions={}, autoupdate=False, parent=None, matplotlib=False, plotIndex=None, colors=None): QDialog.__init__(self, parent=parent) loadUi('UI_Forms/Data_Dialog.ui', self) self.colcycler = cycle(['r', 'g', 'b', 'c', 'm', 'y', 'w']) self.plotWidget = PlotWidget(parent=self, matplotlib=matplotlib) self.plotTab = self.tabWidget.addTab(self.plotWidget, 'Plots') self.tabWidget.setCurrentIndex(0) self.show() self.fileWatcher = QFileSystemWatcher() self.fileWatcher.fileChanged.connect(self.fileUpdated) self.cwd = None self.plotNum = 0 self.xlabel = [] self.ylabel = [] self.oldPlotIndex = {} self.oldColors = {} self.dataAltered = False self.expressions = expressions if data is not None: self.data = data self.autoUpdateCheckBox.setEnabled(False) elif fname is not None: self.data = self.readData(fname, comment=comment, skiprows=skiprows, delimiter=delimiter) else: self.data = None self.autoUpdateCheckBox.setEnabled(False) self.saveDataPushButton.setEnabled(False) self.addRowPushButton.setEnabled(False) self.removeRowsPushButton.setEnabled(False) self.removeColumnPushButton.setEnabled(False) if self.data is not None: self.setMeta2Table() self.setData2Table() if plotIndex is None: self.addPlots(color=None) else: self.addMultiPlots(plotIndex=plotIndex, colors=colors) self.init_signals() self.okPushButton.setAutoDefault(False) self.make_default() self.setWindowTitle('Data Dialog') self.acceptData = True #self.setWindowSize((600,400)) # if self.parentWidget() is not None: # self.addPlotPushButton.setEnabled(False) # self.removePlotPushButton.setEnabled(False) def make_default(self): self.okPushButton.setAutoDefault(False) self.closePushButton.setAutoDefault(False) self.openDataFilePushButton.setAutoDefault(False) self.saveDataPushButton.setAutoDefault(False) self.okPushButton.setDefault(False) self.closePushButton.setDefault(False) self.openDataFilePushButton.setDefault(False) self.saveDataPushButton.setDefault(False) def init_signals(self): self.closePushButton.clicked.connect(self.closeWidget) self.okPushButton.clicked.connect(self.acceptWidget) self.openDataFilePushButton.clicked.connect(self.openFile) self.autoUpdateCheckBox.stateChanged.connect(self.autoUpdate_ON_OFF) self.saveDataPushButton.clicked.connect(self.saveData) self.addPlotPushButton.clicked.connect( lambda x: self.addPlots(plotIndex=None)) self.plotSetupTableWidget.cellChanged.connect(self.updatePlotData) self.removePlotPushButton.clicked.connect(self.removePlots) self.addMetaDataPushButton.clicked.connect(self.addMetaData) self.metaDataTableWidget.itemChanged.connect(self.metaDataChanged) self.metaDataTableWidget.itemClicked.connect(self.metaDataClicked) self.metaDataTableWidget.itemSelectionChanged.connect( self.metaDataSelectionChanged) self.removeMetaDataPushButton.clicked.connect(self.removeMetaData) self.dataTableWidget.itemChanged.connect(self.dataChanged) self.editColumnPushButton.clicked.connect(self.editDataColumn) self.addColumnPushButton.clicked.connect( lambda x: self.addDataColumn(colName='Col_X')) self.removeColumnPushButton.clicked.connect(self.removeDataColumn) self.removeRowsPushButton.clicked.connect(self.removeDataRows) self.dataTableWidget.setSelection self.dataTableWidget.horizontalHeader().sortIndicatorChanged.connect( self.dataSorted) self.addRowPushButton.clicked.connect(self.addDataRow) def closeWidget(self): self.acceptData = False self.reject() def acceptWidget(self): self.acceptData = True self.accept() def addMetaData(self): """ Opens a MetaData Dialog and by accepting the dialog inputs the data to the MetaDataTable """ self.metaDialog = MetaData_Dialog() if self.metaDialog.exec_(): name, value = self.metaDialog.parNameLineEdit.text( ), self.metaDialog.parValueLineEdit.text() if name not in self.data['meta'].keys(): row = self.metaDataTableWidget.rowCount() self.metaDataTableWidget.insertRow(row) self.metaDataTableWidget.setItem(row, 0, QTableWidgetItem(name)) self.metaDataTableWidget.setItem(row, 1, QTableWidgetItem(value)) try: self.data['meta'][name] = eval(value) except: self.data['meta'][name] = value else: QMessageBox.warning( self, "Parameter Exists", "The parameter %s already exists in meta data. Please provide a different parameter name" % name, QMessageBox.Ok) self.addMetaData() def removeMetaData(self): """ Removes the selected Metadata from the table """ self.metaDataTableWidget.itemSelectionChanged.disconnect() rows = list( set([ item.row() for item in self.metaDataTableWidget.selectedItems() ])) for row in rows: key = self.metaDataTableWidget.item(row, 0).text() if key != 'col_names': del self.data['meta'][key] self.metaDataTableWidget.removeRow(row) else: QMessageBox.warning(self, 'Restricted Parameter', 'You cannot delete the parameter %s' % key, QMessageBox.Ok) self.metaDataTableWidget.itemSelectionChanged.connect( self.metaDataSelectionChanged) def metaDataChanged(self, item): """ Updates the value metadata as per the changes in the metaDataTableWidget """ row = item.row() col = item.column() key = self.metaDataTableWidget.item(row, 0).text() if col != 0: try: self.data['meta'][key] = eval(item.text()) except: self.data['meta'][key] = item.text() if self.metaDataTableWidget.item( row, 0).text() == 'col_names' and len( self.data['meta'][key]) != len( self.data['data'].columns): QMessageBox.warning( self, 'Restricted Parameter', 'Please provide same length of col_names as the number of the column of the data' ) self.data['meta'][key] = eval(self.oldMetaText) item.setText(self.oldMetaText) elif self.metaDataTableWidget.item( row, 0).text() == 'col_names' and len( self.data['meta'][key]) == len( self.data['data'].columns): self.data['data'].columns = self.data['meta'][key] self.dataTableWidget.setHorizontalHeaderLabels( self.data['meta'][key]) self.dataAltered = True self.resetPlotSetup() self.dataAltered = False else: if self.oldMetaText == 'col_names': QMessageBox.warning( self, 'Restricted Parameter', 'col_names is a restricted parameter the name of which cannot be changed', QMessageBox.Ok) item.setText(self.oldMetaText) elif item.text() not in self.data['meta'].keys(): self.data['meta'][key] = self.data['meta'][self.oldMetaText] del self.data['meta'][self.oldMetaText] else: self.metaDataTableWidget.itemChanged.disconnect() QMessageBox.warning( self, "Parameter Exists", "The parameter %s already exists in meta data. Please provide a different parameter name" % item.text(), QMessageBox.Ok) item.setText(self.oldMetaText) self.metaDataTableWidget.itemChanged.connect( self.metaDataChanged) self.oldMetaText = item.text() def metaDataClicked(self, item): self.oldMetaText = item.text() def metaDataSelectionChanged(self): self.oldMetaText = self.metaDataTableWidget.selectedItems()[0].text() def dataChanged(self, item): row, col = item.row(), item.column() key = self.dataTableWidget.horizontalHeaderItem(col).text() self.data['data'][key][row] = eval(item.text()) self.dataAltered = True self.resetPlotSetup() self.dataAltered = False def dataSorted(self): """ Updates the data after sorting the DataTableWidget """ self.getDataFromTable() self.dataAltered = True self.resetPlotSetup() self.dataAltered = False def addDataRow(self): try: self.dataTableWidget.itemChanged.disconnect() except: pass row = self.dataTableWidget.currentRow() self.dataTableWidget.insertRow(row + 1) for col in range(self.dataTableWidget.columnCount()): self.dataTableWidget.setItem( row + 1, col, QCustomTableWidgetItem( float(self.dataTableWidget.item(row, col).text()))) self.getDataFromTable() self.dataAltered = True self.resetPlotSetup() self.dataAltered = False self.dataTableWidget.itemChanged.connect(self.dataChanged) def editDataColumn(self): if self.data is not None: items = self.dataTableWidget.selectedItems() selCols = list([item.column() for item in items]) if len(selCols) == 1: colName = self.dataTableWidget.horizontalHeaderItem( selCols[0]).text() self.addDataColumn(colName=colName, expr=self.expressions[colName], new=False) else: QMessageBox.warning( self, 'Column Selection Error', 'Please select only elements of a single column.', QMessageBox.Ok) else: QMessageBox.warning(self, 'Data error', 'There is no data', QMessageBox.Ok) def addDataColumn(self, colName='Col_X', expr=None, new=True): if self.data is not None: row, col = self.data['data'].shape self.insertColDialog = InsertCol_Dialog(colName=colName, minCounter=1, maxCounter=row, expr=expr) if self.insertColDialog.exec_(): imin = eval(self.insertColDialog.minCounterLineEdit.text()) imax = eval(self.insertColDialog.maxCounterLineEdit.text()) i = arange(imin, imax + 1) colname = self.insertColDialog.colNameLineEdit.text() data = copy.copy(self.data) if new: if colname not in self.data['data'].columns: try: self.data['data'][colname] = eval(expr) except: try: expr = self.insertColDialog.colExprTextEdit.toPlainText( ) cexpr = expr.replace('col', "self.data['data']") self.data['data'][colname] = eval(cexpr) self.data['meta']['col_names'].append(colname) except: QMessageBox.warning( self, 'Column Error', 'Please check the expression.\n The expression should be in this format:\n col[column_name]*5', QMessageBox.Ok) self.addDataColumn(colName='Col_X', expr=expr) self.expressions[colname] = expr self.setData2Table() self.setMeta2Table() self.dataAltered = True self.resetPlotSetup() self.dataAltered = False else: QMessageBox.warning( self, 'Column Name Error', 'Please choose different column name than the exisiting ones', QMessageBox.Ok) self.addDataColumn(colName='Col_X', expr=expr) else: try: self.data['data'][colname] = eval(expr) except: try: expr = self.insertColDialog.colExprTextEdit.toPlainText( ) cexpr = expr.replace('col', "self.data['data\']") self.data['data'][colname] = eval(cexpr) except: QMessageBox.warning( self, 'Column Error', 'Please check the expression.\n The expression should be in this format:\n col[column_name]*5', QMessageBox.Ok) self.addDataColumn(colName='Col_X', expr=expr) self.expressions[colname] = expr self.setData2Table() self.setMeta2Table() self.dataAltered = True self.resetPlotSetup() self.dataAltered = False else: self.data = {} self.insertColDialog = InsertCol_Dialog(colName=colName, minCounter=1, maxCounter=100, expr=expr) if self.insertColDialog.exec_(): imin = eval(self.insertColDialog.minCounterLineEdit.text()) imax = eval(self.insertColDialog.maxCounterLineEdit.text()) i = arange(imin, imax + 1) colname = self.insertColDialog.colNameLineEdit.text() expr = self.insertColDialog.colExprTextEdit.toPlainText() expr = expr.replace('col.', "self.data['data']") try: self.data['data'] = pd.DataFrame(eval(expr), columns=[colname]) self.data['meta'] = {} self.data['meta']['col_names'] = [colname] self.setData2Table() self.setMeta2Table() self.dataAltered = True self.resetPlotSetup() self.dataAltered = False self.saveDataPushButton.setEnabled(True) self.addRowPushButton.setEnabled(True) self.removeRowsPushButton.setEnabled(True) self.removeColumnPushButton.setEnabled(True) self.expressions[colname] = expr except: QMessageBox.warning( self, 'Column Error', 'Please check the expression.\n The expression should be in this format:\n col.column_name*5', QMessageBox.Ok) self.data = None self.addDataColumn(colName='Col_X', expr=expr) def removeDataColumn(self): """ Removes selected columns from dataTableWidget """ colIndexes = [ index.column() for index in self.dataTableWidget.selectionModel().selectedColumns() ] colIndexes.sort(reverse=True) if self.dataTableWidget.columnCount() - len( colIndexes) >= 2 or self.plotSetupTableWidget.rowCount() == 0: for index in colIndexes: colname = self.data['meta']['col_names'][index] self.data['meta']['col_names'].pop(index) del self.expressions[colname] self.dataTableWidget.removeColumn(index) if self.dataTableWidget.columnCount() != 0: self.getDataFromTable() self.setMeta2Table() self.dataAltered = True self.resetPlotSetup() self.dataAltered = False else: self.data['data'] = None self.dataTableWidget.clear() #self.metaDataTableWidget.clear() self.autoUpdateCheckBox.setEnabled(False) self.saveDataPushButton.setEnabled(False) self.addRowPushButton.setEnabled(False) self.removeRowsPushButton.setEnabled(False) self.removeColumnPushButton.setEnabled(False) else: QMessageBox.warning( self, 'Remove Error', 'Cannot remove these many columns because Data Dialog needs to have atleast two columns', QMessageBox.Ok) def removeDataRows(self): rowIndexes = [ index.row() for index in self.dataTableWidget.selectionModel().selectedRows() ] rowIndexes.sort(reverse=True) if len(rowIndexes) > 0: ans = QMessageBox.question( self, 'Confirmation', 'Are you sure of removing the selected rows?', QMessageBox.Yes, QMessageBox.No) if ans == QMessageBox.Yes: for i in rowIndexes: self.dataTableWidget.removeRow(i) self.getDataFromTable() self.dataAltered = True self.resetPlotSetup() self.dataAltered = False def setMeta2Table(self): """ Populates the metaDataTable widget with metadata available from the data """ try: self.metaDataTableWidget.itemChanged.disconnect() self.metaDataTableWidget.itemSelectionChanged.disconnect() except: pass self.metaDataTableWidget.clear() self.metaDataTableWidget.setColumnCount(2) self.metaDataTableWidget.setRowCount(len(self.data['meta'].keys())) for num, key in enumerate(self.data['meta'].keys()): self.metaDataTableWidget.setItem(num, 0, QTableWidgetItem(key)) self.metaDataTableWidget.setItem( num, 1, QTableWidgetItem(str(self.data['meta'][key]))) if 'col_names' not in self.data['meta'].keys(): self.data['meta']['col_names'] = self.data['data'].columns.tolist() self.metaDataTableWidget.insertRow( self.metaDataTableWidget.rowCount()) self.metaDataTableWidget.setItem(num + 1, 0, QTableWidgetItem('col_names')) self.metaDataTableWidget.setItem( num + 1, 1, QTableWidgetItem(str(self.data['meta']['col_names']))) self.metaDataTableWidget.setHorizontalHeaderLabels( ['Parameter', 'Value']) self.metaDataTableWidget.itemChanged.connect(self.metaDataChanged) self.metaDataTableWidget.itemSelectionChanged.connect( self.metaDataSelectionChanged) def getMetaFromTable(self): self.data['meta'] = {} for i in range(self.metaDataTableWidget.rowCount()): try: self.data['meta'][self.metaDataTableWidget.item( i, 0).text()] = eval( self.metaDataTableWidget.item(i, 1).text()) except: self.data['meta'][self.metaDataTableWidget.item( i, 0).text()] = self.metaDataTableWidget.item(i, 1).text() def setData2Table(self): """ Populates the dataTableWidget with data available from data """ try: self.dataTableWidget.itemChanged.disconnect() except: pass self.dataTableWidget.clear() self.dataTableWidget.setColumnCount(len(self.data['data'].columns)) self.dataTableWidget.setRowCount(len(self.data['data'].index)) for j, colname in enumerate(self.data['data'].columns): if colname not in self.expressions.keys(): self.expressions[colname] = "col['%s']" % colname for i in range(len(self.data['data'].index)): #self.dataTableWidget.setItem(i,j,QTableWidgetItem(str(self.data['data'][colname][i]))) self.dataTableWidget.setItem( i, j, QCustomTableWidgetItem(self.data['data'][colname][i])) self.dataTableWidget.setHorizontalHeaderLabels( self.data['data'].columns.values.tolist()) self.dataTableWidget.itemChanged.connect(self.dataChanged) def getDataFromTable(self): self.data['data'] = pd.DataFrame() for col in range(self.dataTableWidget.columnCount()): label = self.dataTableWidget.horizontalHeaderItem(col).text() self.data['data'][label] = array([ float(self.dataTableWidget.item(i, col).text()) for i in range(self.dataTableWidget.rowCount()) ]) def readData(self, fname, skiprows=0, comment='#', delimiter=' '): """ Read data from a file and put it in dictionary structure with keys 'meta' and 'data' and the data would look like the following data={'meta':meta_dictionary,'data'=pandas_dataframe} """ if os.path.exists(os.path.abspath(fname)): self.data = {} self.fname = fname self.dataFileLineEdit.setText(self.fname) self.cwd = os.path.dirname(self.fname) fh = open(os.path.abspath(self.fname), 'r') lines = fh.readlines() fh.close() self.data['meta'] = {} for line in lines[skiprows:]: if line[0] == comment: try: key, value = line[1:].strip().split('=') try: self.data['meta'][key] = eval( value ) # When the value is either valid number, lists, arrays, dictionaries except: self.data['meta'][ key] = value # When the value is just a string except: pass else: if '\t' in line: delimiter = '\t' elif ',' in line: delimiter = ',' elif ' ' in line: delimiter = ' ' break if 'col_names' in self.data['meta'].keys(): self.data['data'] = pd.read_csv( self.fname, comment=comment, names=self.data['meta']['col_names'], header=None, sep=delimiter) if not all(self.data['data'].isnull().values): self.data['data'] = pd.DataFrame( loadtxt(self.fname, skiprows=skiprows), columns=self.data['meta']['col_names']) else: self.data['data'] = pd.read_csv(self.fname, comment=comment, header=None, sep=delimiter) if not all(self.data['data'].isnull()): self.data['data'] = pd.DataFrame( loadtxt(self.fname, skiprows=skiprows)) self.data['data'].columns = [ 'Col_%d' % i for i in self.data['data'].columns.values.tolist() ] self.data['meta']['col_names'] = self.data[ 'data'].columns.values.tolist() self.autoUpdate_ON_OFF() self.autoUpdateCheckBox.setEnabled(True) self.saveDataPushButton.setEnabled(True) self.addRowPushButton.setEnabled(True) self.removeRowsPushButton.setEnabled(True) self.removeColumnPushButton.setEnabled(True) return self.data else: QMessageBox.warning(self, 'File Error', 'The file doesnot exists!') return None def fileUpdated(self, fname): QTest.qWait(1000) self.readData(fname=fname) if self.data is not None: self.setMeta2Table() self.setData2Table() self.dataAltered = True self.resetPlotSetup() self.dataAltered = False def autoUpdate_ON_OFF(self): files = self.fileWatcher.files() if len(files) != 0: self.fileWatcher.removePaths(files) if self.autoUpdateCheckBox.isChecked(): self.fileWatcher.addPath(self.fname) def saveData(self): """ Save data to a file """ fname = QFileDialog.getSaveFileName(self, 'Save file as', self.cwd, filter='*.*')[0] if fname != '': ext = os.path.splitext(fname)[1] if ext == '': ext = '.txt' fname = fname + ext header = 'File saved on %s\n' % time.asctime() for key in self.data['meta'].keys(): header = header + '%s=%s\n' % (key, str( self.data['meta'][key])) if 'col_names' not in self.data['meta'].keys(): header = header + 'col_names=%s\n' % str( self.data['data'].columns.tolist()) savetxt(fname, self.data['data'].values, header=header, comments='#') def openFile(self): """ Opens a openFileDialog to open a data file """ if self.cwd is not None: fname = QFileDialog.getOpenFileName(self, 'Select a data file to open', directory=self.cwd, filter='*.*')[0] else: fname = QFileDialog.getOpenFileName(self, 'Select a data file to open', directory='', filter='*.*')[0] if fname != '': self.data = self.readData(fname=fname) if self.data is not None: self.setMeta2Table() self.setData2Table() self.dataAltered = True self.resetPlotSetup() self.dataAltered = False def resetPlotSetup(self): try: self.plotSetupTableWidget.cellChanged.disconnect() except: pass columns = self.data['data'].columns.tolist() self.xlabel = [] self.ylabel = [] for row in range(self.plotSetupTableWidget.rowCount()): for i in range(1, 3): self.plotSetupTableWidget.cellWidget( row, i).currentIndexChanged.disconnect() self.plotSetupTableWidget.cellWidget(row, i).clear() self.plotSetupTableWidget.cellWidget(row, i).addItems(columns) self.plotSetupTableWidget.cellWidget(row, i).setCurrentIndex(i - 1) self.plotSetupTableWidget.cellWidget( row, i).currentIndexChanged.connect(self.updateCellData) self.xlabel.append( '[%s]' % self.plotSetupTableWidget.cellWidget(row, 1).currentText()) self.ylabel.append( '[%s]' % self.plotSetupTableWidget.cellWidget(row, 2).currentText()) self.plotSetupTableWidget.cellWidget( row, 3).currentIndexChanged.disconnect() self.plotSetupTableWidget.cellWidget(row, 3).clear() self.plotSetupTableWidget.cellWidget(row, 3).addItems(['None'] + columns) self.plotSetupTableWidget.cellWidget(row, 3).setCurrentIndex(0) self.plotSetupTableWidget.cellWidget( row, 3).currentIndexChanged.connect(self.updateCellData) self.plotSetupTableWidget.setCurrentCell(row, 3) color = self.plotSetupTableWidget.cellWidget(row, 4).color() self.plotSetupTableWidget.setCellWidget( row, 4, pg.ColorButton(color=color)) self.plotSetupTableWidget.cellWidget( row, 4).sigColorChanging.connect(self.updateCellData) self.plotSetupTableWidget.cellWidget( row, 4).sigColorChanged.connect(self.updateCellData) self.updatePlotData(row, i) self.plotSetupTableWidget.cellChanged.connect(self.updatePlotData) def addMultiPlots(self, plotIndex=None, colors=None): for key in plotIndex.keys(): pi = plotIndex[key] if colors is None: color = next(self.colcycler ) #array([random.randint(200, high=255),0,0]) print(color) else: color = colors[key] self.addPlots(plotIndex=pi, color=color) def addPlots(self, plotIndex=None, color=None): #self.plotSetupTableWidget.clear() # if self.parentWidget() is None or self.plotSetupTableWidget.rowCount()==0: try: self.plotSetupTableWidget.cellChanged.disconnect() except: pass columns = self.data['data'].columns.tolist() if len(columns) >= 2: self.plotSetupTableWidget.insertRow( self.plotSetupTableWidget.rowCount()) row = self.plotSetupTableWidget.rowCount() - 1 self.plotSetupTableWidget.setItem( row, 0, QTableWidgetItem('Data_%d' % self.plotNum)) for i in range(1, 3): self.plotSetupTableWidget.setCellWidget(row, i, QComboBox()) self.plotSetupTableWidget.cellWidget(row, i).addItems(columns) if plotIndex is not None: self.plotSetupTableWidget.cellWidget( row, i).setCurrentIndex(plotIndex[i - 1]) else: self.plotSetupTableWidget.cellWidget( row, i).setCurrentIndex(i - 1) self.plotSetupTableWidget.cellWidget( row, i).currentIndexChanged.connect(self.updateCellData) self.xlabel.append( '[%s]' % self.plotSetupTableWidget.cellWidget(row, 1).currentText()) self.ylabel.append( '[%s]' % self.plotSetupTableWidget.cellWidget(row, 2).currentText()) self.plotSetupTableWidget.setCellWidget(row, 3, QComboBox()) self.plotSetupTableWidget.cellWidget(row, 3).addItems(['None'] + columns) if color is None: color = next(self.colcycler ) #array([random.randint(200, high=255),0,0]) self.plotSetupTableWidget.setCellWidget( row, 4, pg.ColorButton(color=color)) self.plotSetupTableWidget.cellWidget( row, 4).sigColorChanging.connect(self.updateCellData) self.plotSetupTableWidget.cellWidget( row, 4).sigColorChanged.connect(self.updateCellData) if plotIndex is not None: self.plotSetupTableWidget.cellWidget(row, 3).setCurrentIndex( plotIndex[-1]) else: # try: # self.plotSetupTableWidget.cellWidget(row,3).setCurrentIndex(2) # except: # self.plotSetupTableWidget.cellWidget(row, 3).setCurrentIndex(0) self.plotSetupTableWidget.cellWidget( row, 3).currentIndexChanged.connect(self.updateCellData) self.plotSetupTableWidget.setCurrentCell(row, 3) self.updatePlotData(row, 3) self.plotNum += 1 else: QMessageBox.warning( self, 'Data file error', 'The data file do not have two or more columns to be plotted.', QMessageBox.Ok) self.plotSetupTableWidget.cellChanged.connect(self.updatePlotData) # else: # QMessageBox.warning(self,'Warning','As the Data Dialog is used within another widget you cannot add more plots',QMessageBox.Ok) def removePlots(self): """ Removes data for PlotSetup """ try: self.plotSetupTableWidget.cellChanged.disconnect() except: pass rowIndexes = self.plotSetupTableWidget.selectionModel().selectedRows() selectedRows = [index.row() for index in rowIndexes] selectedRows.sort(reverse=True) if self.parentWidget() is None: for row in selectedRows: name = self.plotSetupTableWidget.item(row, 0).text() self.plotWidget.remove_data([name]) self.plotSetupTableWidget.removeRow(row) else: if self.plotSetupTableWidget.rowCount() - len(rowIndexes) >= 1: for row in selectedRows: name = self.plotSetupTableWidget.item(row, 0).text() self.plotWidget.remove_data([name]) self.plotSetupTableWidget.removeRow(row) else: QMessageBox.warning( self, 'Warning', 'Cannot remove single plots from Data Dialog because the Data Dialog is used within another widget', QMessageBox.Ok) self.updatePlot() self.plotSetupTableWidget.cellChanged.connect(self.updatePlotData) def updatePlotData(self, row, col): #row=self.plotSetupTableWidget.currentRow() name = self.plotSetupTableWidget.item(row, 0).text() if self.dataAltered: for i in range(1, 4): try: self.plotSetupTableWidget.cellWidget( row, i).setCurrentIndex(self.oldPlotIndex[name][i - 1]) except: pass xcol, ycol, yerrcol = [ self.plotSetupTableWidget.cellWidget(row, i).currentText() for i in range(1, 4) ] #ycol=self.plotSetupTableWidget.cellWidget(row,2).currentText() #yerrcol=self.plotSetupTableWidget.cellWidget(row,3).currentText() if yerrcol != 'None': if ycol == 'fit': self.plotWidget.add_data( self.data['data'][xcol].values, self.data['data'][ycol].values, yerr=self.data['data'][yerrcol].values, name=name, fit=True, color=self.plotSetupTableWidget.cellWidget(row, 4).color()) else: self.plotWidget.add_data( self.data['data'][xcol].values, self.data['data'][ycol].values, yerr=self.data['data'][yerrcol].values, name=name, fit=False, color=self.plotSetupTableWidget.cellWidget(row, 4).color()) else: if ycol == 'fit': self.plotWidget.add_data( self.data['data'][xcol].values, self.data['data'][ycol].values, name=name, fit=True, color=self.plotSetupTableWidget.cellWidget(row, 4).color()) else: self.plotWidget.add_data( self.data['data'][xcol].values, self.data['data'][ycol].values, name=name, fit=False, color=self.plotSetupTableWidget.cellWidget(row, 4).color()) self.xlabel[row] = '[%s]' % self.plotSetupTableWidget.cellWidget( row, 1).currentText() self.ylabel[row] = '[%s]' % self.plotSetupTableWidget.cellWidget( row, 2).currentText() self.updatePlot() self.oldPlotIndex[name] = [ self.plotSetupTableWidget.cellWidget(row, i).currentIndex() for i in range(1, 4) ] def updateCellData(self, index): row = self.plotSetupTableWidget.indexAt(self.sender().pos()).row() self.updatePlotData(row, index) def updatePlot(self): self.make_default() names = [ self.plotSetupTableWidget.item(i, 0).text() for i in range(self.plotSetupTableWidget.rowCount()) ] #self.plotColIndex=[self.plotSetupTableWidget.cellWidget(0,i).currentIndex() for i in range(1,4)] self.plotColIndex = {} self.externalData = {} self.plotColors = {} for i in range(self.plotSetupTableWidget.rowCount()): key = self.plotSetupTableWidget.cellWidget(i, 2).currentText() self.plotColIndex[key] = [ self.plotSetupTableWidget.cellWidget(i, j).currentIndex() for j in range(1, 4) ] self.plotColors[key] = self.plotSetupTableWidget.cellWidget( i, 4).color() self.externalData[key] = copy.copy(self.data['meta']) self.externalData[key]['x'] = copy.copy( self.data['data'][self.plotSetupTableWidget.cellWidget( i, 1).currentText()].values) self.externalData[key]['y'] = copy.copy( self.data['data'][self.plotSetupTableWidget.cellWidget( i, 2).currentText()].values) if self.plotSetupTableWidget.cellWidget(i, 3).currentText() == 'None': self.externalData[key]['yerr'] = ones_like( self.externalData[key]['x']) else: self.externalData[key]['yerr'] = copy.copy( self.data['data'][self.plotSetupTableWidget.cellWidget( i, 3).currentText()].values) self.externalData[key][ 'color'] = self.plotSetupTableWidget.cellWidget(i, 4).color() self.plotWidget.Plot(names) self.plotWidget.setXLabel(' '.join(self.xlabel)) self.plotWidget.setYLabel(' '.join(self.ylabel))
class MainWindow(QMainWindow): __PREF_GEOM__ = "UI/Geometry" __PREF_STATE__ = "UI/State" __PREF_DIR__ = "Config/Directories" __PREF_SAVE__ = "Config/SaveDirectory" __PREF_SAVE_ALL__ = "Config/SaveAllDirectory" def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.analyzer = Analyzer() self.currentSolution = None self._buildUI() self._loadSettings() QTimer.singleShot(0, self._loadInitialData) def _buildUI(self): self.setWindowTitle("MOOI: Multi-Objective Optimization Interface") self.resize(840, 480) self.statusBar().setSizeGripEnabled(False) self.statusBar().showMessage("Loading initial data...") # Plot widget self.plot = PlotWidget() self.plot.setMinimumSize(320, 480) self.plot.setAlignment(Qt.AlignCenter) self.plot.setContextMenuPolicy(Qt.ActionsContextMenu) self.setCentralWidget(self.plot) # Function widget self.functionWidget = QListWidget() self.functionWidget.itemSelectionChanged.connect(self.solutionSelected) rightDock = QDockWidget("Functions", self) rightDock.setObjectName("Functions") rightDock.setWidget(self.functionWidget) rightDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.addDockWidget(Qt.RightDockWidgetArea, rightDock) # Control widget self.showSolutionsRadio = QRadioButton("Functions") self.showSolutionsRadio.setChecked(True) self.showSolutionsRadio.toggled.connect(self._showSolution) self.showVariablesRadio = QRadioButton("Variables") radioWidget = QWidget() radioLayout = QHBoxLayout() radioLayout.addWidget(self.showSolutionsRadio) radioLayout.addWidget(self.showVariablesRadio) radioWidget.setLayout(radioLayout) self.generationLabel = QLabel("Run: 1") self.generationSlider = QSlider(Qt.Horizontal) self.generationSlider.setTickPosition(QSlider.TicksBothSides) self.generationSlider.setTracking(True) self.generationSlider.setMinimum(1) self.generationSlider.setMaximum(1) self.generationSlider.setTickInterval(1) self.generationSlider.valueChanged.connect(self._showSolution) self.solutionSelector = QWidget() self.solutionSelector.setLayout(QVBoxLayout()) addSolutionButton = QPushButton("Add") addSolutionButton.clicked.connect(self.addImplementation) removeSolutionButton = QPushButton("Remove unselected") removeSolutionButton.clicked.connect(self.removeResult) solutionSelectorButtons = QWidget() solutionSelectorButtons.setLayout(QHBoxLayout()) solutionSelectorButtons.layout().addWidget(addSolutionButton) solutionSelectorButtons.layout().addWidget(removeSolutionButton) self.solutionSelectorWidget = QWidget() self.solutionSelectorWidget.setLayout(QVBoxLayout()) self.solutionSelectorWidget.layout().addWidget(solutionSelectorButtons) self.solutionSelectorWidget.layout().addWidget(self.solutionSelector) exportButton = QPushButton("Export image") exportButton.clicked.connect(self.exportImage) exportAllButton = QPushButton("Export all images") exportAllButton.clicked.connect(self.exportAllImages) computeMetricsButton = QPushButton("Compute metrics") computeMetricsButton.clicked.connect(self.computeMetricsAsync) refreshButton = QPushButton("Refresh") refreshButton.clicked.connect(self.updateUI) controlLayout = QVBoxLayout() controlLayout.addWidget(radioWidget) controlLayout.addWidget(self.generationLabel) controlLayout.addWidget(self.generationSlider) controlLayout.addWidget(self.solutionSelectorWidget) controlLayout.addStretch() controlLayout.addWidget(computeMetricsButton) controlLayout.addWidget(refreshButton) controlLayout.addWidget(exportButton) controlLayout.addWidget(exportAllButton) controlWidget = QWidget() controlWidget.setLayout(controlLayout) leftDock = QDockWidget("Control", self) leftDock.setObjectName("Control") leftDock.setWidget(controlWidget) leftDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.addDockWidget(Qt.LeftDockWidgetArea, leftDock) # Metric widget self.metrics = MetricsPanel(self.analyzer) bottomDock = QDockWidget("Metrics", self) bottomDock.setObjectName("Metrics") bottomDock.setWidget(self.metrics) bottomDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.addDockWidget(Qt.BottomDockWidgetArea, bottomDock) # Actions exitAction = QAction("&Exit", self) exitAction.setShortcut("Ctrl+Q") exitAction.setStatusTip("Exit application") exitAction.triggered.connect(qApp.quit) copyAction = QAction("&Copy", self) copyAction.setShortcut("Ctrl+C") copyAction.setStatusTip("Copy metrics") copyAction.triggered.connect(self.metrics.copyMetrics) aboutAction = QAction("&About", self) aboutAction.setStatusTip("About MOOI") aboutAction.triggered.connect(self.helpAbout) # Menus menubar = self.menuBar() fileMenu = menubar.addMenu("&File") fileMenu.addAction(copyAction) fileMenu.addAction(aboutAction) fileMenu.addSeparator() fileMenu.addAction(exitAction) def _loadSettings(self): settings = QSettings() self.restoreState(settings.value(MainWindow.__PREF_STATE__).toByteArray()) self.restoreGeometry(settings.value(MainWindow.__PREF_GEOM__).toByteArray()) paretoDirectory = __RESOURCES_DIR__ + Analyzer.__PARETO__ self.analyzer.setPareto(paretoDirectory) currentDirs = settings.value(MainWindow.__PREF_DIR__) if currentDirs is not None: self.analyzer.setResultDirectories([directory.toString() for directory in currentDirs.toList()]) self._updateSolutionSelection() def exportImage(self): settings = QSettings() filename = settings.value(MainWindow.__PREF_SAVE__) if filename is None: filename = os.path.dirname(__file__) else: filename = os.path.abspath(os.path.join(str(filename.toString()), os.path.pardir)) + "/" filename += "%s_%s.png" % ( self.currentSolution.functionName, "fun" if self.isFunctionSpaceSelected() else "var", ) filename = QFileDialog.getSaveFileName(self, "Export image as", filename, ("PNG image (*.png)")) if filename is None or filename == "": return settings.setValue(MainWindow.__PREF_SAVE__, QVariant(filename)) self._exportCurrentImage(filename) self.statusBar().showMessage("Image saved!", 5000) def isFunctionSpaceSelected(self): return self.showSolutionsRadio.isChecked() def _exportCurrentImage(self, filename=None): generation = self.generationSlider.value() self.generationLabel.setText("Run: %d" % generation) tmp = filename is None if tmp: prefix = "mooi_%s_" % self.currentSolution.functionName filename = tempfile.mkstemp(prefix=prefix, suffix=".png", text=False)[1] resultNames = self._getSelectedResultNames() self.analyzer.exportToImage( self.currentSolution, [generation - 1] * len(resultNames), self.isFunctionSpaceSelected(), resultNames, str(filename), ) if tmp: self.plot.setPlotPixmap(filename) try: os.remove(filename) except: print >>sys.stderr, "Couldn't delete temporal file: %s" % filename def _getSelectedResultNames(self): resultNames = [] for i in xrange(self.analyzer.nResults): implementationItem = self.solutionSelector.layout().itemAt(i).widget() if implementationItem.isChecked(): resultNames.append(str(implementationItem.text())) return resultNames def exportAllImages(self): settings = QSettings() directory = settings.value(MainWindow.__PREF_SAVE_ALL__).toString() directory = QFileDialog.getExistingDirectory(self, "Select a directory to export to", directory) if directory is None or not os.path.exists(directory): return self.analyzer.exportAllImages(directory, self._getSelectedResultNames()) settings.setValue(MainWindow.__PREF_SAVEL_ALL__, QVariant(directory)) self.statusBar().showMessage("Images saved!", 5000) def computeMetricsAsync(self): self.statusBar().showMessage("Computing metrics...") QTimer.singleShot(0, self.computeMetrics) def computeMetrics(self): self._computeMetrics(self.currentSolution.functionName) self.statusBar().showMessage("Metrics computed!", 5000) def _computeMetrics(self, functionName): pareto = self.analyzer.getFunctionPareto(functionName) solutions = self.analyzer.getFunctionResults(functionName, self._getSelectedResultNames()) self.metrics.updateMetrics(pareto, solutions, functionName) def helpAbout(self): QMessageBox.about( self, "About Image Changer", """<b>Multi-Objective Optimization Interface</b> v%s <p>Copyright © 2011-2012 %s All rights reserved. <p>This application can be used to perform simple optimization analysis. <p><a href='%s'>%s</a> <p>Python %s - Qt %s - PyQt %s on %s""" % ( __VERSION__, __AUTHOR__, __WEBSITE__, __WEBSITE__, platform.python_version(), QT_VERSION_STR, PYQT_VERSION_STR, platform.system(), ), ) def addImplementation(self): if self.analyzer.nResults == 0: directory = "" else: directory = os.path.abspath(os.path.join(str(self.analyzer.resultDirectories[-1]), os.path.pardir)) directory = QFileDialog.getExistingDirectory( self, "Select a directory to scan", directory, QFileDialog.ShowDirsOnly ) if not os.path.exists(directory) or directory in self.analyzer.resultDirectories: return self.analyzer.addResultDirectory(directory) self.addSolutionForSelection(self.analyzer.getResultName(directory)) settings = QSettings() settings.setValue(MainWindow.__PREF_DIR__, QVariant(self.analyzer.resultDirectories)) def removeResult(self): layout = self.solutionSelector.layout() for i in xrange(layout.count() - 1, -1, -1): item = layout.itemAt(i) if not item.widget().isChecked(): # and self.analyzer.resultNames[i] != Analyzer.__PARETO__: item.widget().setVisible(False) layout.removeItem(item) self.analyzer.removeResultDirectory(self.analyzer.resultDirectories[i]) layout.update() settings = QSettings() settings.setValue(MainWindow.__PREF_DIR__, QVariant(self.analyzer.resultDirectories)) def solutionSelected(self): selection = self.functionWidget.currentItem() if selection is None: return self.showSolution(str(selection.text())) def showSolution(self, functionName): self.currentSolution = self.analyzer.getResultsForFunction(functionName) self.metrics.clear() self._showSolution() def addSolutionForSelection(self, name): solution = QCheckBox(name) solution.setChecked(True) solution.stateChanged.connect(self._showSolution) self.solutionSelector.layout().addWidget(solution) self.solutionSelector.layout().update() def _updateSolutionSelection(self): self.clearWidget(self.solutionSelector) for directory in self.analyzer.resultDirectories: self.addSolutionForSelection(self.analyzer.getResultName(directory)) def _showSolution(self): sol = self.currentSolution if sol is None: return if len(sol.variableImplementation) == 0 and self.showVariablesRadio.isEnabled(): self.showVariablesRadio.setEnabled(False) if self.showVariablesRadio.isChecked(): self.showSolutionsRadio.setChecked(True) else: self.showVariablesRadio.setEnabled(True) if len(sol.functionImplementation) == 0 and self.showSolutionsRadio.isEnabled(): self.showSolutionsRadio.setEnabled(False) if self.showSolutionsRadio.isChecked(): self.showVariablesRadio.setChecked(True) else: self.showSolutionsRadio.setEnabled(True) if self.showSolutionsRadio.isChecked(): self.generationSlider.setMaximum( max([sol.getFunctionSolution(impl).count() for impl in sol.functionImplementation]) ) else: self.generationSlider.setMaximum( max([sol.getVariableSolution(impl).count() for impl in sol.variableImplementation]) ) self._exportCurrentImage() def clearWidget(self, widget): layout = widget.layout() for i in xrange(layout.count() - 1, -1, -1): layout.removeItem(layout.itemAt(i)) def updateUI(self): self.statusBar().showMessage("Updating solutions...") selectedRow = self.functionWidget.currentRow() self.functionWidget.clear() names = [] + self.analyzer.getFunctionNames() names.sort() for name in names: item = QListWidgetItem() item.setText(name) self.functionWidget.addItem(item) if self.functionWidget.count() > 0: self.functionWidget.setCurrentRow( selectedRow if selectedRow >= 0 and selectedRow < self.functionWidget.count() else 0 ) self.statusBar().showMessage("Updated!", 5000) def _loadInitialData(self): self.updateUI() self.statusBar().showMessage("Ready!", 5000) def closeEvent(self, event): self.statusBar().showMessage("Closing...") settings = QSettings() settings.setValue(MainWindow.__PREF_GEOM__, self.saveGeometry()) settings.setValue(MainWindow.__PREF_STATE__, self.saveState()) self.plot.clear()
def _buildUI(self): self.setWindowTitle("MOOI: Multi-Objective Optimization Interface") self.resize(840, 480) self.statusBar().setSizeGripEnabled(False) self.statusBar().showMessage("Loading initial data...") # Plot widget self.plot = PlotWidget() self.plot.setMinimumSize(320, 480) self.plot.setAlignment(Qt.AlignCenter) self.plot.setContextMenuPolicy(Qt.ActionsContextMenu) self.setCentralWidget(self.plot) # Function widget self.functionWidget = QListWidget() self.functionWidget.itemSelectionChanged.connect(self.solutionSelected) rightDock = QDockWidget("Functions", self) rightDock.setObjectName("Functions") rightDock.setWidget(self.functionWidget) rightDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.addDockWidget(Qt.RightDockWidgetArea, rightDock) # Control widget self.showSolutionsRadio = QRadioButton("Functions") self.showSolutionsRadio.setChecked(True) self.showSolutionsRadio.toggled.connect(self._showSolution) self.showVariablesRadio = QRadioButton("Variables") radioWidget = QWidget() radioLayout = QHBoxLayout() radioLayout.addWidget(self.showSolutionsRadio) radioLayout.addWidget(self.showVariablesRadio) radioWidget.setLayout(radioLayout) self.generationLabel = QLabel("Run: 1") self.generationSlider = QSlider(Qt.Horizontal) self.generationSlider.setTickPosition(QSlider.TicksBothSides) self.generationSlider.setTracking(True) self.generationSlider.setMinimum(1) self.generationSlider.setMaximum(1) self.generationSlider.setTickInterval(1) self.generationSlider.valueChanged.connect(self._showSolution) self.solutionSelector = QWidget() self.solutionSelector.setLayout(QVBoxLayout()) addSolutionButton = QPushButton("Add") addSolutionButton.clicked.connect(self.addImplementation) removeSolutionButton = QPushButton("Remove unselected") removeSolutionButton.clicked.connect(self.removeResult) solutionSelectorButtons = QWidget() solutionSelectorButtons.setLayout(QHBoxLayout()) solutionSelectorButtons.layout().addWidget(addSolutionButton) solutionSelectorButtons.layout().addWidget(removeSolutionButton) self.solutionSelectorWidget = QWidget() self.solutionSelectorWidget.setLayout(QVBoxLayout()) self.solutionSelectorWidget.layout().addWidget(solutionSelectorButtons) self.solutionSelectorWidget.layout().addWidget(self.solutionSelector) exportButton = QPushButton("Export image") exportButton.clicked.connect(self.exportImage) exportAllButton = QPushButton("Export all images") exportAllButton.clicked.connect(self.exportAllImages) computeMetricsButton = QPushButton("Compute metrics") computeMetricsButton.clicked.connect(self.computeMetricsAsync) refreshButton = QPushButton("Refresh") refreshButton.clicked.connect(self.updateUI) controlLayout = QVBoxLayout() controlLayout.addWidget(radioWidget) controlLayout.addWidget(self.generationLabel) controlLayout.addWidget(self.generationSlider) controlLayout.addWidget(self.solutionSelectorWidget) controlLayout.addStretch() controlLayout.addWidget(computeMetricsButton) controlLayout.addWidget(refreshButton) controlLayout.addWidget(exportButton) controlLayout.addWidget(exportAllButton) controlWidget = QWidget() controlWidget.setLayout(controlLayout) leftDock = QDockWidget("Control", self) leftDock.setObjectName("Control") leftDock.setWidget(controlWidget) leftDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.addDockWidget(Qt.LeftDockWidgetArea, leftDock) # Metric widget self.metrics = MetricsPanel(self.analyzer) bottomDock = QDockWidget("Metrics", self) bottomDock.setObjectName("Metrics") bottomDock.setWidget(self.metrics) bottomDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.addDockWidget(Qt.BottomDockWidgetArea, bottomDock) # Actions exitAction = QAction('&Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(qApp.quit) copyAction = QAction("&Copy", self) copyAction.setShortcut("Ctrl+C") copyAction.setStatusTip('Copy metrics') copyAction.triggered.connect(self.metrics.copyMetrics) aboutAction = QAction("&About", self) aboutAction.setStatusTip('About MOOI') aboutAction.triggered.connect(self.helpAbout) # Menus menubar = self.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(copyAction) fileMenu.addAction(aboutAction) fileMenu.addSeparator() fileMenu.addAction(exitAction)
class XYView(View): AUTOFIT_MARGIN = 0.03 # 3% # See http://matplotlib.org/api/markers_api.html: CURVE_MARKERS = [ "o", # circle "*", # star "+", # plus "x", # x "s", # square "p", # pentagon "h", # hexagon1 "8", # octagon "D", # diamond "^", # triangle_up "<", # triangle_left ">", # triangle_right "1", # tri_down "2", # tri_up "3", # tri_left "4", # tri_right "v", # triangle_down "H", # hexagon2 "d", # thin diamond "", # NO MARKER ] _DEFAULT_LEGEND_STATE = False # for test purposes mainly - initial status of the legend def __init__(self, controller): View.__init__(self, controller) self._eventHandler = EventHandler() self._curveViews = {} # key: curve (model) ID, value: CurveView self._salomeViewID = None self._mplFigure = None self._mplAxes = None self._mplCanvas = None self._plotWidget = None self._sgPyQt = self._controller._sgPyQt self._toolbar = None self._mplNavigationActions = {} self._toobarMPL = None self._grid = None self._currCrv = None # current curve selected in the view self._legend = None self._legendLoc = "right" # "right" or "bottom" self._fitArea = False self._zoomPan = False self._dragOnDrop = False self._move = False self._patch = None self._xdata = None self._ydata = None self._defaultLineStyle = None self._last_point = None self._lastMarkerID = -1 self._blockLogSignal = False self._axisXSciNotation = False self._axisYSciNotation = False self._prevTitle = None def __repaintOK(self): """ To be called inside XYView each time a low-level expansive matplotlib methods is to be invoked. @return False if painting is currently locked, in which case it will also register the current XYView as needing a refresh when unlocked """ ret = self._controller._plotManager.isRepaintLocked() if ret: self._controller._plotManager.registerRepaint(self._model) return (not ret) def appendCurve(self, curveID): newC = CurveView(self._controller, self) newC.setModel(self._model._curves[curveID]) newC.setMPLAxes(self._mplAxes) newC.draw() newC.setMarker(self.getMarker(go_next=True)) self._curveViews[curveID] = newC def removeCurve(self, curveID): v = self._curveViews.pop(curveID) v.erase() if self._currCrv is not None and self._currCrv.getID() == curveID: self._currCrv = None def cleanBeforeClose(self): """ Clean some items to avoid accumulating stuff in memory """ self._mplFigure.clear() plt.close(self._mplFigure) self._plotWidget.clearAll() # For memory debugging only: import gc gc.collect() def repaint(self): if self.__repaintOK(): Logger.Debug("XYView::draw") self._mplCanvas.draw() def onXLabelChange(self): if self.__repaintOK(): self._mplAxes.set_xlabel(self._model._xlabel) self.repaint() def onYLabelChange(self): if self.__repaintOK(): self._mplAxes.set_ylabel(self._model._ylabel) self.repaint() def onTitleChange(self): if self.__repaintOK(): self._mplAxes.set_title(self._model._title) self.updateViewTitle() self.repaint() def onCurveTitleChange(self): # Updating the legend should suffice self.showHideLegend() def onClearAll(self): """ Just does an update with a reset of the marker cycle. """ if self.__repaintOK(): self._lastMarkerID = -1 self.update() def onPick(self, event): """ MPL callback when picking """ if event.mouseevent.button == 1: selected_id = -1 a = event.artist for crv_id, cv in self._curveViews.items(): if cv._mplLines[0] is a: selected_id = crv_id # Use the plotmanager so that other plot sets get their current reset: self._controller._plotManager.setCurrentCurve(selected_id) def createAndAddLocalAction(self, icon_file, short_name): return self._toolbar.addAction( self._sgPyQt.loadIcon("CURVEPLOT", icon_file), short_name) def createPlotWidget(self): self._mplFigure = Figure((8.0, 5.0), dpi=100) self._mplCanvas = FigureCanvasQTAgg(self._mplFigure) self._mplCanvas.installEventFilter(self._eventHandler) self._mplCanvas.mpl_connect('pick_event', self.onPick) self._mplAxes = self._mplFigure.add_subplot(1, 1, 1) self._plotWidget = PlotWidget() self._toobarMPL = NavigationToolbar2QT(self._mplCanvas, None) for act in self._toobarMPL.actions(): actionName = str(act.text()).strip() self._mplNavigationActions[actionName] = act self._plotWidget.setCentralWidget(self._mplCanvas) self._toolbar = self._plotWidget.toolBar self.populateToolbar() self._popupMenu = QtGui.QMenu() self._popupMenu.addAction(self._actionLegend) # Connect evenement for the graphic scene self._mplCanvas.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self._mplCanvas.customContextMenuRequested.connect(self.onContextMenu) self._mplCanvas.mpl_connect('scroll_event', self.onScroll) self._mplCanvas.mpl_connect('button_press_event', self.onMousePress) def populateToolbar(self): # Action to dump view in a file a = self.createAndAddLocalAction("dump_view.png", trQ("DUMP_VIEW_TXT")) a.triggered.connect(self.dumpView) self._toolbar.addSeparator() # Actions to manipulate the scene a = self.createAndAddLocalAction("fit_all.png", trQ("FIT_ALL_TXT")) a.triggered.connect(self.autoFit) # Zoom and pan are mutually exclusive but can be both de-activated: self._zoomAction = self.createAndAddLocalAction( "fit_area.png", trQ("FIT_AREA_TXT")) self._zoomAction.triggered.connect(self.zoomArea) self._zoomAction.setCheckable(True) self._panAction = self.createAndAddLocalAction("zoom_pan.png", trQ("ZOOM_PAN_TXT")) self._panAction.triggered.connect(self.pan) self._panAction.setCheckable(True) self._toolbar.addSeparator() # Actions to change the representation of curves self._curveActionGroup = QtGui.QActionGroup(self._plotWidget) self._pointsAction = self.createAndAddLocalAction( "draw_points.png", trQ("DRAW_POINTS_TXT")) self._pointsAction.setCheckable(True) self._linesAction = self.createAndAddLocalAction( "draw_lines.png", trQ("DRAW_LINES_TXT")) self._linesAction.setCheckable(True) self._curveActionGroup.addAction(self._pointsAction) self._curveActionGroup.addAction(self._linesAction) self._linesAction.setChecked(True) self._curveActionGroup.triggered.connect(self.changeModeCurve) self._curveActionGroup.setExclusive(True) self._toolbar.addSeparator() # Actions to draw horizontal curves as linear or logarithmic self._horActionGroup = QtGui.QActionGroup(self._plotWidget) self._horLinearAction = self.createAndAddLocalAction( "hor_linear.png", trQ("HOR_LINEAR_TXT")) self._horLinearAction.setCheckable(True) self._horLogarithmicAction = self.createAndAddLocalAction( "hor_logarithmic.png", trQ("HOR_LOGARITHMIC_TXT")) self._horLogarithmicAction.setCheckable(True) self._horActionGroup.addAction(self._horLinearAction) self._horActionGroup.addAction(self._horLogarithmicAction) self._horLinearAction.setChecked(True) self._horActionGroup.triggered.connect(self.onViewHorizontalMode) self._toolbar.addSeparator() # Actions to draw vertical curves as linear or logarithmic self._verActionGroup = QtGui.QActionGroup(self._plotWidget) self._verLinearAction = self.createAndAddLocalAction( "ver_linear.png", trQ("VER_LINEAR_TXT")) self._verLinearAction.setCheckable(True) self._verLogarithmicAction = self.createAndAddLocalAction( "ver_logarithmic.png", trQ("VER_LOGARITHMIC_TXT")) self._verLogarithmicAction.setCheckable(True) self._verActionGroup.addAction(self._verLinearAction) self._verActionGroup.addAction(self._verLogarithmicAction) self._verLinearAction.setChecked(True) self._verActionGroup.triggered.connect(self.onViewVerticalMode) self._verActionGroup.setExclusive(True) self._toolbar.addSeparator() # Action to show or hide the legend self._actionLegend = self.createAndAddLocalAction( "legend.png", trQ("SHOW_LEGEND_TXT")) self._actionLegend.setCheckable(True) self._actionLegend.triggered.connect(self.showHideLegend) if self._DEFAULT_LEGEND_STATE: self._actionLegend.setChecked(True) self._toolbar.addSeparator() # Action to set the preferences a = self.createAndAddLocalAction("settings.png", trQ("SETTINGS_TXT")) a.triggered.connect(self.onSettings) pass def dumpView(self): # Choice of the view backup file filters = [] for form in [ "IMAGES_FILES", "PDF_FILES", "POSTSCRIPT_FILES", "ENCAPSULATED_POSTSCRIPT_FILES" ]: filters.append(trQ(form)) fileName = self._sgPyQt.getFileName(self._sgPyQt.getDesktop(), "", filters, trQ("DUMP_VIEW_FILE"), False) if not fileName.isEmpty(): name = str(fileName) self._mplAxes.figure.savefig(name) pass def autoFit(self, check=True, repaint=True): if self.__repaintOK(): self._mplAxes.relim() xm, xM = self._mplAxes.xaxis.get_data_interval() ym, yM = self._mplAxes.yaxis.get_data_interval() i = yM - ym self._mplAxes.axis([ xm, xM, ym - i * self.AUTOFIT_MARGIN, yM + i * self.AUTOFIT_MARGIN ]) if repaint: self.repaint() def zoomArea(self): if self._panAction.isChecked() and self._zoomAction.isChecked(): self._panAction.setChecked(False) # Trigger underlying matplotlib action: self._mplNavigationActions["Zoom"].trigger() def pan(self): if self._panAction.isChecked() and self._zoomAction.isChecked(): self._zoomAction.setChecked(False) # Trigger underlying matplotlib action: self._mplNavigationActions["Pan"].trigger() def getMarker(self, go_next=False): if go_next: self._lastMarkerID = (self._lastMarkerID + 1) % len( self.CURVE_MARKERS) return self.CURVE_MARKERS[self._lastMarkerID] def changeModeCurve(self, repaint=True): if not self.__repaintOK(): return action = self._curveActionGroup.checkedAction() if action is self._pointsAction: for crv_view in self._curveViews.values(): crv_view.setLineStyle("None") elif action is self._linesAction: for crv_view in self._curveViews.values(): crv_view.setLineStyle("-") else: raise NotImplementedError if repaint: self.repaint() def setXLog(self, log, repaint=True): if not self.__repaintOK(): return self._blockLogSignal = True if log: self._mplAxes.set_xscale('log') self._horLogarithmicAction.setChecked(True) else: self._mplAxes.set_xscale('linear') self._horLinearAction.setChecked(True) if repaint: self.autoFit() self.repaint() self._blockLogSignal = False def setYLog(self, log, repaint=True): if not self.__repaintOK(): return self._blockLogSignal = True if log: self._mplAxes.set_yscale('log') self._verLogarithmicAction.setChecked(True) else: self._mplAxes.set_yscale('linear') self._verLinearAction.setChecked(True) if repaint: self.autoFit() self.repaint() self._blockLogSignal = False def setXSciNotation(self, sciNotation, repaint=True): self._axisXSciNotation = sciNotation self.changeFormatAxis() if repaint: self.repaint() def setYSciNotation(self, sciNotation, repaint=True): self._axisYSciNotation = sciNotation self.changeFormatAxis() if repaint: self.repaint() def onViewHorizontalMode(self, checked=True, repaint=True): if self._blockLogSignal: return action = self._horActionGroup.checkedAction() if action is self._horLinearAction: self.setXLog(False, repaint) elif action is self._horLogarithmicAction: self.setXLog(True, repaint) else: raise NotImplementedError def onViewVerticalMode(self, checked=True, repaint=True): if self._blockLogSignal: return action = self._verActionGroup.checkedAction() if action is self._verLinearAction: self.setYLog(False, repaint) elif action is self._verLogarithmicAction: self.setYLog(True, repaint) else: raise NotImplementedError if repaint: self.repaint() def __adjustFigureMargins(self, withLegend): """ Adjust figure margins to make room for the legend """ if withLegend: leg = self._legend bbox = leg.get_window_extent() # In axes coordinates: bbox2 = bbox.transformed(leg.figure.transFigure.inverted()) if self._legendLoc == "right": self._mplFigure.subplots_adjust(right=1.0 - (bbox2.width + 0.02)) elif self._legendLoc == "bottom": self._mplFigure.subplots_adjust(bottom=bbox2.height + 0.1) else: # Reset to default (rc) values self._mplFigure.subplots_adjust(bottom=0.1, right=0.9) def setLegendVisible(self, visible, repaint=True): if visible and not self._actionLegend.isChecked(): self._actionLegend.setChecked(True) self.showHideLegend(repaint=repaint) if not visible and self._actionLegend.isChecked(): self._actionLegend.setChecked(False) self.showHideLegend(repaint=repaint) def showHideLegend(self, actionChecked=None, repaint=True): if not self.__repaintOK(): # Show/hide legend is extremely costly return show = self._actionLegend.isChecked() nCurves = len(self._curveViews) if nCurves > 10: fontSize = 'x-small' else: fontSize = None if nCurves == 0: # Remove legend leg = self._mplAxes.legend() if leg is not None: leg.remove() if show and nCurves > 0: # Recreate legend from scratch if self._legend is not None: self._legend = None self._mplAxes._legend = None if self._legendLoc == "bottom": self._legend = self._mplAxes.legend(loc="upper left", bbox_to_anchor=(0.0, -0.05, 1.0, -0.05), borderaxespad=0.0, mode="expand", fancybox=True, shadow=True, ncol=3, prop={ 'size': fontSize, 'style': 'italic' }) elif self._legendLoc == "right": self._legend = self._mplAxes.legend(loc="upper left", bbox_to_anchor=(1.02, 1.0), borderaxespad=0.0, ncol=1, fancybox=True, shadow=True, prop={ 'size': fontSize, 'style': 'italic' }) else: raise Exception( "Invalid legend placement! Must be 'bottom' or 'right'") # Canvas must be drawn so we can adjust the figure placement: self._mplCanvas.draw() self.__adjustFigureMargins(withLegend=True) else: if self._legend is None: # Nothing to do return else: self._legend.set_visible(False) self._legend = None self._mplAxes._legend = None self._mplCanvas.draw() self.__adjustFigureMargins(withLegend=False) curr_crv = self._model._currentCurve if curr_crv is None: curr_title = None else: curr_title = curr_crv.getTitle() if self._legend is not None: for label in self._legend.get_texts(): text = label.get_text() if (text == curr_title): label.set_backgroundcolor('0.85') else: label.set_backgroundcolor('white') if repaint: self.repaint() def onSettings(self, trigger=False, dlg_test=None): dlg = dlg_test or PlotSettings() dlg.titleEdit.setText(self._mplAxes.get_title()) dlg.axisXTitleEdit.setText(self._mplAxes.get_xlabel()) dlg.axisYTitleEdit.setText(self._mplAxes.get_ylabel()) dlg.gridCheckBox.setChecked( self._mplAxes.xaxis._gridOnMajor ) # could not find a relevant API to check this dlg.axisXSciCheckBox.setChecked(self._axisXSciNotation) dlg.axisYSciCheckBox.setChecked(self._axisYSciNotation) xmin, xmax = self._mplAxes.get_xlim() ymin, ymax = self._mplAxes.get_ylim() xminText = "%g" % xmin xmaxText = "%g" % xmax yminText = "%g" % ymin ymaxText = "%g" % ymax dlg.axisXMinEdit.setText(xminText) dlg.axisXMaxEdit.setText(xmaxText) dlg.axisYMinEdit.setText(yminText) dlg.axisYMaxEdit.setText(ymaxText) # List of markers dlg.markerCurve.clear() for marker in self.CURVE_MARKERS: dlg.markerCurve.addItem(marker) curr_crv = self._model.getCurrentCurve() if not curr_crv is None: dlg.colorCurve.setEnabled(True) dlg.markerCurve.setEnabled(True) name = curr_crv.getTitle() dlg.nameCurve.setText(name) view = self._curveViews[curr_crv.getID()] marker = view.getMarker() color = view.getColor() index = dlg.markerCurve.findText(marker) dlg.markerCurve.setCurrentIndex(index) rgb = colors.colorConverter.to_rgb(color) dlg.setRGB(rgb[0], rgb[1], rgb[2]) else: dlg.colorCurve.setEnabled(False) dlg.markerCurve.setEnabled(False) dlg.nameCurve.setText("") view = None if self._legend is None: dlg.showLegendCheckBox.setChecked(False) dlg.legendPositionComboBox.setEnabled(False) else: if self._legend.get_visible(): dlg.showLegendCheckBox.setChecked(True) dlg.legendPositionComboBox.setEnabled(True) if self._legendLoc == "bottom": dlg.legendPositionComboBox.setCurrentIndex(0) elif self._legendLoc == "right": dlg.legendPositionComboBox.setCurrentIndex(1) else: dlg.showLegendCheckBox.setChecked(False) dlg.legendPositionComboBox.setEnabled(False) if dlg.exec_(): # Title self._model.setTitle(dlg.titleEdit.text()) # Axis self._model.setXLabel(dlg.axisXTitleEdit.text()) self._model.setYLabel(dlg.axisYTitleEdit.text()) # Grid if dlg.gridCheckBox.isChecked(): self._mplAxes.grid(True) else: self._mplAxes.grid(False) # Legend if dlg.showLegendCheckBox.isChecked(): self._actionLegend.setChecked(True) if dlg.legendPositionComboBox.currentIndex() == 0: self._legendLoc = "bottom" elif dlg.legendPositionComboBox.currentIndex() == 1: self._legendLoc = "right" else: self._actionLegend.setChecked(False) xminText = dlg.axisXMinEdit.text() xmaxText = dlg.axisXMaxEdit.text() yminText = dlg.axisYMinEdit.text() ymaxText = dlg.axisYMaxEdit.text() self._mplAxes.axis([ float(xminText), float(xmaxText), float(yminText), float(ymaxText) ]) self._axisXSciNotation = dlg.axisXSciCheckBox.isChecked() self._axisYSciNotation = dlg.axisYSciCheckBox.isChecked() self.changeFormatAxis() # Color and marker of the curve if view: view.setColor(dlg.getRGB()) view.setMarker( self.CURVE_MARKERS[dlg.markerCurve.currentIndex()]) self.showHideLegend(repaint=True) self._mplCanvas.draw() pass def updateViewTitle(self): s = "" if self._model._title != "": s = " - %s" % self._model._title title = "CurvePlot (%d)%s" % (self._model.getID(), s) self._sgPyQt.setViewTitle(self._salomeViewID, title) def onCurrentPlotSetChange(self): """ Avoid a unnecessary call to update() when just switching current plot set! """ pass def onCurrentCurveChange(self): curr_crv2 = self._model.getCurrentCurve() if curr_crv2 != self._currCrv: if self._currCrv is not None: view = self._curveViews[self._currCrv.getID()] view.toggleHighlight(False) if not curr_crv2 is None: view = self._curveViews[curr_crv2.getID()] view.toggleHighlight(True) self._currCrv = curr_crv2 self.showHideLegend(repaint=False) # redo legend self.repaint() def changeFormatAxis(self): if not self.__repaintOK(): return # don't try to switch to sci notation if we are not using the # matplotlib.ticker.ScalarFormatter (i.e. if in Log for ex.) if self._horLinearAction.isChecked(): if self._axisXSciNotation: self._mplAxes.ticklabel_format(style='sci', scilimits=(0, 0), axis='x') else: self._mplAxes.ticklabel_format(style='plain', axis='x') if self._verLinearAction.isChecked(): if self._axisYSciNotation: self._mplAxes.ticklabel_format(style='sci', scilimits=(0, 0), axis='y') else: self._mplAxes.ticklabel_format(style='plain', axis='y') def update(self): if self._salomeViewID is None: self.createPlotWidget() self._salomeViewID = self._sgPyQt.createView( "CurvePlot", self._plotWidget) Logger.Debug("Creating SALOME view ID=%d" % self._salomeViewID) self._sgPyQt.setViewVisible(self._salomeViewID, True) self.updateViewTitle() # Check list of curve views: set_mod = set(self._model._curves.keys()) set_view = set(self._curveViews.keys()) # Deleted/Added curves: dels = set_view - set_mod added = set_mod - set_view for d in dels: self.removeCurve(d) if not len(self._curveViews): # Reset color cycle self._mplAxes.set_color_cycle(None) for a in added: self.appendCurve(a) # Axes labels and title self._mplAxes.set_xlabel(self._model._xlabel) self._mplAxes.set_ylabel(self._model._ylabel) self._mplAxes.set_title(self._model._title) self.onViewHorizontalMode(repaint=False) self.onViewVerticalMode(repaint=False) self.changeModeCurve(repaint=False) self.showHideLegend( repaint=False ) # The canvas is repainted anyway (needed to get legend bounding box) self.changeFormatAxis() # Redo auto-fit self.autoFit(repaint=False) self.repaint() def onDataChange(self): # the rest is done in the CurveView: self.autoFit(repaint=True) def onMousePress(self, event): if event.button == 3: if self._panAction.isChecked(): self._panAction.setChecked(False) if self._zoomAction.isChecked(): self._zoomAction.setChecked(False) def onContextMenu(self, position): pos = self._mplCanvas.mapToGlobal( QtCore.QPoint(position.x(), position.y())) self._popupMenu.exec_(pos) def onScroll(self, event): # Event location (x and y) xdata = event.xdata ydata = event.ydata cur_xlim = self._mplAxes.get_xlim() cur_ylim = self._mplAxes.get_ylim() base_scale = 2. if event.button == 'down': # deal with zoom in scale_factor = 1 / base_scale elif event.button == 'up': # deal with zoom out scale_factor = base_scale else: # deal with something that should never happen scale_factor = 1 new_width = (cur_xlim[1] - cur_xlim[0]) * scale_factor new_height = (cur_ylim[1] - cur_ylim[0]) * scale_factor relx = (cur_xlim[1] - xdata) / (cur_xlim[1] - cur_xlim[0]) rely = (cur_ylim[1] - ydata) / (cur_ylim[1] - cur_ylim[0]) self._mplAxes.set_xlim( [xdata - new_width * (1 - relx), xdata + new_width * (relx)]) self._mplAxes.set_ylim( [ydata - new_height * (1 - rely), ydata + new_height * (rely)]) self.repaint() pass def onPressEvent(self, event): if event.button == 3: #self._mplCanvas.emit(QtCore.SIGNAL("button_release_event()")) canvasSize = event.canvas.geometry() point = event.canvas.mapToGlobal( QtCore.QPoint(event.x, canvasSize.height() - event.y)) self._popupMenu.exec_(point) else: print "Press event on the other button" #if event.button == 3 : # canvasSize = event.canvas.geometry() # point = event.canvas.mapToGlobal(QtCore.QPoint(event.x,canvasSize.height()-event.y)) # self._popupMenu.move(point) # self._popupMenu.show() def onMotionEvent(self, event): print "OnMotionEvent ", event.button #if event.button == 3 : # event.button = None # return True def onReleaseEvent(self, event): print "OnReleaseEvent ", event.button
class XYView(View): AUTOFIT_MARGIN = 0.03 # 3% # See http://matplotlib.org/api/markers_api.html: CURVE_MARKERS = [ "o" ,# circle "*", # star "+", # plus "x", # x "s", # square "p", # pentagon "h", # hexagon1 "8", # octagon "D", # diamond "^", # triangle_up "<", # triangle_left ">", # triangle_right "1", # tri_down "2", # tri_up "3", # tri_left "4", # tri_right "v", # triangle_down "H", # hexagon2 "d", # thin diamond "", # NO MARKER ] _DEFAULT_LEGEND_STATE = False # for test purposes mainly - initial status of the legend def __init__(self, controller): View.__init__(self, controller) self._eventHandler = EventHandler() self._curveViews = {} # key: curve (model) ID, value: CurveView self._salomeViewID = None self._mplFigure = None self._mplAxes = None self._mplCanvas = None self._plotWidget = None self._sgPyQt = self._controller._sgPyQt self._toolbar = None self._mplNavigationActions = {} self._toobarMPL = None self._grid = None self._currCrv = None # current curve selected in the view self._legend = None self._legendLoc = "right" # "right" or "bottom" self._fitArea = False self._zoomPan = False self._dragOnDrop = False self._move = False self._patch = None self._xdata = None self._ydata = None self._defaultLineStyle = None self._last_point = None self._lastMarkerID = -1 self._blockLogSignal = False self._axisXSciNotation = False self._axisYSciNotation = False self._prevTitle = None def __repaintOK(self): """ To be called inside XYView each time a low-level expansive matplotlib methods is to be invoked. @return False if painting is currently locked, in which case it will also register the current XYView as needing a refresh when unlocked """ ret = self._controller._plotManager.isRepaintLocked() if ret: self._controller._plotManager.registerRepaint(self._model) return (not ret) def appendCurve(self, curveID): newC = CurveView(self._controller, self) newC.setModel(self._model._curves[curveID]) newC.setMPLAxes(self._mplAxes) newC.draw() newC.setMarker(self.getMarker(go_next=True)) self._curveViews[curveID] = newC def removeCurve(self, curveID): v = self._curveViews.pop(curveID) v.erase() if self._currCrv is not None and self._currCrv.getID() == curveID: self._currCrv = None def cleanBeforeClose(self): """ Clean some items to avoid accumulating stuff in memory """ self._mplFigure.clear() plt.close(self._mplFigure) self._plotWidget.clearAll() # For memory debugging only: import gc gc.collect() def repaint(self): if self.__repaintOK(): Logger.Debug("XYView::draw") self._mplCanvas.draw() def onXLabelChange(self): if self.__repaintOK(): self._mplAxes.set_xlabel(self._model._xlabel) self.repaint() def onYLabelChange(self): if self.__repaintOK(): self._mplAxes.set_ylabel(self._model._ylabel) self.repaint() def onTitleChange(self): if self.__repaintOK(): self._mplAxes.set_title(self._model._title) self.updateViewTitle() self.repaint() def onCurveTitleChange(self): # Updating the legend should suffice self.showHideLegend() def onClearAll(self): """ Just does an update with a reset of the marker cycle. """ if self.__repaintOK(): self._lastMarkerID = -1 self.update() def onPick(self, event): """ MPL callback when picking """ if event.mouseevent.button == 1: selected_id = -1 a = event.artist for crv_id, cv in self._curveViews.items(): if cv._mplLines[0] is a: selected_id = crv_id # Use the plotmanager so that other plot sets get their current reset: self._controller._plotManager.setCurrentCurve(selected_id) def createAndAddLocalAction(self, icon_file, short_name): return self._toolbar.addAction(self._sgPyQt.loadIcon("CURVEPLOT", icon_file), short_name) def createPlotWidget(self): self._mplFigure = Figure((8.0,5.0), dpi=100) self._mplCanvas = FigureCanvasQTAgg(self._mplFigure) self._mplCanvas.installEventFilter(self._eventHandler) self._mplCanvas.mpl_connect('pick_event', self.onPick) self._mplAxes = self._mplFigure.add_subplot(1, 1, 1) self._plotWidget = PlotWidget() self._toobarMPL = NavigationToolbar2QT(self._mplCanvas, None) for act in self._toobarMPL.actions(): actionName = str(act.text()).strip() self._mplNavigationActions[actionName] = act self._plotWidget.setCentralWidget(self._mplCanvas) self._toolbar = self._plotWidget.toolBar self.populateToolbar() self._popupMenu = QtGui.QMenu() self._popupMenu.addAction(self._actionLegend) # Connect evenement for the graphic scene self._mplCanvas.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self._mplCanvas.customContextMenuRequested.connect(self.onContextMenu) self._mplCanvas.mpl_connect('scroll_event', self.onScroll) self._mplCanvas.mpl_connect('button_press_event', self.onMousePress) def populateToolbar(self): # Action to dump view in a file a = self.createAndAddLocalAction("dump_view.png", trQ("DUMP_VIEW_TXT")) a.triggered.connect(self.dumpView) self._toolbar.addSeparator() # Actions to manipulate the scene a = self.createAndAddLocalAction("fit_all.png", trQ("FIT_ALL_TXT")) a.triggered.connect(self.autoFit) # Zoom and pan are mutually exclusive but can be both de-activated: self._zoomAction = self.createAndAddLocalAction("fit_area.png", trQ("FIT_AREA_TXT")) self._zoomAction.triggered.connect(self.zoomArea) self._zoomAction.setCheckable(True) self._panAction = self.createAndAddLocalAction("zoom_pan.png", trQ("ZOOM_PAN_TXT")) self._panAction.triggered.connect(self.pan) self._panAction.setCheckable(True) self._toolbar.addSeparator() # Actions to change the representation of curves self._curveActionGroup = QtGui.QActionGroup(self._plotWidget) self._pointsAction = self.createAndAddLocalAction("draw_points.png", trQ("DRAW_POINTS_TXT")) self._pointsAction.setCheckable(True) self._linesAction = self.createAndAddLocalAction("draw_lines.png", trQ("DRAW_LINES_TXT")) self._linesAction.setCheckable(True) self._curveActionGroup.addAction(self._pointsAction) self._curveActionGroup.addAction(self._linesAction) self._linesAction.setChecked(True) self._curveActionGroup.triggered.connect(self.changeModeCurve) self._curveActionGroup.setExclusive(True) self._toolbar.addSeparator() # Actions to draw horizontal curves as linear or logarithmic self._horActionGroup = QtGui.QActionGroup(self._plotWidget) self._horLinearAction = self.createAndAddLocalAction("hor_linear.png", trQ("HOR_LINEAR_TXT")) self._horLinearAction.setCheckable(True) self._horLogarithmicAction = self.createAndAddLocalAction("hor_logarithmic.png", trQ("HOR_LOGARITHMIC_TXT")) self._horLogarithmicAction.setCheckable(True) self._horActionGroup.addAction(self._horLinearAction) self._horActionGroup.addAction(self._horLogarithmicAction) self._horLinearAction.setChecked(True) self._horActionGroup.triggered.connect(self.onViewHorizontalMode) self._toolbar.addSeparator() # Actions to draw vertical curves as linear or logarithmic self._verActionGroup = QtGui.QActionGroup(self._plotWidget) self._verLinearAction = self.createAndAddLocalAction("ver_linear.png", trQ("VER_LINEAR_TXT")) self._verLinearAction.setCheckable(True) self._verLogarithmicAction = self.createAndAddLocalAction("ver_logarithmic.png", trQ("VER_LOGARITHMIC_TXT")) self._verLogarithmicAction.setCheckable(True) self._verActionGroup.addAction(self._verLinearAction) self._verActionGroup.addAction(self._verLogarithmicAction) self._verLinearAction.setChecked(True) self._verActionGroup.triggered.connect(self.onViewVerticalMode) self._verActionGroup.setExclusive(True) self._toolbar.addSeparator() # Action to show or hide the legend self._actionLegend = self.createAndAddLocalAction("legend.png", trQ("SHOW_LEGEND_TXT")) self._actionLegend.setCheckable(True) self._actionLegend.triggered.connect(self.showHideLegend) if self._DEFAULT_LEGEND_STATE: self._actionLegend.setChecked(True) self._toolbar.addSeparator() # Action to set the preferences a = self.createAndAddLocalAction("settings.png", trQ("SETTINGS_TXT")) a.triggered.connect(self.onSettings) pass def dumpView(self): # Choice of the view backup file filters = [] for form in ["IMAGES_FILES", "PDF_FILES", "POSTSCRIPT_FILES", "ENCAPSULATED_POSTSCRIPT_FILES"]: filters.append(trQ(form)) fileName = self._sgPyQt.getFileName(self._sgPyQt.getDesktop(), "", filters, trQ("DUMP_VIEW_FILE"), False ) if not fileName.isEmpty(): name = str(fileName) self._mplAxes.figure.savefig(name) pass def autoFit(self, check=True, repaint=True): if self.__repaintOK(): self._mplAxes.relim() xm, xM = self._mplAxes.xaxis.get_data_interval() ym, yM = self._mplAxes.yaxis.get_data_interval() i = yM-ym self._mplAxes.axis([xm, xM, ym-i*self.AUTOFIT_MARGIN, yM+i*self.AUTOFIT_MARGIN]) if repaint: self.repaint() def zoomArea(self): if self._panAction.isChecked() and self._zoomAction.isChecked(): self._panAction.setChecked(False) # Trigger underlying matplotlib action: self._mplNavigationActions["Zoom"].trigger() def pan(self): if self._panAction.isChecked() and self._zoomAction.isChecked(): self._zoomAction.setChecked(False) # Trigger underlying matplotlib action: self._mplNavigationActions["Pan"].trigger() def getMarker(self, go_next=False): if go_next: self._lastMarkerID = (self._lastMarkerID+1) % len(self.CURVE_MARKERS) return self.CURVE_MARKERS[self._lastMarkerID] def changeModeCurve(self, repaint=True): if not self.__repaintOK(): return action = self._curveActionGroup.checkedAction() if action is self._pointsAction : for crv_view in self._curveViews.values(): crv_view.setLineStyle("None") elif action is self._linesAction : for crv_view in self._curveViews.values(): crv_view.setLineStyle("-") else : raise NotImplementedError if repaint: self.repaint() def setXLog(self, log, repaint=True): if not self.__repaintOK(): return self._blockLogSignal = True if log: self._mplAxes.set_xscale('log') self._horLogarithmicAction.setChecked(True) else: self._mplAxes.set_xscale('linear') self._horLinearAction.setChecked(True) if repaint: self.autoFit() self.repaint() self._blockLogSignal = False def setYLog(self, log, repaint=True): if not self.__repaintOK(): return self._blockLogSignal = True if log: self._mplAxes.set_yscale('log') self._verLogarithmicAction.setChecked(True) else: self._mplAxes.set_yscale('linear') self._verLinearAction.setChecked(True) if repaint: self.autoFit() self.repaint() self._blockLogSignal = False def setXSciNotation(self, sciNotation, repaint=True): self._axisXSciNotation = sciNotation self.changeFormatAxis() if repaint: self.repaint() def setYSciNotation(self, sciNotation, repaint=True): self._axisYSciNotation = sciNotation self.changeFormatAxis() if repaint: self.repaint() def onViewHorizontalMode(self, checked=True, repaint=True): if self._blockLogSignal: return action = self._horActionGroup.checkedAction() if action is self._horLinearAction: self.setXLog(False, repaint) elif action is self._horLogarithmicAction: self.setXLog(True, repaint) else: raise NotImplementedError def onViewVerticalMode(self, checked=True, repaint=True): if self._blockLogSignal: return action = self._verActionGroup.checkedAction() if action is self._verLinearAction: self.setYLog(False, repaint) elif action is self._verLogarithmicAction: self.setYLog(True, repaint) else: raise NotImplementedError if repaint: self.repaint() def __adjustFigureMargins(self, withLegend): """ Adjust figure margins to make room for the legend """ if withLegend: leg = self._legend bbox = leg.get_window_extent() # In axes coordinates: bbox2 = bbox.transformed(leg.figure.transFigure.inverted()) if self._legendLoc == "right": self._mplFigure.subplots_adjust(right=1.0-(bbox2.width+0.02)) elif self._legendLoc == "bottom": self._mplFigure.subplots_adjust(bottom=bbox2.height+0.1) else: # Reset to default (rc) values self._mplFigure.subplots_adjust(bottom=0.1, right=0.9) def setLegendVisible(self, visible, repaint=True): if visible and not self._actionLegend.isChecked(): self._actionLegend.setChecked(True) self.showHideLegend(repaint=repaint) if not visible and self._actionLegend.isChecked(): self._actionLegend.setChecked(False) self.showHideLegend(repaint=repaint) def showHideLegend(self, actionChecked=None, repaint=True): if not self.__repaintOK(): # Show/hide legend is extremely costly return show = self._actionLegend.isChecked() nCurves = len(self._curveViews) if nCurves > 10: fontSize = 'x-small' else: fontSize = None if nCurves == 0: # Remove legend leg = self._mplAxes.legend() if leg is not None: leg.remove() if show and nCurves > 0: # Recreate legend from scratch if self._legend is not None: self._legend = None self._mplAxes._legend = None if self._legendLoc == "bottom": self._legend = self._mplAxes.legend(loc="upper left", bbox_to_anchor=(0.0, -0.05, 1.0, -0.05), borderaxespad=0.0, mode="expand", fancybox=True, shadow=True, ncol=3, prop={'size':fontSize, 'style': 'italic'}) elif self._legendLoc == "right": self._legend = self._mplAxes.legend(loc="upper left", bbox_to_anchor=(1.02,1.0), borderaxespad=0.0, ncol=1, fancybox=True, shadow=True, prop={'size':fontSize, 'style': 'italic'}) else: raise Exception("Invalid legend placement! Must be 'bottom' or 'right'") # Canvas must be drawn so we can adjust the figure placement: self._mplCanvas.draw() self.__adjustFigureMargins(withLegend=True) else: if self._legend is None: # Nothing to do return else: self._legend.set_visible(False) self._legend = None self._mplAxes._legend = None self._mplCanvas.draw() self.__adjustFigureMargins(withLegend=False) curr_crv = self._model._currentCurve if curr_crv is None: curr_title = None else: curr_title = curr_crv.getTitle() if self._legend is not None: for label in self._legend.get_texts() : text = label.get_text() if (text == curr_title): label.set_backgroundcolor('0.85') else : label.set_backgroundcolor('white') if repaint: self.repaint() def onSettings(self, trigger=False, dlg_test=None): dlg = dlg_test or PlotSettings() dlg.titleEdit.setText(self._mplAxes.get_title()) dlg.axisXTitleEdit.setText(self._mplAxes.get_xlabel()) dlg.axisYTitleEdit.setText(self._mplAxes.get_ylabel()) dlg.gridCheckBox.setChecked(self._mplAxes.xaxis._gridOnMajor) # could not find a relevant API to check this dlg.axisXSciCheckBox.setChecked(self._axisXSciNotation) dlg.axisYSciCheckBox.setChecked(self._axisYSciNotation) xmin, xmax = self._mplAxes.get_xlim() ymin, ymax = self._mplAxes.get_ylim() xminText = "%g" %xmin xmaxText = "%g" %xmax yminText = "%g" %ymin ymaxText = "%g" %ymax dlg.axisXMinEdit.setText(xminText) dlg.axisXMaxEdit.setText(xmaxText) dlg.axisYMinEdit.setText(yminText) dlg.axisYMaxEdit.setText(ymaxText) # List of markers dlg.markerCurve.clear() for marker in self.CURVE_MARKERS : dlg.markerCurve.addItem(marker) curr_crv = self._model.getCurrentCurve() if not curr_crv is None: dlg.colorCurve.setEnabled(True) dlg.markerCurve.setEnabled(True) name = curr_crv.getTitle() dlg.nameCurve.setText(name) view = self._curveViews[curr_crv.getID()] marker = view.getMarker() color = view.getColor() index = dlg.markerCurve.findText(marker) dlg.markerCurve.setCurrentIndex(index) rgb = colors.colorConverter.to_rgb(color) dlg.setRGB(rgb[0],rgb[1],rgb[2]) else : dlg.colorCurve.setEnabled(False) dlg.markerCurve.setEnabled(False) dlg.nameCurve.setText("") view = None if self._legend is None: dlg.showLegendCheckBox.setChecked(False) dlg.legendPositionComboBox.setEnabled(False) else : if self._legend.get_visible(): dlg.showLegendCheckBox.setChecked(True) dlg.legendPositionComboBox.setEnabled(True) if self._legendLoc == "bottom": dlg.legendPositionComboBox.setCurrentIndex(0) elif self._legendLoc == "right" : dlg.legendPositionComboBox.setCurrentIndex(1) else : dlg.showLegendCheckBox.setChecked(False) dlg.legendPositionComboBox.setEnabled(False) if dlg.exec_(): # Title self._model.setTitle(dlg.titleEdit.text()) # Axis self._model.setXLabel(dlg.axisXTitleEdit.text()) self._model.setYLabel(dlg.axisYTitleEdit.text()) # Grid if dlg.gridCheckBox.isChecked() : self._mplAxes.grid(True) else : self._mplAxes.grid(False) # Legend if dlg.showLegendCheckBox.isChecked(): self._actionLegend.setChecked(True) if dlg.legendPositionComboBox.currentIndex() == 0 : self._legendLoc = "bottom" elif dlg.legendPositionComboBox.currentIndex() == 1 : self._legendLoc = "right" else : self._actionLegend.setChecked(False) xminText = dlg.axisXMinEdit.text() xmaxText = dlg.axisXMaxEdit.text() yminText = dlg.axisYMinEdit.text() ymaxText = dlg.axisYMaxEdit.text() self._mplAxes.axis([float(xminText), float(xmaxText), float(yminText), float(ymaxText)] ) self._axisXSciNotation = dlg.axisXSciCheckBox.isChecked() self._axisYSciNotation = dlg.axisYSciCheckBox.isChecked() self.changeFormatAxis() # Color and marker of the curve if view: view.setColor(dlg.getRGB()) view.setMarker(self.CURVE_MARKERS[dlg.markerCurve.currentIndex()]) self.showHideLegend(repaint=True) self._mplCanvas.draw() pass def updateViewTitle(self): s = "" if self._model._title != "": s = " - %s" % self._model._title title = "CurvePlot (%d)%s" % (self._model.getID(), s) self._sgPyQt.setViewTitle(self._salomeViewID, title) def onCurrentPlotSetChange(self): """ Avoid a unnecessary call to update() when just switching current plot set! """ pass def onCurrentCurveChange(self): curr_crv2 = self._model.getCurrentCurve() if curr_crv2 != self._currCrv: if self._currCrv is not None: view = self._curveViews[self._currCrv.getID()] view.toggleHighlight(False) if not curr_crv2 is None: view = self._curveViews[curr_crv2.getID()] view.toggleHighlight(True) self._currCrv = curr_crv2 self.showHideLegend(repaint=False) # redo legend self.repaint() def changeFormatAxis(self) : if not self.__repaintOK(): return # don't try to switch to sci notation if we are not using the # matplotlib.ticker.ScalarFormatter (i.e. if in Log for ex.) if self._horLinearAction.isChecked(): if self._axisXSciNotation : self._mplAxes.ticklabel_format(style='sci',scilimits=(0,0), axis='x') else : self._mplAxes.ticklabel_format(style='plain',axis='x') if self._verLinearAction.isChecked(): if self._axisYSciNotation : self._mplAxes.ticklabel_format(style='sci',scilimits=(0,0), axis='y') else : self._mplAxes.ticklabel_format(style='plain',axis='y') def update(self): if self._salomeViewID is None: self.createPlotWidget() self._salomeViewID = self._sgPyQt.createView("CurvePlot", self._plotWidget) Logger.Debug("Creating SALOME view ID=%d" % self._salomeViewID) self._sgPyQt.setViewVisible(self._salomeViewID, True) self.updateViewTitle() # Check list of curve views: set_mod = set(self._model._curves.keys()) set_view = set(self._curveViews.keys()) # Deleted/Added curves: dels = set_view - set_mod added = set_mod - set_view for d in dels: self.removeCurve(d) if not len(self._curveViews): # Reset color cycle self._mplAxes.set_color_cycle(None) for a in added: self.appendCurve(a) # Axes labels and title self._mplAxes.set_xlabel(self._model._xlabel) self._mplAxes.set_ylabel(self._model._ylabel) self._mplAxes.set_title(self._model._title) self.onViewHorizontalMode(repaint=False) self.onViewVerticalMode(repaint=False) self.changeModeCurve(repaint=False) self.showHideLegend(repaint=False) # The canvas is repainted anyway (needed to get legend bounding box) self.changeFormatAxis() # Redo auto-fit self.autoFit(repaint=False) self.repaint() def onDataChange(self): # the rest is done in the CurveView: self.autoFit(repaint=True) def onMousePress(self, event): if event.button == 3 : if self._panAction.isChecked(): self._panAction.setChecked(False) if self._zoomAction.isChecked(): self._zoomAction.setChecked(False) def onContextMenu(self, position): pos = self._mplCanvas.mapToGlobal(QtCore.QPoint(position.x(),position.y())) self._popupMenu.exec_(pos) def onScroll(self, event): # Event location (x and y) xdata = event.xdata ydata = event.ydata cur_xlim = self._mplAxes.get_xlim() cur_ylim = self._mplAxes.get_ylim() base_scale = 2. if event.button == 'down': # deal with zoom in scale_factor = 1 / base_scale elif event.button == 'up': # deal with zoom out scale_factor = base_scale else: # deal with something that should never happen scale_factor = 1 new_width = (cur_xlim[1] - cur_xlim[0]) * scale_factor new_height = (cur_ylim[1] - cur_ylim[0]) * scale_factor relx = (cur_xlim[1] - xdata)/(cur_xlim[1] - cur_xlim[0]) rely = (cur_ylim[1] - ydata)/(cur_ylim[1] - cur_ylim[0]) self._mplAxes.set_xlim([xdata - new_width * (1-relx), xdata + new_width * (relx)]) self._mplAxes.set_ylim([ydata - new_height * (1-rely), ydata + new_height * (rely)]) self.repaint() pass def onPressEvent(self, event): if event.button == 3 : #self._mplCanvas.emit(QtCore.SIGNAL("button_release_event()")) canvasSize = event.canvas.geometry() point = event.canvas.mapToGlobal(QtCore.QPoint(event.x,canvasSize.height()-event.y)) self._popupMenu.exec_(point) else : print "Press event on the other button" #if event.button == 3 : # canvasSize = event.canvas.geometry() # point = event.canvas.mapToGlobal(QtCore.QPoint(event.x,canvasSize.height()-event.y)) # self._popupMenu.move(point) # self._popupMenu.show() def onMotionEvent(self, event): print "OnMotionEvent ",event.button #if event.button == 3 : # event.button = None # return True def onReleaseEvent(self, event): print "OnReleaseEvent ",event.button
class NeonPlot: def __init__(self): filename = "MainWindow.glade" builder = gtk.Builder() builder.add_from_file(filename) builder.connect_signals(self) self.window = builder.get_object("mainWindow") self.window.connect("destroy", self.onDeleteWindow) self.window.show_all() self.functionsVbox = builder.get_object("functionsVbox") self.addFunctionButton = builder.get_object("addFuncitonButton") self.viewParamsStatusBar = builder.get_object('viewParamsLabel') self.errorsStatusBar = builder.get_object('errorsLabel') self.eventbox1 = builder.get_object("eventbox1") self.plotWidget = PlotWidget() self.plotWidget.connect('view_updated', self.update_plotview_status_bar) self.plotWidget.update_view_info() self.plotWidget.show() self.eventbox1.add(self.plotWidget) #self.viewCursorMenuItem = builder.get_object('viewCursor') #self.viewCursorMenuItem.connect("toggled", self.viewCursor_toggled_cb) # test = builder.get_object("eventbox1") #test.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color("#FF8")) def update_plotview_status_bar(self, widget): self.viewParamsStatusBar.set_text('Środek: ' + str(widget.center) + ', skala: ' + str(widget.scale) + ' px/j') def viewCursor_toggled_cb(self, widget): self.plotWidget.show_cursor = widget.active def viewGridlines_toggled_cb(self, widget): self.plotWidget.show_gridlines = widget.active def on_howToUse_activate(self, widget): filename = "HowToWindow.glade" builder = gtk.Builder() builder.add_from_file(filename) builder.connect_signals(self) window = builder.get_object("howToWindow") window.show_all() def open_about_window_cb(self, widget): filename = "AboutWindow.glade" builder = gtk.Builder() builder.add_from_file(filename) builder.connect_signals(self) window = builder.get_object("aboutWindow") window.show_all() def addFunction(self, widget): # DrawableFunction drawableFunction = DrawableFunction() self.plotWidget.add_function(drawableFunction) # GtkEventBox (will contain all elements) eventBox = gtk.EventBox() eventBox.show() # GtkFixed and setting its height fixed = gtk.Fixed() fixed.show() fixed.set_size_request(-1, 60) # "x" button removeButton = gtk.Button() removeButton.show() removeButton.set_size_request(45, 21) removeButton.set_label('usuń') removeButton.connect("clicked", self.removeFunction, drawableFunction, eventBox) fixed.put(removeButton, 197, 2) # "choose color" button changeColorButton = gtk.Button() changeColorButton.show() changeColorButton.set_size_request(73, 21) changeColorButton.set_label('zmień kolor') changeColorButton.connect("clicked", self.changeColor, drawableFunction, eventBox) fixed.put(changeColorButton, 120, 2) # text field textField = gtk.Entry() textField.show() textField.set_size_request(230, 27) textField.connect('changed', self.editFunction, drawableFunction) fixed.put(textField, 10, 23) # "draw' checkbox checkBox = gtk.CheckButton() checkBox.show() checkBox.set_size_request(70, 27) checkBox.set_label('aktywna') checkBox.set_active(True) checkBox.connect('toggled', self.showOrHideFunction, drawableFunction) fixed.put(checkBox, 10, 0) eventBox.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color("#CCCCCC")) # adding the event box as a child of the functionsVbox eventBox.add(fixed) self.functionsVbox.pack_start(eventBox, False, True, 1) # move the function adding button to the end of the Vbox self.functionsVbox.reorder_child(self.addFunctionButton, -1) # placing cursor in the newly added Entry textField.grab_focus() return eventBox, textField, checkBox, drawableFunction def on_readFromFile_activate(self, widget): openDialog = gtk.FileChooserDialog('Wskaż plik, z którego mają zostać załadowane funkcje', self.window, gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) openDialog.set_default_response(gtk.RESPONSE_OK) filter = gtk.FileFilter() filter.set_name("Pliki XML (*.xml)") filter.add_pattern("*.xml") openDialog.add_filter(filter) response = openDialog.run() if response == gtk.RESPONSE_OK: self.on_clearList_activate(None) tree = ElementTree.parse(openDialog.get_filename()) root = tree.getroot() for f in root: eventBox, textField, checkBox, drawableFunction = self.addFunction(None) color = f.find('color') gtkColor = gtk.gdk.Color(float(color.get('red')), float(color.get('green')), float(color.get('blue'))) drawableFunction.color = color_from_gtk_to_float(gtkColor) eventBox.modify_bg(gtk.STATE_NORMAL, gtkColor) checkBox.set_active(f.get('active') == 'True') textField.set_text(f.find('code').text.strip()) openDialog.destroy() def on_saveToFile_activate(self, widget): saveDialog = gtk.FileChooserDialog('Wskaż plik gdzie zapisać funkcje', self.window, gtk.FILE_CHOOSER_ACTION_SAVE, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)) saveDialog.set_default_response(gtk.RESPONSE_OK) filter = gtk.FileFilter() filter.set_name("Pliki XML (*.xml)") filter.add_pattern("*.xml") saveDialog.add_filter(filter) response = saveDialog.run() if response == gtk.RESPONSE_OK: functions = self.plotWidget.functions top = Element('functions') for f in functions: functionTag = SubElement(top, 'function') functionTag.set('active', str(f.enabled)) colorTag = SubElement(functionTag, 'color') colorTag.set('red', str(f.color.r)) colorTag.set('green', str(f.color.g)) colorTag.set('blue', str(f.color.b)) codeTag = SubElement(functionTag, 'code') codeTag.text = f.function_evaluator.function_string with open(saveDialog.get_filename(), 'w') as file: file.write(prettify(top)) saveDialog.destroy() def on_clearList_activate(self, widget): self.plotWidget.functions = [] for item in self.functionsVbox: if type(item) is gtk.EventBox: self.functionsVbox.remove(item) def on_zoomIn_activate(self, widget): self.plotWidget.zoom_in() def on_zoomOut_activate(self, widget): self.plotWidget.zoom_out() def on_reset_activate(self, widget): self.plotWidget.reset_view() self.plotWidget.queue_draw() def showOrHideFunction(self, checkBox, drawableFunction): drawableFunction.enabled = checkBox.get_active() self.plotWidget.queue_draw() def editFunction(self, entry, drawableFunction): newText = entry.get_text() drawableFunction.function_evaluator.set_function(newText) entry.modify_base(gtk.STATE_NORMAL, gtk.gdk.Color("#FFF" if drawableFunction.function_evaluator.can_be_drawn or newText is "" else "#F66")) self.errorsStatusBar.set_text(translate_to_polish(drawableFunction.function_evaluator.errors)) self.plotWidget.queue_draw() def changeColor(self, button, drawableFunction, eventBox): csw = ColorSelectionWindow(self.plotWidget, drawableFunction, eventBox) csw.show_window() def removeFunction(self, widget, drawableFunction, eventBox): self.plotWidget.functions.remove(drawableFunction) self.functionsVbox.remove(eventBox) self.plotWidget.queue_draw() def onDeleteWindow(self, *args): gtk.main_quit(*args)